~ubuntu-branches/debian/stretch/insubstantial/stretch

« back to all changes in this revision

Viewing changes to flamingo/src/main/java/org/pushingpixels/flamingo/internal/ui/common/BasicCommandButtonPanelUI.java

  • Committer: Package Import Robot
  • Author(s): Felix Natter
  • Date: 2016-01-18 20:58:45 UTC
  • Revision ID: package-import@ubuntu.com-20160118205845-crbmrkda61qsi5qa
Tags: upstream-7.3+dfsg2
ImportĀ upstreamĀ versionĀ 7.3+dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without 
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 * 
 
7
 *  o Redistributions of source code must retain the above copyright notice, 
 
8
 *    this list of conditions and the following disclaimer. 
 
9
 *     
 
10
 *  o Redistributions in binary form must reproduce the above copyright notice, 
 
11
 *    this list of conditions and the following disclaimer in the documentation 
 
12
 *    and/or other materials provided with the distribution. 
 
13
 *     
 
14
 *  o Neither the name of Flamingo Kirill Grouchnikov nor the names of 
 
15
 *    its contributors may be used to endorse or promote products derived 
 
16
 *    from this software without specific prior written permission. 
 
17
 *     
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 
20
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 
21
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 
22
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 
23
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 
24
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 
25
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 
26
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 
27
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 
28
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
29
 */
 
30
package org.pushingpixels.flamingo.internal.ui.common;
 
31
 
 
32
import java.awt.*;
 
33
import java.beans.PropertyChangeEvent;
 
34
import java.beans.PropertyChangeListener;
 
35
 
 
36
import javax.swing.*;
 
37
import javax.swing.event.ChangeEvent;
 
38
import javax.swing.event.ChangeListener;
 
39
import javax.swing.plaf.ComponentUI;
 
40
import javax.swing.plaf.UIResource;
 
41
 
 
42
import org.pushingpixels.flamingo.api.common.AbstractCommandButton;
 
43
import org.pushingpixels.flamingo.api.common.JCommandButtonPanel;
 
44
import org.pushingpixels.flamingo.api.common.JCommandButtonPanel.LayoutKind;
 
45
import org.pushingpixels.flamingo.internal.utils.FlamingoUtilities;
 
46
 
 
47
/**
 
48
 * Basic UI for command button panel {@link JCommandButtonPanel}.
 
49
 * 
 
50
 * @author Kirill Grouchnikov
 
51
 */
 
52
public class BasicCommandButtonPanelUI extends CommandButtonPanelUI {
 
53
        /**
 
54
         * The associated command button panel.
 
55
         */
 
56
        protected JCommandButtonPanel buttonPanel;
 
57
 
 
58
        /**
 
59
         * Labels of the button panel groups.
 
60
         */
 
61
        protected JLabel[] groupLabels;
 
62
 
 
63
        /**
 
64
         * Bounds of button panel groups.
 
65
         */
 
66
        protected Rectangle[] groupRects;
 
67
 
 
68
        /**
 
69
         * Property change listener on {@link #buttonPanel}.
 
70
         */
 
71
        protected PropertyChangeListener propertyChangeListener;
 
72
 
 
73
        /**
 
74
         * Change listener on {@link #buttonPanel}.
 
75
         */
 
76
        protected ChangeListener changeListener;
 
77
 
 
78
        /**
 
79
         * Default insets of button panel groups.
 
80
         */
 
81
        protected static final Insets GROUP_INSETS = new Insets(4, 4, 4, 4);
 
82
 
 
83
        /*
 
84
         * (non-Javadoc)
 
85
         * 
 
86
         * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
 
87
         */
 
88
        public static ComponentUI createUI(JComponent c) {
 
89
                return new BasicCommandButtonPanelUI();
 
90
        }
 
91
 
 
92
        /*
 
93
         * (non-Javadoc)
 
94
         * 
 
95
         * @see javax.swing.plaf.ComponentUI#installUI(javax.swing.JComponent)
 
96
         */
 
97
        @Override
 
98
        public void installUI(JComponent c) {
 
99
                this.buttonPanel = (JCommandButtonPanel) c;
 
100
 
 
101
                installDefaults();
 
102
                installComponents();
 
103
                installListeners();
 
104
        }
 
105
 
 
106
        /**
 
107
         * Installs defaults on the associated button panel.
 
108
         */
 
109
        protected void installDefaults() {
 
110
                this.buttonPanel.setLayout(this.createLayoutManager());
 
111
                Font currFont = this.buttonPanel.getFont();
 
112
                if ((currFont == null) || (currFont instanceof UIResource)) {
 
113
                        Font titleFont = FlamingoUtilities.getFont(null,
 
114
                                        "CommandButtonPanel.font", "Button.font", "Panel.font");
 
115
                        this.buttonPanel.setFont(titleFont);
 
116
                }
 
117
        }
 
118
 
 
119
        /**
 
120
         * Installs sub-components on the associated button panel.
 
121
         */
 
122
        protected void installComponents() {
 
123
                this.recomputeGroupHeaders();
 
124
        }
 
125
 
 
126
        /**
 
127
         * Installs listeners on the associated button panel.
 
128
         */
 
129
        protected void installListeners() {
 
130
                this.propertyChangeListener = new PropertyChangeListener() {
 
131
                        @Override
 
132
            public void propertyChange(PropertyChangeEvent evt) {
 
133
                                if ("maxButtonColumns".equals(evt.getPropertyName())
 
134
                                                || "maxButtonRows".equals(evt.getPropertyName())
 
135
                                                || "toShowGroupLabels".equals(evt.getPropertyName())) {
 
136
                                        SwingUtilities.invokeLater(new Runnable() {
 
137
                                                @Override
 
138
                        public void run() {
 
139
                                                        if (buttonPanel != null) {
 
140
                                                                recomputeGroupHeaders();
 
141
                                                                buttonPanel.revalidate();
 
142
                                                                buttonPanel.doLayout();
 
143
                                                        }
 
144
                                                }
 
145
                                        });
 
146
                                }
 
147
 
 
148
                                if ("layoutKind".equals(evt.getPropertyName())) {
 
149
                                        SwingUtilities.invokeLater(new Runnable() {
 
150
                                                @Override
 
151
                                                public void run() {
 
152
                                                        if (buttonPanel != null) {
 
153
                                                                buttonPanel.setLayout(createLayoutManager());
 
154
                                                                buttonPanel.revalidate();
 
155
                                                                buttonPanel.doLayout();
 
156
                                                        }
 
157
                                                }
 
158
                                        });
 
159
                                }
 
160
                        }
 
161
                };
 
162
                this.buttonPanel.addPropertyChangeListener(this.propertyChangeListener);
 
163
 
 
164
                this.changeListener = new ChangeListener() {
 
165
                        @Override
 
166
                        public void stateChanged(ChangeEvent e) {
 
167
                                recomputeGroupHeaders();
 
168
                                buttonPanel.revalidate();
 
169
                                buttonPanel.doLayout();
 
170
                        }
 
171
                };
 
172
                this.buttonPanel.addChangeListener(this.changeListener);
 
173
        }
 
174
 
 
175
        /*
 
176
         * (non-Javadoc)
 
177
         * 
 
178
         * @see javax.swing.plaf.ComponentUI#uninstallUI(javax.swing.JComponent)
 
179
         */
 
180
        @Override
 
181
        public void uninstallUI(JComponent c) {
 
182
                c.setLayout(null);
 
183
 
 
184
                uninstallListeners();
 
185
                uninstallComponents();
 
186
                uninstallDefaults();
 
187
                this.buttonPanel = null;
 
188
        }
 
189
 
 
190
        /**
 
191
         * Uninstalls defaults from the associated button panel.
 
192
         */
 
193
        protected void uninstallDefaults() {
 
194
        }
 
195
 
 
196
        /**
 
197
         * Uninstalls sub-components from the associated button panel.
 
198
         */
 
199
        protected void uninstallComponents() {
 
200
                if (this.groupLabels != null) {
 
201
                        for (JLabel groupLabel : this.groupLabels) {
 
202
                                this.buttonPanel.remove(groupLabel);
 
203
                        }
 
204
                        // for (JSeparator groupSeparator : this.groupSeparators) {
 
205
                        // this.buttonPanel.remove(groupSeparator);
 
206
                        // }
 
207
                }
 
208
        }
 
209
 
 
210
        /**
 
211
         * Uninstalls listeners from the associated button panel.
 
212
         */
 
213
        protected void uninstallListeners() {
 
214
                this.buttonPanel
 
215
                                .removePropertyChangeListener(this.propertyChangeListener);
 
216
                this.propertyChangeListener = null;
 
217
 
 
218
                this.buttonPanel.removeChangeListener(this.changeListener);
 
219
                this.changeListener = null;
 
220
        }
 
221
 
 
222
        /**
 
223
         * Returns the layout manager for the associated button panel.
 
224
         * 
 
225
         * @return The layout manager for the associated button panel.
 
226
         */
 
227
        protected LayoutManager createLayoutManager() {
 
228
                if (this.buttonPanel.getLayoutKind() == LayoutKind.ROW_FILL)
 
229
                        return new RowFillLayout();
 
230
                else
 
231
                        return new ColumnFillLayout();
 
232
        }
 
233
 
 
234
        /*
 
235
         * (non-Javadoc)
 
236
         * 
 
237
         * @see javax.swing.plaf.ComponentUI#paint(java.awt.Graphics,
 
238
         * javax.swing.JComponent)
 
239
         */
 
240
        @Override
 
241
        public void paint(Graphics g, JComponent c) {
 
242
                Color bg = this.buttonPanel.getBackground();
 
243
                g.setColor(bg);
 
244
                g.fillRect(0, 0, c.getWidth(), c.getHeight());
 
245
 
 
246
                for (int i = 0; i < this.buttonPanel.getGroupCount(); i++) {
 
247
                        Rectangle groupRect = this.groupRects[i];
 
248
                        this.paintGroupBackground(g, i, groupRect.x, groupRect.y,
 
249
                                        groupRect.width, groupRect.height);
 
250
 
 
251
                        if (this.groupLabels[i].isVisible()) {
 
252
                                Rectangle groupTitleBackground = this.groupLabels[i]
 
253
                                                .getBounds();
 
254
                                this.paintGroupTitleBackground(g, i, groupRect.x,
 
255
                                                groupTitleBackground.y - getGroupInsets().top,
 
256
                                                groupRect.width, groupTitleBackground.height
 
257
                                                                + getGroupInsets().top + getLayoutGap());
 
258
                        }
 
259
                }
 
260
        }
 
261
 
 
262
        /**
 
263
         * Paints the background of the specified button panel group.
 
264
         * 
 
265
         * @param g
 
266
         *            Graphics context.
 
267
         * @param groupIndex
 
268
         *            Group index.
 
269
         * @param x
 
270
         *            X coordinate of the button group bounds.
 
271
         * @param y
 
272
         *            Y coordinate of the button group bounds.
 
273
         * @param width
 
274
         *            Width of the button group bounds.
 
275
         * @param height
 
276
         *            Height of the button group bounds.
 
277
         */
 
278
        protected void paintGroupBackground(Graphics g, int groupIndex, int x,
 
279
                        int y, int width, int height) {
 
280
                Color c = this.buttonPanel.getBackground();
 
281
                if ((c == null) || (c instanceof UIResource)) {
 
282
                        c = UIManager.getColor("Panel.background");
 
283
                        if (c == null)
 
284
                                c = new Color(190, 190, 190);
 
285
                        if (groupIndex % 2 == 1) {
 
286
                                double coef = 0.95;
 
287
                                c = new Color((int) (c.getRed() * coef),
 
288
                                                (int) (c.getGreen() * coef), (int) (c.getBlue() * coef));
 
289
                        }
 
290
                }
 
291
                g.setColor(c);
 
292
                g.fillRect(x, y, width, height);
 
293
        }
 
294
 
 
295
        /**
 
296
         * Paints the background of the title of specified button panel group.
 
297
         * 
 
298
         * @param g
 
299
         *            Graphics context.
 
300
         * @param groupIndex
 
301
         *            Group index.
 
302
         * @param x
 
303
         *            X coordinate of the button group title bounds.
 
304
         * @param y
 
305
         *            Y coordinate of the button group title bounds.
 
306
         * @param width
 
307
         *            Width of the button group title bounds.
 
308
         * @param height
 
309
         *            Height of the button group title bounds.
 
310
         */
 
311
        protected void paintGroupTitleBackground(Graphics g, int groupIndex, int x,
 
312
                        int y, int width, int height) {
 
313
                FlamingoUtilities.renderSurface(g, this.buttonPanel, new Rectangle(x,
 
314
                                y, width, height), false, (groupIndex > 0), true);
 
315
        }
 
316
 
 
317
        /**
 
318
         * Returns the height of the group title strip.
 
319
         * 
 
320
         * @param groupIndex
 
321
         *            Group index.
 
322
         * @return The height of the title strip of the specified group.
 
323
         */
 
324
        protected int getGroupTitleHeight(int groupIndex) {
 
325
                return this.groupLabels[groupIndex].getPreferredSize().height;
 
326
        }
 
327
 
 
328
        /**
 
329
         * Returns the insets of button panel groups.
 
330
         * 
 
331
         * @return The insets of button panel groups.
 
332
         */
 
333
        protected Insets getGroupInsets() {
 
334
                return GROUP_INSETS;
 
335
        }
 
336
 
 
337
        /**
 
338
         * Row-fill layout for the button panel.
 
339
         * 
 
340
         * @author Kirill Grouchnikov
 
341
         */
 
342
        protected class RowFillLayout implements LayoutManager {
 
343
                /*
 
344
                 * (non-Javadoc)
 
345
                 * 
 
346
                 * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
 
347
                 * java.awt.Component)
 
348
                 */
 
349
                @Override
 
350
        public void addLayoutComponent(String name, Component comp) {
 
351
                }
 
352
 
 
353
                /*
 
354
                 * (non-Javadoc)
 
355
                 * 
 
356
                 * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
 
357
                 */
 
358
                @Override
 
359
        public void removeLayoutComponent(Component comp) {
 
360
                }
 
361
 
 
362
                /*
 
363
                 * (non-Javadoc)
 
364
                 * 
 
365
                 * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
 
366
                 */
 
367
                @Override
 
368
        public void layoutContainer(Container parent) {
 
369
                        Insets bInsets = parent.getInsets();
 
370
                        Insets groupInsets = getGroupInsets();
 
371
                        int left = bInsets.left;
 
372
                        int right = bInsets.right;
 
373
 
 
374
                        int y = bInsets.top;
 
375
 
 
376
                        JCommandButtonPanel panel = (JCommandButtonPanel) parent;
 
377
                        boolean ltr = panel.getComponentOrientation().isLeftToRight();
 
378
 
 
379
                        // compute max width of buttons
 
380
                        int maxButtonWidth = 0;
 
381
                        int maxButtonHeight = 0;
 
382
                        int groupCount = panel.getGroupCount();
 
383
                        for (int i = 0; i < groupCount; i++) {
 
384
                                for (AbstractCommandButton button : panel.getGroupButtons(i)) {
 
385
                                        maxButtonWidth = Math.max(maxButtonWidth, button
 
386
                                                        .getPreferredSize().width);
 
387
                                        maxButtonHeight = Math.max(maxButtonHeight, button
 
388
                                                        .getPreferredSize().height);
 
389
                                }
 
390
                        }
 
391
                        groupRects = new Rectangle[groupCount];
 
392
 
 
393
                        int gap = getLayoutGap();
 
394
                        int maxWidth = parent.getWidth() - bInsets.left - bInsets.right
 
395
                                        - groupInsets.left - groupInsets.right;
 
396
                        // for N buttons, there are N-1 gaps. Add the gap to the
 
397
                        // available width and divide by the max button width + gap.
 
398
                        int buttonsInRow = (maxButtonWidth == 0) ? 0 : (maxWidth + gap)
 
399
                                        / (maxButtonWidth + gap);
 
400
                        int maxButtonColumnsToUse = panel.getMaxButtonColumns();
 
401
                        if (maxButtonColumnsToUse > 0) {
 
402
                                buttonsInRow = Math.min(buttonsInRow, maxButtonColumnsToUse);
 
403
                        }
 
404
 
 
405
                        // System.out.println("Layout : " + buttonsInRow);
 
406
                        for (int i = 0; i < groupCount; i++) {
 
407
                                int topGroupY = y;
 
408
                                y += groupInsets.top;
 
409
 
 
410
                                JLabel groupLabel = groupLabels[i];
 
411
                                if (buttonPanel.isToShowGroupLabels()) {
 
412
                                        int labelWidth = groupLabel.getPreferredSize().width;
 
413
                                        int labelHeight = getGroupTitleHeight(i);
 
414
                                        if (groupLabel.getComponentOrientation().isLeftToRight()) {
 
415
                                                groupLabel.setBounds(left + groupInsets.left, y,
 
416
                                                                labelWidth, labelHeight);
 
417
                                        } else {
 
418
                                                groupLabel.setBounds(parent.getWidth() - right
 
419
                                                                - groupInsets.right - labelWidth, y,
 
420
                                                                labelWidth, labelHeight);
 
421
                                        }
 
422
                                        y += labelHeight + gap;
 
423
                                }
 
424
 
 
425
                                int buttonRows = (buttonsInRow == 0) ? 0 : (int) (Math
 
426
                                                .ceil((double) panel.getGroupButtons(i).size()
 
427
                                                                / buttonsInRow));
 
428
                                if (maxButtonColumnsToUse > 0) {
 
429
                                        buttonsInRow = Math
 
430
                                                        .min(buttonsInRow, maxButtonColumnsToUse);
 
431
                                }
 
432
 
 
433
                                // spread the buttons so that we don't have extra space
 
434
                                // on the right
 
435
                                int actualButtonWidth = (buttonRows > 1) ? (maxWidth - (buttonsInRow - 1)
 
436
                                                * gap)
 
437
                                                / buttonsInRow
 
438
                                                : maxButtonWidth;
 
439
                                if (maxButtonColumnsToUse == 1)
 
440
                                        actualButtonWidth = maxWidth;
 
441
 
 
442
                                if (ltr) {
 
443
                                        int currX = left + groupInsets.left;
 
444
                                        for (AbstractCommandButton button : panel
 
445
                                                        .getGroupButtons(i)) {
 
446
                                                int endX = currX + actualButtonWidth;
 
447
                                                if (endX > (parent.getWidth() - right - groupInsets.right)) {
 
448
                                                        currX = left + groupInsets.left;
 
449
                                                        y += maxButtonHeight;
 
450
                                                        y += gap;
 
451
                                                }
 
452
                                                button.setBounds(currX, y, actualButtonWidth,
 
453
                                                                maxButtonHeight);
 
454
                                                // System.out.println(button.getText() + ":"
 
455
                                                // + button.isVisible() + ":" + button.getBounds());
 
456
                                                currX += actualButtonWidth;
 
457
                                                currX += gap;
 
458
                                        }
 
459
                                } else {
 
460
                                        int currX = parent.getWidth() - right - groupInsets.right;
 
461
                                        for (AbstractCommandButton button : panel
 
462
                                                        .getGroupButtons(i)) {
 
463
                                                int startX = currX - actualButtonWidth;
 
464
                                                if (startX < (left + groupInsets.left)) {
 
465
                                                        currX = parent.getWidth() - right
 
466
                                                                        - groupInsets.right;
 
467
                                                        y += maxButtonHeight;
 
468
                                                        y += gap;
 
469
                                                }
 
470
                                                button.setBounds(currX - actualButtonWidth, y,
 
471
                                                                actualButtonWidth, maxButtonHeight);
 
472
                                                // System.out.println(button.getText() + ":"
 
473
                                                // + button.isVisible() + ":" + button.getBounds());
 
474
                                                currX -= actualButtonWidth;
 
475
                                                currX -= gap;
 
476
                                        }
 
477
                                }
 
478
 
 
479
                                y += maxButtonHeight + groupInsets.bottom;
 
480
                                int bottomGroupY = y;
 
481
                                groupRects[i] = new Rectangle(left, topGroupY, (parent
 
482
                                                .getWidth()
 
483
                                                - left - right), (bottomGroupY - topGroupY));
 
484
                        }
 
485
                }
 
486
 
 
487
                /*
 
488
                 * (non-Javadoc)
 
489
                 * 
 
490
                 * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
 
491
                 */
 
492
                @Override
 
493
        public Dimension minimumLayoutSize(Container parent) {
 
494
                        return new Dimension(20, 20);
 
495
                }
 
496
 
 
497
                /*
 
498
                 * (non-Javadoc)
 
499
                 * 
 
500
                 * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
 
501
                 */
 
502
                @Override
 
503
        public Dimension preferredLayoutSize(Container parent) {
 
504
                        JCommandButtonPanel panel = (JCommandButtonPanel) parent;
 
505
 
 
506
                        int maxButtonColumnsToUse = panel.getMaxButtonColumns();
 
507
 
 
508
                        Insets bInsets = parent.getInsets();
 
509
                        Insets groupInsets = getGroupInsets();
 
510
                        int insetsWidth = bInsets.left + groupInsets.left + bInsets.right
 
511
                                        + groupInsets.right;
 
512
 
 
513
                        // compute max width of buttons
 
514
                        int maxButtonWidth = 0;
 
515
                        int maxButtonHeight = 0;
 
516
                        int groupCount = panel.getGroupCount();
 
517
                        for (int i = 0; i < groupCount; i++) {
 
518
                                for (AbstractCommandButton button : panel.getGroupButtons(i)) {
 
519
                                        maxButtonWidth = Math.max(maxButtonWidth, button
 
520
                                                        .getPreferredSize().width);
 
521
                                        maxButtonHeight = Math.max(maxButtonHeight, button
 
522
                                                        .getPreferredSize().height);
 
523
                                }
 
524
                        }
 
525
 
 
526
                        // total height
 
527
                        int gap = getLayoutGap();
 
528
                        boolean usePanelWidth = (maxButtonColumnsToUse <= 0);
 
529
                        int availableWidth = panel.getWidth();
 
530
                        availableWidth -= insetsWidth;
 
531
 
 
532
                        if (usePanelWidth) {
 
533
                                // this hasn't been set. Compute using the available
 
534
                                // width
 
535
                                maxButtonColumnsToUse = (availableWidth + gap)
 
536
                                                / (maxButtonWidth + gap);
 
537
                        }
 
538
                        int height = bInsets.top + bInsets.bottom;
 
539
                        // System.out.print(height + "[" + maxButtonColumnsToUse + "]");
 
540
                        for (int i = 0; i < groupCount; i++) {
 
541
                                if (groupLabels[i].isVisible()) {
 
542
                                        height += (getGroupTitleHeight(i) + gap);
 
543
                                }
 
544
 
 
545
                                height += (groupInsets.top + groupInsets.bottom);
 
546
 
 
547
                                int buttonRows = (int) (Math.ceil((double) panel
 
548
                                                .getGroupButtons(i).size()
 
549
                                                / maxButtonColumnsToUse));
 
550
                                height += buttonRows * maxButtonHeight + (buttonRows - 1) * gap;
 
551
                                // System.out.print(" " + height);
 
552
                        }
 
553
                        int prefWidth = usePanelWidth ? availableWidth
 
554
                                        : maxButtonColumnsToUse * maxButtonWidth
 
555
                                                        + (maxButtonColumnsToUse - 1) * gap + bInsets.left
 
556
                                                        + bInsets.right + groupInsets.left
 
557
                                                        + groupInsets.right;
 
558
                        // System.out.println(" : " + height);
 
559
                        return new Dimension(Math.max(10, prefWidth), Math.max(10, height));
 
560
                }
 
561
        }
 
562
 
 
563
        /**
 
564
         * Column-fill layout for the button panel.
 
565
         * 
 
566
         * @author Kirill Grouchnikov
 
567
         */
 
568
        protected class ColumnFillLayout implements LayoutManager {
 
569
                /*
 
570
                 * (non-Javadoc)
 
571
                 * 
 
572
                 * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
 
573
                 * java.awt.Component)
 
574
                 */
 
575
                @Override
 
576
        public void addLayoutComponent(String name, Component comp) {
 
577
                }
 
578
 
 
579
                /*
 
580
                 * (non-Javadoc)
 
581
                 * 
 
582
                 * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
 
583
                 */
 
584
                @Override
 
585
        public void removeLayoutComponent(Component comp) {
 
586
                }
 
587
 
 
588
                /*
 
589
                 * (non-Javadoc)
 
590
                 * 
 
591
                 * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
 
592
                 */
 
593
                @Override
 
594
        public void layoutContainer(Container parent) {
 
595
                        Insets bInsets = parent.getInsets();
 
596
                        Insets groupInsets = getGroupInsets();
 
597
                        int top = bInsets.top;
 
598
                        int bottom = bInsets.bottom;
 
599
 
 
600
                        JCommandButtonPanel panel = (JCommandButtonPanel) parent;
 
601
                        boolean ltr = panel.getComponentOrientation().isLeftToRight();
 
602
 
 
603
                        // compute max width of buttons
 
604
                        int maxButtonWidth = 0;
 
605
                        int maxButtonHeight = 0;
 
606
                        int groupCount = panel.getGroupCount();
 
607
                        for (int i = 0; i < groupCount; i++) {
 
608
                                for (AbstractCommandButton button : panel.getGroupButtons(i)) {
 
609
                                        maxButtonWidth = Math.max(maxButtonWidth, button
 
610
                                                        .getPreferredSize().width);
 
611
                                        maxButtonHeight = Math.max(maxButtonHeight, button
 
612
                                                        .getPreferredSize().height);
 
613
                                }
 
614
                        }
 
615
                        groupRects = new Rectangle[groupCount];
 
616
 
 
617
                        int gap = getLayoutGap();
 
618
                        int maxHeight = parent.getHeight() - bInsets.top - bInsets.bottom
 
619
                                        - groupInsets.top - groupInsets.bottom;
 
620
                        // for N buttons, there are N-1 gaps. Add the gap to the
 
621
                        // available width and divide by the max button width + gap.
 
622
                        int buttonsInRow = (maxButtonHeight == 0) ? 0 : (maxHeight + gap)
 
623
                                        / (maxButtonHeight + gap);
 
624
 
 
625
                        if (ltr) {
 
626
                                int x = bInsets.left + groupInsets.left;
 
627
                                for (int i = 0; i < groupCount; i++) {
 
628
                                        int leftGroupX = x;
 
629
                                        x += groupInsets.left;
 
630
                                        int currY = top + groupInsets.top;
 
631
 
 
632
                                        int buttonColumns = (buttonsInRow == 0) ? 0 : (int) (Math
 
633
                                                        .ceil((double) panel.getGroupButtons(i).size()
 
634
                                                                        / buttonsInRow));
 
635
                                        // spread the buttons so that we don't have extra space
 
636
                                        // on the bottom
 
637
                                        int actualButtonHeight = (buttonColumns > 1) ? (maxHeight - (buttonsInRow - 1)
 
638
                                                        * gap)
 
639
                                                        / buttonsInRow
 
640
                                                        : maxButtonWidth;
 
641
 
 
642
                                        for (AbstractCommandButton button : panel
 
643
                                                        .getGroupButtons(i)) {
 
644
                                                int endY = currY + actualButtonHeight;
 
645
                                                if (endY > (parent.getHeight() - bottom - groupInsets.bottom)) {
 
646
                                                        currY = top + groupInsets.top;
 
647
                                                        x += maxButtonWidth;
 
648
                                                        x += gap;
 
649
                                                }
 
650
                                                button.setBounds(x, currY, maxButtonWidth,
 
651
                                                                actualButtonHeight);
 
652
                                                // System.out.println(button.getText() + ":"
 
653
                                                // + button.isVisible() + ":" + button.getBounds());
 
654
                                                currY += actualButtonHeight;
 
655
                                                currY += gap;
 
656
                                        }
 
657
                                        x += maxButtonWidth + groupInsets.bottom;
 
658
                                        int rightGroupX = x;
 
659
                                        groupRects[i] = new Rectangle(leftGroupX, top,
 
660
                                                        (rightGroupX - leftGroupX), (parent.getHeight()
 
661
                                                                        - top - bottom));
 
662
                                }
 
663
                        } else {
 
664
                                int x = panel.getWidth() - bInsets.right - groupInsets.right;
 
665
                                for (int i = 0; i < groupCount; i++) {
 
666
                                        int rightGroupX = x;
 
667
                                        x -= groupInsets.left;
 
668
                                        int currY = top + groupInsets.top;
 
669
 
 
670
                                        int buttonColumns = (buttonsInRow == 0) ? 0 : (int) (Math
 
671
                                                        .ceil((double) panel.getGroupButtons(i).size()
 
672
                                                                        / buttonsInRow));
 
673
                                        // spread the buttons so that we don't have extra space
 
674
                                        // on the bottom
 
675
                                        int actualButtonHeight = (buttonColumns > 1) ? (maxHeight - (buttonsInRow - 1)
 
676
                                                        * gap)
 
677
                                                        / buttonsInRow
 
678
                                                        : maxButtonWidth;
 
679
 
 
680
                                        for (AbstractCommandButton button : panel
 
681
                                                        .getGroupButtons(i)) {
 
682
                                                int endY = currY + actualButtonHeight;
 
683
                                                if (endY > (parent.getHeight() - bottom - groupInsets.bottom)) {
 
684
                                                        currY = top + groupInsets.top;
 
685
                                                        x -= maxButtonWidth;
 
686
                                                        x -= gap;
 
687
                                                }
 
688
                                                button.setBounds(x - maxButtonWidth, currY,
 
689
                                                                maxButtonWidth, actualButtonHeight);
 
690
                                                // System.out.println(button.getText() + ":"
 
691
                                                // + button.isVisible() + ":" + button.getBounds());
 
692
                                                currY += actualButtonHeight;
 
693
                                                currY += gap;
 
694
                                        }
 
695
                                        x -= (maxButtonWidth + groupInsets.bottom);
 
696
                                        int leftGroupX = x;
 
697
                                        groupRects[i] = new Rectangle(leftGroupX, top,
 
698
                                                        (rightGroupX - leftGroupX), (parent.getHeight()
 
699
                                                                        - top - bottom));
 
700
                                }
 
701
                        }
 
702
                }
 
703
 
 
704
                /*
 
705
                 * (non-Javadoc)
 
706
                 * 
 
707
                 * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
 
708
                 */
 
709
                @Override
 
710
        public Dimension minimumLayoutSize(Container parent) {
 
711
                        return new Dimension(20, 20);
 
712
                }
 
713
 
 
714
                /*
 
715
                 * (non-Javadoc)
 
716
                 * 
 
717
                 * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
 
718
                 */
 
719
                @Override
 
720
        public Dimension preferredLayoutSize(Container parent) {
 
721
                        JCommandButtonPanel panel = (JCommandButtonPanel) parent;
 
722
 
 
723
                        int maxButtonRowsToUse = panel.getMaxButtonRows();
 
724
 
 
725
                        Insets bInsets = parent.getInsets();
 
726
                        Insets groupInsets = getGroupInsets();
 
727
                        int insetsHeight = bInsets.top + groupInsets.top + bInsets.bottom
 
728
                                        + groupInsets.bottom;
 
729
 
 
730
                        // compute max width of buttons
 
731
                        int maxButtonWidth = 0;
 
732
                        int maxButtonHeight = 0;
 
733
                        int groupCount = panel.getGroupCount();
 
734
                        for (int i = 0; i < groupCount; i++) {
 
735
                                for (AbstractCommandButton button : panel.getGroupButtons(i)) {
 
736
                                        maxButtonWidth = Math.max(maxButtonWidth, button
 
737
                                                        .getPreferredSize().width);
 
738
                                        maxButtonHeight = Math.max(maxButtonHeight, button
 
739
                                                        .getPreferredSize().height);
 
740
                                }
 
741
                        }
 
742
 
 
743
                        // total width
 
744
                        int gap = getLayoutGap();
 
745
                        boolean usePanelHeight = (maxButtonRowsToUse <= 0);
 
746
 
 
747
                        int availableHeight = panel.getHeight();
 
748
                        availableHeight -= insetsHeight;
 
749
                        if (usePanelHeight) {
 
750
                                // this hasn't been set. Compute using the available
 
751
                                // height
 
752
                                maxButtonRowsToUse = (availableHeight + gap)
 
753
                                                / (maxButtonHeight + gap);
 
754
                        }
 
755
                        // go over all groups and see how many columns each one needs
 
756
                        int width = bInsets.left + bInsets.right;
 
757
                        for (int i = 0; i < groupCount; i++) {
 
758
                                width += (groupInsets.left + groupInsets.right);
 
759
 
 
760
                                int buttonColumns = (int) (Math.ceil((double) panel
 
761
                                                .getGroupButtons(i).size()
 
762
                                                / maxButtonRowsToUse));
 
763
                                width += buttonColumns * maxButtonWidth + (buttonColumns - 1)
 
764
                                                * gap;
 
765
                        }
 
766
                        int prefHeight = usePanelHeight ? availableHeight
 
767
                                        : maxButtonRowsToUse * maxButtonWidth
 
768
                                                        + (maxButtonRowsToUse - 1) * gap + bInsets.top
 
769
                                                        + bInsets.bottom + groupInsets.top
 
770
                                                        + groupInsets.bottom;
 
771
                        return new Dimension(Math.max(10, width), Math.max(10, prefHeight));
 
772
                }
 
773
        }
 
774
 
 
775
        /**
 
776
         * Returns the layout gap for button panel components.
 
777
         * 
 
778
         * @return The layout gap for button panel components.
 
779
         */
 
780
        protected int getLayoutGap() {
 
781
                return 4;
 
782
        }
 
783
 
 
784
        /**
 
785
         * Recomputes the components for button group headers.
 
786
         */
 
787
        protected void recomputeGroupHeaders() {
 
788
                if (this.groupLabels != null) {
 
789
                        for (JLabel groupLabel : this.groupLabels) {
 
790
                                this.buttonPanel.remove(groupLabel);
 
791
                        }
 
792
                }
 
793
 
 
794
                int groupCount = this.buttonPanel.getGroupCount();
 
795
                this.groupLabels = new JLabel[groupCount];
 
796
                for (int i = 0; i < groupCount; i++) {
 
797
                        this.groupLabels[i] = new JLabel(this.buttonPanel
 
798
                                        .getGroupTitleAt(i));
 
799
                        this.groupLabels[i].setComponentOrientation(this.buttonPanel
 
800
                                        .getComponentOrientation());
 
801
 
 
802
                        this.buttonPanel.add(this.groupLabels[i]);
 
803
 
 
804
                        this.groupLabels[i].setVisible(this.buttonPanel
 
805
                                        .isToShowGroupLabels());
 
806
                }
 
807
        }
 
808
 
 
809
        /**
 
810
         * Returns the preferred size of the associated button panel for the
 
811
         * specified parameters.
 
812
         * 
 
813
         * @param buttonVisibleRows
 
814
         *            Target number of visible button rows.
 
815
         * @param titleVisibleRows
 
816
         *            Target number of visible group title rows.
 
817
         * @return The preferred size of the associated button panel for the
 
818
         *         specified parameters.
 
819
         */
 
820
        public int getPreferredHeight(int buttonVisibleRows, int titleVisibleRows) {
 
821
                Insets bInsets = this.buttonPanel.getInsets();
 
822
                Insets groupInsets = getGroupInsets();
 
823
                int maxButtonHeight = 0;
 
824
                int groupCount = this.buttonPanel.getGroupCount();
 
825
                for (int i = 0; i < groupCount; i++) {
 
826
                        for (AbstractCommandButton button : this.buttonPanel
 
827
                                        .getGroupButtons(i)) {
 
828
                                maxButtonHeight = Math.max(maxButtonHeight, button
 
829
                                                .getPreferredSize().height);
 
830
                        }
 
831
                }
 
832
 
 
833
                // total height
 
834
                int gap = getLayoutGap();
 
835
 
 
836
                // panel insets
 
837
                int totalHeight = bInsets.top + bInsets.bottom;
 
838
                // height of icon rows
 
839
                totalHeight += buttonVisibleRows * maxButtonHeight;
 
840
                // gaps between icon rows
 
841
                totalHeight += (buttonVisibleRows - 1) * gap;
 
842
                // title height
 
843
                totalHeight += titleVisibleRows * getGroupTitleHeight(0);
 
844
                // title insets
 
845
                totalHeight += (titleVisibleRows - 1)
 
846
                                * (groupInsets.top + groupInsets.bottom);
 
847
 
 
848
                return totalHeight;
 
849
        }
 
850
}