View Javadoc

1   /**********************************************
2    * Copyright (C) 2011 Lukas Laag
3    * This file is part of svgreal.
4    * 
5    * svgreal is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * svgreal is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with svgreal.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package org.vectomatic.svg.edit.client.gxt.widget;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import org.vectomatic.dom.svg.OMSVGElement;
24  import org.vectomatic.dom.svg.OMSVGMatrix;
25  import org.vectomatic.dom.svg.OMSVGPoint;
26  import org.vectomatic.dom.svg.OMSVGRect;
27  import org.vectomatic.dom.svg.OMSVGSVGElement;
28  import org.vectomatic.dom.svg.impl.SVGSVGElement;
29  import org.vectomatic.dom.svg.itf.ISVGLocatable;
30  import org.vectomatic.dom.svg.utils.SVGConstants;
31  import org.vectomatic.svg.edit.client.AppBundle;
32  import org.vectomatic.svg.edit.client.AppCss;
33  import org.vectomatic.svg.edit.client.command.dnd.IDndHandler;
34  import org.vectomatic.svg.edit.client.model.svg.SVGElementModel;
35  
36  import com.extjs.gxt.ui.client.event.DNDEvent;
37  import com.extjs.gxt.ui.client.event.DragEvent;
38  import com.google.gwt.core.client.GWT;
39  import com.google.gwt.dom.client.DivElement;
40  import com.google.gwt.dom.client.Document;
41  import com.google.gwt.user.client.Element;
42  
43  /**
44   * Class to give users visual feedback on the drag operation
45   * about to be performed
46   * @author laaglu
47   */
48  public class DNDGhost {
49  	private static final String ATT_OPERATION = "operation";
50  	/**
51  	 * To update the DND operation
52  	 */
53  	private static SVGSVGElement operationElement;
54  	private static DivElement messageElement;
55  	private DivElement ghostElement;
56  	private List<SVGElementModel> sourceElements;
57  	public DNDGhost(List<SVGElementModel> sourceElements, DNDEvent event) {
58  		/*
59  		 * The custom ghost has the following css structure
60  		 * custom ghost container div (ghost)
61  		 *  source div (ghost-source)
62  		 *  operation div (ghost-operation)
63  		 *  message div (ghost-message)
64  		 */
65  		this.sourceElements = sourceElements;
66  		
67  		// Create the SVG miniature of the first element in the source
68  		AppCss css = AppBundle.INSTANCE.css();
69  		OMSVGSVGElement svg = new OMSVGSVGElement();
70  		OMSVGElement svgElement = sourceElements.get(0).getElementWrapper();
71  		ISVGLocatable locatable = (ISVGLocatable) svgElement;
72  	    OMSVGRect bbox = getScreenBBox(svg, locatable);
73  		OMSVGRect viewBox = svg.getViewBox().getBaseVal();
74  		bbox.assignTo(viewBox);
75  		OMSVGElement clone = (OMSVGElement) svgElement.cloneNode(true);
76  		OMSVGMatrix m = locatable.getCTM();
77  		if (!m.isIdentity()) {
78  			StringBuilder builder = new StringBuilder();
79  			builder.append(SVGConstants.TRANSFORM_MATRIX + "(");
80  			builder.append(m.getDescription());
81  			builder.append(")");
82  			clone.setAttribute(SVGConstants.SVG_TRANSFORM_ATTRIBUTE, builder.toString());
83  		} else {
84  			clone.removeAttribute(SVGConstants.SVG_TRANSFORM_ATTRIBUTE);
85  		}
86  		
87  		svg.appendChild(clone);
88  		svg.setClassNameBaseVal(css.ghostSource());
89  
90  		// Create the operation icon
91  		if (operationElement == null) {
92  			operationElement = (SVGSVGElement) AppBundle.INSTANCE.dndIcons().getSvg().getElement();
93  			operationElement.getClassName_().setBaseVal(css.ghostOperation());
94  		}
95  
96  		// Create the DND message
97  		if (messageElement == null) {
98  			messageElement = Document.get().createDivElement();
99  			messageElement.setClassName(css.ghostMessage());
100 		}
101 		
102 		// Create the ghost
103 		ghostElement = Document.get().createDivElement();
104 		ghostElement.setClassName(css.ghost());
105 		ghostElement.appendChild(svg.getElement());
106 		ghostElement.appendChild(operationElement);
107 		ghostElement.appendChild(messageElement);
108 		
109 		DragEvent dragEvent = event.getDragEvent();
110 		dragEvent.setWidth(120);
111 		dragEvent.setHeight(94);
112 	}
113 	
114 	public void update(IDndHandler dndHandler) {
115 		operationElement.setAttribute(ATT_OPERATION, dndHandler.getOperationCssAttr());
116 		messageElement.setInnerText(dndHandler.getMessage(sourceElements));
117 	}
118 
119 	public Element getElement() {
120 		return (com.google.gwt.user.client.Element) ghostElement.cast();
121 	}
122 
123 	private static OMSVGRect getScreenBBox(OMSVGSVGElement svg, ISVGLocatable locatable) {
124 		OMSVGRect bbox = locatable.getBBox();
125 	    OMSVGMatrix m = locatable.getCTM();
126 	    List<OMSVGPoint> list = new ArrayList<OMSVGPoint>();
127 	    list.add(svg.createSVGPoint(bbox.getX(), bbox.getY()).matrixTransform(m));
128 	    list.add(svg.createSVGPoint(bbox.getMaxX(), bbox.getY()).matrixTransform(m));
129 	    list.add(svg.createSVGPoint(bbox.getX(), bbox.getMaxY()).matrixTransform(m));
130 	    list.add(svg.createSVGPoint(bbox.getMaxX(), bbox.getMaxY()).matrixTransform(m));
131 	    float xmin = list.get(0).getX(), ymin = list.get(0).getY(), xmax = list.get(0).getX(), ymax = list.get(0).getY();
132 		for (int i = 1, size = list.size(); i < size; i++) {
133 			OMSVGPoint p = list.get(i);
134 			xmin = Math.min(p.getX(), xmin);
135 			ymin = Math.min(p.getY(), ymin);
136 			xmax = Math.max(p.getX(), xmax);
137 			ymax = Math.max(p.getY(), ymax);
138 		}
139 	    OMSVGRect screenBBox = svg.createSVGRect(xmin, ymin, xmax - xmin, ymax - ymin);
140 		GWT.log("m="+m.getDescription());
141 		GWT.log("bbox="+bbox.getDescription());
142 		GWT.log("screenBBox="+screenBBox.getDescription());
143 		return screenBBox;
144 	}
145 
146 }