1    /*
2    Copyright 2001 by Ralph Hartley
3    This software is licenced under the terms of the
4    Gnu Public Licence
5    */
6    
7    import java.awt.geom.*;
8    import java.awt.*;
9    import javax.swing.*;
10   import java.util.*;
11   import java.awt.event.*;
12   
13   public class Section extends Symbol implements DragableSymbol,ActionListener{
14   
15     private static final long serialVersionUID = Version.getSUID();
16   
17     public static String ENDFLIP = "Swap ends";
18     public static String DIRFLIP = "Switch direction";
19   
20     public PointSym[] anchors = new PointSym[2]; 
21     public Symbol contents;
22   
23     public int direction = 1;
24   
25     public double end1 = 0.1;
26     public double end2 = 0.1;
27   
28     public Size tick = (Size)FileDefaultable.lookup(Size.class,Size.SECTIONTICK);
29     public Size margin = (Size)FileDefaultable.lookup(Size.class,Size.SECTIONMARGIN);
30     public Size line1size = (Size)FileDefaultable.lookup(Size.class,Size.SECTIONLINE1);
31     public LineType line1style = LineType.lookup("Generic");
32     public Size line2size = (Size)FileDefaultable.lookup(Size.class,Size.SECTIONLINE2);
33     public LineType line2style = LineType.lookup("Invisible");
34   
35     transient int selmode = -1;
36   
37     public Section(){}
38   
39     public Section(Point2D where,View view,Object arg) {
40       super(where,view,arg);
41       if (arg instanceof Symbol) contents = (Symbol)arg;
42       anchors[0] = new PointSym(where,view,null);
43       anchors[1] = new PointSym(where,view,null);
44       selmode = 1;
45     }
46   
47     public Symbol importSym(Carto dest,Carto source) {
48       contents = contents.importSym(dest,source);
49       return(this);
50     }
51   
52     public Rectangle2D getBounds(AffineTransform trans) {
53   //    Rectangle2D res = contents.getBounds(trans);
54       Rectangle2D res = anchors[0].getBounds(trans);
55       res.add(anchors[1].getBounds(trans));
56       return(res);
57     }
58   
59     public void showSelected(View view) {
60       if (selmode>=0) anchors[selmode].showSelected(view);
61       anchors[0].paint(view);
62       anchors[1].paint(view);
63     }
64   
65     public void paint(View view) {
66       if (!view.visible.isMember(this)) return;
67   
68       Point2D pos1 = anchors[0].position.getTranslation();
69       Point2D pos2 = anchors[1].position.getTranslation();
70       view.trans.transform(pos1,pos1);
71       view.trans.transform(pos2,pos2);
72       int boxfact = (pos2.getX()>pos1.getX()?1:-1);
73   
74       double angle = view.angle;
75       view.push(anchors[1].position);
76       view.setRotation(2*angle/*-anchors[1].position.angle*/,0,0);
77       Rectangle2D box = contents.getBounds(new AffineTransform());
78       double marg = (margin==null?0:margin.getSize(view.mapscale));
79       view.trans.translate(-box.getX()+(boxfact-1)/2*box.getWidth()+marg/view.scale,-box.getY()+marg/view.scale);
80       contents.paint(view);
81       view.pop();
82   
83       if (line1style!=null && line1size!=null) {
84         Stroke stroke = line1style.getStroke(line1size.getSize(view.mapscale));
85   
86         if (stroke!=null) {
87           Point2D pos3 = new Point2D.Double(pos2.getX()+boxfact*(box.getWidth()*view.scale+marg*2),pos2.getY());
88   //        anchors[1].position.transform(pos3,pos3);
89   //        view.trans.transform(pos3,pos3);
90           GeneralPath mark = new GeneralPath();
91           double dx = pos2.getX() - pos1.getX();
92           double dy = pos2.getY() - pos1.getY();
93           double mag = direction*(tick!=null?(tick.getSize(view.mapscale)):5.0)/Math.sqrt(dx*dx+dy*dy);
94           mark.moveTo((float)(pos1.getX()+mag*dy),(float)(pos1.getY()-mag*dx));
95           mark.lineTo((float)pos1.getX(),(float)pos1.getY());
96           mark.lineTo((float)(pos1.getX()+dx*end1),(float)(pos1.getY()+dy*end1));
97           mark.moveTo((float)(pos1.getX()+dx*(1-end2)),(float)(pos1.getY()+dy*(1-end2)));
98           mark.lineTo((float)pos2.getX(),(float)pos2.getY());
99           mark.lineTo((float)pos3.getX(),(float)pos3.getY());
100  
101          Stroke st = view.draw.getStroke();
102          view.draw.setStroke(stroke);
103  //              shape = view.trans.createTransformedShape((GeneralPath)subpath.elementAt(i));
104          view.draw.draw(mark);
105          view.draw.setStroke(st);
106        }
107      }
108  //    view.draw.drawLine((int)(pos1.getX()+dx*2*end1),(int)(pos1.getY()+dy*2*end1),
109  //        	       (int)(pos1.getX()+dx*(1-2*end2)),(int)(pos1.getY()+dy*(1-2*end2)));
110    }
111  
112    public boolean selectProbe(Point2D pos,View view){
113  //    if (selmode==2) {
114  //      selmode=1;
115  //      System.out.println("Section startsel");
116  //      return(true);
117  //    }
118      for (int i=0;i<2;i++)
119        if (anchors[i].selectProbe(pos,view)) {
120          selmode = i;
121          return(true);
122        }
123      selmode = -1;
124      return(false);
125    }
126  
127    public void startDrag(int command,Point2D where,View view){
128      if (selmode>=0) {
129        anchors[selmode].startDrag(command,where,view);
130      }
131    }
132  
133    public void drag(int command,Point2D where,View view){
134      if (selmode>=0) {
135        anchors[selmode].drag(command,where,view);
136      }
137    }
138  
139    public int getLevel() {return(super.getLevel()+1);}
140  
141    transient JTextField end1field,end2field;
142    transient JComboBox tickfield=null,marginfield,size1field,size2field,style1field,style2field;
143  
144    public void getPropertyEdit(Object[] edits,int slot,Set sub,Symbol parent) {
145      JPanel res = new JPanel();
146      edits[slot] = res;
147      ((Component)edits[slot]).setName("Section");
148      res.setLayout(new BoxLayout(res,BoxLayout.Y_AXIS));
149  
150      res.add(anchors[1].pointPropertyEdit());
151  
152      JPanel row = new JPanel();
153      row.setLayout(new BoxLayout(row,BoxLayout.X_AXIS));
154  
155      JButton but = new JButton(ENDFLIP);
156      but.addActionListener(this);
157      row.add(but);
158      but = new JButton(DIRFLIP);
159      but.addActionListener(this);
160      row.add(but);
161      res.add(row);
162      
163      row = new JPanel();
164      row.setLayout(new BoxLayout(row,BoxLayout.X_AXIS));
165      end1field = PrefEditor.addDouble(row,end1,"near end %",5);
166      end2field = PrefEditor.addDouble(row,end2,"far end %",5);
167  
168      res.add(row);
169  
170      row = new JPanel();
171      row.setLayout(new BoxLayout(row,BoxLayout.X_AXIS));
172  
173      row.add(new JLabel("Tick "));
174      tickfield = new JComboBox(Size.getAll(Size.class));
175      tickfield.setSelectedItem(tick);
176      row.add(tickfield);
177  
178      row.add(new JLabel("Margin "));
179      marginfield = new JComboBox(Size.getAll(Size.class));
180      marginfield.setSelectedItem(margin);
181      row.add(marginfield);
182  
183      res.add(row);
184  
185      row = new JPanel();
186      row.setLayout(new BoxLayout(row,BoxLayout.X_AXIS));
187      row.add(new JLabel("Line 1 size "));
188      size1field = new JComboBox(Size.getAll(Size.class));
189      size1field.setSelectedItem(line1size);
190      row.add(size1field);
191      res.add(row);
192  /*
193      row = new JPanel();
194      row.add(new JLabel("Line 2 size "));
195      size2field = new JComboBox(Size.getAll(Size.class));
196      size2field.setSelectedItem(line2size);
197      row.add(size2field);
198      res.add(row);
199  */
200      super.getPropertyEdit(edits,slot-1,sub,parent);
201    }
202  
203    public void acceptPropertyEdit() {
204      if (tickfield!=null) {
205        end1 = PrefEditor.readDouble(end1field);
206        end2 = PrefEditor.readDouble(end2field);
207        tick = (Size)tickfield.getSelectedItem();
208        margin = (Size)marginfield.getSelectedItem();
209        line1size = (Size)size1field.getSelectedItem();
210  
211        anchors[1].acceptPropertyEdit();
212        clear();
213      }
214      super.acceptPropertyEdit();
215    }
216  
217    public void actionPerformed(ActionEvent e) {
218      if (e.getSource() instanceof AbstractButton) {
219        String command = ((AbstractButton)e.getSource()).getActionCommand();
220        if (command==ENDFLIP) {
221          PointSym tmp = anchors[0];
222          anchors[0] = anchors[1];
223          anchors[1] = tmp;
224        }
225        if ((command==DIRFLIP) || (command==ENDFLIP)){
226          direction *= -1;
227        }      
228      }
229    }
230    public void abandonPropertyEdit() {
231      clear();
232      anchors[1].abandonPropertyEdit();
233      super.abandonPropertyEdit();
234    }
235  
236    void clear() {
237      end1field=null;
238      end2field=null;
239      tickfield=null;
240      marginfield=null;
241      style1field=null;
242      style2field=null;
243      size1field=null;
244      size2field=null;
245    }
246  }
247  
248  
249