def __init__(self, parent, caption, collapsed): """ :param parent: Parent window (FoldPanelItem) :param caption: Header caption (str) :param collapsed: Draw the CaptionBar collapsed or not (boolean) """ wx.Window.__init__(self, parent, wx.ID_ANY, pos=(0, 0), size=CAPTION_BAR_SIZE, style=wx.NO_BORDER) self.SetBackgroundStyle(wx.BG_STYLE_PAINT) # FIXME: on wx4 with GTK2, the background is always redrawn anyway, # which causes flickering, especially as the default background colour is # white. As a workaround, we set a less white background. self.SetBackgroundColour(BG_COLOUR_MAIN) self._collapsed = collapsed # The current state of the CaptionBar self._caption = caption self._mouse_hovering = False # Set Icons self._icon_size = wx.Size(16, 16) self._foldIcons = wx.ImageList(self._icon_size.x, self._icon_size.y) bmp = img.getBitmap("icon/arr_down.png") self._foldIcons.Add(bmp) bmp = img.getBitmap("icon/arr_right.png") self._foldIcons.Add(bmp) self.Bind(wx.EVT_PAINT, self.on_paint) if isinstance(self.Parent, FoldPanelItem): self.Bind(wx.EVT_MOUSE_EVENTS, self.on_mouse_event)
def _add_button(self, cls, img_prefix, tooltip=None): bmp = img.getBitmap("menu/" + img_prefix + ".png") bmpa = img.getBitmap("menu/" + img_prefix + "_a.png") bmph = img.getBitmap("menu/" + img_prefix + "_h.png") dimg = img.getImage("menu/" + img_prefix + ".png") darken_image(dimg, 0.5) bmpd = dimg.ConvertToBitmap() btn = cls(self.btn_panel, bitmap=bmp, size=(24, 24)) btn.bmpSelected = bmpa btn.bmpHover = bmph btn.bmpDisabled = bmpd if tooltip: btn.SetToolTip(tooltip) if self.orientation == wx.HORIZONTAL: f = wx.LEFT | wx.RIGHT | wx.TOP b = 5 else: f = wx.TOP | wx.BOTTOM | wx.ALIGN_CENTRE_HORIZONTAL b = 5 self.btn_sizer.Add(btn, border=b, flag=f) self.btn_panel.Layout() return btn
def __init__(self, parent, caption, collapsed): """ :param parent: Parent window (FoldPanelItem) :param caption: Header caption (str) :param collapsed: Draw the CaptionBar collapsed or not (boolean) """ wx.Window.__init__(self, parent, wx.ID_ANY, pos=(0, 0), size=CAPTION_BAR_SIZE, style=wx.NO_BORDER) if os.name == "nt": # Avoids flickering on windows, but prevents black background on Linux... # Confirmed: If this statement is not present, there is flickering on MS Windows self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self._collapsed = collapsed # The current state of the CaptionBar self._caption = caption self._mouse_hovering = False # Set Icons self._icon_size = wx.Size(16, 16) self._foldIcons = wx.ImageList(self._icon_size.x, self._icon_size.y) bmp = img.getBitmap("icon/arr_down.png") self._foldIcons.Add(bmp) bmp = img.getBitmap("icon/arr_right.png") self._foldIcons.Add(bmp) self.Bind(wx.EVT_PAINT, self.on_paint) if isinstance(self.Parent, FoldPanelItem): self.Bind(wx.EVT_MOUSE_EVENTS, self.on_mouse_event)
def OnInit(self): """ Initialize the GUI This method is automatically called from the :wx:`App` constructor """ gui.legend_logo = "legend_logo_delmic.png" if self._is_standalone: microscope = None gui.icon = img.getIcon("icon/ico_gui_viewer_256.png") gui.name = odemis.__shortname__ + " Viewer" if "delphi" == self._is_standalone: gui.logo = img.getBitmap("logo_delphi.png") gui.legend_logo = "legend_logo_delphi.png" else: gui.icon = img.getIcon("icon/ico_gui_full_256.png") gui.name = odemis.__shortname__ try: microscope = model.getMicroscope() except (IOError, Pyro4.errors.CommunicationError) as e: logging.exception("Failed to connect to back-end") msg = ("The Odemis GUI could not connect to the Odemis back-end:" "\n\n{0}\n\n" "Launch user interface anyway?").format(e) answer = wx.MessageBox(msg, "Connection error", style=wx.YES | wx.NO | wx.ICON_ERROR) if answer == wx.NO: sys.exit(1) microscope = None else: if microscope.role == "delphi": gui.logo = img.getBitmap("logo_delphi.png") gui.legend_logo = "legend_logo_delphi.png" # TODO: if microscope.ghost is not empty => wait and/or display a special # "hardware status" tab. if microscope and microscope.role == "mbsem": self.main_data = guimodel.FastEMMainGUIData(microscope) else: self.main_data = guimodel.MainGUIData(microscope) # Load the main frame self.main_frame = main_xrc.xrcfr_main(None) self.init_gui() try: from odemis.gui.dev.powermate import Powermate self.dev_powermate = Powermate(self.main_data) except (LookupError, NotImplementedError) as ex: logging.debug("Not using Powermate: %s", ex) except Exception: logging.exception("Failed to load Powermate support") # Application successfully launched return True
def test_image_button_align(self): # btn = buttons.ImageButton(self.panel, height=16, size=(100, -1), # icon=img.getBitmap("icon/ico_chevron_down.png")) # self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) btn = buttons.ImageButton(self.panel, height=32, size=(100, -1), icon=img.getBitmap("icon/ico_acqui.png"), style=wx.ALIGN_LEFT) self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) btn = buttons.ImageButton(self.panel, height=32, size=(100, -1), icon=img.getBitmap("icon/ico_acqui.png"), style=wx.ALIGN_CENTER) self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) btn = buttons.ImageButton(self.panel, height=32, size=(100, -1), icon=img.getBitmap("icon/ico_acqui.png"), style=wx.ALIGN_RIGHT) self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL)
def __init__(self, parent, wid=wx.ID_ANY, pos=(0, 0), size=wx.DefaultSize, style=wx.NO_BORDER, orientation=wx.HORIZONTAL): style |= wx.NO_BORDER wx.Panel.__init__(self, parent, wid, pos, size, style) self.SetBackgroundColour(parent.GetBackgroundColour()) self.SetForegroundColour(parent.GetForegroundColour()) self.tick_colour = wxcol_to_frgb(self.ForegroundColour) self.Bind(wx.EVT_PAINT, self.on_paint) self.Bind(wx.EVT_SIZE, self.on_size) self._orientation = orientation self._max_tick_width = 32 # Largest pixel width of any label in use self._tick_spacing = 120 if orientation == wx.HORIZONTAL else 80 self._unit = None self._lo_ellipsis = False self._hi_ellipsis = False self._lock_va = None # Explicitly set the min size if self._orientation == wx.HORIZONTAL: self.SetMinSize((-1, 32)) else: self.SetMinSize((42, -1)) # The following properties are volatile, meaning that they can change often self._value_range = None # 2 tuple with the minimum and maximum value self._tick_list = None # Lust of 2 tuples, containing the pixel position and value self._vtp_ratio = None # Ratio to convert value to pixel self._pixel_space = None # Number of available pixels # Axis lock button # This button allows a user to lock the scales from manipulation bmp = img.getBitmap("menu/btn_lock.png") bmpa = img.getBitmap("menu/btn_lock_a.png") bmph = img.getBitmap("menu/btn_lock.png") self.lockBtn = ImageToggleButton(self, pos=(0, 0), bitmap=bmp, size=(24, 24)) self.lockBtn.bmpSelected = bmpa self.lockBtn.bmpHover = bmph self.lockBtn.Hide() self.on_size() # Force a refresh if self._orientation == wx.HORIZONTAL: self.SetCursor(wx.Cursor(wx.CURSOR_SIZEWE)) else: self.SetCursor(wx.Cursor(wx.CURSOR_SIZENS))
def __init__(self, *args, **kwargs): labels = kwargs.pop('labels', []) choices = kwargs.pop('choices', []) wx.combo.OwnerDrawnComboBox.__init__(self, *args, **kwargs) # SetMargins allow the left margin to be set to 0, but the top # margin won't move and stays at the default -1. self.SetMargins(0, 0) self.SetForegroundColour(odemis.gui.FG_COLOUR_EDIT) # Even those this colour sets the right self.SetBackgroundColour(self.Parent.GetBackgroundColour()) icon = img.getBitmap("icon/arr_down_s.png") icon_x = 16 // 2 - icon.GetWidth() // 2 icon_y = (16 // 2) - (icon.GetHeight() // 2) - 1 bmpLabel = ImageButton._create_bitmap(img.getBitmap("button/btn_def_16.png"), (16, 16), self.GetBackgroundColour()) dc = wx.MemoryDC() dc.SelectObject(bmpLabel) dc.DrawBitmap(icon, icon_x, icon_y) dc.SelectObject(wx.NullBitmap) hover_image = bmpLabel.ConvertToImage() darken_image(hover_image, 1.1) dis_iamge = bmpLabel.ConvertToImage() darken_image(dis_iamge, 0.8) self.SetButtonBitmaps(bmpLabel, bmpHover=hover_image.ConvertToBitmap(), bmpDisabled=dis_iamge.ConvertToBitmap(), pushButtonBg=False) # self.Bind(wx.EVT_KEY_DOWN, self.on_key) self.Bind(wx.EVT_PAINT, self.on_paint) # If no labels are provided, create them from the choices if not labels and choices: labels = [unicode(c) for c in choices] for label, choice in zip(labels, choices): self.Append(label, choice) def _eat_event(evt): """ Quick and dirty empty function used to 'eat' mouse wheel events """ # TODO: This solution only makes sure that the control's value # doesn't accidentally get altered when it gets hit by a mouse # wheel event. However, it also stop the event from propagating # so the containing scrolled window will not scroll either. # (If the event is skipped, the control will change value again) # No easy fix found in wxPython 3.0. pass self.Bind(wx.EVT_MOUSEWHEEL, _eat_event)
def __init__(self, *args, **kwargs): kwargs['bitmap'] = img.getBitmap("overview_add.png") super(PlusImageButton, self).__init__(*args, **kwargs) self.SetForegroundColour(wx.WHITE) self.bmpSelected = img.getBitmap("overview_add_a.png") self.bmpHover = img.getBitmap("overview_add_h.png") btn_img = img.getImage("overview_add.png") darken_image(btn_img, 0.8) self.bmpDisabled = wx.Bitmap(btn_img)
def initialize_bitmaps(self): """ Initializes the check bitmaps. """ # We keep 4 bitmaps for CustomCheckBox, depending on the # checking state (Checked/UnCkecked) and the control # state (Enabled/Disabled). # FIXME: no such image self._bitmaps = { "CheckedEnable": img.getBitmap("btn_16x16.png"), "UnCheckedEnable": img.getBitmap("btn_16x16.png"), "CheckedDisable": grayOut(img.getImage("btn_16x16.png")), "UnCheckedDisable": grayOut(img.getImage("btn_16x16.png")) }
def _add_button(self, tool_id, cls, img_prefix, tooltip=None): bmp = img.getBitmap("menu/" + img_prefix + ".png") bmpa = img.getBitmap("menu/" + img_prefix + "_a.png") bmph = img.getBitmap("menu/" + img_prefix + "_h.png") dimg = img.getImage("menu/" + img_prefix + ".png") darken_image(dimg, 0.5) bmpd = dimg.ConvertToBitmap() btn = cls(self.btn_panel, bitmap=bmp, size=(24, 24)) btn.bmpSelected = bmpa btn.bmpHover = bmph btn.bmpDisabled = bmpd if tooltip: btn.SetToolTip(tooltip) if self.orientation == (wx.VERTICAL | wx.HORIZONTAL): # Ideal position for the known tools pos = { TOOL_RULER: (0, 0), TOOL_LABEL: (1, 0), TOOL_POINT: (0, 1), TOOL_LINE: (1, 1), TOOL_ACT_ZOOM_FIT: (2, 1) }.get(tool_id) # Unknown tool, or position already used => pick the first position available if not pos or self.btn_sizer.FindItemAtPosition(pos): for p in itertools.product( range(8), range(2)): # max 8 (height) x 2 (width) if not self.btn_sizer.FindItemAtPosition(p): pos = p break else: raise ValueError("No more space in toolbar") self.btn_sizer.Add(btn, pos, border=5, flag=wx.LEFT | wx.BOTTOM | wx.ALIGN_CENTRE_HORIZONTAL) elif self.orientation == wx.VERTICAL: self.btn_sizer.Add(btn, border=5, flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTRE_HORIZONTAL) else: # wx.HORIZONTAL self.btn_sizer.Add(btn, border=5, flag=wx.LEFT | wx.RIGHT | wx.TOP) self.btn_panel.Layout() return btn
def __init__(self, *args, **kwargs): wx.Panel.__init__(self, *args, **kwargs) self.SetBackgroundColour(self.Parent.GetBackgroundColour()) # Create orientation dependent objects if kwargs['style'] & wx.VERTICAL: self.orientation = wx.VERTICAL main_sizer = wx.BoxSizer(wx.VERTICAL) first_bmp = wx.StaticBitmap( self, -1, img.getBitmap("menu/side_menu_top.png")) second_bmp = wx.StaticBitmap( self, -1, img.getBitmap("menu/side_menu_bottom.png")) self.btn_sizer = wx.BoxSizer(wx.VERTICAL) else: self.orientation = wx.HORIZONTAL main_sizer = wx.BoxSizer(wx.HORIZONTAL) first_bmp = wx.StaticBitmap( self, -1, img.getBitmap("menu/side_menu_left.png")) second_bmp = wx.StaticBitmap( self, -1, img.getBitmap("menu/side_menu_right.png")) self.btn_sizer = wx.BoxSizer(wx.HORIZONTAL) # Set the main sizer that will contain the elements that will form # the toolbar bar. self.SetSizer(main_sizer) # Add the left or top image main_sizer.Add(first_bmp) # Create a panel that will hold the actual buttons self.btn_panel = wx.Panel(self, -1) self.btn_panel.SetBackgroundColour(wx.BLACK) self.btn_panel.SetSizer(self.btn_sizer) # Add the button panel to the toolbar main_sizer.Add(self.btn_panel) main_sizer.Add(second_bmp) if self.orientation == wx.VERTICAL: main_sizer.SetItemMinSize(self.btn_panel, 40, -1) else: main_sizer.SetItemMinSize(self.btn_panel, -1, 36) self._buttons = {} # References of va callbacks are stored in this list, to prevent un-subscription self._mode_callbacks = []
def __init__(self, *args, **kwargs): kwargs['style'] = kwargs.get('style', 0) | wx.ALIGN_CENTER kwargs['bitmap'] = img.getBitmap("tab_inactive.png") super(TabButton, self).__init__(*args, **kwargs) self.bmpHover = img.getBitmap("tab_hover.png") self.bmpSelected = img.getBitmap("tab_active.png") self.bmpDisabled = img.getBitmap("tab_disabled.png") self.fg_color_normal = "#FFFFFF" self.fg_color_dis = "#E0E0E0" self.SetForegroundColour(self.fg_color_normal) self.highlighted = False
def __init__(self, *args, **kwargs): super(ARLiveViewport, self).__init__(*args, **kwargs) # TODO: should be done on the fly by _checkMergeSliderDisplay() # change SEM icon to Goal if self.bottom_legend: self.bottom_legend.bmp_slider_right.SetBitmap( getBitmap("icon/ico_blending_goal.png"))
def _calc_overlay_size(self): """ Calculate the size the thumbnail overlay should be """ btn_width, btn_height = img.getBitmap("preview_block_a.png").Size total_border = self.thumbnail_border * 2 self.thumbnail_size.x = max( 1, btn_width - total_border - self.pointer_offset) self.thumbnail_size.y = max(1, btn_height - total_border)
def set_colour(self, colour): """ Change the background colour of the button :param colour: (3-tuple of 0<=int<=255) RGB values """ self.colour = colour self.bmpLabel = self.bmpSelected = self.bmpDisabled = self._create_colour_bitmap( ) if self.use_hover: bmp = wx.Bitmap(*self.Size) mdc = wx.MemoryDC() mdc.SelectObject(bmp) mdc.DrawBitmap(img.getBitmap("empty_h.png"), 0, 0) mdc.DrawBitmap(self.bmpLabel.GetSubBitmap((4, 4, 10, 10)), 4, 4) mdc.SelectObject(wx.NullBitmap) self.bmpHover = bmp else: self.bmpHover = self.bmpLabel self.Refresh()
def test_text_buttons(self): self.assertRaises(ValueError, buttons.ImageTextButton, self.panel, {'label': "blah"}) btn = buttons.ImageTextButton(self.panel, height=32) self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) btn = buttons.ImageTextToggleButton(self.panel, height=32, label="Toggle") self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) btn = buttons.ImageTextButton(self.panel, size=(300, -1), face_colour='blue', height=32, label="Wider!") btn.Disable() self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) btn = buttons.ImageTextButton(self.panel, size=(300, -1), height=32, label="Icon!") btn.SetIcon(img.getBitmap("icon/ico_ang.png")) btn.Disable() self.add_control(btn, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL) test.gui_loop()
def set_colour(self, colour): """ Change the background colour of the button :param colour: (3-tuple of 0<=int<=255) RGB values """ self.colour = colour self.bmpLabel = self.bmpSelected = self.bmpDisabled = self._create_colour_bitmap() if self.use_hover: bmp = wx.EmptyBitmap(*self.Size) mdc = wx.MemoryDC() mdc.SelectObject(bmp) mdc.DrawBitmap(img.getBitmap("empty_h.png"), 0, 0) mdc.DrawBitmap(self.bmpLabel.GetSubBitmap((4, 4, 10, 10)), 4, 4) mdc.SelectObject(wx.NullBitmap) self.bmpHover = bmp else: self.bmpHover = self.bmpLabel self.Refresh()
def __init__(self, *args, **kwargs): kwargs['bitmap'] = img.getBitmap("stream_add.png") super(PopupImageButton, self).__init__(*args, **kwargs) self.SetForegroundColour(wx.WHITE) self.bmpSelected = img.getBitmap("stream_add_a.png") self.bmpHover = img.getBitmap("stream_add_h.png") btn_img = img.getImage("stream_add.png") darken_image(btn_img, 0.8) self.bmpDisabled = wx.BitmapFromImage(btn_img) self.choices = {} self.menu = wx.Menu() self.Bind(wx.EVT_BUTTON, self.show_menu) self.Disable()
def __init__(self, *args, **kwargs): kwargs['bitmap'] = img.getBitmap("stream_add.png") super(PopupImageButton, self).__init__(*args, **kwargs) self.SetForegroundColour(wx.WHITE) self.bmpSelected = img.getBitmap("stream_add_a.png") self.bmpHover = img.getBitmap("stream_add_h.png") btn_img = img.getImage("stream_add.png") darken_image(btn_img, 0.8) self.bmpDisabled = wx.Bitmap(btn_img) self.choices = {} self.menu = wx.Menu() self.Bind(wx.EVT_BUTTON, self.show_menu) self.Disable()
def create_dialog(self, parent, id, pos, size, style, name, clear_btn): """ Setup the graphic representation of the dialog """ wx.Panel.__init__(self, parent, id, pos, size, style, name) self.SetBackgroundColour(parent.GetBackgroundColour()) box = wx.BoxSizer(wx.HORIZONTAL) self.text_ctrl = wx.TextCtrl(self, style=wx.BORDER_NONE | wx.TE_READONLY) self.text_ctrl.SetForegroundColour(odemis.gui.FG_COLOUR_EDIT) self.text_ctrl.SetBackgroundColour(odemis.gui.BG_COLOUR_MAIN) self.text_ctrl.Bind(wx.EVT_TEXT, self.on_changed) if self.file_path: self.SetValue(self.file_path) box.Add(self.text_ctrl, 1) if clear_btn: self._btn_clear = ImageButton( self, bitmap=img.getBitmap("icon/ico_clear.png"), pos=(10, 8)) self._btn_clear.bmpHover = img.getBitmap("icon/ico_clear_h.png") self._btn_clear.SetToolTipString( "Clear calibration") # FIXME: do not hard code self._btn_clear.Hide() self._btn_clear.Bind(wx.EVT_BUTTON, self._on_clear) box.Add(self._btn_clear, 0, wx.LEFT, 10) self.btn_ctrl = ImageTextButton(self, label="change...", height=16, style=wx.ALIGN_CENTER) self.btn_ctrl.Bind(wx.EVT_BUTTON, self._on_browse) box.Add(self.btn_ctrl, 0, wx.LEFT, 5) self.SetAutoLayout(True) self.SetSizer(box) self.Layout() if isinstance(size, tuple): size = wx.Size(size) self.SetDimensions(-1, -1, size.width, size.height, wx.SIZE_USE_EXISTING)
def __init__(self, *args, **kwargs): wx.Panel.__init__(self, *args, **kwargs) self.SetBackgroundColour(self.Parent.GetBackgroundColour()) # Create orientation dependent objects if kwargs['style'] & wx.VERTICAL: self.orientation = wx.VERTICAL main_sizer = wx.BoxSizer(wx.VERTICAL) first_bmp = wx.StaticBitmap(self, -1, img.getBitmap("menu/side_menu_top.png")) second_bmp = wx.StaticBitmap(self, -1, img.getBitmap("menu/side_menu_bottom.png")) self.btn_sizer = wx.BoxSizer(wx.VERTICAL) else: self.orientation = wx.HORIZONTAL main_sizer = wx.BoxSizer(wx.HORIZONTAL) first_bmp = wx.StaticBitmap(self, -1, img.getBitmap("menu/side_menu_left.png")) second_bmp = wx.StaticBitmap(self, -1, img.getBitmap("menu/side_menu_right.png")) self.btn_sizer = wx.BoxSizer(wx.HORIZONTAL) # Set the main sizer that will contain the elements that will form # the toolbar bar. self.SetSizer(main_sizer) # Add the left or top image main_sizer.Add(first_bmp) # Create a panel that will hold the actual buttons self.btn_panel = wx.Panel(self, -1) self.btn_panel.SetBackgroundColour(wx.BLACK) self.btn_panel.SetSizer(self.btn_sizer) # Add the button panel to the toolbar main_sizer.Add(self.btn_panel) main_sizer.Add(second_bmp) if self.orientation == wx.VERTICAL: main_sizer.SetItemMinSize(self.btn_panel, 40, -1) else: main_sizer.SetItemMinSize(self.btn_panel, -1, 36) self._buttons = {} # References of va callbacks are stored in this list, to prevent un-subscription self._mode_callbacks = []
def __init__(self, *args, **kwargs): """ :param parent: (wx.Window) parent window :param size: (int, int) button size """ kwargs['bitmap'] = img.getBitmap("preview_block.png") super(ViewButton, self).__init__(*args, **kwargs) self.bmpHover = img.getBitmap("preview_block_a.png") self.bmpSelected = img.getBitmap("preview_block_a.png") self.bmpDisabled = img.getBitmap("preview_block.png") self.thumbnail_bmp = None # The number of pixels from the right that need to be kept clear so the # 'arrow pointer' is visible. self.pointer_offset = 16 self.thumbnail_size = wx.Size() self._calc_overlay_size()
def __init__(self, *args, **kwargs): # The initial color to display self.colour = kwargs.pop('colour', None) or self.DEFAULT_COLOR # Determine if a hover effect needs to be used self.use_hover = kwargs.pop('use_hover', False) kwargs['size'] = kwargs.get('size', None) or (18, 18) kwargs['bitmap'] = img.getBitmap("empty.png") super(ColourButton, self).__init__(*args, **kwargs) self.set_colour(self.colour)
def DoCreateResource(self): assert self.GetInstance() is None # Now create the object new_ctrl = wx.adv.OwnerDrawnComboBox(self.GetParentAsWindow(), id=self.GetID(), pos=self.GetPosition(), size=self.GetSize(), style=self.GetStyle()) new_ctrl.SetButtonBitmaps(img.getBitmap("button/btn_down.png"), pushButtonBg=False) self.SetupWindow(new_ctrl) return new_ctrl
def __init__(self, parent, caption, collapsed): """ :param parent: Parent window (FoldPanelItem) :param caption: Header caption (str) :param collapsed: Draw the CaptionBar collapsed or not (boolean) """ wx.Window.__init__(self, parent, wx.ID_ANY, pos=(0, 0), size=CAPTION_BAR_SIZE, style=wx.NO_BORDER) self.SetBackgroundStyle(wx.BG_STYLE_PAINT) # FIXME: on wx4 with GTK2, the background is always redrawn anyway, # which causes flickering, especially as the default background colour is # white. As a workaround, we set a less white background. self.SetBackgroundColour(BG_COLOUR_MAIN) self._collapsed = collapsed # The current state of the CaptionBar self._caption = caption self._mouse_hovering = False self._logo = None # wx.Bitmap or None # Set Icons self._icon_size = wx.Size(16, 16) self._foldIcons = wx.ImageList(self._icon_size.x, self._icon_size.y) bmp = img.getBitmap("icon/arr_down.png") self._foldIcons.Add(bmp) bmp = img.getBitmap("icon/arr_right.png") self._foldIcons.Add(bmp) self.Bind(wx.EVT_PAINT, self.on_paint) if isinstance(self.Parent, FoldPanelItem): self.Bind(wx.EVT_MOUSE_EVENTS, self.on_mouse_event)
def create_dialog(self, parent, id, pos, size, style, name, clear_btn): """ Setup the graphic representation of the dialog """ wx.Panel.__init__(self, parent, id, pos, size, style, name) self.SetBackgroundColour(parent.GetBackgroundColour()) box = wx.BoxSizer(wx.HORIZONTAL) self.text_ctrl = wx.TextCtrl(self, style=wx.BORDER_NONE | wx.TE_READONLY) self.text_ctrl.SetForegroundColour(odemis.gui.FG_COLOUR_EDIT) self.text_ctrl.SetBackgroundColour(odemis.gui.BG_COLOUR_MAIN) self.text_ctrl.Bind(wx.EVT_TEXT, self.on_changed) if self.file_path: self.SetValue(self.file_path) box.Add(self.text_ctrl, 1) if clear_btn: self._btn_clear = ImageButton(self, bitmap=img.getBitmap("icon/ico_clear.png"), pos=(10, 8)) self._btn_clear.bmpHover = img.getBitmap("icon/ico_clear_h.png") self._btn_clear.SetToolTipString("Clear calibration") # FIXME: do not hard code self._btn_clear.Hide() self._btn_clear.Bind(wx.EVT_BUTTON, self._on_clear) box.Add(self._btn_clear, 0, wx.LEFT, 10) self.btn_ctrl = ImageTextButton(self, label="change...", height=16, style=wx.ALIGN_CENTER) self.btn_ctrl.Bind(wx.EVT_BUTTON, self._on_browse) box.Add(self.btn_ctrl, 0, wx.LEFT, 5) self.SetAutoLayout(True) self.SetSizer(box) self.Layout() if isinstance(size, tuple): size = wx.Size(size) self.SetDimensions(-1, -1, size.width, size.height, wx.SIZE_USE_EXISTING)
def set_stream_type(self, side, stream_class): """ Set the stream type, to put the right icon on the merge slider :param side: (wx.LEFT or wx.RIGHT): whether this set the left or right stream :param stream_class: (Stream (sub)class): the class of the stream """ for group_of_classes, class_icon in self._stream_to_icon: if issubclass(stream_class, group_of_classes): icon = class_icon break else: # Don't fail too bad icon = img.getBitmap("icon/ico_blending_opt.png") if self.merge_slider.IsShown(): logging.warning("Failed to find icon for stream of class %s", stream_class) if side == wx.LEFT: self.bmp_slider_left.SetBitmap(icon) else: self.bmp_slider_right.SetBitmap(icon)
def set_stream_type(self, side, acq_type): """ Set the stream type, to put the right icon on the merge slider :param side: (wx.LEFT or wx.RIGHT): whether this set the left or right stream :param acq_type: (String): acquisition type associated with stream """ for t, type_icon in self._type_to_icon: if acq_type == t: icon = type_icon break else: # Don't fail too bad icon = img.getBitmap("icon/ico_blending_opt.png") if self.merge_slider.IsShown(): logging.warning("Failed to find icon for stream of type %s", acq_type) if side == wx.LEFT: self.bmp_slider_left.SetBitmap(icon) else: self.bmp_slider_right.SetBitmap(icon)
def __init__(self, parent, wid=wx.ID_ANY, value=0.0, min_val=0.0, max_val=1.0, size=(-1, -1), pos=wx.DefaultPosition, style=wx.NO_BORDER, name="Slider", scale=None, **ignored): """ :param parent: Parent window. Must not be None. :param id: Slider identifier. :param pos: Slider position. If the position (-1, -1) is specified then a default position is chosen. :param size: Slider size. If the default size (-1, -1) is specified then a default size is chosen. :param style: use wx.Panel styles :param name: Window name. :param scale: 'linear' (default), 'cubic' or 'log' *Note*: Make sure to add any new option to the Slider ParamScale in xmlh.delmic! :param ignored: This is a way to catch all the extra keyword arguments that might be passed using a conf dict, but not have them cause exceptions (unexpected keyword argument) Events This slider produces two event. wx.EVT_SLIDER: This event continuously fires while the slider is being dragged wx.EVT_SCROLL_CHANGED: This event is fired *after* the dragging has ended """ super(Slider, self).__init__(parent, wid, pos, size, style) # Set minimum height if size == (-1, -1): self.SetMinSize((-1, 8)) self.name = name self.current_value = value # Closed range within which the current value must fall self.min_value = min_val self.max_value = max_val # event.GetX() position or Horizontal position across Panel self.x = 0 # position of the drag handle within the slider, ranging from 0 to # the slider width self.handlePos = 0 # Get Pointer's bitmap self.bitmap = img.getBitmap("slider.png") self.bitmap_dis = img.getBitmap("slider_dis.png") # Pointer dimensions self.handle_width, self.handle_height = self.bitmap.GetSize() self.half_h_width = self.handle_width // 2 self.half_h_height = self.handle_height // 2 if scale == "cubic": self._percentage_to_val = self._cubic_perc_to_val self._val_to_percentage = self._cubic_val_to_perc elif scale == "log": self._percentage_to_val = self._log_perc_to_val self._val_to_percentage = self._log_val_to_perc else: self._percentage_to_val = self._linear_prec_to_val self._val_to_percentage = self._linear_val_to_perc # Fire slide events at a maximum of once per '_fire_rate' seconds self._fire_rate = 0.05 self._fire_time = time.time() # Data events self.Bind(wx.EVT_MOTION, self.OnMotion) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost) # Layout Events self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SIZE, self.OnSize) # If the user is dragging the NumberSlider, and thus it has the mouse # captured, a call to SetValue will not result in the value of the # slider changing. This is to prevent the slider from jumping back and # forth, while the user is trying to drag. # A side effect of that is, that when another part of the system (e.g. # a VirtualAttribute) is trying to set the value, it will be ignored. # Instead of ignoring the value, it is now stored in the last_set # attribute, which is used to call _SetValue when the mouse button is # released (i.e. end of dragging). self.last_set = None
def _calc_overlay_size(self): """ Calculate the size the thumbnail overlay should be """ btn_width, btn_height = img.getBitmap("preview_block_a.png").Size total_border = self.thumbnail_border * 2 self.thumbnail_size.x = max(1, btn_width - total_border - self.pointer_offset) self.thumbnail_size.y = max(1, btn_height - total_border)
def __init__(self, parent, wid=-1, pos=(0, 0), size=wx.DefaultSize, style=wx.NO_BORDER): style = style | wx.NO_BORDER super(InfoLegend, self).__init__(parent, wid, pos, size, style) # Cannot be a constant because loading bitmaps only works after wx.App # has been created. self._stream_to_icon = ( (stream.ARStream, img.getBitmap("icon/ico_blending_ang.png")), (stream.SpectrumStream, img.getBitmap("icon/ico_blending_spec.png")), (stream.OpticalStream, img.getBitmap("icon/ico_blending_opt.png")), (stream.CLStream, img.getBitmap("icon/ico_blending_opt.png")), # same as optical (stream.EMStream, img.getBitmap("icon/ico_blending_sem.png")), (stream.RGBStream, img.getBitmap("icon/ico_blending_goal.png")), ) self.SetBackgroundColour(parent.GetBackgroundColour()) self.SetForegroundColour(parent.GetForegroundColour()) ### Create child windows # Merge slider # TODO: should be possible to use VAConnector self.merge_slider = Slider(self, wx.ID_ANY, 50, # val 0, 100, size=(100, 12), style=(wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_TICKS | wx.NO_BORDER) ) self.merge_slider.SetBackgroundColour(parent.GetBackgroundColour()) self.merge_slider.SetForegroundColour(FG_COLOUR_DIS) # "#4d4d4d" self.merge_slider.SetToolTipString("Merge ratio") self.bmp_slider_left = wx.StaticBitmap(self, wx.ID_ANY, img.getBitmap("icon/ico_blending_opt.png")) self.bmp_slider_right = wx.StaticBitmap(self, wx.ID_ANY, img.getBitmap("icon/ico_blending_sem.png")) # Horizontal Field Width text self.hfw_text = wx.TextCtrl(self, style=wx.NO_BORDER | wx.CB_READONLY) self.hfw_text.SetBackgroundColour(parent.GetBackgroundColour()) self.hfw_text.SetForegroundColour(parent.GetForegroundColour()) self.hfw_text.SetToolTipString("Horizontal Field Width") # Magnification text self.magnification_text = wx.TextCtrl(self, style=wx.NO_BORDER | wx.CB_READONLY) self.magnification_text.SetBackgroundColour(parent.GetBackgroundColour()) self.magnification_text.SetForegroundColour(parent.GetForegroundColour()) self.magnification_text.SetToolTipString("Magnification") # Scale window self.scale_win = ScaleWindow(self) # TODO more... # self.LegendWl = wx.StaticText(self.legend) # self.LegendWl.SetToolTipString("Wavelength") # self.LegendET = wx.StaticText(self.legend) # self.LegendET.SetToolTipString("Exposure Time") # self.LegendDwell = wx.StaticText(self.legend) # self.LegendSpot = wx.StaticText(self.legend) # self.LegendHV = wx.StaticText(self.legend) ## Child window layout # Sizer composition: # # +-------------------------------------------------------+ # | <Mag> | <HFW> | <Scale> | [Icon|Slider|Icon] | # +-------------------------------------------------------+ slider_sizer = wx.BoxSizer(wx.HORIZONTAL) # TODO: need to have the icons updated according to the streams type slider_sizer.Add( self.bmp_slider_left, 0, border=3, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) slider_sizer.Add( self.merge_slider, 1, flag=wx.ALIGN_CENTER | wx.EXPAND | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) slider_sizer.Add( self.bmp_slider_right, 0, border=3, flag=wx.ALIGN_CENTER | wx.LEFT | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) control_sizer = wx.BoxSizer(wx.HORIZONTAL) control_sizer.Add(self.magnification_text, 2, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(self.hfw_text, 2, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(self.scale_win, 3, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(slider_sizer, 0, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT) # legend_panel_sizer is needed to add a border around the legend border_sizer = wx.BoxSizer(wx.VERTICAL) border_sizer.Add(control_sizer, border=6, flag=wx.ALL | wx.EXPAND) self.SetSizerAndFit(border_sizer) ## Event binding # Dragging the slider should set the focus to the right view self.merge_slider.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.merge_slider.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) # Make sure that mouse clicks on the icons set the correct focus self.bmp_slider_left.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.bmp_slider_right.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) # Set slider to min/max self.bmp_slider_left.Bind(wx.EVT_LEFT_UP, parent.OnSliderIconClick) self.bmp_slider_right.Bind(wx.EVT_LEFT_UP, parent.OnSliderIconClick) self.hfw_text.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.magnification_text.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
def __init__(self, *args, **kwargs): super(ARLiveViewport, self).__init__(*args, **kwargs) # TODO: should be done on the fly by _checkMergeSliderDisplay() # change SEM icon to Goal if self.bottom_legend: self.bottom_legend.bmp_slider_right.SetBitmap(getBitmap("icon/ico_blending_goal.png"))
def __init__(self, parent, wid=-1, pos=(0, 0), size=wx.DefaultSize, style=wx.NO_BORDER): style = style | wx.NO_BORDER super(InfoLegend, self).__init__(parent, wid, pos, size, style) # Cannot be a constant because loading bitmaps only works after wx.App # has been created. self._type_to_icon = ( (MD_AT_AR, img.getBitmap("icon/ico_blending_ang.png")), (MD_AT_SPECTRUM, img.getBitmap("icon/ico_blending_spec.png")), (MD_AT_EM, img.getBitmap("icon/ico_blending_sem.png")), (MD_AT_OVV_TILES, img.getBitmap("icon/ico_blending_map.png")), (MD_AT_OVV_FULL, img.getBitmap("icon/ico_blending_navcam.png")), (MD_AT_HISTORY, img.getBitmap("icon/ico_blending_history.png")), (MD_AT_CL, img.getBitmap("icon/ico_blending_opt.png")), (MD_AT_FLUO, img.getBitmap("icon/ico_blending_opt.png")), (MD_AT_SLIT, img.getBitmap("icon/ico_blending_slit.png")), ) self.SetBackgroundColour(parent.GetBackgroundColour()) self.SetForegroundColour(parent.GetForegroundColour()) ### Create child windows # Merge slider # TODO: should be possible to use VAConnector self.merge_slider = Slider(self, wx.ID_ANY, 50, # val 0, 100, size=(100, 12), style=(wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_TICKS | wx.NO_BORDER) ) self.merge_slider.SetBackgroundColour(parent.GetBackgroundColour()) self.merge_slider.SetForegroundColour(FG_COLOUR_DIS) # "#4d4d4d" self.merge_slider.SetToolTip("Merge ratio") self.bmp_slider_left = wx.StaticBitmap(self, wx.ID_ANY, img.getBitmap("icon/ico_blending_opt.png")) self.bmp_slider_right = wx.StaticBitmap(self, wx.ID_ANY, img.getBitmap("icon/ico_blending_sem.png")) # Horizontal Field Width text self.hfw_text = wx.TextCtrl(self, style=wx.NO_BORDER | wx.CB_READONLY) self.hfw_text.SetBackgroundColour(parent.GetBackgroundColour()) self.hfw_text.SetForegroundColour(parent.GetForegroundColour()) self.hfw_text.SetToolTip("Horizontal Field Width") # Magnification text self.magnification_text = wx.TextCtrl(self, style=wx.NO_BORDER | wx.CB_READONLY) self.magnification_text.SetBackgroundColour(parent.GetBackgroundColour()) self.magnification_text.SetForegroundColour(parent.GetForegroundColour()) self.magnification_text.SetToolTip("Magnification") # Z position text self.zPos_text = wx.TextCtrl(self, style=wx.NO_BORDER | wx.CB_READONLY) self.zPos_text.SetBackgroundColour(parent.GetBackgroundColour()) self.zPos_text.SetForegroundColour(parent.GetForegroundColour()) self.zPos_text.SetToolTip("Z Position") self.zPos_text.Hide() # Scale window self.scale_win = ScaleWindow(self) ## Child window layout # Sizer composition: # # +-------------------------------------------------------+ # | <Mag> | <HFW> | <Scale> | [Icon|Slider|Icon] | # +-------------------------------------------------------+ slider_sizer = wx.BoxSizer(wx.HORIZONTAL) # TODO: need to have the icons updated according to the streams type slider_sizer.Add( self.bmp_slider_left, 0, border=3, flag=wx.ALIGN_CENTER | wx.RIGHT) slider_sizer.Add( self.merge_slider, 1, flag=wx.ALIGN_CENTER | wx.EXPAND) slider_sizer.Add( self.bmp_slider_right, 0, border=3, flag=wx.ALIGN_CENTER | wx.LEFT) control_sizer = wx.BoxSizer(wx.HORIZONTAL) control_sizer.Add(self.magnification_text, 2, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(self.hfw_text, 2, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(self.scale_win, 3, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(self.zPos_text, 2, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT | wx.EXPAND) control_sizer.Add(slider_sizer, 0, border=10, flag=wx.ALIGN_CENTER | wx.RIGHT) # border_sizer is needed to add a border around the legend border_sizer = wx.BoxSizer(wx.VERTICAL) border_sizer.Add(control_sizer, border=6, flag=wx.ALL | wx.EXPAND) self.SetSizerAndFit(border_sizer) ## Event binding # Dragging the slider should set the focus to the right view self.merge_slider.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.merge_slider.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) # Make sure that mouse clicks on the icons set the correct focus self.bmp_slider_left.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.bmp_slider_right.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) # Set slider to min/max self.bmp_slider_left.Bind(wx.EVT_LEFT_UP, parent.OnSliderIconClick) self.bmp_slider_right.Bind(wx.EVT_LEFT_UP, parent.OnSliderIconClick) self.hfw_text.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.magnification_text.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.zPos_text.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
def __init__(self, parent): wx.Panel.__init__(self, parent, style=wx.BORDER_SIMPLE) self.Bind(wx.EVT_PAINT, self.OnPaint) self.text = 'Hello World!' self.imgdata = img.getBitmap("canvasbg.png") self.offset = 5
def test_image_button(self): # No icon for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton(self.panel, height=h) btn.SetToolTip("No width defined") row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton(self.panel, height=h, size=(w, -1)) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton(self.panel, height=h) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2) # With icon for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton(self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png")) btn.SetToolTip("No width defined") row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton(self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png")) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton(self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png")) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2) # With icon, CENTER ALIGNED for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton(self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_CENTER) btn.SetToolTip("No width defined") btn.SetIcon(img.getBitmap("icon/ico_chevron_down.png")) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton(self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_CENTER) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton(self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_CENTER) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2) # With icon, RIGHT ALIGNED for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton(self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_RIGHT) btn.SetToolTip("No width defined") btn.SetIcon(img.getBitmap("icon/ico_chevron_down.png")) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton(self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_RIGHT) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton(self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_RIGHT) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2)
def __init__(self, *args, **kwargs): labels = kwargs.pop('labels', []) choices = kwargs.pop('choices', []) super(ComboBox, self).__init__(*args, **kwargs) # SetMargins allow the left margin to be set to 0, but the top # margin won't move and stays at the default -1. self.SetMargins(0, 0) self.SetForegroundColour(odemis.gui.FG_COLOUR_EDIT) # Use the same colour as the parent (by default) # HACK: there seems to be a bug in wxWidgets (v3.0.2), where # OwnerDrawnComboBox.GetBackgroundColour() always returns the same fixed # colour (in init?). So we cannot rely on it. bckcol = self.Parent.GetBackgroundColour() self.SetBackgroundColour(bckcol) icon = img.getBitmap("icon/arr_down_s.png") icon_x = 16 // 2 - icon.GetWidth() // 2 icon_y = 16 // 2 - icon.GetHeight() // 2 - 1 bmpLabel = ImageButton._create_bitmap(img.getImage("button/btn_def_16.png"), (16, 16), bckcol) dc = wx.MemoryDC() dc.SelectObject(bmpLabel) dc.DrawBitmap(icon, icon_x, icon_y) dc.SelectObject(wx.NullBitmap) hover_image = bmpLabel.ConvertToImage() darken_image(hover_image, 1.1) dis_image = bmpLabel.ConvertToImage() darken_image(dis_image, 0.8) orig_image = bmpLabel.ConvertToImage() darken_image(orig_image, 1.0) self.SetButtonBitmaps(orig_image.ConvertToBitmap(), bmpHover=hover_image.ConvertToBitmap(), bmpDisabled=dis_image.ConvertToBitmap(), pushButtonBg=False) # Convert losing the focus into accepting the new value typed in # (generates EVT_TEXT_ENTER). self._prev_text = None self._text_changed = False self.Bind(wx.EVT_TEXT, self._on_text) self.Bind(wx.EVT_COMBOBOX, self._on_text_enter) self.Bind(wx.EVT_TEXT_ENTER, self._on_text_enter) self.Bind(wx.EVT_KILL_FOCUS, self._on_focus) self.Bind(wx.EVT_PAINT, self.on_paint) # If no labels are provided, create them from the choices if not labels and choices: labels = [unicode(c) for c in choices] for label, choice in zip(labels, choices): self.Append(label, choice) def _eat_event(evt): """ Quick and dirty empty function used to 'eat' mouse wheel events """ # TODO: This solution only makes sure that the control's value # doesn't accidentally get altered when it gets hit by a mouse # wheel event. However, it also stop the event from propagating # so the containing scrolled window will not scroll either. # (If the event is skipped, the control will change value again) # No easy fix found in wxPython 3.0. pass self.Bind(wx.EVT_MOUSEWHEEL, _eat_event)
def test_image_button(self): # No icon for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton(self.panel, height=h) btn.SetToolTip("No width defined") row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton(self.panel, height=h, size=(w, -1)) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton(self.panel, height=h) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2) # With icon for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton( self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png")) btn.SetToolTip("No width defined") row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton( self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png")) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton( self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png")) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2) # With icon, CENTER ALIGNED for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton( self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_CENTER) btn.SetToolTip("No width defined") btn.SetIcon(img.getBitmap("icon/ico_chevron_down.png")) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton( self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_CENTER) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton( self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_CENTER) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2) # With icon, RIGHT ALIGNED for i, h in enumerate(BTN_SIZES): row_sizer = wx.BoxSizer(wx.HORIZONTAL) # Without explicit size btn = buttons.ImageButton( self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_RIGHT) btn.SetToolTip("No width defined") btn.SetIcon(img.getBitmap("icon/ico_chevron_down.png")) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) for w in BTN_WIDTHS: btn = buttons.ImageButton( self.panel, height=h, size=(w, -1), icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_RIGHT) btn.SetToolTip("Width set to %d" % w) row_sizer.Add(btn, flag=wx.LEFT | wx.RIGHT, border=2) self.add_control(row_sizer, flags=wx.ALL | wx.EXPAND, border=2) btn = buttons.ImageButton( self.panel, height=h, icon=img.getBitmap("icon/ico_chevron_down.png"), style=wx.ALIGN_RIGHT) btn.SetToolTip("Expand") self.add_control(btn, flags=wx.ALL | wx.EXPAND, border=2)
def add_bc_control(self, detector): """ Add Hw brightness/contrast control """ self.panel.add_divider() # Create extra gird bag sizer gb_sizer = wx.GridBagSizer() gb_sizer.SetEmptyCellSize((0, 0)) # Create the widgets btn_autoadjust = ImageTextToggleButton(self.panel, height=24, label="Auto adjust", icon=img.getBitmap("icon/ico_contrast.png")) btn_autoadjust.SetToolTip("Adjust detector brightness/contrast") gb_sizer.Add(btn_autoadjust, (0, 0), (2, 1), border=10, flag=wx.ALIGN_CENTRE_VERTICAL | wx.RIGHT) sld_conf = { "accuracy": 2, "event": wx.EVT_SCROLL_CHANGED, "control_type": odemis.gui.CONTROL_SLIDER, "type": "slider", } num_rows = 0 if model.hasVA(detector, "brightness"): brightness_entry = self.add_setting_entry("brightness", detector.brightness, detector, sld_conf) # TODO: 'Ugly' detaching somewhat nullifies the cleanliness created by using # 'add_setting_entry'. 'add_setting_entry' Needs some more refactoring anyway. self.panel.gb_sizer.Detach(brightness_entry.value_ctrl) self.panel.gb_sizer.Detach(brightness_entry.lbl_ctrl) gb_sizer.Add(brightness_entry.lbl_ctrl, (num_rows, 1)) gb_sizer.Add(brightness_entry.value_ctrl, (num_rows, 2), flag=wx.EXPAND) num_rows += 1 if model.hasVA(detector, "contrast"): contrast_entry = self.add_setting_entry("contrast", detector.contrast, detector, sld_conf) self.panel.gb_sizer.Detach(contrast_entry.value_ctrl) self.panel.gb_sizer.Detach(contrast_entry.lbl_ctrl) gb_sizer.Add(contrast_entry.lbl_ctrl, (num_rows, 1)) gb_sizer.Add(contrast_entry.value_ctrl, (num_rows, 2), flag=wx.EXPAND) num_rows += 1 if num_rows: gb_sizer.AddGrowableCol(2) # Add the extra sizer to the main sizer self.panel.gb_sizer.Add(gb_sizer, (self.panel.num_rows, 0), span=(1, 2), border=5, flag=wx.ALL | wx.EXPAND) self.panel.num_rows += 1 # Connect various events to the auto adjust button def on_chamber_state(state, btn=btn_autoadjust): wx.CallAfter(btn.Enable, state in (CHAMBER_UNKNOWN, CHAMBER_VACUUM)) # We keep a reference to keep the subscription active. self._subscriptions.append(on_chamber_state) self.tab_data.main.chamberState.subscribe(on_chamber_state, init=True) def adjust_done(_): """ Callback that enables and untoggles the 'auto adjust' contrast button """ btn_autoadjust.SetToggle(False) btn_autoadjust.SetLabel("Auto adjust") btn_autoadjust.Enable() brightness_entry.value_ctrl.Enable() contrast_entry.value_ctrl.Enable() def auto_adjust(_): """ Call the auto contrast method on the detector if it's not already running """ if not btn_autoadjust.up: f = detector.applyAutoContrast() btn_autoadjust.SetLabel("Adjusting...") btn_autoadjust.Disable() brightness_entry.value_ctrl.Disable() contrast_entry.value_ctrl.Disable() f.add_done_callback(adjust_done) btn_autoadjust.Bind(wx.EVT_BUTTON, auto_adjust)
def __init__(self, *args, **kwargs): labels = kwargs.pop('labels', []) choices = kwargs.pop('choices', []) super(ComboBox, self).__init__(*args, **kwargs) # SetMargins allow the left margin to be set to 0, but the top # margin won't move and stays at the default -1. self.SetMargins(0, 0) self.SetForegroundColour(odemis.gui.FG_COLOUR_EDIT) # Use the same colour as the parent (by default) # HACK: there seems to be a bug in wxWidgets (v3.0.2), where # OwnerDrawnComboBox.GetBackgroundColour() always returns the same fixed # colour (in init?). So we cannot rely on it. bckcol = self.Parent.GetBackgroundColour() self.SetBackgroundColour(bckcol) icon = img.getBitmap("icon/arr_down_s.png") icon_x = 16 // 2 - icon.GetWidth() // 2 icon_y = 16 // 2 - icon.GetHeight() // 2 - 1 bmpLabel = ImageButton._create_bitmap( img.getImage("button/btn_def_16.png"), (16, 16), bckcol) dc = wx.MemoryDC() dc.SelectObject(bmpLabel) dc.DrawBitmap(icon, icon_x, icon_y) dc.SelectObject(wx.NullBitmap) hover_image = bmpLabel.ConvertToImage() darken_image(hover_image, 1.1) dis_image = bmpLabel.ConvertToImage() darken_image(dis_image, 0.8) orig_image = bmpLabel.ConvertToImage() darken_image(orig_image, 1.0) self.SetButtonBitmaps(orig_image.ConvertToBitmap(), bmpHover=hover_image.ConvertToBitmap(), bmpDisabled=dis_image.ConvertToBitmap(), pushButtonBg=False) # Convert losing the focus into accepting the new value typed in # (generates EVT_TEXT_ENTER). self._prev_text = None self._text_changed = False self.Bind(wx.EVT_TEXT, self._on_text) self.Bind(wx.EVT_COMBOBOX, self._on_text_enter) self.Bind(wx.EVT_TEXT_ENTER, self._on_text_enter) self.Bind(wx.EVT_KILL_FOCUS, self._on_focus) self.Bind(wx.EVT_PAINT, self.on_paint) # If no labels are provided, create them from the choices if not labels and choices: labels = [str(c) for c in choices] for label, choice in zip(labels, choices): self.Append(label, choice) def _eat_event(evt): """ Quick and dirty empty function used to 'eat' mouse wheel events """ # TODO: This solution only makes sure that the control's value # doesn't accidentally get altered when it gets hit by a mouse # wheel event. However, it also stop the event from propagating # so the containing scrolled window will not scroll either. # (If the event is skipped, the control will change value again) # No easy fix found in wxPython 3.0. pass self.Bind(wx.EVT_MOUSEWHEEL, _eat_event)
def add_bc_control(self, detector): """ Add Hw brightness/contrast control """ self.panel.add_divider() # Create extra gird bag sizer gb_sizer = wx.GridBagSizer() gb_sizer.SetEmptyCellSize((0, 0)) # Create the widgets btn_autoadjust = ImageTextToggleButton( self.panel, height=24, label="Auto adjust", icon=img.getBitmap("icon/ico_contrast.png")) btn_autoadjust.SetToolTip("Adjust detector brightness/contrast") gb_sizer.Add(btn_autoadjust, (0, 0), (2, 1), border=10, flag=wx.ALIGN_CENTRE_VERTICAL | wx.RIGHT) sld_conf = { "accuracy": 2, "event": wx.EVT_SCROLL_CHANGED, "control_type": odemis.gui.CONTROL_SLIDER, "type": "slider", } num_rows = 0 if model.hasVA(detector, "brightness"): brightness_entry = self.add_setting_entry("brightness", detector.brightness, detector, sld_conf) # TODO: 'Ugly' detaching somewhat nullifies the cleanliness created by using # 'add_setting_entry'. 'add_setting_entry' Needs some more refactoring anyway. self.panel.gb_sizer.Detach(brightness_entry.value_ctrl) self.panel.gb_sizer.Detach(brightness_entry.lbl_ctrl) gb_sizer.Add(brightness_entry.lbl_ctrl, (num_rows, 1)) gb_sizer.Add(brightness_entry.value_ctrl, (num_rows, 2), flag=wx.EXPAND) num_rows += 1 if model.hasVA(detector, "contrast"): contrast_entry = self.add_setting_entry("contrast", detector.contrast, detector, sld_conf) self.panel.gb_sizer.Detach(contrast_entry.value_ctrl) self.panel.gb_sizer.Detach(contrast_entry.lbl_ctrl) gb_sizer.Add(contrast_entry.lbl_ctrl, (num_rows, 1)) gb_sizer.Add(contrast_entry.value_ctrl, (num_rows, 2), flag=wx.EXPAND) num_rows += 1 if num_rows: gb_sizer.AddGrowableCol(2) # Add the extra sizer to the main sizer self.panel.gb_sizer.Add(gb_sizer, (self.panel.num_rows, 0), span=(1, 2), border=5, flag=wx.ALL | wx.EXPAND) self.panel.num_rows += 1 # Connect various events to the auto adjust button def on_chamber_state(state, btn=btn_autoadjust): wx.CallAfter(btn.Enable, state in (CHAMBER_UNKNOWN, CHAMBER_VACUUM)) # We keep a reference to keep the subscription active. self._subscriptions.append(on_chamber_state) self.tab_data.main.chamberState.subscribe(on_chamber_state, init=True) @call_in_wx_main def adjust_done(_): """ Callback that enables and untoggles the 'auto adjust' contrast button """ btn_autoadjust.SetToggle(False) btn_autoadjust.SetLabel("Auto adjust") btn_autoadjust.Enable() brightness_entry.value_ctrl.Enable() contrast_entry.value_ctrl.Enable() def auto_adjust(_): """ Call the auto contrast method on the detector if it's not already running """ if not btn_autoadjust.up: f = detector.applyAutoContrast() btn_autoadjust.SetLabel("Adjusting...") btn_autoadjust.Disable() brightness_entry.value_ctrl.Disable() contrast_entry.value_ctrl.Disable() f.add_done_callback(adjust_done) btn_autoadjust.Bind(wx.EVT_BUTTON, auto_adjust)
def OnInit(self): """ Initialize the GUI This method is automatically called from the :wx:`App` constructor """ gui.legend_logo = "legend_logo_delmic.png" if self._is_standalone: microscope = None gui.icon = img.getIcon("icon/ico_gui_viewer_256.png") gui.name = odemis.__shortname__ + " Viewer" if "delphi" == self._is_standalone: gui.logo = img.getBitmap("logo_delphi.png") gui.legend_logo = "legend_logo_delphi.png" else: gui.icon = img.getIcon("icon/ico_gui_full_256.png") gui.name = odemis.__shortname__ try: microscope = model.getMicroscope() except (IOError, Pyro4.errors.CommunicationError) as e: logging.exception("Failed to connect to back-end") msg = ("The Odemis GUI could not connect to the Odemis back-end:" "\n\n{0}\n\n" "Launch user interface anyway?").format(e) answer = wx.MessageBox(msg, "Connection error", style=wx.YES | wx.NO | wx.ICON_ERROR) if answer == wx.NO: sys.exit(1) microscope = None else: if microscope.role == "delphi": gui.logo = img.getBitmap("logo_delphi.png") gui.legend_logo = "legend_logo_delphi.png" logging.info("\n\n************ Starting Odemis GUI ************\n") logging.info("Odemis GUI v%s (from %s)", odemis.__version__, __file__) logging.info("wxPython v%s", wx.version()) # TODO: if microscope.ghost is not empty => wait and/or display a special # "hardware status" tab. self.main_data = guimodel.MainGUIData(microscope) # Load the main frame self.main_frame = main_xrc.xrcfr_main(None) self.init_gui() try: from odemis.gui.dev.powermate import Powermate self.dev_powermate = Powermate(self.main_data) except (LookupError, NotImplementedError) as ex: logging.debug("Not using Powermate: %s", ex) except Exception: logging.exception("Failed to load Powermate support") # Application successfully launched return True