def OnKeyDown(self, evt): """Capture the keypress when the notebook tab is focused. Currently this is used to workaround a bug in Windows since the notebook tab instead of the panel receives focus.""" if guiutil.IsMSWindows(): pub.sendMessage('main.key_down', msg=evt)
def OnMouseWheel(self, evt): """Capture the mousewheel event when the notebook tab is focused. Currently this is used to workaround a bug in Windows since the notebook tab instead of the panel receives focus.""" if guiutil.IsMSWindows(): pub.sendMessage('main.mousewheel', msg=evt)
def OnKeyDown(self, evt): """Change the image when the user presses the appropriate keys.""" # Needed to work around a bug in Windows. See main.py for more details. if guiutil.IsMSWindows(): try: evt = evt.data except AttributeError: keyname = evt.GetKeyCode() if len(self.images): keyname = evt.GetKeyCode() prevkey = [wx.WXK_UP, wx.WXK_PAGEUP] nextkey = [wx.WXK_DOWN, wx.WXK_PAGEDOWN] zoominkey = [43, 61, 388] # Keys: +, =, Numpad add zoomoutkey = [45, 95, 390] # Keys: -, _, Numpad subtract if (keyname in prevkey): if (self.imagenum > 1): self.imagenum -= 1 self.Refresh() if (keyname in nextkey): if (self.imagenum < len(self.images)): self.imagenum += 1 self.Refresh() if (keyname == wx.WXK_HOME): self.imagenum = 1 self.Refresh() if (keyname == wx.WXK_END): self.imagenum = len(self.images) self.Refresh() if (keyname in zoominkey): self.OnZoomIn(None) if (keyname in zoomoutkey): self.OnZoomOut(None)
def Init(self, plugins, pluginsDisabled): """Method called after the panel has been initialized.""" # Set window icon if not guiutil.IsMac(): self.SetIcon(guiutil.get_icon()) # Initialize controls self.tcPlugins = XRCCTRL(self, 'tcPlugins') self.panelTreeView = XRCCTRL(self, 'panelTreeView') self.panelProperties = XRCCTRL(self, 'panelProperties') self.lblName = XRCCTRL(self, 'lblName') self.lblAuthor = XRCCTRL(self, 'lblAuthor') self.lblPluginType = XRCCTRL(self, 'lblPluginType') self.lblVersion = XRCCTRL(self, 'lblVersion') self.lblVersionNumber = XRCCTRL(self, 'lblVersionNumber') self.lblDescription = XRCCTRL(self, 'lblDescription') self.checkEnabled = XRCCTRL(self, 'checkEnabled') self.lblMessage = XRCCTRL(self, 'lblMessage') self.btnGetMorePlugins = XRCCTRL(self, 'btnGetMorePlugins') self.btnDeletePlugin = XRCCTRL(self, 'btnDeletePlugin') self.plugins = plugins self.pluginsDisabled = set(pluginsDisabled) # Bind interface events to the proper methods # wx.EVT_BUTTON(self, XRCID('btnDeletePlugin'), self.DeletePlugin) wx.EVT_CHECKBOX(self, XRCID('checkEnabled'), self.OnEnablePlugin) wx.EVT_TREE_ITEM_ACTIVATED(self, XRCID('tcPlugins'), self.OnEnablePlugin) wx.EVT_TREE_SEL_CHANGED(self, XRCID('tcPlugins'), self.OnSelectTreeItem) wx.EVT_TREE_SEL_CHANGING(self, XRCID('tcPlugins'), self.OnSelectRootItem) # Modify the control and font size as needed font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) if guiutil.IsMac(): children = list(self.Children) + \ list(self.panelTreeView.Children) + \ list(self.panelProperties.Children) for control in children: control.SetFont(font) control.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) XRCCTRL(self, 'wxID_OK').SetWindowVariant(wx.WINDOW_VARIANT_NORMAL) font.SetWeight(wx.FONTWEIGHT_BOLD) if guiutil.IsMSWindows(): self.tcPlugins.SetPosition((0, 3)) self.panelTreeView.SetWindowStyle(wx.STATIC_BORDER) if (guiutil.IsMac() or guiutil.IsGtk()): self.tcPlugins.SetPosition((-30, 0)) self.panelTreeView.SetWindowStyle(wx.SUNKEN_BORDER) self.lblName.SetFont(font) self.lblMessage.SetFont(font) self.Layout() self.InitPluginList() self.LoadPlugins()
def OnMouseMotion(self, evt): """Process mouse motion events and pass to the appropriate handler.""" if evt.LeftIsDown(): self.OnLeftIsDown(evt) self.SetCursor(wx.Cursor(wx.CURSOR_SIZING)) elif evt.RightIsDown(): self.OnRightIsDown(evt) # Custom cursors with > 2 colors only works on Windows currently if guiutil.IsMSWindows(): image = wx.Image(util.GetResourcePath('contrast_high.png')) self.SetCursor(wx.CursorFromImage(image)) # Update the positon and values of the mouse cursor self.mousepos = evt.GetPosition() self.OnUpdatePositionValues(evt)
def OnUnfocus(self): """Unbind to certain events when the plugin is unfocused.""" # Unbind keyboard and mouse events self.Unbind(wx.EVT_KEY_DOWN) self.Unbind(wx.EVT_MOUSEWHEEL) self.Unbind(wx.EVT_LEFT_DOWN) self.Unbind(wx.EVT_LEFT_UP) self.Unbind(wx.EVT_RIGHT_DOWN) self.Unbind(wx.EVT_RIGHT_UP) self.Unbind(wx.EVT_MOTION) if guiutil.IsMSWindows(): pub.unsubscribe(self.OnKeyDown, 'main.key_down') pub.unsubscribe(self.OnMouseWheel, 'main.mousewheel') pub.unsubscribe(self.OnRefresh, '2dview.refresh')
def OnFocus(self): """Bind to certain events when the plugin is focused.""" # Bind keyboard and mouse events self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown) self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp) self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseDown) self.Bind(wx.EVT_RIGHT_UP, self.OnMouseUp) self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) if guiutil.IsMSWindows(): pub.subscribe(self.OnKeyDown, 'main.key_down') pub.subscribe(self.OnMouseWheel, 'main.mousewheel')
def OnLicense(self, evt): """Show the license document in a new dialog.""" f = open(util.get_text_resources("license.txt"), "rU") msg = f.read() f.close() if guiutil.IsMSWindows(): dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg, "dicompyler License") else: dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg, "dicompyler License", size=(650, 550)) dlg.ShowModal() dlg.Destroy()
def OnMouseWheel(self, evt): """Change the image when the user scrolls the mouse wheel.""" # Needed to work around a bug in Windows. See main.py for more details. if guiutil.IsMSWindows(): try: evt = evt.data except AttributeError: delta = evt.GetWheelDelta() rot = evt.GetWheelRotation() if len(self.images): delta = evt.GetWheelDelta() rot = evt.GetWheelRotation() rot = rot/delta if (rot >= 1): if (self.imagenum > 1): self.imagenum -= 1 self.Refresh() if (rot <= -1): if (self.imagenum < len(self.images)): self.imagenum += 1 self.Refresh()
def OnPaint(self, evt): """Update the panel when it needs to be refreshed.""" # Bind motion event when the panel has been painted to avoid a blank # image on Windows if a file is loaded too quickly before the plugin # is initialized self.Bind(wx.EVT_MOTION, self.OnMouseMotion) # Special case for Windows to account for flickering # if and only if images are loaded if (guiutil.IsMSWindows() and len(self.images)): dc = wx.BufferedPaintDC(self) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) else: dc = wx.PaintDC(self) width, height = self.GetClientSize() try: gc = wx.GraphicsContext.Create(dc) except NotImplementedError: dc.DrawText( "This build of wxPython does not support the " "wx.GraphicsContext family of classes.", 25, 25) return # If we have images loaded, process and show the image if len(self.images): # Save the original drawing state gc.PushState() # Scale the image by the zoom factor gc.Scale(self.zoom, self.zoom) # Redraw the background on Windows if guiutil.IsMSWindows(): gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0))) gc.SetPen(wx.Pen(wx.Colour(0, 0, 0))) gc.DrawRectangle(0, 0, width, height) image = guiutil.convert_pil_to_wx( self.images[self.imagenum - 1].GetImage( self.window, self.level)) bmp = wx.Bitmap(image) self.bwidth, self.bheight = image.GetSize() # Center the image transx = self.pan[0] + (width - self.bwidth * self.zoom) / (2 * self.zoom) transy = self.pan[1] + (height - self.bheight * self.zoom) / (2 * self.zoom) gc.Translate(transx, transy) gc.DrawBitmap(bmp, 0, 0, self.bwidth, self.bheight) gc.SetBrush(wx.Brush(wx.Colour(0, 0, 255, 30))) gc.SetPen(wx.Pen(wx.Colour(0, 0, 255, 30))) # Draw the structures if present imdata = self.images[self.imagenum - 1].GetImageData() self.z = '%.2f' % imdata['position'][2] # Determine whether the patient is prone or supine if 'p' in imdata['patientposition'].lower(): prone = True else: prone = False # Determine whether the patient is feet first or head first if 'ff' in imdata['patientposition'].lower(): feetfirst = True else: feetfirst = False for id, structure in self.structures.items(): self.DrawStructure(structure, gc, self.z, prone, feetfirst) # Draw the isodoses if present if len(self.isodoses): grid = self.dose.GetDoseGrid(float(self.z)) if not (grid == []): x, y = np.meshgrid(np.arange(grid.shape[1]), np.arange(grid.shape[0])) # Instantiate the isodose generator for this slice isodosegen = cntr.Cntr(x, y, grid) for id, isodose in iter(sorted(self.isodoses.items())): self.DrawIsodose(isodose, gc, isodosegen) # Restore the translation and scaling gc.PopState() # Prepare the font for drawing the information text font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) if guiutil.IsMac(): font.SetPointSize(10) gc.SetFont(font, wx.WHITE) # Draw the information text imtext = "Image: " + str(self.imagenum) + "/" + str( len(self.images)) te = gc.GetFullTextExtent(imtext) gc.DrawText(imtext, 10, 7) impos = "Position: " + str(self.z) + " mm" gc.DrawText(impos, 10, 7 + te[1] * 1.1) if ("%.3f" % self.zoom == "1.000"): zoom = "1" else: zoom = "%.3f" % self.zoom imzoom = "Zoom: " + zoom + ":1" gc.DrawText(imzoom, 10, height - 17) imsize = "Image Size: " + str(self.bheight) + "x" + str( self.bwidth) + " px" gc.DrawText(imsize, 10, height - 17 - te[1] * 1.1) imwinlevel = "W/L: " + str(self.window) + ' / ' + str(self.level) te = gc.GetFullTextExtent(imwinlevel) gc.DrawText(imwinlevel, width - te[0] - 7, 7) impatpos = "Patient Position: " + imdata['patientposition'] te = gc.GetFullTextExtent(impatpos) gc.DrawText(impatpos, width - te[0] - 7, height - 17) # Send message with the current image number and various properties pub.sendMessage( '2dview.updated.image', msg={ 'number': self.imagenum, # slice number 'z': self.z, # slice location 'window': self.window, # current window value 'level': self.level, # curent level value 'gc': gc, # wx.GraphicsContext 'scale': self.zoom, # current zoom level 'transx': transx, # current x translation 'transy': transy, # current y translation 'imdata': imdata, # image data dictionary 'patientpixlut': self.structurepixlut })