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

« back to all changes in this revision

Viewing changes to flamingo/src/main/java/org/pushingpixels/flamingo/api/common/JCommandButtonPanel.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.api.common;
 
31
 
 
32
import java.awt.Dimension;
 
33
import java.awt.Rectangle;
 
34
import java.util.*;
 
35
 
 
36
import javax.swing.*;
 
37
import javax.swing.event.ChangeEvent;
 
38
import javax.swing.event.ChangeListener;
 
39
 
 
40
import org.pushingpixels.flamingo.internal.ui.common.BasicCommandButtonPanelUI;
 
41
import org.pushingpixels.flamingo.internal.ui.common.CommandButtonPanelUI;
 
42
 
 
43
/**
 
44
 * Panel that hosts command buttons. Provides support for button groups, single
 
45
 * selection mode (for toggle command buttons), same icon state / dimension and
 
46
 * column-fill / row-fill layout.
 
47
 * 
 
48
 * <p>
 
49
 * Under the default {@link LayoutKind#ROW_FILL}, the buttons are laid out in
 
50
 * rows, never exceeding the available horizontal space. A vertical scroll bar
 
51
 * will kick in once there is not enough vertical space to show all the buttons.
 
52
 * The schematic below shows a row-fill command button panel:
 
53
 * </p>
 
54
 * 
 
55
 * <pre>
 
56
 * +-----------------------------+-+ 
 
57
 * |                             | |
 
58
 * | +----+ +----+ +----+ +----+ | |
 
59
 * | | 01 | | 02 | | 03 | | 04 | | |
 
60
 * | +----+ +----+ +----+ +----+ | |
 
61
 * |                             | |
 
62
 * | +----+ +----+ +----+ +----+ | |
 
63
 * | | 05 | | 06 | | 07 | | 07 | | |
 
64
 * | +----+ +----+ +----+ +----+ | |
 
65
 * |                             | |
 
66
 * | +----+ +----+ +----+ +----+ | |
 
67
 * | | 09 | | 10 | | 11 | | 12 | | |
 
68
 * | +----+ +----+ +----+ +----+ | |
 
69
 * |                             | |
 
70
 * | +----+ +----+ +----+ +----+ | |
 
71
 * | | 13 | | 14 | | 15 | | 16 | | |
 
72
 * +-----------------------------+-+
 
73
 * </pre>
 
74
 * 
 
75
 * <p>
 
76
 * Each row hosts four buttons, and the vertical scroll bar allows scrolling the
 
77
 * content down.
 
78
 * </p>
 
79
 * 
 
80
 * <p>
 
81
 * Under the {@link LayoutKind#COLUMN_FILL}, the buttons are laid out in
 
82
 * columns, never exceeding the available vertical space. A horizontal scroll
 
83
 * bar will kick in once there is not enough horizontal space to show all the
 
84
 * buttons. The schematic below shows a column-fill command button panel:
 
85
 * </p>
 
86
 * 
 
87
 * <pre>
 
88
 * +---------------------------------+ 
 
89
 * |                                 |
 
90
 * | +----+ +----+ +----+ +----+ +---|
 
91
 * | | 01 | | 04 | | 07 | | 10 | | 13|
 
92
 * | +----+ +----+ +----+ +----+ +---|
 
93
 * |                                 |
 
94
 * | +----+ +----+ +----+ +----+ +---|
 
95
 * | | 02 | | 05 | | 08 | | 11 | | 14|
 
96
 * | +----+ +----+ +----+ +----+ +---|
 
97
 * |                                 |
 
98
 * | +----+ +----+ +----+ +----+ +---|
 
99
 * | | 03 | | 06 | | 09 | | 12 | | 15|
 
100
 * | +----+ +----+ +----+ +----+ +---|
 
101
 * |                                 |
 
102
 * +---------------------------------+
 
103
 * +---------------------------------+
 
104
 * </pre>
 
105
 * 
 
106
 * <p>
 
107
 * Each column hosts three buttons, and the horizontal scroll bar allows
 
108
 * scrolling the content down.
 
109
 * </p>
 
110
 * 
 
111
 * @author Kirill Grouchnikov
 
112
 */
 
113
public class JCommandButtonPanel extends JPanel implements Scrollable {
 
114
        /**
 
115
         * @see #getUIClassID
 
116
         */
 
117
        public static final String uiClassID = "CommandButtonPanelUI";
 
118
 
 
119
        /**
 
120
         * List of titles for all button groups.
 
121
         * 
 
122
         * @see #getGroupCount()
 
123
         * @see #getGroupTitleAt(int)
 
124
         */
 
125
        protected List<String> groupTitles;
 
126
 
 
127
        /**
 
128
         * List of all button groups.
 
129
         * 
 
130
         * @see #getGroupCount()
 
131
         * @see #getGroupButtons(int)
 
132
         */
 
133
        protected List<List<AbstractCommandButton>> buttons;
 
134
 
 
135
        /**
 
136
         * Maximum number of columns for this panel. Relevant only when the layout
 
137
         * kind is {@link LayoutKind#ROW_FILL}.
 
138
         * 
 
139
         * @see #getMaxButtonColumns()
 
140
         * @see #setMaxButtonColumns(int)
 
141
         */
 
142
        protected int maxButtonColumns;
 
143
 
 
144
        /**
 
145
         * Maximum number of rows for this panel. Relevant only when the layout kind
 
146
         * is {@link LayoutKind#COLUMN_FILL}.
 
147
         * 
 
148
         * @see #getMaxButtonRows()
 
149
         * @see #setMaxButtonRows(int)
 
150
         */
 
151
        protected int maxButtonRows;
 
152
 
 
153
        /**
 
154
         * Indicates the selection mode for the {@link JCommandToggleButton} in this
 
155
         * panel.
 
156
         * 
 
157
         * @see #setSingleSelectionMode(boolean)
 
158
         */
 
159
        protected boolean isSingleSelectionMode;
 
160
 
 
161
        /**
 
162
         * If <code>true</code>, the panel will show group labels.
 
163
         * 
 
164
         * @see #setToShowGroupLabels(boolean)
 
165
         * @see #isToShowGroupLabels()
 
166
         */
 
167
        protected boolean toShowGroupLabels;
 
168
 
 
169
        /**
 
170
         * The button group for the single selection mode.
 
171
         */
 
172
        protected CommandToggleButtonGroup buttonGroup;
 
173
 
 
174
        /**
 
175
         * Current icon dimension.
 
176
         */
 
177
        protected int currDimension;
 
178
 
 
179
        /**
 
180
         * Current icon state.
 
181
         */
 
182
        protected CommandButtonDisplayState currState;
 
183
 
 
184
        /**
 
185
         * Layout kind of this button panel.
 
186
         * 
 
187
         * @see #getLayoutKind()
 
188
         * @see #setLayoutKind(LayoutKind)
 
189
         */
 
190
        protected LayoutKind layoutKind;
 
191
 
 
192
        /**
 
193
         * Enumerates the available layout kinds.
 
194
         * 
 
195
         * @author Kirill Grouchnikov
 
196
         */
 
197
        public enum LayoutKind {
 
198
                /**
 
199
                 * The buttons are layed out in rows respecting the available width.
 
200
                 */
 
201
                ROW_FILL,
 
202
 
 
203
                /**
 
204
                 * The buttons are layed out in columns respecting the available height.
 
205
                 */
 
206
                COLUMN_FILL
 
207
        }
 
208
 
 
209
        /**
 
210
         * Creates a new panel.
 
211
         */
 
212
        protected JCommandButtonPanel() {
 
213
                this.buttons = new ArrayList<List<AbstractCommandButton>>();
 
214
                this.groupTitles = new ArrayList<String>();
 
215
                this.maxButtonColumns = -1;
 
216
                this.maxButtonRows = -1;
 
217
                this.isSingleSelectionMode = false;
 
218
                this.toShowGroupLabels = true;
 
219
                this.setLayoutKind(LayoutKind.ROW_FILL);
 
220
        }
 
221
 
 
222
        /**
 
223
         * Creates a new panel.
 
224
         * 
 
225
         * @param startingDimension
 
226
         *            Initial dimension for buttons.
 
227
         */
 
228
        public JCommandButtonPanel(int startingDimension) {
 
229
                this();
 
230
                this.currDimension = startingDimension;
 
231
                this.currState = CommandButtonDisplayState.FIT_TO_ICON;
 
232
                this.updateUI();
 
233
        }
 
234
 
 
235
        /**
 
236
         * Creates a new panel.
 
237
         * 
 
238
         * @param startingState
 
239
         *            Initial state for buttons.
 
240
         */
 
241
        public JCommandButtonPanel(CommandButtonDisplayState startingState) {
 
242
                this();
 
243
                this.currDimension = -1;
 
244
                this.currState = startingState;
 
245
                this.updateUI();
 
246
        }
 
247
 
 
248
        /**
 
249
         * Adds a new button group at the specified index.
 
250
         * 
 
251
         * @param buttonGroupName
 
252
         *            Button group name.
 
253
         * @param groupIndex
 
254
         *            Button group index.
 
255
         * @see #addButtonGroup(String)
 
256
         * @see #removeButtonGroup(String)
 
257
         * @see #removeAllGroups()
 
258
         */
 
259
        public void addButtonGroup(String buttonGroupName, int groupIndex) {
 
260
                this.groupTitles.add(groupIndex, buttonGroupName);
 
261
                List<AbstractCommandButton> list = new ArrayList<AbstractCommandButton>();
 
262
                this.buttons.add(groupIndex, list);
 
263
                this.fireStateChanged();
 
264
        }
 
265
 
 
266
        /**
 
267
         * Adds a new button group after all the existing button groups.
 
268
         * 
 
269
         * @param buttonGroupName
 
270
         *            Button group name.
 
271
         * @see #addButtonGroup(String, int)
 
272
         * @see #removeButtonGroup(String)
 
273
         * @see #removeAllGroups()
 
274
         */
 
275
        public void addButtonGroup(String buttonGroupName) {
 
276
                this.addButtonGroup(buttonGroupName, this.groupTitles.size());
 
277
        }
 
278
 
 
279
        /**
 
280
         * Removes the specified button group.
 
281
         * 
 
282
         * @param buttonGroupName
 
283
         *            Name of the button group to remove.
 
284
         * @see #addButtonGroup(String)
 
285
         * @see #addButtonGroup(String, int)
 
286
         * @see #removeAllGroups()
 
287
         */
 
288
        public void removeButtonGroup(String buttonGroupName) {
 
289
                int groupIndex = this.groupTitles.indexOf(buttonGroupName);
 
290
                if (groupIndex < 0)
 
291
                        return;
 
292
                this.groupTitles.remove(groupIndex);
 
293
                List<AbstractCommandButton> list = this.buttons.get(groupIndex);
 
294
                if (list != null) {
 
295
                        for (AbstractCommandButton button : list) {
 
296
                                this.remove(button);
 
297
                                if (this.isSingleSelectionMode
 
298
                                                && (button instanceof JCommandToggleButton)) {
 
299
                                        this.buttonGroup.remove((JCommandToggleButton) button);
 
300
                                }
 
301
                        }
 
302
                }
 
303
                this.buttons.remove(groupIndex);
 
304
                this.fireStateChanged();
 
305
        }
 
306
 
 
307
        /**
 
308
         * Adds a new button to the specified button group.
 
309
         * 
 
310
         * @param commandButton
 
311
         *            Button to add.
 
312
         * @return Returns the index of the button on the specified group, or -1 if
 
313
         *         no such group exists.
 
314
         * @see #addButtonToGroup(String, AbstractCommandButton)
 
315
         * @see #addButtonToGroup(String, int, AbstractCommandButton)
 
316
         * @see #removeButtonFromGroup(String, int)
 
317
         */
 
318
        public int addButtonToLastGroup(AbstractCommandButton commandButton) {
 
319
                if (this.groupTitles.size() == 0)
 
320
                        return -1;
 
321
                int groupIndex = this.groupTitles.size() - 1;
 
322
                commandButton.setDisplayState(this.currState);
 
323
                return this.addButtonToGroup(this.groupTitles.get(groupIndex),
 
324
                                this.buttons.get(groupIndex).size(), commandButton);
 
325
        }
 
326
 
 
327
        /**
 
328
         * Adds a new button to the specified button group.
 
329
         * 
 
330
         * @param buttonGroupName
 
331
         *            Name of the button group.
 
332
         * @param commandButton
 
333
         *            Button to add.
 
334
         * @return Returns the index of the button on the specified group, or -1 if
 
335
         *         no such group exists.
 
336
         * @see #addButtonToGroup(String, int, AbstractCommandButton)
 
337
         * @see #addButtonToLastGroup(AbstractCommandButton)
 
338
         * @see #removeButtonFromGroup(String, int)
 
339
         */
 
340
        public int addButtonToGroup(String buttonGroupName,
 
341
                        AbstractCommandButton commandButton) {
 
342
                int groupIndex = this.groupTitles.indexOf(buttonGroupName);
 
343
                if (groupIndex < 0)
 
344
                        return -1;
 
345
                commandButton.setDisplayState(this.currState);
 
346
                return this.addButtonToGroup(buttonGroupName, this.buttons.get(
 
347
                                groupIndex).size(), commandButton);
 
348
        }
 
349
 
 
350
        /**
 
351
         * Adds a new button to the specified button group.
 
352
         * 
 
353
         * @param buttonGroupName
 
354
         *            Name of the button group.
 
355
         * @param indexInGroup
 
356
         *            Index of the button in group.
 
357
         * @param commandButton
 
358
         *            Button to add.
 
359
         * @return Returns the index of the button on the specified group, or -1 if
 
360
         *         no such group exists.
 
361
         * @see #addButtonToGroup(String, int, AbstractCommandButton)
 
362
         * @see #addButtonToLastGroup(AbstractCommandButton)
 
363
         * @see #removeButtonFromGroup(String, int)
 
364
         */
 
365
        public int addButtonToGroup(String buttonGroupName, int indexInGroup,
 
366
                        AbstractCommandButton commandButton) {
 
367
                int groupIndex = this.groupTitles.indexOf(buttonGroupName);
 
368
                if (groupIndex < 0)
 
369
                        return -1;
 
370
                // commandButton.setState(ElementState.ORIG, true);
 
371
                this.add(commandButton);
 
372
                this.buttons.get(groupIndex).add(indexInGroup, commandButton);
 
373
                if (this.isSingleSelectionMode
 
374
                                && (commandButton instanceof JCommandToggleButton)) {
 
375
                        this.buttonGroup.add((JCommandToggleButton) commandButton);
 
376
                }
 
377
                this.fireStateChanged();
 
378
                return indexInGroup;
 
379
        }
 
380
 
 
381
        /**
 
382
         * Removes the button at the specified index from the specified button
 
383
         * group.
 
384
         * 
 
385
         * @param buttonGroupName
 
386
         *            Name of the button group.
 
387
         * @param indexInGroup
 
388
         *            Index of the button to remove.
 
389
         * @see #addButtonToGroup(String, AbstractCommandButton)
 
390
         * @see #addButtonToGroup(String, int, AbstractCommandButton)
 
391
         * @see #addButtonToLastGroup(AbstractCommandButton)
 
392
         */
 
393
        public void removeButtonFromGroup(String buttonGroupName, int indexInGroup) {
 
394
                int groupIndex = this.groupTitles.indexOf(buttonGroupName);
 
395
                if (groupIndex < 0)
 
396
                        return;
 
397
 
 
398
                AbstractCommandButton removed = this.buttons.get(groupIndex).remove(
 
399
                                indexInGroup);
 
400
                this.remove(removed);
 
401
                if (this.isSingleSelectionMode
 
402
                                && (removed instanceof JCommandToggleButton)) {
 
403
                        this.buttonGroup.remove((JCommandToggleButton) removed);
 
404
                }
 
405
                this.fireStateChanged();
 
406
        }
 
407
 
 
408
        /**
 
409
         * Removes all the button groups and buttons from this panel.
 
410
         * 
 
411
         * @see #addButtonGroup(String, int)
 
412
         * @see #addButtonGroup(String)
 
413
         * @see #removeButtonGroup(String)
 
414
         * @see #removeButtonFromGroup(String, int)
 
415
         */
 
416
        public void removeAllGroups() {
 
417
                for (List<AbstractCommandButton> ljcb : this.buttons) {
 
418
                        for (AbstractCommandButton jcb : ljcb) {
 
419
                                if (this.isSingleSelectionMode
 
420
                                                && (jcb instanceof JCommandToggleButton)) {
 
421
                                        this.buttonGroup.remove((JCommandToggleButton) jcb);
 
422
                                }
 
423
                                this.remove(jcb);
 
424
                        }
 
425
                }
 
426
                this.buttons.clear();
 
427
                this.groupTitles.clear();
 
428
                this.fireStateChanged();
 
429
        }
 
430
 
 
431
        /**
 
432
         * Returns the number of button groups in this panel.
 
433
         * 
 
434
         * @return Number of button groups in this panel.
 
435
         */
 
436
        public int getGroupCount() {
 
437
                if (this.groupTitles == null)
 
438
                        return 0;
 
439
                return this.groupTitles.size();
 
440
        }
 
441
 
 
442
        /**
 
443
         * Returns the number of buttons in this panel.
 
444
         * 
 
445
         * @return Number of buttons in this panel.
 
446
         */
 
447
        public int getButtonCount() {
 
448
                int result = 0;
 
449
                for (List<AbstractCommandButton> ljcb : this.buttons) {
 
450
                        result += ljcb.size();
 
451
                }
 
452
                return result;
 
453
        }
 
454
 
 
455
        /**
 
456
         * Returns the title of the button group at the specified index.
 
457
         * 
 
458
         * @param index
 
459
         *            Button group index.
 
460
         * @return Title of the button group at the specified index.
 
461
         */
 
462
        public String getGroupTitleAt(int index) {
 
463
                return this.groupTitles.get(index);
 
464
        }
 
465
 
 
466
        /*
 
467
         * (non-Javadoc)
 
468
         * 
 
469
         * @see javax.swing.JPanel#updateUI()
 
470
         */
 
471
        @Override
 
472
        public void updateUI() {
 
473
                if (UIManager.get(getUIClassID()) != null) {
 
474
                        setUI((CommandButtonPanelUI) UIManager.getUI(this));
 
475
                } else {
 
476
                        setUI(BasicCommandButtonPanelUI.createUI(this));
 
477
                }
 
478
        }
 
479
 
 
480
        /*
 
481
         * (non-Javadoc)
 
482
         * 
 
483
         * @see javax.swing.JPanel#getUIClassID()
 
484
         */
 
485
        @Override
 
486
        public String getUIClassID() {
 
487
                return uiClassID;
 
488
        }
 
489
 
 
490
        /**
 
491
         * Sets the maximum button columns for this panel. When this panel is shown
 
492
         * and the layout kind is {@link LayoutKind#ROW_FILL}, it will have no more
 
493
         * than this number of buttons in each row. Fires a
 
494
         * <code>maxButtonColumns</code> property change event.
 
495
         * 
 
496
         * @param maxButtonColumns
 
497
         *            Maximum button columns for this panel.
 
498
         * @see #getMaxButtonColumns()
 
499
         * @see #setMaxButtonRows(int)
 
500
         */
 
501
        public void setMaxButtonColumns(int maxButtonColumns) {
 
502
                if (maxButtonColumns != this.maxButtonColumns) {
 
503
                        int oldValue = this.maxButtonColumns;
 
504
                        this.maxButtonColumns = maxButtonColumns;
 
505
                        this.firePropertyChange("maxButtonColumns", oldValue,
 
506
                                        this.maxButtonColumns);
 
507
                }
 
508
        }
 
509
 
 
510
        /**
 
511
         * Returns the maximum button columns for this panel. The return value is
 
512
         * relevant only when the layout kind is {@link LayoutKind#ROW_FILL}.
 
513
         * 
 
514
         * @return Maximum button columns for this panel.
 
515
         * @see #setMaxButtonColumns(int)
 
516
         * @see #getMaxButtonRows()
 
517
         */
 
518
        public int getMaxButtonColumns() {
 
519
                return this.maxButtonColumns;
 
520
        }
 
521
 
 
522
        /**
 
523
         * Sets the maximum button rows for this panel. When this panel is shown and
 
524
         * the layout kind is {@link LayoutKind#COLUMN_FILL}, it will have no more
 
525
         * than this number of buttons in each column. Fires a
 
526
         * <code>maxButtonRows</code> property change event.
 
527
         * 
 
528
         * @param maxButtonRows
 
529
         *            Maximum button rows for this panel.
 
530
         * @see #getMaxButtonRows()
 
531
         * @see #setMaxButtonColumns(int)
 
532
         */
 
533
        public void setMaxButtonRows(int maxButtonRows) {
 
534
                if (maxButtonRows != this.maxButtonRows) {
 
535
                        int oldValue = this.maxButtonRows;
 
536
                        this.maxButtonRows = maxButtonRows;
 
537
                        this.firePropertyChange("maxButtonRows", oldValue,
 
538
                                        this.maxButtonRows);
 
539
                }
 
540
        }
 
541
 
 
542
        /**
 
543
         * Returns the maximum button rows for this panel. The return value is
 
544
         * relevant only when the layout kind is {@link LayoutKind#COLUMN_FILL}.
 
545
         * 
 
546
         * @return Maximum button rows for this panel.
 
547
         * @see #setMaxButtonRows(int)
 
548
         * @see #getMaxButtonColumns()
 
549
         */
 
550
        public int getMaxButtonRows() {
 
551
                return this.maxButtonRows;
 
552
        }
 
553
 
 
554
        /**
 
555
         * Returns the list of all buttons in the specified button group.
 
556
         * 
 
557
         * @param groupIndex
 
558
         *            Group index.
 
559
         * @return Unmodifiable view on the list of all buttons in the specified
 
560
         *         button group.
 
561
         * @see #getGroupCount()
 
562
         */
 
563
        public List<AbstractCommandButton> getGroupButtons(int groupIndex) {
 
564
                return Collections.unmodifiableList(this.buttons.get(groupIndex));
 
565
        }
 
566
 
 
567
        /**
 
568
         * Sets the selection mode for this panel. If <code>true</code> is passed as
 
569
         * the parameter, all {@link JCommandToggleButton} in this panel are set to
 
570
         * belong to the same button group.
 
571
         * 
 
572
         * @param isSingleSelectionMode
 
573
         *            If <code>true</code>,all {@link JCommandToggleButton} in this
 
574
         *            panel are set to belong to the same button group.
 
575
         * @see #getSelectedButton()
 
576
         */
 
577
        public void setSingleSelectionMode(boolean isSingleSelectionMode) {
 
578
                if (this.isSingleSelectionMode == isSingleSelectionMode)
 
579
                        return;
 
580
 
 
581
                this.isSingleSelectionMode = isSingleSelectionMode;
 
582
                if (this.isSingleSelectionMode) {
 
583
                        this.buttonGroup = new CommandToggleButtonGroup();
 
584
                        for (List<AbstractCommandButton> ljrb : this.buttons) {
 
585
                                for (AbstractCommandButton jrb : ljrb) {
 
586
                                        if (jrb instanceof JCommandToggleButton) {
 
587
                                                this.buttonGroup.add((JCommandToggleButton) jrb);
 
588
                                        }
 
589
                                }
 
590
                        }
 
591
                } else {
 
592
                        for (List<AbstractCommandButton> ljrb : this.buttons) {
 
593
                                for (AbstractCommandButton jrb : ljrb) {
 
594
                                        if (jrb instanceof JCommandToggleButton) {
 
595
                                                this.buttonGroup.remove((JCommandToggleButton) jrb);
 
596
                                        }
 
597
                                }
 
598
                        }
 
599
                        this.buttonGroup = null;
 
600
                }
 
601
        }
 
602
 
 
603
        /**
 
604
         * Sets indication whether button group labels should be shown. Fires a
 
605
         * <code>toShowGroupLabels</code> property change event.
 
606
         * 
 
607
         * @param toShowGroupLabels
 
608
         *            If <code>true</code>, this panel will show the labels of the
 
609
         *            button groups.
 
610
         * @see #isToShowGroupLabels()
 
611
         */
 
612
        public void setToShowGroupLabels(boolean toShowGroupLabels) {
 
613
                if ((layoutKind == LayoutKind.COLUMN_FILL) && toShowGroupLabels) {
 
614
                        throw new IllegalArgumentException(
 
615
                                        "Column fill layout is not supported when group labels are shown");
 
616
                }
 
617
                if (this.toShowGroupLabels != toShowGroupLabels) {
 
618
                        boolean oldValue = this.toShowGroupLabels;
 
619
                        this.toShowGroupLabels = toShowGroupLabels;
 
620
                        this.firePropertyChange("toShowGroupLabels", oldValue,
 
621
                                        this.toShowGroupLabels);
 
622
                }
 
623
        }
 
624
 
 
625
        /**
 
626
         * Returns indication whether button group labels should be shown.
 
627
         * 
 
628
         * @return If <code>true</code>, this panel shows the labels of the button
 
629
         *         groups, and <code>false</code> otherwise.
 
630
         * @see #setToShowGroupLabels(boolean)
 
631
         */
 
632
        public boolean isToShowGroupLabels() {
 
633
                return this.toShowGroupLabels;
 
634
        }
 
635
 
 
636
        /**
 
637
         * Sets the new dimension for the icons in this panel. The state for all the
 
638
         * icons is set to {@link CommandButtonDisplayState#FIT_TO_ICON}.
 
639
         * 
 
640
         * @param dimension
 
641
         *            New dimension for the icons in this panel.
 
642
         * @see #setIconState(CommandButtonDisplayState)
 
643
         */
 
644
        public void setIconDimension(int dimension) {
 
645
                this.currDimension = dimension;
 
646
                this.currState = CommandButtonDisplayState.FIT_TO_ICON;
 
647
                for (List<AbstractCommandButton> buttonList : this.buttons) {
 
648
                        for (AbstractCommandButton button : buttonList) {
 
649
                                button.updateCustomDimension(dimension);
 
650
                        }
 
651
                }
 
652
                this.revalidate();
 
653
                this.doLayout();
 
654
                this.repaint();
 
655
        }
 
656
 
 
657
        /**
 
658
         * Sets the new state for the icons in this panel. The dimension for all the
 
659
         * icons is set to -1; this method should only be called with a state that
 
660
         * has an associated default size (like
 
661
         * {@link CommandButtonDisplayState#BIG},
 
662
         * {@link CommandButtonDisplayState#TILE},
 
663
         * {@link CommandButtonDisplayState#MEDIUM} and
 
664
         * {@link CommandButtonDisplayState#SMALL}).
 
665
         * 
 
666
         * @param state
 
667
         *            New state for the icons in this panel.
 
668
         * @see #setIconDimension(int)
 
669
         */
 
670
        public void setIconState(CommandButtonDisplayState state) {
 
671
                this.currDimension = -1;
 
672
                this.currState = state;
 
673
                for (List<AbstractCommandButton> ljrb : this.buttons) {
 
674
                        for (AbstractCommandButton jrb : ljrb) {
 
675
                                jrb.setDisplayState(state);
 
676
                                jrb.revalidate();
 
677
                                jrb.doLayout();
 
678
                        }
 
679
                }
 
680
                this.revalidate();
 
681
                this.doLayout();
 
682
                this.repaint();
 
683
        }
 
684
 
 
685
        /**
 
686
         * Returns the selected button of this panel. Only relevant for single
 
687
         * selection mode (set by {@link #setSingleSelectionMode(boolean)}),
 
688
         * returning <code>null</code> otherwise.
 
689
         * 
 
690
         * @return The selected button of this panel.
 
691
         * @see #setSingleSelectionMode(boolean)
 
692
         */
 
693
        public JCommandToggleButton getSelectedButton() {
 
694
                if (this.isSingleSelectionMode) {
 
695
                        for (List<AbstractCommandButton> ljrb : this.buttons) {
 
696
                                for (AbstractCommandButton jrb : ljrb) {
 
697
                                        if (jrb instanceof JCommandToggleButton) {
 
698
                                                JCommandToggleButton jctb = (JCommandToggleButton) jrb;
 
699
                                                if (jctb.getActionModel().isSelected())
 
700
                                                        return jctb;
 
701
                                        }
 
702
                                }
 
703
                        }
 
704
                }
 
705
                return null;
 
706
        }
 
707
 
 
708
        /**
 
709
         * Returns the layout kind of this panel.
 
710
         * 
 
711
         * @return Layout kind of this panel.
 
712
         * @see #setLayoutKind(LayoutKind)
 
713
         */
 
714
        public LayoutKind getLayoutKind() {
 
715
                return layoutKind;
 
716
        }
 
717
 
 
718
        /**
 
719
         * Sets the new layout kind for this panel. Fires a <code>layoutKind</code>
 
720
         * property change event.
 
721
         * 
 
722
         * @param layoutKind
 
723
         *            New layout kind for this panel.
 
724
         * @see #getLayoutKind()
 
725
         */
 
726
        public void setLayoutKind(LayoutKind layoutKind) {
 
727
                if (layoutKind == null)
 
728
                        throw new IllegalArgumentException("Layout kind cannot be null");
 
729
                if ((layoutKind == LayoutKind.COLUMN_FILL)
 
730
                                && this.isToShowGroupLabels()) {
 
731
                        throw new IllegalArgumentException(
 
732
                                        "Column fill layout is not supported when group labels are shown");
 
733
                }
 
734
                if (layoutKind != this.layoutKind) {
 
735
                        LayoutKind old = this.layoutKind;
 
736
                        this.layoutKind = layoutKind;
 
737
                        this.firePropertyChange("layoutKind", old, this.layoutKind);
 
738
                }
 
739
        }
 
740
 
 
741
        /**
 
742
         * Adds the specified change listener to this button panel.
 
743
         * 
 
744
         * @param l
 
745
         *            Change listener to add.
 
746
         * @see #removeChangeListener(ChangeListener)
 
747
         */
 
748
        public void addChangeListener(ChangeListener l) {
 
749
                this.listenerList.add(ChangeListener.class, l);
 
750
        }
 
751
 
 
752
        /**
 
753
         * Removes the specified change listener from this button panel.
 
754
         * 
 
755
         * @param l
 
756
         *            Change listener to remove.
 
757
         * @see #addChangeListener(ChangeListener)
 
758
         */
 
759
        public void removeChangeListener(ChangeListener l) {
 
760
                this.listenerList.remove(ChangeListener.class, l);
 
761
        }
 
762
 
 
763
        /**
 
764
         * Notifies all registered listener that the state of this command button
 
765
         * panel has changed.
 
766
         */
 
767
        protected void fireStateChanged() {
 
768
                // Guaranteed to return a non-null array
 
769
                Object[] listeners = listenerList.getListenerList();
 
770
                // Process the listeners last to first, notifying
 
771
                // those that are interested in this event
 
772
                ChangeEvent event = new ChangeEvent(this);
 
773
                for (int i = listeners.length - 2; i >= 0; i -= 2) {
 
774
                        if (listeners[i] == ChangeListener.class) {
 
775
                                ((ChangeListener) listeners[i + 1]).stateChanged(event);
 
776
                        }
 
777
                }
 
778
        }
 
779
 
 
780
        /*
 
781
         * (non-Javadoc)
 
782
         * 
 
783
         * @see javax.swing.Scrollable#getPreferredScrollableViewportSize()
 
784
         */
 
785
        @Override
 
786
    public Dimension getPreferredScrollableViewportSize() {
 
787
                return this.getPreferredSize();
 
788
        }
 
789
 
 
790
        /*
 
791
         * (non-Javadoc)
 
792
         * 
 
793
         * @see
 
794
         * javax.swing.Scrollable#getScrollableBlockIncrement(java.awt.Rectangle,
 
795
         * int, int)
 
796
         */
 
797
        @Override
 
798
    public int getScrollableBlockIncrement(Rectangle visibleRect,
 
799
                        int orientation, int direction) {
 
800
                return 30;
 
801
        }
 
802
 
 
803
        /*
 
804
         * (non-Javadoc)
 
805
         * 
 
806
         * @see javax.swing.Scrollable#getScrollableTracksViewportHeight()
 
807
         */
 
808
        @Override
 
809
    public boolean getScrollableTracksViewportHeight() {
 
810
                return (this.layoutKind == LayoutKind.COLUMN_FILL);
 
811
        }
 
812
 
 
813
        /*
 
814
         * (non-Javadoc)
 
815
         * 
 
816
         * @see javax.swing.Scrollable#getScrollableTracksViewportWidth()
 
817
         */
 
818
        @Override
 
819
    public boolean getScrollableTracksViewportWidth() {
 
820
                return (this.layoutKind == LayoutKind.ROW_FILL);
 
821
        }
 
822
 
 
823
        /*
 
824
         * (non-Javadoc)
 
825
         * 
 
826
         * @see
 
827
         * javax.swing.Scrollable#getScrollableUnitIncrement(java.awt.Rectangle,
 
828
         * int, int)
 
829
         */
 
830
        @Override
 
831
    public int getScrollableUnitIncrement(Rectangle visibleRect,
 
832
                        int orientation, int direction) {
 
833
                return 10;
 
834
        }
 
835
}