Example #1
0
    def test_general_command_do(self):
        history = UndoHistory()
        command = DummyCommand()

        history.add(command)

        self.assertEqual(command.data, "do")
Example #2
0
    def test_add_middle_mergeable(self):
        history = UndoHistory()
        example = SimpleExample(str_value='foo', value=10)
        undo_item = UndoItem(
            object=example,
            name='str_value',
            old_value='bar',
            new_value='baz',
        )

        history.add(
            UndoItem(
                object=example,
                name='str_value',
                old_value='foo',
                new_value='bar',
            ))
        history.add(
            UndoItem(
                object=example,
                name='str_value',
                old_value='bar',
                new_value='wombat',
            ), )
        history.undo()

        with self.assertTraitDoesNotChange(history, 'undoable'):
            with self.assertTraitChanges(history, 'redoable', count=1):
                history.add(undo_item)

        self.assertEqual(history.now, 1)
        self.assertTrue(history.can_undo)
        self.assertFalse(history.can_redo)
Example #3
0
    def test_clear_end(self):
        history = UndoHistory()
        self._populate_history(history)

        with self.assertTraitDoesNotChange(history, 'redoable'):
            with self.assertTraitChanges(history, 'undoable', count=1):
                with self.assertTraitDoesNotChange(self._example, 'anytrait'):
                    history.clear()

        self.assertEqual(history.now, 0)
        self.assertFalse(history.can_undo)
        self.assertFalse(history.can_redo)
Example #4
0
    def test_revert_end(self):
        history = UndoHistory()
        self._populate_history(history)

        with self.assertTraitChanges(history, 'redoable', count=2):
            with self.assertTraitChanges(history, 'undoable', count=1):
                with self.assertTraitChanges(self._example,
                                             'anytrait',
                                             count=3):  # noqa: E501
                    history.revert()

        self.assertEqual(history.now, 0)
        self.assertFalse(history.can_undo)
        self.assertFalse(history.can_redo)
Example #5
0
    def test_undo_last(self):
        history = UndoHistory()
        self._populate_history(history)

        with self.assertTraitDoesNotChange(history, 'undoable'):
            with self.assertTraitChanges(history, 'redoable', count=1):
                with self.assertTraitChanges(self._example,
                                             'anytrait',
                                             count=1):  # noqa: E501
                    history.undo()

        self.assertEqual(history.now, 2)
        self.assertTrue(history.can_undo)
        self.assertTrue(history.can_redo)
Example #6
0
    def test_add_end_extend_merge(self):
        history = UndoHistory()
        example = SimpleExample(str_value='foo', value=10)
        undo_item = UndoItem(
            object=example,
            name='str_value',
            old_value='foo',
            new_value='baz',
        )

        history.add(
            UndoItem(
                object=example,
                name='str_value',
                old_value='foo',
                new_value='bar',
            ))

        with self.assertTraitDoesNotChange(history, 'undoable'):
            with self.assertTraitDoesNotChange(history, 'redoable'):
                history.add(undo_item, extend=True)

        self.assertEqual(history.now, 1)
        self.assertTrue(history.can_undo)
        self.assertFalse(history.can_redo)
        # XXX this is testing private state to ensure merge happened
        self.assertEqual(len(history.stack._stack), 1)
Example #7
0
    def test_add_end_extend(self):
        history = UndoHistory()
        example = SimpleExample(str_value='foo', value=10)
        undo_item = UndoItem(
            object=example,
            name='value',
            old_value=0,
            new_value=10,
        )

        history.add(
            UndoItem(
                object=example,
                name='str_value',
                old_value='foo',
                new_value='bar',
            ))

        with self.assertTraitDoesNotChange(history, 'undoable'):
            with self.assertTraitDoesNotChange(history, 'redoable'):
                history.add(undo_item, extend=True)

        self.assertEqual(history.now, 1)
        self.assertTrue(history.can_undo)
        self.assertFalse(history.can_redo)
Example #8
0
    def init(self, ui, parent, style):
        self.is_modal = style == self.MODAL
        window_style = 0
        view = ui.view
        if view.resizable:
            window_style |= wx.RESIZE_BORDER

        title = view.title
        if title == "":
            title = DefaultTitle

        history = ui.history
        window = ui.control
        if window is not None:
            if history is not None:
                history.observe(
                    self._on_undoable, "undoable", remove=True, dispatch="ui"
                )
                history.observe(
                    self._on_redoable, "redoable", remove=True, dispatch="ui"
                )
                history.observe(
                    self._on_revertable, "undoable", remove=True, dispatch="ui"
                )
            window.SetSizer(None)
            ui.reset()
        else:
            self.ui = ui
            if style == self.MODAL:
                if view.resizable:
                    window_style |= wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX
                window = wx.Dialog(
                    parent,
                    -1,
                    title,
                    style=window_style | wx.DEFAULT_DIALOG_STYLE,
                )
            elif style == self.NONMODAL:
                if parent is not None:
                    window_style |= (
                        wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR
                    )
                window = wx.Frame(
                    parent,
                    -1,
                    title,
                    style=window_style
                    | (wx.DEFAULT_FRAME_STYLE & (~wx.RESIZE_BORDER)),
                )
            else:
                if window_style == 0:
                    window_style = wx.SIMPLE_BORDER
                if parent is not None:
                    window_style |= (
                        wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR
                    )

                if isinstance(parent, tuple):
                    window = wx.Frame(None, -1, "", style=window_style)
                    window._control_region = parent
                else:
                    window = wx.Frame(parent, -1, "", style=window_style)
                window._kind = ui.view.kind
                self._monitor = MouseMonitor(ui)

            # Set the correct default window background color:
            window.SetBackgroundColour(WindowColor)

            self.control = window
            window.Bind(wx.EVT_CLOSE, self._on_close_page)
            window.Bind(wx.EVT_CHAR, self._on_key)

        self.set_icon(view.icon)
        buttons = [self.coerce_button(button) for button in view.buttons]
        nbuttons = len(buttons)
        no_buttons = (nbuttons == 1) and self.is_button(buttons[0], "")
        has_buttons = (not no_buttons) and (
            (nbuttons > 0)
            or view.undo
            or view.revert
            or view.ok
            or view.cancel
        )
        if has_buttons or (view.menubar is not None):
            if history is None:
                history = UndoHistory()
        else:
            history = None
        ui.history = history

        # Create the actual trait sheet panel and imbed it in a scrollable
        # window (if requested):
        sw_sizer = wx.BoxSizer(wx.VERTICAL)
        if ui.scrollable:
            sizer = wx.BoxSizer(wx.VERTICAL)
            sw = TraitsUIScrolledPanel(window)
            trait_sheet = panel(ui, sw)
            sizer.Add(trait_sheet, 1, wx.EXPAND)
            tsdx, tsdy = trait_sheet.GetSize()
            sw.SetScrollRate(16, 16)
            max_dy = (2 * SystemMetrics().screen_height) // 3
            sw.SetSizer(sizer)
            sw.SetSize(
                wx.Size(
                    tsdx + ((tsdy > max_dy) * scrollbar_dx), min(tsdy, max_dy)
                )
            )
        else:
            sw = panel(ui, window)

        sw_sizer.Add(sw, 1, wx.EXPAND)
        sw_sizer.SetMinSize(sw.GetSize())

        # Check to see if we need to add any of the special function buttons:
        if (not no_buttons) and (has_buttons or view.help):
            sw_sizer.Add(wx.StaticLine(window, -1), 0, wx.EXPAND)
            b_sizer = wx.BoxSizer(wx.HORIZONTAL)

            # Convert all button flags to actual button actions if no buttons
            # were specified in the 'buttons' trait:
            if nbuttons == 0:
                if view.undo:
                    self.check_button(buttons, UndoButton)

                if view.revert:
                    self.check_button(buttons, RevertButton)

                if view.ok:
                    self.check_button(buttons, OKButton)

                if view.cancel:
                    self.check_button(buttons, CancelButton)

                if view.help:
                    self.check_button(buttons, HelpButton)

            # Create a button for each button action:
            for raw_button, button in zip(view.buttons, buttons):
                button = self.coerce_button(button)
                default = raw_button == view.default_button

                if self.is_button(button, "Undo"):
                    self.undo = self.add_button(
                        button, b_sizer, self._on_undo, False, default=default
                    )
                    self.redo = self.add_button(
                        button, b_sizer, self._on_redo, False, "Redo"
                    )
                    history.observe(
                        self._on_undoable, "undoable", dispatch="ui"
                    )
                    history.observe(
                        self._on_redoable, "redoable", dispatch="ui"
                    )
                    if history.can_undo:
                        self._on_undoable(True)

                    if history.can_redo:
                        self._on_redoable(True)

                elif self.is_button(button, "Revert"):
                    self.revert = self.add_button(
                        button,
                        b_sizer,
                        self._on_revert,
                        False,
                        default=default,
                    )
                    history.observe(
                        self._on_revertable, "undoable", dispatch="ui"
                    )
                    if history.can_undo:
                        self._on_revertable(True)

                elif self.is_button(button, "OK"):
                    self.ok = self.add_button(
                        button, b_sizer, self._on_ok, default=default
                    )
                    ui.observe(self._on_error, "errors", dispatch="ui")

                elif self.is_button(button, "Cancel"):
                    self.add_button(
                        button, b_sizer, self._on_cancel, default=default
                    )

                elif self.is_button(button, "Help"):
                    self.add_button(
                        button, b_sizer, self._on_help, default=default
                    )

                elif not self.is_button(button, ""):
                    self.add_button(button, b_sizer, default=default)

            sw_sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)

        # Add the menu bar, tool bar and status bar (if any):
        self.add_menubar()
        self.add_toolbar()
        self.add_statusbar()

        # Lay all of the dialog contents out:
        window.SetSizer(sw_sizer)
        window.Fit()
Example #9
0
    def init(self, ui, parent, style):
        """Initialise the object.

           FIXME: Note that we treat MODAL and POPUP as equivalent until we
           have an example that demonstrates how POPUP is supposed to work.
        """
        self.ui = ui
        self.control = ui.control
        view = ui.view
        history = ui.history

        if self.control is not None:
            if history is not None:
                history.on_trait_change(self._on_undoable, 'undoable',
                                        remove=True)
                history.on_trait_change(self._on_redoable, 'redoable',
                                        remove=True)
                history.on_trait_change(self._on_revertable, 'undoable',
                                        remove=True)

            ui.reset()
        else:
            self.create_dialog(parent, style)

        self.set_icon(view.icon)

        # Convert the buttons to actions.
        buttons = [self.coerce_button(button) for button in view.buttons]
        nr_buttons = len(buttons)

        no_buttons = ((nr_buttons == 1) and self.is_button(buttons[0], ''))

        has_buttons = (
            (not no_buttons) and (
                (nr_buttons > 0) or view.undo or view.revert or view.ok or view.cancel))

        if has_buttons or (view.menubar is not None):
            if history is None:
                history = UndoHistory()
        else:
            history = None

        ui.history = history

        if (not no_buttons) and (has_buttons or view.help):
            bbox = QtGui.QDialogButtonBox()

            # Create the necessary special function buttons.
            if nr_buttons == 0:
                if view.undo:
                    self.check_button(buttons, UndoButton)
                if view.revert:
                    self.check_button(buttons, RevertButton)
                if view.ok:
                    self.check_button(buttons, OKButton)
                if view.cancel:
                    self.check_button(buttons, CancelButton)
                if view.help:
                    self.check_button(buttons, HelpButton)

            for raw_button, button in zip(view.buttons, buttons):
                default = raw_button == view.default_button

                if self.is_button(button, 'Undo'):
                    self.undo = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ActionRole,
                        self._on_undo,
                        False,
                        default=default)
                    history.on_trait_change(self._on_undoable, 'undoable',
                                            dispatch='ui')
                    if history.can_undo:
                        self._on_undoable(True)

                    self.redo = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ActionRole,
                        self._on_redo,
                        False,
                        'Redo')
                    history.on_trait_change(self._on_redoable, 'redoable',
                                            dispatch='ui')
                    if history.can_redo:
                        self._on_redoable(True)

                elif self.is_button(button, 'Revert'):
                    self.revert = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ResetRole,
                        self._on_revert,
                        False,
                        default=default)
                    history.on_trait_change(self._on_revertable, 'undoable',
                                            dispatch='ui')
                    if history.can_undo:
                        self._on_revertable(True)

                elif self.is_button(button, 'OK'):
                    self.ok = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.AcceptRole,
                        self.control.accept,
                        default=default)
                    ui.on_trait_change(self._on_error, 'errors', dispatch='ui')

                elif self.is_button(button, 'Cancel'):
                    self.add_button(button, bbox,
                                    QtGui.QDialogButtonBox.RejectRole,
                                    self.control.reject, default=default)

                elif self.is_button(button, 'Help'):
                    self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.HelpRole,
                        self._on_help,
                        default=default)

                elif not self.is_button(button, ''):
                    self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ActionRole,
                        default=default)

        else:
            bbox = None

        self.add_contents(panel(ui), bbox)
Example #10
0
    def __init__(self, ui, parent, allow_buttons):
        """ Initializes the object.
        """
        self.ui = ui
        history = None
        view = ui.view
        title = view.title

        # Reset any existing history listeners:
        history = ui.history
        if history is not None:
            history.on_trait_change(self._on_undoable,
                                    'undoable', remove=True)
            history.on_trait_change(self._on_redoable,
                                    'redoable', remove=True)
            history.on_trait_change(self._on_revertable,
                                    'undoable', remove=True)

        # Determine if we need any buttons or an 'undo' history:
        buttons = [self.coerce_button(button) for button in view.buttons]
        nbuttons = len(buttons)
        if nbuttons == 0:
            if view.undo:
                self.check_button(buttons, UndoButton)
            if view.revert:
                self.check_button(buttons, RevertButton)
            if view.help:
                self.check_button(buttons, HelpButton)

        if allow_buttons and (history is None):
            for button in buttons:
                if (self.is_button(button, 'Undo') or
                        self.is_button(button, 'Revert')):
                    history = UndoHistory()
                    break
        ui.history = history

        # Create a container panel to put everything in:
        cpanel = getattr(self, 'control', None)
        if cpanel is not None:
            cpanel.SetSizer(None)
            cpanel.DestroyChildren()
        else:
            self.control = cpanel = TraitsUIPanel(parent, -1)

        # Create the actual trait sheet panel and embed it in a scrollable
        # window (if requested):
        sw_sizer = wx.BoxSizer(wx.VERTICAL)
        if ui.scrollable:
            sizer = wx.BoxSizer(wx.VERTICAL)
            sw = TraitsUIScrolledPanel(cpanel)
            sizer.Add(panel(ui, sw), 1, wx.EXPAND)

            sw.SetSizerAndFit(sizer)
            sw.SetScrollRate(16, 16)
        else:
            sw = panel(ui, cpanel)

        if ((title != '') and
                (not isinstance(getattr(parent, 'owner', None), DockWindow))):
            sw_sizer.Add(heading_text(cpanel, text=title).control, 0,
                         wx.EXPAND)

        self.add_toolbar(sw_sizer)

        sw_sizer.Add(sw, 1, wx.EXPAND)

        if (allow_buttons and
                ((nbuttons != 1) or (not self.is_button(buttons[0], '')))):
            # Add the special function buttons:
            sw_sizer.Add(wx.StaticLine(cpanel, -1), 0, wx.EXPAND)
            b_sizer = wx.BoxSizer(wx.HORIZONTAL)
            for button in buttons:
                if self.is_button(button, 'Undo'):
                    self.undo = self.add_button(button, b_sizer,
                                                self._on_undo, False)
                    self.redo = self.add_button(button, b_sizer,
                                                self._on_redo, False, 'Redo')
                    history.on_trait_change(self._on_undoable, 'undoable',
                                            dispatch='ui')
                    history.on_trait_change(self._on_redoable, 'redoable',
                                            dispatch='ui')
                elif self.is_button(button, 'Revert'):
                    self.revert = self.add_button(button, b_sizer,
                                                  self._on_revert, False)
                    history.on_trait_change(self._on_revertable, 'undoable',
                                            dispatch='ui')
                elif self.is_button(button, 'Help'):
                    self.add_button(button, b_sizer, self._on_help)
                elif not self.is_button(button, ''):
                    self.add_button(button, b_sizer)

            sw_sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)

        cpanel.SetSizerAndFit(sw_sizer)
Example #11
0
    def test_defaults(self):
        history = UndoHistory()

        self.assertEqual(history.now, 0)
        self.assertFalse(history.can_undo)
        self.assertFalse(history.can_redo)
Example #12
0
    def test_undo(self):
        editor = create_editor()
        editor.prepare(None)
        editor.ui.history = UndoHistory()

        self.assertEqual(editor.old_value, "test")

        # Enter 'one' followed by 'two'
        with editor.updating_value():
            self.gui.set_trait_later(editor.control, "control_value", "one")
            self.gui.set_trait_later(editor.control, "control_value", "two")

        # Perform an UNDO
        self.undo(editor)

        # Expect 2 items in history and pointer at first item
        self.assertEventuallyTrue(editor,
                                  "ui",
                                  functools.partial(self.check_history,
                                                    expected_history_now=1,
                                                    expected_history_length=2),
                                  timeout=5.0)

        # Perform a REDO
        self.redo(editor)

        # Expect 2 items in history and pointer at second item
        self.assertEventuallyTrue(editor,
                                  "ui",
                                  functools.partial(self.check_history,
                                                    expected_history_now=2,
                                                    expected_history_length=2),
                                  timeout=5.0)

        # Enter 'three'
        with editor.updating_value():
            self.gui.set_trait_later(editor.control, "control_value", "three")

        # Perform an UNDO
        self.undo(editor)

        # Expect 3 items in history and pointer at second item
        self.assertEventuallyTrue(editor,
                                  "ui",
                                  functools.partial(self.check_history,
                                                    expected_history_now=2,
                                                    expected_history_length=3),
                                  timeout=5.0)

        # Enter 'four'
        with editor.updating_value():
            self.gui.set_trait_later(editor.control, "control_value", "four")
        self.event_loop_helper.event_loop_with_timeout()

        # Expect 3 items in history and pointer at second item
        # Note: Modifying the history after an UNDO, clears the future,
        # hence, we expect 3 items in the history, not 4
        self.assertEventuallyTrue(editor,
                                  "ui",
                                  functools.partial(self.check_history,
                                                    expected_history_now=3,
                                                    expected_history_length=3),
                                  timeout=5.0)

        # The following sequence after modifying the history had caused
        # the application to hang, verify it.

        # Perform an UNDO
        self.undo(editor)
        self.undo(editor)
        self.redo(editor)

        # Expect 3 items in history and pointer at second item
        self.assertEventuallyTrue(editor,
                                  "ui",
                                  functools.partial(self.check_history,
                                                    expected_history_now=2,
                                                    expected_history_length=3),
                                  timeout=5.0)
Example #13
0
    def init(self, ui, parent, style):
        self.is_modal = (style == MODAL)
        window_style = 0
        view = ui.view
        if view.resizable:
            window_style |= wx.RESIZE_BORDER

        title = view.title
        if title == '':
            title = DefaultTitle

        history = ui.history
        window = ui.control
        if window is not None:
            if history is not None:
                history.on_trait_change(self._on_undoable, 'undoable',
                                        remove=True)
                history.on_trait_change(self._on_redoable, 'redoable',
                                        remove=True)
                history.on_trait_change(self._on_revertable, 'undoable',
                                        remove=True)
            window.SetSizer(None)
            ui.reset()
        else:
            self.ui = ui
            if style == MODAL:
                if view.resizable:
                    window_style |= (wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX)
                window = wx.Dialog(
                    parent, -1, title, style=window_style | wx.DEFAULT_DIALOG_STYLE)
            elif style == NONMODAL:
                if parent is not None:
                    window_style |= (wx.FRAME_FLOAT_ON_PARENT |
                                     wx.FRAME_NO_TASKBAR)
                window = wx.Frame(parent, -1, title, style=window_style |
                                  (wx.DEFAULT_FRAME_STYLE & (~wx.RESIZE_BORDER)))
            else:
                if window_style == 0:
                    window_style = wx.SIMPLE_BORDER
                if parent is not None:
                    window_style |= (wx.FRAME_FLOAT_ON_PARENT |
                                     wx.FRAME_NO_TASKBAR)

                window = wx.Frame(parent, -1, '', style=window_style)
                window._kind = ui.view.kind
                self._monitor = MouseMonitor(ui)

            # Set the correct default window background color:
            window.SetBackgroundColour(WindowColor)

            self.control = window
            wx.EVT_CLOSE(window, self._on_close_page)
            wx.EVT_CHAR(window, self._on_key)

        self.set_icon(view.icon)
        buttons = [self.coerce_button(button)
                   for button in view.buttons]
        nbuttons = len(buttons)
        no_buttons = ((nbuttons == 1) and self.is_button(buttons[0], ''))
        has_buttons = (
            (not no_buttons) and (
                (nbuttons > 0) or view.undo or view.revert or view.ok or view.cancel))
        if has_buttons or (view.menubar is not None):
            if history is None:
                history = UndoHistory()
        else:
            history = None
        ui.history = history

        # Create the actual trait sheet panel and imbed it in a scrollable
        # window (if requested):
        sw_sizer = wx.BoxSizer(wx.VERTICAL)
        if ui.scrollable:
            sizer = wx.BoxSizer(wx.VERTICAL)
            sw = TraitsUIScrolledPanel(window)
            trait_sheet = panel(ui, sw)
            sizer.Add(trait_sheet, 1, wx.EXPAND)
            tsdx, tsdy = trait_sheet.GetSize()
            sw.SetScrollRate(16, 16)
            max_dy = (2 * screen_dy) / 3
            sw.SetSizer(sizer)
            sw.SetSize(wx.Size(tsdx + ((tsdy > max_dy) * scrollbar_dx),
                               min(tsdy, max_dy)))
        else:
            sw = panel(ui, window)

        sw_sizer.Add(sw, 1, wx.EXPAND)
        sw_sizer.SetMinSize(sw.GetSize())

        # Check to see if we need to add any of the special function buttons:
        if (not no_buttons) and (has_buttons or view.help):
            sw_sizer.Add(wx.StaticLine(window, -1), 0, wx.EXPAND)
            b_sizer = wx.BoxSizer(wx.HORIZONTAL)

            # Convert all button flags to actual button actions if no buttons
            # were specified in the 'buttons' trait:
            if nbuttons == 0:
                if view.undo:
                    self.check_button(buttons, UndoButton)

                if view.revert:
                    self.check_button(buttons, RevertButton)

                if view.ok:
                    self.check_button(buttons, OKButton)

                if view.cancel:
                    self.check_button(buttons, CancelButton)

                if view.help:
                    self.check_button(buttons, HelpButton)

            # Create a button for each button action:
            for raw_button, button in zip(view.buttons, buttons):
                button = self.coerce_button(button)
                default = raw_button == view.default_button

                if self.is_button(button, 'Undo'):
                    self.undo = self.add_button(
                        button, b_sizer, self._on_undo, False, default=default)
                    self.redo = self.add_button(button, b_sizer,
                                                self._on_redo, False, 'Redo')
                    history.on_trait_change(self._on_undoable, 'undoable',
                                            dispatch='ui')
                    history.on_trait_change(self._on_redoable, 'redoable',
                                            dispatch='ui')
                    if history.can_undo:
                        self._on_undoable(True)

                    if history.can_redo:
                        self._on_redoable(True)

                elif self.is_button(button, 'Revert'):
                    self.revert = self.add_button(
                        button, b_sizer, self._on_revert, False, default=default)
                    history.on_trait_change(self._on_revertable, 'undoable',
                                            dispatch='ui')
                    if history.can_undo:
                        self._on_revertable(True)

                elif self.is_button(button, 'OK'):
                    self.ok = self.add_button(button, b_sizer, self._on_ok,
                                              default=default)
                    ui.on_trait_change(self._on_error, 'errors',
                                       dispatch='ui')

                elif self.is_button(button, 'Cancel'):
                    self.add_button(button, b_sizer, self._on_cancel,
                                    default=default)

                elif self.is_button(button, 'Help'):
                    self.add_button(button, b_sizer, self._on_help,
                                    default=default)

                elif not self.is_button(button, ''):
                    self.add_button(button, b_sizer, default=default)

            sw_sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)

        # Add the menu bar, tool bar and status bar (if any):
        self.add_menubar()
        self.add_toolbar()
        self.add_statusbar()

        # Lay all of the dialog contents out:
        window.SetSizer(sw_sizer)
        window.Fit()
Example #14
0
    def init(self, ui, parent, style):
        """Initialise the object.

           FIXME: Note that we treat MODAL and POPUP as equivalent until we
           have an example that demonstrates how POPUP is supposed to work.
        """
        self.ui = ui
        self.control = ui.control
        view = ui.view
        history = ui.history

        if self.control is not None:
            if history is not None:
                history.on_trait_change(
                    self._on_undoable, "undoable", remove=True
                )
                history.on_trait_change(
                    self._on_redoable, "redoable", remove=True
                )
                history.on_trait_change(
                    self._on_revertable, "undoable", remove=True
                )

            ui.reset()
        else:
            self.create_dialog(parent, style)

        self.set_icon(view.icon)

        # Convert the buttons to actions.
        buttons = [self.coerce_button(button) for button in view.buttons]
        nr_buttons = len(buttons)

        no_buttons = (nr_buttons == 1) and self.is_button(buttons[0], "")

        has_buttons = (not no_buttons) and (
            (nr_buttons > 0)
            or view.undo
            or view.revert
            or view.ok
            or view.cancel
        )

        if has_buttons or (view.menubar is not None):
            if history is None:
                history = UndoHistory()
        else:
            history = None

        ui.history = history

        if (not no_buttons) and (has_buttons or view.help):
            bbox = QtGui.QDialogButtonBox()

            # Create the necessary special function buttons.
            if nr_buttons == 0:
                if view.undo:
                    self.check_button(buttons, UndoButton)
                if view.revert:
                    self.check_button(buttons, RevertButton)
                if view.ok:
                    self.check_button(buttons, OKButton)
                if view.cancel:
                    self.check_button(buttons, CancelButton)
                if view.help:
                    self.check_button(buttons, HelpButton)

            for raw_button, button in zip(view.buttons, buttons):
                default = raw_button == view.default_button

                if self.is_button(button, "Undo"):
                    self.undo = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ActionRole,
                        self._on_undo,
                        False,
                        default=default,
                    )
                    history.on_trait_change(
                        self._on_undoable, "undoable", dispatch="ui"
                    )
                    if history.can_undo:
                        self._on_undoable(True)

                    self.redo = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ActionRole,
                        self._on_redo,
                        False,
                        "Redo",
                    )
                    history.on_trait_change(
                        self._on_redoable, "redoable", dispatch="ui"
                    )
                    if history.can_redo:
                        self._on_redoable(True)

                elif self.is_button(button, "Revert"):
                    self.revert = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ResetRole,
                        self._on_revert,
                        False,
                        default=default,
                    )
                    history.on_trait_change(
                        self._on_revertable, "undoable", dispatch="ui"
                    )
                    if history.can_undo:
                        self._on_revertable(True)

                elif self.is_button(button, "OK"):
                    self.ok = self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.AcceptRole,
                        self.control.accept,
                        default=default,
                    )
                    ui.on_trait_change(self._on_error, "errors", dispatch="ui")

                elif self.is_button(button, "Cancel"):
                    self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.RejectRole,
                        self.control.reject,
                        default=default,
                    )

                elif self.is_button(button, "Help"):
                    self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.HelpRole,
                        self._on_help,
                        default=default,
                    )

                elif not self.is_button(button, ""):
                    self.add_button(
                        button,
                        bbox,
                        QtGui.QDialogButtonBox.ActionRole,
                        default=default,
                    )

        else:
            bbox = None

        self.add_contents(panel(ui), bbox)
Example #15
0
    def __init__(self, ui, parent, is_subpanel):
        """Initialise the object.
        """
        self.ui = ui
        history = ui.history
        view = ui.view

        # Reset any existing history listeners.
        if history is not None:
            history.observe(self._on_undoable,
                            "undoable",
                            remove=True,
                            dispatch="ui")
            history.observe(self._on_redoable,
                            "redoable",
                            remove=True,
                            dispatch="ui")
            history.observe(self._on_revertable,
                            "undoable",
                            remove=True,
                            dispatch="ui")

        # Determine if we need any buttons or an 'undo' history.
        buttons = [self.coerce_button(button) for button in view.buttons]
        nr_buttons = len(buttons)
        has_buttons = not is_subpanel and (nr_buttons != 1 or
                                           not self.is_button(buttons[0], ""))

        if nr_buttons == 0:
            if view.undo:
                self.check_button(buttons, UndoButton)
            if view.revert:
                self.check_button(buttons, RevertButton)
            if view.help:
                self.check_button(buttons, HelpButton)

        if not is_subpanel and history is None:
            for button in buttons:
                if self.is_button(button, "Undo") or self.is_button(
                        button, "Revert"):
                    history = ui.history = UndoHistory()
                    break

        # Create the panel.
        self.control = panel(ui)

        # Suppress the title if this is a subpanel or if we think it should be
        # superceded by the title of an "outer" widget (eg. a dock widget).
        title = view.title
        if (is_subpanel or (isinstance(parent, QtGui.QMainWindow)
                            and not isinstance(parent.parent(), QtGui.QDialog))
                or isinstance(parent, QtGui.QTabWidget)):
            title = ""

        # Panels must be widgets as it is only the TraitsUI PyQt code that can
        # handle them being layouts as well.  Therefore create a widget if the
        # panel is not a widget or if we need a title or buttons.
        if (not isinstance(self.control, QtGui.QWidget) or title != ""
                or has_buttons):
            w = QtGui.QWidget()
            layout = QtGui.QVBoxLayout(w)
            layout.setContentsMargins(0, 0, 0, 0)

            # Handle any view title.
            if title != "":
                layout.addWidget(heading_text(None, text=view.title).control)

            if isinstance(self.control, QtGui.QWidget):
                layout.addWidget(self.control)
            elif isinstance(self.control, QtGui.QLayout):
                layout.addLayout(self.control)

            self.control = w

            # Add any buttons.
            if has_buttons:

                # Add the horizontal separator
                separator = QtGui.QFrame()
                separator.setFrameStyle(QtGui.QFrame.Sunken
                                        | QtGui.QFrame.HLine)
                separator.setFixedHeight(2)
                layout.addWidget(separator)

                # Add the special function buttons
                bbox = QtGui.QDialogButtonBox(QtCore.Qt.Horizontal)
                for button in buttons:
                    role = QtGui.QDialogButtonBox.ActionRole
                    if self.is_button(button, "Undo"):
                        self.undo = self.add_button(button, bbox, role,
                                                    self._on_undo, False,
                                                    "Undo")
                        self.redo = self.add_button(button, bbox, role,
                                                    self._on_redo, False,
                                                    "Redo")
                        history.observe(self._on_undoable,
                                        "undoable",
                                        dispatch="ui")
                        history.observe(self._on_redoable,
                                        "redoable",
                                        dispatch="ui")
                    elif self.is_button(button, "Revert"):
                        role = QtGui.QDialogButtonBox.ResetRole
                        self.revert = self.add_button(button, bbox, role,
                                                      self._on_revert, False)
                        history.observe(self._on_revertable,
                                        "undoable",
                                        dispatch="ui")
                    elif self.is_button(button, "Help"):
                        role = QtGui.QDialogButtonBox.HelpRole
                        self.add_button(button, bbox, role, self._on_help)
                    elif not self.is_button(button, ""):
                        self.add_button(button, bbox, role)
                layout.addWidget(bbox)

        # If the UI has a toolbar, should add it to the panel too
        self._add_toolbar(parent)

        # Ensure the control has a size hint reflecting the View specification.
        # Yes, this is a hack, but it's too late to repair this convoluted
        # control building process, so we do what we have to...
        self.control.sizeHint = _size_hint_wrapper(self.control.sizeHint, ui)
Example #16
0
    def __init__(self, ui, parent, allow_buttons):
        """ Initializes the object.
        """
        self.ui = ui
        history = None
        view = ui.view
        title = view.title

        # Reset any existing history listeners:
        history = ui.history
        if history is not None:
            history.on_trait_change(self._on_undoable, "undoable", remove=True)
            history.on_trait_change(self._on_redoable, "redoable", remove=True)
            history.on_trait_change(
                self._on_revertable, "undoable", remove=True
            )

        # Determine if we need any buttons or an 'undo' history:
        buttons = [self.coerce_button(button) for button in view.buttons]
        nbuttons = len(buttons)
        if nbuttons == 0:
            if view.undo:
                self.check_button(buttons, UndoButton)
            if view.revert:
                self.check_button(buttons, RevertButton)
            if view.help:
                self.check_button(buttons, HelpButton)

        if allow_buttons and (history is None):
            for button in buttons:
                if self.is_button(button, "Undo") or self.is_button(
                    button, "Revert"
                ):
                    history = UndoHistory()
                    break
        ui.history = history

        # Create a container panel to put everything in:
        cpanel = getattr(self, "control", None)
        if cpanel is not None:
            cpanel.SetSizer(None)
            cpanel.DestroyChildren()
        else:
            self.control = cpanel = TraitsUIPanel(parent, -1)

        # Create the actual trait sheet panel and embed it in a scrollable
        # window (if requested):
        sw_sizer = wx.BoxSizer(wx.VERTICAL)
        if ui.scrollable:
            sizer = wx.BoxSizer(wx.VERTICAL)
            sw = TraitsUIScrolledPanel(cpanel)
            sizer.Add(panel(ui, sw), 1, wx.EXPAND)

            sw.SetSizerAndFit(sizer)
            sw.SetScrollRate(16, 16)
        else:
            sw = panel(ui, cpanel)

        if (title != "") and (
            not isinstance(getattr(parent, "owner", None), DockWindow)
        ):
            sw_sizer.Add(
                heading_text(cpanel, text=title).control, 0, wx.EXPAND
            )

        self.add_toolbar(sw_sizer)

        sw_sizer.Add(sw, 1, wx.EXPAND)

        if allow_buttons and (
            (nbuttons != 1) or (not self.is_button(buttons[0], ""))
        ):
            # Add the special function buttons:
            sw_sizer.Add(wx.StaticLine(cpanel, -1), 0, wx.EXPAND)
            b_sizer = wx.BoxSizer(wx.HORIZONTAL)
            for button in buttons:
                if self.is_button(button, "Undo"):
                    self.undo = self.add_button(
                        button, b_sizer, self._on_undo, False
                    )
                    self.redo = self.add_button(
                        button, b_sizer, self._on_redo, False, "Redo"
                    )
                    history.on_trait_change(
                        self._on_undoable, "undoable", dispatch="ui"
                    )
                    history.on_trait_change(
                        self._on_redoable, "redoable", dispatch="ui"
                    )
                elif self.is_button(button, "Revert"):
                    self.revert = self.add_button(
                        button, b_sizer, self._on_revert, False
                    )
                    history.on_trait_change(
                        self._on_revertable, "undoable", dispatch="ui"
                    )
                elif self.is_button(button, "Help"):
                    self.add_button(button, b_sizer, self._on_help)
                elif not self.is_button(button, ""):
                    self.add_button(button, b_sizer)

            sw_sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)

        cpanel.SetSizerAndFit(sw_sizer)
Example #17
0
    def __init__(self, ui, parent, allow_buttons):
        """ Initializes the object.
        """
        self.ui = ui
        history = None
        view = ui.view
        title = view.title

        # Reset any existing history listeners:
        history = ui.history
        if history is not None:
            history.on_trait_change(self._on_undoable, "undoable", remove=True)
            history.on_trait_change(self._on_redoable, "redoable", remove=True)
            history.on_trait_change(self._on_revertable, "undoable", remove=True)

        # Determine if we need any buttons or an 'undo' history:
        buttons = [self.coerce_button(button) for button in view.buttons]
        nbuttons = len(buttons)
        if nbuttons == 0:
            if view.undo:
                self.check_button(buttons, UndoButton)
            if view.revert:
                self.check_button(buttons, RevertButton)
            if view.help:
                self.check_button(buttons, HelpButton)

        if allow_buttons and (history is None):
            for button in buttons:
                if self.is_button(button, "Undo") or self.is_button(button, "Revert"):
                    history = UndoHistory()
                    break
        ui.history = history

        # Create a container panel to put everything in:
        cpanel = getattr(self, "control", None)
        if cpanel is not None:
            cpanel.SetSizer(None)
            cpanel.DestroyChildren()
        else:
            if is_mac:
                # Groups with borders have a two-tone background, and the
                # getter is picking the wrong color.  Set to transparent
                # and hope that the parent has been painted.
                bg_color = wx.Colour(224, 224, 224, 0)
                self.control = cpanel = TraitsUIPanel(parent, -1, bg_color=bg_color)
            else:
                self.control = cpanel = TraitsUIPanel(parent, -1)

        # Create the actual trait sheet panel and embed it in a scrollable
        # window (if requested):
        sw_sizer = wx.BoxSizer(wx.VERTICAL)
        if ui.scrollable:
            sizer = wx.BoxSizer(wx.VERTICAL)
            sw = TraitsUIScrolledPanel(cpanel)
            sizer.Add(panel(ui, sw), 1, wx.EXPAND)

            sw.SetSizerAndFit(sizer)
            sw.SetScrollRate(16, 16)
        else:
            sw = panel(ui, cpanel)

        if (title != "") and (not isinstance(getattr(parent, "owner", None), DockWindow)):
            sw_sizer.Add(heading_text(cpanel, text=title).control, 0, wx.EXPAND)

        self.add_toolbar(sw_sizer)

        sw_sizer.Add(sw, 1, wx.EXPAND)

        if allow_buttons and ((nbuttons != 1) or (not self.is_button(buttons[0], ""))):
            # Add the special function buttons:
            sw_sizer.Add(wx.StaticLine(cpanel, -1), 0, wx.EXPAND)
            b_sizer = wx.BoxSizer(wx.HORIZONTAL)
            for button in buttons:
                if self.is_button(button, "Undo"):
                    self.undo = self.add_button(button, b_sizer, self._on_undo, False)
                    self.redo = self.add_button(button, b_sizer, self._on_redo, False, "Redo")
                    history.on_trait_change(self._on_undoable, "undoable", dispatch="ui")
                    history.on_trait_change(self._on_redoable, "redoable", dispatch="ui")
                elif self.is_button(button, "Revert"):
                    self.revert = self.add_button(button, b_sizer, self._on_revert, False)
                    history.on_trait_change(self._on_revertable, "undoable", dispatch="ui")
                elif self.is_button(button, "Help"):
                    self.add_button(button, b_sizer, self._on_help)
                elif not self.is_button(button, ""):
                    self.add_button(button, b_sizer)

            sw_sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)

        cpanel.SetSizerAndFit(sw_sizer)