1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.svg.edit.client.engine;
19
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Stack;
25
26 import org.vectomatic.dom.svg.OMElement;
27 import org.vectomatic.dom.svg.OMSVGDocument;
28 import org.vectomatic.dom.svg.OMSVGElement;
29 import org.vectomatic.dom.svg.OMSVGGElement;
30 import org.vectomatic.dom.svg.OMSVGMatrix;
31 import org.vectomatic.dom.svg.OMSVGPoint;
32 import org.vectomatic.dom.svg.OMSVGRect;
33 import org.vectomatic.dom.svg.OMSVGRectElement;
34 import org.vectomatic.dom.svg.OMSVGSVGElement;
35 import org.vectomatic.dom.svg.OMSVGStyle;
36 import org.vectomatic.dom.svg.impl.SVGElement;
37 import org.vectomatic.dom.svg.impl.SVGGElement;
38 import org.vectomatic.dom.svg.impl.SVGRectElement;
39 import org.vectomatic.dom.svg.itf.ISVGLocatable;
40 import org.vectomatic.dom.svg.itf.ISVGTransformable;
41 import org.vectomatic.dom.svg.utils.DOMHelper;
42 import org.vectomatic.dom.svg.utils.OMSVGParser;
43 import org.vectomatic.dom.svg.utils.SVGConstants;
44 import org.vectomatic.dom.svg.utils.SVGPrefixResolver;
45 import org.vectomatic.svg.edit.client.SVGSelectionModel;
46 import org.vectomatic.svg.edit.client.SvgrealApp;
47 import org.vectomatic.svg.edit.client.command.CommandStore;
48 import org.vectomatic.svg.edit.client.command.ICommandFactory;
49 import org.vectomatic.svg.edit.client.command.RemoveElementsCommandFactory;
50 import org.vectomatic.svg.edit.client.command.ShowPropertiesCommandFactory;
51 import org.vectomatic.svg.edit.client.command.add.AddCircleCommandFactory;
52 import org.vectomatic.svg.edit.client.command.add.AddEllipseCommandFactory;
53 import org.vectomatic.svg.edit.client.command.add.AddGroupCommandFactory;
54 import org.vectomatic.svg.edit.client.command.add.AddLineCommandFactory;
55 import org.vectomatic.svg.edit.client.command.add.AddPathCommandFactory;
56 import org.vectomatic.svg.edit.client.command.add.AddPolygonCommandFactory;
57 import org.vectomatic.svg.edit.client.command.add.AddPolylineCommandFactory;
58 import org.vectomatic.svg.edit.client.command.add.AddRectCommandFactory;
59 import org.vectomatic.svg.edit.client.event.HasRotationHandlers;
60 import org.vectomatic.svg.edit.client.event.HasScalingHandlers;
61 import org.vectomatic.svg.edit.client.event.KeyPressProcessor;
62 import org.vectomatic.svg.edit.client.event.KeyUpProcessor;
63 import org.vectomatic.svg.edit.client.event.MouseDownProcessor;
64 import org.vectomatic.svg.edit.client.event.MouseMoveProcessor;
65 import org.vectomatic.svg.edit.client.event.MouseUpProcessor;
66 import org.vectomatic.svg.edit.client.event.RotationEvent;
67 import org.vectomatic.svg.edit.client.event.RotationHandler;
68 import org.vectomatic.svg.edit.client.event.ScalingEvent;
69 import org.vectomatic.svg.edit.client.event.ScalingHandler;
70 import org.vectomatic.svg.edit.client.event.StoreEventProcessor;
71 import org.vectomatic.svg.edit.client.gxt.widget.CommandFactoryMenuItem;
72 import org.vectomatic.svg.edit.client.gxt.widget.KeyNavExt;
73 import org.vectomatic.svg.edit.client.model.MetaModel;
74 import org.vectomatic.svg.edit.client.model.svg.SVGCircleElementModel;
75 import org.vectomatic.svg.edit.client.model.svg.SVGElementModel;
76 import org.vectomatic.svg.edit.client.model.svg.SVGEllipseElementModel;
77 import org.vectomatic.svg.edit.client.model.svg.SVGImageElementModel;
78 import org.vectomatic.svg.edit.client.model.svg.SVGLineElementModel;
79 import org.vectomatic.svg.edit.client.model.svg.SVGNamedElementModel;
80 import org.vectomatic.svg.edit.client.model.svg.SVGPathElementModel;
81 import org.vectomatic.svg.edit.client.model.svg.SVGPolygonElementModel;
82 import org.vectomatic.svg.edit.client.model.svg.SVGPolylineElementModel;
83 import org.vectomatic.svg.edit.client.model.svg.SVGRectElementModel;
84 import org.vectomatic.svg.edit.client.model.svg.SVGUseElementModel;
85 import org.vectomatic.svg.edit.client.model.svg.SVGViewBoxElementModel;
86
87 import com.extjs.gxt.ui.client.event.ComponentEvent;
88 import com.extjs.gxt.ui.client.store.StoreEvent;
89 import com.extjs.gxt.ui.client.store.StoreListener;
90 import com.extjs.gxt.ui.client.store.TreeStore;
91 import com.extjs.gxt.ui.client.widget.menu.Item;
92 import com.extjs.gxt.ui.client.widget.menu.Menu;
93 import com.extjs.gxt.ui.client.widget.treepanel.TreePanelSelectionModel;
94 import com.google.gwt.core.client.GWT;
95 import com.google.gwt.dom.client.Element;
96 import com.google.gwt.dom.client.Node;
97 import com.google.gwt.dom.client.NodeList;
98 import com.google.gwt.dom.client.Style.Unit;
99 import com.google.gwt.event.dom.client.KeyCodes;
100 import com.google.gwt.event.dom.client.MouseDownEvent;
101 import com.google.gwt.event.dom.client.MouseDownHandler;
102 import com.google.gwt.event.dom.client.MouseEvent;
103 import com.google.gwt.event.dom.client.MouseMoveEvent;
104 import com.google.gwt.event.dom.client.MouseMoveHandler;
105 import com.google.gwt.event.dom.client.MouseUpEvent;
106 import com.google.gwt.event.dom.client.MouseUpHandler;
107 import com.google.gwt.event.shared.EventHandler;
108 import com.google.gwt.event.shared.GwtEvent;
109 import com.google.gwt.event.shared.HandlerRegistration;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 public class SVGModel implements MouseDownHandler, MouseMoveHandler, MouseUpHandler, HasScalingHandlers, HasRotationHandlers {
142
143
144
145 private static final String ATTR_KIND = "kind";
146 private static final String ATTR_KIND_VIEWBOX = "viewBox";
147
148
149
150 public static final String EXT_TWIN = "twin";
151
152
153
154 protected String idPrefix;
155
156
157
158 protected OMSVGSVGElement svg;
159
160
161
162
163 protected OMSVGGElement xformGroup;
164
165
166
167 protected SVGElementModel modelGroup;
168
169
170
171 protected OMSVGMatrix m;
172
173
174
175 protected float angle;
176
177
178
179 protected float scale;
180
181
182
183 protected SVGSelectionModel selectionModel;
184
185
186
187 protected boolean highlightingMode;
188
189
190
191 protected SVGElementModel highlightedModel;
192
193
194
195
196 protected Map<String, Integer> tagNameToTagCount;
197
198
199
200 protected TreeStore<SVGElementModel> store;
201
202
203
204 protected CommandStore commandStore;
205
206
207
208 protected Map<SVGElement, SVGElementModel> elementToModel;
209
210
211
212 protected Map<String, Object> idToModel;
213
214
215
216 protected SVGViewBoxElementModel viewBox;
217
218
219
220 protected OMSVGRect windowRect;
221
222
223
224 protected Grid grid;
225
226
227
228
229
230
231
232 public SVGModel() {
233 elementToModel = new HashMap<SVGElement, SVGElementModel>();
234 idToModel = new HashMap<String, Object>();
235 tagNameToTagCount = new HashMap<String, Integer>();
236 grid = new Grid();
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 public static SVGModel newInstance(OMSVGSVGElement svg, String title, String idPrefix) {
254 SVGModel model = GWT.create(SVGModel.class);
255 model.setSvgElement(svg, title, idPrefix);
256 return model;
257 }
258
259 static {
260 initialize();
261 }
262 protected static Map<String, MetaModel<SVGElement>> tagNameToMetamodel;
263 public static MetaModel<SVGElement> getMetamodel(SVGElement element) {
264 if (tagNameToMetamodel == null) {
265 tagNameToMetamodel = new HashMap<String, MetaModel<SVGElement>>();
266 tagNameToMetamodel.put(SVGConstants.SVG_CIRCLE_TAG, SVGCircleElementModel.getCircleElementMetaModel());
267 tagNameToMetamodel.put(SVGConstants.SVG_ELLIPSE_TAG, SVGEllipseElementModel.getEllipseElementMetaModel());
268 tagNameToMetamodel.put(SVGConstants.SVG_LINE_TAG, SVGLineElementModel.getLineElementMetaModel());
269 tagNameToMetamodel.put(SVGConstants.SVG_RECT_TAG, SVGRectElementModel.getRectElementMetaModel());
270 tagNameToMetamodel.put(SVGConstants.SVG_POLYGON_TAG, SVGPolygonElementModel.getPolygonElementMetaModel());
271 tagNameToMetamodel.put(SVGConstants.SVG_POLYLINE_TAG, SVGPolylineElementModel.getPolylineElementMetaModel());
272 tagNameToMetamodel.put(SVGConstants.SVG_PATH_TAG, SVGPathElementModel.getPathElementMetaModel());
273 tagNameToMetamodel.put(SVGConstants.SVG_IMAGE_TAG, SVGImageElementModel.getImageElementMetaModel());
274 tagNameToMetamodel.put(SVGConstants.SVG_USE_TAG, SVGUseElementModel.getUseElementMetaModel());
275 }
276 return tagNameToMetamodel.get(element.getTagName());
277 }
278
279 private static final native void initialize()
280
281
282
283
284
285
286
287
288
289
290
291
292 ;
293
294
295
296
297
298
299
300 public SVGElementModel convert(SVGElement element) {
301 SVGElementModel model = elementToModel.get(element);
302
303 return model;
304 }
305
306 public OMSVGSVGElement getSvgElement() {
307 return svg;
308 }
309
310
311
312
313
314
315
316 public void setSvgElement(OMSVGSVGElement svg, String title, String idPrefix) {
317 this.svg = svg;
318 this.idPrefix = idPrefix;
319 windowRect = svg.createSVGRect();
320
321
322
323
324
325
326 svg.removeAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE);
327 svg.removeAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE);
328
329
330
331 svg.addMouseMoveHandler(this);
332 svg.addMouseDownHandler(this);
333 svg.addMouseUpHandler(this);
334
335 elementToModel.clear();
336 tagNameToTagCount.clear();
337
338
339 SVGProcessor.normalizeIds(svg, idPrefix);
340
341
342 xformGroup = new OMSVGGElement();
343 xformGroup.getTransform().getBaseVal().appendItem(svg.createSVGTransform());
344
345
346
347 OMSVGGElement elementGroup = new OMSVGGElement();
348 SVGNamedElementModel.createTitleDesc(elementGroup.getElement().<SVGElement>cast(), title);
349 SVGProcessor.reparent(svg, elementGroup);
350
351
352
353 OMSVGGElement twinGroup = (OMSVGGElement) elementGroup.cloneNode(true);
354 twinGroup.getTransform().getBaseVal().appendItem(svg.createSVGTransform());
355 SVGProcessor.normalizeIds(twinGroup, SVGProcessor.newPrefixExtension(idPrefix, EXT_TWIN));
356 twinGroup.getStyle().setSVGProperty(SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_HIDDEN_VALUE);
357
358 modelGroup = create(elementGroup.getElement().<SVGElement>cast(), twinGroup.getElement().<SVGElement>cast());
359 xformGroup.appendChild(elementGroup);
360 svg.appendChild(xformGroup);
361 svg.appendChild(twinGroup);
362 setScale(1f);
363
364
365 store = new TreeStore<SVGElementModel>();
366 store.add(modelGroup, true);
367
368
369
370 store.addStoreListener(new StoreListener<SVGElementModel>() {
371 @Override
372 public void storeUpdate(StoreEvent<SVGElementModel> se) {
373 SVGModel.this.storeUpdate(se);
374 }
375 });
376
377
378
379 OMSVGRect viewBoxRect = svg.getViewBox().getBaseVal();
380 if (viewBoxRect.getWidth() != 0f && viewBoxRect.getHeight() != 0f) {
381 createViewBox(viewBoxRect);
382 }
383 svg.removeAttribute(SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
384
385
386 commandStore = new CommandStore();
387
388
389 selectionModel = new SVGSelectionModel();
390
391 }
392
393
394
395
396
397
398 public boolean contains(SVGElement element) {
399 return elementToModel.containsKey(element);
400 }
401
402 protected void adopt(SVGElementModel model) {
403 adopt(model, true);
404 }
405 protected void adopt(SVGElementModel model, boolean root) {
406 model.setOwner(this);
407 elementToModel.put(model.getElement(), model);
408 elementToModel.put(model.getTwin(), model);
409
410
411 SVGElementModel firstChild = (SVGElementModel) model.getChild(0);
412 if (firstChild != null) {
413 adopt(firstChild, false);
414 }
415 if (!root) {
416 SVGElementModel nextSibling = model.getNextSibling();
417 if (nextSibling != null) {
418 adopt(nextSibling, false);
419 }
420 }
421 }
422
423 protected void orphan(SVGElementModel model) {
424 orphan(model, true);
425 }
426
427 protected void orphan(SVGElementModel model, boolean root) {
428 model.setOwner(null);
429 elementToModel.remove(model.getElement());
430 elementToModel.remove(model.getTwin());
431
432
433 SVGElementModel firstChild = (SVGElementModel) model.getChild(0);
434 if (firstChild != null) {
435 orphan(firstChild, false);
436 }
437 if (!root) {
438 SVGElementModel nextSibling = model.getNextSibling();
439 if (nextSibling != null) {
440 orphan(nextSibling, false);
441 }
442 }
443 }
444
445 public SVGElementModel create(Node modelNode, Node modelTwin) {
446 Stack<Node> stack = new Stack<Node>();
447 stack.push(modelNode);
448 stack.push(modelTwin);
449 while(!stack.empty()) {
450 Node twin = stack.pop();
451 Node node = stack.pop();
452 if (SVGProcessor.isSvgElement(node)) {
453 if (SVGProcessor.isTitleDescElement(node.<SVGElement>cast())) {
454 continue;
455 }
456
457
458
459
460 SVGElementModel model = convert(node.<SVGElement>cast());
461 if (model == null) {
462 model = create(this, node, twin);
463 adopt(model, false);
464 }
465 SVGElementModel parentModel = (SVGElementModel) model.getParent();
466 if (parentModel == null) {
467 parentModel = convert(node.getParentElement().<SVGElement>cast());
468 }
469 if (parentModel != null) {
470 parentModel.add(model);
471 }
472
473 }
474 NodeList<Node> nodeChildren = node.getChildNodes();
475 NodeList<Node> twinChildren = twin.getChildNodes();
476 for (int i = nodeChildren.getLength() - 1; i >= 0; i--) {
477 stack.push(nodeChildren.getItem(i));
478 stack.push(twinChildren.getItem(i));
479 }
480 }
481 return convert(modelNode.<SVGElement>cast());
482 }
483
484 private final native SVGElementModel create(SVGModel owner, Node element, Node twin)
485
486
487
488
489
490
491
492
493
494
495
496
497
498 ;
499
500
501
502
503
504
505 public void add(SVGElementModel parentModel, SVGElementModel model) {
506 insertBefore(parentModel, model, null);
507 }
508
509
510
511
512
513
514
515
516
517
518 public void insertBefore(SVGElementModel parentModel, SVGElementModel newModel, SVGElementModel refModel) {
519
520 Element element = newModel.getElement();
521 Element parentElement = parentModel.getElement();
522 assert(parentElement != null);
523 assert(contains(parentElement.<SVGElement>cast())) : parentModel.toString() + " element is not in this model";
524 Element refElement = refModel != null ? refModel.getElement() : null;
525 if (refElement != null) {
526 assert(contains(refElement.<SVGElement>cast())) : refElement.toString() + " element is not in this model";
527 }
528
529 Element twin = newModel.getTwin();
530 Element parentTwin = parentModel.getTwin();
531 assert(parentTwin != null);
532 assert(contains(parentTwin.<SVGElement>cast())) : parentModel.toString() + " twin is not in this model";
533 Element refTwin = refModel != null ? refModel.getTwin() : null;
534 if (refElement != null) {
535 assert(contains(refTwin.<SVGElement>cast())) : refElement.toString() + " twin is not in this model";
536 }
537
538
539 SVGModel owner = newModel.getOwner();
540 if (owner != null) {
541 owner.remove(newModel);
542 }
543 adopt(newModel);
544
545
546 parentElement.insertBefore(element, refElement);
547
548 parentTwin.insertBefore(twin, refTwin);
549
550
551 if (refModel == null) {
552
553 parentModel.add(newModel);
554
555
556 store.add(parentModel, newModel, true);
557 } else {
558 int index = parentModel.indexOf(refModel);
559
560 parentModel.insert(newModel, index);
561
562
563 store.insert(parentModel, newModel, index, true);
564 }
565 }
566
567
568
569
570
571 public void remove(SVGElementModel model) {
572 if (model.getOwner() == this) {
573
574 orphan(model);
575
576
577 Element element = model.getElement();
578 Element parentElement = element.getParentElement();
579 if (parentElement != null) {
580 parentElement.removeChild(element);
581 }
582 Element twin = model.getTwin();
583 Element parentTwin = twin.getParentElement();
584 if (parentTwin != null) {
585 parentTwin.removeChild(twin);
586 }
587
588
589 if (model.getParent() != null) {
590 model.getParent().remove(model);
591 }
592
593
594 store.removeAll(model);
595 store.remove(model);
596 }
597 }
598
599
600
601
602
603
604 public SVGElementModel clone(SVGElementModel model, String name) {
605 SVGElementModel clone = create(model.getElement().cloneNode(true).<SVGElement>cast(), model.getTwin().cloneNode(true).<SVGElement>cast());
606 clone.set(SVGConstants.SVG_TITLE_TAG, name);
607 return clone;
608 }
609
610
611 protected void storeUpdate(StoreEvent<SVGElementModel> se) {
612 ICommandFactory factory = SvgrealApp.getApp().getCommandFactorySelector().getActiveFactory();
613 if (factory instanceof StoreEventProcessor) {
614 ((StoreEventProcessor)factory).processStoreEvent(se);
615 }
616 }
617
618 public String getMarkup() {
619 OMSVGSVGElement svg = new OMSVGSVGElement();
620 svg.setAttribute(SVGConstants.XMLNS_PREFIX + ":" + SVGConstants.XLINK_PREFIX, SVGConstants.XLINK_NAMESPACE_URI);
621 svg.setViewBox(
622 viewBox.<Float>get(SVGConstants.SVG_X_ATTRIBUTE),
623 viewBox.<Float>get(SVGConstants.SVG_Y_ATTRIBUTE),
624 viewBox.<Float>get(SVGConstants.SVG_WIDTH_ATTRIBUTE),
625 viewBox.<Float>get(SVGConstants.SVG_HEIGHT_ATTRIBUTE));
626 SVGGElement g = modelGroup.getElement().cloneNode(true).cast();
627
628
629 Node viewBoxElement = DOMHelper.evaluateNodeXPath(g, "//svg:rect[@" + ATTR_KIND + "='" + ATTR_KIND_VIEWBOX + "']", SVGPrefixResolver.INSTANCE);
630
631 Node node = null;
632 while((node = g.getFirstChild()) != null) {
633 Node child = g.removeChild(node);
634 if (child != viewBoxElement) {
635 svg.getElement().appendChild(child);
636 }
637 }
638 return svg.getMarkup();
639 }
640
641
642
643
644
645 public SVGElementModel getRoot() {
646 return store.getRootItems().get(0);
647 }
648
649
650
651
652
653
654
655
656
657
658
659 public TreeStore<SVGElementModel> getStore() {
660 return store;
661 }
662
663
664
665
666 public CommandStore getCommandStore() {
667 return commandStore;
668 }
669
670
671
672
673
674 public TreePanelSelectionModel<SVGElementModel> getSelectionModel() {
675 return selectionModel;
676 }
677
678
679
680
681
682 public SVGViewBoxElementModel getViewBox() {
683 return viewBox;
684 }
685
686
687
688
689
690 public String getIdPrefix() {
691 return idPrefix;
692 }
693
694
695
696
697
698
699
700
701 @Override
702 public void onMouseMove(MouseMoveEvent event) {
703
704 ICommandFactory commandFactory = SvgrealApp.getApp().getCommandFactorySelector().getActiveFactory();
705 if (commandFactory instanceof MouseMoveProcessor) {
706 if (((MouseMoveProcessor)commandFactory).processMouseMove(event)) {
707 return;
708 }
709 }
710
711
712 if (highlightingMode) {
713 SVGElementModel model = convert(event.getNativeEvent().getEventTarget().<SVGElement>cast());
714 highlightModel(model);
715 }
716 }
717
718 @Override
719 public void onMouseDown(MouseDownEvent event) {
720 GWT.log("SVGModel.onMouseDown");
721 SVGElement target = event.getNativeEvent().getEventTarget().cast();
722
723
724 if (event.getNativeButton() == 2) {
725 SVGElementModel model = convert(target);
726 if (model == null || SVGConstants.SVG_SVG_TAG.equals(target.getTagName())) {
727
728 selectionModel.deselectAll();
729 } else {
730 if (!selectionModel.isSelected(model)) {
731
732 selectionModel.select(model, false);
733 }
734
735
736
737
738 }
739 return;
740 }
741
742
743 ICommandFactory commandFactory = SvgrealApp.getApp().getCommandFactorySelector().getActiveFactory();
744 if (commandFactory instanceof MouseDownProcessor) {
745 if (((MouseDownProcessor)commandFactory).processMouseDown(event)) {
746 return;
747 }
748 }
749
750
751 if (SVGConstants.SVG_SVG_TAG.equals(target.getTagName())) {
752 selectionModel.deselectAll();
753 } else {
754 SVGElementModel model = convert(target);
755 if (model != null) {
756 if (selectionModel.isSelected(model)) {
757 if (event.isControlKeyDown()) {
758
759 selectionModel.deselect(model);
760 }
761 } else if (event.isShiftKeyDown() | event.isControlKeyDown()) {
762
763 selectionModel.select(model, true);
764 } else {
765
766 selectionModel.select(model, false);
767 }
768 }
769 }
770 }
771
772 @Override
773 public void onMouseUp(MouseUpEvent event) {
774 GWT.log("SVGModel.onMouseUp");
775 ICommandFactory commandFactory = SvgrealApp.getApp().getCommandFactorySelector().getActiveFactory();
776 if (commandFactory instanceof MouseUpProcessor) {
777 ((MouseUpProcessor)commandFactory).processMouseUp(event);
778 }
779 }
780
781 public void onKeyPress(ComponentEvent event) {
782 int code = event.getKeyCode();
783 GWT.log("SVGModel.onKeyPress: " + code);
784 ICommandFactory commandFactory = SvgrealApp.getApp().getCommandFactorySelector().getActiveFactory();
785 if (commandFactory instanceof KeyPressProcessor && ((KeyPressProcessor)commandFactory).processKeyPress(event)) {
786 return;
787 }
788 if (code == KeyCodes.KEY_DELETE || code == KeyCodes.KEY_BACKSPACE) {
789 RemoveElementsCommandFactory.INSTANTIATOR.create().start(this);
790 }
791 if (code == KeyNavExt.KEY_F2) {
792 List<SVGElementModel> selectedItems = selectionModel.getSelectedItems();
793 if (selectedItems.size() == 1) {
794 SVGElementModel model = selectedItems.get(0);
795 SvgrealApp.getApp().getWindow(model.getElement()).renameModel(model);
796 }
797 }
798 }
799
800 public void onKeyUp(ComponentEvent event) {
801 int code = event.getKeyCode();
802 GWT.log("SVGModel.onKeyUp: " + code);
803 ICommandFactory commandFactory = SvgrealApp.getApp().getCommandFactorySelector().getActiveFactory();
804 if (commandFactory instanceof KeyUpProcessor && ((KeyUpProcessor)commandFactory).processKeyUp(event)) {
805 return;
806 }
807 }
808
809
810
811
812 public void updateContextMenu(Menu contextMenu) {
813 List<SVGElementModel> selectedModels = selectionModel.getSelectedItems();
814 List<Item> items = new ArrayList<Item>();
815 int size = selectedModels.size();
816 if (size == 0) {
817
818 items.add(new CommandFactoryMenuItem(AddLineCommandFactory.INSTANTIATOR));
819 items.add(new CommandFactoryMenuItem(AddCircleCommandFactory.INSTANTIATOR));
820 items.add(new CommandFactoryMenuItem(AddEllipseCommandFactory.INSTANTIATOR));
821 items.add(new CommandFactoryMenuItem(AddRectCommandFactory.INSTANTIATOR));
822 items.add(new CommandFactoryMenuItem(AddPolylineCommandFactory.INSTANTIATOR));
823 items.add(new CommandFactoryMenuItem(AddPolygonCommandFactory.INSTANTIATOR));
824 items.add(new CommandFactoryMenuItem(AddPathCommandFactory.INSTANTIATOR));
825 items.add(new CommandFactoryMenuItem(AddGroupCommandFactory.INSTANTIATOR));
826 } else if (size == 1) {
827
828 MetaModel metaModel = selectedModels.get(0).getMetaModel();
829 items.addAll(metaModel.getContextMenuItems());
830 items.add(new CommandFactoryMenuItem(RemoveElementsCommandFactory.INSTANTIATOR));
831 } else {
832
833 items.add(new CommandFactoryMenuItem(RemoveElementsCommandFactory.INSTANTIATOR));
834 }
835 items.add(new CommandFactoryMenuItem(ShowPropertiesCommandFactory.INSTANTIATOR));
836 contextMenu.removeAll();
837 for (Item item : items) {
838 contextMenu.add(item);
839 }
840 }
841
842
843
844
845
846
847
848
849
850
851
852
853
854 public OMSVGPoint getCoordinates(MouseEvent<? extends EventHandler> e, boolean snap) {
855 OMSVGMatrix m = modelGroup.getElement().<SVGGElement>cast().getScreenCTM().inverse();
856 OMSVGPoint p = svg.createSVGPoint(e.getClientX(), e.getClientY()).matrixTransform(m);
857 return grid.snapsToGrid() ? grid.snap(p) : p;
858 }
859
860
861
862
863
864
865
866 public void onAttach() {
867
868
869 if (viewBox == null) {
870 GWT.log(svg.getBBox().getDescription());
871 createViewBox(svg.getBBox().inset(svg.createSVGRect(), -0.1f * svg.getBBox().getWidth(), -0.1f * svg.getBBox().getHeight()));
872 }
873 if (!grid.isAttached()) {
874 grid.attach(this);
875 svg.insertBefore(grid.getDefs(), xformGroup);
876 xformGroup.getElement().insertBefore(grid.getRoot().getElement(), modelGroup.getElement());
877 }
878
879 modelGroup.computeSeverity();
880 }
881
882 private void createViewBox(OMSVGRect viewBoxRect) {
883 OMSVGDocument document = (OMSVGDocument) svg.getOwnerDocument();
884 OMSVGRectElement rect = document.createSVGRectElement(viewBoxRect);
885 rect.getStyle().setSVGProperty(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
886 rect.getStyle().setSVGProperty(SVGConstants.CSS_STROKE_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
887 rect.getStyle().setSVGProperty(SVGConstants.CSS_STROKE_DASHARRAY_PROPERTY, "4, 2");
888 rect.setAttribute(ATTR_KIND, ATTR_KIND_VIEWBOX);
889 SVGRectElement element = rect.getElement().cast();
890 SVGRectElement twin = element.cloneNode(true).cast();
891 viewBox = new SVGViewBoxElementModel(this, element, twin);
892 adopt(viewBox);
893
894 insertBefore(modelGroup, viewBox, (SVGElementModel) modelGroup.getChild(0)
895 }
896
897
898
899
900
901 public float getScale() {
902 return scale;
903 }
904
905
906
907
908
909
910 public void setScale(float scale) {
911 this.scale = scale;
912 updateTransform();
913 fireEvent(new ScalingEvent(scale));
914 }
915
916 public float getRotation() {
917 return angle;
918 }
919
920
921
922
923
924
925 public void setRotation(float angle) {
926 this.angle = angle;
927 updateTransform();
928 fireEvent(new RotationEvent(angle));
929 }
930
931
932
933
934
935 public Grid getGrid() {
936 return grid;
937 }
938
939 @Override
940 public void fireEvent(GwtEvent<?> event) {
941 SvgrealApp.getApp().getEventBus().fireEventFromSource(event, this);
942 }
943
944 @Override
945 public HandlerRegistration addRotationHandler(RotationHandler handler) {
946 return SvgrealApp.getApp().getEventBus().addHandlerToSource(RotationEvent.getType(), this, handler);
947 }
948
949 @Override
950 public HandlerRegistration addScalingHandler(ScalingHandler handler) {
951 return SvgrealApp.getApp().getEventBus().addHandlerToSource(ScalingEvent.getType(), this, handler);
952 }
953
954
955
956
957
958
959 public void setWindowRect(int width, int height) {
960 GWT.log("setWindowRect(" + width + ", " + height + ")");
961 windowRect.setWidth(width);
962 windowRect.setHeight(height);
963 updateTransform();
964 }
965 public OMSVGRect getWindowRect() {
966 return windowRect;
967 }
968
969
970
971
972 public void updateTransform() {
973 if (viewBox != null) {
974 OMSVGRect bbox = ((SVGRectElement)viewBox.getElement()).getBBox();
975
976 float d = (float)Math.sqrt((bbox.getWidth() * bbox.getWidth() + bbox.getHeight() * bbox.getHeight()) * 0.25) * scale * 2;
977
978
979
980
981 float width = Math.max(d, windowRect.getWidth());
982 float height = Math.max(d, windowRect.getHeight());
983
984
985
986
987
988 OMSVGMatrix m = svg.createSVGMatrix();
989 float cx = bbox.getCenterX();
990 float cy = bbox.getCenterY();
991 m = m.translate(0.5f * (width - bbox.getWidth()) -bbox.getX(), 0.5f * (height - bbox.getHeight()) -bbox.getY())
992 .translate(cx, cy)
993 .rotate(angle)
994 .scale(scale)
995 .translate(-cx, -cy);
996 ((ISVGTransformable)xformGroup).getTransform().getBaseVal().getItem(0).setMatrix(m);
997 ((ISVGTransformable)modelGroup.getTwinWrapper()).getTransform().getBaseVal().getItem(0).setMatrix(m);
998
999 svg.getStyle().setWidth(width, Unit.PX);
1000 svg.getStyle().setHeight(height, Unit.PX);
1001 }
1002 }
1003
1004
1005
1006
1007
1008
1009 public static float getVertexSize(SVGElementModel model) {
1010 return getVertexSize((ISVGLocatable)model.getElementWrapper());
1011 }
1012
1013 public static float getVertexSize(ISVGLocatable element) {
1014 OMSVGMatrix m = element.getScreenCTM().inverse();
1015
1016 float a = 3.543307f * m.getA();
1017 float b = 3.543307f * m.getD();
1018 return (float)Math.sqrt(a * a + b * b);
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028 public OMSVGGElement getElementGroup() {
1029 return (OMSVGGElement) modelGroup.getElementWrapper();
1030 }
1031 public OMSVGGElement getTwinGroup() {
1032 return (OMSVGGElement) modelGroup.getTwinWrapper();
1033 }
1034
1035 public boolean isHighlightingMode() {
1036 return highlightingMode;
1037 }
1038
1039 public void setHighlightingMode(boolean highlightingMode) {
1040 if (highlightingMode != this.highlightingMode) {
1041
1042 this.highlightingMode = highlightingMode;
1043 float opacity = this.highlightingMode ? 0.25f : 1f;
1044 modelGroup.getElementWrapper().getStyle().setSVGProperty(SVGConstants.CSS_OPACITY_PROPERTY, Float.toString(opacity));
1045
1046 for (SVGElementModel model : selectionModel.getSelectedItems()) {
1047 displayTwin(model, highlightingMode);
1048 }
1049 highlightModel(null);
1050 }
1051 }
1052
1053 public void highlightModel(SVGElementModel model) {
1054 if (model != highlightedModel) {
1055
1056 if (highlightedModel != null && !selectionModel.isSelected(highlightedModel)) {
1057 displayTwin(highlightedModel, false);
1058 }
1059 if (model != null) {
1060 displayTwin(model, true);
1061 }
1062 highlightedModel = model;
1063 }
1064 }
1065
1066 public void displayTwin(SVGElementModel model, boolean value) {
1067
1068 if (model != modelGroup) {
1069 OMSVGStyle style = model.getTwin().getStyle().cast();
1070 if (style != null) {
1071 if (value) {
1072 style.setSVGProperty(SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_VISIBLE_VALUE);
1073
1074 } else {
1075 style.clearSVGProperty(SVGConstants.CSS_VISIBILITY_PROPERTY);
1076 }
1077 }
1078 }
1079 }
1080
1081
1082
1083
1084
1085
1086
1087 public String generateName(SVGElementModel model) {
1088 String name = model.getMetaModel().getName();
1089 if (name == null) {
1090 name = DOMHelper.getLocalName(model.getElement());
1091 }
1092 Integer count = tagNameToTagCount.get(name);
1093 if (count == null) {
1094 count = 0;
1095 }
1096 tagNameToTagCount.put(name, count + 1);
1097 return name + (count + 1);
1098 }
1099
1100
1101
1102
1103
1104
1105
1106 public OMSVGElement dereference(String idref) {
1107 if (idref.startsWith("#")) {
1108 idref = idref.substring(1);
1109 } else if (idref.startsWith("url(#")) {
1110 idref = idref.substring(5, idref.length() - 1);
1111 }
1112 return OMSVGParser.currentDocument().getElementById(idref);
1113 }
1114 }