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))
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