Ejemplo n.º 1
0
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self._id_to_window = {} # type: typing.Dict[int, wx.Frame]

        menu_item = self.Append(wx.ID_ANY, item='Reset window positions')
        self.Bind(wx.EVT_MENU, self.OnResetWindowPositions, menu_item)

        # A separator between the window menu items and the other
        # extra windows.
        self.AppendSeparator()

        # Add item to launch valueLogViewer (XXX: this should be
        # handled by some sort of plugin system and not hardcoded).
        from cockpit.util import valueLogger
        from cockpit.util import csv_plotter
        menu_item = self.Append(wx.ID_ANY, "Launch ValueLogViewer")
        logs = valueLogger.ValueLogger.getLogFiles()
        if not logs:
            menu_item.Enable(False)
        else:
            shell = sys.platform == 'win32'
            args = ['python', csv_plotter.__file__] + logs
            self.Bind(wx.EVT_MENU,
                      lambda e: subprocess.Popen(args, shell=shell),
                      menu_item)

        # This is only for the piDIO and executor, both of which are a
        # window to set lines high/low.  We should probably have a
        # general window for this which we could use for all executor
        # handlers (probably piDIO device should provide an executor
        # handler).
        for obj in chain(depot.getAllHandlers(), depot.getAllDevices()):
            if hasattr(obj, 'showDebugWindow'):
                label = 'debug %s (%s)' % (obj.name, obj.__class__.__name__)
                menu_item = self.Append(wx.ID_ANY, label)
                self.Bind(wx.EVT_MENU,
                          lambda e, obj=obj: obj.showDebugWindow(),
                          menu_item)

        # When the menu is created the windows don't exist yet so we
        # will update it each time the menu is open.
        self.Bind(wx.EVT_MENU_OPEN, self.OnMenuOpen)
Ejemplo n.º 2
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Find out what devices we have to work with.
        lightToggles = depot.getHandlersOfType(depot.LIGHT_TOGGLE)

        ## Maps LightSource handlers to their associated panels of controls.
        self.lightToPanel = dict()

        # Construct the UI.
        # Sizer for all controls. We'll split them into bottom half (light
        # sources) and top half (everything else).
        self.Sizer = wx.BoxSizer(wx.VERTICAL)

        # Panel for holding the non-lightsource controls.
        topPanel = wx.Panel(self)
        self.topPanel = topPanel
        topSizer = wx.BoxSizer(wx.VERTICAL)

        # A row of buttons for various actions we know we can take.
        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        # Abort button
        abortButton = wx.Button(topPanel, wx.ID_ANY, "abort")
        abortButton.SetLabelMarkup(
            "<span foreground='red'><big><b>ABORT</b></big></span>")
        abortButton.Bind(wx.EVT_BUTTON,
                         lambda event: events.publish(events.USER_ABORT))
        buttonSizer.Add(abortButton, 1, wx.EXPAND)
        # Experiment & review buttons
        for lbl, fn in (("Single-site\nexperiment",
                         lambda evt: singleSiteExperiment.showDialog(self)),
                        ("Multi-site\nexperiment",
                         lambda evt: multiSiteExperiment.showDialog(self)),
                        ("View last\nfile", self.onViewLastFile)):
            btn = wx.Button(topPanel, wx.ID_ANY, lbl)
            btn.Bind(wx.EVT_BUTTON, fn)
            buttonSizer.Add(btn, 1, wx.EXPAND)
        # Video mode button
        videoButton = wx.ToggleButton(topPanel, wx.ID_ANY, "Live")
        videoButton.Bind(wx.EVT_TOGGLEBUTTON,
                         lambda evt: cockpit.interfaces.imager.videoMode())
        events.subscribe(cockpit.events.VIDEO_MODE_TOGGLE,
                         lambda state: videoButton.SetValue(state))
        buttonSizer.Add(videoButton, 1, wx.EXPAND)

        # Snap image button
        snapButton = wx.Button(topPanel, wx.ID_ANY, "Snap\nimage")
        snapButton.Bind(
            wx.EVT_BUTTON,
            lambda evt: cockpit.interfaces.imager.imager.takeImage())
        buttonSizer.Add(snapButton, 1, wx.EXPAND)
        # Increase font size in top row buttons.
        for w in [child.GetWindow() for child in buttonSizer.Children]:
            w.SetFont(w.GetFont().Larger())
        topSizer.Add(buttonSizer)
        topSizer.AddSpacer(ROW_SPACER)

        # Make UIs for any other handlers / devices and insert them into
        # our window, if possible.
        # Light power things will be handled later.
        lightPowerThings = depot.getHandlersOfType(depot.LIGHT_POWER)
        lightPowerThings.sort(key=lambda l: l.wavelength)
        # Camera UIs are drawn seperately. Currently, they are drawn first,
        # but this separation may make it easier to implement cameras in
        # ordered slots, giving the user control over exposure order.
        cameraThings = depot.getHandlersOfType(depot.CAMERA)
        # Ignore anything that is handled specially.
        ignoreThings = lightToggles + lightPowerThings
        ignoreThings += cameraThings
        # Remove ignoreThings from the full list of devices.
        otherThings = list(depot.getAllDevices())
        otherThings.sort(key=lambda d: d.__class__.__name__)
        otherThings.extend(depot.getAllHandlers())
        rowSizer = wx.WrapSizer(wx.HORIZONTAL)

        # Add objective control
        # If only one objective device (usual), add to end of top row,
        # otherwise add to start of 2nd row.
        hs = depot.getHandlersOfType(depot.OBJECTIVE)
        if len(hs) == 1:
            buttonSizer.Add(mainPanels.ObjectiveControls(self.topPanel),
                            flag=wx.LEFT,
                            border=2)
        else:
            rowSizer.Add(mainPanels.ObjectiveControls(self.topPanel),
                         flag=wx.EXPAND)
            rowSizer.AddSpacer(COL_SPACER)
        ignoreThings.extend(hs)

        # Make the UI elements for the cameras.
        rowSizer.Add(mainPanels.CameraControlsPanel(self.topPanel),
                     flag=wx.EXPAND)
        rowSizer.AddSpacer(COL_SPACER)

        # Add light controls.
        lightfilters = sorted(depot.getHandlersOfType(depot.LIGHT_FILTER))
        ignoreThings.extend(lightfilters)

        # Add filterwheel controls.
        rowSizer.Add(mainPanels.FilterControls(self.topPanel), flag=wx.EXPAND)

        # Make the UI elements for eveything else.
        for thing in ignoreThings:
            if thing in otherThings:
                otherThings.remove(thing)
        for thing in sorted(otherThings):
            if depot.getHandler(thing, depot.CAMERA):
                # Camera UIs already drawn.
                continue
            item = thing.makeUI(topPanel)
            if item is not None:
                itemsizer = wx.BoxSizer(wx.VERTICAL)
                itemsizer.Add(
                    cockpit.gui.mainPanels.PanelLabel(topPanel, thing.name))
                itemsizer.Add(item, 1, wx.EXPAND)
                if rowSizer.GetChildren():
                    # Add a spacer.
                    rowSizer.AddSpacer(COL_SPACER)
                rowSizer.Add(itemsizer, flag=wx.EXPAND)

        topSizer.Add(rowSizer)
        topPanel.SetSizerAndFit(topSizer)

        self.Sizer.Add(topPanel, flag=wx.EXPAND)
        self.Sizer.AddSpacer(ROW_SPACER)

        ## Panel for holding light sources.
        self.Sizer.Add(mainPanels.LightControlsPanel(self), flag=wx.EXPAND)

        keyboard.setKeyboardHandlers(self)
        self.joystick = joystick.Joystick(self)

        self.SetDropTarget(viewFileDropTarget.ViewFileDropTarget(self))

        # Show the list of windows on right-click.
        self.Bind(wx.EVT_CONTEXT_MENU,
                  lambda event: keyboard.martialWindows(self))
Ejemplo n.º 3
0
def martialWindows(parent):
    menu = wx.Menu()

    menu_item = menu.Append(wx.ID_ANY, "Reset window positions")
    parent.Bind(wx.EVT_MENU, lambda e: wx.GetApp().SetWindowPositions(),
                menu_item)

    main_window = wx.GetApp().GetTopWindow()
    for window in wx.GetTopLevelWindows():
        if window is main_window:
            # Don't show this for the main window.
            continue
        if not window.GetTitle():
            # Sometimes we get bogus top-level windows; no idea why.
            # Just skip them.
            # \todo Figure out where these windows come from and either get
            # rid of them or fix them so they don't cause trouble here.
            continue

        subMenu = wx.Menu()

        def show_or_hide(evt, w=window):
            # The window might be hidden but maybe it's just iconized
            # (minimized), or maybe it's both.  If it's iconized we
            # need to restore it first
            if w.IsIconized():
                w.Restore()
                w.Show()
            else:
                w.Show(not w.IsShown())

        def raise_window(evt, w=window):
            # At least on Mac we need to call Show before Raise in
            # case the window is hidden (see issue #599).  It is not
            # yet clear what is wx expected behaviour.  See upstream
            # issue https://trac.wxwidgets.org/ticket/18762
            w.Show()
            w.Raise()

        menu_item = subMenu.Append(wx.ID_ANY, "Show/Hide")
        parent.Bind(wx.EVT_MENU, show_or_hide, menu_item)

        menu_item = subMenu.Append(wx.ID_ANY, "Raise to top")
        parent.Bind(wx.EVT_MENU, raise_window, menu_item)

        menu_item = subMenu.Append(wx.ID_ANY, "Move to mouse")
        parent.Bind(wx.EVT_MENU,
                    lambda e, w=window: w.SetPosition(wx.GetMousePosition()),
                    menu_item)

        menu.AppendSubMenu(subMenu, window.GetTitle())

    # Add item to launch valueLogViewer.
    from subprocess import Popen
    from sys import platform
    from cockpit.util import valueLogger
    from cockpit.util import csv_plotter
    menu_item = menu.Append(wx.ID_ANY, "Launch ValueLogViewer")
    logs = valueLogger.ValueLogger.getLogFiles()
    if not logs:
        menu_item.Enable(False)
    else:
        shell = platform == 'win32'
        args = ['python', csv_plotter.__file__] + logs
        parent.Bind(wx.EVT_MENU, lambda e: Popen(args, shell=shell), menu_item)

    for d in filter(lambda x: hasattr(x, "showDebugWindow"),
                    chain(depot.getAllHandlers(), depot.getAllDevices())):
        menu_item = menu.Append(
            wx.ID_ANY, 'debug  %s  %s' % (d.__class__.__name__, d.name))
        parent.Bind(wx.EVT_MENU, lambda e, d=d: d.showDebugWindow(), menu_item)

    cockpit.gui.guiUtils.placeMenuAtMouse(parent, menu)
Ejemplo n.º 4
0
def martialWindows(parent):
    primaryWindows = wx.GetApp().primaryWindows
    secondaryWindows = wx.GetApp().secondaryWindows
    otherWindows = [w for w in wx.GetTopLevelWindows() 
                        if w not in (primaryWindows + secondaryWindows)]
    # windows = wx.GetTopLevelWindows()
    menu = wx.Menu()
    menuId = 1000
    menu.Append(menuId, "Reset window positions")
    parent.Bind(wx.EVT_MENU,
                lambda e: wx.GetApp().SetWindowPositions(), id= menuId)
    menuId += 1
    #for i, window in enumerate(windows):
    for i, window in enumerate(primaryWindows):
        if not window.GetTitle():
            # Sometimes we get bogus top-level windows; no idea why.
            # Just skip them.
            # \todo Figure out where these windows come from and either get
            # rid of them or fix them so they don't cause trouble here.
            continue
        subMenu = wx.Menu()
        subMenu.Append(menuId, "Raise to top")
        parent.Bind(wx.EVT_MENU,
                    lambda e, window = window: window.Raise(),id=menuId)
        menuId += 1
        subMenu.Append(menuId, "Move to mouse")
        parent.Bind(wx.EVT_MENU,
                lambda e, window = window: window.SetPosition(wx.GetMousePosition()), id=menuId)
        menuId += 1
        subMenu.Append(menuId, "Move to top-left corner")
        parent.Bind(wx.EVT_MENU,
                lambda e, window = window: window.SetPosition((0, 0)),
                    id=menuId)
        menuId += 1
        # Some windows have very long titles (e.g. the Macro Stage View),
        # so just take the first 50 characters.
        if version.LooseVersion(wx.__version__) < version.LooseVersion('4'):
            menu.AppendMenu(menuId, str(window.GetTitle())[:50], subMenu)
        else:
            menu.AppendSubMenu(subMenu, str(window.GetTitle())[:50])
        menuId += 1

    menu.AppendSeparator()
    for i, window in enumerate(secondaryWindows):
        if not window.GetTitle():
            # Sometimes we get bogus top-level windows; no idea why.
            # Just skip them.
            # \todo Figure out where these windows come from and either get
            # rid of them or fix them so they don't cause trouble here.
            continue
        subMenu = wx.Menu()
        subMenu.Append(menuId, "Show/Hide")
        parent.Bind(wx.EVT_MENU,
                lambda e, window = window: ((window.Restore() and
                    (cockpit.util.userConfig.setValue('windowState'+window.GetTitle(),
                                               1)))
                                                if window.IsIconized() 
                                                else ((window.Show(not window.IsShown()) ) and (cockpit.util.userConfig.setValue('windowState'+window.GetTitle(),0)))), id=menuId)
        menuId += 1
        subMenu.Append(menuId, "Move to mouse")
        parent.Bind(wx.EVT_MENU,
                lambda e, window = window: window.SetPosition(wx.GetMousePosition()), id=menuId)
        menuId += 1
        # Some windows have very long titles (e.g. the Macro Stage View),
        # so just take the first 50 characters.
        if version.LooseVersion(wx.__version__) < version.LooseVersion('4'):
            menu.AppendMenu(menuId, str(window.GetTitle())[:50], subMenu)
        else:
            menu.AppendSubMenu(subMenu, str(window.GetTitle())[:50])
        menuId += 1

    # Add item to launch valueLogViewer.
    from subprocess import Popen
    from sys import platform
    from cockpit.util import valueLogger
    from cockpit.util import csv_plotter
    menu.Append(menuId, "Launch ValueLogViewer")
    logs = valueLogger.ValueLogger.getLogFiles()
    if not logs:
        menu.Enable(menuId, False)
    else:
        shell = platform == 'win32'
        args = ['python', csv_plotter.__file__] + logs
        parent.Bind(wx.EVT_MENU,
                    lambda e: Popen(args, shell=shell),
                    id = menuId)
    menuId += 1

    menu.AppendSeparator()
    for i, window in enumerate(otherWindows):
        if not window.GetTitle() or not window.IsShown():
            # Sometimes we get bogus top-level windows; no idea why.
            # Just skip them.
            # Also, some windows are hidden rather than destroyed
            # (e.g. the experiment setup window). Skip those, too.
            # \todo Figure out where these windows come from and either get
            # rid of them or fix them so they don't cause trouble here.
            continue
        subMenu = wx.Menu()
        subMenu.Append(menuId, "Raise to top")
        parent.Bind(wx.EVT_MENU,
                    lambda e, window = window: window.Raise(), id=menuId)
        menuId += 1
        subMenu.Append(menuId, "Move to mouse")
        parent.Bind(wx.EVT_MENU,
                    lambda e, window = window: window.SetPosition(wx.GetMousePosition()), id=menuId)
        menuId += 1
        subMenu.Append(menuId, "Move to top-left corner")
        parent.Bind(wx.EVT_MENU,
                lambda e, window = window: window.SetPosition((0, 0))
                    , id=menuId)
        menuId += 1
        # Some windows have very long titles (e.g. the Macro Stage View),
        # so just take the first 50 characters.
        try:
            menu.Append(menuId, str(window.GetTitle())[:50], subMenu)
        except TypeError as e:
            # Sometimes, windows created late (e.g. wx InspectionTool) cause
            # a weird error here: menu.Append throws a type error, insisting
            # it needs a String or Unicode type, despite being passed a String
            # or Unicode type.
            print ("Omitting %s from window - weird wx string/unicode type error." % window.GetTitle())
        menuId += 1

    for d in filter(lambda x: hasattr(x, "showDebugWindow"),
                    chain(depot.getAllHandlers(), depot.getAllDevices())):
        menu.Append(menuId, 'debug  %s  %s' % (d.__class__.__name__, d.name ))
        parent.Bind(wx.EVT_MENU,
                    lambda e, d=d: d.showDebugWindow(),
                    id=menuId)
        menuId += 1

    cockpit.gui.guiUtils.placeMenuAtMouse(parent, menu)