Example #1
0
File: gui.py Project: hastern/jelly
    def prepare(self, title="Jelly Application", size=(1200, 700)):
        """Prepare the window, by loading all views and menu-entires.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  title: str
        @param title: The title of the window

        @type  size: tuple
        @param size: The default size of the window
        """
        self.wHnd = wx.Frame(None, wx.NewId(), title, size=size, style=wx.DEFAULT_FRAME_STYLE)
        self.onWHndCreate()

        self.menu = MenuBuilder(self.wHnd, self)
        self.view = ViewBuilder(self.wHnd, self)
        self.view.createView()
        self.wHnd.SetMenuBar(self.menu.build())
        self.statusbar = self.wHnd.CreateStatusBar()

        self.wHnd.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_CLOSE)
        self.wHnd.Bind(wx.EVT_SIZE, self.update)
        self.wHnd.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        entries = []
        entries.extend(self.shortcutIds)
        entries.extend(self.view.getShortcutIds())
        entries.extend(self.menu.getShortcutIds())
        specialMapping = {wx.ACCEL_CTRL: "CTRL + ", wx.ACCEL_SHIFT: "Shift + ", wx.ACCEL_NORMAL: ""}
        keyMapping = {id: "F{}".format(i) for id, i in zip([wx.WXK_F1, wx.WXK_F2, wx.WXK_F3, wx.WXK_F4, wx.WXK_F5, wx.WXK_F6, wx.WXK_F7, wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11, wx.WXK_F12], itertools.count(1))}
        for special, key, func in itertools.chain(self.shortcuts, self.view.getShortcuts(), self.menu.getShortcuts()):
            logger.debug("Registering Shortcut {}{} to method {}".format(specialMapping[special], keyMapping[key] if key in keyMapping else chr(key), func))
            id = wx.NewId()
            entries.append((special, key, id))
            self.wHnd.Bind(wx.EVT_MENU, func, id=id)
        self.acceleratorTable = wx.AcceleratorTable(entries)
        self.wHnd.SetAcceleratorTable(self.acceleratorTable)

        self.SetTopWindow(self.wHnd)

        self.onPrepare()

        return self.wHnd
Example #2
0
File: gui.py Project: hastern/jelly
class InterfaceBuilder(wx.App):
    """Jelly Interface Builder

    The interface builder is the application's core.
    It inherits from `wx.App` and behaves as one.

    The interface builder houses a `MenuBuilder` and `ViewBuilder` which form
    the interface. It will automatically load all available views and menus
    (meaning: in any loaded module).
    """
    __metaclass__ = MixinMount

    def __init__(self, *args, **kwargs):
        """

        @type  self: InterfaceBuilder
        @param self: The class instance
        """
        logger.debug("Initialize interface builder")
        self.helpProvider = wx.SimpleHelpProvider()
        wx.HelpProvider_Set(self.helpProvider)
        logger.info("Starting wxPython")
        wx.App.__init__(self, redirect=False)
        self.wHnd = None
        self.suppress_dialogs = False

        self.shortcuts = [
            (wx.ACCEL_NORMAL, wx.WXK_F5, self.update),
        ]
        self.shortcutIds = [
            (wx.ACCEL_CTRL, ord('q'), wx.ID_CLOSE),
            (wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CLOSE),
        ]

    def prepare(self, title="Jelly Application", size=(1200, 700)):
        """Prepare the window, by loading all views and menu-entires.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  title: str
        @param title: The title of the window

        @type  size: tuple
        @param size: The default size of the window
        """
        self.wHnd = wx.Frame(None, wx.NewId(), title, size=size, style=wx.DEFAULT_FRAME_STYLE)
        self.onWHndCreate()

        self.menu = MenuBuilder(self.wHnd, self)
        self.view = ViewBuilder(self.wHnd, self)
        self.view.createView()
        self.wHnd.SetMenuBar(self.menu.build())
        self.statusbar = self.wHnd.CreateStatusBar()

        self.wHnd.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_CLOSE)
        self.wHnd.Bind(wx.EVT_SIZE, self.update)
        self.wHnd.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        entries = []
        entries.extend(self.shortcutIds)
        entries.extend(self.view.getShortcutIds())
        entries.extend(self.menu.getShortcutIds())
        specialMapping = {wx.ACCEL_CTRL: "CTRL + ", wx.ACCEL_SHIFT: "Shift + ", wx.ACCEL_NORMAL: ""}
        keyMapping = {id: "F{}".format(i) for id, i in zip([wx.WXK_F1, wx.WXK_F2, wx.WXK_F3, wx.WXK_F4, wx.WXK_F5, wx.WXK_F6, wx.WXK_F7, wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11, wx.WXK_F12], itertools.count(1))}
        for special, key, func in itertools.chain(self.shortcuts, self.view.getShortcuts(), self.menu.getShortcuts()):
            logger.debug("Registering Shortcut {}{} to method {}".format(specialMapping[special], keyMapping[key] if key in keyMapping else chr(key), func))
            id = wx.NewId()
            entries.append((special, key, id))
            self.wHnd.Bind(wx.EVT_MENU, func, id=id)
        self.acceleratorTable = wx.AcceleratorTable(entries)
        self.wHnd.SetAcceleratorTable(self.acceleratorTable)

        self.SetTopWindow(self.wHnd)

        self.onPrepare()

        return self.wHnd

    def onWHndCreate(self):
        pass

    def onPrepare(self):
        pass

    def update(self, event=None):
        """Eventhandler for resize events.
        Updates all views.

        @type  self: InterfaceBuilder
        @param self: The class instance
        """
        self.view.updateView()
        if event is not None:
            event.Skip()

    def OnCloseWindow(self, e):
        """Eventhandler for the close event.
        Prompts the user if this was intentional.

        @type  self: InterfaceBuilder
        @param self: The class instance
        """
        if self.displayQuestion('Are you sure to quit?'):
            self.wHnd.Destroy()
            self.ExitMainLoop()

    def fileDialog(self, mode, message, fileTypes=None, dir=wx.EmptyString):
        """Displays a file dialog to open or save a file.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @param mode: The mode of the dialog (save / open)

        @type  message: str
        @param message: The title of the dialog

        @param fileTypes: List of available filetypes

        @param dir: The default directory for the dialog
        """
        if fileTypes is None:
            wc = wx.FileSelectorDefaultWildcardStr
        else:
            wc = ""
            for descr, ext in fileTypes:
                wc += descr + " (*" + ext + ")|*" + ext + "|"
            wc = wc[:-1]  # remove trailing "|"

        diag = wx.FileDialog(self.wHnd, message, defaultDir=dir, wildcard=wc, style=mode)
        diag.ShowModal()
        return os.path.join(diag.Directory, diag.Filename) if diag.Filename != "" else ""

    def messageDialog(self, message, caption=wx.MessageBoxCaptionStr, style=wx.OK | wx.ICON_INFORMATION):
        """Displays a messagedialog.
        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The message of the dialog

        @type  caption: str
        @param message: The caption of the dialog

        @param style: The dialog style (Buttons & Icon)
        """
        if self.wHnd is not None and self.wHnd.IsShown() and not self.suppress_dialogs:
            dial = wx.MessageDialog(None, message, caption, style)
            return dial.ShowModal()
        else:
            return True

    def displayError(self, message, caption='An error occured', logname=None):
        """Displays an error message.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The message of the dialog

        @type  caption: str
        @param message: The caption of the dialog
        """
        if logname is None:
            logger.error(message)
        else:
            logging.getLogger(logname).error(message)
        return self.messageDialog(message, caption, wx.OK | wx.ICON_ERROR) == wx.OK

    def displayWarning(self, message, caption='Warning', logname=None):
        """Displays a warning message.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The message of the dialog

        @type  caption: str
        @param message: The caption of the dialog
        """
        if logname is None:
            logger.warning(message)
        else:
            logging.getLogger(logname).warning(message)
        return self.messageDialog(message, caption, wx.OK | wx.ICON_EXCLAMATION) == wx.OK

    def displayInformation(self, message, caption='Information', logname=None):
        """Displays an information message.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The message of the dialog

        @type  caption: str
        @param message: The caption of the dialog
        """
        if logname is None:
            logger.info(message)
        else:
            logging.getLogger(logname).info(message)
        return self.messageDialog(message, caption, wx.OK | wx.ICON_INFORMATION) == wx.OK

    def displayQuestion(self, message, caption='Question', logname=None):
        """Displays a question.

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The message of the dialog

        @type  caption: str
        @param message: The cpation of the dialog
        """
        if logname is None:
            logger.info(message)
        else:
            logging.getLogger(logname).info(message)
        return self.messageDialog(message, caption, wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) == wx.ID_YES

    def loadFileDialog(self, message="Load File", fileTypes=None, dir=wx.EmptyString):
        """File load dialog

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The title of the dialog

        @param fileTypes: List of available filetypes

        @param dir: The default directory for the dialog
        """
        return self.fileDialog(mode=wx.FD_OPEN, message=message, fileTypes=fileTypes, dir=dir)

    def saveFileDialog(self, message="Message", fileTypes=None, dir=wx.EmptyString):
        """File save dialog

        @type  self: InterfaceBuilder
        @param self: The class instance

        @type  message: str
        @param message: The title of the dialog

        @param fileTypes: List of available filetypes

        @param dir: The default directory for the dialog
        """
        return self.fileDialog(mode=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, message=message, fileTypes=fileTypes, dir=dir)

    def show(self):
        """Show the application window and start the event handling loop.

        @type  self: InterfaceBuilder
        @param self: The class instance
        """
        self.wHnd.Centre()
        self.wHnd.Show()
        self.MainLoop()