1    /*
2    Copyright 2004 by Ralph Hartley
3    This software is licenced under the terms of the
4    Gnu Public Licence
5    */
6    import javax.swing.*;
7    import java.awt.*;
8    import java.awt.geom.*;
9    import java.util.*;
10   import java.awt.event.*;
11   
12   public class Selection implements Cloneable {
13   
14     public HashSet selection = new HashSet();
15     public HashSet subselection = new HashSet();
16     public Carto file;
17   
18     public Selection(Carto file) {
19       this.file = file;
20     }
21   
22     public Object clone() {
23       Selection res = new Selection(file);
24       res.selection = (HashSet) selection.clone();
25       res.subselection = (HashSet) subselection.clone();
26       return(res);
27     }
28   
29     public void show(View view){
30       for (Iterator it = selection.iterator();it.hasNext();)
31         ((Symbol)it.next()).showSelected(view);
32       for (Iterator it = subselection.iterator();it.hasNext();)
33         ((Symbol)it.next()).showSelected(view);      
34     }
35   
36     public boolean setLineType(LineType type,Size size,Color color) {
37       if (!selection.isEmpty()) {
38         for (Iterator it = selection.iterator();it.hasNext();) {
39           Symbol item = (Symbol)it.next();
40           if (item instanceof Curve) ((Curve)item).setLineType(type,size,color,subselection);
41         }
42         return(true);
43       }
44       return(false);
45     }
46   
47     public boolean setFill(Fill newfill) {
48       if (!selection.isEmpty()) {
49         for (Iterator it = selection.iterator();it.hasNext();) {
50           Symbol item = (Symbol)it.next();
51           if (item instanceof Curve) ((Curve)item).setFill(newfill);
52         }
53         return(true);
54       }
55       else
56         return(false);
57     }
58   
59     public boolean setFill(Color newfill) {
60       if (!selection.isEmpty()) {
61         for (Iterator it = selection.iterator();it.hasNext();) {
62           Symbol item = (Symbol)it.next();
63           if (item instanceof Curve) ((Curve)item).setFill(newfill);
64         }
65         return(true);
66       }
67       else
68         return(false);
69     }
70   
71     public void flip() {
72       for (Iterator it = selection.iterator();it.hasNext();) {
73         Symbol item = (Symbol)it.next();
74         if (item instanceof Curve) ((Curve)item).flip(subselection);
75         }
76     }
77   
78     public void copy() {
79       Carto.cutbuffer = (Selection)clone();
80     }
81   
82     public void paste(CompPane target){
83       Carto newfile = target.editor.frame.carto;
84   
85       for (Iterator it = selection.iterator();it.hasNext();) {
86         Symbol sym = ((Symbol)it.next());
87         if (newfile != file)
88           sym = sym.importSym(newfile,file);
89           target.contents.add(sym);
90         }
91   
92       file = newfile;
93       target.sel = (Selection)clone();
94       target.repaint();
95     }
96   
97     public void delete(CompPane target){
98       if (subselection.isEmpty()) {
99         for (Iterator it = selection.iterator();it.hasNext();)
100          target.contents.delete((Symbol)it.next());
101        clearSelection();
102      }
103      else {
104        for (Iterator it = selection.iterator();it.hasNext();) {
105          Symbol parent = (Symbol)it.next();
106          if (parent instanceof Addable) {
107            for (Iterator jt = subselection.iterator();jt.hasNext();) {
108              Symbol child = (Symbol) jt.next();
109              if (((Addable)parent).addType().isInstance(child))
110                ((Addable)parent).delete(child);
111            }
112          }
113        }
114        clearSubSelection();
115      }
116      target.repaint();
117    }
118  
119    public Symbol oneSelection() {
120      Symbol sel = null;
121      if (selection.size()==1) {
122        sel = (Symbol) selection.iterator().next();
123        if (subselection.size()==1)
124          sel = (Symbol) subselection.iterator().next();
125      }
126      return(sel);
127    }
128  
129  
130    public void clearSelection() {
131  //    for (Iterator it=subselection.iterator();it.hasNext();)
132  //      ((Symbol)it.next()).unSelected();
133      subselection.clear();
134  //    for (Iterator it=selection.iterator();it.hasNext();)
135  //      ((Symbol)it.next()).unSelected();
136      selection.clear();
137    }
138  
139    public void clearSubSelection() {
140  //    for (Iterator it=subselection.iterator();it.hasNext();)
141  //      ((Symbol)it.next()).unSelected();
142      subselection.clear();
143    }
144  
145    public HashSet selectionOrSub() {
146      HashSet sel = (HashSet)selection.clone();
147  
148      sel.addAll(subselection);
149      return(sel);
150    }
151  
152    public void selectAll(Comp contents) {
153      for (Iterator it=contents.members.iterator();it.hasNext();)
154        selection.add((Symbol)it.next());
155    }
156  
157    public void invertSelection(Comp contents) {
158  //    for (Iterator it=subselection.iterator();it.hasNext();)
159  //      ((Symbol)it.next()).unSelected();
160      subselection.clear();
161      for (Iterator it=contents.members.iterator();it.hasNext();) {
162        Symbol item = (Symbol)it.next();
163        if (selection.contains(item)) {
164          selection.remove(item);
165  //        item.unSelected();
166        }
167        else selection.add(item);
168      }
169    }
170  
171    static Symbol checkSet(Collection cands,Point2D pos,View view) {
172      for (Iterator it=cands.iterator();it.hasNext();) {
173        Symbol item = (Symbol)it.next();
174        if (item.selectProbe(pos,view)) return(item);
175      }
176      return(null);
177    }
178  
179    static Symbol exclusiveCheckSet(Collection cands,Collection exclude,Point2D pos,View view) {
180      for (Iterator it=cands.iterator();it.hasNext();) {
181        Symbol item = (Symbol)it.next();
182        if (!exclude.contains(item)&&item.selectProbe(pos,view)) return(item);
183      }
184      return(null);
185    }
186  
187    /** selects or subselects at the given point.
188     *Return true if something was selected */
189    public boolean select(Comp contents,boolean shift,Point2D pos,View view,boolean sub) {
190      Symbol newselection = null;
191      if (sub) {
192        newselection = checkSet(subselection,pos,view);
193        if (newselection!=null) {
194          if (shift) {
195            subselection.remove(newselection);
196  //          newselection.unSelected();
197            return(false);
198          }
199          return(true);
200        }
201        for (Iterator it=selection.iterator();it.hasNext();) {
202            Symbol item = (Symbol)it.next();
203            if (item instanceof SubSelectable) {
204              newselection = checkSet(((SubSelectable)item).getSelectable(),pos,view);
205              if (newselection!=null) {
206                if (!shift) {
207          	clearSubSelection();
208  //        	return(false);
209                }
210                subselection.add(newselection);
211                return(true);
212              }
213          }
214        }
215      }
216      newselection = checkSet(selection,pos,view);
217      if (newselection!=null) {
218        if (shift) {
219          selection.remove(newselection);
220          if (newselection instanceof SubSelectable)
221            for (Iterator it=((SubSelectable)newselection).getSelectable().iterator();it.hasNext();) {
222              Symbol item = (Symbol)it.next();
223              if (subselection.contains(item)) {
224                subselection.remove(item);
225  //              item.unSelected();
226              }
227            }
228  //        newselection.unSelected();
229          return(false);
230        }
231        return(true);
232      }
233      if (!shift) clearSelection();
234  
235      newselection = exclusiveCheckSet(contents.getSelectable(),selection,pos,view);
236      if (newselection!=null) {
237        selection.add(newselection);
238        return(true);
239      }
240      return(false);
241    }
242  
243    public void editProperties(Comp contents,boolean shift,Point2D pos,View view,boolean sub) {
244      if (!select(contents,shift,pos,view,sub) || selection.size()!=1)
245        contents.editProperties(selection,contents);
246      else {
247        ((Symbol)selection.iterator().next()).editProperties(subselection,contents);
248      }
249    }
250  
251    public Addable getAddable() {
252      for (Iterator it = selection.iterator();it.hasNext();) {
253        Object item = it.next();
254        if (item instanceof Addable) return((Addable)item);
255      }
256      return(null);
257    }
258  
259    Set dragset = null;
260    boolean dragsub;
261  
262    public void startDrag(boolean subsel) {
263      dragsub = !subsel && !subselection.isEmpty();
264  
265      Set drag;
266      if (dragsub)
267        drag = subselection;
268      else
269        drag = selection;
270  
271      dragset = new HashSet();
272      for (Iterator it = drag.iterator();it.hasNext();) {
273        Symbol item = (Symbol)it.next();
274        if (item instanceof DragableSymbol) dragset.add(item);
275      }
276      if (dragset.isEmpty()) dragset=null;
277    }
278  
279    public boolean drag(Point2D pos,boolean dragged,int mode,Point2D dragpos,View view) {
280      if (dragset==null) return(false);
281  
282      if (!dragged)
283        for (Iterator it = dragset.iterator();it.hasNext();)
284          ((DragableSymbol)it.next()).startDrag(mode,dragpos,view);
285      
286      for (Iterator it = dragset.iterator();it.hasNext();) {
287        ((DragableSymbol)it.next()).drag(mode,pos,view);
288      }
289  
290      if (dragsub)
291        for (Iterator it = selection.iterator();it.hasNext();) {
292          Symbol item = (Symbol)it.next();
293          if (item instanceof Addable) ((Addable)item).change(dragset,pos,view);
294        }
295  
296      return(true);
297    }
298  
299    public boolean endDrag(Point2D pos, int mode, View view) {
300      if (dragset==null) return(false);
301  
302      for (Iterator it = dragset.iterator();it.hasNext();)
303        ((DragableSymbol)it.next()).endDrag(mode,pos,view);
304  
305      return(true);
306    }
307  
308    public void selectRect(Rectangle2D selregion,Comp contents,View view,boolean shift) {
309      for (Iterator it = contents.getSelectable().iterator();it.hasNext();) {
310        Symbol item = (Symbol)it.next();
311        Rectangle2D ibounds = item.getBounds(view.trans);
312  
313        if (ibounds!=null && selregion.contains(ibounds)) {
314          if (shift && selection.contains(item)) {
315            selection.remove(item);
316            if (item instanceof SubSelectable)
317              for (Iterator remit=((SubSelectable)item).getSelectable().iterator();remit.hasNext();) {
318                Symbol ritem = (Symbol)remit.next();
319                if (subselection.contains(ritem)) {
320          	subselection.remove(ritem);
321  //        	ritem.unSelected();
322                }
323              }
324  //          item.unSelected();
325          }
326          else selection.add(item);
327        }
328      }
329    }
330  }
331