Ejemplo n.º 1
0
    def test_construction_after_setting_layout(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paned = DockPaned()
        group = DockGroup()
        item = DockItem()

        layout = DockLayout()

        layout.add(frame)

        win.add(frame)
        frame.add(paned)
        paned.add(group)
        group.add(item)

        assert frame in layout.frames
        self.assertEquals(4, len(layout._signal_handlers))
        self.assertEquals(9, len(layout._signal_handlers[frame]))

        paned.remove(group)

        self.assertEquals(2, len(layout._signal_handlers), layout._signal_handlers)
        assert frame in layout._signal_handlers.keys(), layout._signal_handlers
        assert paned in layout._signal_handlers.keys(), layout._signal_handlers
        assert group not in layout._signal_handlers.keys(), layout._signal_handlers
        assert item not in layout._signal_handlers.keys(), layout._signal_handlers
        assert frame in layout.frames
Ejemplo n.º 2
0
    def test_get_widgets(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paned = DockPaned()
        group = DockGroup()
        item = DockItem()
        label = gtk.Label()

        layout = DockLayout()

        layout.add(frame)

        win.add(frame)
        frame.add(paned)
        paned.add(group)
        group.add(item)
        item.add(label)

        group2 = DockGroup()
        paned.add(group2)

        paned.set_name('foo')

        widgets = list(layout.get_widgets('foo'))
        assert len(widgets) == 1
        assert widgets[0] is paned

        widgets = list(layout.get_widgets('EtkDockGroup'))
        assert len(widgets) == 2
        assert widgets[0] is group
        assert widgets[1] is group2
Ejemplo n.º 3
0
    def test_construction(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paned = DockPaned()
        group = DockGroup()
        item = DockItem()

        win.add(frame)
        frame.add(paned)
        paned.add(group)
        group.add(item)

        layout = DockLayout()

        layout.add(frame)

        assert frame in layout.frames
        print layout._signal_handlers
        self.assertEquals(4, len(layout._signal_handlers))
        self.assertEquals(9, len(layout._signal_handlers[frame]))

        layout.remove(frame)

        assert not layout._signal_handlers, layout._signal_handlers
        assert frame not in layout.frames
Ejemplo n.º 4
0
    def setUp(self):
        self.layout = DockLayout()
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.frame = DockFrame()
        self.group = DockGroup()

        self.layout.add(self.frame)
        self.window.add(self.frame)
        self.frame.add(self.group)
Ejemplo n.º 5
0
    def test_serialize(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        layout = DockLayout()
        frame = DockFrame()
        win.add(frame)
        layout.add(frame)
        paned = DockPaned()
        frame.add(paned)
        group = DockGroup()
        paned.add(group)
        item = DockItem(title='t', title_tooltip_text='xx', icon_name='icon', stock_id="")
        item.set_name('fillme')
        group.add(item)

        s = serialize(layout)
        assert '<layout><dockframe height="1" width="1">'\
        '<dockpaned orientation="horizontal">'\
        '<dockgroup weight="100">'\
        '<dockitem icon_name="icon" title="t" tooltip="xx" />'\
        '</dockgroup></dockpaned></dockframe></layout>' == s, s
Ejemplo n.º 6
0
    def setUp(self):

        self.layout = DockLayout()

        def drag_get_data(widget, context, target, timestamp):
            selection_data = StubSelectionData()
            context.source_widget.do_drag_data_get(context, selection_data, None, timestamp)
            self.layout.on_widget_drag_data_received(widget, context, 20, 20, selection_data, None, timestamp)

        DockGroup.drag_get_data = drag_get_data
        DockPaned.drag_get_data = drag_get_data
        DockFrame.drag_get_data = drag_get_data
Ejemplo n.º 7
0
def default_window(n_groups):
    world.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    world.window.set_default_size(800, 150)
    world.frame = DockFrame()
    world.window.add(world.frame)
    world.layout = DockLayout()
    world.layout.add(world.frame)
    paned = DockPaned()
    world.frame.add(paned)
    world.window.show()
    world.frame.show()
    paned.show()
    world.groups = []
    for i in range(int(n_groups)):
        group = DockGroup()
        paned.add(group)
        group.show()
        world.groups.append(group)
Ejemplo n.º 8
0
    def test_get_widgets_with_many_frames(self):
        frame1 = DockFrame()
        frame2 = DockFrame()
        frame3 = DockFrame()
        
        layout = DockLayout()

        layout.add(frame1)
        layout.add(frame2)
        layout.add(frame3)

        widgets = list(layout.get_widgets('foo'))
        assert len(widgets) == 0
Ejemplo n.º 9
0
class MainWindow(object):
    """
    The main window for the application.
    It contains a Namespace-based tree view and a menu and a statusbar.
    """
    interface.implements(IService, IActionProvider)


    component_registry = inject('component_registry')
    properties = inject('properties')
    element_factory = inject('element_factory')
    action_manager = inject('action_manager')
    file_manager = inject('file_manager')
    ui_manager = inject('ui_manager')

    title = 'Gaphor'
    size = property(lambda s: s.properties.get('ui.window-size', (760, 580)))
    menubar_path = '/mainwindow'
    toolbar_path = '/mainwindow-toolbar'
    resizable = True

    menu_xml = """
      <ui>
        <menubar name="mainwindow">
          <menu action="file">
            <placeholder name="primary" />
            <separator />
            <menu action="file-export" />
            <menu action="file-import" />
            <separator />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
            <separator />
            <menuitem action="file-quit" />
          </menu>
          <menu action="edit">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="diagram">
            <menuitem action="diagram-drawing-style" />
            <separator />
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="tools">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="window">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="help">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
        </menubar>
        <toolbar name='mainwindow-toolbar'>
            <placeholder name="left" />
            <separator expand="true" />
            <placeholder name="right" />
        </toolbar>
      </ui>
    """

    def __init__(self):
        self.window = None
        self.model_changed = False

        # Map tab contents to DiagramTab
        #self.notebook_map = {}
        self._current_diagram_tab = None
        self.layout = None


    def init(self, app=None):
        #self.init_pygtk()
        self.init_stock_icons()
        self.init_action_group()
        self.init_ui_components()


    def init_pygtk(self):
        """
        Make sure we have GTK+ >= 2.0
        """
        import pygtk
        pygtk.require('2.0')
        del pygtk


    def init_stock_icons(self):
        # Load stock items
        import gaphor.ui.stock
        gaphor.ui.stock.load_stock_icons()


    def init_ui_components(self):
        component_registry = self.component_registry
        for ep in pkg_resources.iter_entry_points('gaphor.uicomponents'):
            log.debug('found entry point uicomponent.%s' % ep.name)
            cls = ep.load()
            if not IUIComponent.implementedBy(cls):
                raise NameError, 'Entry point %s doesn''t provide IUIComponent' % ep.name
            uicomp = cls()
            uicomp.ui_name = ep.name
            component_registry.register_utility(uicomp, IUIComponent, ep.name)
            if IActionProvider.providedBy(uicomp):
                self.action_manager.register_action_provider(uicomp)
                

    def shutdown(self):
        if self.window:
            self.window.destroy()
            self.window = None
        save_accel_map()

        cr = self.component_registry
        cr.unregister_handler(self._on_file_manager_state_changed)
        cr.unregister_handler(self._on_undo_manager_state_changed)
        cr.unregister_handler(self._new_model_content)
        self.ui_manager.remove_action_group(self.action_group)


    def init_action_group(self):
        self.action_group = build_action_group(self)
        for name, label in (('file', '_File'),
                            ('file-export', '_Export'),
                            ('file-import', '_Import'),
                            ('edit', '_Edit'),
                            ('diagram', '_Diagram'),
                            ('tools', '_Tools'),
                            ('window', '_Window'),
                            ('help', '_Help')):
            a = gtk.Action(name, label, None, None)
            a.set_property('hide-if-empty', False)
            self.action_group.add_action(a)
        self._tab_ui_settings = None
        self.action_group.get_action('diagram-drawing-style').set_active(self.properties('diagram.sloppiness', 0) != 0)

        self.action_manager.register_action_provider(self)


    def get_filename(self):
        """
        Return the file name of the currently opened model.
        """
        return self.file_manager.filename


    def get_current_diagram_tab(self):
        """
        Get the currently opened and viewed DiagramTab, shown on the right
        side of the main window.
        See also: get_current_diagram(), get_current_diagram_view().
        """
        return self._current_diagram_tab


    def get_current_diagram(self):
        """
        Return the Diagram associated with the viewed DiagramTab.
        See also: get_current_diagram_tab(), get_current_diagram_view().
        """
        tab = self._current_diagram_tab
        return tab and tab.get_diagram()


    def get_current_diagram_view(self):
        """
        Return the DiagramView associated with the viewed DiagramTab.
        See also: get_current_diagram_tab(), get_current_diagram().
        """
        tab = self._current_diagram_tab
        return tab and tab.get_view()


    def ask_to_close(self):
        """
        Ask user to close window if the model has changed.
        The user is asked to either discard the changes, keep the
        application running or save the model and quit afterwards.
        """
        if self.model_changed:
            dialog = gtk.MessageDialog(self.window,
                    gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                    gtk.MESSAGE_WARNING,
                    gtk.BUTTONS_NONE,
                    _('Save changed to your model before closing?'))
            dialog.format_secondary_text(
                    _('If you close without saving, your changes will be discarded.'))
            dialog.add_buttons('Close _without saving', gtk.RESPONSE_REJECT,
                    gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                    gtk.STOCK_SAVE, gtk.RESPONSE_YES)
            dialog.set_default_response(gtk.RESPONSE_YES)
            response = dialog.run()
            dialog.destroy()

            if response == gtk.RESPONSE_YES:
                # On filedialog.cancel, the application should not close.
                return self.file_manager.action_save()
            return response == gtk.RESPONSE_REJECT
        return True


    def show_diagram(self, diagram):
        """
        Show a Diagram element in a new tab.
        If a tab is already open, show that one instead.
        """
        # Try to find an existing window/tab and let it get focus:
        for tab in self.get_tabs():
            if tab.get_diagram() is diagram:
                self.set_current_page(tab)
                return tab

        tab = DiagramTab(diagram)
        dock_item = tab.construct()
        dock_item.set_name('diagram-tab')
        dock_item.diagram_tab = tab
        assert dock_item.get_name() == 'diagram-tab'
        tab.set_drawing_style(self.properties('diagram.sloppiness', 0))

        self.add_tab(dock_item)

        return tab


    def open(self):

        load_accel_map()

        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(self.title)
        self.window.set_size_request(*self.size)
        self.window.set_resizable(self.resizable)

        # set default icons of gaphor windows
        icon_dir = os.path.abspath(pkg_resources.resource_filename('gaphor.ui', 'pixmaps'))
        icons = (gtk.gdk.pixbuf_new_from_file(os.path.join(icon_dir, f)) for f in ICONS)
        self.window.set_icon_list(*icons)

        self.window.add_accel_group(self.ui_manager.get_accel_group())

        
        # Create a full featured window.
        vbox = gtk.VBox()
        self.window.add(vbox)
        vbox.show()

        menubar = self.ui_manager.get_widget(self.menubar_path)
        if menubar:
            vbox.pack_start(menubar, expand=False)
        
        toolbar = self.ui_manager.get_widget(self.toolbar_path)
        if toolbar:
            vbox.pack_start(toolbar, expand=False)

        def _factory(name):
            comp = self.component_registry.get_utility(IUIComponent, name)
            logger.debug('open component %s' % str(comp))
            return comp.open()

        filename = pkg_resources.resource_filename('gaphor.ui', 'layout.xml')
        self.layout = DockLayout()

        with open(filename) as f:
            deserialize(self.layout, vbox, f.read(), _factory)
        
        self.layout.connect('item-closed', self._on_item_closed)
        self.layout.connect('item-selected', self._on_item_selected)

        vbox.show()
        # TODO: add statusbar

        self.window.show()

        self.window.connect('delete-event', self._on_window_delete)

        # We want to store the window size, so it can be reloaded on startup
        self.window.set_property('allow-shrink', True)
        self.window.connect('size-allocate', self._on_window_size_allocate)
        self.window.connect('destroy', self._on_window_destroy)
        #self.window.connect_after('key-press-event', self._on_key_press_event)

        cr = self.component_registry
        cr.register_handler(self._on_file_manager_state_changed)
        cr.register_handler(self._on_undo_manager_state_changed)
        cr.register_handler(self._new_model_content)
        # TODO: register on ElementCreate/Delete event


    def open_welcome_page(self):
        """
        Create a new tab with a textual welcome page, a sort of 101 for
        Gaphor.
        """
        pass

    def set_title(self):
        """
        Sets the window title.
        """
        filename = self.file_manager.filename
        if self.window:
            if filename:
                title = '%s - %s' % (self.title, filename)
            else:
                title = self.title
            if self.model_changed:
                title += ' *'
            self.window.set_title(title)


    # Notebook methods:

    def add_tab(self, item):
        """
        Create a new tab on the notebook with window as its contents.
        Returns: The page number of the tab.
        """
        group = list(self.layout.get_widgets('diagrams'))[0]
        group.insert_item(item)
        item.show_all()
        #item.diagram_tab = tab
        #self.notebook_map[item] = tab

    def set_current_page(self, tab):
        """
        Force a specific tab (DiagramTab) to the foreground.
        """
        for i in self.layout.get_widgets('diagram-tab'):
            if i.diagram_tab is tab:
                g = i.get_parent()
                g.set_current_item(g.item_num(i))
                return
        #for p, t in self.notebook_map.iteritems():
        #    if tab is t:
        #        num = self.notebook.page_num(p)
        #        self.notebook.set_current_page(num)
        #        return
        pass


    def get_tabs(self):
        tabs = map(lambda i: i.diagram_tab, self.layout.get_widgets('diagram-tab'))
        return tabs

    # Signal callbacks:

    @component.adapter(ModelFactoryEvent)
    def _new_model_content(self, event):
        """
        Open the toplevel element and load toplevel diagrams.
        """
        # TODO: Make handlers for ModelFactoryEvent from within the GUI obj
        for diagram in self.element_factory.select(lambda e: e.isKindOf(UML.Diagram) and not (e.namespace and e.namespace.namespace)):
            self.show_diagram(diagram)
    

    @component.adapter(FileManagerStateChanged)
    def _on_file_manager_state_changed(self, event):
        # We're only interested in file operations
        if event.service is self.file_manager:
            self.model_changed = False
            self.set_title()


    @component.adapter(UndoManagerStateChanged)
    def _on_undo_manager_state_changed(self, event):
        """
        """
        undo_manager = event.service
        if not self.model_changed and undo_manager.can_undo():
            self.model_changed = True
            self.set_title()


    def _on_window_destroy(self, window):
        """
        Window is destroyed... Quit the application.
        """
        self.window = None
        if gobject.main_depth() > 0:
            gtk.main_quit()
        cr = self.component_registry
        cr.unregister_handler(self._on_undo_manager_state_changed)
        cr.unregister_handler(self._on_file_manager_state_changed)
        cr.unregister_handler(self._new_model_content)

    def _on_window_delete(self, window = None, event = None):
        return not self.ask_to_close()

    def _clear_ui_settings(self):
        if self._tab_ui_settings:
            action_group, ui_id = self._tab_ui_settings
            self.ui_manager.remove_action_group(action_group)
            self.ui_manager.remove_ui(ui_id)
            self._tab_ui_settings = None

    def _on_item_closed(self, layout, group, item):
        self._clear_ui_settings()
        try:
            ui_component = item.ui_component
        except AttributeError:
            pass
        else:
            ui_component.close()
        item.destroy()

    def _on_item_selected(self, layout, group, item):
        """
        Another page (tab) is put on the front of the diagram notebook.
        A dummy action is executed.
        """
        # TODO: Here the magic happens!
        # TODO: Need to see what the active view is, or make toolbox actions global
        self._clear_ui_settings()

        # Is it a diagram view?
        try:
            tab = item.diagram_tab
        except AttributeError:
            # Not a diagram tab
            return

        self._current_diagram_tab = tab

        #content = self.notebook.get_nth_page(page_num)
        #tab = self.notebook_map.get(content)
        #assert isinstance(tab, DiagramTab), str(tab)
        
        self.ui_manager.insert_action_group(tab.action_group, -1)
        ui_id = self.ui_manager.add_ui_from_string(tab.menu_xml)
        self._tab_ui_settings = tab.action_group, ui_id
        log.debug('Menus updated with %s, %d' % self._tab_ui_settings)

        # Make sure everyone knows the selection has changed.
        self.component_registry.handle(DiagramTabChange(item), DiagramSelectionChange(tab.view, tab.view.focused_item, tab.view.selected_items))


    def _on_window_size_allocate(self, window, allocation):
        """
        Store the window size in a property.
        """
        self.properties.set('ui.window-size', (allocation.width, allocation.height))


    # Actions:

    @action(name='file-quit', stock_id='gtk-quit')
    def quit(self):
        # TODO: check for changes (e.g. undo manager), fault-save
        self.ask_to_close() and gtk.main_quit()
        self.shutdown()


    @toggle_action(name='diagram-drawing-style', label='Hand drawn style', active=False)
    def hand_drawn_style(self, active):
        """
        Toggle between straight diagrams and "hand drawn" diagram style.
        """
        if active:
            sloppiness = 0.5
        else:
            sloppiness = 0.0
        for tab in self.get_tabs():
            tab.set_drawing_style(sloppiness)
        self.properties.set('diagram.sloppiness', sloppiness)


    def create_item(self, ui_component): #, widget, title, placement=None):
        """
        Create an item for a ui component. This method can be called from UIComponents.
        """
        item = DockItem(ui_component.title)
        item.add(ui_component.open())
        group = DockGroup()
        group.insert_item(item)
        placement = ui_component.placement
        if placement:
            if placement == 'floating':
                add_new_group_floating(group, self.layout, ui_component.size)
            else:
                location = self.layout.get_widgets(placement[1])[0]
                { 'left': add_new_group_left,
                  'right': add_new_group_right,
                  'above': add_new_group_above,
                  'below': add_new_group_below }[placement[0]](location, group)
        else:
            add_new_group_floating(group)
        item.show()
        item.ui_component = ui_component
        group.show()
Ejemplo n.º 10
0
    def open(self):

        load_accel_map()

        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(self.title)
        self.window.set_size_request(*self.size)
        self.window.set_resizable(self.resizable)

        # set default icons of gaphor windows
        icon_dir = os.path.abspath(pkg_resources.resource_filename('gaphor.ui', 'pixmaps'))
        icons = (gtk.gdk.pixbuf_new_from_file(os.path.join(icon_dir, f)) for f in ICONS)
        self.window.set_icon_list(*icons)

        self.window.add_accel_group(self.ui_manager.get_accel_group())

        
        # Create a full featured window.
        vbox = gtk.VBox()
        self.window.add(vbox)
        vbox.show()

        menubar = self.ui_manager.get_widget(self.menubar_path)
        if menubar:
            vbox.pack_start(menubar, expand=False)
        
        toolbar = self.ui_manager.get_widget(self.toolbar_path)
        if toolbar:
            vbox.pack_start(toolbar, expand=False)

        def _factory(name):
            comp = self.component_registry.get_utility(IUIComponent, name)
            logger.debug('open component %s' % str(comp))
            return comp.open()

        filename = pkg_resources.resource_filename('gaphor.ui', 'layout.xml')
        self.layout = DockLayout()

        with open(filename) as f:
            deserialize(self.layout, vbox, f.read(), _factory)
        
        self.layout.connect('item-closed', self._on_item_closed)
        self.layout.connect('item-selected', self._on_item_selected)

        vbox.show()
        # TODO: add statusbar

        self.window.show()

        self.window.connect('delete-event', self._on_window_delete)

        # We want to store the window size, so it can be reloaded on startup
        self.window.set_property('allow-shrink', True)
        self.window.connect('size-allocate', self._on_window_size_allocate)
        self.window.connect('destroy', self._on_window_destroy)
        #self.window.connect_after('key-press-event', self._on_key_press_event)

        cr = self.component_registry
        cr.register_handler(self._on_file_manager_state_changed)
        cr.register_handler(self._on_undo_manager_state_changed)
        cr.register_handler(self._new_model_content)
Ejemplo n.º 11
0
class PlacementTest(unittest.TestCase):

    def setUp(self):
        self.layout = DockLayout()
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.frame = DockFrame()
        self.group = DockGroup()

        self.layout.add(self.frame)
        self.window.add(self.frame)
        self.frame.add(self.group)

    def test_placement_left(self):

        g1, g2 = DockGroup(), DockGroup()

        docklayout.add_new_group_left(self.group, g1)

        paned = g1.get_parent()
        assert isinstance(paned, DockPaned), paned
        assert self.group.get_parent() is paned
        assert paned.get_nth_item(0) is g1
        assert paned.get_nth_item(1) is self.group

        docklayout.add_new_group_left(self.group, g2)
        assert self.group.get_parent() is paned
        assert g2.get_parent() is paned
        assert paned.get_nth_item(0) is g1
        assert paned.get_nth_item(1) is g2
        assert paned.get_nth_item(2) is self.group

    def test_placement_right(self):

        g1, g2 = DockGroup(), DockGroup()

        docklayout.add_new_group_right(self.group, g1)

        paned = g1.get_parent()
        assert isinstance(paned, DockPaned), paned
        assert self.group.get_parent() is paned
        assert paned.get_nth_item(0) is self.group
        assert paned.get_nth_item(1) is g1

        docklayout.add_new_group_right(self.group, g2)
        assert self.group.get_parent() is paned
        assert g2.get_parent() is paned
        assert paned.get_nth_item(0) is self.group
        assert paned.get_nth_item(1) is g2
        assert paned.get_nth_item(2) is g1


    def test_placement_above(self):

        g1, g2 = DockGroup(), DockGroup()

        docklayout.add_new_group_above(self.group, g1)

        paned = g1.get_parent()
        assert isinstance(paned, DockPaned), paned
        assert self.group.get_parent() is paned
        assert paned.get_nth_item(0) is g1
        assert paned.get_nth_item(1) is self.group

        docklayout.add_new_group_above(self.group, g2)
        assert self.group.get_parent() is paned
        assert g2.get_parent() is paned
        assert paned.get_nth_item(0) is g1
        assert paned.get_nth_item(1) is g2
        assert paned.get_nth_item(2) is self.group

    def test_placement_below(self):

        g1, g2 = DockGroup(), DockGroup()

        docklayout.add_new_group_below(self.group, g1)

        paned = g1.get_parent()
        assert isinstance(paned, DockPaned), paned
        assert self.group.get_parent() is paned
        assert paned.get_nth_item(0) is self.group
        assert paned.get_nth_item(1) is g1

        docklayout.add_new_group_below(self.group, g2)
        assert self.group.get_parent() is paned
        assert g2.get_parent() is paned
        assert paned.get_nth_item(0) is self.group
        assert paned.get_nth_item(1) is g2
        assert paned.get_nth_item(2) is g1
Ejemplo n.º 12
0
class TestDockLayoutDnD(unittest.TestCase):

    def setUp(self):

        self.layout = DockLayout()

        def drag_get_data(widget, context, target, timestamp):
            selection_data = StubSelectionData()
            context.source_widget.do_drag_data_get(context, selection_data, None, timestamp)
            self.layout.on_widget_drag_data_received(widget, context, 20, 20, selection_data, None, timestamp)

        DockGroup.drag_get_data = drag_get_data
        DockPaned.drag_get_data = drag_get_data
        DockFrame.drag_get_data = drag_get_data

    def tearDown(self):
        del self.layout
        del DockGroup.drag_get_data
        del DockPaned.drag_get_data
        del DockFrame.drag_get_data

    def test_drag_drop_on_group(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paned = DockPaned()
        group = DockGroup()
        item = DockItem()

        layout = self.layout

        layout.add(frame)

        win.add(frame)
        frame.add(paned)
        paned.add(group)
        group.add(item)

        win.set_default_size(200, 200)
        win.show_all()

        while gtk.events_pending():
            gtk.main_iteration()


        context = StubContext(group, [group.items[0]])

        group.do_drag_begin(context)
        x, y = 30, 30
        layout.on_widget_drag_motion(group, context, x, y, 0)

        assert layout._drag_data
        assert layout._drag_data.drop_widget is group

        layout.on_widget_drag_drop(group, context, x, y, 0)

    def test_drag_drop_on_paned(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paned = DockPaned()
        groups = (DockGroup(), DockGroup())
        item = DockItem()

        layout = self.layout

        layout.add(frame)

        win.add(frame)
        frame.add(paned)
        map(paned.add, groups)
        groups[0].add(item)

        win.set_default_size(200, 200)
        win.show_all()


        x, y = 10, 10
        context = StubContext(groups[0], [groups[0].items[0]])
        layout.on_widget_drag_motion(paned, context, x, y, 0)

        assert layout._drag_data
        assert layout._drag_data.drop_widget is paned, '%s != %s' % (layout._drag_data.drop_widget, paned)

    def test_remove_paned_with_one_child(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paned = DockPaned()
        groups = (DockGroup(), DockGroup())
        item = DockItem()

        layout = self.layout

        layout.add(frame)

        win.add(frame)
        frame.add(paned)
        map(paned.add, groups)
        #groups[0].add(item)

        win.set_default_size(200, 200)
        win.show_all()

        # simulate end of DnD on group
        context = StubContext(groups[0], None)
        layout.on_widget_drag_end(groups[0], context)

        assert not paned.get_parent()
        assert groups[1].get_parent() is frame

    def test_remove_nested_paned_with_one_child(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paneds = (DockPaned(), DockPaned())
        groups = (DockGroup(), DockGroup())
        item = DockItem()

        layout = self.layout

        layout.add(frame)

        win.add(frame)
        frame.add(paneds[0])
        paneds[0].add(groups[0])
        paneds[0].add(paneds[1])
        paneds[1].add(groups[1])
        #groups[0].add(item)

        win.set_default_size(200, 200)
        win.show_all()

        # simulate end of DnD on group, where group is removed and only one
        # paned remains.
        context = StubContext(groups[0], None)
        layout.on_widget_drag_end(paneds[1], context)

        assert not paneds[1].get_parent()
        assert groups[1].get_parent() is paneds[0], (paneds, groups[1].get_parent())

    def test_remove_empty_groups_recursively(self):
        win = gtk.Window(gtk.WINDOW_TOPLEVEL)
        frame = DockFrame()
        paneds = (DockPaned(), DockPaned(), DockPaned())
        group = DockGroup()
        item = DockItem()

        layout = self.layout

        layout.add(frame)

        win.add(frame)
        frame.add(paneds[0])
        paneds[0].add(paneds[1])
        paneds[1].add(paneds[2])
        paneds[2].add(group)

        win.set_default_size(200, 200)
        win.show_all()

        context = StubContext(group, None)
        layout.on_widget_drag_end(group, context)

        # TODO: check is paned[0]
        assert not paneds[0].get_parent()
Ejemplo n.º 13
0
    def __init__(self, docklayout=None, dockframe=None):
        gtk.Window.__init__(self)

        self.set_default_size(500, 150)
        self.set_title("etk.docking demo")
        self.set_border_width(4)
        self.file_counter = 1
        self.subwindows = []

        vbox = gtk.VBox()
        vbox.set_spacing(4)
        self.add(vbox)

        ########################################################################
        # Docking
        ########################################################################
        if docklayout and dockframe:
            self.dockframe = dockframe
            self.docklayout = docklayout
        else:
            self.dockframe = DockFrame()
            self.dockframe.set_border_width(8)
            g = DockGroup()
            g.set_name("main")
            self.dockframe.add(g)
            self.docklayout = DockLayout()
            self.docklayout.add(self.dockframe)

        settings["main"].auto_remove = False
        settings["main"].can_float = True
        settings["main"].inherit_settings = False
        settings["main"].expand = False

        # To change default group behaviour:
        # self.docklayout.settings[None].inherit_settings = False

        vbox.pack_start(self.dockframe)

        def on_item_closed(layout, group, item):
            item.destroy()
            print "closed item:", item.title

        self.docklayout.connect("item-closed", on_item_closed)

        def on_item_selected(layout, group, item):
            print "Selected item:", item.title

        self.docklayout.connect("item-selected", on_item_selected)

        ########################################################################
        # Testing Tools
        ########################################################################
        adddibutton = gtk.Button("Create docked items")
        adddibutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        adddibutton.connect("clicked", self._on_add_di_button_clicked)
        vbox.pack_start(adddibutton, False, False)

        orientationbutton = gtk.Button("Switch Orientation")
        orientationbutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        orientationbutton.connect("clicked", self._on_orientation_button_clicked)
        vbox.pack_start(orientationbutton, False, False)

        hbox = gtk.HBox()

        savebutton = gtk.Button("Save layout")
        savebutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        savebutton.connect("clicked", self._on_save_button_clicked)
        hbox.pack_start(savebutton, True, True)

        loadbutton = gtk.Button("Load layout")
        loadbutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        loadbutton.connect("clicked", self._on_load_button_clicked)
        hbox.pack_start(loadbutton, True, True)

        vbox.pack_start(hbox, False, False)

        self.show_all()
Ejemplo n.º 14
0
class MainWindow(gtk.Window):
    def __init__(self, docklayout=None, dockframe=None):
        gtk.Window.__init__(self)

        self.set_default_size(500, 150)
        self.set_title("etk.docking demo")
        self.set_border_width(4)
        self.file_counter = 1
        self.subwindows = []

        vbox = gtk.VBox()
        vbox.set_spacing(4)
        self.add(vbox)

        ########################################################################
        # Docking
        ########################################################################
        if docklayout and dockframe:
            self.dockframe = dockframe
            self.docklayout = docklayout
        else:
            self.dockframe = DockFrame()
            self.dockframe.set_border_width(8)
            g = DockGroup()
            g.set_name("main")
            self.dockframe.add(g)
            self.docklayout = DockLayout()
            self.docklayout.add(self.dockframe)

        settings["main"].auto_remove = False
        settings["main"].can_float = True
        settings["main"].inherit_settings = False
        settings["main"].expand = False

        # To change default group behaviour:
        # self.docklayout.settings[None].inherit_settings = False

        vbox.pack_start(self.dockframe)

        def on_item_closed(layout, group, item):
            item.destroy()
            print "closed item:", item.title

        self.docklayout.connect("item-closed", on_item_closed)

        def on_item_selected(layout, group, item):
            print "Selected item:", item.title

        self.docklayout.connect("item-selected", on_item_selected)

        ########################################################################
        # Testing Tools
        ########################################################################
        adddibutton = gtk.Button("Create docked items")
        adddibutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        adddibutton.connect("clicked", self._on_add_di_button_clicked)
        vbox.pack_start(adddibutton, False, False)

        orientationbutton = gtk.Button("Switch Orientation")
        orientationbutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        orientationbutton.connect("clicked", self._on_orientation_button_clicked)
        vbox.pack_start(orientationbutton, False, False)

        hbox = gtk.HBox()

        savebutton = gtk.Button("Save layout")
        savebutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        savebutton.connect("clicked", self._on_save_button_clicked)
        hbox.pack_start(savebutton, True, True)

        loadbutton = gtk.Button("Load layout")
        loadbutton.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
        loadbutton.connect("clicked", self._on_load_button_clicked)
        hbox.pack_start(loadbutton, True, True)

        vbox.pack_start(hbox, False, False)

        self.show_all()

        # def on_has_toplevel_focus(window, pspec):
        #    print 'Has toplevel focus', window, pspec
        #    print 'Focus widget is', window.get_focus()

        # self.connect('notify::has-toplevel-focus', on_has_toplevel_focus)

    def _on_add_di_button_clicked(self, button):
        def add_dockitems(child):
            if isinstance(child, DockGroup):
                self._add_dockitems(child)
            elif isinstance(child, DockPaned):
                for child in child:
                    add_dockitems(child)

        for child in self.dockframe:
            add_dockitems(child)

    def _on_orientation_button_clicked(self, button):
        def switch_orientation(paned):
            if isinstance(paned, DockPaned):
                if paned.get_orientation() == gtk.ORIENTATION_HORIZONTAL:
                    paned.set_orientation(gtk.ORIENTATION_VERTICAL)
                else:
                    paned.set_orientation(gtk.ORIENTATION_HORIZONTAL)

                for child in paned.get_children():
                    switch_orientation(child)

        paned = self.dockframe.get_children()[0]
        switch_orientation(paned)

    def _on_save_button_clicked(self, button):
        file = "demo.sav"
        s = dockstore.serialize(self.docklayout)

        with open(file, "w") as f:
            f.write(s)

    def _on_load_button_clicked(self, button):
        file = "demo.sav"

        with open(file) as f:
            s = f.read()

        newlayout = dockstore.deserialize(s, self._create_content)
        main_frames = list(dockstore.get_main_frames(newlayout))
        assert len(main_frames) == 1, main_frames
        subwindow = MainWindow(newlayout, main_frames[0])
        self.subwindows.append(subwindow)
        dockstore.finish(newlayout, main_frames[0])

        for f in newlayout.frames:
            f.get_toplevel().show_all()

    def _create_content(self, text=None):
        # Create a TextView and set some example text
        scrolledwindow = gtk.ScrolledWindow()
        scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        textview = gtk.TextView()
        textview.get_buffer().set_text(text)
        scrolledwindow.add(textview)
        return scrolledwindow

    def _add_dockitems(self, dockgroup):
        examples = [
            (gtk.STOCK_EXECUTE, "calculator", "#!/usr/bin/env python\n\nprint 'Hello!'"),
            (gtk.STOCK_OPEN, "Hi!", "Hello!"),
            (gtk.STOCK_FILE, "ABC", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
            (gtk.STOCK_FIND, "abc", "abcdefghijklmnopqrstuvwxyz"),
            (gtk.STOCK_HARDDISK, "browser", "0123456789"),
            (gtk.STOCK_HOME, "today", "9876543210"),
            gtk.Notebook,
        ]

        for i in [1]:  # range(random.randrange(1, 10, 1)):
            example = random.choice(examples)

            if example is gtk.Notebook:
                child = gtk.Notebook()
                child.append_page(gtk.Button("Click me"), gtk.Label("New %s" % self.file_counter))
                stock_id = ""
                tooltip_text = "notebook"
            else:
                stock_id, tooltip_text, text = example
                child = self._create_content(text)
                child.set_name(stock_id)

            # Create a DockItem and add our TextView
            di = DockItem(title="New %s" % self.file_counter, title_tooltip_text=tooltip_text, stock_id=stock_id)

            def on_close(item):
                print "close:", item

            di.connect("close", on_close)
            di.add(child)
            di.show_all()

            # Add out DockItem to the DockGroup
            dockgroup.add(di)

            # Increment file counter
            self.file_counter += 1
Ejemplo n.º 15
0
class MainWindow(object):
    """
    The main window for the application.
    It contains a Namespace-based tree view and a menu and a statusbar.
    """
    interface.implements(IService, IActionProvider)


    component_registry = inject('component_registry')
    properties = inject('properties')
    element_factory = inject('element_factory')
    action_manager = inject('action_manager')
    file_manager = inject('file_manager')
    ui_manager = inject('ui_manager')

    title = 'Gaphor'
    size = property(lambda s: s.properties.get('ui.window-size', (760, 580)))
    menubar_path = '/mainwindow'
    toolbar_path = '/mainwindow-toolbar'
    resizable = True

    menu_xml = """
      <ui>
        <menubar name="mainwindow">
          <menu action="file">
            <placeholder name="primary" />
            <separator />
            <menu action="file-export" />
            <menu action="file-import" />
            <separator />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
            <separator />
            <menuitem action="file-quit" />
          </menu>
          <menu action="edit">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="diagram">
            <menuitem action="diagram-drawing-style" />
            <separator />
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="tools">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="window">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
          <menu action="help">
            <placeholder name="primary" />
            <placeholder name="secondary" />
            <placeholder name="ternary" />
          </menu>
        </menubar>
        <toolbar name='mainwindow-toolbar'>
            <placeholder name="left" />
            <separator expand="true" />
            <placeholder name="right" />
        </toolbar>
      </ui>
    """

    def __init__(self):
        self.window = None
        self.model_changed = False

        # Map tab contents to DiagramTab
        #self.notebook_map = {}
        self._current_diagram_tab = None
        self.layout = None


    def init(self, app=None):
        #self.init_pygtk()
        self.init_stock_icons()
        self.init_action_group()
        self.init_ui_components()


    def init_pygtk(self):
        """
        Make sure we have GTK+ >= 2.0
        """
        import pygtk
        pygtk.require('2.0')
        del pygtk


    def init_stock_icons(self):
        # Load stock items
        import gaphor.ui.stock
        gaphor.ui.stock.load_stock_icons()


    def init_ui_components(self):
        component_registry = self.component_registry
        for ep in pkg_resources.iter_entry_points('gaphor.uicomponents'):
            log.debug('found entry point uicomponent.%s' % ep.name)
            cls = ep.load()
            if not IUIComponent.implementedBy(cls):
                raise NameError('Entry point %s doesn''t provide IUIComponent' % ep.name)
            uicomp = cls()
            uicomp.ui_name = ep.name
            component_registry.register_utility(uicomp, IUIComponent, ep.name)
            if IActionProvider.providedBy(uicomp):
                self.action_manager.register_action_provider(uicomp)
                

    def shutdown(self):
        if self.window:
            self.window.destroy()
            self.window = None
        save_accel_map()

        cr = self.component_registry
        cr.unregister_handler(self._on_file_manager_state_changed)
        cr.unregister_handler(self._on_undo_manager_state_changed)
        cr.unregister_handler(self._new_model_content)
        #self.ui_manager.remove_action_group(self.action_group)


    def init_action_group(self):
        self.action_group = build_action_group(self)
        for name, label in (('file', '_File'),
                            ('file-export', '_Export'),
                            ('file-import', '_Import'),
                            ('edit', '_Edit'),
                            ('diagram', '_Diagram'),
                            ('tools', '_Tools'),
                            ('window', '_Window'),
                            ('help', '_Help')):
            a = gtk.Action(name, label, None, None)
            a.set_property('hide-if-empty', False)
            self.action_group.add_action(a)
        self._tab_ui_settings = None
        self.action_group.get_action('diagram-drawing-style').set_active(self.properties('diagram.sloppiness', 0) != 0)

        self.action_manager.register_action_provider(self)


    def get_filename(self):
        """
        Return the file name of the currently opened model.
        """
        return self.file_manager.filename


    def get_current_diagram_tab(self):
        """
        Get the currently opened and viewed DiagramTab, shown on the right
        side of the main window.
        See also: get_current_diagram(), get_current_diagram_view().
        """
        return self._current_diagram_tab


    def get_current_diagram(self):
        """
        Return the Diagram associated with the viewed DiagramTab.
        See also: get_current_diagram_tab(), get_current_diagram_view().
        """
        tab = self._current_diagram_tab
        return tab and tab.get_diagram()


    def get_current_diagram_view(self):
        """
        Return the DiagramView associated with the viewed DiagramTab.
        See also: get_current_diagram_tab(), get_current_diagram().
        """
        tab = self._current_diagram_tab
        return tab and tab.get_view()


    def ask_to_close(self):
        """
        Ask user to close window if the model has changed.
        The user is asked to either discard the changes, keep the
        application running or save the model and quit afterwards.
        """
        if self.model_changed:
            dialog = gtk.MessageDialog(self.window,
                    gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                    gtk.MESSAGE_WARNING,
                    gtk.BUTTONS_NONE,
                    _('Save changed to your model before closing?'))
            dialog.format_secondary_text(
                    _('If you close without saving, your changes will be discarded.'))
            dialog.add_buttons('Close _without saving', gtk.RESPONSE_REJECT,
                    gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                    gtk.STOCK_SAVE, gtk.RESPONSE_YES)
            dialog.set_default_response(gtk.RESPONSE_YES)
            response = dialog.run()
            dialog.destroy()

            if response == gtk.RESPONSE_YES:
                # On filedialog.cancel, the application should not close.
                return self.file_manager.action_save()
            return response == gtk.RESPONSE_REJECT
        return True


    def show_diagram(self, diagram):
        """
        Show a Diagram element in a new tab.
        If a tab is already open, show that one instead.
        """
        # Try to find an existing window/tab and let it get focus:
        for tab in self.get_tabs():
            if tab.get_diagram() is diagram:
                self.set_current_page(tab)
                return tab

        tab = DiagramTab(diagram)
        dock_item = tab.construct()
        dock_item.set_name('diagram-tab')
        dock_item.diagram_tab = tab
        assert dock_item.get_name() == 'diagram-tab'
        tab.set_drawing_style(self.properties('diagram.sloppiness', 0))

        self.add_tab(dock_item)

        return tab


    def open(self):

        load_accel_map()

        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(self.title)
        self.window.set_size_request(*self.size)
        self.window.set_resizable(self.resizable)

        # set default icons of gaphor windows
        icon_dir = os.path.abspath(pkg_resources.resource_filename('gaphor.ui', 'pixmaps'))
        icons = (gtk.gdk.pixbuf_new_from_file(os.path.join(icon_dir, f)) for f in ICONS)
        self.window.set_icon_list(*icons)

        self.window.add_accel_group(self.ui_manager.get_accel_group())

        
        # Create a full featured window.
        vbox = gtk.VBox()
        self.window.add(vbox)
        vbox.show()

        menubar = self.ui_manager.get_widget(self.menubar_path)
        if menubar:
            vbox.pack_start(menubar, expand=False)
        
        toolbar = self.ui_manager.get_widget(self.toolbar_path)
        if toolbar:
            vbox.pack_start(toolbar, expand=False)

        def _factory(name):
            comp = self.component_registry.get_utility(IUIComponent, name)
            logger.debug('open component %s' % str(comp))
            return comp.open()

        filename = pkg_resources.resource_filename('gaphor.ui', 'layout.xml')
        self.layout = DockLayout()

        with open(filename) as f:
            deserialize(self.layout, vbox, f.read(), _factory)
        
        self.layout.connect('item-closed', self._on_item_closed)
        self.layout.connect('item-selected', self._on_item_selected)

        vbox.show()
        # TODO: add statusbar

        self.window.show()

        self.window.connect('delete-event', self._on_window_delete)

        # We want to store the window size, so it can be reloaded on startup
        self.window.set_property('allow-shrink', True)
        self.window.connect('size-allocate', self._on_window_size_allocate)
        self.window.connect('destroy', self._on_window_destroy)
        #self.window.connect_after('key-press-event', self._on_key_press_event)

        cr = self.component_registry
        cr.register_handler(self._on_file_manager_state_changed)
        cr.register_handler(self._on_undo_manager_state_changed)
        cr.register_handler(self._new_model_content)
        # TODO: register on ElementCreate/Delete event


    def open_welcome_page(self):
        """
        Create a new tab with a textual welcome page, a sort of 101 for
        Gaphor.
        """
        pass

    def set_title(self):
        """
        Sets the window title.
        """
        filename = self.file_manager.filename
        if self.window:
            if filename:
                title = '%s - %s' % (self.title, filename)
            else:
                title = self.title
            if self.model_changed:
                title += ' *'
            self.window.set_title(title)


    # Notebook methods:

    def add_tab(self, item):
        """
        Create a new tab on the notebook with window as its contents.
        Returns: The page number of the tab.
        """
        group = list(self.layout.get_widgets('diagrams'))[0]
        group.insert_item(item)
        item.show_all()
        #item.diagram_tab = tab
        #self.notebook_map[item] = tab

    def set_current_page(self, tab):
        """
        Force a specific tab (DiagramTab) to the foreground.
        """
        for i in self.layout.get_widgets('diagram-tab'):
            if i.diagram_tab is tab:
                g = i.get_parent()
                g.set_current_item(g.item_num(i))
                return
        #for p, t in self.notebook_map.iteritems():
        #    if tab is t:
        #        num = self.notebook.page_num(p)
        #        self.notebook.set_current_page(num)
        #        return
        pass


    def get_tabs(self):
        tabs = [i.diagram_tab for i in self.layout.get_widgets('diagram-tab')]
        return tabs

    # Signal callbacks:

    @component.adapter(ModelFactoryEvent)
    def _new_model_content(self, event):
        """
        Open the toplevel element and load toplevel diagrams.
        """
        # TODO: Make handlers for ModelFactoryEvent from within the GUI obj
        for diagram in self.element_factory.select(lambda e: e.isKindOf(uml2.Diagram) and not (e.namespace and e.namespace.namespace)):
            self.show_diagram(diagram)
    

    @component.adapter(FileManagerStateChanged)
    def _on_file_manager_state_changed(self, event):
        # We're only interested in file operations
        if event.service is self.file_manager:
            self.model_changed = False
            self.set_title()


    @component.adapter(UndoManagerStateChanged)
    def _on_undo_manager_state_changed(self, event):
        """
        """
        undo_manager = event.service
        if not self.model_changed and undo_manager.can_undo():
            self.model_changed = True
            self.set_title()


    def _on_window_destroy(self, window):
        """
        Window is destroyed... Quit the application.
        """
        self.window = None
        if gobject.main_depth() > 0:
            gtk.main_quit()
        cr = self.component_registry
        cr.unregister_handler(self._on_undo_manager_state_changed)
        cr.unregister_handler(self._on_file_manager_state_changed)
        cr.unregister_handler(self._new_model_content)

    def _on_window_delete(self, window = None, event = None):
        return not self.ask_to_close()

    def _clear_ui_settings(self):
        try:
            ui_manager = self.ui_manager
        except component.ComponentLookupError as e:
            log.warning('No UI manager service found')
        else:
            if self._tab_ui_settings:
                action_group, ui_id = self._tab_ui_settings
                self.ui_manager.remove_action_group(action_group)
                self.ui_manager.remove_ui(ui_id)
                self._tab_ui_settings = None

    def _on_item_closed(self, layout, group, item):
        self._clear_ui_settings()
        try:
            ui_component = item.ui_component
        except AttributeError:
            log.warning('No ui component defined on item')
        else:
            ui_component.close()
        item.destroy()

    def _on_item_selected(self, layout, group, item):
        """
        Another page (tab) is put on the front of the diagram notebook.
        A dummy action is executed.
        """
        # TODO: Here the magic happens!
        # TODO: Need to see what the active view is, or make toolbox actions global
        self._clear_ui_settings()

        # Is it a diagram view?
        try:
            tab = item.diagram_tab
        except AttributeError:
            # Not a diagram tab
            return

        self._current_diagram_tab = tab

        #content = self.notebook.get_nth_page(page_num)
        #tab = self.notebook_map.get(content)
        #assert isinstance(tab, DiagramTab), str(tab)
        
        self.ui_manager.insert_action_group(tab.action_group, -1)
        ui_id = self.ui_manager.add_ui_from_string(tab.menu_xml)
        self._tab_ui_settings = tab.action_group, ui_id
        log.debug('Menus updated with %s, %d' % self._tab_ui_settings)

        # Make sure everyone knows the selection has changed.
        self.component_registry.handle(DiagramTabChange(item), DiagramSelectionChange(tab.view, tab.view.focused_item, tab.view.selected_items))


    def _on_window_size_allocate(self, window, allocation):
        """
        Store the window size in a property.
        """
        self.properties.set('ui.window-size', (allocation.width, allocation.height))


    # Actions:

    @action(name='file-quit', stock_id='gtk-quit')
    def quit(self):
        # TODO: check for changes (e.g. undo manager), fault-save
        self.ask_to_close() and gtk.main_quit()
        self.shutdown()


    @toggle_action(name='diagram-drawing-style', label='Hand drawn style', active=False)
    def hand_drawn_style(self, active):
        """
        Toggle between straight diagrams and "hand drawn" diagram style.
        """
        if active:
            sloppiness = 0.5
        else:
            sloppiness = 0.0
        for tab in self.get_tabs():
            tab.set_drawing_style(sloppiness)
        self.properties.set('diagram.sloppiness', sloppiness)


    def create_item(self, ui_component): #, widget, title, placement=None):
        """
        Create an item for a ui component. This method can be called from UIComponents.
        """
        item = DockItem(ui_component.title)
        item.add(ui_component.open())
        group = DockGroup()
        group.insert_item(item)
        placement = ui_component.placement
        if placement:
            if placement == 'floating':
                add_new_group_floating(group, self.layout, ui_component.size)
            else:
                location = self.layout.get_widgets(placement[1])[0]
                { 'left': add_new_group_left,
                  'right': add_new_group_right,
                  'above': add_new_group_above,
                  'below': add_new_group_below }[placement[0]](location, group)
        else:
            add_new_group_floating(group)
        item.show()
        item.ui_component = ui_component
        group.show()
Ejemplo n.º 16
0
    def open(self):

        load_accel_map()

        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title(self.title)
        self.window.set_size_request(*self.size)
        self.window.set_resizable(self.resizable)

        # set default icons of gaphor windows
        icon_dir = os.path.abspath(pkg_resources.resource_filename('gaphor.ui', 'pixmaps'))
        icons = (gtk.gdk.pixbuf_new_from_file(os.path.join(icon_dir, f)) for f in ICONS)
        self.window.set_icon_list(*icons)

        self.window.add_accel_group(self.ui_manager.get_accel_group())

        
        # Create a full featured window.
        vbox = gtk.VBox()
        self.window.add(vbox)
        vbox.show()

        menubar = self.ui_manager.get_widget(self.menubar_path)
        if menubar:
            vbox.pack_start(menubar, expand=False)
        
        toolbar = self.ui_manager.get_widget(self.toolbar_path)
        if toolbar:
            vbox.pack_start(toolbar, expand=False)

        def _factory(name):
            comp = self.component_registry.get_utility(IUIComponent, name)
            logger.debug('open component %s' % str(comp))
            return comp.open()

        filename = pkg_resources.resource_filename('gaphor.ui', 'layout.xml')
        self.layout = DockLayout()

        with open(filename) as f:
            deserialize(self.layout, vbox, f.read(), _factory)
        
        self.layout.connect('item-closed', self._on_item_closed)
        self.layout.connect('item-selected', self._on_item_selected)

        vbox.show()
        # TODO: add statusbar

        self.window.show()

        self.window.connect('delete-event', self._on_window_delete)

        # We want to store the window size, so it can be reloaded on startup
        self.window.set_property('allow-shrink', True)
        self.window.connect('size-allocate', self._on_window_size_allocate)
        self.window.connect('destroy', self._on_window_destroy)
        #self.window.connect_after('key-press-event', self._on_key_press_event)

        cr = self.component_registry
        cr.register_handler(self._on_file_manager_state_changed)
        cr.register_handler(self._on_undo_manager_state_changed)
        cr.register_handler(self._new_model_content)