toolbars.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. """
  2. @package iclass.toolbars
  3. @brief wxIClass toolbars and icons.
  4. Classes:
  5. - toolbars::IClassMapToolbar
  6. - toolbars::IClassToolbar
  7. - toolbars::IClassMapManagerToolbar
  8. - toolbars::IClassMiscToolbar
  9. (C) 2006-2011 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Vaclav Petras <wenzeslaus gmail.com>
  14. @author Anna Kratochvilova <kratochanna gmail.com>
  15. """
  16. from __future__ import print_function
  17. import wx
  18. from gui_core.toolbars import BaseToolbar, BaseIcons
  19. from icons.icon import MetaIcon
  20. from iclass.dialogs import IClassMapDialog, ContrastColor
  21. from gui_core.forms import GUI
  22. from gui_core.wrap import StaticText
  23. import grass.script as grass
  24. iClassIcons = {
  25. "opacity": MetaIcon(img="layer-opacity", label=_("Set opacity level")),
  26. "classManager": MetaIcon(img="table-manager", label=_("Class manager")),
  27. "selectGroup": MetaIcon(img="layer-group-add", label=_("Select imagery group")),
  28. "run": MetaIcon(
  29. img="execute", label=_("Run analysis, update histogram and coincidence plots")
  30. ),
  31. "sigFile": MetaIcon(img="script-save", label=_("Save signature file for i.maxlik")),
  32. "delCmd": MetaIcon(img="layer-remove", label=_("Remove selected map layer")),
  33. "exportAreas": MetaIcon(
  34. img="layer-export", label=_("Export training areas to vector map")
  35. ),
  36. "importAreas": MetaIcon(
  37. img="layer-import", label=_("Import training areas from vector map")
  38. ),
  39. "addRgb": MetaIcon(img="layer-rgb-add", label=_("Add RGB map layer")),
  40. }
  41. class IClassMapToolbar(BaseToolbar):
  42. """IClass Map toolbar"""
  43. def __init__(self, parent, toolSwitcher):
  44. """IClass Map toolbar constructor"""
  45. BaseToolbar.__init__(self, parent, toolSwitcher)
  46. self.InitToolbar(self._toolbarData())
  47. self._default = self.pan
  48. # add tool to toggle active map window
  49. self.togglemap = wx.Choice(
  50. parent=self, id=wx.ID_ANY, choices=[_("Training"), _("Preview")]
  51. )
  52. self.InsertControl(9, self.togglemap)
  53. self.SetToolShortHelp(
  54. self.togglemap.GetId(),
  55. "%s %s %s"
  56. % (
  57. _("Set map canvas for "),
  58. BaseIcons["zoomBack"].GetLabel(),
  59. _("/ Zoom to map"),
  60. ),
  61. )
  62. for tool in (self.pan, self.zoomIn, self.zoomOut):
  63. self.toolSwitcher.AddToolToGroup(group="mouseUse", toolbar=self, tool=tool)
  64. # realize the toolbar
  65. self.Realize()
  66. self.EnableTool(self.zoomBack, False)
  67. def GetActiveMapTool(self):
  68. """Return widget for selecting active maps"""
  69. return self.togglemap
  70. def GetActiveMap(self):
  71. """Get currently selected map"""
  72. return self.togglemap.GetSelection()
  73. def SetActiveMap(self, index):
  74. """Set currently selected map"""
  75. return self.togglemap.SetSelection(index)
  76. def _toolbarData(self):
  77. """Toolbar data"""
  78. icons = BaseIcons
  79. return self._getToolbarData(
  80. (
  81. (
  82. ("displaymap", icons["display"].label),
  83. icons["display"],
  84. self.parent.OnDraw,
  85. ),
  86. (
  87. ("rendermap", icons["render"].label),
  88. icons["render"],
  89. self.parent.OnRender,
  90. ),
  91. (
  92. ("erase", icons["erase"].label),
  93. icons["erase"],
  94. self.parent.OnErase,
  95. ),
  96. (None,),
  97. (
  98. ("pan", icons["pan"].label),
  99. icons["pan"],
  100. self.parent.OnPan,
  101. wx.ITEM_CHECK,
  102. ),
  103. (
  104. ("zoomIn", icons["zoomIn"].label),
  105. icons["zoomIn"],
  106. self.parent.OnZoomIn,
  107. wx.ITEM_CHECK,
  108. ),
  109. (
  110. ("zoomOut", icons["zoomOut"].label),
  111. icons["zoomOut"],
  112. self.parent.OnZoomOut,
  113. wx.ITEM_CHECK,
  114. ),
  115. (
  116. ("zoomRegion", icons["zoomRegion"].label),
  117. icons["zoomRegion"],
  118. self.parent.OnZoomToWind,
  119. ),
  120. (
  121. ("zoomMenu", icons["zoomMenu"].label),
  122. icons["zoomMenu"],
  123. self.parent.OnZoomMenu,
  124. ),
  125. (None,),
  126. (
  127. ("zoomBack", icons["zoomBack"].label),
  128. icons["zoomBack"],
  129. self.parent.OnZoomBack,
  130. ),
  131. (
  132. ("zoomToMap", icons["zoomExtent"].label),
  133. icons["zoomExtent"],
  134. self.parent.OnZoomToMap,
  135. ),
  136. (
  137. ("mapDispSettings", BaseIcons["mapDispSettings"].label),
  138. BaseIcons["mapDispSettings"],
  139. self.parent.OnMapDisplayProperties,
  140. ),
  141. )
  142. )
  143. class IClassToolbar(BaseToolbar):
  144. """IClass toolbar"""
  145. def __init__(self, parent, stats_data):
  146. """IClass toolbar constructor"""
  147. self.stats_data = stats_data
  148. BaseToolbar.__init__(self, parent)
  149. self.InitToolbar(self._toolbarData())
  150. self.choice = wx.Choice(parent=self, id=wx.ID_ANY, size=(110, -1))
  151. self.InsertControl(3, self.choice)
  152. self.choice.Bind(wx.EVT_CHOICE, self.OnSelectCategory)
  153. # stupid workaround to insert small space between controls
  154. self.InsertControl(4, StaticText(self, id=wx.ID_ANY, label=" "))
  155. self.combo = wx.ComboBox(
  156. self, id=wx.ID_ANY, size=(130, -1), style=wx.TE_PROCESS_ENTER
  157. )
  158. self.InitStddev()
  159. self.InsertControl(5, self.combo)
  160. self.EnableControls(False)
  161. self.combo.Bind(wx.EVT_COMBOBOX, self.OnStdChangeSelection)
  162. self.combo.Bind(wx.EVT_TEXT_ENTER, self.OnStdChangeText)
  163. self.stats_data.statisticsAdded.connect(self.Update)
  164. self.stats_data.statisticsDeleted.connect(self.Update)
  165. self.stats_data.allStatisticsDeleted.connect(self.Update)
  166. self.stats_data.statisticsSet.connect(self.Update)
  167. # realize the toolbar
  168. self.Realize()
  169. def _toolbarData(self):
  170. """Toolbar data"""
  171. icons = iClassIcons
  172. return self._getToolbarData(
  173. (
  174. (
  175. ("selectGroup", icons["selectGroup"].label),
  176. icons["selectGroup"],
  177. lambda event: self.parent.AddBands(),
  178. ),
  179. (None,),
  180. (
  181. ("classManager", icons["classManager"].label),
  182. icons["classManager"],
  183. self.parent.OnCategoryManager,
  184. ),
  185. (None,),
  186. (
  187. ("runAnalysis", icons["run"].label),
  188. icons["run"],
  189. self.parent.OnRunAnalysis,
  190. ),
  191. (None,),
  192. (
  193. ("importAreas", icons["importAreas"].label),
  194. icons["importAreas"],
  195. self.parent.OnImportAreas,
  196. ),
  197. (
  198. ("exportAreas", icons["exportAreas"].label),
  199. icons["exportAreas"],
  200. self.parent.OnExportAreas,
  201. ),
  202. (
  203. ("sigFile", icons["sigFile"].label),
  204. icons["sigFile"],
  205. self.parent.OnSaveSigFile,
  206. ),
  207. )
  208. )
  209. def OnMotion(self, event):
  210. print(self.choice.GetStringSelection())
  211. def OnSelectCategory(self, event):
  212. idx = self.choice.GetSelection()
  213. cat = self.choice.GetClientData(idx)
  214. self._updateColor(cat)
  215. self.parent.CategoryChanged(currentCat=cat)
  216. def _updateColor(self, cat):
  217. if cat:
  218. stat = self.stats_data.GetStatistics(cat)
  219. back_c = wx.Colour([int(x) for x in stat.color.split(":")])
  220. text_c = wx.Colour(*ContrastColor(back_c))
  221. else:
  222. back_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
  223. text_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT)
  224. self.choice.SetForegroundColour(text_c)
  225. self.choice.SetBackgroundColour(back_c)
  226. def SetCategories(self, catNames, catIdx):
  227. self.choice.Clear()
  228. for name, idx in zip(catNames, catIdx):
  229. self.choice.Append(name, idx)
  230. def GetSelectedCategoryName(self):
  231. return self.choice.GetStringSelection()
  232. def GetSelectedCategoryIdx(self):
  233. idx = self.choice.GetSelection()
  234. if idx != wx.NOT_FOUND:
  235. return self.choice.GetClientData(idx)
  236. return None
  237. def OnStdChangeSelection(self, event):
  238. idx = self.combo.GetSelection()
  239. nstd = self.combo.GetClientData(idx)
  240. self.StddevChanged(nstd)
  241. def OnStdChangeText(self, event):
  242. val = self.combo.GetValue().strip()
  243. try:
  244. nstd = float(val)
  245. except ValueError:
  246. try:
  247. nstd = float(val.split()[0])
  248. except ValueError:
  249. nstd = None
  250. if nstd is not None:
  251. self.StddevChanged(nstd)
  252. def StddevChanged(self, nstd):
  253. idx = self.GetSelectedCategoryIdx()
  254. if not idx:
  255. return
  256. self.parent.StddevChanged(cat=idx, nstd=nstd)
  257. def UpdateStddev(self, nstd):
  258. self.combo.SetValue(" ".join(("%.2f" % nstd, _("std dev"))))
  259. def InitStddev(self):
  260. for nstd in range(50, 250, 25):
  261. nstd /= 100.0
  262. self.combo.Append(
  263. item=" ".join(("%.2f" % nstd, _("std dev"))), clientData=nstd
  264. )
  265. self.combo.SetSelection(4) # 1.5
  266. def EnableControls(self, enable=True):
  267. self.combo.Enable(enable)
  268. self.choice.Enable(enable)
  269. def Update(self, *args, **kwargs):
  270. name = self.GetSelectedCategoryName()
  271. catNames = []
  272. cats = self.stats_data.GetCategories()
  273. for cat in cats:
  274. stat = self.stats_data.GetStatistics(cat)
  275. catNames.append(stat.name)
  276. self.SetCategories(catNames=catNames, catIdx=cats)
  277. if name in catNames:
  278. self.choice.SetStringSelection(name)
  279. cat = self.GetSelectedCategoryIdx()
  280. elif catNames:
  281. self.choice.SetSelection(0)
  282. cat = self.GetSelectedCategoryIdx()
  283. else:
  284. cat = None
  285. if self.choice.IsEmpty():
  286. self.EnableControls(False)
  287. else:
  288. self.EnableControls(True)
  289. self._updateColor(cat)
  290. self.parent.CategoryChanged(cat)
  291. # don't forget to update maps, histo, ...
  292. class IClassMapManagerToolbar(BaseToolbar):
  293. """IClass toolbar"""
  294. def __init__(self, parent, mapManager):
  295. """IClass toolbar constructor"""
  296. BaseToolbar.__init__(self, parent)
  297. self.InitToolbar(self._toolbarData())
  298. self.choice = wx.Choice(parent=self, id=wx.ID_ANY, size=(300, -1))
  299. self.choiceid = self.AddControl(self.choice)
  300. self.choice.Bind(wx.EVT_CHOICE, self.OnSelectLayer)
  301. self.mapManager = mapManager
  302. # realize the toolbar
  303. self.Realize()
  304. def _toolbarData(self):
  305. """Toolbar data"""
  306. return self._getToolbarData(
  307. (
  308. (
  309. ("addRast", BaseIcons["addRast"].label),
  310. BaseIcons["addRast"],
  311. self.OnAddRast,
  312. ),
  313. (
  314. ("addRgb", iClassIcons["addRgb"].label),
  315. iClassIcons["addRgb"],
  316. self.OnAddRGB,
  317. ),
  318. (
  319. ("delRast", iClassIcons["delCmd"].label),
  320. iClassIcons["delCmd"],
  321. self.OnDelRast,
  322. ),
  323. (
  324. ("setOpacity", iClassIcons["opacity"].label),
  325. iClassIcons["opacity"],
  326. self.OnSetOpacity,
  327. ),
  328. )
  329. )
  330. def OnSelectLayer(self, event):
  331. layer = self.choice.GetStringSelection()
  332. self.mapManager.SelectLayer(name=layer)
  333. def OnAddRast(self, event):
  334. dlg = IClassMapDialog(self, title=_("Add raster map"), element="raster")
  335. if dlg.ShowModal() == wx.ID_OK:
  336. raster = grass.find_file(name=dlg.GetMap(), element="cell")
  337. if raster["fullname"]:
  338. self.mapManager.AddLayer(name=raster["fullname"])
  339. dlg.Destroy()
  340. def OnAddRGB(self, event):
  341. cmd = ["d.rgb"]
  342. GUI(parent=self.parent).ParseCommand(cmd, completed=(self.GetOptData, "", ""))
  343. def GetOptData(self, dcmd, layer, params, propwin):
  344. if dcmd:
  345. self.mapManager.AddLayerRGB(cmd=dcmd)
  346. def OnDelRast(self, event):
  347. layer = self.choice.GetStringSelection()
  348. idx = self.choice.GetSelection()
  349. if layer:
  350. self.mapManager.RemoveLayer(name=layer, idx=idx)
  351. def OnSetOpacity(self, event):
  352. layer = self.choice.GetStringSelection()
  353. idx = self.choice.GetSelection()
  354. if idx == wx.NOT_FOUND:
  355. return
  356. self.mapManager.SetOpacity(name=layer)
  357. class IClassMiscToolbar(BaseToolbar):
  358. """IClass toolbar"""
  359. def __init__(self, parent):
  360. """IClass toolbar constructor"""
  361. BaseToolbar.__init__(self, parent)
  362. self.InitToolbar(self._toolbarData())
  363. # realize the toolbar
  364. self.Realize()
  365. def _toolbarData(self):
  366. """Toolbar data"""
  367. icons = BaseIcons
  368. return self._getToolbarData(
  369. (
  370. (
  371. ("help", icons["help"].label),
  372. icons["help"],
  373. self.parent.OnHelp,
  374. ),
  375. (
  376. ("quit", icons["quit"].label),
  377. icons["quit"],
  378. self.parent.OnCloseWindow,
  379. ),
  380. )
  381. )