nviz.py 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688
  1. """
  2. @package nviz.py
  3. @brief 2.5/3D visialization mode for Map Display Window
  4. List of classes:
  5. - GLWindow
  6. - NvizToolWindow
  7. - ViewPositionWindow
  8. (C) 2008 by the GRASS Development Team
  9. This program is free software under the GNU General Public
  10. License (>=v2). Read the file COPYING that comes with GRASS
  11. for details.
  12. @author Martin Landa <landa.martin gmail.com> (Google SoC 2008)
  13. """
  14. import os
  15. import sys
  16. import time
  17. from threading import Thread
  18. import wx
  19. import wx.lib.colourselect as csel
  20. import wx.lib.scrolledpanel as scrolled
  21. try:
  22. from wx import glcanvas
  23. haveGLCanvas = True
  24. except ImportError:
  25. haveGLCanvas = False
  26. try:
  27. from OpenGL.GL import *
  28. from OpenGL.GLUT import *
  29. haveOpenGL = True
  30. except ImportError:
  31. haveOpenGL = False
  32. import globalvar
  33. import gcmd
  34. import gselect
  35. from debug import Debug as Debug
  36. from mapdisp import MapWindow as MapWindow
  37. from preferences import globalSettings as UserSettings
  38. try:
  39. nvizPath = os.path.join(globalvar.ETCWXDIR, "nviz")
  40. sys.path.append(nvizPath)
  41. import grass7_wxnviz as wxnviz
  42. haveNviz = True
  43. except ImportError:
  44. haveNviz = False
  45. class GLWindow(MapWindow, glcanvas.GLCanvas):
  46. """OpenGL canvas for Map Display Window"""
  47. def __init__(self, parent, id,
  48. pos=wx.DefaultPosition,
  49. size=wx.DefaultSize,
  50. style=wx.NO_FULL_REPAINT_ON_RESIZE,
  51. Map=None, tree=None, gismgr=None):
  52. self.parent = parent # MapFrame
  53. self.Map = Map
  54. self.tree = tree
  55. self.gismgr = gismgr
  56. glcanvas.GLCanvas.__init__(self, parent, id)
  57. MapWindow.__init__(self, parent, id, pos, size, style,
  58. Map, tree, gismgr)
  59. self.parent = parent # MapFrame
  60. # attribList=[wx.WX_GL_RGBA, wx.GLX_RED_SIZE, 1,
  61. # wx.GLX_GREEN_SIZE, 1,
  62. # wx.GLX_BLUE_SIZE, 1,
  63. # wx.GLX_DEPTH_SIZE, 1,
  64. # None])
  65. self.init = False
  66. self.render = True # render in full resolution
  67. #
  68. # create nviz instance
  69. #
  70. self.nvizClass = wxnviz.Nviz()
  71. #
  72. # set current display
  73. #
  74. self.nvizClass.SetDisplay(self)
  75. #
  76. # set default lighting model
  77. #
  78. self.nvizClass.SetLightsDefault()
  79. #
  80. # initialize mouse position
  81. #
  82. self.lastX = self.x = 30
  83. self.lastY = self.y = 30
  84. #
  85. # default values
  86. #
  87. self.view = UserSettings.Get(group='nviz', key='view') # reference
  88. self.update = {} # update view/controls
  89. self.object = {} # loaded data objects (layer index / gsurf id)
  90. self.size = None
  91. self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
  92. self.Bind(wx.EVT_SIZE, self.OnSize)
  93. self.Bind(wx.EVT_PAINT, self.OnPaint)
  94. self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  95. self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
  96. self.Bind(wx.EVT_MOTION, self.OnMouseAction)
  97. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
  98. def OnEraseBackground(self, event):
  99. pass # do nothing, to avoid flashing on MSW
  100. def OnSize(self, event):
  101. self.size = self.parent.GetClientSize()
  102. if self.GetContext():
  103. Debug.msg(3, "GLCanvas.OnPaint(): w=%d, h=%d" % \
  104. (self.size.width, self.size.height))
  105. self.SetCurrent()
  106. self.nvizClass.ResizeWindow(self.size.width,
  107. self.size.height)
  108. event.Skip()
  109. def OnPaint(self, event):
  110. Debug.msg(3, "GLCanvas.OnPaint()")
  111. dc = wx.PaintDC(self)
  112. self.SetCurrent()
  113. if not self.init:
  114. self.nvizClass.InitView()
  115. self.LoadDataLayers()
  116. self.view['z-exag']['value'], \
  117. self.view['height']['value'] = self.nvizClass.SetViewDefault()
  118. if hasattr(self.parent, "nvizToolWin"):
  119. self.parent.nvizToolWin.UpdatePage('view')
  120. self.parent.nvizToolWin.UpdateSettings()
  121. self.init = True
  122. self.UpdateMap()
  123. def OnMouseAction(self, event):
  124. # change position
  125. if event.Dragging() and event.LeftIsDown():
  126. self.lastX = self.lastY = self.x = self.y
  127. self.x, self.y = event.GetPosition()
  128. self.Refresh(False)
  129. # change perspective with mouse wheel
  130. wheel = event.GetWheelRotation()
  131. if wheel != 0:
  132. current = event.GetPositionTuple()[:]
  133. Debug.msg (5, "GLWindow.OnMouseMotion(): wheel=%d" % wheel)
  134. if wheel > 0:
  135. value = -1 * self.view['persp']['step']
  136. else:
  137. value = self.view['persp']['step']
  138. self.view['persp']['value'] += value
  139. if self.view['persp']['value'] < 1:
  140. self.view['persp']['value'] = 1
  141. elif self.view['persp']['value'] > 100:
  142. self.view['persp']['value'] = 100
  143. if hasattr(self.parent, "nvizToolWin"):
  144. self.parent.nvizToolWin.UpdateSettings()
  145. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  146. self.view['height']['value'],
  147. self.view['persp']['value'],
  148. self.view['twist']['value'])
  149. # redraw map
  150. self.OnPaint(None)
  151. # update statusbar
  152. ### self.parent.StatusbarUpdate()
  153. def OnLeftDown(self, event):
  154. self.CaptureMouse()
  155. self.x, self.y = self.lastX, self.lastY = event.GetPosition()
  156. def OnLeftUp(self, event):
  157. self.ReleaseMouse()
  158. def UpdateMap(self, render=True):
  159. """
  160. Updates the canvas anytime there is a change to the
  161. underlaying images or to the geometry of the canvas.
  162. @param render re-render map composition
  163. """
  164. start = time.clock()
  165. self.resize = False
  166. # if self.size is None:
  167. # self.size = self.GetClientSize()
  168. # w, h = self.size
  169. # w = float(max(w, 1.0))
  170. # h = float(max(h, 1.0))
  171. # d = float(min(w, h))
  172. # xScale = d / w
  173. # yScale = d / h
  174. # print w, h, d, xScale, yScale
  175. # print self.y, self.lastY, self.x, self.lastX
  176. # print (self.y - self.lastY) * yScale, (self.x - self.lastX) * xScale
  177. # print self.x * xScale
  178. #glRotatef((self.y - self.lastY) * yScale, 1.0, 0.0, 0.0);
  179. #glRotatef((self.x - self.lastX) * xScale, 0.0, 1.0, 0.0);
  180. self.parent.onRenderGauge.Show()
  181. if self.parent.onRenderGauge.GetRange() > 0:
  182. self.parent.onRenderGauge.SetValue(1)
  183. self.parent.onRenderTimer.Start(100)
  184. self.parent.onRenderCounter = 0
  185. if 'view' in self.update.keys():
  186. self.nvizClass.SetView(self.view['pos']['x'], self.view['pos']['y'],
  187. self.view['height']['value'],
  188. self.view['persp']['value'],
  189. self.view['twist']['value'])
  190. del self.update['view']
  191. if 'z-exag' in self.update.keys():
  192. self.nvizClass.SetZExag(self.view['z-exag']['value'])
  193. del self.update['z-exag']
  194. if self.render is True:
  195. self.nvizClass.Draw(False)
  196. else:
  197. self.nvizClass.Draw(True) # quick
  198. self.SwapBuffers()
  199. stop = time.clock()
  200. #
  201. # hide process bar
  202. #
  203. if self.parent.onRenderGauge.GetRange() > 0:
  204. self.parent.onRenderTimer.Stop()
  205. self.parent.onRenderGauge.Hide()
  206. #
  207. # update statusbar
  208. #
  209. ### self.Map.SetRegion()
  210. # self.parent.StatusbarUpdate()
  211. Debug.msg(3, "GLWindow.UpdateMap(): render=%s, -> time=%g" % \
  212. (self.render, (stop-start)))
  213. def EraseMap(self):
  214. """
  215. Erase the canvas
  216. """
  217. self.nvizClass.EraseMap()
  218. self.SwapBuffers()
  219. def LoadDataLayers(self):
  220. """Load raster/vector from current layer tree
  221. @todo volumes
  222. """
  223. # load raster maps
  224. for layer in self.Map.GetListOfLayers(l_type='raster', l_active=True):
  225. self.LoadRaster(layer)
  226. # load vector maps
  227. for layer in self.Map.GetListOfLayers(l_type='vector', l_active=True):
  228. self.LoadVector(layer)
  229. def LoadRaster(self, layer):
  230. """Load raster map -> surface"""
  231. if layer.type != 'raster':
  232. return
  233. id = self.nvizClass.LoadSurface(str(layer.name), None, None)
  234. if id < 0:
  235. raise gcmd.NvizError(parent=self.parent,
  236. message=_("Unable to load raster map <%s>" % layer.name))
  237. # set resolution
  238. res = UserSettings.Get(group='nviz', key='surface',
  239. subkey=['draw', 'res-fine'])
  240. wire = UserSettings.Get(group='nviz', key='surface',
  241. subkey=['draw', 'res-coarse'])
  242. self.nvizClass.SetSurfaceRes(id, res, wire)
  243. self.object[self.Map.GetLayerIndex(layer)] = id ### FIXME layer index is not fixed id!
  244. def UnloadRaster(self, layer):
  245. """Unload raster map"""
  246. if layer.type != 'raster':
  247. return
  248. idx = self.Map.GetLayerIndex(layer) ### FIXME layer index is not fixed id!
  249. if not self.object.has_key(idx):
  250. return
  251. if layer.type == 'raster':
  252. if self.nvizClass.UnloadSurface(self.object[idx]) == 0:
  253. raise gcmd.NvizError(parent=self.parent,
  254. message=_("Unable to unload raster map <%s>" % layer.name))
  255. def LoadVector(self, layer):
  256. """Load vector map overlay"""
  257. if layer.type != 'vector':
  258. return
  259. id = self.nvizClass.LoadVector(str(layer.name))
  260. if id < 0:
  261. raise gcmd.NvizError(parent=self.parent,
  262. message=_("Unable to load vector map <%s>" % layer.name))
  263. self.object[self.Map.GetLayerIndex(layer)] = id ### FIXME layer index is not fixed id!
  264. def UnloadVector(self, layer):
  265. """Unload vector map overlay"""
  266. if layer.type != 'vector':
  267. return
  268. idx = self.Map.GetLayerIndex(layer) ### FIXME layer index is not fixed id!
  269. if not self.object.has_key(idx):
  270. return
  271. if layer.type == 'vector':
  272. if self.nvizClass.UnloadVector(self.object[idx]) == 0:
  273. raise gcmd.NvizError(parent=self.parent,
  274. message=_("Unable to unload vector map <%s>" % layer.name))
  275. def Reset(self):
  276. """Reset (unload data)"""
  277. self.nvizClass.Reset()
  278. self.init = False
  279. def OnZoomToMap(self, event):
  280. """
  281. Set display extents to match selected raster
  282. or vector map or volume.
  283. @todo vector, volume
  284. """
  285. layer = self.GetSelectedLayer()
  286. if layer is None:
  287. return
  288. Debug.msg (3, "GLWindow.OnZoomToMap(): layer=%s, type=%s" % \
  289. (layer.name, layer.type))
  290. self.nvizClass.SetViewportDefault()
  291. def ResetView(self):
  292. """Reset to default view"""
  293. self.view['pos']['x'] = wxnviz.VIEW_DEFAULT_POS_X
  294. self.view['pos']['y'] = wxnviz.VIEW_DEFAULT_POS_Y
  295. self.view['z-exag']['value'], \
  296. self.view['height']['value'] = self.nvizClass.SetViewDefault()
  297. self.view['persp']['value'] = wxnviz.VIEW_DEFAULT_PERSP
  298. self.view['twist']['value'] = wxnviz.VIEW_DEFAULT_TWIST
  299. self.update['view'] = None
  300. self.update['z-exag'] = None
  301. def GetMapObjId(self, layer):
  302. """Get map object id of given map layer (2D)
  303. @param layer MapLayer instance
  304. """
  305. index = self.Map.GetLayerIndex(layer)
  306. try:
  307. return self.object[index]
  308. except:
  309. return -1
  310. def SetLayerSettings(self, data):
  311. """Set settings for selected layer
  312. @param data settings
  313. @return 1 on success
  314. @return 0 on failure
  315. """
  316. # get currently selected map layer
  317. if not self.tree or not self.tree.GetSelection():
  318. return 0
  319. item = self.tree.GetSelection()
  320. try:
  321. self.tree.SetPyData(item)[0]['nviz'] = data
  322. except:
  323. return 0
  324. return 1
  325. class NvizToolWindow(wx.Frame):
  326. """Experimental window for Nviz tools
  327. @todo integrate with Map display
  328. """
  329. def __init__(self, parent=None, id=wx.ID_ANY, title=_("Nviz tools"),
  330. pos=wx.DefaultPosition, size=wx.DefaultSize,
  331. style=wx.DEFAULT_FRAME_STYLE, mapWindow=None):
  332. self.parent = parent # MapFrame
  333. self.mapWindow = mapWindow
  334. self.settings = mapWindow.view # GLWindow.view
  335. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  336. # dialog body
  337. mainSizer = wx.BoxSizer(wx.VERTICAL)
  338. self.win = {} # window ids
  339. #
  340. # notebook
  341. #
  342. self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  343. self.page = {}
  344. # view page
  345. self.__createViewPage()
  346. self.page['view'] = 0
  347. # surface page
  348. self.__createSurfacePage()
  349. self.page['surface'] = 1
  350. # vector page
  351. self.__createVectorPage()
  352. self.page['vector'] = 2
  353. # settings page
  354. self.__createSettingsPage()
  355. self.page['settings'] = 3
  356. self.UpdatePage('surface')
  357. self.UpdatePage('vector')
  358. self.UpdatePage('settings')
  359. mainSizer.Add(item=self.notebook, proportion=1,
  360. flag=wx.EXPAND | wx.ALL, border=5)
  361. #
  362. # button (see menuform)
  363. #
  364. btnCancel = wx.Button(self, wx.ID_CANCEL)
  365. btnApply = wx.Button(self, wx.ID_APPLY)
  366. btnSave = wx.Button(self, wx.ID_SAVE)
  367. btnSave.SetDefault()
  368. # bindings
  369. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  370. btnApply.SetToolTipString(_("Apply changes and update display"))
  371. btnApply.SetDefault()
  372. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  373. btnSave.SetToolTipString(_("Apply changes, update display and save changes to layer settings"))
  374. btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)
  375. btnCancel.SetToolTipString(_("Hide dialog and ignore changes"))
  376. # sizer
  377. btnSizer = wx.StdDialogButtonSizer()
  378. btnSizer.AddButton(btnApply)
  379. btnSizer.AddButton(btnCancel)
  380. btnSizer.AddButton(btnSave)
  381. btnSizer.Realize()
  382. mainSizer.Add(item=btnSizer, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL,
  383. border=5)
  384. #
  385. # bindings
  386. #
  387. self.Bind(wx.EVT_CLOSE, self.OnClose)
  388. #
  389. # layout
  390. #
  391. self.SetSizer(mainSizer)
  392. mainSizer.Fit(self)
  393. def __createViewPage(self):
  394. """Create view settings page"""
  395. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  396. self.notebook.AddPage(page=panel,
  397. text=" %s " % _("View"))
  398. pageSizer = wx.BoxSizer(wx.VERTICAL)
  399. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  400. self.win['view'] = {}
  401. # position
  402. posSizer = wx.GridBagSizer(vgap=3, hgap=3)
  403. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("W")),
  404. pos=(1, 0), flag=wx.ALIGN_CENTER)
  405. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("N")),
  406. pos=(0, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_BOTTOM)
  407. viewPos = ViewPositionWindow(panel, id=wx.ID_ANY, size=(175, 175),
  408. settings=self.settings, mapwindow=self.mapWindow)
  409. self.win['view']['pos'] = viewPos.GetId()
  410. posSizer.Add(item=viewPos,
  411. pos=(1, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL)
  412. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("S")),
  413. pos=(2, 1), flag=wx.ALIGN_CENTER | wx.ALIGN_TOP)
  414. posSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("E")),
  415. pos=(1, 2), flag=wx.ALIGN_CENTER)
  416. gridSizer.Add(item=posSizer, pos=(0, 0))
  417. # perspective
  418. self.CreateControl(panel, dict=self.win['view'], name='persp',
  419. range=(self.settings['persp']['min'], self.settings['persp']['max']),
  420. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  421. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Perspective:")),
  422. pos=(1, 0), flag=wx.ALIGN_CENTER)
  423. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['slider']), pos=(2, 0))
  424. gridSizer.Add(item=self.FindWindowById(self.win['view']['persp']['spin']), pos=(3, 0),
  425. flag=wx.ALIGN_CENTER)
  426. # twist
  427. self.CreateControl(panel, dict=self.win['view'], name='twist',
  428. range=(self.settings['twist']['min'], self.settings['twist']['max']),
  429. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  430. gridSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Twist:")),
  431. pos=(1, 1), flag=wx.ALIGN_CENTER)
  432. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['slider']), pos=(2, 1))
  433. gridSizer.Add(item=self.FindWindowById(self.win['view']['twist']['spin']), pos=(3, 1),
  434. flag=wx.ALIGN_CENTER)
  435. # height + z-exag
  436. self.CreateControl(panel, dict=self.win['view'], name='height', sliderHor=False,
  437. range=(self.settings['height']['min'], self.settings['height']['max']),
  438. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  439. self.CreateControl(panel, dict=self.win['view'], name='z-exag', sliderHor=False,
  440. range=(self.settings['z-exag']['min'], self.settings['z-exag']['max']),
  441. bind=(self.OnViewChange, self.OnViewChanged, self.OnViewChangedSpin))
  442. heightSizer = wx.GridBagSizer(vgap=3, hgap=3)
  443. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Height:")),
  444. pos=(0, 0), flag=wx.ALIGN_LEFT, span=(1, 2))
  445. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['slider']),
  446. flag=wx.ALIGN_RIGHT, pos=(1, 0))
  447. heightSizer.Add(item=self.FindWindowById(self.win['view']['height']['spin']),
  448. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  449. wx.BOTTOM | wx.RIGHT, pos=(1, 1))
  450. heightSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY, label=_("Z-exag:")),
  451. pos=(0, 2), flag=wx.ALIGN_LEFT, span=(1, 2))
  452. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['slider']),
  453. flag=wx.ALIGN_RIGHT, pos=(1, 2))
  454. heightSizer.Add(item=self.FindWindowById(self.win['view']['z-exag']['spin']),
  455. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.TOP |
  456. wx.BOTTOM | wx.RIGHT, pos=(1, 3))
  457. gridSizer.Add(item=heightSizer, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  458. # view setup + reset
  459. viewSizer = wx.BoxSizer(wx.HORIZONTAL)
  460. viewSizer.Add(item=wx.StaticText(panel, id=wx.ID_ANY,
  461. label=_("Look at:")),
  462. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
  463. viewType = wx.Choice (parent=panel, id=wx.ID_ANY, size=(125, -1),
  464. choices = [_("top"),
  465. _("north"),
  466. _("south"),
  467. _("east"),
  468. _("west"),
  469. _("north-west"),
  470. _("north-east"),
  471. _("south-east"),
  472. _("south-west")])
  473. viewType.SetSelection(0)
  474. viewType.Bind(wx.EVT_CHOICE, self.OnLookAt)
  475. # self.win['lookAt'] = viewType.GetId()
  476. viewSizer.Add(item=viewType, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
  477. border=5)
  478. reset = wx.Button(panel, id=wx.ID_ANY, label=_("Reset"))
  479. reset.SetToolTipString(_("Reset to default view"))
  480. # self.win['reset'] = reset.GetId()
  481. reset.Bind(wx.EVT_BUTTON, self.OnResetView)
  482. viewSizer.Add(item=reset, proportion=1,
  483. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT,
  484. border=5)
  485. gridSizer.AddGrowableCol(3)
  486. gridSizer.Add(item=viewSizer, pos=(4, 0), span=(1, 2),
  487. flag=wx.EXPAND)
  488. # body
  489. pageSizer.Add(item=gridSizer, proportion=1,
  490. flag=wx.EXPAND | wx.ALL,
  491. border=5)
  492. panel.SetSizer(pageSizer)
  493. def __createSurfacePage(self):
  494. """Create view settings page"""
  495. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  496. # panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY)
  497. # panel.SetupScrolling(scroll_x=True, scroll_y=True)
  498. self.notebook.AddPage(page=panel,
  499. text=" %s " % _("Surface"))
  500. pageSizer = wx.BoxSizer(wx.VERTICAL)
  501. self.win['surface'] = {}
  502. #
  503. # surface attributes
  504. #
  505. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  506. label=" %s " % (_("Surface attributes")))
  507. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  508. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  509. # labels
  510. # col = 0
  511. # for type in (_("Attribute"),
  512. # _("Use"),
  513. # _("Map"),
  514. # _("Constant")):
  515. # gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  516. # label=type),
  517. # pos=(0, col))
  518. # col += 1
  519. # type
  520. self.win['surface']['attr'] = {}
  521. row = 0
  522. for code, attrb in (('topo', _("Topography")),
  523. ('color', _("Color")),
  524. ('mask', _("Mask")),
  525. ('transp', _("Transparency")),
  526. ('shine', _("Shininess")),
  527. ('emit', _("Emission"))):
  528. self.win['surface'][code] = {}
  529. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  530. label=attrb + ':'),
  531. pos=(row, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  532. use = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  533. choices = [_("map")])
  534. if code not in ('topo', 'color', 'shine'):
  535. use.Insert(item=_("unset"), pos=0)
  536. self.win['surface'][code]['required'] = False
  537. else:
  538. self.win['surface'][code]['required'] = True
  539. if code != 'mask':
  540. use.Append(item=_('constant'))
  541. self.win['surface'][code]['use'] = use.GetId()
  542. use.Bind(wx.EVT_CHOICE, self.OnSurfaceUse)
  543. gridSizer.Add(item=use, flag=wx.ALIGN_CENTER_VERTICAL,
  544. pos=(row, 1))
  545. map = gselect.Select(parent=panel, id=wx.ID_ANY,
  546. # size=globalvar.DIALOG_GSELECT_SIZE,
  547. size=(200, -1),
  548. type="raster")
  549. self.win['surface'][code]['map'] = map.GetId() - 1 # FIXME
  550. map.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  551. # changing map topography not allowed
  552. if code == 'topo':
  553. map.Enable(False)
  554. gridSizer.Add(item=map, flag=wx.ALIGN_CENTER_VERTICAL,
  555. pos=(row, 2))
  556. if code == 'color':
  557. value = csel.ColourSelect(panel, id=wx.ID_ANY,
  558. colour=UserSettings.Get(group='nviz', key='surface',
  559. subkey=['color', 'value']))
  560. value.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceMap)
  561. elif code == 'mask':
  562. value = None
  563. else:
  564. value = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  565. initial=0)
  566. if code == 'topo':
  567. value.SetRange(minVal=-1e9, maxVal=1e9)
  568. elif code in ('shine', 'transp', 'emit'):
  569. value.SetRange(minVal=0, maxVal=255)
  570. else:
  571. value.SetRange(minVal=0, maxVal=100)
  572. value.Bind(wx.EVT_TEXT, self.OnSurfaceMap)
  573. if value:
  574. self.win['surface'][code]['const'] = value.GetId()
  575. value.Enable(False)
  576. gridSizer.Add(item=value, flag=wx.ALIGN_CENTER_VERTICAL,
  577. pos=(row, 3))
  578. else:
  579. self.win['surface'][code]['const'] = None
  580. self.SetSurfaceUseMap(code) # -> enable map / disable constant
  581. row += 1
  582. boxSizer.Add(item=gridSizer, proportion=1,
  583. flag=wx.ALL | wx.EXPAND, border=3)
  584. pageSizer.Add(item=boxSizer, proportion=0,
  585. flag=wx.EXPAND | wx.ALL,
  586. border=5)
  587. #
  588. # draw
  589. #
  590. self.win['surface']['draw'] = {}
  591. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  592. label=" %s " % (_("Draw")))
  593. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  594. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  595. gridSizer.AddGrowableCol(4)
  596. # mode
  597. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  598. label=_("Mode:")),
  599. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  600. mode = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  601. choices = [_("coarse"),
  602. _("fine"),
  603. _("both")])
  604. mode.SetName("selection")
  605. mode.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  606. self.win['surface']['draw']['mode'] = mode.GetId()
  607. gridSizer.Add(item=mode, flag=wx.ALIGN_CENTER_VERTICAL,
  608. pos=(0, 1))
  609. # resolution (mode)
  610. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  611. label=_("Resolution:")),
  612. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  613. resSizer = wx.BoxSizer(wx.HORIZONTAL)
  614. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  615. label=_("coarse:")),
  616. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  617. resC = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  618. initial=1,
  619. min=1,
  620. max=100)
  621. resC.SetName("value")
  622. self.win['surface']['draw']['res-coarse'] = resC.GetId()
  623. resC.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  624. resSizer.Add(item=resC, flag=wx.ALL, border=3)
  625. resSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  626. label=_("fine:")),
  627. flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
  628. resF = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  629. initial=1,
  630. min=1,
  631. max=100)
  632. resF.SetName("value")
  633. self.win['surface']['draw']['res-fine'] = resF.GetId()
  634. resF.Bind(wx.EVT_SPINCTRL, self.OnSurfaceResolution)
  635. resSizer.Add(item=resF, flag=wx.ALL, border=3)
  636. gridSizer.Add(item=resSizer, pos=(0, 3), span=(1, 2))
  637. # style
  638. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  639. label=_("Coarse style:")),
  640. pos=(1, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  641. style = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  642. choices = [_("wire"),
  643. _("surface")])
  644. style.SetName("selection")
  645. self.win['surface']['draw']['style'] = style.GetId()
  646. style.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  647. gridSizer.Add(item=style, flag=wx.ALIGN_CENTER_VERTICAL,
  648. pos=(1, 1))
  649. # shading
  650. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  651. label=_("Shading:")),
  652. pos=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  653. shade = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  654. choices = [_("flat"),
  655. _("gouraud")])
  656. shade.SetName("selection")
  657. self.win['surface']['draw']['shading'] = shade.GetId()
  658. shade.Bind(wx.EVT_CHOICE, self.OnSurfaceMode)
  659. gridSizer.Add(item=shade, flag=wx.ALIGN_CENTER_VERTICAL,
  660. pos=(1, 3))
  661. # color
  662. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  663. label=_("Wire color:")),
  664. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  665. color = csel.ColourSelect(panel, id=wx.ID_ANY)
  666. color.SetName("colour")
  667. color.Bind(csel.EVT_COLOURSELECT, self.OnSurfaceWireColor)
  668. self.win['surface']['draw']['color'] = color.GetId()
  669. gridSizer.Add(item=color, flag=wx.ALIGN_CENTER_VERTICAL,
  670. pos=(2, 1))
  671. boxSizer.Add(item=gridSizer, proportion=1,
  672. flag=wx.ALL | wx.EXPAND, border=3)
  673. pageSizer.Add(item=boxSizer, proportion=0,
  674. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  675. border=5)
  676. all = wx.Button(panel, id=wx.ID_ANY, label=_("All"))
  677. all.SetToolTipString(_("Use for all loaded surfaces"))
  678. # self.win['reset'] = reset.GetId()
  679. all.Bind(wx.EVT_BUTTON, self.OnSurfaceModeAll)
  680. gridSizer.Add(item=all, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
  681. pos=(2, 4))
  682. #
  683. # mask
  684. #
  685. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  686. label=" %s " % (_("Mask")))
  687. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  688. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  689. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  690. label=_("Mask zeros:")),
  691. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  692. elev = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  693. label=_("by elevation"))
  694. elev.Enable(False) # TODO: not implemented yet
  695. gridSizer.Add(item=elev, pos=(0, 1))
  696. color = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  697. label=_("by color"))
  698. color.Enable(False) # TODO: not implemented yet
  699. gridSizer.Add(item=color, pos=(0, 2))
  700. boxSizer.Add(item=gridSizer, proportion=1,
  701. flag=wx.ALL | wx.EXPAND, border=3)
  702. pageSizer.Add(item=boxSizer, proportion=0,
  703. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  704. border=5)
  705. #
  706. # position
  707. #
  708. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  709. label=" %s " % (_("Position")))
  710. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  711. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  712. # position
  713. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  714. label="X:"),
  715. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  716. x = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  717. initial=0,
  718. min=0,
  719. max=100)
  720. x.Enable(False) # TODO: not implemented yet
  721. gridSizer.Add(item=x, pos=(0, 1))
  722. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  723. label="X:"),
  724. pos=(0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
  725. y = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  726. initial=0,
  727. min=0,
  728. max=100)
  729. y.Enable(False) # TODO: not implemented yet
  730. gridSizer.Add(item=y, pos=(0, 3))
  731. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  732. label="X:"),
  733. pos=(0, 4), flag=wx.ALIGN_CENTER_VERTICAL)
  734. z = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
  735. initial=0,
  736. min=0,
  737. max=100)
  738. z.Enable(False) # TODO: not implemented yet
  739. gridSizer.Add(item=z, pos=(0, 5))
  740. boxSizer.Add(item=gridSizer, proportion=1,
  741. flag=wx.ALL | wx.EXPAND, border=3)
  742. pageSizer.Add(item=boxSizer, proportion=0,
  743. flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
  744. border=5)
  745. panel.SetSizer(pageSizer)
  746. def __createVectorPage(self):
  747. """Create view settings page"""
  748. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  749. self.notebook.AddPage(page=panel,
  750. text=" %s " % _("Vector"))
  751. pageSizer = wx.BoxSizer(wx.VERTICAL)
  752. self.win['vector'] = {}
  753. #
  754. # vector lines
  755. #
  756. self.win['vector']['lines'] = {}
  757. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  758. label=" %s " % (_("Vector lines")))
  759. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  760. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  761. # width
  762. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  763. label=_("Width:")),
  764. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  765. width = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(65, -1),
  766. initial=1,
  767. min=1,
  768. max=100)
  769. self.win['vector']['lines']['width'] = width.GetId()
  770. width.Bind(wx.EVT_SPINCTRL, self.OnVectorLines)
  771. gridSizer.Add(item=width, pos=(0, 1),
  772. flag=wx.ALIGN_CENTER_VERTICAL)
  773. gridSizer.AddGrowableCol(2)
  774. # color
  775. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  776. label=_("Color:")),
  777. pos=(0, 3), flag=wx.ALIGN_CENTER_VERTICAL)
  778. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  779. colour=UserSettings.Get(group='nviz', key='vector',
  780. subkey=['lines', 'color']))
  781. self.win['vector']['lines']['color'] = color.GetId()
  782. color.Bind(csel.EVT_COLOURSELECT, self.OnVectorLines)
  783. gridSizer.Add(item=color, pos=(0, 4))
  784. gridSizer.AddGrowableCol(5)
  785. # display
  786. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  787. label=_("Display:")),
  788. pos=(0, 6), flag=wx.ALIGN_CENTER_VERTICAL)
  789. display = wx.Choice (parent=panel, id=wx.ID_ANY, size=(100, -1),
  790. choices = [_("on surface"),
  791. _("flat")])
  792. self.win['vector']['lines']['flat'] = display.GetId()
  793. display.Bind(wx.EVT_CHOICE, self.OnVectorDisplay)
  794. gridSizer.Add(item=display, flag=wx.ALIGN_CENTER_VERTICAL,
  795. pos=(0, 7))
  796. surface = wx.ComboBox(parent=panel, id=wx.ID_ANY, size=(250, -1),
  797. style=wx.CB_SIMPLE | wx.CB_READONLY,
  798. choices=[])
  799. self.win['vector']['lines']['surface'] = surface.GetId()
  800. gridSizer.Add(item=surface,
  801. pos=(1, 0), span=(1, 8),
  802. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
  803. # high
  804. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  805. label=_("Hight above surface:")),
  806. pos=(2, 0), flag=wx.ALIGN_CENTER_VERTICAL,
  807. span=(1, 2))
  808. self.CreateControl(panel, dict=self.win['vector']['lines'], name='height', size=300,
  809. range=(0, 1000),
  810. bind=(self.OnVectorHeight, self.OnVectorHeight, self.OnVectorHeight))
  811. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['slider']),
  812. pos=(2, 2), span=(1, 6))
  813. gridSizer.Add(item=self.FindWindowById(self.win['vector']['lines']['height']['spin']),
  814. pos=(3, 4),
  815. flag=wx.ALIGN_CENTER)
  816. boxSizer.Add(item=gridSizer, proportion=1,
  817. flag=wx.ALL | wx.EXPAND, border=3)
  818. pageSizer.Add(item=boxSizer, proportion=0,
  819. flag=wx.EXPAND | wx.ALL,
  820. border=5)
  821. panel.SetSizer(pageSizer)
  822. def __createSettingsPage(self):
  823. """Create settings page"""
  824. panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
  825. self.notebook.AddPage(page=panel,
  826. text=" %s " % _("Settings"))
  827. pageSizer = wx.BoxSizer(wx.VERTICAL)
  828. self.win['settings'] = {}
  829. #
  830. # general
  831. #
  832. self.win['settings']['general'] = {}
  833. box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
  834. label=" %s " % (_("General")))
  835. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  836. gridSizer = wx.GridBagSizer(vgap=3, hgap=3)
  837. # background color
  838. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  839. label=_("Background color:")),
  840. pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
  841. color = csel.ColourSelect(panel, id=wx.ID_ANY,
  842. colour=UserSettings.Get(group='nviz', key='settings',
  843. subkey=['general', 'bgcolor']))
  844. self.win['settings']['general']['bgcolor'] = color.GetId()
  845. color.Bind(csel.EVT_COLOURSELECT, self.OnSettings)
  846. gridSizer.Add(item=color, pos=(0, 1))
  847. boxSizer.Add(item=gridSizer, proportion=1,
  848. flag=wx.ALL | wx.EXPAND, border=3)
  849. pageSizer.Add(item=boxSizer, proportion=0,
  850. flag=wx.EXPAND | wx.ALL,
  851. border=5)
  852. panel.SetSizer(pageSizer)
  853. panel.SetSizer(pageSizer)
  854. def CreateControl(self, parent, dict, name, range, bind, sliderHor=True, size=200):
  855. """Add control (Slider + SpinCtrl)"""
  856. dict[name] = {}
  857. if sliderHor:
  858. style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
  859. wx.SL_BOTTOM
  860. sizeW = (size, -1)
  861. else:
  862. style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | \
  863. wx.SL_BOTTOM | wx.SL_INVERSE
  864. sizeW = (-1, size)
  865. slider = wx.Slider(parent=parent, id=wx.ID_ANY,
  866. value=self.settings[name]['value'],
  867. minValue=range[0],
  868. maxValue=range[1],
  869. style=style,
  870. size=sizeW)
  871. slider.SetName('slider')
  872. slider.Bind(wx.EVT_SCROLL, bind[0])
  873. slider.Bind(wx.EVT_SCROLL_CHANGED, bind[1])
  874. dict[name]['slider'] = slider.GetId()
  875. spin = wx.SpinCtrl(parent=parent, id=wx.ID_ANY, size=(65, -1),
  876. initial=self.settings[name]['value'],
  877. min=range[0],
  878. max=range[1])
  879. # spin = wx.SpinButton(parent=parent, id=wx.ID_ANY)
  880. # spin.SetValue (self.settings[name]['value'])
  881. # spin.SetRange(self.settings[name]['min'],
  882. # self.settings[name]['max'])
  883. # no 'changed' event ... (FIXME)
  884. spin.SetName('spin')
  885. spin.Bind(wx.EVT_SPINCTRL, bind[2])
  886. dict[name]['spin'] = spin.GetId()
  887. def UpdateSettings(self):
  888. """Update dialog settings"""
  889. for control in ('height',
  890. 'persp',
  891. 'twist',
  892. 'z-exag'):
  893. for win in self.win['view'][control].itervalues():
  894. self.FindWindowById(win).SetValue(int(self.settings[control]['value']))
  895. self.FindWindowById(self.win['view']['pos']).Draw()
  896. self.FindWindowById(self.win['view']['pos']).Refresh(False)
  897. self.Refresh(False)
  898. def __GetWindowName(self, dict, id):
  899. for name in dict.iterkeys():
  900. if type(dict[name]) is type({}):
  901. for win in dict[name].itervalues():
  902. if win == id:
  903. return name
  904. else:
  905. if dict[name] == id:
  906. return name
  907. return None
  908. def OnViewChange(self, event):
  909. """Change view, render in quick mode"""
  910. # find control
  911. winName = self.__GetWindowName(self.win['view'], event.GetId())
  912. if not winName:
  913. return
  914. self.settings[winName]['value'] = event.GetInt()
  915. for win in self.win['view'][winName].itervalues():
  916. self.FindWindowById(win).SetValue(self.settings[winName]['value'])
  917. if winName in ('pos', 'height', 'twist', 'persp'):
  918. self.mapWindow.update['view'] = None
  919. else:
  920. self.mapWindow.update[winName] = None
  921. self.mapWindow.render = False
  922. self.mapWindow.Refresh(False)
  923. def OnViewChanged(self, event):
  924. """View changed, render in full resolution"""
  925. self.mapWindow.render = True
  926. self.mapWindow.Refresh(False)
  927. def OnViewChangedSpin(self, event):
  928. """View changed, render in full resolution"""
  929. self.OnViewChange(event)
  930. self.OnViewChanged(None)
  931. def OnResetView(self, event):
  932. """Reset to default view (view page)"""
  933. self.mapWindow.ResetView()
  934. self.UpdateSettings()
  935. self.mapWindow.Refresh(False)
  936. def OnLookAt(self, event):
  937. """Look at (view page)"""
  938. sel = event.GetSelection()
  939. if sel == 0: # top
  940. self.settings['pos']['x'] = 0.5
  941. self.settings['pos']['y'] = 0.5
  942. elif sel == 1: # north
  943. self.settings['pos']['x'] = 0.5
  944. self.settings['pos']['y'] = 0.0
  945. elif sel == 2: # south
  946. self.settings['pos']['x'] = 0.5
  947. self.settings['pos']['y'] = 1.0
  948. elif sel == 3: # east
  949. self.settings['pos']['x'] = 1.0
  950. self.settings['pos']['y'] = 0.5
  951. elif sel == 4: # west
  952. self.settings['pos']['x'] = 0.0
  953. self.settings['pos']['y'] = 0.5
  954. elif sel == 5: # north-west
  955. self.settings['pos']['x'] = 0.0
  956. self.settings['pos']['y'] = 0.0
  957. elif sel == 6: # north-east
  958. self.settings['pos']['x'] = 1.0
  959. self.settings['pos']['y'] = 0.0
  960. elif sel == 7: # south-east
  961. self.settings['pos']['x'] = 1.0
  962. self.settings['pos']['y'] = 1.0
  963. elif sel == 8: # south-west
  964. self.settings['pos']['x'] = 0.0
  965. self.settings['pos']['y'] = 1.0
  966. self.mapWindow.update['view'] = None
  967. self.UpdateSettings()
  968. self.mapWindow.Refresh(False)
  969. def OnSave(self, event):
  970. """OK button pressed
  971. Apply changes, update map and save settings of selected layer
  972. """
  973. #
  974. # apply changes
  975. #
  976. self.OnApply(None)
  977. #
  978. # save settings
  979. #
  980. type = self.mapWindow.GetSelectedLayer().type
  981. data = self.mapWindow.GetSelectedLayer(nviz=True)
  982. if data is None: # no settings
  983. data = {}
  984. if type == 'raster': # -> surface
  985. #
  986. # surface attributes
  987. #
  988. data['attribute'] = {}
  989. for attrb in ('topo', 'color', 'mask',
  990. 'transp', 'shine', 'emit'):
  991. use = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  992. if self.win['surface'][attrb]['required']: # map, constant
  993. if use == 0: # map
  994. map = True
  995. elif use == 1: # constant
  996. map = False
  997. else: # unset, map, constant
  998. if use == 0: # unset
  999. map = None
  1000. elif use == 1: # map
  1001. map = True
  1002. elif use == 2: # constant
  1003. map = False
  1004. if map is None:
  1005. continue
  1006. if map:
  1007. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1008. else:
  1009. if attrb == 'color':
  1010. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetColour()
  1011. else:
  1012. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1013. data['attribute'][attrb] = {}
  1014. data['attribute'][attrb]['map'] = map
  1015. data['attribute'][attrb]['value'] = value
  1016. #
  1017. # draw
  1018. #
  1019. data['draw'] = {}
  1020. for control in ('mode', 'shading', 'style'):
  1021. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetSelection()
  1022. for control in ('res-coarse', 'res-fine'):
  1023. data['draw'][control] = self.FindWindowById(self.win['surface']['draw'][control]).GetValue()
  1024. self.mapWindow.SetLayerSettings(data)
  1025. def OnApply(self, event):
  1026. """Apply button pressed
  1027. Apply changes, update map
  1028. """
  1029. layer = self.mapWindow.GetSelectedLayer()
  1030. id = self.mapWindow.GetMapObjId(layer)
  1031. if layer.type == 'raster':
  1032. self.ApplySurface(id)
  1033. elif layer.type == 'vector':
  1034. self.ApplyVector(id)
  1035. self.ApplySettings()
  1036. self.mapWindow.Refresh(False)
  1037. def ApplySurface(self, id):
  1038. """Apply changes for surfaces"""
  1039. # surface attributes
  1040. for attrb in ('topo', 'color', 'mask',
  1041. 'transp', 'shine', 'emit'):
  1042. if self.mapWindow.update.has_key(attrb):
  1043. map, value = self.mapWindow.update[attrb]
  1044. if map is None: # unset
  1045. # only optional attributes
  1046. if attrb == 'mask':
  1047. # TODO: invert mask
  1048. # TODO: broken in NVIZ
  1049. self.mapWindow.nvizClass.UnsetSurfaceMask(id)
  1050. elif attrb == 'transp':
  1051. self.mapWindow.nvizClass.UnsetSurfaceTransp(id)
  1052. elif attrb == 'emit':
  1053. self.mapWindow.nvizClass.UnsetSurfaceEmit(id)
  1054. else:
  1055. if len(value) <= 0: # ignore empty values (TODO: warning)
  1056. continue
  1057. if attrb == 'topo':
  1058. self.mapWindow.nvizClass.SetSurfaceTopo(id, map, str(value))
  1059. elif attrb == 'color':
  1060. self.mapWindow.nvizClass.SetSurfaceColor(id, map, str(value))
  1061. elif attrb == 'mask':
  1062. # TODO: invert mask
  1063. # TODO: broken in NVIZ
  1064. self.mapWindow.nvizClass.SetSurfaceMask(id, False, str(value))
  1065. elif attrb == 'transp':
  1066. self.mapWindow.nvizClass.SetSurfaceTransp(id, map, str(value))
  1067. elif attrb == 'shine':
  1068. self.mapWindow.nvizClass.SetSurfaceShine(id, map, str(value))
  1069. elif attrb == 'emit':
  1070. self.mapWindow.nvizClass.SetSurfaceEmit(id, map, str(value))
  1071. del self.mapWindow.update[attrb]
  1072. # draw res
  1073. if self.mapWindow.update.has_key('draw-res'):
  1074. coarse, fine, all = self.mapWindow.update['draw-res']
  1075. if all:
  1076. self.mapWindow.nvizClass.SetSurfaceRes(-1, fine, coarse)
  1077. else:
  1078. self.mapWindow.nvizClass.SetSurfaceRes(id, fine, coarse)
  1079. # draw style
  1080. if self.mapWindow.update.has_key('draw-style'):
  1081. style, all = self.mapWindow.update['draw-style']
  1082. if all:
  1083. self.mapWindow.nvizClass.SetSurfaceStyle(-1, style)
  1084. else:
  1085. self.mapWindow.nvizClass.SetSurfaceStyle(id, style)
  1086. # wire color
  1087. if self.mapWindow.update.has_key('draw-color'):
  1088. color, all = self.mapWindow.update['draw-color']
  1089. if all:
  1090. self.mapWindow.nvizClass.SetWireColor(id, str(color))
  1091. else:
  1092. self.mapWindow.nvizClass.SetWireColor(-1, str(color))
  1093. def ApplyVector(self, id):
  1094. """Apply changes for vector"""
  1095. width = self.FindWindowById(self.win['vector']['lines']['width']).GetValue()
  1096. color = self.FindWindowById(self.win['vector']['lines']['color']).GetColour()
  1097. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1098. if self.FindWindowById(self.win['vector']['lines']['flat']).GetSelection() == 0:
  1099. flat = False
  1100. else:
  1101. flat = True
  1102. self.mapWindow.nvizClass.SetVectorLineMode(id, str(color), width, flat)
  1103. def ApplySettings(self):
  1104. """Apply changes in settings"""
  1105. # bgcolor
  1106. color = self.FindWindowById(self.win['settings']['general']['bgcolor']).GetColour()
  1107. color = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1108. self.mapWindow.nvizClass.SetBgColor(str(color))
  1109. def OnClose(self, event):
  1110. """Close button pressed
  1111. Close dialog
  1112. """
  1113. self.Hide()
  1114. def OnSurfaceUse(self, event):
  1115. """Surface attribute -- use -- map/constant"""
  1116. if not self.mapWindow.init:
  1117. return
  1118. # find attribute row
  1119. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1120. if not attrb:
  1121. return
  1122. selection = event.GetSelection()
  1123. if self.win['surface'][attrb]['required']: # no 'unset'
  1124. selection += 1
  1125. if selection == 0: # unset
  1126. useMap = None
  1127. value = ''
  1128. elif selection == 1: # map
  1129. useMap = True
  1130. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1131. elif selection == 2: # constant
  1132. useMap = False
  1133. if attrb == 'color':
  1134. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1135. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1136. else:
  1137. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1138. self.SetSurfaceUseMap(attrb, useMap)
  1139. self.mapWindow.update[attrb] = (useMap, str(value))
  1140. if self.parent.autoRender.IsChecked():
  1141. self.OnApply(None)
  1142. def SetSurfaceUseMap(self, attrb, map=None):
  1143. if attrb in ('topo', 'color', 'shine'):
  1144. incSel = -1 # decrement selection (no 'unset')
  1145. else:
  1146. incSel = 0
  1147. if map is True: # map
  1148. if attrb != 'topo': # changing map topography not allowed
  1149. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(True) # FIXME
  1150. if self.win['surface'][attrb]['const']:
  1151. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1152. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(1 + incSel)
  1153. elif map is False: # const
  1154. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1155. if self.win['surface'][attrb]['const']:
  1156. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(True)
  1157. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(2 + incSel)
  1158. else: # unset
  1159. self.FindWindowById(self.win['surface'][attrb]['map'] + 1).Enable(False)
  1160. if self.win['surface'][attrb]['const']:
  1161. self.FindWindowById(self.win['surface'][attrb]['const']).Enable(False)
  1162. self.FindWindowById(self.win['surface'][attrb]['use']).SetSelection(0)
  1163. def OnSurfaceMap(self, event):
  1164. """Set surface attribute"""
  1165. if not self.mapWindow.init:
  1166. return
  1167. attrb = self.__GetWindowName(self.win['surface'], event.GetId())
  1168. if not attrb:
  1169. return
  1170. selection = self.FindWindowById(self.win['surface'][attrb]['use']).GetSelection()
  1171. if self.win['surface'][attrb]['required']:
  1172. selection += 1
  1173. if selection == 0: # unset
  1174. map = None
  1175. value = ''
  1176. elif selection == 1: # map
  1177. value = self.FindWindowById(self.win['surface'][attrb]['map']).GetValue()
  1178. map = True
  1179. else: # constant
  1180. if attrb == 'color':
  1181. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetColour()
  1182. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  1183. else:
  1184. value = self.FindWindowById(self.win['surface'][attrb]['const']).GetValue()
  1185. map = False
  1186. self.mapWindow.update[attrb] = (map, str(value))
  1187. if self.parent.autoRender.IsChecked():
  1188. self.OnApply(None)
  1189. def OnSurfaceResolution(self, event):
  1190. """Draw resolution changed"""
  1191. self.SetSurfaceResolution()
  1192. def SetSurfaceResolution(self, all=False, apply=True):
  1193. """Set draw resolution"""
  1194. coarse = self.FindWindowById(self.win['surface']['draw']['res-coarse']).GetValue()
  1195. fine = self.FindWindowById(self.win['surface']['draw']['res-fine']).GetValue()
  1196. self.mapWindow.update['draw-res'] = (coarse, fine, all)
  1197. if apply and self.parent.autoRender.IsChecked():
  1198. self.OnApply(None)
  1199. def SetSurfaceMode(self, apply=True, all=False):
  1200. """Set draw mode
  1201. @param apply allow auto-rendering
  1202. """
  1203. value = 0
  1204. mode = self.FindWindowById(self.win['surface']['draw']['mode']).GetSelection()
  1205. if mode == 0: # coarse
  1206. value |= wxnviz.DM_WIRE
  1207. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1208. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(False)
  1209. elif mode == 1: # fine
  1210. value |= wxnviz.DM_POLY
  1211. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(False)
  1212. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1213. else: # both
  1214. value |= wxnviz.DM_WIRE_POLY
  1215. self.FindWindowById(self.win['surface']['draw']['res-coarse']).Enable(True)
  1216. self.FindWindowById(self.win['surface']['draw']['res-fine']).Enable(True)
  1217. style = self.FindWindowById(self.win['surface']['draw']['style']).GetSelection()
  1218. if style == 0: # wire
  1219. value |= wxnviz.DM_GRID_WIRE
  1220. else: # surface
  1221. value |= wxnviz.DM_GRID_SURF
  1222. shade = self.FindWindowById(self.win['surface']['draw']['shading']).GetSelection()
  1223. if shade == 0:
  1224. value |= wxnviz.DM_FLAT
  1225. else: # surface
  1226. value |= wxnviz.DM_GOURAUD
  1227. self.mapWindow.update['draw-style'] = (value, all)
  1228. if apply and self.parent.autoRender.IsChecked():
  1229. self.OnApply(None)
  1230. def OnSurfaceMode(self, event):
  1231. """Set draw mode"""
  1232. self.SetSurfaceMode()
  1233. def OnSurfaceModeAll(self, event):
  1234. """Set draw mode (including wire color) for all loaded surfaces"""
  1235. self.SetSurfaceMode(apply=False, all=True)
  1236. self.SetSurfaceResolution(apply=False, all=True)
  1237. color = self.FindWindowById(self.win['surface']['draw']['color']).GetColour()
  1238. self.SetSurfaceWireColor(color, all=True)
  1239. def SetSurfaceWireColor(self, color, all=False):
  1240. """Set wire color"""
  1241. value = str(color[0]) + ':' + str(color[1]) + ':' + str(color[2])
  1242. self.mapWindow.update['draw-color'] = (value, all)
  1243. if self.parent.autoRender.IsChecked():
  1244. self.OnApply(None)
  1245. def OnSurfaceWireColor(self, event):
  1246. """Set wire color"""
  1247. self.SetSurfaceWireColor(event.GetValue())
  1248. def OnVectorDisplay(self, event):
  1249. """Display vector lines on surface/flat"""
  1250. if event.GetSelection() == 0: # surface
  1251. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(True)
  1252. # set first found surface
  1253. ### TODO
  1254. else: # flat
  1255. self.FindWindowById(self.win['vector']['lines']['surface']).Enable(False)
  1256. self.OnVectorLines(event)
  1257. event.Skip()
  1258. def OnVectorLines(self, event):
  1259. """Set vector lines mode, apply changes if auto-rendering is enabled"""
  1260. if self.parent.autoRender.IsChecked():
  1261. self.OnApply(None)
  1262. def OnVectorHeight(self, event):
  1263. value = event.GetInt()
  1264. if type(event) == type(wx.ScrollEvent()):
  1265. # slider
  1266. win = self.FindWindowById(self.win['vector']['lines']['height']['spin'])
  1267. else:
  1268. # spin
  1269. win = self.FindWindowById(self.win['vector']['lines']['height']['slider'])
  1270. win.SetValue(value)
  1271. def OnVectorHeightSpin(self, event):
  1272. print event
  1273. def OnSettings(self, event):
  1274. """Update settings, apply changes if auto-rendering is enabled"""
  1275. if self.parent.autoRender.IsChecked():
  1276. self.OnApply(None)
  1277. def UpdatePage(self, pageId):
  1278. """Update dialog (selected page)"""
  1279. layer = self.mapWindow.GetSelectedLayer()
  1280. data = self.mapWindow.GetSelectedLayer(nviz=True)
  1281. if pageId == 'view':
  1282. max = self.settings['z-exag']['value'] * 10
  1283. for control in ('spin', 'slider'):
  1284. self.FindWindowById(self.win['view']['z-exag'][control]).SetRange(0,
  1285. max)
  1286. elif pageId == 'surface':
  1287. # disable vector and enable current
  1288. self.notebook.GetPage(self.page['surface']).Enable(True)
  1289. self.notebook.GetPage(self.page['vector']).Enable(False)
  1290. if data is None: # use default values
  1291. #
  1292. # attributes
  1293. #
  1294. for attr in ('topo', 'color'):
  1295. self.SetSurfaceUseMap(attr, True) # -> map
  1296. if layer and layer.type == 'raster':
  1297. self.FindWindowById(self.win['surface'][attr]['map']).SetValue(layer.name)
  1298. else:
  1299. self.FindWindowById(self.win['surface'][attr]['map']).SetValue('')
  1300. if UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'map']) is False:
  1301. self.SetSurfaceUseMap('shine', False)
  1302. value = UserSettings.Get(group='nviz', key='surface', subkey=['shine', 'value'])
  1303. self.FindWindowById(self.win['surface']['shine']['const']).SetValue(value)
  1304. #
  1305. # draw
  1306. #
  1307. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  1308. win = self.FindWindowById(self.win['surface']['draw'][control])
  1309. name = win.GetName()
  1310. if name == "selection":
  1311. win.SetSelection(value)
  1312. elif name == "colour":
  1313. win.SetColour(value)
  1314. else:
  1315. win.SetValue(value)
  1316. # enable/disable res widget + set draw mode
  1317. self.SetSurfaceMode()
  1318. color = self.FindWindowById(self.win['surface']['draw']['color'])
  1319. self.SetSurfaceWireColor(color.GetColour())
  1320. elif layer.type == 'raster':
  1321. # surface attributes
  1322. for attr in data['attr']:
  1323. if attr['map']:
  1324. win = self.FindWindowById(self.win['surface'][attr]['map'])
  1325. else:
  1326. win = self.FindWindowById(self.win['surface'][attr]['const'])
  1327. win.SetValue(data['value'])
  1328. elif pageId == 'vector':
  1329. # disable surface and enable current
  1330. self.notebook.GetPage(self.page['surface']).Enable(False)
  1331. self.notebook.GetPage(self.page['vector']).Enable(True)
  1332. if data is None: # defaut values
  1333. # lines
  1334. for name in ('width', 'color'):
  1335. win = self.FindWindowById(self.win['vector']['lines'][name])
  1336. win.SetValue(UserSettings.Get(group='nviz', key='vector',
  1337. subkey=['lines', name]))
  1338. display = self.FindWindowById(self.win['vector']['lines']['flat'])
  1339. if UserSettings.Get(group='nviz', key='vector',
  1340. subkey=['lines', 'flat']):
  1341. display.SetSelection(1)
  1342. else:
  1343. display.SetSelection(0)
  1344. value = UserSettings.Get(group='nviz', key='vector',
  1345. subkey=['lines', 'height'])
  1346. for type in ('slider', 'spin'):
  1347. win = self.FindWindowById(self.win['vector']['lines']['height'][type])
  1348. win.SetValue(value)
  1349. def SetPage(self, name):
  1350. """Get named page"""
  1351. self.notebook.SetSelection(self.page[name])
  1352. class ViewPositionWindow(wx.Window):
  1353. """Position control window (for NvizToolWindow)"""
  1354. def __init__(self, parent, id, mapwindow,
  1355. pos=wx.DefaultPosition,
  1356. size=wx.DefaultSize, settings={}):
  1357. self.settings = settings
  1358. self.mapWindow = mapwindow
  1359. wx.Window.__init__(self, parent, id, pos, size)
  1360. self.SetBackgroundColour("WHITE")
  1361. self.pdc = wx.PseudoDC()
  1362. self.pdc.SetBrush(wx.Brush(colour='dark green', style=wx.SOLID))
  1363. self.pdc.SetPen(wx.Pen(colour='dark green', width=2, style=wx.SOLID))
  1364. self.Draw()
  1365. self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
  1366. self.Bind(wx.EVT_PAINT, self.OnPaint)
  1367. # self.Bind(wx.EVT_MOTION, self.OnMouse)
  1368. self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
  1369. def Draw(self, pos=None):
  1370. w, h = self.GetClientSize()
  1371. if pos is None:
  1372. x = self.settings['pos']['x']
  1373. y = self.settings['pos']['y']
  1374. x = x * w
  1375. y = y * h
  1376. else:
  1377. x, y = pos
  1378. self.pdc.Clear()
  1379. self.pdc.BeginDrawing()
  1380. self.pdc.DrawLine(w / 2, h / 2, x, y)
  1381. self.pdc.DrawCircle(x, y, 5)
  1382. self.pdc.EndDrawing()
  1383. def OnPaint(self, event):
  1384. dc = wx.BufferedPaintDC(self)
  1385. dc.SetBackground(wx.Brush("White"))
  1386. dc.Clear()
  1387. self.PrepareDC(dc)
  1388. self.pdc.DrawToDC(dc)
  1389. def OnMouse(self, event):
  1390. if event.LeftIsDown():
  1391. x, y = event.GetPosition()
  1392. self.Draw(pos=(x, y))
  1393. self.Refresh(False)
  1394. w, h = self.GetClientSize()
  1395. x = float(x) / w
  1396. y = float(y) / h
  1397. self.settings['pos']['x'] = x
  1398. self.settings['pos']['y'] = y
  1399. self.mapWindow.update['view'] = None
  1400. self.mapWindow.render = False
  1401. if event.LeftUp():
  1402. self.mapWindow.render = True
  1403. self.mapWindow.Refresh(eraseBackground=False)