dialogs.py 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  1. """
  2. @package wxplot.dialogs
  3. @brief Dialogs for different plotting routines
  4. Classes:
  5. - dialogs::ProfileRasterDialog
  6. - dialogs::ScatterRasterDialog
  7. - dialogs::PlotStatsFrame
  8. - dialogs::HistRasterDialog
  9. - dialogs::TextDialog
  10. - dialogs::OptDialog
  11. (C) 2011-2016 by the GRASS Development Team
  12. This program is free software under the GNU General Public License
  13. (>=v2). Read the file COPYING that comes with GRASS for details.
  14. @author Michael Barton, Arizona State University
  15. """
  16. import os
  17. import wx
  18. import wx.lib.colourselect as csel
  19. import wx.lib.scrolledpanel as scrolled
  20. from core import globalvar
  21. from core.settings import UserSettings
  22. from core.globalvar import ICONDIR
  23. from gui_core.gselect import Select
  24. from gui_core.wrap import SpinCtrl, Button, StaticText, \
  25. StaticBox, TextCtrl, Choice
  26. from grass.script import core as grass
  27. class ProfileRasterDialog(wx.Dialog):
  28. def __init__(self, parent, id=wx.ID_ANY,
  29. title=_("Select raster maps to profile"),
  30. style=wx.DEFAULT_DIALOG_STYLE, **kwargs):
  31. """Dialog to select raster maps to profile.
  32. """
  33. wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)
  34. self.parent = parent
  35. self.colorList = [
  36. "blue",
  37. "red",
  38. "green",
  39. "yellow",
  40. "magenta",
  41. "cyan",
  42. "aqua",
  43. "black",
  44. "grey",
  45. "orange",
  46. "brown",
  47. "purple",
  48. "violet",
  49. "indigo"]
  50. self.rasterList = self.parent.rasterList
  51. self._do_layout()
  52. def _do_layout(self):
  53. sizer = wx.BoxSizer(wx.VERTICAL)
  54. box = wx.GridBagSizer(hgap=3, vgap=3)
  55. rastText = ''
  56. for r in self.rasterList:
  57. rastText += '%s,' % r
  58. rastText = rastText.rstrip(',')
  59. txt = _("Select raster map(s) to profile:")
  60. label = StaticText(parent=self, id=wx.ID_ANY, label=txt)
  61. box.Add(label,
  62. flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  63. selection = Select(self, id=wx.ID_ANY,
  64. size=globalvar.DIALOG_GSELECT_SIZE,
  65. type='cell', multiple=True)
  66. selection.SetValue(rastText)
  67. selection.Bind(wx.EVT_TEXT, self.OnSelection)
  68. box.Add(selection, pos=(0, 1))
  69. sizer.Add(box, proportion=0,
  70. flag=wx.ALL, border=10)
  71. line = wx.StaticLine(
  72. parent=self, id=wx.ID_ANY, size=(
  73. 20, -1), style=wx.LI_HORIZONTAL)
  74. sizer.Add(line, proportion=0, flag=wx.GROW |
  75. wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border=5)
  76. btnsizer = wx.StdDialogButtonSizer()
  77. btn = Button(self, wx.ID_OK)
  78. btn.SetDefault()
  79. btnsizer.AddButton(btn)
  80. btn = Button(self, wx.ID_CANCEL)
  81. btnsizer.AddButton(btn)
  82. btnsizer.Realize()
  83. sizer.Add(
  84. btnsizer,
  85. proportion=0,
  86. flag=wx.ALIGN_RIGHT | wx.ALL,
  87. border=5)
  88. self.SetSizer(sizer)
  89. sizer.Fit(self)
  90. def OnSelection(self, event):
  91. """Choose maps to profile. Convert these into a list
  92. """
  93. self.rasterList = self.FindWindowById(
  94. event.GetId()).GetValue().split(',')
  95. class ScatterRasterDialog(wx.Dialog):
  96. def __init__(self, parent, id=wx.ID_ANY,
  97. title=_("Select pairs of raster maps for scatterplots"),
  98. style=wx.DEFAULT_DIALOG_STYLE, **kwargs):
  99. """Dialog to select raster maps to profile.
  100. """
  101. wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)
  102. self.parent = parent
  103. self.rasterList = self.parent.rasterList
  104. self.bins = self.parent.bins
  105. self.scattertype = self.parent.scattertype
  106. self.maptype = self.parent.maptype
  107. self.spinbins = ''
  108. self.colorList = [
  109. "blue",
  110. "red",
  111. "green",
  112. "yellow",
  113. "magenta",
  114. "cyan",
  115. "aqua",
  116. "black",
  117. "grey",
  118. "orange",
  119. "brown",
  120. "purple",
  121. "violet",
  122. "indigo"]
  123. self._do_layout()
  124. def _do_layout(self):
  125. sizer = wx.BoxSizer(wx.VERTICAL)
  126. box = wx.GridBagSizer(hgap=3, vgap=3)
  127. # parse raster pair tuples
  128. rastText = ''
  129. if len(self.rasterList) > 0:
  130. for r in self.rasterList:
  131. if isinstance(r, tuple):
  132. rastText += '%s,%s,' % r
  133. else:
  134. rastText += '%s,' % r
  135. rastText = rastText.rstrip(',')
  136. # select rasters
  137. txt = _("Select pairs of raster maps for bivariate scatterplots:")
  138. label = StaticText(parent=self, id=wx.ID_ANY, label=txt)
  139. box.Add(label,
  140. flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  141. selection = Select(self, id=wx.ID_ANY,
  142. size=globalvar.DIALOG_GSELECT_SIZE,
  143. type='cell', multiple=True)
  144. selection.SetValue(rastText)
  145. selection.Bind(wx.EVT_TEXT, self.OnSelection)
  146. box.Add(selection, pos=(0, 1))
  147. # Nsteps for FP maps
  148. label = StaticText(parent=self, id=wx.ID_ANY,
  149. label=_("Number of bins (for FP maps)"))
  150. box.Add(label,
  151. flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  152. self.spinbins = SpinCtrl(
  153. parent=self, id=wx.ID_ANY, value="", pos=(
  154. 30, 50), size=(
  155. 100, -1), style=wx.SP_ARROW_KEYS)
  156. self.spinbins.SetRange(1, 1000)
  157. self.spinbins.SetValue(self.bins)
  158. box.Add(self.spinbins,
  159. flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 1))
  160. # TODO possibly make bubble plots with marker size proportional to cell counts
  161. # # scatterplot type
  162. # label = wx.StaticText(parent = self, id = wx.ID_ANY,
  163. # label = _("Scatterplot type"))
  164. # box.Add(item = label,
  165. # flag = wx.ALIGN_CENTER_VERTICAL, pos = (2, 0))
  166. # types = ['normal', 'bubble']
  167. # scattertype = wx.ComboBox(parent = self, id = wx.ID_ANY, size = (250, -1),
  168. # choices = types, style = wx.CB_DROPDOWN)
  169. # scattertype.SetStringSelection(self.scattertype)
  170. # box.Add(item = scattertype,
  171. # flag = wx.ALIGN_CENTER_VERTICAL, pos = (2, 1))
  172. sizer.Add(box, proportion=0,
  173. flag=wx.ALL, border=10)
  174. line = wx.StaticLine(
  175. parent=self, id=wx.ID_ANY, size=(
  176. 20, -1), style=wx.LI_HORIZONTAL)
  177. sizer.Add(line, proportion=0, flag=wx.GROW |
  178. wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border=5)
  179. btnsizer = wx.StdDialogButtonSizer()
  180. btn = Button(self, wx.ID_OK)
  181. btn.SetDefault()
  182. btnsizer.AddButton(btn)
  183. btn = Button(self, wx.ID_CANCEL)
  184. btnsizer.AddButton(btn)
  185. btnsizer.Realize()
  186. sizer.Add(
  187. btnsizer,
  188. proportion=0,
  189. flag=wx.ALIGN_RIGHT | wx.ALL,
  190. border=5)
  191. self.spinbins.Bind(wx.EVT_TEXT, self.OnSetBins)
  192. self.spinbins.Bind(wx.EVT_SPINCTRL, self.OnSetBins)
  193. # scattertype.Bind(wx.EVT_TEXT, self.OnSetScattertypes)
  194. self.SetSizer(sizer)
  195. sizer.Fit(self)
  196. def OnSelection(self, event):
  197. """Select raster maps for scatterplot. Must select maps in pairs.
  198. """
  199. self.rasterList = self.FindWindowById(
  200. event.GetId()).GetValue().split(',', 1)
  201. def OnSetBins(self, event):
  202. """Bins for histogramming FP maps (=nsteps in r.stats)
  203. """
  204. self.bins = self.spinbins.GetValue()
  205. def OnSetScattertypes(self, event):
  206. self.scattertype = event.GetString()
  207. def GetRasterPairs(self):
  208. """Get raster pairs"""
  209. pairsList = list()
  210. pair = list()
  211. for r in self.rasterList:
  212. pair.append(r)
  213. if len(pair) == 2:
  214. pairsList.append(tuple(pair))
  215. pair = list()
  216. return list(pairsList)
  217. def GetSettings(self):
  218. """Get type and bins"""
  219. return self.scattertype, self.bins
  220. class PlotStatsFrame(wx.Frame):
  221. def __init__(self, parent, id, message='', title='',
  222. style=wx.DEFAULT_FRAME_STYLE, **kwargs):
  223. """Dialog to display and save statistics for plots
  224. """
  225. wx.Frame.__init__(self, parent, id, style=style, **kwargs)
  226. self.SetLabel(_("Statistics"))
  227. self.SetIcon(
  228. wx.Icon(
  229. os.path.join(
  230. ICONDIR,
  231. 'grass.ico'),
  232. wx.BITMAP_TYPE_ICO))
  233. self.panel = wx.Panel(self)
  234. sp = scrolled.ScrolledPanel(
  235. self.panel, -1, size=(400, 400),
  236. style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, name="Statistics")
  237. #
  238. # initialize variables
  239. #
  240. self.parent = parent
  241. self.message = message
  242. self.title = title
  243. self.CenterOnParent()
  244. #
  245. # Display statistics
  246. #
  247. sizer = wx.BoxSizer(wx.VERTICAL)
  248. txtSizer = wx.BoxSizer(wx.VERTICAL)
  249. statstitle = StaticText(
  250. parent=self.panel,
  251. id=wx.ID_ANY,
  252. label=self.title)
  253. sizer.Add(statstitle, proportion=0,
  254. flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=3)
  255. line = wx.StaticLine(
  256. parent=self.panel, id=wx.ID_ANY, size=(
  257. 20, -1), style=wx.LI_HORIZONTAL)
  258. sizer.Add(line, proportion=0,
  259. flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=3)
  260. for stats in self.message:
  261. statstxt = StaticText(parent=sp, id=wx.ID_ANY, label=stats)
  262. statstxt.SetBackgroundColour("WHITE")
  263. txtSizer.Add(
  264. statstxt,
  265. proportion=1,
  266. flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
  267. border=3)
  268. line = wx.StaticLine(
  269. parent=sp, id=wx.ID_ANY, size=(
  270. 20, -1), style=wx.LI_HORIZONTAL)
  271. txtSizer.Add(line, proportion=0, flag=wx.GROW |
  272. wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=3)
  273. sp.SetSizer(txtSizer)
  274. sp.SetAutoLayout(1)
  275. sp.SetupScrolling()
  276. sizer.Add(sp, proportion=1,
  277. flag=wx.GROW | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=3)
  278. line = wx.StaticLine(
  279. parent=self.panel, id=wx.ID_ANY, size=(
  280. 20, -1), style=wx.LI_HORIZONTAL)
  281. sizer.Add(line, proportion=0, flag=wx.GROW |
  282. wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border=3)
  283. #
  284. # buttons
  285. #
  286. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  287. btn_clipboard = Button(self.panel, id=wx.ID_COPY, label=_('C&opy'))
  288. btn_clipboard.SetToolTip(
  289. _("Copy regression statistics the clipboard (Ctrl+C)"))
  290. btnSizer.Add(
  291. btn_clipboard,
  292. proportion=0,
  293. flag=wx.ALIGN_LEFT | wx.ALL,
  294. border=5)
  295. btnCancel = Button(self.panel, wx.ID_CLOSE)
  296. btnCancel.SetDefault()
  297. btnSizer.Add(
  298. btnCancel,
  299. proportion=0,
  300. flag=wx.ALIGN_RIGHT | wx.ALL,
  301. border=5)
  302. sizer.Add(
  303. btnSizer,
  304. proportion=0,
  305. flag=wx.ALIGN_RIGHT | wx.ALL,
  306. border=5)
  307. # bindings
  308. btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)
  309. btn_clipboard.Bind(wx.EVT_BUTTON, self.OnCopy)
  310. self.panel.SetSizer(sizer)
  311. sizer.Fit(self)
  312. def OnCopy(self, event):
  313. """Copy the regression stats to the clipboard
  314. """
  315. str = self.title + '\n'
  316. for item in self.message:
  317. str += item
  318. rdata = wx.TextDataObject()
  319. rdata.SetText(str)
  320. if wx.TheClipboard.Open():
  321. wx.TheClipboard.SetData(rdata)
  322. wx.TheClipboard.Close()
  323. wx.MessageBox(_("Regression statistics copied to clipboard"))
  324. def OnClose(self, event):
  325. """Button 'Close' pressed
  326. """
  327. self.Close(True)
  328. class HistRasterDialog(wx.Dialog):
  329. def __init__(self, parent, id=wx.ID_ANY,
  330. title=_("Select raster map or imagery group to histogram"),
  331. style=wx.DEFAULT_DIALOG_STYLE, **kwargs):
  332. """Dialog to select raster maps to histogram.
  333. """
  334. wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)
  335. self.parent = parent
  336. self.rasterList = self.parent.rasterList
  337. self.group = self.parent.group
  338. self.bins = self.parent.bins
  339. self.histtype = self.parent.histtype
  340. self.maptype = self.parent.maptype
  341. self.spinbins = ''
  342. self._do_layout()
  343. def _do_layout(self):
  344. sizer = wx.BoxSizer(wx.VERTICAL)
  345. box = wx.GridBagSizer(hgap=3, vgap=3)
  346. #
  347. # select single raster or image group to histogram radio buttons
  348. #
  349. self.rasterRadio = wx.RadioButton(
  350. self, id=wx.ID_ANY, label=" %s " %
  351. _("Histogram single raster"), style=wx.RB_GROUP)
  352. self.groupRadio = wx.RadioButton(
  353. self, id=wx.ID_ANY, label=" %s " %
  354. _("Histogram imagery group"))
  355. if self.maptype == 'raster':
  356. self.rasterRadio.SetValue(True)
  357. elif self.maptype == 'group':
  358. self.groupRadio.SetValue(True)
  359. box.Add(
  360. self.rasterRadio,
  361. flag=wx.ALIGN_CENTER_VERTICAL,
  362. pos=(
  363. 0,
  364. 0))
  365. box.Add(
  366. self.groupRadio,
  367. flag=wx.ALIGN_CENTER_VERTICAL,
  368. pos=(
  369. 0,
  370. 1))
  371. #
  372. # Select a raster to histogram
  373. #
  374. label = StaticText(parent=self, id=wx.ID_ANY,
  375. label=_("Select raster map:"))
  376. box.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  377. self.rselection = Select(self, id=wx.ID_ANY,
  378. size=globalvar.DIALOG_GSELECT_SIZE,
  379. type='cell')
  380. if self.groupRadio.GetValue() == True:
  381. self.rselection.Disable()
  382. else:
  383. rastText = ''
  384. for r in self.rasterList:
  385. rastText += '%s,' % r
  386. rastText = rastText.rstrip(',')
  387. self.rselection.SetValue(rastText)
  388. box.Add(self.rselection, pos=(1, 1))
  389. #
  390. # Select an image group to histogram
  391. #
  392. label = StaticText(parent=self, id=wx.ID_ANY,
  393. label=_("Select image group:"))
  394. box.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  395. self.gselection = Select(self, id=wx.ID_ANY,
  396. size=globalvar.DIALOG_GSELECT_SIZE,
  397. type='group')
  398. if self.rasterRadio.GetValue() == True:
  399. self.gselection.Disable()
  400. else:
  401. if self.group is not None:
  402. self.gselection.SetValue(self.group)
  403. box.Add(self.gselection, pos=(2, 1))
  404. #
  405. # Nsteps for FP maps and histogram type selection
  406. #
  407. label = StaticText(parent=self, id=wx.ID_ANY,
  408. label=_("Number of bins (for FP maps)"))
  409. box.Add(label,
  410. flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  411. self.spinbins = SpinCtrl(
  412. parent=self, id=wx.ID_ANY, value="", pos=(
  413. 30, 50), size=(
  414. 100, -1), style=wx.SP_ARROW_KEYS)
  415. self.spinbins.SetRange(1, 1000)
  416. self.spinbins.SetValue(self.bins)
  417. box.Add(self.spinbins,
  418. flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 1))
  419. label = StaticText(parent=self, id=wx.ID_ANY,
  420. label=_("Histogram type"))
  421. box.Add(label,
  422. flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  423. types = ['count', 'percent', 'area']
  424. histtype = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  425. choices=types, style=wx.CB_DROPDOWN)
  426. histtype.SetStringSelection(self.histtype)
  427. box.Add(histtype,
  428. flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 1))
  429. sizer.Add(box, proportion=0,
  430. flag=wx.ALL, border=10)
  431. line = wx.StaticLine(
  432. parent=self, id=wx.ID_ANY, size=(
  433. 20, -1), style=wx.LI_HORIZONTAL)
  434. sizer.Add(line, proportion=0, flag=wx.GROW |
  435. wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border=5)
  436. btnsizer = wx.StdDialogButtonSizer()
  437. btn = Button(self, wx.ID_OK)
  438. btn.SetDefault()
  439. btnsizer.AddButton(btn)
  440. btn = Button(self, wx.ID_CANCEL)
  441. btnsizer.AddButton(btn)
  442. btnsizer.Realize()
  443. sizer.Add(
  444. btnsizer,
  445. proportion=0,
  446. flag=wx.ALIGN_RIGHT | wx.ALL,
  447. border=5)
  448. #
  449. # bindings
  450. #
  451. self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.rasterRadio)
  452. self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.groupRadio)
  453. self.rselection.Bind(wx.EVT_TEXT, self.OnRasterSelection)
  454. self.gselection.Bind(wx.EVT_TEXT, self.OnGroupSelection)
  455. self.spinbins.Bind(wx.EVT_TEXT, self.OnSetBins)
  456. self.spinbins.Bind(wx.EVT_SPINCTRL, self.OnSetBins)
  457. histtype.Bind(wx.EVT_TEXT, self.OnSetHisttypes)
  458. self.SetSizer(sizer)
  459. sizer.Fit(self)
  460. def OnHistMap(self, event):
  461. """Hander for radio buttons to choose between histogramming a
  462. single raster and an imagery group
  463. """
  464. if self.rasterRadio.GetValue() is True:
  465. self.maptype = 'raster'
  466. self.rselection.Enable()
  467. self.gselection.Disable()
  468. self.gselection.SetValue('')
  469. elif self.groupRadio.GetValue() is True:
  470. self.maptype = 'group'
  471. self.gselection.Enable()
  472. self.rselection.Disable()
  473. self.rselection.SetValue('')
  474. else:
  475. pass
  476. def OnRasterSelection(self, event):
  477. """Handler for selecting a single raster map
  478. """
  479. self.rasterList = []
  480. self.rasterList.append(event.GetString())
  481. def OnGroupSelection(self, event):
  482. """Handler for selecting imagery group
  483. """
  484. self.rasterList = []
  485. self.group = event.GetString()
  486. ret = grass.read_command('i.group',
  487. group='%s' % self.group,
  488. quiet=True,
  489. flags='g').strip().splitlines()
  490. if ret not in [None, '', ['']]:
  491. self.rasterList = ret
  492. else:
  493. wx.MessageBox(
  494. message=_("Selected group must be in current mapset"),
  495. caption=_('Invalid input'),
  496. style=wx.OK | wx.ICON_ERROR)
  497. def OnSetBins(self, event):
  498. """Bins for histogramming FP maps (=nsteps in r.stats)
  499. """
  500. self.bins = self.spinbins.GetValue()
  501. def OnSetHisttypes(self, event):
  502. self.histtype = event.GetString()
  503. class TextDialog(wx.Dialog):
  504. def __init__(self, parent, giface, id, title, plottype='',
  505. style=wx.DEFAULT_DIALOG_STYLE, **kwargs):
  506. """Dialog to set histogram text options: font, title
  507. and font size, axis labels and font size
  508. """
  509. wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)
  510. #
  511. # initialize variables
  512. #
  513. self._giface = giface
  514. # combo box entry lists
  515. self.ffamilydict = {'default': wx.FONTFAMILY_DEFAULT,
  516. 'decorative': wx.FONTFAMILY_DECORATIVE,
  517. 'roman': wx.FONTFAMILY_ROMAN,
  518. 'script': wx.FONTFAMILY_SCRIPT,
  519. 'swiss': wx.FONTFAMILY_SWISS,
  520. 'modern': wx.FONTFAMILY_MODERN,
  521. 'teletype': wx.FONTFAMILY_TELETYPE}
  522. self.fstyledict = {'normal': wx.FONTSTYLE_NORMAL,
  523. 'slant': wx.FONTSTYLE_SLANT,
  524. 'italic': wx.FONTSTYLE_ITALIC}
  525. self.fwtdict = {'normal': wx.FONTWEIGHT_NORMAL,
  526. 'light': wx.FONTWEIGHT_LIGHT,
  527. 'bold': wx.FONTWEIGHT_BOLD}
  528. self.parent = parent
  529. self.plottype = plottype
  530. self.ptitle = self.parent.ptitle
  531. self.xlabel = self.parent.xlabel
  532. self.ylabel = self.parent.ylabel
  533. self.properties = self.parent.properties # read-only
  534. # font size
  535. self.fontfamily = self.properties['font']['wxfont'].GetFamily()
  536. self.fontstyle = self.properties['font']['wxfont'].GetStyle()
  537. self.fontweight = self.properties['font']['wxfont'].GetWeight()
  538. self._do_layout()
  539. def _do_layout(self):
  540. """Do layout"""
  541. # dialog layout
  542. sizer = wx.BoxSizer(wx.VERTICAL)
  543. box = StaticBox(parent=self, id=wx.ID_ANY,
  544. label=" %s " % _("Text settings"))
  545. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  546. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  547. #
  548. # profile title
  549. #
  550. label = StaticText(
  551. parent=self,
  552. id=wx.ID_ANY,
  553. label=_("Profile title:"))
  554. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  555. self.ptitleentry = TextCtrl(
  556. parent=self, id=wx.ID_ANY, value="", size=(250, -1))
  557. # self.ptitleentry.SetFont(self.font)
  558. self.ptitleentry.SetValue(self.ptitle)
  559. gridSizer.Add(self.ptitleentry, pos=(0, 1))
  560. #
  561. # title font
  562. #
  563. tlabel = StaticText(
  564. parent=self,
  565. id=wx.ID_ANY,
  566. label=_("Title font size (pts):"))
  567. gridSizer.Add(tlabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  568. self.ptitlesize = SpinCtrl(
  569. parent=self, id=wx.ID_ANY, value="", pos=(
  570. 30, 50), size=(
  571. 50, -1), style=wx.SP_ARROW_KEYS)
  572. self.ptitlesize.SetRange(5, 100)
  573. self.ptitlesize.SetValue(
  574. int(self.properties['font']['prop']['titleSize']))
  575. gridSizer.Add(self.ptitlesize, pos=(1, 1))
  576. #
  577. # x-axis label
  578. #
  579. label = StaticText(
  580. parent=self,
  581. id=wx.ID_ANY,
  582. label=_("X-axis label:"))
  583. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  584. self.xlabelentry = TextCtrl(
  585. parent=self, id=wx.ID_ANY, value="", size=(250, -1))
  586. # self.xlabelentry.SetFont(self.font)
  587. self.xlabelentry.SetValue(self.xlabel)
  588. gridSizer.Add(self.xlabelentry, pos=(2, 1))
  589. #
  590. # y-axis label
  591. #
  592. label = StaticText(
  593. parent=self,
  594. id=wx.ID_ANY,
  595. label=_("Y-axis label:"))
  596. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  597. self.ylabelentry = TextCtrl(
  598. parent=self, id=wx.ID_ANY, value="", size=(250, -1))
  599. # self.ylabelentry.SetFont(self.font)
  600. self.ylabelentry.SetValue(self.ylabel)
  601. gridSizer.Add(self.ylabelentry, pos=(3, 1))
  602. #
  603. # font size
  604. #
  605. llabel = StaticText(
  606. parent=self,
  607. id=wx.ID_ANY,
  608. label=_("Label font size (pts):"))
  609. gridSizer.Add(llabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  610. self.axislabelsize = SpinCtrl(
  611. parent=self, id=wx.ID_ANY, value="", pos=(
  612. 30, 50), size=(
  613. 50, -1), style=wx.SP_ARROW_KEYS)
  614. self.axislabelsize.SetRange(5, 100)
  615. self.axislabelsize.SetValue(
  616. int(self.properties['font']['prop']['axisSize']))
  617. gridSizer.Add(self.axislabelsize, pos=(4, 1))
  618. boxSizer.Add(gridSizer)
  619. sizer.Add(boxSizer, flag=wx.ALL | wx.EXPAND, border=3)
  620. #
  621. # font settings
  622. #
  623. box = StaticBox(parent=self, id=wx.ID_ANY,
  624. label=" %s " % _("Font settings"))
  625. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  626. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  627. #
  628. # font family
  629. #
  630. label1 = StaticText(
  631. parent=self,
  632. id=wx.ID_ANY,
  633. label=_("Font family:"))
  634. gridSizer.Add(label1, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  635. self.ffamilycb = wx.ComboBox(
  636. parent=self, id=wx.ID_ANY, size=(250, -1),
  637. choices=list(self.ffamilydict.keys()),
  638. style=wx.CB_DROPDOWN)
  639. self.ffamilycb.SetStringSelection('swiss')
  640. for item in self.ffamilydict.items():
  641. if self.fontfamily == item[1]:
  642. self.ffamilycb.SetStringSelection(item[0])
  643. break
  644. gridSizer.Add(self.ffamilycb, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  645. #
  646. # font style
  647. #
  648. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Style:"))
  649. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  650. self.fstylecb = wx.ComboBox(
  651. parent=self, id=wx.ID_ANY, size=(250, -1),
  652. choices=list(self.fstyledict.keys()),
  653. style=wx.CB_DROPDOWN)
  654. self.fstylecb.SetStringSelection('normal')
  655. for item in self.fstyledict.items():
  656. if self.fontstyle == item[1]:
  657. self.fstylecb.SetStringSelection(item[0])
  658. break
  659. gridSizer.Add(self.fstylecb, pos=(1, 1), flag=wx.ALIGN_RIGHT)
  660. #
  661. # font weight
  662. #
  663. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Weight:"))
  664. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  665. self.fwtcb = wx.ComboBox(
  666. parent=self, size=(250, -1),
  667. choices=list(self.fwtdict.keys()),
  668. style=wx.CB_DROPDOWN)
  669. self.fwtcb.SetStringSelection('normal')
  670. for item in self.fwtdict.items():
  671. if self.fontweight == item[1]:
  672. self.fwtcb.SetStringSelection(item[0])
  673. break
  674. gridSizer.Add(self.fwtcb, pos=(2, 1), flag=wx.ALIGN_RIGHT)
  675. gridSizer.AddGrowableCol(1)
  676. boxSizer.Add(gridSizer, flag=wx.EXPAND)
  677. sizer.Add(boxSizer, flag=wx.LEFT | wx.RIGHT |
  678. wx.BOTTOM | wx.EXPAND, border=3)
  679. line = wx.StaticLine(
  680. parent=self, id=wx.ID_ANY, size=(
  681. 20, -1), style=wx.LI_HORIZONTAL)
  682. sizer.Add(line, proportion=0, flag=wx.GROW |
  683. wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border=3)
  684. #
  685. # buttons
  686. #
  687. btnSave = Button(self, wx.ID_SAVE)
  688. btnApply = Button(self, wx.ID_APPLY)
  689. btnOk = Button(self, wx.ID_OK)
  690. btnCancel = Button(self, wx.ID_CANCEL)
  691. btnOk.SetDefault()
  692. # bindings
  693. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  694. btnApply.SetToolTip(_("Apply changes for the current session"))
  695. btnOk.Bind(wx.EVT_BUTTON, self.OnOk)
  696. btnOk.SetToolTip(
  697. _("Apply changes for the current session and close dialog"))
  698. btnOk.SetDefault()
  699. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  700. btnSave.SetToolTip(
  701. _("Apply and save changes to user settings file (default for next sessions)"))
  702. btnCancel.SetToolTip(_("Close dialog and ignore changes"))
  703. # sizers
  704. btnStdSizer = wx.StdDialogButtonSizer()
  705. btnStdSizer.AddButton(btnOk)
  706. btnStdSizer.AddButton(btnApply)
  707. btnStdSizer.AddButton(btnCancel)
  708. btnStdSizer.Realize()
  709. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  710. btnSizer.Add(
  711. btnSave,
  712. proportion=0,
  713. flag=wx.ALIGN_LEFT | wx.ALL,
  714. border=5)
  715. btnSizer.Add(
  716. btnStdSizer,
  717. proportion=0,
  718. flag=wx.ALIGN_RIGHT | wx.ALL,
  719. border=5)
  720. sizer.Add(
  721. btnSizer,
  722. proportion=0,
  723. flag=wx.ALIGN_RIGHT | wx.ALL,
  724. border=5)
  725. #
  726. # bindings
  727. #
  728. self.ptitleentry.Bind(wx.EVT_TEXT, self.OnTitle)
  729. self.xlabelentry.Bind(wx.EVT_TEXT, self.OnXLabel)
  730. self.ylabelentry.Bind(wx.EVT_TEXT, self.OnYLabel)
  731. self.SetSizer(sizer)
  732. sizer.Fit(self)
  733. def OnTitle(self, event):
  734. self.ptitle = event.GetString()
  735. def OnXLabel(self, event):
  736. self.xlabel = event.GetString()
  737. def OnYLabel(self, event):
  738. self.ylabel = event.GetString()
  739. def UpdateSettings(self):
  740. self.properties['font']['prop'][
  741. 'titleSize'] = self.ptitlesize.GetValue()
  742. self.properties['font']['prop'][
  743. 'axisSize'] = self.axislabelsize.GetValue()
  744. family = self.ffamilydict[self.ffamilycb.GetStringSelection()]
  745. self.properties['font']['wxfont'].SetFamily(family)
  746. style = self.fstyledict[self.fstylecb.GetStringSelection()]
  747. self.properties['font']['wxfont'].SetStyle(style)
  748. weight = self.fwtdict[self.fwtcb.GetStringSelection()]
  749. self.properties['font']['wxfont'].SetWeight(weight)
  750. def OnSave(self, event):
  751. """Button 'Save' pressed"""
  752. self.OnApply(None)
  753. fileSettings = {}
  754. UserSettings.ReadSettingsFile(settings=fileSettings)
  755. fileSettings[self.plottype] = UserSettings.Get(group=self.plottype)
  756. UserSettings.SaveToFile(fileSettings)
  757. self._giface.WriteLog(
  758. _('Plot text sizes saved to file \'%s\'.') % UserSettings.filePath)
  759. self.EndModal(wx.ID_OK)
  760. def OnApply(self, event):
  761. """Button 'Apply' pressed"""
  762. self.UpdateSettings()
  763. self.parent.OnPlotText(self)
  764. def OnOk(self, event):
  765. """Button 'OK' pressed"""
  766. self.OnApply(None)
  767. self.EndModal(wx.ID_OK)
  768. class OptDialog(wx.Dialog):
  769. def __init__(self, parent, giface, id, title, plottype='',
  770. style=wx.DEFAULT_DIALOG_STYLE, **kwargs):
  771. """Dialog to set various options for data plotted, including: line
  772. width, color, style; marker size, color, fill, and style; grid
  773. and legend options.
  774. """
  775. wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)
  776. # init variables
  777. self.parent = parent
  778. self._giface = giface
  779. self.linestyledict = parent.linestyledict
  780. self.ptfilldict = parent.ptfilldict
  781. self.parent = parent
  782. self.plottype = plottype
  783. self.pttypelist = ['circle',
  784. 'dot',
  785. 'square',
  786. 'triangle',
  787. 'triangle_down',
  788. 'cross',
  789. 'plus']
  790. self.axislist = ['min',
  791. 'auto',
  792. 'custom']
  793. # widgets ids
  794. self.wxId = {}
  795. self.parent = parent
  796. # read-only
  797. self.raster = self.parent.raster
  798. self.rasterList = self.parent.rasterList
  799. self.properties = self.parent.properties
  800. self.map = ''
  801. if len(self.rasterList) == 0:
  802. wx.MessageBox(parent=self,
  803. message=_("No map or image group selected to plot."),
  804. caption=_("Warning"), style=wx.OK | wx.ICON_ERROR)
  805. self._do_layout()
  806. def ConvertTuples(self, tlist):
  807. """Converts tuples to strings when rasterList contains raster
  808. pairs for scatterplot
  809. """
  810. list = []
  811. for i in tlist:
  812. i = str(i).strip('()')
  813. list.append(i)
  814. return list
  815. def _do_layout(self):
  816. """Options dialog layout
  817. """
  818. sizer = wx.BoxSizer(wx.VERTICAL)
  819. box = StaticBox(parent=self, id=wx.ID_ANY,
  820. label=" %s " % _("Plot settings"))
  821. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  822. self.wxId['pcolor'] = 0
  823. self.wxId['pwidth'] = 0
  824. self.wxId['pstyle'] = 0
  825. self.wxId['psize'] = 0
  826. self.wxId['ptype'] = 0
  827. self.wxId['pfill'] = 0
  828. self.wxId['plegend'] = 0
  829. self.wxId['marker'] = {}
  830. self.wxId['x-axis'] = {}
  831. self.wxId['y-axis'] = {}
  832. #
  833. # plot line settings and point settings
  834. #
  835. if len(self.rasterList) == 0:
  836. return
  837. box = StaticBox(parent=self, id=wx.ID_ANY,
  838. label=_("Map/image plotted"))
  839. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  840. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  841. row = 0
  842. choicelist = []
  843. for i in self.rasterList:
  844. choicelist.append(str(i))
  845. self.mapchoice = Choice(parent=self, id=wx.ID_ANY, size=(300, -1),
  846. choices=choicelist)
  847. self.mapchoice.SetToolTip(_("Settings for selected map"))
  848. if not self.map:
  849. self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
  850. else:
  851. self.mapchoice.SetStringSelection(str(self.map))
  852. gridSizer.Add(self.mapchoice, flag=wx.ALIGN_CENTER_VERTICAL,
  853. pos=(row, 0), span=(1, 2))
  854. #
  855. # options for line plots (profiles and histograms)
  856. #
  857. if self.plottype != 'scatter':
  858. row += 1
  859. label = StaticText(
  860. parent=self,
  861. id=wx.ID_ANY,
  862. label=_("Line color"))
  863. gridSizer.Add(
  864. label,
  865. flag=wx.ALIGN_CENTER_VERTICAL,
  866. pos=(
  867. row,
  868. 0))
  869. color = csel.ColourSelect(
  870. parent=self, id=wx.ID_ANY, colour=self.raster[
  871. self.map]['pcolor'])
  872. self.wxId['pcolor'] = color.GetId()
  873. gridSizer.Add(color, pos=(row, 1))
  874. row += 1
  875. label = StaticText(
  876. parent=self,
  877. id=wx.ID_ANY,
  878. label=_("Line width"))
  879. gridSizer.Add(
  880. label,
  881. flag=wx.ALIGN_CENTER_VERTICAL,
  882. pos=(
  883. row,
  884. 0))
  885. width = SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  886. size=(50, -1), style=wx.SP_ARROW_KEYS)
  887. width.SetRange(1, 10)
  888. width.SetValue(self.raster[self.map]['pwidth'])
  889. self.wxId['pwidth'] = width.GetId()
  890. gridSizer.Add(width, pos=(row, 1))
  891. row += 1
  892. label = StaticText(
  893. parent=self,
  894. id=wx.ID_ANY,
  895. label=_("Line style"))
  896. gridSizer.Add(
  897. label,
  898. flag=wx.ALIGN_CENTER_VERTICAL,
  899. pos=(
  900. row,
  901. 0))
  902. style = Choice(
  903. parent=self, id=wx.ID_ANY, size=(
  904. 120, -1), choices=list(self.linestyledict.keys()))
  905. style.SetStringSelection(self.raster[self.map]['pstyle'])
  906. self.wxId['pstyle'] = style.GetId()
  907. gridSizer.Add(style, pos=(row, 1))
  908. row += 1
  909. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  910. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  911. legend = TextCtrl(parent=self, id=wx.ID_ANY,
  912. value="", size=(200, -1))
  913. legend.SetValue(self.raster[self.map]['plegend'])
  914. gridSizer.Add(legend, pos=(row, 1))
  915. self.wxId['plegend'] = legend.GetId()
  916. boxSizer.Add(gridSizer)
  917. boxMainSizer.Add(boxSizer, flag=wx.ALL, border=3)
  918. #
  919. # segment marker settings for profiles only
  920. #
  921. if self.plottype == 'profile':
  922. box = StaticBox(
  923. parent=self, id=wx.ID_ANY, label=" %s " %
  924. _("Transect segment marker settings"))
  925. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  926. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  927. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Color"))
  928. gridSizer.Add(
  929. label,
  930. flag=wx.ALIGN_CENTER_VERTICAL,
  931. pos=(
  932. 0,
  933. 0))
  934. ptcolor = csel.ColourSelect(
  935. parent=self,
  936. id=wx.ID_ANY,
  937. colour=self.properties['marker']['color'])
  938. self.wxId['marker']['color'] = ptcolor.GetId()
  939. gridSizer.Add(ptcolor, pos=(0, 1))
  940. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Size"))
  941. gridSizer.Add(
  942. label,
  943. flag=wx.ALIGN_CENTER_VERTICAL,
  944. pos=(
  945. 1,
  946. 0))
  947. ptsize = SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  948. size=(50, -1), style=wx.SP_ARROW_KEYS)
  949. ptsize.SetRange(1, 10)
  950. ptsize.SetValue(self.properties['marker']['size'])
  951. self.wxId['marker']['size'] = ptsize.GetId()
  952. gridSizer.Add(ptsize, pos=(1, 1))
  953. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Fill"))
  954. gridSizer.Add(
  955. label,
  956. flag=wx.ALIGN_CENTER_VERTICAL,
  957. pos=(
  958. 2,
  959. 0))
  960. ptfill = Choice(parent=self, id=wx.ID_ANY,
  961. size=(120, -1), choices=list(self.ptfilldict.keys()))
  962. ptfill.SetStringSelection(self.properties['marker']['fill'])
  963. self.wxId['marker']['fill'] = ptfill.GetId()
  964. gridSizer.Add(ptfill, pos=(2, 1))
  965. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  966. gridSizer.Add(
  967. label,
  968. flag=wx.ALIGN_CENTER_VERTICAL,
  969. pos=(
  970. 3,
  971. 0))
  972. ptlegend = TextCtrl(
  973. parent=self, id=wx.ID_ANY, value="", size=(
  974. 200, -1))
  975. ptlegend.SetValue(self.properties['marker']['legend'])
  976. self.wxId['marker']['legend'] = ptlegend.GetId()
  977. gridSizer.Add(ptlegend, pos=(3, 1))
  978. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Style"))
  979. gridSizer.Add(
  980. label,
  981. flag=wx.ALIGN_CENTER_VERTICAL,
  982. pos=(
  983. 4,
  984. 0))
  985. pttype = Choice(
  986. parent=self, size=(200, -1),
  987. choices=self.pttypelist)
  988. pttype.SetStringSelection(self.properties['marker']['type'])
  989. self.wxId['marker']['type'] = pttype.GetId()
  990. gridSizer.Add(pttype, pos=(4, 1))
  991. boxSizer.Add(gridSizer)
  992. boxMainSizer.Add(boxSizer, flag=wx.ALL, border=3)
  993. #
  994. # point options for scatterplots
  995. #
  996. elif self.plottype == 'scatter':
  997. box = StaticBox(parent=self, id=wx.ID_ANY,
  998. label=" %s " % _("Scatterplot points"))
  999. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1000. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1001. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Color"))
  1002. gridSizer.Add(
  1003. label,
  1004. flag=wx.ALIGN_CENTER_VERTICAL,
  1005. pos=(
  1006. 0,
  1007. 0))
  1008. ptcolor = csel.ColourSelect(
  1009. parent=self, id=wx.ID_ANY, colour=self.raster[
  1010. self.map]['pcolor'])
  1011. self.wxId['pcolor'] = ptcolor.GetId()
  1012. gridSizer.Add(ptcolor, pos=(0, 1))
  1013. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Size"))
  1014. gridSizer.Add(
  1015. label,
  1016. flag=wx.ALIGN_CENTER_VERTICAL,
  1017. pos=(
  1018. 1,
  1019. 0))
  1020. ptsize = SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  1021. size=(50, -1), style=wx.SP_ARROW_KEYS)
  1022. ptsize.SetRange(1, 10)
  1023. ptsize.SetValue(self.raster[self.map]['psize'])
  1024. self.wxId['psize'] = ptsize.GetId()
  1025. gridSizer.Add(ptsize, pos=(1, 1))
  1026. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Fill"))
  1027. gridSizer.Add(
  1028. label,
  1029. flag=wx.ALIGN_CENTER_VERTICAL,
  1030. pos=(
  1031. 2,
  1032. 0))
  1033. ptfill = Choice(parent=self, id=wx.ID_ANY,
  1034. size=(120, -1), choices=list(self.ptfilldict.keys()))
  1035. ptfill.SetStringSelection(self.raster[self.map]['pfill'])
  1036. self.wxId['pfill'] = ptfill.GetId()
  1037. gridSizer.Add(ptfill, pos=(2, 1))
  1038. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  1039. gridSizer.Add(
  1040. label,
  1041. flag=wx.ALIGN_CENTER_VERTICAL,
  1042. pos=(
  1043. 3,
  1044. 0))
  1045. ptlegend = TextCtrl(
  1046. parent=self, id=wx.ID_ANY, value="", size=(
  1047. 200, -1))
  1048. ptlegend.SetValue(self.raster[self.map]['plegend'])
  1049. self.wxId['plegend'] = ptlegend.GetId()
  1050. gridSizer.Add(ptlegend, pos=(3, 1))
  1051. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Style"))
  1052. gridSizer.Add(
  1053. label,
  1054. flag=wx.ALIGN_CENTER_VERTICAL,
  1055. pos=(
  1056. 4,
  1057. 0))
  1058. pttype = Choice(
  1059. parent=self, size=(200, -1),
  1060. choices=self.pttypelist)
  1061. pttype.SetStringSelection(self.raster[self.map]['ptype'])
  1062. self.wxId['ptype'] = pttype.GetId()
  1063. gridSizer.Add(pttype, pos=(4, 1))
  1064. boxSizer.Add(gridSizer)
  1065. boxMainSizer.Add(boxSizer, flag=wx.ALL, border=3)
  1066. sizer.Add(boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  1067. #
  1068. # axis options for all plots
  1069. #
  1070. box = StaticBox(parent=self, id=wx.ID_ANY,
  1071. label=" %s " % _("Axis settings"))
  1072. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1073. middleSizer = wx.BoxSizer(wx.HORIZONTAL)
  1074. idx = 0
  1075. for axis, atype in [(_("X-Axis"), 'x-axis'),
  1076. (_("Y-Axis"), 'y-axis')]:
  1077. box = StaticBox(parent=self, id=wx.ID_ANY,
  1078. label=" %s " % axis)
  1079. boxSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1080. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1081. prop = self.properties[atype]['prop']
  1082. row = 0
  1083. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Scale"))
  1084. gridSizer.Add(
  1085. label,
  1086. flag=wx.ALIGN_CENTER_VERTICAL,
  1087. pos=(
  1088. row,
  1089. 0))
  1090. type = Choice(
  1091. parent=self, id=wx.ID_ANY, size=(
  1092. 100, -1), choices=self.axislist)
  1093. type.SetStringSelection(prop['type'])
  1094. type.SetToolTip(
  1095. _("Automatic axis scaling, custom max and min, or scale matches data range (min)"))
  1096. self.wxId[atype]['type'] = type.GetId()
  1097. gridSizer.Add(type, pos=(row, 1))
  1098. row += 1
  1099. label = StaticText(
  1100. parent=self,
  1101. id=wx.ID_ANY,
  1102. label=_("Custom min"))
  1103. gridSizer.Add(
  1104. label,
  1105. flag=wx.ALIGN_CENTER_VERTICAL,
  1106. pos=(
  1107. row,
  1108. 0))
  1109. min = TextCtrl(parent=self, id=wx.ID_ANY,
  1110. value="", size=(70, -1))
  1111. min.SetValue(str(prop['min']))
  1112. self.wxId[atype]['min'] = min.GetId()
  1113. gridSizer.Add(min, pos=(row, 1))
  1114. row += 1
  1115. label = StaticText(
  1116. parent=self,
  1117. id=wx.ID_ANY,
  1118. label=_("Custom max"))
  1119. gridSizer.Add(
  1120. label,
  1121. flag=wx.ALIGN_CENTER_VERTICAL,
  1122. pos=(
  1123. row,
  1124. 0))
  1125. max = TextCtrl(parent=self, id=wx.ID_ANY,
  1126. value="", size=(70, -1))
  1127. max.SetValue(str(prop['max']))
  1128. self.wxId[atype]['max'] = max.GetId()
  1129. gridSizer.Add(max, pos=(row, 1))
  1130. row += 1
  1131. log = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Log scale"))
  1132. log.SetValue(prop['log'])
  1133. self.wxId[atype]['log'] = log.GetId()
  1134. gridSizer.Add(log, pos=(row, 0), span=(1, 2))
  1135. if idx == 0:
  1136. flag = wx.ALL | wx.EXPAND
  1137. else:
  1138. flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND
  1139. boxSizer.Add(gridSizer, flag=wx.ALL, border=3)
  1140. boxMainSizer.Add(boxSizer, flag=flag, border=3)
  1141. idx += 1
  1142. middleSizer.Add(boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  1143. #
  1144. # grid & legend options for all plots
  1145. #
  1146. self.wxId['grid'] = {}
  1147. self.wxId['legend'] = {}
  1148. self.wxId['font'] = {}
  1149. box = StaticBox(parent=self, id=wx.ID_ANY,
  1150. label=" %s " % _("Grid and Legend settings"))
  1151. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1152. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1153. row = 0
  1154. label = StaticText(parent=self, id=wx.ID_ANY, label=_("Grid color"))
  1155. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1156. gridcolor = csel.ColourSelect(
  1157. parent=self,
  1158. id=wx.ID_ANY,
  1159. colour=self.properties['grid']['color'])
  1160. self.wxId['grid']['color'] = gridcolor.GetId()
  1161. gridSizer.Add(gridcolor, pos=(row, 1))
  1162. row += 1
  1163. gridshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show grid"))
  1164. gridshow.SetValue(self.properties['grid']['enabled'])
  1165. self.wxId['grid']['enabled'] = gridshow.GetId()
  1166. gridSizer.Add(gridshow, pos=(row, 0), span=(1, 2))
  1167. row += 1
  1168. label = StaticText(
  1169. parent=self,
  1170. id=wx.ID_ANY,
  1171. label=_("Legend font size"))
  1172. gridSizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1173. legendfontsize = SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  1174. size=(50, -1), style=wx.SP_ARROW_KEYS)
  1175. legendfontsize.SetRange(5, 100)
  1176. legendfontsize.SetValue(
  1177. int(self.properties['font']['prop']['legendSize']))
  1178. self.wxId['font']['legendSize'] = legendfontsize.GetId()
  1179. gridSizer.Add(legendfontsize, pos=(row, 1))
  1180. row += 1
  1181. legendshow = wx.CheckBox(
  1182. parent=self,
  1183. id=wx.ID_ANY,
  1184. label=_("Show legend"))
  1185. legendshow.SetValue(self.properties['legend']['enabled'])
  1186. self.wxId['legend']['enabled'] = legendshow.GetId()
  1187. gridSizer.Add(legendshow, pos=(row, 0), span=(1, 2))
  1188. boxMainSizer.Add(gridSizer, flag=flag, border=3)
  1189. middleSizer.Add(boxMainSizer, flag=wx.LEFT |
  1190. wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  1191. sizer.Add(middleSizer, flag=wx.ALL, border=0)
  1192. #
  1193. # line & buttons
  1194. #
  1195. line = wx.StaticLine(
  1196. parent=self, id=wx.ID_ANY, size=(
  1197. 20, -1), style=wx.LI_HORIZONTAL)
  1198. sizer.Add(line, proportion=0, flag=wx.GROW |
  1199. wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border=3)
  1200. #
  1201. # buttons
  1202. #
  1203. btnSave = Button(self, wx.ID_SAVE)
  1204. btnApply = Button(self, wx.ID_APPLY)
  1205. btnOk = Button(self, wx.ID_OK)
  1206. btnCancel = Button(self, wx.ID_CANCEL)
  1207. btnOk.SetDefault()
  1208. # tooltips for buttons
  1209. btnApply.SetToolTip(_("Apply changes for the current session"))
  1210. btnOk.SetToolTip(
  1211. _("Apply changes for the current session and close dialog"))
  1212. btnSave.SetToolTip(
  1213. _("Apply and save changes to user settings file (default for next sessions)"))
  1214. btnCancel.SetToolTip(_("Close dialog and ignore changes"))
  1215. # sizers
  1216. btnStdSizer = wx.StdDialogButtonSizer()
  1217. btnStdSizer.AddButton(btnOk)
  1218. btnStdSizer.AddButton(btnApply)
  1219. btnStdSizer.AddButton(btnCancel)
  1220. btnStdSizer.Realize()
  1221. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  1222. btnSizer.Add(
  1223. btnSave,
  1224. proportion=0,
  1225. flag=wx.ALIGN_LEFT | wx.ALL,
  1226. border=5)
  1227. btnSizer.Add(
  1228. btnStdSizer,
  1229. proportion=0,
  1230. flag=wx.ALIGN_RIGHT | wx.ALL,
  1231. border=5)
  1232. sizer.Add(
  1233. btnSizer,
  1234. proportion=0,
  1235. flag=wx.ALIGN_RIGHT | wx.ALL,
  1236. border=5)
  1237. #
  1238. # bindings for buttons and map plot settings controls
  1239. #
  1240. self.mapchoice.Bind(wx.EVT_CHOICE, self.OnSetMap)
  1241. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1242. btnOk.Bind(wx.EVT_BUTTON, self.OnOk)
  1243. btnOk.SetDefault()
  1244. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1245. self.SetSizer(sizer)
  1246. sizer.Fit(self)
  1247. def OnSetMap(self, event):
  1248. """Handler for changing map selection"""
  1249. idx = event.GetSelection()
  1250. self.map = self.rasterList[idx]
  1251. # update settings controls for all plots
  1252. self.FindWindowById(
  1253. self.wxId['pcolor']).SetColour(
  1254. self.raster[self.map]['pcolor'])
  1255. self.FindWindowById(
  1256. self.wxId['plegend']).SetValue(
  1257. self.raster[self.map]['plegend'])
  1258. # update settings controls for histograms and profiles
  1259. if self.plottype != 'scatter':
  1260. self.FindWindowById(
  1261. self.wxId['pwidth']).SetValue(
  1262. self.raster[self.map]['pwidth'])
  1263. self.FindWindowById(
  1264. self.wxId['pstyle']).SetStringSelection(
  1265. self.raster[
  1266. self.map]['pstyle'])
  1267. # update settings controls for scatterplots
  1268. elif self.plottype == 'scatter':
  1269. self.FindWindowById(
  1270. self.wxId['psize']).SetValue(
  1271. self.raster[self.map]['psize'])
  1272. self.FindWindowById(
  1273. self.wxId['ptype']).SetStringSelection(
  1274. self.raster[
  1275. self.map]['ptype'])
  1276. self.FindWindowById(
  1277. self.wxId['pfill']).SetStringSelection(
  1278. self.raster[
  1279. self.map]['pfill'])
  1280. self.Refresh()
  1281. def OnSetOpt(self, event):
  1282. """Handler for changing any other option"""
  1283. self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
  1284. self.UpdateSettings()
  1285. self.parent.SetGraphStyle()
  1286. p = self.parent.CreatePlotList()
  1287. self.parent.DrawPlot(p)
  1288. def UpdateSettings(self):
  1289. """Apply settings to each map and to entire plot"""
  1290. self.raster[self.map]['pcolor'] = self.FindWindowById(
  1291. self.wxId['pcolor']).GetColour()
  1292. self.properties['raster']['pcolor'] = self.raster[self.map]['pcolor']
  1293. self.raster[self.map]['plegend'] = self.FindWindowById(
  1294. self.wxId['plegend']).GetValue()
  1295. if self.plottype != 'scatter':
  1296. self.raster[
  1297. self.map]['pwidth'] = int(
  1298. self.FindWindowById(
  1299. self.wxId['pwidth']).GetValue())
  1300. self.properties['raster'][
  1301. 'pwidth'] = self.raster[self.map]['pwidth']
  1302. self.raster[self.map]['pstyle'] = self.FindWindowById(
  1303. self.wxId['pstyle']).GetStringSelection()
  1304. self.properties['raster'][
  1305. 'pstyle'] = self.raster[self.map]['pstyle']
  1306. elif self.plottype == 'scatter':
  1307. self.raster[
  1308. self.map]['psize'] = self.FindWindowById(
  1309. self.wxId['psize']).GetValue()
  1310. self.properties['raster']['psize'] = self.raster[self.map]['psize']
  1311. self.raster[self.map]['ptype'] = self.FindWindowById(
  1312. self.wxId['ptype']).GetStringSelection()
  1313. self.properties['raster']['ptype'] = self.raster[self.map]['ptype']
  1314. self.raster[self.map]['pfill'] = self.FindWindowById(
  1315. self.wxId['pfill']).GetStringSelection()
  1316. self.properties['raster']['pfill'] = self.raster[self.map]['pfill']
  1317. # update settings for entire plot
  1318. for axis in ('x-axis', 'y-axis'):
  1319. self.properties[axis]['prop']['type'] = self.FindWindowById(
  1320. self.wxId[axis]['type']).GetStringSelection()
  1321. self.properties[axis]['prop']['min'] = float(
  1322. self.FindWindowById(self.wxId[axis]['min']).GetValue())
  1323. self.properties[axis]['prop']['max'] = float(
  1324. self.FindWindowById(self.wxId[axis]['max']).GetValue())
  1325. self.properties[axis]['prop']['log'] = self.FindWindowById(
  1326. self.wxId[axis]['log']).IsChecked()
  1327. if self.plottype == 'profile':
  1328. self.properties['marker']['color'] = self.FindWindowById(
  1329. self.wxId['marker']['color']).GetColour()
  1330. self.properties['marker']['fill'] = self.FindWindowById(
  1331. self.wxId['marker']['fill']).GetStringSelection()
  1332. self.properties['marker']['size'] = self.FindWindowById(
  1333. self.wxId['marker']['size']).GetValue()
  1334. self.properties['marker']['type'] = self.FindWindowById(
  1335. self.wxId['marker']['type']).GetStringSelection()
  1336. self.properties['marker']['legend'] = self.FindWindowById(
  1337. self.wxId['marker']['legend']).GetValue()
  1338. self.properties['grid']['color'] = self.FindWindowById(
  1339. self.wxId['grid']['color']).GetColour()
  1340. self.properties['grid']['enabled'] = self.FindWindowById(
  1341. self.wxId['grid']['enabled']).IsChecked()
  1342. # this makes more sense in the text properties, including for settings update. But will need to change
  1343. # layout for controls to text dialog too.
  1344. self.properties['font']['prop']['legendSize'] = self.FindWindowById(
  1345. self.wxId['font']['legendSize']).GetValue()
  1346. self.properties['legend']['enabled'] = self.FindWindowById(
  1347. self.wxId['legend']['enabled']).IsChecked()
  1348. self.parent.UpdateLabels()
  1349. def OnSave(self, event):
  1350. """Button 'Save' pressed"""
  1351. self.OnApply(None)
  1352. fileSettings = {}
  1353. UserSettings.ReadSettingsFile(settings=fileSettings)
  1354. fileSettings[self.plottype] = UserSettings.Get(group=self.plottype)
  1355. UserSettings.SaveToFile(fileSettings)
  1356. self._giface.WriteLog(
  1357. _('Plot settings saved to file \'%s\'.') % UserSettings.filePath)
  1358. self.EndModal(wx.ID_OK)
  1359. def OnApply(self, event):
  1360. """Button 'Apply' pressed. Does not close dialog"""
  1361. self.UpdateSettings()
  1362. self.parent.SetGraphStyle()
  1363. p = self.parent.CreatePlotList()
  1364. self.parent.DrawPlot(p)
  1365. def OnOk(self, event):
  1366. """Button 'OK' pressed"""
  1367. self.OnApply(None)
  1368. self.EndModal(wx.ID_OK)