1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.editor.textEditor.viewers;
13
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Set;
17
18 import org.eclipse.gef.EditPart;
19 import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
20 import org.w3c.dom.Node;
21
22 import sk.baka.ikslibs.ids.IDManager;
23 import sk.baka.ikslibs.interval.DOMInterval;
24 import sk.baka.ikslibs.interval.DOMIntervalSet;
25 import sk.uniba.euromath.editor.selections.DOMSelectionChangedEvent;
26 import sk.uniba.euromath.editor.selections.IDOMSelectionChangedListener;
27 import sk.uniba.euromath.editor.selections.IDOMSelectionProvider;
28 import sk.uniba.euromath.editor.textEditor.ITextPieceContainer;
29 import sk.uniba.euromath.editor.textEditor.ITextPieceKeeper;
30 import sk.uniba.euromath.editor.textEditor.TextEditPartFactory;
31 import sk.uniba.euromath.editor.textEditor.editParts.TextEditPart;
32 import sk.uniba.euromath.editor.xmlEditor.IdVisualInfo;
33 import sk.uniba.euromath.editor.xmlEditor.XMLEditDomain;
34 import sk.uniba.euromath.editor.xmlEditor.XMLEditPartFactory;
35 import sk.uniba.euromath.editor.xmlEditor.XMLEditor;
36 import sk.uniba.euromath.editor.xmlEditor.editParts.XMLEditPart;
37 import sk.uniba.euromath.editor.xmlEditor.viewers.IXMLGraphicalViewer;
38
39 /***
40 * Overrides selection funcionality of ScrollingGraphicalViewer. Selection is represented by DOMIntervalSet.
41 * Converts DOMIntervals from DOMIntervalSet to EditParts and start offset and end offset in this EditParts
42 *
43 * Call @see #commitSelection() when selecting ends (mouse up, button up), this fires selection to
44 * <code>selectionChangedListeners</code>
45 *
46 * @author Martin Kollar
47 */
48
49 public class ScrollingTextGraphicalViewer extends ScrollingGraphicalViewer
50 implements IXMLGraphicalViewer{
51
52 /***
53 * Local selection for this viewer. This selection is commited to listeners by calling
54 * fireSelectionChanged() method
55 */
56 private DOMIntervalSet localSelection;
57 protected List<IDOMSelectionChangedListener> selectionChangedListeners =
58 new ArrayList<IDOMSelectionChangedListener>();
59
60 private XMLEditor editor;
61
62 /***
63 * @param editor Editor that uses this viewer to view its state
64 */
65 public ScrollingTextGraphicalViewer(XMLEditor editor){
66 super();
67 this.editor = editor;
68 }
69
70 /***
71 * @param listener new listener to be add from selectionChangedListeners
72 */
73 public void addSelectionChangedListener(IDOMSelectionChangedListener listener) {
74 if (!(selectionChangedListeners.contains(listener)))
75 selectionChangedListeners.add(listener);
76 }
77
78 /***
79 * @param listener listener to be removed from selectionChangedListeners
80 */
81 public void removeSelectionChangedListener(IDOMSelectionChangedListener listener) {
82 selectionChangedListeners.remove(listener);
83 }
84
85 public void showSelection(DOMIntervalSet selection) {
86
87
88 }
89
90 /***
91 * Deselects editparts with Ids, that were in previous selection and select editparts
92 * that are in DOMIntervalSet
93 * @param selection DOMIntervalSet containing DOMInetervals, that have to be selected
94 */
95 public void setSelection(DOMIntervalSet selection) {
96 IdVisualInfo visualInfo = ((XMLEditPartFactory)getEditPartFactory()).getVisualInfo();
97
98 Set<String> oldIds = getDOMSelection().getContentIds(getIDManager());
99
100 for (String notSelectedId : oldIds){
101
102 if (notSelectedId.indexOf(':') >= 0)
103 notSelectedId = notSelectedId.substring(0, notSelectedId.indexOf(':'));
104
105 List<XMLEditPart> notSelectedParts = visualInfo.getVisualParts(notSelectedId);
106 for (XMLEditPart editPart : notSelectedParts)
107 deselect(editPart);
108 }
109
110 this.localSelection = selection;
111
112 for (DOMInterval interval : selection.getIntervals()){
113
114 List<Node> contents = interval.getContents();
115
116 int startOffset = -1;
117 int endOffset = -1;
118
119 if ( (interval.getStartingIndex() > -1) && (interval.getEndingIndex() > -1) ) {
120
121 if (getEditPartFactory() instanceof TextEditPartFactory){
122
123 ITextPieceContainer container1 = ((TextEditPartFactory)getEditPartFactory()).
124 getIdLastContainerMap().get(interval.from.pointsTo);
125 ITextPieceKeeper keeper1 = container1.OffsetInPieceKeeper(interval.getStartingIndex());
126 startOffset = interval.getStartingIndex() - keeper1.getTextPieceInfo().getOffset();
127
128 ITextPieceContainer container2 = ((TextEditPartFactory)getEditPartFactory()).
129 getIdLastContainerMap().get(interval.to.pointsTo);
130 ITextPieceKeeper keeper2 = container2.OffsetInPieceKeeper(interval.getEndingIndex());
131 endOffset = interval.getEndingIndex() - keeper2.getTextPieceInfo().getOffset();
132
133 if (container1 == container2){
134
135 int i = container1.indexOf(keeper1);
136 int j = container1.indexOf(keeper2);
137 if (i==j){
138
139
140
141 keeper1.select(startOffset, endOffset);
142 select(keeper1, startOffset, endOffset);
143 break;
144 }
145 if (i<j){
146 select(keeper1, startOffset, keeper1.getText().length());
147 select(keeper2, 0, endOffset);
148 keeper1.select(startOffset,keeper1.getText().length());
149 keeper2.select(0, endOffset);
150 for (int k = i+1; k<j-1; k++){
151
152 ITextPieceKeeper keeper = container1.getPiece(k);
153 keeper.select();
154 select(keeper,0,keeper.getText().length());
155 }
156 break;
157 }
158 throw new IllegalStateException("Interval starting index have to be befor interval ending index");
159 }
160
161
162 ITextPieceContainer container;
163 for (Node node : contents){
164 String nodeId = getIDManager().getIDNull(node);
165 if (nodeId != null){
166 container = ((TextEditPartFactory)getEditPartFactory()).
167 getIdLastContainerMap().get(nodeId);
168
169 int fromKeeper = 0;
170 int toKeeper = container.getPieceCount()-1;
171 if (container == container1)
172 fromKeeper = container1.indexOf(keeper1);
173 if (container == container2)
174 toKeeper = container2.indexOf(keeper2);
175 for (int i=fromKeeper; i<toKeeper; i++){
176 ITextPieceKeeper keeper = container.getPiece(i);
177 int start;
178 int end;
179 if (keeper == keeper1)
180 start = startOffset;
181 else
182 start = 0;
183 if (keeper == keeper2)
184 end = endOffset;
185 else
186 end = keeper.getText().length();
187 keeper.select(start, end);
188 select(keeper,start,end);
189 break;
190 }
191 }
192 }
193
194 }
195 }
196
197
198 for (Node node : contents){
199 String nodeId = getIDManager().getIDNull(node);
200 if (nodeId != null){
201 List<XMLEditPart> selectedParts = visualInfo.getVisualParts(nodeId);
202 for(XMLEditPart xmlEditPart : selectedParts){
203 select(xmlEditPart);
204 }
205 }
206 }
207
208
209 }
210 }
211
212
213 /***
214 * Effect is same as using setSelection
215 *@param event DOMSelectionChangedEvent that contains source of new selction, that should be
216 * some XMLEditor and DOMIntervalSet as selection
217 */
218 public void selectionChanged(DOMSelectionChangedEvent event) {
219 setSelection(event.getDOMSelection());
220 }
221
222 /***
223 * This is called when selecting ends (mouse up or button up)
224 */
225 @Override
226 protected void fireSelectionChanged(){
227 DOMSelectionChangedEvent event = new DOMSelectionChangedEvent(this, this.localSelection);
228 for (IDOMSelectionChangedListener listener : selectionChangedListeners)
229 listener.selectionChanged(event);
230 }
231
232 protected void select(ITextPieceKeeper keeper, int start, int end){
233 keeper.select(start, end);
234 if (!(getSelectedEditParts().contains(keeper))){
235 getSelectedEditParts().add(keeper);
236
237 }
238 }
239
240 /***
241 * Selecting whole EditPart. When this EditPart was not in selected EditParts, than
242 * fireSelectionChanged()
243 *
244 * If <code>editpart</code> is ITextPieceKeeper then visualization is left on
245 * @see ITextPieceKeeper#select()
246 * If <code>editpart</code> is not ITextPieceKeeper then visualization is left on this editpart.
247 * @see EditPart#setSelected(EditPart.SELECTED)
248 *
249 * @param editpart EditPart that is going to be selected
250 */
251 @Override
252 public void select(EditPart editpart){
253
254 editpart.setSelected(EditPart.SELECTED);
255
256 if (editpart instanceof ITextPieceKeeper)
257 ((ITextPieceKeeper)editpart).select();
258
259
260 if (!(getSelectedEditParts().contains(editpart))){
261 getSelectedEditParts().add(editpart);
262
263 }
264
265 }
266
267
268 /***
269 * Deselecting whole EditPart. Alwas fires selection change
270 *
271 * If <code>editpart</code> is ITextPieceKeeper then visualization is left on
272 * @see ITextPieceKeeper#deselect()
273 * If <code>editpart</code> is not ITextPieceKeeper then visualization is left on this editpart.
274 * @see EditPart#setSelected(EditPart.SELECTED_NONE)
275 *
276 * @param editpart EditPart that is going to be deselected
277 */
278 @Override
279 public void deselect(EditPart editpart){
280 editpart.setSelected(EditPart.SELECTED_NONE);
281
282 if (editpart instanceof ITextPieceKeeper)
283 ((ITextPieceKeeper)editpart).deselect();
284
285 if (getSelectedEditParts().contains(editpart)){
286 getSelectedEditParts().remove(editpart);
287
288 }
289
290 }
291
292 /***
293 * Deselects all selected editparts.
294 * At the end fires selection change
295 */
296 @Override
297 public void deselectAll(){
298 super.deselectAll();
299 List<EditPart> list = new ArrayList<EditPart>();
300 list.addAll(getSelectedEditParts());
301
302 this.selection.clear();
303
304 for(EditPart editpart : list){
305 editpart.setSelected(EditPart.SELECTED_NONE);
306
307 if (editpart instanceof ITextPieceKeeper)
308 ((ITextPieceKeeper)editpart).deselect();
309 }
310
311 getSelectedEditParts().clear();
312
313 fireSelectionChanged();
314 }
315
316 /***
317 * This tells to DOMSelectionChangeListeners(probably only TextEditor), about new
318 * selection. Local selection of this GraphiclViewer becomes a globalSelction
319 *
320 * Call this method when selction ends - mouse up, Shift key up, etc.
321 */
322 public void commitSelection(){
323 fireSelectionChanged();
324 }
325
326 public List getSelectedEditParts(){
327 return super.getSelectedEditParts();
328 }
329
330
331 private IDManager getIDManager(){
332 return ((XMLEditDomain)getEditDomain()).getXMLEditor().getXMLAccess().getIdManager();
333 }
334
335 /***
336 * @return global selection
337 */
338 public DOMIntervalSet getDOMSelection() {
339 return this.editor.getDOMSelection();
340 }
341
342 }