Subversion Repositories wimsdev

Rev

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
}