Exemplo n.º 1
0
class App(wx.App):

    """
    Core application class.

    Use App.main() to run the application.

    :ivar args: command line arguments
    """

    version = _version
    usage = _usage

    entry_points = """
        [madgui.core.app.init]
        mainframe = madgui.core.mainframe:MainFrame

        [madgui.core.mainframe.menu]
        online_control = madgui.online.control:Control

        [madgui.widget.figure.init]
        matchtool = madgui.component.matchtool:MatchTool
        selecttool = madgui.component.selecttool:SelectTool
        comparetool = madgui.component.comparetool:CompareTool
        statusbar = madgui.component.lineview:UpdateStatusBar.create

        [madgui.component.matching.start]
        drawconstraints = madgui.component.lineview:DrawConstraints
    """

    @classmethod
    def main(cls, argv=None):
        """
        Create an application instance and run the MainLoop.

        :param list argv: command line parameters
        """
        from docopt import docopt
        args = docopt(cls.usage, argv, version=cls.version)
        conf = load_config(args['--config'])
        cls(args, conf).MainLoop()

    def __init__(self, args=None, conf=None):
        """
        Create an application instance.

        :param dict args: preprocessed command line parameters
        """
        self.hook = HookCollection(
            init='madgui.core.app.init')
        self.args = args
        self.conf = conf
        self.dist = working_set.find(Requirement.parse('madgui'))
        self.add_entry_points(self.entry_points)
        # Add all entry point maps (strings like `App.entry_point` above) that
        # are registered under 'madgui.entry_points'. This indirection renders
        # the plugin mechanism more dynamic and allows plugins to be defined
        # more easily by eliminating the need to execute 'setup.py' each time
        # an entrypoint is added, changed or removed. Instead, their setup
        # step only needs to create a single entrypoint which is less likely
        # to change.
        for ep in iter_entry_points('madgui.entry_points'):
            self.add_entry_points(ep.load())
        super(App, self).__init__(redirect=False)

    def OnInit(self):
        """Initialize the application and create main window."""
        # allow plugin components to create stuff (frame!)
        self.hook.init(self)
        # signal wxwidgets to enter the main loop
        return True

    def add_entry_points(self, entry_map_section):
        """Add entry points."""
        recursive_merge(
            self.dist.get_entry_map(),
            EntryPoint.parse_map(entry_map_section, self.dist))
Exemplo n.º 2
0
class FigurePanel(wx.Panel):

    """
    Display panel for a matplotlib figure.
    """

    def __init__(self, parent, view, **kwargs):

        """
        Initialize panel and connect the view.

        Extends wx.App.__init__.
        """

        self.hook = HookCollection(
            init='madgui.widget.figure.init',
            capture_mouse=None)

        super(FigurePanel, self).__init__(parent, **kwargs)

        self.capturing = False
        self.view = view

        # couple figure to canvas
        self.canvas = Canvas(self, -1, view.figure.figure)
        view.canvas = self.canvas

        # create a toolbar
        self.toolbar = Toolbar(self.canvas)
        self.hook.init(self)
        self.toolbar.Realize()

        # put elements into sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND)
        sizer.Add(self.toolbar, 0 , wx.LEFT | wx.EXPAND)
        self.SetSizer(sizer)

        # setup mouse capturing
        self.hook.capture_mouse.connect(self.on_capture_mouse)
        self.toolbar.Bind(wx.EVT_TOOL,
                          self.on_zoom_or_pan,
                          id=self.get_zoom_id())
        self.toolbar.Bind(wx.EVT_TOOL,
                          self.on_zoom_or_pan,
                          id=self.get_pan_id())

        # get notified when frame is destroyed
        self.Bind(wx.EVT_WINDOW_DESTROY, self.on_destroy)

    def on_destroy(self, event):
        """Invoked when C++ window is destroyed."""
        self.view.destroy()

    def on_zoom_or_pan(self, event):
        """Capture mouse, after Zoom/Pan tools were clicked."""
        if event.IsChecked():
            self.capturing = True
            self.hook.capture_mouse()
            self.capturing = False
        event.Skip()

    def on_capture_mouse(self):
        """Disable Zoom/Pan tools when someone captures the mouse."""
        if self.capturing:
            return
        zoom_id = self.get_zoom_id()
        if self.toolbar.GetToolState(zoom_id):
            self.toolbar.zoom()
            self.toolbar.ToggleTool(zoom_id, False)
        pan_id = self.get_pan_id()
        if self.toolbar.GetToolState(pan_id):
            self.toolbar.pan()
            self.toolbar.ToggleTool(pan_id, False)

    def get_pan_id(self):
        try:
            return self.toolbar.wx_ids['Pan']
        except AttributeError:
            return self.toolbar._NTB2_PAN

    def get_zoom_id(self):
        try:
            return self.toolbar.wx_ids['Zoom']
        except AttributeError:
            return self.toolbar._NTB2_ZOOM