Commit 8baa329698ef9760118155b5ada5c834505402f8
1 parent
45f41b2a
Exists in
master
and in
6 other branches
ENH: Task surface layout (#73)
Showing
2 changed files
with
150 additions
and
12 deletions
Show diff stats
invesalius/gui/task_surface.py
@@ -20,15 +20,16 @@ import sys | @@ -20,15 +20,16 @@ import sys | ||
20 | 20 | ||
21 | import wx | 21 | import wx |
22 | import wx.lib.hyperlink as hl | 22 | import wx.lib.hyperlink as hl |
23 | -import wx.lib.platebtn as pbtn | ||
24 | import wx.lib.pubsub as ps | 23 | import wx.lib.pubsub as ps |
25 | 24 | ||
26 | import gui.dialogs as dlg | 25 | import gui.dialogs as dlg |
27 | import gui.widgets.foldpanelbar as fpb | 26 | import gui.widgets.foldpanelbar as fpb |
28 | import gui.widgets.colourselect as csel | 27 | import gui.widgets.colourselect as csel |
28 | +import gui.widgets.platebtn as pbtn | ||
29 | import project as prj | 29 | import project as prj |
30 | import utils as utl | 30 | import utils as utl |
31 | 31 | ||
32 | + | ||
32 | #INTERPOLATION_MODE_LIST = ["Cubic", "Linear", "NearestNeighbor"] | 33 | #INTERPOLATION_MODE_LIST = ["Cubic", "Linear", "NearestNeighbor"] |
33 | MIN_TRANSPARENCY = 0 | 34 | MIN_TRANSPARENCY = 0 |
34 | MAX_TRANSPARENCY = 100 | 35 | MAX_TRANSPARENCY = 100 |
@@ -159,7 +160,7 @@ class InnerTaskPanel(wx.Panel): | @@ -159,7 +160,7 @@ class InnerTaskPanel(wx.Panel): | ||
159 | 160 | ||
160 | class FoldPanel(wx.Panel): | 161 | class FoldPanel(wx.Panel): |
161 | def __init__(self, parent): | 162 | def __init__(self, parent): |
162 | - wx.Panel.__init__(self, parent, size=(50,50)) | 163 | + wx.Panel.__init__(self, parent, size=(50,700)) |
163 | self.SetBackgroundColour(wx.Colour(0,255,0)) | 164 | self.SetBackgroundColour(wx.Colour(0,255,0)) |
164 | 165 | ||
165 | inner_panel = InnerFoldPanel(self) | 166 | inner_panel = InnerFoldPanel(self) |
@@ -185,7 +186,7 @@ class InnerFoldPanel(wx.Panel): | @@ -185,7 +186,7 @@ class InnerFoldPanel(wx.Panel): | ||
185 | # parent panel. Perhaps we need to insert the item into the sizer also... | 186 | # parent panel. Perhaps we need to insert the item into the sizer also... |
186 | # Study this. | 187 | # Study this. |
187 | fold_panel = fpb.FoldPanelBar(self, -1, wx.DefaultPosition, | 188 | fold_panel = fpb.FoldPanelBar(self, -1, wx.DefaultPosition, |
188 | - (10, 100), 0,fpb.FPB_SINGLE_FOLD) | 189 | + (10, 140), 0,fpb.FPB_SINGLE_FOLD) |
189 | 190 | ||
190 | # Fold panel style | 191 | # Fold panel style |
191 | style = fpb.CaptionBarStyle() | 192 | style = fpb.CaptionBarStyle() |
@@ -195,15 +196,18 @@ class InnerFoldPanel(wx.Panel): | @@ -195,15 +196,18 @@ class InnerFoldPanel(wx.Panel): | ||
195 | 196 | ||
196 | # Fold 1 - Surface properties | 197 | # Fold 1 - Surface properties |
197 | item = fold_panel.AddFoldPanel(_("Surface properties"), collapsed=True) | 198 | item = fold_panel.AddFoldPanel(_("Surface properties"), collapsed=True) |
199 | + self.surface_properties = SurfaceProperties(item) | ||
198 | fold_panel.ApplyCaptionStyle(item, style) | 200 | fold_panel.ApplyCaptionStyle(item, style) |
199 | - fold_panel.AddFoldPanelWindow(item, SurfaceProperties(item), Spacing= 0, | 201 | + fold_panel.AddFoldPanelWindow(item, self.surface_properties, Spacing= 0, |
200 | leftSpacing=0, rightSpacing=0) | 202 | leftSpacing=0, rightSpacing=0) |
201 | fold_panel.Expand(fold_panel.GetFoldPanel(0)) | 203 | fold_panel.Expand(fold_panel.GetFoldPanel(0)) |
202 | 204 | ||
203 | # Fold 2 - Surface tools | 205 | # Fold 2 - Surface tools |
204 | item = fold_panel.AddFoldPanel(_("Advanced options"), collapsed=True) | 206 | item = fold_panel.AddFoldPanel(_("Advanced options"), collapsed=True) |
205 | fold_panel.ApplyCaptionStyle(item, style) | 207 | fold_panel.ApplyCaptionStyle(item, style) |
206 | - fold_panel.AddFoldPanelWindow(item, SurfaceTools(item), Spacing= 0, | 208 | + self.surface_tools = SurfaceTools(item) |
209 | + self.surface_tools.combo_surface_name = self.surface_properties.combo_surface_name | ||
210 | + fold_panel.AddFoldPanelWindow(item, self.surface_tools, Spacing= 0, | ||
207 | leftSpacing=0, rightSpacing=0) | 211 | leftSpacing=0, rightSpacing=0) |
208 | 212 | ||
209 | #fold_panel.AddFoldPanelWindow(item, QualityAdjustment(item), Spacing= 0, | 213 | #fold_panel.AddFoldPanelWindow(item, QualityAdjustment(item), Spacing= 0, |
@@ -219,16 +223,142 @@ class InnerFoldPanel(wx.Panel): | @@ -219,16 +223,142 @@ class InnerFoldPanel(wx.Panel): | ||
219 | self.Update() | 223 | self.Update() |
220 | self.SetAutoLayout(1) | 224 | self.SetAutoLayout(1) |
221 | 225 | ||
222 | - | 226 | +BTN_LARGEST = wx.NewId() |
227 | +BTN_SPLIT = wx.NewId() | ||
228 | +BTN_SEEDS = wx.NewId() | ||
223 | class SurfaceTools(wx.Panel): | 229 | class SurfaceTools(wx.Panel): |
224 | def __init__(self, parent): | 230 | def __init__(self, parent): |
225 | - wx.Panel.__init__(self, parent, size=(50,240)) | 231 | + wx.Panel.__init__(self, parent, size=(50,400)) |
226 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) | 232 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) |
227 | self.SetBackgroundColour(default_colour) | 233 | self.SetBackgroundColour(default_colour) |
228 | 234 | ||
235 | + #self.SetBackgroundColour(wx.Colour(255,255,255)) | ||
236 | + self.SetAutoLayout(1) | ||
237 | + | ||
238 | + self.combo_surface_name = None | ||
239 | + | ||
240 | + # Fixed hyperlink items | ||
241 | + tooltip = wx.ToolTip(_("Automatically select largest disconnect surface")) | ||
242 | + link_largest = hl.HyperLinkCtrl(self, -1, _("Split largest surface")) | ||
243 | + link_largest.SetUnderlines(False, False, False) | ||
244 | + link_largest.SetColours("BLACK", "BLACK", "BLACK") | ||
245 | + link_largest.SetToolTip(tooltip) | ||
246 | + link_largest.AutoBrowse(False) | ||
247 | + link_largest.UpdateLink() | ||
248 | + link_largest.Bind(hl.EVT_HYPERLINK_LEFT, self.OnLinkLargest) | ||
249 | + | ||
250 | + tooltip = wx.ToolTip(_("Automatically split surfaces into new ones")) | ||
251 | + link_split_all = hl.HyperLinkCtrl(self, -1,"Split all disconnect surfaces") | ||
252 | + link_split_all.SetUnderlines(False, False, False) | ||
253 | + link_split_all.SetColours("BLACK", "BLACK", "BLACK") | ||
254 | + link_split_all.SetToolTip(tooltip) | ||
255 | + link_split_all.AutoBrowse(False) | ||
256 | + link_split_all.UpdateLink() | ||
257 | + link_split_all.Bind(hl.EVT_HYPERLINK_LEFT, self.OnLinkSplit) | ||
258 | + | ||
259 | + tooltip = wx.ToolTip(_("Manually insert seeds of surfaces of interest")) | ||
260 | + link_seeds = hl.HyperLinkCtrl(self,-1,_("Select surfaces of interest")) | ||
261 | + link_seeds.SetUnderlines(False, False, False) | ||
262 | + link_seeds.SetColours("BLACK", "BLACK", "BLACK") | ||
263 | + link_seeds.SetToolTip(tooltip) | ||
264 | + link_seeds.AutoBrowse(False) | ||
265 | + link_seeds.UpdateLink() | ||
266 | + link_seeds.Bind(hl.EVT_HYPERLINK_LEFT, self.OnLinkSeed) | ||
267 | + | ||
268 | + # Image(s) for buttons | ||
269 | + BMP_LARGEST = wx.Bitmap("../icons/connectivity_largest.png", wx.BITMAP_TYPE_PNG) | ||
270 | + BMP_SPLIT_ALL = wx.Bitmap("../icons/connectivity_split_all.png", wx.BITMAP_TYPE_PNG) | ||
271 | + BMP_SEEDS = wx.Bitmap("../icons/connectivity_manual.png", wx.BITMAP_TYPE_PNG) | ||
272 | + | ||
273 | + bmp_list = [BMP_LARGEST, BMP_SPLIT_ALL, BMP_SEEDS] | ||
274 | + for bmp in bmp_list: | ||
275 | + bmp.SetWidth(25) | ||
276 | + bmp.SetHeight(25) | ||
277 | + | ||
278 | + # Buttons related to hyperlinks | ||
279 | + button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT | ||
280 | + button_style_plus = button_style|pbtn.PB_STYLE_TOGGLE | ||
281 | + | ||
282 | + button_split = pbtn.PlateButton(self, BTN_SPLIT, "", BMP_SPLIT_ALL, | ||
283 | + style=button_style) | ||
284 | + button_largest = pbtn.PlateButton(self, BTN_LARGEST, "", | ||
285 | + BMP_LARGEST, style=button_style) | ||
286 | + button_seeds = pbtn.PlateButton(self, BTN_SEEDS, "", | ||
287 | + BMP_SEEDS, style=button_style_plus) | ||
288 | + self.button_seeds = button_seeds | ||
289 | + | ||
290 | + # When using PlaneButton, it is necessary to bind events from parent win | ||
291 | + self.Bind(wx.EVT_BUTTON, self.OnButton) | ||
292 | + | ||
293 | + # Tags and grid sizer for fixed items | ||
294 | + flag_link = wx.EXPAND|wx.GROW|wx.LEFT|wx.TOP | ||
295 | + flag_button = wx.EXPAND | wx.GROW | ||
296 | + | ||
297 | + #fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=2, vgap=0) | ||
298 | + fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=2, vgap=0) | ||
299 | + fixed_sizer.AddGrowableCol(0, 1) | ||
300 | + fixed_sizer.AddMany([ (link_largest, 1, flag_link, 3), | ||
301 | + (button_largest, 0, flag_button), | ||
302 | + (link_seeds, 1, flag_link, 3), | ||
303 | + (button_seeds, 0, flag_button), | ||
304 | + (link_split_all, 1, flag_link, 3), | ||
305 | + (button_split, 0, flag_button) ]) | ||
306 | + | ||
307 | + | ||
308 | + # Add line sizers into main sizer | ||
309 | + main_sizer = wx.BoxSizer(wx.VERTICAL) | ||
310 | + main_sizer.Add(fixed_sizer, 0, wx.GROW|wx.EXPAND|wx.TOP, 5) | ||
311 | + | ||
312 | + # Update main sizer and panel layout | ||
313 | + self.SetSizer(main_sizer) | ||
314 | + self.Update() | ||
315 | + self.SetAutoLayout(1) | ||
316 | + self.sizer = main_sizer | ||
317 | + | ||
318 | + def OnLinkLargest(self, evt): | ||
319 | + self.SelectLargest() | ||
320 | + | ||
321 | + def OnLinkSplit(self, evt): | ||
322 | + self.SplitSurface() | ||
323 | + | ||
324 | + def OnLinkSeed(self, evt): | ||
325 | + self.button_seeds.Toggle() | ||
326 | + self.SelectSeed() | ||
327 | + | ||
328 | + def OnButton(self, evt): | ||
329 | + if id == BTN_LARGEST: | ||
330 | + self.SelectLargest() | ||
331 | + elif id == BTN_SPLIT: | ||
332 | + self.SplitSurface() | ||
333 | + else: | ||
334 | + self.SelectSeed() | ||
335 | + | ||
336 | + def SelectLargest(self): | ||
337 | + index = self.combo_surface_name.GetSelection() | ||
338 | + ps.Publisher().sendMessage('Split surface by largest region', index) | ||
339 | + | ||
340 | + def SplitSurface(self): | ||
341 | + index = self.combo_surface_name.GetSelection() | ||
342 | + ps.Publisher().sendMessage('Create surface by largest region', index) | ||
343 | + | ||
344 | + def SelectSeed(self): | ||
345 | + if self.button_seeds.IsPressed(): | ||
346 | + self.StartSeeding() | ||
347 | + else: | ||
348 | + self.EndSeeding() | ||
349 | + | ||
350 | + def StartSeeding(self): | ||
351 | + index = self.combo_surface_name.GetSelection() | ||
352 | + ps.Publisher().sendMessage('Create surface by seeding - start', index) | ||
353 | + | ||
354 | + def EndSeeding(self): | ||
355 | + ps.Publisher().sendMessage('Create surface by seeding - end') | ||
356 | + | ||
357 | + | ||
358 | + | ||
229 | class SurfaceProperties(wx.Panel): | 359 | class SurfaceProperties(wx.Panel): |
230 | def __init__(self, parent): | 360 | def __init__(self, parent): |
231 | - wx.Panel.__init__(self, parent, size=(50,240)) | 361 | + wx.Panel.__init__(self, parent, size=(50,400)) |
232 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) | 362 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) |
233 | self.SetBackgroundColour(default_colour) | 363 | self.SetBackgroundColour(default_colour) |
234 | 364 | ||
@@ -252,8 +382,8 @@ class SurfaceProperties(wx.Panel): | @@ -252,8 +382,8 @@ class SurfaceProperties(wx.Panel): | ||
252 | 382 | ||
253 | # Sizer which represents the first line | 383 | # Sizer which represents the first line |
254 | line1 = wx.BoxSizer(wx.HORIZONTAL) | 384 | line1 = wx.BoxSizer(wx.HORIZONTAL) |
255 | - line1.Add(combo_surface_name, 1, wx.EXPAND|wx.GROW|wx.TOP|wx.RIGHT, 2) | ||
256 | - line1.Add(button_colour, 0, wx.TOP|wx.LEFT|wx.RIGHT, 2) | 385 | + line1.Add(combo_surface_name, 1, wx.LEFT|wx.EXPAND|wx.GROW|wx.TOP|wx.RIGHT, 7) |
386 | + line1.Add(button_colour, 0, wx.TOP|wx.RIGHT, 7) | ||
257 | 387 | ||
258 | 388 | ||
259 | ## LINE 2 | 389 | ## LINE 2 |
@@ -283,8 +413,9 @@ class SurfaceProperties(wx.Panel): | @@ -283,8 +413,9 @@ class SurfaceProperties(wx.Panel): | ||
283 | 413 | ||
284 | # Add all lines into main sizer | 414 | # Add all lines into main sizer |
285 | sizer = wx.BoxSizer(wx.VERTICAL) | 415 | sizer = wx.BoxSizer(wx.VERTICAL) |
286 | - sizer.Add(line1, 1, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) | ||
287 | - sizer.Add(fixed_sizer, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) | 416 | + sizer.Add(line1, 1, wx.GROW|wx.EXPAND|wx.TOP, 10) |
417 | + sizer.Add(fixed_sizer, 0, | ||
418 | +wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, 10) | ||
288 | #sizer.Add(cb, 0, wx.GROW|wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP|wx.BOTTOM, 5) | 419 | #sizer.Add(cb, 0, wx.GROW|wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP|wx.BOTTOM, 5) |
289 | sizer.Fit(self) | 420 | sizer.Fit(self) |
290 | 421 |
invesalius/gui/widgets/platebtn.py
@@ -686,6 +686,13 @@ class PlateButton(wx.PyControl): | @@ -686,6 +686,13 @@ class PlateButton(wx.PyControl): | ||
686 | 686 | ||
687 | self.PopupMenu(self._menu, (xpos, size[1] + adj)) | 687 | self.PopupMenu(self._menu, (xpos, size[1] + adj)) |
688 | 688 | ||
689 | + def Toggle(self): | ||
690 | + self._pressed = not self._pressed | ||
691 | + if self._pressed: | ||
692 | + self.SetState(PLATE_PRESSED) | ||
693 | + else: | ||
694 | + self.SetState(PLATE_NORMAL) | ||
695 | + | ||
689 | def ToggleState(self): | 696 | def ToggleState(self): |
690 | """Toggle button state""" | 697 | """Toggle button state""" |
691 | if self._state['cur'] != PLATE_PRESSED: | 698 | if self._state['cur'] != PLATE_PRESSED: |