コード例 #1
0
ファイル: contenthandlers.py プロジェクト: oaubert/advene2
    def get_view (self, compact=False):
        """Generate a view widget for editing SVG."""
        vbox=gtk.VBox()

        if self.parent is not None and hasattr(self.parent, 'begin'):
            i=image_from_position(self.controller, self.parent.begin)
            self.view = ShapeEditor(background=i, pixmap_dir=config.data.advenefile('pixmaps'))

            def snapshot_update_cb(context, target):
                if context.globals['position'] == self.parent.begin:
                    # Refresh image
                    i=image_from_position(self.controller, self.parent.begin)
                    self.view.set_background(i)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='SnapshotUpdate',
                                                                           method=snapshot_update_cb))

            def annotation_update_cb(context, target):
                i=image_from_position(self.controller, self.parent.begin)
                self.view.set_background(i)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='AnnotationEditEnd',
                                                                           method=annotation_update_cb))

        else:
            self.view = ShapeEditor(pixmap_dir=config.data.advenefile('pixmaps'))

        self.parse_svg()

        self.view.drawer.widget.connect('drag-data-received', self.drawer_drag_received)
        self.view.drawer.widget.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
                                              gtk.DEST_DEFAULT_HIGHLIGHT |
                                              gtk.DEST_DEFAULT_ALL,
                                              config.data.drag_type['view']
                                              + config.data.drag_type['annotation']
                                              + config.data.drag_type['uri-list'],
                                              gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_LINK)

        def edit_svg(b):
            vbox.foreach(vbox.remove)
            vbox.add(self.view.widget)

            b=gtk.Button(_("Edit XML"))
            b.connect('clicked', edit_xml)
            vbox.pack_start(b, expand=False)
            self.editing_source=False
            vbox.show_all()
            return True

        def edit_xml(b):
            if self.sourceview is None:
                self.sourceview=TextContentHandler(element=self.element,
                                                   controller=self.controller,
                                                   parent=self.parent)
                self.sourceview.widget=self.sourceview.get_view()

            vbox.foreach(vbox.remove)
            vbox.add(self.sourceview.widget)

            b=gtk.Button(_("Graphical editor"))
            b.connect('clicked', edit_svg)
            vbox.pack_start(b, expand=False)
            self.editing_source=True
            vbox.show_all()
            return True

        edit_svg(None)
        return vbox
コード例 #2
0
ファイル: contenthandlers.py プロジェクト: oaubert/advene2
class SVGContentHandler (ContentHandler):
    """Create a SVG edit form for the given element."""
    def can_handle(mimetype):
        res=0
        if mimetype == 'image/svg+xml':
            res=80
        return res
    can_handle=staticmethod(can_handle)

    def __init__ (self, element, controller=None, parent=None, **kw):
        self.element = element
        self.controller=controller
        self.parent=parent
        self.editable = True
        # Internal rules defined by the plugin
        self.rules=[]
        self.fname=None
        self.view = None
        self.sourceview=None
        self.editing_source=False

    def close(self):
        for r in self.rules:
            self.controller.event_handler.remove_rule(r, 'internal')
        return True

    def set_editable (self, boolean):
        self.editable = boolean
        if self.sourceview:
            self.sourceview.set_editable(boolean)

    def parse_svg(self):
        if self.element.data:
            try:
                f=self.element.as_file
                root=ET.parse(f).getroot()
                f.close()
            except xml.parsers.expat.ExpatError:
                root=None
                dialog.message_dialog(
                    _("Error while parsing SVG content:\n\n%s") % unicode(e),
                    icon=gtk.MESSAGE_ERROR)
            if root:
                self.view.drawer.clear_objects()
                path=''
                if self.parent is not None and hasattr(self.parent, 'file_'):
                    # We are in a resource. Pass its path as current path.
                    path=os.path.dirname(self.parent.file_)
                self.view.drawer.parse_svg(root, current_path=path)
        return True

    def update_element (self):
        """Update the element fields according to the values in the view."""
        if not self.editable:
            return False

        if self.editing_source:
            self.sourceview.update_element()
            # We applied our modifications to the XML source, so
            # parse the source again in the SVG editor
            self.parse_svg()
            return True

        if self.view is None:
            return True

        tree=ET.ElementTree(self.view.drawer.get_svg(relative=False))
        #ET.dump(tree)
        s=StringIO.StringIO()
        tree.write(s, encoding='utf-8')
        self.element.data = s.getvalue()
        s.close()
        # Update the XML source representation
        if self.sourceview is not None:
            self.sourceview.content_set(self.element.data)
        return True

    def drawer_drag_received(self, widget, context, x, y, selection, targetType, time):
        here=None
        url=None
        title=''
        if targetType == config.data.target_type['annotation']:
            here=self.controller.package.get(unicode(selection.data, 'utf8').splitlines()[0])
        elif targetType == config.data.target_type['view']:
            data=decode_drop_parameters(selection.data)
            v=self.controller.package.get(data['id'])
            if v is None:
                print "Cannot find view", data['id']
                return True
            here=v
            title=self.controller.get_title(v)
            ctx=self.controller.build_context()
            root=ctx.evaluate('here/absolute_url')
            url='%s/action/OpenView?id=%s' % (root, v.id)
        elif targetType == config.data.target_type['uri-list']:
            here=None
            url=unicode(selection.data.splitlines()[0], 'utf8')
            title=url
        else:
            # Invalid drop target
            return True

        if url is None and here is not None:
            ctx=self.controller.build_context(here=here)
            title=self.controller.get_title(here)
            url=ctx.evaluate('here/absolute_url')

        if url is None:
            print "Cannot guess url"
            return True

        s=self.view.drawer.clicked_shape( (x, y) )
        if s is None:
            # Drop on no shape. Create one.
            s = self.view.drawer.shape_class()
            s.name = s.SHAPENAME + _(" created from ") + title
            s.color = self.view.defaultcolor
            s.set_bounds( ( (x, y), (x+20, y+20) ) )
            self.view.drawer.add_object(s)
        # Drop on an existing shape. Update its link attribute
        s.link=url
        s.link_label=title
        return False

    def set_begin(self, t):
        i=image_from_position(self.controller, t)
        self.view.set_background(i)
        return True

    def get_view (self, compact=False):
        """Generate a view widget for editing SVG."""
        vbox=gtk.VBox()

        if self.parent is not None and hasattr(self.parent, 'begin'):
            i=image_from_position(self.controller, self.parent.begin)
            self.view = ShapeEditor(background=i, pixmap_dir=config.data.advenefile('pixmaps'))

            def snapshot_update_cb(context, target):
                if context.globals['position'] == self.parent.begin:
                    # Refresh image
                    i=image_from_position(self.controller, self.parent.begin)
                    self.view.set_background(i)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='SnapshotUpdate',
                                                                           method=snapshot_update_cb))

            def annotation_update_cb(context, target):
                i=image_from_position(self.controller, self.parent.begin)
                self.view.set_background(i)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='AnnotationEditEnd',
                                                                           method=annotation_update_cb))

        else:
            self.view = ShapeEditor(pixmap_dir=config.data.advenefile('pixmaps'))

        self.parse_svg()

        self.view.drawer.widget.connect('drag-data-received', self.drawer_drag_received)
        self.view.drawer.widget.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
                                              gtk.DEST_DEFAULT_HIGHLIGHT |
                                              gtk.DEST_DEFAULT_ALL,
                                              config.data.drag_type['view']
                                              + config.data.drag_type['annotation']
                                              + config.data.drag_type['uri-list'],
                                              gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_LINK)

        def edit_svg(b):
            vbox.foreach(vbox.remove)
            vbox.add(self.view.widget)

            b=gtk.Button(_("Edit XML"))
            b.connect('clicked', edit_xml)
            vbox.pack_start(b, expand=False)
            self.editing_source=False
            vbox.show_all()
            return True

        def edit_xml(b):
            if self.sourceview is None:
                self.sourceview=TextContentHandler(element=self.element,
                                                   controller=self.controller,
                                                   parent=self.parent)
                self.sourceview.widget=self.sourceview.get_view()

            vbox.foreach(vbox.remove)
            vbox.add(self.sourceview.widget)

            b=gtk.Button(_("Graphical editor"))
            b.connect('clicked', edit_svg)
            vbox.pack_start(b, expand=False)
            self.editing_source=True
            vbox.show_all()
            return True

        edit_svg(None)
        return vbox
コード例 #3
0
    def get_view(self, compact=False):
        """Generate a view widget for editing SVG."""
        vbox = Gtk.VBox()

        if self.parent is not None and hasattr(self.parent, 'fragment'):
            i = image_from_position(self.controller,
                                    position=self.parent.fragment.begin,
                                    media=self.parent.media)
            vi = self.controller.package.imagecache.video_info
            self.view = ShapeEditor(background=i,
                                    icon_dir=config.data.advenefile('pixmaps'),
                                    default_size=(vi.get('width', 320),
                                                  vi.get('height', 200)))

            def snapshot_update_cb(context, target):
                if context.globals['media'] != self.parent.media:
                    return True
                pos = self.get_background_position()
                if context.globals['position'] == pos:
                    # Refresh image
                    i = image_from_position(self.controller,
                                            position=pos,
                                            media=self.parent.media)
                    self.view.set_background(i)
                return True

            self.rules.append(
                self.controller.event_handler.internal_rule(
                    event='SnapshotUpdate', method=snapshot_update_cb))

            def annotation_update_cb(context, target):
                self.view.background_adj.set_value(0)
                return True

            self.rules.append(
                self.controller.event_handler.internal_rule(
                    event='AnnotationEditEnd', method=annotation_update_cb))

        else:
            self.view = ShapeEditor(icon_dir=config.data.advenefile('pixmaps'))

        self.parse_svg()

        self.view.drawer.widget.connect('drag-data-received',
                                        self.drawer_drag_received)
        self.view.drawer.widget.drag_dest_set(
            Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT
            | Gtk.DestDefaults.ALL,
            config.data.get_target_types('view', 'annotation', 'uri-list'),
            Gdk.DragAction.COPY | Gdk.DragAction.LINK)

        def edit_svg(b=None):
            vbox.foreach(vbox.remove)
            vbox.add(self.view.widget)
            self.editing_source = False
            vbox.show_all()
            return True

        def edit_xml(b=None):
            if self.sourceview is None:
                self.sourceview = TextContentHandler(
                    element=self.element,
                    controller=self.controller,
                    parent=self.parent)
                self.sourceview.widget = self.sourceview.get_view()
                b = get_pixmap_toolbutton('xml.png', edit_svg)
                b.set_tooltip_text(_("Graphical editor"))
                self.sourceview.toolbar.insert(b, 0)

            vbox.foreach(vbox.remove)
            vbox.add(self.sourceview.widget)
            self.editing_source = True
            vbox.show_all()
            return True

        # Insert "View source" button in Shapewidget toolbar
        b = get_pixmap_toolbutton('xml.png', edit_xml)
        b.set_tooltip_text(_("Edit XML"))
        self.view.toolbar.insert(b, 0)

        def update_background(adj):
            pos = self.get_background_position()
            i = image_from_position(self.controller,
                                    position=pos,
                                    media=self.parent.media)
            self.view.set_background(i)
            return True

        self.view.background_adj = Gtk.Adjustment.new(value=0,
                                                      lower=0,
                                                      upper=1.0,
                                                      step_increment=0.1,
                                                      page_increment=0.2,
                                                      page_size=0.2)
        slider = Gtk.HScale.new(self.view.background_adj)
        slider.connect(
            "format-value",
            lambda s, v: helper.format_time(self.parent.fragment.begin + int(
                v * self.parent.fragment.duration)))
        ti = Gtk.ToolItem()
        ti.add(slider)
        ti.set_expand(True)
        self.view.toolbar.insert(ti, -1)
        self.view.background_adj.connect('value-changed', update_background)

        if config.data.preferences['prefer-wysiwyg']:
            edit_svg()
        else:
            edit_xml()
        return vbox
コード例 #4
0
class SVGContentHandler(ContentHandler):
    """Create a SVG edit form for the given element."""
    @staticmethod
    def can_handle(mimetype):
        res = 0
        if mimetype == 'image/svg+xml':
            res = 80
        return res

    def __init__(self, element, controller=None, parent=None, **kw):
        super().__init__(element, controller)
        self.parent = parent
        self.editable = True
        # Internal rules defined by the plugin
        self.rules = []
        self.fname = None
        self.view = None
        self.sourceview = None
        self.editing_source = False

    def close(self):
        for r in self.rules:
            self.controller.event_handler.remove_rule(r, 'internal')
        return True

    def set_editable(self, boolean):
        self.editable = boolean
        if self.sourceview:
            self.sourceview.set_editable(boolean)

    def parse_svg(self):
        if self.element.data:
            try:
                root = ET.parse(self.element.stream).getroot()
            except xml.parsers.expat.ExpatError as e:
                root = None
                dialog.message_dialog(
                    _("Error while parsing SVG content:\n\n%s") % str(e),
                    icon=Gtk.MessageType.ERROR)
            if root is not None:
                self.view.drawer.clear_objects()
                path = ''
                if self.parent is not None and hasattr(self.parent, 'file_'):
                    # We are in a resource. Pass its path as current path.
                    path = os.path.dirname(self.parent.file_)
                self.view.drawer.parse_svg(root, current_path=path)
        return True

    def update_element(self):
        """Update the element fields according to the values in the view."""
        if not self.editable:
            return False

        if self.editing_source:
            self.sourceview.update_element()
            # We applied our modifications to the XML source, so
            # parse the source again in the SVG editor
            self.parse_svg()
            return True

        if self.view is None:
            return True

        tree = ET.ElementTree(self.view.drawer.get_svg(relative=False))
        #ET.dump(tree)
        s = io.StringIO()
        tree.write(s, encoding='unicode')
        self.element.data = s.getvalue()
        s.close()
        # Update the XML source representation
        if self.sourceview is not None:
            self.sourceview.content_set(self.element.data)
        return True

    def get_background_position(self):
        """Return the background position, considering the background slider value.
        """
        frag = self.parent.fragment
        pos = self.controller.round_timestamp(
            frag.begin +
            int(self.view.background_adj.get_value() * frag.duration))
        return pos

    def drawer_drag_received(self, widget, context, x, y, selection,
                             targetType, time):
        here = None
        url = None
        title = ''
        if targetType == config.data.target_type['annotation']:
            here = self.controller.package.annotations.get(
                str(selection.get_data(), 'utf8').split('\n')[0])
        elif targetType == config.data.target_type['view']:
            data = decode_drop_parameters(selection.get_data())
            v = self.controller.package.get_element_by_id(data['id'])
            if v is None:
                logger.error("Cannot find view %s", data['id'])
                return True
            here = v
            title = self.controller.get_title(v)
            ctx = self.controller.build_context()
            root = ctx.evaluateValue('here/absolute_url')
            url = '%s/action/OpenView?id=%s' % (root, v.id)
        elif targetType == config.data.target_type['uri-list']:
            here = None
            url = str(selection.get_data().splitlines()[0], 'utf8')
            title = url
        else:
            # Invalid drop target
            return True

        if url is None and here is not None:
            ctx = self.controller.build_context(here=here)
            title = self.controller.get_title(here)
            url = ctx.evaluateValue('here/absolute_url')

        if url is None:
            logger.error("Cannot guess url after DND")
            return True

        s = self.view.drawer.clicked_shape((x, y))
        if s is None:
            # Drop on no shape. Create one.
            s = self.view.drawer.shape_class()
            s.name = s.SHAPENAME + _(" created from ") + title
            s.color = self.view.defaultcolor
            s.set_bounds(((x, y), (x + 20, y + 20)))
            self.view.drawer.add_object(s)
        # Drop on an existing shape. Update its link attribute
        s.link = url
        s.link_label = title
        return False

    def set_begin(self, t):
        try:
            media = self.parent.media
        except AttributeError:
            media = None

        self.view.set_background(
            image_from_position(self.controller, position=t, media=media))
        return True

    def get_view(self, compact=False):
        """Generate a view widget for editing SVG."""
        vbox = Gtk.VBox()

        if self.parent is not None and hasattr(self.parent, 'fragment'):
            i = image_from_position(self.controller,
                                    position=self.parent.fragment.begin,
                                    media=self.parent.media)
            vi = self.controller.package.imagecache.video_info
            self.view = ShapeEditor(background=i,
                                    icon_dir=config.data.advenefile('pixmaps'),
                                    default_size=(vi.get('width', 320),
                                                  vi.get('height', 200)))

            def snapshot_update_cb(context, target):
                if context.globals['media'] != self.parent.media:
                    return True
                pos = self.get_background_position()
                if context.globals['position'] == pos:
                    # Refresh image
                    i = image_from_position(self.controller,
                                            position=pos,
                                            media=self.parent.media)
                    self.view.set_background(i)
                return True

            self.rules.append(
                self.controller.event_handler.internal_rule(
                    event='SnapshotUpdate', method=snapshot_update_cb))

            def annotation_update_cb(context, target):
                self.view.background_adj.set_value(0)
                return True

            self.rules.append(
                self.controller.event_handler.internal_rule(
                    event='AnnotationEditEnd', method=annotation_update_cb))

        else:
            self.view = ShapeEditor(icon_dir=config.data.advenefile('pixmaps'))

        self.parse_svg()

        self.view.drawer.widget.connect('drag-data-received',
                                        self.drawer_drag_received)
        self.view.drawer.widget.drag_dest_set(
            Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT
            | Gtk.DestDefaults.ALL,
            config.data.get_target_types('view', 'annotation', 'uri-list'),
            Gdk.DragAction.COPY | Gdk.DragAction.LINK)

        def edit_svg(b=None):
            vbox.foreach(vbox.remove)
            vbox.add(self.view.widget)
            self.editing_source = False
            vbox.show_all()
            return True

        def edit_xml(b=None):
            if self.sourceview is None:
                self.sourceview = TextContentHandler(
                    element=self.element,
                    controller=self.controller,
                    parent=self.parent)
                self.sourceview.widget = self.sourceview.get_view()
                b = get_pixmap_toolbutton('xml.png', edit_svg)
                b.set_tooltip_text(_("Graphical editor"))
                self.sourceview.toolbar.insert(b, 0)

            vbox.foreach(vbox.remove)
            vbox.add(self.sourceview.widget)
            self.editing_source = True
            vbox.show_all()
            return True

        # Insert "View source" button in Shapewidget toolbar
        b = get_pixmap_toolbutton('xml.png', edit_xml)
        b.set_tooltip_text(_("Edit XML"))
        self.view.toolbar.insert(b, 0)

        def update_background(adj):
            pos = self.get_background_position()
            i = image_from_position(self.controller,
                                    position=pos,
                                    media=self.parent.media)
            self.view.set_background(i)
            return True

        self.view.background_adj = Gtk.Adjustment.new(value=0,
                                                      lower=0,
                                                      upper=1.0,
                                                      step_increment=0.1,
                                                      page_increment=0.2,
                                                      page_size=0.2)
        slider = Gtk.HScale.new(self.view.background_adj)
        slider.connect(
            "format-value",
            lambda s, v: helper.format_time(self.parent.fragment.begin + int(
                v * self.parent.fragment.duration)))
        ti = Gtk.ToolItem()
        ti.add(slider)
        ti.set_expand(True)
        self.view.toolbar.insert(ti, -1)
        self.view.background_adj.connect('value-changed', update_background)

        if config.data.preferences['prefer-wysiwyg']:
            edit_svg()
        else:
            edit_xml()
        return vbox
コード例 #5
0
ファイル: contenthandlers.py プロジェクト: oaubert/advene
    def get_view (self, compact=False):
        """Generate a view widget for editing SVG."""
        vbox=Gtk.VBox()

        if self.parent is not None and hasattr(self.parent, 'fragment'):
            i = image_from_position(self.controller,
                                    position=self.parent.fragment.begin,
                                    media=self.parent.media)
            vi = self.controller.package.imagecache.video_info
            self.view = ShapeEditor(background=i,
                                    icon_dir=config.data.advenefile('pixmaps'),
                                    default_size=(vi.get('width', 320), vi.get('height', 200)))

            def snapshot_update_cb(context, target):
                if context.globals['media'] != self.parent.media:
                    return True
                pos = self.get_background_position()
                if context.globals['position'] == pos:
                    # Refresh image
                    i = image_from_position(self.controller,
                                            position=pos,
                                            media=self.parent.media)
                    self.view.set_background(i)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='SnapshotUpdate',
                                                                           method=snapshot_update_cb))

            def annotation_update_cb(context, target):
                self.view.background_adj.set_value(0)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='AnnotationEditEnd',
                                                                           method=annotation_update_cb))

        else:
            self.view = ShapeEditor(icon_dir=config.data.advenefile('pixmaps'))

        self.parse_svg()

        self.view.drawer.widget.connect('drag-data-received', self.drawer_drag_received)
        self.view.drawer.widget.drag_dest_set(Gtk.DestDefaults.MOTION |
                                              Gtk.DestDefaults.HIGHLIGHT |
                                              Gtk.DestDefaults.ALL,
                                              config.data.get_target_types('view', 'annotation', 'uri-list'),
                                              Gdk.DragAction.COPY | Gdk.DragAction.LINK)

        def edit_svg(b=None):
            vbox.foreach(vbox.remove)
            vbox.add(self.view.widget)
            self.editing_source=False
            vbox.show_all()
            return True

        def edit_xml(b=None):
            if self.sourceview is None:
                self.sourceview=TextContentHandler(element=self.element,
                                                   controller=self.controller,
                                                   parent=self.parent)
                self.sourceview.widget=self.sourceview.get_view()
                b = get_pixmap_toolbutton('xml.png', edit_svg)
                b.set_tooltip_text(_("Graphical editor"))
                self.sourceview.toolbar.insert(b, 0)

            vbox.foreach(vbox.remove)
            vbox.add(self.sourceview.widget)
            self.editing_source=True
            vbox.show_all()
            return True

        # Insert "View source" button in Shapewidget toolbar
        b = get_pixmap_toolbutton('xml.png', edit_xml)
        b.set_tooltip_text(_("Edit XML"))
        self.view.toolbar.insert(b, 0)

        def update_background(adj):
            pos = self.get_background_position()
            i = image_from_position(self.controller,
                                    position=pos,
                                    media=self.parent.media)
            self.view.set_background(i)
            return True

        self.view.background_adj = Gtk.Adjustment.new(value=0, lower=0, upper=1.0, step_increment=0.1, page_increment=0.2, page_size=0.2)
        slider = Gtk.HScale.new(self.view.background_adj)
        slider.connect("format-value", lambda s, v: helper.format_time(self.parent.fragment.begin + int(v * self.parent.fragment.duration)))
        ti = Gtk.ToolItem()
        ti.add(slider)
        ti.set_expand(True)
        self.view.toolbar.insert(ti, -1)
        self.view.background_adj.connect('value-changed', update_background)

        if config.data.preferences['prefer-wysiwyg']:
            edit_svg()
        else:
            edit_xml()
        return vbox
コード例 #6
0
ファイル: contenthandlers.py プロジェクト: oaubert/advene
class SVGContentHandler (ContentHandler):
    """Create a SVG edit form for the given element."""
    def can_handle(mimetype):
        res=0
        if mimetype == 'image/svg+xml':
            res=80
        return res
    can_handle=staticmethod(can_handle)

    def __init__ (self, element, controller=None, parent=None, **kw):
        self.element = element
        self.controller=controller
        self.parent=parent
        self.editable = True
        # Internal rules defined by the plugin
        self.rules=[]
        self.fname=None
        self.view = None
        self.sourceview=None
        self.editing_source=False

    def close(self):
        for r in self.rules:
            self.controller.event_handler.remove_rule(r, 'internal')
        return True

    def set_editable (self, boolean):
        self.editable = boolean
        if self.sourceview:
            self.sourceview.set_editable(boolean)

    def parse_svg(self):
        if self.element.data:
            try:
                root=ET.parse(self.element.stream).getroot()
            except xml.parsers.expat.ExpatError as e:
                root=None
                dialog.message_dialog(
                    _("Error while parsing SVG content:\n\n%s") % str(e),
                    icon=Gtk.MessageType.ERROR)
            if root is not None:
                self.view.drawer.clear_objects()
                path=''
                if self.parent is not None and hasattr(self.parent, 'file_'):
                    # We are in a resource. Pass its path as current path.
                    path=os.path.dirname(self.parent.file_)
                self.view.drawer.parse_svg(root, current_path=path)
        return True

    def update_element (self):
        """Update the element fields according to the values in the view."""
        if not self.editable:
            return False

        if self.editing_source:
            self.sourceview.update_element()
            # We applied our modifications to the XML source, so
            # parse the source again in the SVG editor
            self.parse_svg()
            return True

        if self.view is None:
            return True

        tree=ET.ElementTree(self.view.drawer.get_svg(relative=False))
        #ET.dump(tree)
        s=io.StringIO()
        tree.write(s, encoding='unicode')
        self.element.data = s.getvalue()
        s.close()
        # Update the XML source representation
        if self.sourceview is not None:
            self.sourceview.content_set(self.element.data)
        return True

    def get_background_position(self):
        """Return the background position, considering the background slider value.
        """
        frag = self.parent.fragment
        pos = self.controller.round_timestamp(frag.begin + int(self.view.background_adj.get_value() * frag.duration))
        return pos

    def drawer_drag_received(self, widget, context, x, y, selection, targetType, time):
        here=None
        url=None
        title=''
        if targetType == config.data.target_type['annotation']:
            here=self.controller.package.annotations.get(str(selection.get_data(), 'utf8').split('\n')[0])
        elif targetType == config.data.target_type['view']:
            data=decode_drop_parameters(selection.get_data())
            v=self.controller.package.get_element_by_id(data['id'])
            if v is None:
                logger.error("Cannot find view %s", data['id'])
                return True
            here=v
            title=self.controller.get_title(v)
            ctx=self.controller.build_context()
            root=ctx.evaluateValue('here/absolute_url')
            url='%s/action/OpenView?id=%s' % (root, v.id)
        elif targetType == config.data.target_type['uri-list']:
            here=None
            url=str(selection.get_data().splitlines()[0], 'utf8')
            title=url
        else:
            # Invalid drop target
            return True

        if url is None and here is not None:
            ctx=self.controller.build_context(here=here)
            title=self.controller.get_title(here)
            url=ctx.evaluateValue('here/absolute_url')

        if url is None:
            logger.error("Cannot guess url after DND")
            return True

        s=self.view.drawer.clicked_shape( (x, y) )
        if s is None:
            # Drop on no shape. Create one.
            s = self.view.drawer.shape_class()
            s.name = s.SHAPENAME + _(" created from ") + title
            s.color = self.view.defaultcolor
            s.set_bounds( ( (x, y), (x+20, y+20) ) )
            self.view.drawer.add_object(s)
        # Drop on an existing shape. Update its link attribute
        s.link=url
        s.link_label=title
        return False

    def set_begin(self, t):
        try:
            media = self.parent.media
        except AttributeError:
            media = None

        self.view.set_background(image_from_position(self.controller,
                                                     position=t,
                                                     media=media))
        return True

    def get_view (self, compact=False):
        """Generate a view widget for editing SVG."""
        vbox=Gtk.VBox()

        if self.parent is not None and hasattr(self.parent, 'fragment'):
            i = image_from_position(self.controller,
                                    position=self.parent.fragment.begin,
                                    media=self.parent.media)
            vi = self.controller.package.imagecache.video_info
            self.view = ShapeEditor(background=i,
                                    icon_dir=config.data.advenefile('pixmaps'),
                                    default_size=(vi.get('width', 320), vi.get('height', 200)))

            def snapshot_update_cb(context, target):
                if context.globals['media'] != self.parent.media:
                    return True
                pos = self.get_background_position()
                if context.globals['position'] == pos:
                    # Refresh image
                    i = image_from_position(self.controller,
                                            position=pos,
                                            media=self.parent.media)
                    self.view.set_background(i)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='SnapshotUpdate',
                                                                           method=snapshot_update_cb))

            def annotation_update_cb(context, target):
                self.view.background_adj.set_value(0)
                return True
            self.rules.append(self.controller.event_handler.internal_rule (event='AnnotationEditEnd',
                                                                           method=annotation_update_cb))

        else:
            self.view = ShapeEditor(icon_dir=config.data.advenefile('pixmaps'))

        self.parse_svg()

        self.view.drawer.widget.connect('drag-data-received', self.drawer_drag_received)
        self.view.drawer.widget.drag_dest_set(Gtk.DestDefaults.MOTION |
                                              Gtk.DestDefaults.HIGHLIGHT |
                                              Gtk.DestDefaults.ALL,
                                              config.data.get_target_types('view', 'annotation', 'uri-list'),
                                              Gdk.DragAction.COPY | Gdk.DragAction.LINK)

        def edit_svg(b=None):
            vbox.foreach(vbox.remove)
            vbox.add(self.view.widget)
            self.editing_source=False
            vbox.show_all()
            return True

        def edit_xml(b=None):
            if self.sourceview is None:
                self.sourceview=TextContentHandler(element=self.element,
                                                   controller=self.controller,
                                                   parent=self.parent)
                self.sourceview.widget=self.sourceview.get_view()
                b = get_pixmap_toolbutton('xml.png', edit_svg)
                b.set_tooltip_text(_("Graphical editor"))
                self.sourceview.toolbar.insert(b, 0)

            vbox.foreach(vbox.remove)
            vbox.add(self.sourceview.widget)
            self.editing_source=True
            vbox.show_all()
            return True

        # Insert "View source" button in Shapewidget toolbar
        b = get_pixmap_toolbutton('xml.png', edit_xml)
        b.set_tooltip_text(_("Edit XML"))
        self.view.toolbar.insert(b, 0)

        def update_background(adj):
            pos = self.get_background_position()
            i = image_from_position(self.controller,
                                    position=pos,
                                    media=self.parent.media)
            self.view.set_background(i)
            return True

        self.view.background_adj = Gtk.Adjustment.new(value=0, lower=0, upper=1.0, step_increment=0.1, page_increment=0.2, page_size=0.2)
        slider = Gtk.HScale.new(self.view.background_adj)
        slider.connect("format-value", lambda s, v: helper.format_time(self.parent.fragment.begin + int(v * self.parent.fragment.duration)))
        ti = Gtk.ToolItem()
        ti.add(slider)
        ti.set_expand(True)
        self.view.toolbar.insert(ti, -1)
        self.view.background_adj.connect('value-changed', update_background)

        if config.data.preferences['prefer-wysiwyg']:
            edit_svg()
        else:
            edit_xml()
        return vbox