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 org.vectomatic.svg.edit.client.SVGWindow;
21  import org.vectomatic.svg.edit.client.command.CommandFactories;
22  import org.vectomatic.svg.edit.client.command.DndCommandFactory;
23  import org.vectomatic.svg.edit.client.command.DndCommandFactory.DropGesture;
24  import org.vectomatic.svg.edit.client.engine.SVGModel;
25  import org.vectomatic.svg.edit.client.engine.SVGProcessor;
26  import org.vectomatic.svg.edit.client.model.svg.SVGElementModel;
27  
28  import com.extjs.gxt.ui.client.core.El;
29  import com.extjs.gxt.ui.client.dnd.DropTarget;
30  import com.extjs.gxt.ui.client.dnd.Insert;
31  import com.extjs.gxt.ui.client.dnd.ScrollSupport;
32  import com.extjs.gxt.ui.client.event.DNDEvent;
33  import com.extjs.gxt.ui.client.util.Rectangle;
34  import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.TreeNode;
35  import com.google.gwt.core.client.GWT;
36  import com.google.gwt.user.client.Element;
37  import com.google.gwt.user.client.Timer;
38  
39  /**
40   * Drop target for SVGWindow
41   * @author laaglu
42   */
43  public class SVGTreePanelDropTarget extends DropTarget {
44  	protected DndCommandFactory dndCommandFactory;
45  	protected TreePanelExt<SVGElementModel> tree;
46  	protected TreeNode activeItem, appendItem;
47  	protected DropGesture dropGesture;
48  
49  	private boolean restoreTrackMouse;
50  	private ScrollSupport scrollSupport;
51  
52  	protected SVGModel svgModel;
53  	public SVGTreePanelDropTarget(SVGWindow window) {
54  		super(window.getTree());
55  		this.tree = window.getTree();
56  		svgModel = window.getSvgModel();
57  		dndCommandFactory = CommandFactories.getDndCommandFactory();
58  	}
59  
60  	protected void clearStyles(DNDEvent event) {
61  		Insert.get().hide();
62  		event.getStatus().setStatus(false);
63  		if (activeItem != null) {
64  			tree.getView().onDropChange(activeItem, false);
65  		}
66  	}
67  
68  	@Override
69  	protected void onDragDrop(DNDEvent event) {
70  		GWT.log("SVGTreePanelDropTarget.onDragDrop");
71  		super.onDragDrop(event);
72  		if (event.getData() == null)
73  			return;
74  
75  		tree.getView().onDropChange(activeItem, false);
76  		dndCommandFactory.processDragAndDrop(dropGesture);
77  		tree.setTrackMouseOver(restoreTrackMouse);
78  		activeItem = null;
79  		appendItem = null;
80  		scrollSupport.stop();
81  	}
82  
83  	@Override
84  	protected void onDragEnter(DNDEvent e) {
85  		super.onDragEnter(e);
86  		e.getStatus().setStatus(false);
87  		restoreTrackMouse = tree.isTrackMouseOver();
88  		tree.setTrackMouseOver(false);
89  
90  		if (scrollSupport == null) {
91  			scrollSupport = new ScrollSupport(tree.el());
92  		}
93  		scrollSupport.start();
94  	}
95  
96  	@Override
97  	protected void onDragFail(DNDEvent event) {
98  		super.onDragFail(event);
99  		scrollSupport.stop();
100 	}
101 
102 	@Override
103 	protected void onDragLeave(DNDEvent e) {
104 		super.onDragLeave(e);
105 		if (activeItem != null) {
106 			tree.getView().onDropChange(activeItem, false);
107 			activeItem = null;
108 		}
109 		tree.setTrackMouseOver(restoreTrackMouse);
110 		scrollSupport.stop();
111 	}
112 
113 	@Override
114 	protected void onDragMove(DNDEvent event) {
115 		event.setCancelled(false);
116 	}
117 
118 	@Override
119 	protected void showFeedback(DNDEvent event) {
120 		// GWT.log("showFeedback");
121 		// Determine the tree node over which the cursor is hovering, if any
122 		final TreeNode overItem = tree.findNode(event.getTarget());
123 		if (!dndCommandFactory.isValidDropTarget(getModel(overItem))) {
124 			// Not over a tree item
125 			clearStyles(event);
126 			return;
127 		}
128 		handleInsert(event, overItem);
129 	}
130 	
131 
132 	protected void handleInsert(DNDEvent event, final TreeNode item) {
133 		// Determine the position of the cursor with regards to the drop item
134 		// to find out if the drag source should be inserted before or after
135 		// the drop item
136 		int height = item.getElement().getOffsetHeight();
137 		int mid = height / 2;
138 		int top = item.getElement().getAbsoluteTop();
139 		mid += top;
140 		int y = event.getClientY();
141 		boolean before = y < mid;
142 
143 		if ((!item.isLeaf() || SVGProcessor.isGroupElement(getModel(item).getElement()))
144 				&& ((before && y > top + 4) || (!before && y < top + height - 4))) {
145 			handleAppend(event, item);
146 			return;
147 		}
148 		dropGesture = before ? DropGesture.BeforeNode : DropGesture.AfterNode;
149 
150 		// clear any active append item
151 		if (activeItem != null) {
152 			tree.getView().onDropChange(activeItem, false);
153 		}
154 		appendItem = null;
155 		activeItem = item;
156 
157 		int idx = -1;
158 		if (activeItem.getParent() == null) {
159 			idx = tree.getStore().getRootItems().indexOf(activeItem);
160 		} else {
161 			idx = activeItem.getParent().indexOf(item);
162 		}
163 		
164 		event.getStatus().setStatus(true);
165 
166 		showInsert(event, item.getElement(), before);
167 	}
168 	
169 	protected void handleAppend(DNDEvent event, final TreeNode item) {
170 		dropGesture = DropGesture.OnNode;
171 		Insert.get().hide();
172 		event.getStatus().setStatus(true);
173 		// clear any active append item
174 		if (activeItem != null) {
175 			tree.getView().onDropChange(activeItem, false);
176 		}
177 
178 		if (item != null && item != appendItem && !item.isExpanded()) {
179 			Timer t = new Timer() {
180 				@Override
181 				public void run() {
182 					if (item == appendItem) {
183 
184 						item.setExpanded(true);
185 					} else {
186 					}
187 				}
188 			};
189 			// auto-expand delay
190 			t.schedule(800);
191 		}
192 		appendItem = item;
193 		activeItem = item;
194 		if (activeItem != null) {
195 			tree.getView().onDropChange(activeItem, true);
196 		}
197 	}
198 
199 
200 
201 	private void showInsert(DNDEvent event, Element elem, boolean before) {
202 		Insert insert = Insert.get();
203 		insert.show(elem);
204 		Rectangle rect = El.fly(elem).getBounds();
205 		int y = before ? rect.y - 2 : (rect.y + rect.height - 4);
206 		insert.setBounds(rect.x, y, rect.width, 6);
207 	}
208 	
209 	
210 	public SVGElementModel getActiveItem() {
211 		return getModel(activeItem);
212 	}
213 	public SVGElementModel getModel(TreeNode treeNode) {
214 		if (treeNode != null) {
215 			return (SVGElementModel)treeNode.getModel();
216 		}
217 		return null;
218 	}
219 	public SVGModel getSvgModel() {
220 		return svgModel;
221 	}
222 }