src_js/iconolab-bundle/src/components/editor/Canvas.vue
changeset 418 a04c55054afe
parent 414 49a753808505
child 421 6949fe7a69b6
--- a/src_js/iconolab-bundle/src/components/editor/Canvas.vue	Thu Mar 09 12:39:36 2017 +0100
+++ b/src_js/iconolab-bundle/src/components/editor/Canvas.vue	Mon Mar 13 18:48:35 2017 +0100
@@ -12,14 +12,40 @@
                     x="0" y="0"
                     v-bind:width="imageWidth"
                     v-bind:height="imageHeight" />
-                <shape-rect ref="rect" v-show="loaded &amp;&amp; mode == 'rect'"
+
+                <!-- These are the existing fragments -->
+
+                <!-- FIXME using <component :is="..."> does not work -->
+                <shape-rect
+                    v-for="annotation in normalizedAnnotations"
+                    :key="annotation.annotation_guid"
+                    v-if="loaded &amp;&amp; readonly &amp;&amp; annotation.mode == 'rect'"
                     v-bind:paper="paper"
                     v-bind:original-annotation="annotation"
-                    v-bind:readonly="readonly"></shape-rect>
-                <shape-free ref="free" v-show="loaded &amp;&amp; mode == 'free'"
+                    v-bind:original-path="annotation.path"
+                    v-bind:readonly="readonly"
+                    v-on:click="onAnnotationClick(annotation)"></shape-rect>
+                <shape-free
+                    v-for="annotation in normalizedAnnotations"
+                    :key="annotation.annotation_guid"
+                    v-if="loaded &amp;&amp; readonly &amp;&amp; annotation.mode == 'free'"
                     v-bind:paper="paper"
                     v-bind:original-annotation="annotation"
-                    v-bind:readonly="readonly"></shape-free>
+                    v-bind:original-path="annotation.path"
+                    v-bind:readonly="readonly"
+                    v-on:click="onAnnotationClick(annotation)"></shape-free>
+
+                <!-- These are the new fragments -->
+
+                <shape-rect ref="rect"
+                    v-show="loaded &amp;&amp; !readonly &amp;&amp; mode == 'rect'"
+                    v-bind:paper="paper"
+                    :readonly="false"></shape-rect>
+                <shape-free ref="free"
+                    v-show="loaded &amp;&amp; !readonly &amp;&amp; mode == 'free'"
+                    v-bind:paper="paper"
+                    :readonly="false"></shape-free>
+
                 <defs>
                     <filter id="shadow" width="200%" height="200%">
                         <feOffset result="offOut" in="SourceAlpha" dx="0" dy="0"/>
@@ -31,6 +57,10 @@
         </div>
         <div class="controls">
             <div class="controls-left">
+                <button @click="readonly = !readonly" type="button" class="btn">
+                    <i v-show="readonly" class="fa fa-pencil"></i>
+                    <i v-show="!readonly" class="fa fa-close"></i>
+                </button>
                 <button @click="setMode('rect')" type="button" class="btn"
                     v-bind:class="{ 'active': mode === 'rect', 'disabled': readonly }">
                     <svg width="14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><g><rect x="352" y="432" width="64" height="48"/><polygon points="416,352 416,96 176,96 176,160 352,160 352,352 160,352 160,32 96,32 96,96 32,96 32,160 96,160 96,416 480,416 480,352"/></g><text x="0" y="527" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by Bluetip Design</text><text x="0" y="532" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg>
@@ -72,6 +102,7 @@
     import ShapeRect from './ShapeRect.vue'
     import ShapeFree from './ShapeFree.vue'
     import ZoomThumbnail from './ZoomThumbnail.vue'
+    import _ from 'lodash'
 
     export default {
         props: {
@@ -88,6 +119,10 @@
             isAuthenticated: {
                 type: Boolean,
                 default: false
+            },
+            annotations: {
+                type: Array,
+                default: []
             }
         },
         components: {
@@ -116,17 +151,37 @@
                     'canvas--rect': !this.readonly && this.isAuthenticated && this.mode === 'rect',
                     'canvas--free': !this.readonly && this.isAuthenticated && this.mode === 'free'
                 }
+            },
+            normalizedAnnotations: function() {
+                var normalizedAnnotations = _.map(this.annotations, (annotation) => {
+                    if (annotation.fragment.length > 0) {
+                        var pieces = annotation.fragment.split(';');
+                        var path = this.denormalizePath(pieces[0]);
+                        var mode = pieces[1].toLowerCase();
+
+                        Object.assign(annotation, {
+                            mode: mode,
+                            path: path,
+                        });
+                    }
+
+                    return annotation;
+                });
+
+                if (this.annotation) {
+                    return _.filter(normalizedAnnotations, (annotation) => {
+                        return annotation === this.annotation;
+                    });
+                }
+
+                return normalizedAnnotations;
             }
         },
         watch: {
             mode: function(mode) {
                 this.reset();
-                if (mode === 'free') {
-                    this.handleDrawFree();
-                }
-                if (mode === 'rect') {
-                    this.handleDrawRect();
-                }
+                if (this.readonly) { return; }
+                this.handleDraw();
             },
             loaded: function(loaded) {
                 if (!loaded) { return; }
@@ -153,23 +208,13 @@
 
                 this.paper.attr({"viewBox": this.viewBox});
 
-                if (this.annotation) {
-                    this.loadAnnotation();
-                } else {
-                    if (this.mode === 'free') {
-                        this.handleDrawFree();
-                    }
-                    if (this.mode === 'rect') {
-                        this.handleDrawRect();
-                    }
+                if (_.size(this.annotations) > 0) {
+                    this.readonly = true;
                 }
+
             },
             annotation: function(annotation) {
-                this.reset();
                 this.readonly = !!annotation || !this.isAuthenticated;
-                if (this.annotation) {
-                    this.loadAnnotation();
-                }
             },
             scale: function(scale) {
                 var factor = 0;
@@ -195,6 +240,16 @@
                     this.hideTooltip();
                     this.animateViewBox(viewBox, () => this.showTooltip());
                 }
+            },
+            readonly: function(readonly, previous) {
+                this.reset();
+
+                if (!readonly) {
+                    this.handleDraw();
+                    if (this.annotation) {
+                        this.$emit('close:annotation');
+                    }
+                }
             }
         },
         mounted() {
@@ -219,13 +274,12 @@
 
         },
         methods: {
+            onAnnotationClick: function(annotation) {
+                this.$emit('click:annotation', annotation);
+            },
             hideTooltip: function() {
-                if (this.mode === 'free') {
-                    this.$refs.free.hideTooltip();
-                }
-                if (this.mode === 'rect') {
-                    this.$refs.rect.hideTooltip();
-                }
+                this.$refs.free.hideTooltip();
+                this.$refs.rect.hideTooltip();
             },
             showTooltip: function() {
                 if (this.mode === 'free') {
@@ -236,20 +290,13 @@
                 }
             },
             reset: function() {
-                // Clear shapes
+
                 this.$refs.rect.clear();
                 this.$refs.free.clear();
 
                 this.removeEventHandlers();
                 this.resetZoom();
                 this.resetViewBox();
-
-                if (this.mode === 'free') {
-                    this.handleDrawFree();
-                }
-                if (this.mode === 'rect') {
-                    this.handleDrawRect();
-                }
             },
 
             removeEventHandlers: function() {
@@ -259,26 +306,6 @@
                 this.paper.unclick();
             },
 
-            loadAnnotation: function() {
-                if (this.annotation.fragment.length > 0) {
-                    var pieces = this.annotation.fragment.split(';');
-                    var path = pieces[0];
-                    var mode = pieces[1].toLowerCase();
-
-                    this.mode = mode;
-
-                    this.$nextTick(() => {
-                        path = this.denormalizePath(path);
-                        if (mode === 'free') {
-                            this.$refs.free.fromSVGPath(path, this.tooltip);
-                        }
-                        if (mode === 'rect') {
-                            this.$refs.rect.fromSVGPath(path, this.tooltip);
-                        }
-                    });
-                }
-            },
-
             setMode: function(mode) {
                 if (this.readonly) { return; }
 
@@ -403,6 +430,15 @@
                 }
             },
 
+            handleDraw: function() {
+                if (this.mode === 'free') {
+                    this.handleDrawFree();
+                }
+                if (this.mode === 'rect') {
+                    this.handleDrawRect();
+                }
+            },
+
             handleDrawFree: function() {
 
                 if (!this.isAuthenticated) { return; }