1    /*
2    Copyright 2004 by Ralph Hartley
3    This software is licenced under the terms of the
4    Gnu Public Licence
5    */
6    import java.util.*;
7    import java.awt.*;
8    import java.awt.geom.*;
9    import java.awt.event.*;
10   import javax.swing.*;
11   import javax.swing.event.*;
12   
13   public class Stacking implements ActionListener,ListModel,ListCellRenderer,java.io.Serializable {
14   
15     private static final long serialVersionUID = Version.getSUID();
16   
17   //  Comp comp = null;
18   
19     Vector modifier = new Vector();
20     Vector target = new Vector();
21     Vector relation = new Vector();
22   
23     transient Stacking edit;
24     transient JList memberlist;
25     transient JList modlist;
26     transient JList targlist;
27     transient HashSet datalisteners;
28   
29     transient JPanel listbox;
30     transient JLabel modlab;
31     transient int modpad;
32     transient JLabel rellab;
33     transient JLabel targlab;
34     transient int targpad;
35   
36     static int scrollmargin = 4;
37     static int MAXWIDTH = 400;
38     static int MAXHEIGHT = 200;
39   
40     static Icon DELICON = null;
41     static Icon OVERICON = null;
42     static Icon UNDERICON = null;
43     static Icon HIDEICON = null;
44   
45     static String DELCOM = "Delete";
46     static String OVERCOM = "Over";
47     static String UNDERCOM = "Under";
48     static String HIDECOM = "Hide";
49   
50     static int OVER = 1;
51     static int UNDER = 2;
52     static int HIDE = 4;
53   
54     transient public Area over = null;
55     transient public Area under = null;
56     transient public Area hide = null;
57   
58     public void getOverUnder(Symbol targ,View view) {
59   
60       over = null;
61       under = null;
62       hide = null;
63   
64       for (int i=target.indexOf(targ);i>=0;i=target.indexOf(targ,i+1)) {
65         int rel = ((Integer)relation.elementAt(i)).intValue();
66         Area part = ((Region)modifier.elementAt(i)).getIn(view);
67   
68         if (rel>0) {
69           if (rel == OVER) {
70             if (over == null) over = part;
71             else over.add(part);
72           }
73   
74           else if (rel == UNDER) {
75             if (under == null) under = part;
76             else under.add(part);
77           }
78   
79           else if (rel == HIDE) {
80             if (hide == null) hide = part;
81             else hide.add(part);
82           }
83         }
84       }
85     }
86   
87     public Stacking() {
88     }
89   
90     public Object clone() {
91       Stacking res = new Stacking();
92       res.copy(this);
93       return((Object)res);
94     }
95   
96     public void copy(Stacking thatitem) {
97   //    super.copy(thatitem);
98       modifier = (Vector)thatitem.modifier.clone();
99       target = (Vector)thatitem.target.clone();
100      relation = (Vector)thatitem.relation.clone();
101    }
102  
103    public Object[] getMods(){
104  //    return(CartoFrame.topframe.carto.complist.toArray());
105  
106      java.util.List comps = (java.util.List)CartoFrame.topframe.carto.complist.clone();
107      comps.add(0,Everywhere.everywhere);
108  
109      return(comps.toArray());
110    }
111  
112    public Object[] getTargs(Comp comp){
113  
114      if (comp==null) return new Object[0];
115  
116      Object[] targs = new Object[comp.members.size()];
117  
118      int i = 0;
119      for (Iterator it=comp.members.iterator();it.hasNext();) {
120        Symbol sym = (Symbol)it.next();
121        if (sym instanceof Comp)
122          targs[i++] = sym;
123      }
124      for (Iterator it=comp.members.iterator();it.hasNext();) {
125        Symbol sym = (Symbol)it.next();
126        if (!(sym instanceof Comp))
127          targs[i++] = sym;
128      }
129      return(targs);
130    }
131  
132    public Container getPane(Comp comp) {
133      if (DELICON==null) {
134        DELICON = new ImageIcon(getClass().getResource("icons/stackdel.gif"));
135        OVERICON = new ImageIcon(getClass().getResource("icons/stackover.gif"));
136        UNDERICON = new ImageIcon(getClass().getResource("icons/stackunder.gif"));
137        HIDEICON = new ImageIcon(getClass().getResource("icons/stackhide.gif"));
138      }
139  
140      javax.swing.Box pane = new javax.swing.Box(BoxLayout.Y_AXIS);
141  
142      edit = (Stacking)this.clone();
143  
144      memberlist = new JList(edit);
145      memberlist.setCellRenderer(edit);
146  
147      pane.add(new JScrollPane(memberlist){
148          public Dimension getPreferredSize() {
149            Dimension dim = memberlist.getPreferredSize();
150            int w = dim.width+scrollmargin;
151            int h = dim.height+scrollmargin;
152            if (w>MAXWIDTH) w = MAXWIDTH;
153            if (h>MAXHEIGHT) h = MAXHEIGHT;
154            return(new Dimension(w,h));
155          }
156        });
157  
158      javax.swing.Box lower = new javax.swing.Box(BoxLayout.X_AXIS);
159  
160      modlist = new JList(getMods());
161      lower.add(new JScrollPane(modlist){
162          public Dimension getPreferredSize() {
163            Dimension dim = modlist.getPreferredSize();
164            int w = dim.width+scrollmargin;
165            int h = dim.height+scrollmargin;
166            if (w>MAXWIDTH/2) w = MAXWIDTH/2;
167            if (h>MAXHEIGHT/2) h = MAXHEIGHT/2;
168            return(new Dimension(w,h));
169          }
170        });
171  
172      javax.swing.Box butbox = new javax.swing.Box(BoxLayout.Y_AXIS); 
173  
174      JButton but = new JButton(OVERICON);
175      but.setActionCommand(OVERCOM);
176      but.addActionListener(this);
177      butbox.add(but);
178  
179      but = new JButton(UNDERICON);
180      but.setActionCommand(UNDERCOM);
181      but.addActionListener(this);
182      butbox.add(but);
183  
184      but = new JButton(HIDEICON);
185      but.setActionCommand(HIDECOM);
186      but.addActionListener(this);
187      butbox.add(but);
188  
189      but = new JButton(DELICON);
190      but.setActionCommand(DELCOM);
191      but.addActionListener(this);
192      butbox.add(but);
193  
194      lower.add(butbox);
195      
196      targlist = new JList(getTargs(comp));
197      lower.add(new JScrollPane(targlist){
198          public Dimension getPreferredSize() {
199            Dimension dim = targlist.getPreferredSize();
200            int w = dim.width+scrollmargin;
201            int h = dim.height+scrollmargin;
202            if (w>MAXWIDTH/2) w = MAXWIDTH/2;
203            if (h>MAXHEIGHT/2) h = MAXHEIGHT/2;
204            return(new Dimension(w,h));
205          }
206        });
207      
208      pane.add(lower);
209  
210      return(pane);
211  
212    }
213  
214    public void save() {
215      copy(edit);
216    }
217  
218    public void clear() {
219      edit = null;
220      memberlist = null;
221      modlist = null;
222      targlist = null;
223      datalisteners = null;
224  
225      listbox = null;
226      modlab = null;
227      rellab = null;
228      targlab = null;
229    }
230  
231    public void addMember(Region mod, Symbol targ, int rel) {
232      int index = modifier.size();
233  
234      modifier.add(mod);
235      target.add(targ);
236      relation.add(new Integer(rel));
237  
238      if (datalisteners!=null) {
239        ListDataEvent ev = new ListDataEvent(this,ListDataEvent.INTERVAL_ADDED,index,index);
240          for (Iterator it = datalisteners.iterator();it.hasNext();)
241            ((ListDataListener)it.next()).intervalAdded(ev);
242        }
243  
244      //      getPad();
245    }
246  
247    public void delMember(int index) {
248      modifier.removeElementAt(index);
249      target.removeElementAt(index);
250      relation.removeElementAt(index);
251      if (datalisteners!=null) {
252        ListDataEvent ev = new ListDataEvent(this,ListDataEvent.INTERVAL_REMOVED,index,index);
253        for (Iterator it = datalisteners.iterator();it.hasNext();)
254          ((ListDataListener)it.next()).intervalRemoved(ev);
255      }
256  //    getPad();
257        }
258  
259    public void actionPerformed(ActionEvent e) {
260  
261      String command = e.getActionCommand();
262      
263      if(command==OVERCOM || command==UNDERCOM || command==HIDECOM){
264        Region newmod = (Region)modlist.getSelectedValue();
265        if (newmod==null) {
266          ErrorLog.log("You need to select a modifier first.");
267          return;
268        }
269  
270        Symbol newtarg = (Symbol)targlist.getSelectedValue();
271        if (newtarg==null) {
272          ErrorLog.log("You need to select a target first.");
273          return;
274        }
275  
276        if (command==OVERCOM) edit.addMember(newmod,newtarg,OVER);
277        else if (command==UNDERCOM) edit.addMember(newmod,newtarg,UNDER);
278        else if (command==HIDECOM) edit.addMember(newmod,newtarg,HIDE);
279        memberlist.invalidate();
280  
281        return;
282      }
283  
284      else if (e.getActionCommand()==DELCOM){
285        if (edit.getSize()==0) {
286          ErrorLog.log("Nothing to delete.");
287          return;
288        }
289        int index = memberlist.getSelectedIndex();
290        if (index==-1) index = edit.getSize()-1;
291  
292        edit.delMember(index);
293        memberlist.invalidate();
294  
295        return;
296      }
297    }
298  
299    public void addListDataListener(ListDataListener list) {
300      if (datalisteners==null) datalisteners = new HashSet();
301      datalisteners.add(list);
302    }
303  
304    public int getSize() {
305      return(modifier.size());
306    }
307  
308    public Object getElementAt(int index) {
309      return(new Integer(index));
310    }
311  
312    public void removeListDataListener(ListDataListener list) {
313      if (datalisteners!=null) datalisteners.remove(list);
314    }
315  
316  /*
317    void getPad() {
318      int maxwidth = 0;
319      for (Iterator it=modifier.iterator();it.hasNext();) {
320        int width = ((Comp)it.next()).getName().length();
321        if (maxwidth<width) maxwidth = width;
322      }
323      modpad = "";
324      for (int i=all.getName().length();i<1.5*maxwidth;i++)
325        modpad = modpad+" ";
326  
327      maxwidth = 0;
328      for (Iterator it=target.iterator();it.hasNext();) {
329        int width = ((Comp)it.next()).getName().length();
330        if (maxwidth<width) maxwidth = width;
331      }
332      targpad = "";
333      for (int i=all.getName().length();i<1.5*maxwidth;i++)
334        targpad = targpad+" ";
335    }
336  */
337  
338    public Component getListCellRendererComponent(JList list,
339          					Object value,
340          					int index,
341          					boolean selected,
342          					boolean hasfocus) {
343      if (listbox==null) {
344        listbox = new JPanel();
345        listbox.setLayout(new BoxLayout(listbox,BoxLayout.X_AXIS));
346        listbox.setOpaque(true);
347  
348        javax.swing.border.Border bord = new javax.swing.border.EmptyBorder(2,2,2,2);
349  
350        modlab = new JLabel();
351        modlab.setBorder(bord);
352        listbox.add(modlab);
353  
354        rellab = new JLabel();
355        rellab.setBorder(bord);
356        listbox.add(rellab);
357  
358        targlab = new JLabel();
359        targlab.setBorder(bord);
360        listbox.add(targlab);
361      }
362  
363      int op = ((Integer)relation.elementAt(index)).intValue();
364  
365      if (op==OVER) rellab.setIcon(OVERICON);
366      if (op==UNDER) rellab.setIcon(UNDERICON);
367      if (op==HIDE) rellab.setIcon(HIDEICON);
368  
369      Region mod = (Region)modifier.elementAt(index);
370      String lab = mod.getName();
371  //    if (lab.length()>maxwidth) maxwidth = lab.length();
372  //    if (layer==all) {
373  //      for (int i=lab.length();i<maxwidth;i++) lab = lab+" ";
374  //    }
375      modlab.setText(lab);
376  
377      Symbol targ = (Symbol)target.elementAt(index);
378      lab = targ.getName();
379      targlab.setText(lab);
380  
381      listbox.setForeground(selected?list.getSelectionForeground():list.getForeground());
382      listbox.setBackground(selected?list.getSelectionBackground():list.getBackground());
383  
384      return(listbox);
385    }
386  
387  }
388