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.command.dnd;
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.itf.ISVGTransformable;
25  import org.vectomatic.dom.svg.utils.SVGConstants;
26  import org.vectomatic.svg.edit.client.command.CommandFactories;
27  import org.vectomatic.svg.edit.client.command.DndCommandFactory.DropGesture;
28  import org.vectomatic.svg.edit.client.engine.SVGModel;
29  import org.vectomatic.svg.edit.client.model.ModelConstants;
30  import org.vectomatic.svg.edit.client.model.svg.SVGElementModel;
31  import org.vectomatic.svg.edit.client.model.svg.SVGNamedElementModel;
32  
33  import com.extjs.gxt.ui.client.data.BeanModel;
34  import com.extjs.gxt.ui.client.data.BeanModelLookup;
35  import com.extjs.gxt.ui.client.util.Format;
36  
37  /**
38   * Class to represent a tree cloning command
39   * @author laaglu
40   */
41  public class CloneCommand extends DndCommandBase {
42  	/**
43  	 * The models to copy, unsorted
44  	 */
45  	protected List<SVGElementModel> models;
46  	/**
47  	 * The cloned models, unsorted
48  	 */
49  	protected List<SVGElementModel> clones;
50  	/**
51  	 * The target model
52  	 */
53  	protected SVGElementModel target;
54  	/**
55  	 * The drop gesture
56  	 */
57  	protected DropGesture dropGesture;
58  	
59  	public CloneCommand(List<SVGElementModel> models, SVGElementModel target, DropGesture dropGesture) {
60  		super(CommandFactories.getDndCommandFactory());
61  		this.models = models;
62  		this.target = target;
63  		this.dropGesture = dropGesture;
64  		for (SVGElementModel model : models) {
65  			assert model.getOwner() == target.getOwner() : "Attempt to copy models from heterogeneous owners: " + model.getOwner() + ", " + target.getOwner();
66  		}
67  	}
68  
69  	@Override
70  	public String getDescription() {
71  		String message = null;
72  		switch(dropGesture) {
73  			case OnNode:
74  				message = ModelConstants.INSTANCE.dndCloneCmdIn();
75  				break;
76  			case BeforeNode:
77  				message = ModelConstants.INSTANCE.dndCloneCmdBefore();
78  				break;
79  			case AfterNode:
80  				message = ModelConstants.INSTANCE.dndCloneCmdAfter();
81  				break;
82  		}
83  		return Format.substitute(message, SVGNamedElementModel.getNames(models), target.toString());
84  	}
85  
86  	@Override
87  	public void commit() {
88  		SVGModel owner = target.getOwner();
89  		if (clones == null) {
90  			clones = new ArrayList<SVGElementModel>();
91  			for (SVGElementModel model : models) {
92  				SVGElementModel clone = owner.clone(model, Format.substitute(ModelConstants.INSTANCE.copyOf(), model.get(SVGConstants.SVG_TITLE_TAG).toString()));
93  				clones.add(clone);
94  			}
95  		}
96  		SVGElementModel parentModel = null;
97  		SVGElementModel refModel = null;
98  		if (dropGesture == DropGesture.OnNode) {
99  			// target is a folder
100 			parentModel = target;
101 		} else {
102 			// target is a leaf in the same document
103 			parentModel = (SVGElementModel) target.getParent();
104 			if (dropGesture == DropGesture.BeforeNode) {
105 				refModel = target;
106 			} else if (dropGesture == DropGesture.AfterNode) {
107 				refModel = target.getNextSibling();
108 			}
109 		}
110 		
111 		OMSVGElement parentElement = parentModel.getElementWrapper();
112 		for (int i = 0, size = models.size(); i < size; i++) {
113 			SVGElementModel model = models.get(i);
114 			SVGElementModel clone = clones.get(i);
115 
116 			// Update the transform of a model which is going to be
117 			// attached to a parent model so that the model appears 
118 			// unchanged to the end-user. This is done by applying
119 			// a counter transform (the inverse of the transform
120 			// of the parent) to to nullify its effect
121 			OMSVGElement element = model.getElementWrapper();
122 			clone.updateTransform(((ISVGTransformable)element).getTransformToElement(parentElement));
123 
124 			owner.insertBefore(parentModel, clone, refModel);
125 		}
126 
127 	}
128 
129 	@Override
130 	public void rollback() {
131 		SVGModel owner = target.getOwner();
132 		for (SVGElementModel clone : clones) {
133 			owner.remove(clone);
134 		}
135 	}
136 
137 	@Override
138 	public BeanModel asModel() {
139 		return BeanModelLookup.get().getFactory(CloneCommand.class).createModel(this);
140 	}
141 
142 }