Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7246 | schaersvoo | 1 | /* |
2 | Sketch Elements: Chemistry molecular diagram drawing tool. |
||
3 | |||
4 | (c) 2008 Dr. Alex M. Clark |
||
5 | |||
6 | Released as GNUware, under the Gnu Public License (GPL) |
||
7 | |||
8 | See www.gnu.org for details. |
||
9 | */ |
||
10 | |||
11 | package WIMSchem; |
||
12 | |||
13 | import java.io.*; |
||
14 | import java.awt.*; |
||
15 | import java.util.*; |
||
16 | import java.awt.image.*; |
||
17 | import java.awt.event.*; |
||
18 | import javax.swing.*; |
||
19 | |||
20 | /* |
||
21 | JLineup: a medium-weight layout-support component for Swing, which encapsulates some of the fundamental aspects of making |
||
22 | everything in a panel line up nicely. Somewhat of a subset of the functionality offered by GroupLayout (v1.6 and later). |
||
23 | |||
24 | Two modes: |
||
25 | VERTICAL - the child components are lined up from top to bottom; titles+padding line up |
||
26 | HORIZONTAL - the child components are lined up from left to right; titles only line up on the baseline |
||
27 | |||
28 | Both modes have optional titles, though the vertical invocation goes further than just the basic convenience of not |
||
29 | needing to do the widget creation. Both have stretch weights for X & Y, though the meanings are inverted. For vertical |
||
30 | lineups, the Y weights affect the overall size of the widget, while the X weights just affect how existing space is |
||
31 | filled. The converse is true for horizontal lineups. |
||
32 | */ |
||
33 | |||
34 | |||
35 | public class JLineup extends JPanel |
||
36 | { |
||
37 | class Unit |
||
38 | { |
||
39 | Component c; |
||
40 | JLabel label; |
||
41 | int stretchX,stretchY; |
||
42 | } |
||
43 | private ArrayList<Unit> content=new ArrayList<Unit>(); |
||
44 | |||
45 | public static final int VERTICAL=1; |
||
46 | public static final int HORIZONTAL=2; |
||
47 | private int dir,padding; |
||
48 | |||
49 | // Constructor: |
||
50 | // dir: must be VERTICAL or HORIZONTAL |
||
51 | // padding: number of pixels between each component, and around the edges |
||
52 | |||
53 | public JLineup(int dir) |
||
54 | { |
||
55 | super(); |
||
56 | this.dir=dir; |
||
57 | this.padding=0; |
||
58 | } |
||
59 | public JLineup(int dir,int padding) |
||
60 | { |
||
61 | super(); |
||
62 | this.dir=dir; |
||
63 | this.padding=padding; |
||
64 | } |
||
65 | |||
66 | // for cleaning house |
||
67 | |||
68 | public void clear() |
||
69 | { |
||
70 | for (int n=0;n<content.size();n++) |
||
71 | { |
||
72 | Unit u=content.get(n); |
||
73 | super.remove(u.c); |
||
74 | if (u.label!=null) super.remove(u.label); |
||
75 | } |
||
76 | content.clear(); |
||
77 | } |
||
78 | public void remove(Component c) |
||
79 | { |
||
80 | for (int n=0;n<content.size();n++) |
||
81 | { |
||
82 | Unit u=content.get(n); |
||
83 | if (u.c==c) |
||
84 | { |
||
85 | super.remove(c); |
||
86 | if (u.label!=null) super.remove(u.label); |
||
87 | } |
||
88 | } |
||
89 | } |
||
90 | |||
91 | // convenience shortcuts |
||
92 | |||
93 | public Component add(Component c) {return add(c,null,0,0);} |
||
94 | public Component add(Component c,String title) {return add(c,title,0,0);} |
||
95 | |||
96 | public Component add(Component c,String title,int stretchX,int stretchY) |
||
97 | { |
||
98 | super.add(c); |
||
99 | |||
100 | Unit u=new Unit(); |
||
101 | u.c=c; |
||
102 | u.label=null; |
||
103 | u.stretchX=stretchX; |
||
104 | u.stretchY=stretchY; |
||
105 | |||
106 | if (title!=null) |
||
107 | { |
||
108 | u.label=new JLabel(title); |
||
109 | super.add(u.label); |
||
110 | } |
||
111 | |||
112 | content.add(u); |
||
113 | invalidate(); |
||
114 | |||
115 | return c; |
||
116 | } |
||
117 | |||
118 | public Dimension getMinimumSize() |
||
119 | { |
||
120 | Dimension sz=new Dimension(0,0); |
||
121 | |||
122 | if (dir==VERTICAL) |
||
123 | { |
||
124 | int mw=0; |
||
125 | for (int n=0;n<content.size();n++) |
||
126 | { |
||
127 | Unit u=content.get(n); |
||
128 | mw=Math.max(mw,u.c.getPreferredSize().width); |
||
129 | sz.height+=Math.max(u.label==null ? 0 : u.label.getPreferredSize().height,u.c.getPreferredSize().height); |
||
130 | } |
||
131 | sz.width=calculateTitleWidth()+mw+2*padding; |
||
132 | sz.height+=padding*(content.size()+1); |
||
133 | } |
||
134 | else // HORIZONTAL |
||
135 | { |
||
136 | int mh=0; |
||
137 | for (int n=0;n<content.size();n++) |
||
138 | { |
||
139 | Unit u=content.get(n); |
||
140 | if (u.label!=null) |
||
141 | { |
||
142 | sz.width+=u.label.getPreferredSize().width+padding; |
||
143 | sz.height=Math.max(sz.height,u.label.getPreferredSize().height); |
||
144 | } |
||
145 | sz.width+=u.c.getPreferredSize().width; |
||
146 | sz.height=Math.max(sz.height,u.c.getPreferredSize().height); |
||
147 | } |
||
148 | sz.width+=padding*(content.size()+1); |
||
149 | sz.height+=padding*2; |
||
150 | } |
||
151 | |||
152 | return sz; |
||
153 | } |
||
154 | public Dimension getPreferredSize() {return getMinimumSize();} |
||
155 | public Dimension getMaximumSize() |
||
156 | { |
||
157 | Dimension sz=new Dimension(Integer.MAX_VALUE,Integer.MAX_VALUE); |
||
158 | boolean anyX=false,anyY=false; |
||
159 | for (int n=0,y=0;n<content.size();n++) |
||
160 | { |
||
161 | Unit u=content.get(n); |
||
162 | anyX=anyX || u.stretchX>0; |
||
163 | anyY=anyY || u.stretchY>0; |
||
164 | } |
||
165 | if (!anyX || !anyY) |
||
166 | { |
||
167 | Dimension psz=getPreferredSize(); |
||
168 | if (!anyX) sz.width=psz.width; |
||
169 | if (!anyY) sz.height=psz.height; |
||
170 | } |
||
171 | |||
172 | return sz; |
||
173 | } |
||
174 | |||
175 | public void doLayout() |
||
176 | { |
||
177 | if (dir==VERTICAL) layoutVertical(); |
||
178 | else layoutHorizontal(); |
||
179 | } |
||
180 | |||
181 | private void layoutVertical() |
||
182 | { |
||
183 | Dimension prefsz=getPreferredSize(),cursz=getSize(); |
||
184 | int totalStretch=0,stretchPoints=cursz.height-prefsz.height; |
||
185 | if (stretchPoints>0) for (int n=0;n<content.size();n++) totalStretch+=content.get(n).stretchY; |
||
186 | |||
187 | int tw=calculateTitleWidth(),residual=stretchPoints,cw=cursz.width-tw-2*padding; |
||
188 | for (int n=0,y=padding;n<content.size();n++) |
||
189 | { |
||
190 | Unit u=content.get(n); |
||
191 | int h=Math.max(u.label==null ? 0 : u.label.getPreferredSize().height,u.c.getPreferredSize().height); |
||
192 | if (u.stretchY>0 && stretchPoints>0) |
||
193 | { |
||
194 | int extra=(int)Math.min(Math.ceil(stretchPoints*u.stretchY/(double)totalStretch),residual); |
||
195 | h+=extra; |
||
196 | residual-=extra; |
||
197 | } |
||
198 | if (u.label!=null) |
||
199 | { |
||
200 | int ly=y; |
||
201 | if (u.c instanceof JComponent) |
||
202 | { |
||
203 | int delta=((JComponent)u.c).getBaseline(tw,h)-u.label.getBaseline(cw,u.label.getPreferredSize().height); |
||
204 | ly+=delta>0 ? delta : 0; |
||
205 | } |
||
206 | u.label.setBounds(padding,ly,tw,u.label.getPreferredSize().height); |
||
207 | } |
||
208 | u.c.setBounds(padding+tw,y,u.stretchX==0 ? u.c.getPreferredSize().width : cw,h); |
||
209 | |||
210 | y+=h+padding; |
||
211 | } |
||
212 | } |
||
213 | |||
214 | private void layoutHorizontal() |
||
215 | { |
||
216 | Dimension prefsz=getPreferredSize(),cursz=getSize(); |
||
217 | int totalStretch=0,stretchPoints=cursz.height-prefsz.height-2*padding; |
||
218 | if (stretchPoints>0) for (int n=0;n<content.size();n++) totalStretch+=content.get(n).stretchX; |
||
219 | |||
220 | int residual=stretchPoints; |
||
221 | for (int n=0,x=padding;n<content.size();n++) |
||
222 | { |
||
223 | Unit u=content.get(n); |
||
224 | int w=u.c.getPreferredSize().width,h=cursz.height-2*padding; |
||
225 | int ch=u.stretchY==0 ? u.c.getPreferredSize().height : h; |
||
226 | if (u.stretchX>0 && stretchPoints>0) |
||
227 | { |
||
228 | int extra=(int)Math.min(Math.ceil(stretchPoints*u.stretchX/(double)totalStretch),residual); |
||
229 | w+=extra; |
||
230 | residual-=extra; |
||
231 | } |
||
232 | if (u.label!=null) |
||
233 | { |
||
234 | int ly=padding; |
||
235 | Dimension lsz=u.label.getPreferredSize(); |
||
236 | if (u.c instanceof JComponent) |
||
237 | { |
||
238 | // (NOTE: this matches the baseline for pairs; probably should do for all components...) |
||
239 | int delta=((JComponent)u.c).getBaseline(w,ch)-u.label.getBaseline(lsz.width,lsz.height); |
||
240 | ly+=delta>0 ? delta : 0; |
||
241 | } |
||
242 | u.label.setBounds(x,ly,lsz.width,lsz.height); |
||
243 | x+=lsz.width+padding; |
||
244 | } |
||
245 | u.c.setBounds(x,padding,w,ch); |
||
246 | x+=w+padding; |
||
247 | } |
||
248 | } |
||
249 | |||
250 | private int calculateTitleWidth() |
||
251 | { |
||
252 | int w=0; |
||
253 | for (int n=0;n<content.size();n++) |
||
254 | { |
||
255 | Unit u=content.get(n); |
||
256 | if (u.label==null) continue; |
||
257 | w=Math.max(w,u.label.getPreferredSize().width); |
||
258 | } |
||
259 | if (w>0) w+=padding; |
||
260 | return w; |
||
261 | } |
||
262 | } |