1    /*
2    Copyright 2000 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.event.*;
9    import javax.swing.*;
10   import javax.swing.event.*;
11   
12   public class LayerList extends Layer implements ActionListener,ListModel,ListCellRenderer {
13   
14     private static final long serialVersionUID = Version.getSUID();
15   
16     Vector members;
17     Vector operator;
18   
19   //  transient HashSet on = new HashSet();
20   //  transient HashSet off = new HashSet();
21   
22     public static int PROVISIONAL = 1;
23     public static int INCLUDE = 2;
24   
25     public LayerList(String name,Collection members) {
26       super(name);
27       this.members = new Vector();
28       this.members.add(all);
29       this.members.addAll(members);
30       operator = new Vector();
31       operator.add(new Integer(PROVISIONAL&INCLUDE));
32       for (Iterator it=members.iterator();it.hasNext();) {
33         operator.add(new Integer(PROVISIONAL|INCLUDE));
34       }
35     }
36   
37     public LayerList(String str) {
38       super(str);
39       members = new Vector();
40       members.add(all);
41       operator = new Vector();
42       operator.add(new Integer(PROVISIONAL|INCLUDE));
43     }
44   
45     LayerList() {}
46   
47     public Object clone() {
48       LayerList res = new LayerList();
49       res.copy(this);
50       return((Object)res);
51     }
52   
53     public void copy(FileDefaultable thatitem) {
54       super.copy(thatitem);
55       members = (Vector)((LayerList)thatitem).members.clone();
56       operator = (Vector)((LayerList)thatitem).operator.clone();
57     }
58   
59     public boolean isMember(Object target) {
60       Iterator listit = members.iterator();
61       boolean value = false;
62       for (Iterator opit = operator.iterator();opit.hasNext();) {
63         if (((Layer)listit.next()).isMember(target)) {
64           int op = ((Integer)opit.next()).intValue();
65           value = (op&INCLUDE)!=0;
66           if ((op&PROVISIONAL)==0) return(value);
67         }
68         else opit.next();
69       }
70   
71       return(value);
72     }
73   
74     public boolean inList(Layer list) {
75       if (!(list instanceof LayerList)) return(false);
76       if (list.equals(this)) return(true);
77   
78       for (Iterator it = ((LayerList)list).members.iterator();it.hasNext();)
79         if (inList((Layer)it.next())) return(true);
80   
81       return(false);
82     }
83   
84     public boolean check() {
85       for (int i=1;i<members.size();i++)
86         if (inList((Layer)members.elementAt(i))) {
87           ErrorLog.log("Layer "+this+" includes "+members.elementAt(i)+" which contains "+this+
88           	     "\ndeleted");
89           members.removeElementAt(i);
90           operator.removeElementAt(i);
91         }
92       
93       return(true);
94     }
95   
96     static Icon INCLUDEICON = null;
97     static Icon EXCLUDEICON = null;
98     static Icon PROVICON = null;
99     static Icon SUREICON = null;
100    static Icon ADDICON = null;
101    static Icon DELICON = null;
102    static Icon ADDSELICON = null;
103    static Icon COMPRESSICON = null;
104  
105    static String INCLUDECOM = "Include";
106    static String EXCLUDECOM = "Exclude";
107    static String PROVCOM = "Provitional";
108    static String SURECOM = "Definitive";
109    static String ADDCOM = "Add";
110    static String DELCOM = "Delete";
111    static String ADDSELCOM = "Add Selection";
112    static String COMPRESSCOM = "Compress";
113  
114    transient LayerList edit;
115    transient JList memberlist;
116    transient JList candlist;
117    transient HashSet datalisteners;
118  
119    transient JPanel box;
120  
121    static int scrollmargin = 4;
122  
123    public boolean edit(JFrame owner) {
124  
125      if (INCLUDEICON==null) {
126        INCLUDEICON = new ImageIcon(getClass().getResource("icons/include.gif"));
127        EXCLUDEICON = new ImageIcon(getClass().getResource("icons/exclude.gif"));
128        PROVICON = new ImageIcon(getClass().getResource("icons/prov.gif"));
129        SUREICON = new ImageIcon(getClass().getResource("icons/sure.gif"));
130        ADDICON = new ImageIcon(getClass().getResource("icons/layeradd.gif"));
131        DELICON = new ImageIcon(getClass().getResource("icons/layerdel.gif"));
132        ADDSELICON = new ImageIcon(getClass().getResource("icons/layeraddsel.gif"));
133        COMPRESSICON = new ImageIcon(getClass().getResource("icons/layercompress.gif"));
134      }
135  
136      box = new JPanel();
137      box.setLayout(new BoxLayout(box,BoxLayout.X_AXIS));
138  
139      javax.swing.Box box = new javax.swing.Box(BoxLayout.X_AXIS);
140      javax.swing.Box butbox = new javax.swing.Box(BoxLayout.Y_AXIS);
141  
142      edit = (LayerList)this.clone();
143  
144      edit.getPad();
145  
146      memberlist = new JList(edit);
147      memberlist.setCellRenderer(edit);
148  
149      box.add(new JScrollPane(memberlist){
150          public Dimension getPreferredSize() {
151            Dimension dim = memberlist.getPreferredSize();
152            return(new Dimension(dim.width+scrollmargin,dim.height+scrollmargin));
153          }
154        });
155  
156      JButton but = new JButton(INCLUDEICON);
157      but.setActionCommand(INCLUDECOM);
158      but.addActionListener(this);
159      butbox.add(but);
160  
161      but = new JButton(EXCLUDEICON);
162      but.setActionCommand(EXCLUDECOM);
163      but.addActionListener(this);
164      butbox.add(but);
165  
166      but = new JButton(PROVICON);
167      but.setActionCommand(PROVCOM);
168      but.addActionListener(this);
169      butbox.add(but);
170  
171      but = new JButton(SUREICON);
172      but.setActionCommand(SURECOM);
173      but.addActionListener(this);
174      butbox.add(but);
175  
176      but = new JButton(ADDICON);
177      but.setActionCommand(ADDCOM);
178      but.addActionListener(this);
179      butbox.add(but);
180  
181      but = new JButton(DELICON);
182      but.setActionCommand(DELCOM);
183      but.addActionListener(this);
184      butbox.add(but);
185  
186      but = new JButton(ADDSELICON);
187      but.setActionCommand(ADDSELCOM);
188      but.addActionListener(this);
189      butbox.add(but);
190  
191      but = new JButton(COMPRESSICON);
192      but.setActionCommand(COMPRESSCOM);
193      but.addActionListener(this);
194      butbox.add(but);
195  
196      box.add(butbox);
197  
198      candlist = new JList(FileDefaultable.getAll(Layer.class,((CartoFrame)owner).carto.defaults));
199      box.add(new JScrollPane(candlist){
200          public Dimension getPreferredSize() {
201            Dimension dim = candlist.getPreferredSize();
202            return(new Dimension(dim.width+scrollmargin,dim.height+scrollmargin));
203          }
204        });
205  
206      boolean res = false;
207  
208      if (JOptionPane.showConfirmDialog(owner,box,"Edit Layer"+name,JOptionPane.OK_CANCEL_OPTION) ==
209          JOptionPane.OK_OPTION) {
210        copy(edit);
211        res = true;
212      }
213  
214      edit = null;
215      memberlist = null;
216      candlist = null;
217      box=null;
218  
219      return(res);  
220    }
221  
222    public void addMember(Layer newlayer,int index) {
223        members.add(index+1,newlayer);
224        operator.add(index+1,new Integer(INCLUDE|PROVISIONAL));
225        if (datalisteners!=null) {
226          ListDataEvent ev = new ListDataEvent(this,ListDataEvent.INTERVAL_ADDED,index+1,index+1);
227          for (Iterator it = datalisteners.iterator();it.hasNext();)
228            ((ListDataListener)it.next()).intervalAdded(ev);
229        }
230        getPad();
231    }
232  
233    public void delMember(int index) {
234      operator.removeElementAt(index);
235      members.removeElementAt(index);
236      if (datalisteners!=null) {
237        ListDataEvent ev = new ListDataEvent(this,ListDataEvent.INTERVAL_REMOVED,index,index);
238        for (Iterator it = datalisteners.iterator();it.hasNext();)
239          ((ListDataListener)it.next()).intervalRemoved(ev);
240      }
241      getPad();
242    }
243  
244    public void compress() {
245      for (int i=0; i<members.size();i++) {
246        Layer first = (Layer)members.elementAt(i);
247          for (int j=i+1; j<members.size();j++) {
248            Layer second = (Layer)members.elementAt(j);
249            if (first instanceof LayerSet && second instanceof LayerSet) {
250              if ((((Integer)operator.elementAt(i)).intValue()&PROVISIONAL) == 0)
251                ((LayerSet)second).members.removeAll(((LayerSet)first).members);
252              else
253                ((LayerSet)first).members.removeAll(((LayerSet)second).members);
254              if (((LayerSet)first).members.isEmpty()) {
255                delMember(i);
256                i--;
257                break;
258              }
259              if (((LayerSet)second).members.isEmpty()) {
260                delMember(j);
261                j--;
262              }
263            }
264          }
265      }
266    }  
267  
268    public void actionPerformed(ActionEvent e) {
269  
270      int index = memberlist.getSelectedIndex();
271      if (index==-1) index = edit.getSize()-1;
272  
273      if (e.getActionCommand()==INCLUDECOM){
274        edit.operator.setElementAt(
275          new Integer(INCLUDE|(((Integer)edit.operator.elementAt(index)).intValue())),index);
276      }
277  
278      else if (e.getActionCommand()==EXCLUDECOM){
279        edit.operator.setElementAt(
280          new Integer((~INCLUDE)&(((Integer)edit.operator.elementAt(index)).intValue())),index);
281      }
282  
283      else if (e.getActionCommand()==PROVCOM){
284        edit.operator.setElementAt(
285          new Integer(PROVISIONAL|(((Integer)edit.operator.elementAt(index)).intValue())),index);
286      }
287      
288      else if (e.getActionCommand()==SURECOM){
289        edit.operator.setElementAt(
290          new Integer((~PROVISIONAL)&(((Integer)edit.operator.elementAt(index)).intValue())),index);
291      }
292      
293      else if(e.getActionCommand()==ADDCOM){
294        Layer newlayer = (Layer)candlist.getSelectedValue();
295        if (newlayer==null) {
296          ErrorLog.log("You need to select an item to add first.");
297          return;
298        }
299        if (inList(newlayer)) {
300          ErrorLog.log("The item "+newlayer+" which you are trying to add to "+this+
301          	     " cannot be added because "+
302          	     (newlayer.equals(this)?"they are the same":newlayer+" is a list containing "+this));
303          return;
304        }
305        edit.addMember(newlayer,index);
306        return;
307      }
308  
309      else if (e.getActionCommand()==DELCOM){
310        if (index==0) {
311          ErrorLog.log("The first item sets the default\nYou cannot delete it.");
312          return;
313        }
314        edit.delMember(index);
315        return;
316      }
317  
318      else if (e.getActionCommand()==ADDSELCOM){
319        Set sel = null;
320  
321        Editor last = CartoFrame.topframe.lastselected;
322        if (last!=null &&last instanceof CompEditor)
323          sel = ((CompEditor)last).pane.sel.selection;
324  
325        if (sel==null || sel.isEmpty()) ErrorLog.log("No selection,\nSelect some symbols to add to layer");
326  
327        else edit.addMember(new LayerSet(sel),index);
328      }
329  
330      else if (e.getActionCommand()==COMPRESSCOM){
331        edit.compress();      
332      }
333  
334      box.validate();
335      memberlist.repaint();
336    }
337  
338    public void addListDataListener(ListDataListener list) {
339      if (datalisteners==null) datalisteners = new HashSet();
340      datalisteners.add(list);
341    }
342  
343    public int getSize() {
344      return(members.size());
345    }
346  
347    public Object getElementAt(int index) {
348      return(new Integer(index));
349    }
350  
351    public void removeListDataListener(ListDataListener list) {
352      if (datalisteners!=null) datalisteners.remove(list);
353    }
354  
355    transient JPanel listbox;
356    transient JLabel inclab;
357    transient JLabel deflab;
358    transient JLabel listlab;
359  
360    transient String pad;
361  
362    void getPad() {
363      int maxwidth = 0;
364      for (Iterator it=members.iterator();it.hasNext();) {
365        int width = ((Layer)it.next()).getName().length();
366        if (maxwidth<width) maxwidth = width;
367      }
368      pad = "";
369      for (int i=all.getName().length();i<1.5*maxwidth;i++)
370        pad = pad+" ";
371  //    pad = pad+".";
372  //    System.out.println("Pad = '"+pad+"'");
373    }
374  
375    public Component getListCellRendererComponent(JList list,
376          					Object value,
377          					int index,
378          					boolean selected,
379          					boolean hasfocus) {
380      if (listbox==null) {
381        listbox = new JPanel();//(BoxLayout.X_AXIS);
382        listbox.setLayout(new BoxLayout(listbox,BoxLayout.X_AXIS));
383        listbox.setOpaque(true);
384  
385        javax.swing.border.Border bord = new javax.swing.border.EmptyBorder(2,2,2,2);
386  
387        inclab = new JLabel();
388        inclab.setBorder(bord);
389        listbox.add(inclab);
390  
391        deflab = new JLabel();
392        deflab.setBorder(bord);
393        listbox.add(deflab);
394  
395        listlab = new JLabel("");
396        listlab.setBorder(bord);
397        listbox.add(listlab);
398      }
399  
400      int op = ((Integer)operator.elementAt(index)).intValue();
401  
402      inclab.setIcon((op&INCLUDE)==0?EXCLUDEICON:INCLUDEICON);
403      deflab.setIcon((op&PROVISIONAL)==0?SUREICON:PROVICON);
404  
405      Layer layer = (Layer)members.elementAt(index);
406      String lab = layer.getName();
407  //    if (lab.length()>maxwidth) maxwidth = lab.length();
408  //    if (layer==all) {
409  //      for (int i=lab.length();i<maxwidth;i++) lab = lab+" ";
410  //    }
411      listlab.setText(lab+(layer.equals(all)?pad:""));
412  
413      listbox.setForeground(selected?list.getSelectionForeground():list.getForeground());
414      listbox.setBackground(selected?list.getSelectionBackground():list.getBackground());
415  
416      return(listbox);
417    }
418          				
419  }
420  
421