frame.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. """!
  2. @package mapswipe.frame
  3. @brief Map Swipe Frame
  4. Classes:
  5. - dialogs::SwipeMapDialog
  6. (C) 2012 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Anna Kratochvilova <kratochanna gmail.com>
  10. """
  11. import os
  12. import sys
  13. import wx
  14. import time
  15. import grass.script as grass
  16. from gui_core.mapdisp import DoubleMapFrame
  17. from gui_core.dialogs import GetImageHandlers
  18. from core.render import Map
  19. from mapdisp import statusbar as sb
  20. from core.debug import Debug
  21. from core.gcmd import RunCommand, GError, GMessage
  22. from mapdisp.statusbar import EVT_AUTO_RENDER
  23. from mapswipe.toolbars import SwipeMapToolbar, SwipeMainToolbar, SwipeMiscToolbar
  24. from mapswipe.mapwindow import SwipeBufferedWindow
  25. from mapswipe.dialogs import SwipeMapDialog
  26. class SwipeMapFrame(DoubleMapFrame):
  27. def __init__(self, parent = None, giface = None,
  28. title = _("GRASS GIS Map Swipe"), name = "swipe", **kwargs):
  29. DoubleMapFrame.__init__(self, parent = parent, title = title, name = name,
  30. firstMap = Map(), secondMap = Map(), **kwargs)
  31. Debug.msg (1, "SwipeMapFrame.__init__()")
  32. #
  33. # Add toolbars
  34. #
  35. toolbars = ['swipeMisc', 'swipeMap', 'swipeMain']
  36. if sys.platform == 'win32':
  37. self.AddToolbar(toolbars.pop(1))
  38. toolbars.reverse()
  39. else:
  40. self.AddToolbar(toolbars.pop(0))
  41. for toolb in toolbars:
  42. self.AddToolbar(toolb)
  43. self._giface = giface
  44. #
  45. # create widgets
  46. #
  47. self.splitter = MapSplitter(parent = self, id = wx.ID_ANY)
  48. self.sliderH = wx.Slider(self, id = wx.ID_ANY, style = wx.SL_HORIZONTAL)
  49. self.sliderV = wx.Slider(self, id = wx.ID_ANY, style = wx.SL_VERTICAL)
  50. self.firstMapWindow = SwipeBufferedWindow(parent = self.splitter, giface = self._giface,
  51. Map = self.firstMap, frame = self)
  52. self.secondMapWindow = SwipeBufferedWindow(parent = self.splitter, giface = self._giface,
  53. Map = self.secondMap, frame = self)
  54. self.MapWindow = self.firstMapWindow # current by default
  55. self.firstMap.region = self.secondMap.region
  56. self.firstMapWindow.zoomhistory = self.secondMapWindow.zoomhistory
  57. self._mode = 'swipe'
  58. self.splitter.SplitVertically(self.firstMapWindow, self.secondMapWindow, 0)
  59. self._addPanes()
  60. self._bindWindowsActivation()
  61. self._mgr.GetPane('sliderV').Hide()
  62. self._mgr.GetPane('sliderH').Show()
  63. self.slider = self.sliderH
  64. self.InitStatusbar()
  65. self.Bind(wx.EVT_SIZE, self.OnSize)
  66. self.Bind(EVT_AUTO_RENDER, self.OnAutoRenderChanged)
  67. self.Bind(wx.EVT_IDLE, self.OnIdle)
  68. self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
  69. self.SetSize((800, 600))
  70. self._mgr.Update()
  71. self.rasters = {'first': None, 'second': None}
  72. # default action in map toolbar
  73. self.OnPan(event = None)
  74. self.resize = False
  75. wx.CallAfter(self.CallAfterInit)
  76. def CallAfterInit(self):
  77. self.InitSliderBindings()
  78. if not (self.rasters['first'] and self.rasters['second']):
  79. self.OnSelectRasters(event = None)
  80. def InitStatusbar(self):
  81. """!Init statusbar (default items)."""
  82. # items for choice
  83. self.statusbarItems = [sb.SbCoordinates,
  84. sb.SbRegionExtent,
  85. sb.SbCompRegionExtent,
  86. sb.SbShowRegion,
  87. sb.SbAlignExtent,
  88. sb.SbResolution,
  89. sb.SbDisplayGeometry,
  90. sb.SbMapScale,
  91. sb.SbGoTo,
  92. sb.SbProjection]
  93. # create statusbar and its manager
  94. statusbar = self.CreateStatusBar(number = 4, style = 0)
  95. statusbar.SetStatusWidths([-5, -2, -1, -1])
  96. self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar)
  97. # fill statusbar manager
  98. self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar)
  99. self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
  100. self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
  101. self.statusbarManager.Update()
  102. def ResetSlider(self):
  103. if self.splitter.GetSplitMode() == wx.SPLIT_VERTICAL:
  104. size = self.splitter.GetSize()[0]
  105. else:
  106. size = self.splitter.GetSize()[1]
  107. self.slider.SetRange(0, size)
  108. self.slider.SetValue(self.splitter.GetSashPosition())
  109. def InitSliderBindings(self):
  110. self.sliderH.Bind(wx.EVT_SPIN, self.OnSliderPositionChanging)
  111. self.sliderH.Bind(wx.EVT_SCROLL_THUMBRELEASE, self.OnSliderPositionChanged)
  112. self.sliderV.Bind(wx.EVT_SPIN, self.OnSliderPositionChanging)
  113. self.sliderV.Bind(wx.EVT_SCROLL_THUMBRELEASE, self.OnSliderPositionChanged)
  114. self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.OnSashChanging)
  115. self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged)
  116. def OnSliderPositionChanging(self, event):
  117. """!Slider changes its position, sash must be moved too."""
  118. Debug.msg (5, "SwipeMapFrame.OnSliderPositionChanging()")
  119. self.GetFirstWindow().movingSash = True
  120. self.GetSecondWindow().movingSash = True
  121. pos = event.GetPosition()
  122. if pos > 0:
  123. self.splitter.SetSashPosition(pos)
  124. self.splitter.OnSashChanging(None)
  125. def OnSliderPositionChanged(self, event):
  126. """!Slider position changed, sash must be moved too."""
  127. Debug.msg (5, "SwipeMapFrame.OnSliderPositionChanged()")
  128. self.splitter.SetSashPosition(event.GetPosition())
  129. self.splitter.OnSashChanged(None)
  130. def OnSashChanging(self, event):
  131. """!Sash position is changing, slider must be moved too."""
  132. Debug.msg (5, "SwipeMapFrame.OnSashChanging()")
  133. self.slider.SetValue(self.splitter.GetSashPosition())
  134. event.Skip()
  135. def OnSashChanged(self, event):
  136. """!Sash position changed, slider must be moved too."""
  137. Debug.msg (5, "SwipeMapFrame.OnSashChanged()")
  138. self.OnSashChanging(event)
  139. event.Skip()
  140. def OnSize(self, event):
  141. Debug.msg (4, "SwipeMapFrame.OnSize()")
  142. self.resize = time.clock()
  143. def OnIdle(self, event):
  144. if self.resize and time.clock() - self.resize > 0.2:
  145. w1 = self.GetFirstWindow()
  146. w2 = self.GetSecondWindow()
  147. sizeAll = self.splitter.GetSize()
  148. w1.SetClientSize(sizeAll)
  149. w2.SetClientSize(sizeAll)
  150. w1.OnSize(event)
  151. w2.OnSize(event)
  152. self.ResetSlider()
  153. self.resize = False
  154. def OnAutoRenderChanged(self, event):
  155. """!Auto rendering state changed."""
  156. style = self.splitter.GetWindowStyle()
  157. style ^= wx.SP_LIVE_UPDATE
  158. self.splitter.SetWindowStyle(style)
  159. def AddToolbar(self, name):
  160. """!Add defined toolbar to the window
  161. Currently known toolbars are:
  162. - 'swipeMap' - basic map toolbar
  163. - 'swipeMain' - swipe functionality
  164. """
  165. if name == "swipeMap":
  166. self.toolbars[name] = SwipeMapToolbar(self)
  167. self._mgr.AddPane(self.toolbars[name],
  168. wx.aui.AuiPaneInfo().
  169. Name(name).Caption(_("Map Toolbar")).
  170. ToolbarPane().Top().
  171. LeftDockable(False).RightDockable(False).
  172. BottomDockable(False).TopDockable(True).
  173. CloseButton(False).Layer(2).Row(1).
  174. BestSize((self.toolbars[name].GetBestSize())))
  175. if name == "swipeMain":
  176. self.toolbars[name] = SwipeMainToolbar(self)
  177. self._mgr.AddPane(self.toolbars[name],
  178. wx.aui.AuiPaneInfo().
  179. Name(name).Caption(_("Main Toolbar")).
  180. ToolbarPane().Top().
  181. LeftDockable(False).RightDockable(False).
  182. BottomDockable(False).TopDockable(True).
  183. CloseButton(False).Layer(2).Row(1).
  184. BestSize((self.toolbars[name].GetBestSize())))
  185. if name == "swipeMisc":
  186. self.toolbars[name] = SwipeMiscToolbar(self)
  187. self._mgr.AddPane(self.toolbars[name],
  188. wx.aui.AuiPaneInfo().
  189. Name(name).Caption(_("Misc Toolbar")).
  190. ToolbarPane().Top().
  191. LeftDockable(False).RightDockable(False).
  192. BottomDockable(False).TopDockable(True).
  193. CloseButton(False).Layer(2).Row(1).
  194. BestSize((self.toolbars[name].GetBestSize())))
  195. def _addPanes(self):
  196. """!Add splitter window and sliders to aui manager"""
  197. # splitter window
  198. self._mgr.AddPane(self.splitter, wx.aui.AuiPaneInfo().
  199. Name('splitter').CaptionVisible(False).PaneBorder(True).
  200. Dockable(False).Floatable(False).CloseButton(False).
  201. Center().Layer(1).BestSize((self.splitter.GetBestSize())))
  202. # sliders
  203. self._mgr.AddPane(self.sliderH, wx.aui.AuiPaneInfo().
  204. Name('sliderH').CaptionVisible(False).PaneBorder(False).
  205. CloseButton(False).Gripper(True).GripperTop(False).
  206. BottomDockable(True).TopDockable(True).
  207. LeftDockable(False).RightDockable(False).
  208. Bottom().Layer(1).BestSize((self.sliderH.GetBestSize())))
  209. self._mgr.AddPane(self.sliderV, wx.aui.AuiPaneInfo().
  210. Name('sliderV').CaptionVisible(False).PaneBorder(False).
  211. CloseButton(False).Gripper(True).GripperTop(True).
  212. BottomDockable(False).TopDockable(False).
  213. LeftDockable(True).RightDockable(True).
  214. Right().Layer(1).BestSize((self.sliderV.GetBestSize())))
  215. def UpdateRegion(self):
  216. """!
  217. Rerender the second window
  218. when the region of the first changed.
  219. """
  220. Debug.msg(3, "SwipeMapFrame.UpdateRegion()")
  221. if self.GetWindow() == self.GetSecondWindow():
  222. self.Render(self.GetFirstWindow())
  223. else:
  224. self.Render(self.GetSecondWindow())
  225. def ZoomToMap(self):
  226. """!
  227. Set display extents to match selected raster (including NULLs)
  228. or vector map.
  229. """
  230. if self.rasters['first']:
  231. self.GetFirstWindow().ZoomToMap(layers = self.firstMap.GetListOfLayers())
  232. if self.rasters['second']:
  233. self.GetSecondWindow().ZoomToMap(layers = self.secondMap.GetListOfLayers())
  234. # needed again, don't know why
  235. self.firstMap.region = self.secondMap.region
  236. def OnZoomToMap(self, event):
  237. """!Zoom to map"""
  238. self.ZoomToMap()
  239. def OnZoomBack(self, event):
  240. self.GetFirstWindow().ZoomBack()
  241. self.secondMap.region = self.firstMap.region
  242. self.Render(self.GetSecondWindow())
  243. def OnSelectRasters(self, event):
  244. """!Choose raster maps and rerender."""
  245. dlg = SwipeMapDialog(self, first = self.rasters['first'], second = self.rasters['second'])
  246. if dlg.ShowModal() == wx.ID_OK:
  247. maps = dlg.GetValues()
  248. res1 = self.SetFirstRaster(name = maps[0])
  249. res2 = self.SetSecondRaster(name = maps[1])
  250. if not (res1 and res2):
  251. message = ''
  252. if not res1:
  253. message += _("Map <%s> not found. ") % maps[0]
  254. if not res2:
  255. message += _("Map <%s> not found.") % maps[1]
  256. GError(parent = self, message = message)
  257. dlg.Destroy()
  258. self.SetRasterNames()
  259. self.ZoomToMap()
  260. dlg.Destroy()
  261. self.OnRender(event = None)
  262. def SetFirstRaster(self, name):
  263. """!Set raster map to first Map"""
  264. raster = grass.find_file(name = name, element = 'cell')
  265. if raster['fullname']:
  266. self.rasters['first'] = raster['fullname']
  267. self.SetLayer(name = raster['fullname'], mapInstance = self.GetFirstMap())
  268. return True
  269. return False
  270. def SetSecondRaster(self, name):
  271. """!Set raster map to second Map"""
  272. raster = grass.find_file(name = name, element = 'cell')
  273. if raster['fullname']:
  274. self.rasters['second'] = raster['fullname']
  275. self.SetLayer(name = raster['fullname'], mapInstance = self.GetSecondMap())
  276. return True
  277. return False
  278. def SetLayer(self, name, mapInstance):
  279. """!Sets layer in Map.
  280. @param name layer (raster) name
  281. """
  282. Debug.msg (3, "SwipeMapFrame.SetLayer(): name=%s" % name)
  283. # this simple application enables to keep only one raster
  284. mapInstance.DeleteAllLayers()
  285. cmdlist = ['d.rast', 'map=%s' % name]
  286. # add layer to Map instance (core.render)
  287. newLayer = mapInstance.AddLayer(type = 'raster', command = cmdlist, l_active = True,
  288. name = name, l_hidden = False, l_opacity = 1.0,
  289. l_render = True)
  290. def OnSwitchWindows(self, event):
  291. """!Switch windows position."""
  292. Debug.msg(3, "SwipeMapFrame.OnSwitchWindows()")
  293. splitter = self.splitter
  294. w1, w2 = splitter.GetWindow1(), splitter.GetWindow2()
  295. splitter.ReplaceWindow(w1, w2)
  296. splitter.ReplaceWindow(w2, w1)
  297. # self.OnSize(None)
  298. splitter.OnSashChanged(None)
  299. def _saveToFile(self, fileName, fileType):
  300. """!Creates composite image by rendering both images and
  301. pasting them into the new one.
  302. @todo specify size of the new image (problem is inaccurate scaling)
  303. @todo make dividing line width and color optional
  304. """
  305. w1 = self.splitter.GetWindow1()
  306. w2 = self.splitter.GetWindow2()
  307. lineWidth = 1
  308. # render to temporary files
  309. filename1 = grass.tempfile(False) + '1'
  310. filename2 = grass.tempfile(False) + '2'
  311. width, height = self.splitter.GetClientSize()
  312. if self._mode == 'swipe':
  313. x, y = w2.GetImageCoords()
  314. w1.SaveToFile(filename1, fileType, width, height)
  315. w2.SaveToFile(filename2, fileType, width, height)
  316. else:
  317. fw, fh = w1.GetClientSize()
  318. w1.SaveToFile(filename1, fileType, fw, fh)
  319. sw, sh = w2.GetClientSize()
  320. w2.SaveToFile(filename2, fileType, sw, sh)
  321. # create empty white image - needed for line
  322. im = wx.EmptyImage(width, height)
  323. im.Replace(0, 0, 0, 255, 255, 255)
  324. # paste images
  325. if self._mode == 'swipe':
  326. if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL:
  327. im1 = wx.Image(filename1).GetSubImage((0, 0, width, -y))
  328. im.Paste(im1, 0, 0)
  329. im.Paste(wx.Image(filename2), -x, -y + lineWidth)
  330. else:
  331. im1 = wx.Image(filename1).GetSubImage((0, 0, -x, height))
  332. im.Paste(im1, 0, 0)
  333. im.Paste(wx.Image(filename2), -x + lineWidth, -y)
  334. else:
  335. if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL:
  336. im1 = wx.Image(filename1)
  337. im.Paste(im1, 0, 0)
  338. im.Paste(wx.Image(filename2), 0, fh + lineWidth)
  339. else:
  340. im1 = wx.Image(filename1)
  341. im.Paste(im1, 0, 0)
  342. im.Paste(wx.Image(filename2), fw + lineWidth, 0)
  343. im.SaveFile(fileName, fileType)
  344. # remove temporary files
  345. grass.try_remove(filename1)
  346. grass.try_remove(filename2)
  347. def SaveToFile(self, event):
  348. """!Save map to image
  349. """
  350. img = self.firstMapWindow.img or self.secondMapWindow.img
  351. if not img:
  352. GMessage(parent = self,
  353. message = _("Nothing to render (empty map). Operation canceled."))
  354. return
  355. filetype, ltype = GetImageHandlers(img)
  356. # get filename
  357. dlg = wx.FileDialog(parent = self,
  358. message = _("Choose a file name to save the image "
  359. "(no need to add extension)"),
  360. wildcard = filetype,
  361. style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
  362. if dlg.ShowModal() == wx.ID_OK:
  363. path = dlg.GetPath()
  364. if not path:
  365. dlg.Destroy()
  366. return
  367. base, ext = os.path.splitext(path)
  368. fileType = ltype[dlg.GetFilterIndex()]['type']
  369. extType = ltype[dlg.GetFilterIndex()]['ext']
  370. if ext != extType:
  371. path = base + '.' + extType
  372. self._saveToFile(path, fileType)
  373. dlg.Destroy()
  374. def OnSwitchOrientation(self, event):
  375. """!Switch orientation of the sash."""
  376. Debug.msg(3, "SwipeMapFrame.OnSwitchOrientation()")
  377. splitter = self.splitter
  378. splitter.Unsplit()
  379. if splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL:
  380. splitter.SplitVertically(self.firstMapWindow, self.secondMapWindow, 0)
  381. self.slider = self.sliderH
  382. if self._mode == 'swipe':
  383. self._mgr.GetPane('sliderH').Show()
  384. self._mgr.GetPane('sliderV').Hide()
  385. else:
  386. splitter.SplitHorizontally(self.firstMapWindow, self.secondMapWindow, 0)
  387. self.slider = self.sliderV
  388. if self._mode == 'swipe':
  389. self._mgr.GetPane('sliderV').Show()
  390. self._mgr.GetPane('sliderH').Hide()
  391. self._mgr.Update()
  392. splitter.OnSashChanged(None)
  393. self.OnSize(None)
  394. self.SetRasterNames()
  395. def OnAddText(self, event):
  396. """!Double click on text overlay
  397. So far not implemented.
  398. """
  399. pass
  400. def SetViewMode(self, mode):
  401. """!Sets view mode.
  402. @param mode view mode ('swipe', 'mirror')
  403. """
  404. if self._mode == mode:
  405. return
  406. self._mode = mode
  407. self.toolbars['swipeMain'].SetMode(mode)
  408. # set window mode
  409. self.GetFirstWindow().SetMode(mode)
  410. self.GetSecondWindow().SetMode(mode)
  411. # hide/show slider
  412. if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL:
  413. self._mgr.GetPane('sliderV').Show(mode == 'swipe')
  414. size = self.splitter.GetSize()[1] / 2
  415. else:
  416. self._mgr.GetPane('sliderH').Show(mode == 'swipe')
  417. size = self.splitter.GetSize()[0] / 2
  418. # set sash in the middle
  419. self.splitter.SetSashPosition(size)
  420. self.slider.SetValue(size)
  421. self._mgr.Update()
  422. # enable / disable sash
  423. self.splitter.EnableSash(mode == 'swipe')
  424. # hack to make it work
  425. self.splitter.OnSashChanged(None)
  426. self.SendSizeEvent()
  427. def SetRasterNames(self):
  428. if self.rasters['first']:
  429. self.GetFirstWindow().SetRasterNameText(self.rasters['first'], 101)
  430. if self.rasters['second']:
  431. self.GetSecondWindow().SetRasterNameText(self.rasters['second'], 102)
  432. def GetMapToolbar(self):
  433. """!Returns toolbar with zooming tools"""
  434. return self.toolbars['swipeMap']
  435. def IsStandalone(self):
  436. """!Since we do not need layer manager, we are standalone"""
  437. return True
  438. def OnHelp(self, event):
  439. self._giface.Help(entry = 'wxGUI.mapswipe')
  440. def OnCloseWindow(self, event):
  441. self.GetFirstMap().Clean()
  442. self.GetSecondMap().Clean()
  443. self.Destroy()
  444. class MapSplitter(wx.SplitterWindow):
  445. """!Splitter window for displaying two maps"""
  446. def __init__(self, parent, id):
  447. wx.SplitterWindow.__init__(self, parent = parent, id = id,
  448. style = wx.SP_LIVE_UPDATE
  449. )
  450. Debug.msg(2, "MapSplitter.__init__()")
  451. self.sashWidthMin = 1
  452. self.sashWidthMax = 10
  453. self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged)
  454. self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.OnSashChanging)
  455. self._moveSash = True
  456. wx.CallAfter(self.Init)
  457. def EnableSash(self, enable):
  458. self._moveSash = enable
  459. def Init(self):
  460. self.OnSashChanged(evt = None)
  461. self.SetMinimumPaneSize(0)
  462. self.SetSashSize(self.sashWidthMin)
  463. # def OnMotion(self, event):
  464. # w = self.GetSashSize()
  465. # w1, w2 = self.GetWindow1(), self.GetWindow2()
  466. # if self.SashHitTest(event.GetX(), event.GetY(), tolerance = 20):
  467. # if w == self.sashWidthMin:
  468. # self.SetSashSize(self.sashWidthMax)
  469. # self.SetNeedUpdating(True)
  470. # w1.movingSash = True
  471. # w2.movingSash = True
  472. # else:
  473. # w1.movingSash = False
  474. # w1.movingSash = False
  475. # else:
  476. # if w == self.sashWidthMax:
  477. # self.SetSashSize(self.sashWidthMin)
  478. # self.SetNeedUpdating(True)
  479. # w1.movingSash = True
  480. # w2.movingSash = True
  481. # else:
  482. # w1.movingSash = False
  483. # w2.movingSash = False
  484. # event.Skip()
  485. def OnSashChanged(self, evt):
  486. Debug.msg(5, "MapSplitter.OnSashChanged()")
  487. if not self._moveSash:
  488. return
  489. w1, w2 = self.GetWindow1(), self.GetWindow2()
  490. w1.movingSash = False
  491. w2.movingSash = False
  492. wx.CallAfter(self.SashChanged)
  493. def SashChanged(self):
  494. Debug.msg(5, "MapSplitter.SashChanged()")
  495. w1, w2 = self.GetWindow1(), self.GetWindow2()
  496. w1.SetImageCoords((0, 0))
  497. if self.GetSplitMode() == wx.SPLIT_VERTICAL:
  498. w = w1.GetSize()[0]
  499. w2.SetImageCoords((-w, 0))
  500. else:
  501. h = w1.GetSize()[1]
  502. w2.SetImageCoords((0, -h))
  503. w1.UpdateMap(render = False, renderVector = False)
  504. w2.UpdateMap(render = False, renderVector = False)
  505. pos = self.GetSashPosition()
  506. self.last = pos
  507. def OnSashChanging(self, event):
  508. Debug.msg(5, "MapSplitter.OnSashChanging()")
  509. if not self._moveSash:
  510. event.SetSashPosition(-1)
  511. return
  512. if not (self.GetWindowStyle() & wx.SP_LIVE_UPDATE):
  513. if event:
  514. event.Skip()
  515. return
  516. pos = self.GetSashPosition()
  517. dpos = pos - self.last
  518. self.last = pos
  519. if self.GetSplitMode() == wx.SPLIT_VERTICAL:
  520. dx = -dpos
  521. dy = 0
  522. else:
  523. dx = 0
  524. dy = -dpos
  525. self.GetWindow2().TranslateImage(dx, dy)
  526. self.GetWindow1().movingSash = True
  527. self.GetWindow2().movingSash = True