1 package be
.nikiroo
.utils
.ui
;
3 import java
.awt
.Dimension
;
4 import java
.awt
.event
.ActionEvent
;
5 import java
.awt
.event
.ActionListener
;
7 import javax
.swing
.BorderFactory
;
8 import javax
.swing
.BoxLayout
;
9 import javax
.swing
.Icon
;
10 import javax
.swing
.JButton
;
11 import javax
.swing
.JLabel
;
12 import javax
.swing
.JTextField
;
15 * A Swing-based navigation bar, that displays first/previous/next/last page
20 public class NavBar
extends ListenerPanel
{
21 private static final long serialVersionUID
= 1L;
23 /** The event that is fired on page change. */
24 public static final String PAGE_CHANGED
= "page changed";
26 private JTextField page
;
27 private JLabel pageLabel
;
28 private JLabel maxPage
;
31 private int index
= 0;
34 private String extraLabel
= null;
36 private boolean vertical
;
38 private JButton first
;
39 private JButton previous
;
44 * Create a new navigation bar.
46 * The minimum must be lower or equal to the maximum, but a max of "-1"
49 * A {@link NavBar#PAGE_CHANGED} event will be fired on startup.
52 * the minimum page number (cannot be negative)
54 * the maximum page number (cannot be lower than min, except if
57 * @throws IndexOutOfBoundsException
58 * if min > max and max is not "-1"
60 public NavBar(int min
, int max
) {
61 if (min
> max
&& max
!= -1) {
62 throw new IndexOutOfBoundsException(
63 String
.format("min (%d) > max (%d)", min
, max
));
67 first
= new JButton();
68 first
.addActionListener(new ActionListener() {
70 public void actionPerformed(ActionEvent e
) {
75 previous
= new JButton();
76 previous
.addActionListener(new ActionListener() {
78 public void actionPerformed(ActionEvent e
) {
83 final int defaultHeight
= new JButton("dummy")
84 .getPreferredSize().height
;
85 final int width4
= new JButton("1234").getPreferredSize().width
;
86 page
= new JTextField(Integer
.toString(min
));
87 page
.setPreferredSize(new Dimension(width4
, defaultHeight
));
88 page
.addActionListener(new ActionListener() {
90 public void actionPerformed(ActionEvent e
) {
92 int pageNb
= Integer
.parseInt(page
.getText());
93 if (pageNb
< NavBar
.this.min
|| pageNb
> NavBar
.this.max
) {
94 throw new NumberFormatException("invalid");
98 fireActionPerformed(PAGE_CHANGED
);
99 } catch (NumberFormatException nfe
) {
100 page
.setText(Integer
.toString(index
));
105 pageLabel
= new JLabel(Integer
.toString(min
));
106 pageLabel
.setBorder(BorderFactory
.createEmptyBorder(0, 10, 0, 10));
108 maxPage
= new JLabel("of " + max
);
109 maxPage
.setBorder(BorderFactory
.createEmptyBorder(0, 10, 0, 10));
111 next
= new JButton();
112 next
.addActionListener(new ActionListener() {
114 public void actionPerformed(ActionEvent e
) {
119 last
= new JButton();
120 last
.addActionListener(new ActionListener() {
122 public void actionPerformed(ActionEvent e
) {
127 label
= new JLabel("");
129 // Set the << < > >> "icons"
130 setIcons(null, null, null, null);
138 setOrientation(vertical
);
140 fireActionPerformed(PAGE_CHANGED
);
144 * The current index, must be between {@link NavBar#min} and
145 * {@link NavBar#max}, both inclusive.
149 public int getIndex() {
154 * The current index, should be between {@link NavBar#min} and
155 * {@link NavBar#max}, both inclusive.
160 * @return TRUE if the index changed, FALSE if not (either it was already at
161 * that value, or it is outside of the bounds set by
162 * {@link NavBar#min} and {@link NavBar#max})
164 public synchronized boolean setIndex(int index
) {
165 if (index
!= this.index
) {
166 if (index
< min
|| (index
> max
&& max
!= -1)) {
181 * The minimun page number. Cannot be negative.
185 public int getMin() {
190 * The minimum page number. Cannot be negative.
192 * May update the index if needed (if the index is < the new min).
194 * Will also (always) update the label and enable/disable the required
200 public synchronized void setMin(int min
) {
211 * The maximum page number. Cannot be lower than min, except if -1
216 public int getMax() {
221 * The maximum page number. Cannot be lower than min, except if -1
224 * May update the index if needed (if the index is > the new max).
226 * Will also (always) update the label and enable/disable the required
232 public synchronized void setMax(int max
) {
234 if (index
> max
&& max
!= -1) {
238 maxPage
.setText("of " + max
);
244 * The current extra label to display.
246 * @return the current label
248 public String
getExtraLabel() {
253 * The current extra label to display.
255 * @param currentLabel
256 * the new current label
258 public void setExtraLabel(String currentLabel
) {
259 this.extraLabel
= currentLabel
;
264 * Change the page to the next one.
266 * @return TRUE if it changed
268 public synchronized boolean next() {
269 if (setIndex(index
+ 1)) {
270 fireActionPerformed(PAGE_CHANGED
);
278 * Change the page to the previous one.
280 * @return TRUE if it changed
282 public synchronized boolean previous() {
283 if (setIndex(index
- 1)) {
284 fireActionPerformed(PAGE_CHANGED
);
292 * Change the page to the first one.
294 * @return TRUE if it changed
296 public synchronized boolean first() {
298 fireActionPerformed(PAGE_CHANGED
);
306 * Change the page to the last one.
308 * @return TRUE if it changed
310 public synchronized boolean last() {
312 fireActionPerformed(PAGE_CHANGED
);
320 * Set icons for the buttons instead of square brackets.
322 * Any NULL value will make the button use square brackets again.
325 * the icon of the button "go to first page"
327 * the icon of the button "go to previous page"
329 * the icon of the button "go to next page"
331 * the icon of the button "go to last page"
333 public void setIcons(Icon first
, Icon previous
, Icon next
, Icon last
) {
334 this.first
.setIcon(first
);
335 this.first
.setText(first
== null ?
"<<" : "");
336 this.previous
.setIcon(previous
);
337 this.previous
.setText(previous
== null ?
"<" : "");
338 this.next
.setIcon(next
);
339 this.next
.setText(next
== null ?
">" : "");
340 this.last
.setIcon(last
);
341 this.last
.setText(last
== null ?
">>" : "");
345 * The general orientation of the component.
347 * @return TRUE for vertical orientation, FALSE for horisontal orientation
349 public boolean getOrientation() {
354 * Update the general orientation of the component.
357 * TRUE for vertical orientation, FALSE for horisontal
360 * @return TRUE if it changed something
362 public boolean setOrientation(boolean vertical
) {
363 if (getWidth() == 0 || this.vertical
!= vertical
) {
364 this.vertical
= vertical
;
366 BoxLayout layout
= new BoxLayout(this,
367 vertical ? BoxLayout
.Y_AXIS
: BoxLayout
.X_AXIS
);
396 * Update the label displayed in the UI.
398 private void updateLabel() {
399 label
.setText(getExtraLabel());
400 pageLabel
.setText(Integer
.toString(index
));
401 page
.setText(Integer
.toString(index
));
405 * Update the navigation buttons "enabled" state according to the current
408 private synchronized void updateEnabled() {
409 first
.setEnabled(index
> min
);
410 previous
.setEnabled(index
> min
);
411 next
.setEnabled(index
< max
|| max
== -1);
412 last
.setEnabled(index
< max
|| max
== -1);