package be.nikiroo.fanfix_swing.gui.viewer;
-import java.awt.Color;
+import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
-import javax.swing.JPanel;
+import javax.swing.JTextField;
-import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix_swing.images.IconGenerator;
+import be.nikiroo.fanfix_swing.images.IconGenerator.Icon;
+import be.nikiroo.fanfix_swing.images.IconGenerator.Size;
+import be.nikiroo.utils.ui.ListenerPanel;
/**
* A Swing-based navigation bar, that displays first/previous/next/last page
*
* @author niki
*/
-public class NavBar extends JPanel {
+public class NavBar extends ListenerPanel {
private static final long serialVersionUID = 1L;
+ /** The event that is fired on page change. */
+ public static final String PAGE_CHANGED = "page changed";
+
+ private JTextField page;
+ private JLabel maxPage;
private JLabel label;
+
private int index = 0;
private int min = 0;
private int max = 0;
- private JButton[] navButtons;
- String extraLabel = null;
+ private String extraLabel = null;
- private List<ActionListener> listeners = new ArrayList<ActionListener>();
+ private JButton first;
+ private JButton previous;
+ private JButton next;
+ private JButton last;
/**
* Create a new navigation bar.
*/
public NavBar(int min, int max) {
if (min > max && max != -1) {
- throw new IndexOutOfBoundsException(String.format(
- "min (%d) > max (%d)", min, max));
+ throw new IndexOutOfBoundsException(
+ String.format("min (%d) > max (%d)", min, max));
}
LayoutManager layout = new BoxLayout(this, BoxLayout.X_AXIS);
setLayout(layout);
- // TODO:
- // JButton up = new BasicArrowButton(BasicArrowButton.NORTH);
- // JButton down = new BasicArrowButton(BasicArrowButton.SOUTH);
-
- navButtons = new JButton[4];
+ // Page navigation
+ first = new JButton(
+ IconGenerator.get(Icon.arrow_double_left, Size.x32));
+ first.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ first();
+ }
+ });
- navButtons[0] = createNavButton("<<", new ActionListener() {
+ previous = new JButton(IconGenerator.get(Icon.arrow_left, Size.x32));
+ previous.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- setIndex(NavBar.this.min);
- fireEvent();
+ previous();
}
});
- navButtons[1] = createNavButton(" < ", new ActionListener() {
+
+ page = new JTextField("1");
+ page.setPreferredSize(new Dimension(page.getPreferredSize().width * 2,
+ page.getPreferredSize().height));
+ page.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- setIndex(index - 1);
- fireEvent();
+ try {
+ int pageNb = Integer.parseInt(page.getText());
+ if (pageNb < NavBar.this.min || pageNb > NavBar.this.max) {
+ throw new NumberFormatException("invalid");
+ }
+
+ if (setIndex(pageNb))
+ fireActionPerformed(PAGE_CHANGED);
+ } catch (NumberFormatException nfe) {
+ page.setText(Integer.toString(index + 1));
+ }
}
});
- navButtons[2] = createNavButton(" > ", new ActionListener() {
+
+ maxPage = new JLabel(" of " + max);
+
+ next = new JButton(IconGenerator.get(Icon.arrow_right, Size.x32));
+ next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- setIndex(index + 1);
- fireEvent();
+ next();
}
});
- navButtons[3] = createNavButton(">>", new ActionListener() {
+
+ last = new JButton(
+ IconGenerator.get(Icon.arrow_double_right, Size.x32));
+ last.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- setIndex(NavBar.this.max);
- fireEvent();
+ last();
}
});
- for (JButton navButton : navButtons) {
- add(navButton);
- }
+ this.add(first);
+ this.add(previous);
+ this.add(page);
+ this.add(maxPage);
+ this.add(next);
+ this.add(last);
label = new JLabel("");
- add(label);
+ this.add(label);
this.min = min;
this.max = max;
updateEnabled();
updateLabel();
- fireEvent();
+ fireActionPerformed(PAGE_CHANGED);
}
/**
*
* @param index
* the new index
+ *
+ * @return TRUE if the index changed
+ *
+ * @throws IndexOutOfBoundsException
+ * if the index is out of bounds according to
+ * {@link NavBar#getMin()} and {@link NavBar#getMax()}.
*/
- public void setIndex(int index) {
+ public boolean setIndex(int index) {
if (index != this.index) {
if (index < min || (index > max && max != -1)) {
throw new IndexOutOfBoundsException(String.format(
this.index = index;
updateLabel();
+ updateEnabled();
+
+ return true;
}
- updateEnabled();
+ return false;
}
/**
if (index < min) {
index = min;
}
+
updateEnabled();
updateLabel();
-
}
/**
if (index > max && max != -1) {
index = max;
}
+
+ maxPage.setText(" of " + max);
updateEnabled();
updateLabel();
}
/**
- * The current extra label to display with the default
- * {@link NavBar#computeLabel(int, int, int)} implementation.
+ * The current extra label to display.
*
* @return the current label
*/
}
/**
- * The current extra label to display with the default
- * {@link NavBar#computeLabel(int, int, int)} implementation.
+ * The current extra label to display.
*
* @param currentLabel
* the new current label
}
/**
- * Add a listener that will be called on each page change.
+ * Change the page to the next one.
*
- * @param listener
- * the new listener
+ * @return TRUE if it changed
*/
- public void addActionListener(ActionListener listener) {
- listeners.add(listener);
+ public boolean next() {
+ if (setIndex(index + 1)) {
+ fireActionPerformed(PAGE_CHANGED);
+ return true;
+ }
+
+ return false;
}
/**
- * Remove the given listener if possible.
+ * Change the page to the previous one.
*
- * @param listener
- * the listener to remove
- * @return TRUE if it was removed, FALSE if it was not found
+ * @return TRUE if it changed
*/
- public boolean removeActionListener(ActionListener listener) {
- return listeners.remove(listener);
- }
+ public boolean previous() {
+ if (setIndex(index - 1)) {
+ fireActionPerformed(PAGE_CHANGED);
+ return true;
+ }
- /**
- * Remove all the listeners.
- */
- public void clearActionsListeners() {
- listeners.clear();
+ return false;
}
/**
- * Notify a change of page.
+ * Change the page to the first one.
+ *
+ * @return TRUE if it changed
*/
- public void fireEvent() {
- for (ActionListener listener : listeners) {
- try {
- listener.actionPerformed(new ActionEvent(this,
- ActionEvent.ACTION_FIRST, "page changed"));
- } catch (Exception e) {
- Instance.getInstance().getTraceHandler().error(e);
- }
+ public boolean first() {
+ if (setIndex(min)) {
+ fireActionPerformed(PAGE_CHANGED);
+ return true;
}
+
+ return false;
}
/**
- * Create a single navigation button.
+ * Change the page to the last one.
*
- * @param text
- * the text to display
- * @param action
- * the action to take on click
- * @return the button
+ * @return TRUE if it changed
*/
- private JButton createNavButton(String text, ActionListener action) {
- JButton navButton = new JButton(text);
- navButton.addActionListener(action);
- navButton.setForeground(Color.BLUE);
- return navButton;
+ public boolean last() {
+ if (setIndex(max)) {
+ fireActionPerformed(PAGE_CHANGED);
+ return true;
+ }
+
+ return false;
}
/**
* Update the label displayed in the UI.
*/
private void updateLabel() {
- label.setText(computeLabel(index, min, max));
+ label.setText(getExtraLabel());
+ page.setText(Integer.toString(index));
}
/**
* index value.
*/
private void updateEnabled() {
- navButtons[0].setEnabled(index > min);
- navButtons[1].setEnabled(index > min);
- navButtons[2].setEnabled(index < max || max == -1);
- navButtons[3].setEnabled(index < max || max == -1);
- }
-
- /**
- * Return the label to display for the given index.
- * <p>
- * Swing HTML (HTML3) is supported if surrounded by <HTML> and
- * </HTML>.
- * <p>
- * By default, return "Page 1/5: current_label" (with the current index and
- * {@link NavBar#getCurrentLabel()}).
- *
- * @param index
- * the new index number
- * @param mix
- * the minimum index (inclusive)
- * @param max
- * the maximum index (inclusive)
- * @return the label
- */
- protected String computeLabel(int index,
- @SuppressWarnings("unused") int min, int max) {
-
- String base = " <B>Page <SPAN COLOR='#444466'>%d</SPAN> ";
- if (max >= 0) {
- base += "/ %d";
- }
- base += "</B>";
-
- String ifLabel = ": %s";
-
- String display = base;
- String label = getExtraLabel();
- if (label != null && !label.trim().isEmpty()) {
- display += ifLabel;
- }
-
- display = "<HTML>" + display + "</HTML>";
-
- if (max >= 0) {
- return String.format(display, index, max, label);
- }
-
- return String.format(display, index, label);
+ first.setEnabled(index > min);
+ previous.setEnabled(index > min);
+ next.setEnabled(index < max || max == -1);
+ last.setEnabled(index < max || max == -1);
}
}
private boolean zoomSnapWidth = true;
private Rotation rotation = Rotation.NONE;
+ private NavBar navbar;
private JLabel area;
private JScrollPane scroll;
private JTextField page;
JToolBar toolBar = new JToolBar();
// Page navigation
- JButton first = new JButton(
- IconGenerator.get(Icon.arrow_double_left, Size.x32));
- first.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- first();
- }
- });
-
- JButton previous = new JButton(
- IconGenerator.get(Icon.arrow_left, Size.x32));
- previous.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- previous();
- }
- });
-
- page = new JTextField("1");
- page.setPreferredSize(new Dimension(page.getPreferredSize().width * 2,
- page.getPreferredSize().height));
- page.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- try {
- int pageNb = Integer.parseInt(page.getText());
- pageNb--;
- if (pageNb < 0 || pageNb >= images.size()) {
- throw new NumberFormatException("invalid");
- }
- display(pageNb, rotation, true);
- } catch (NumberFormatException nfe) {
- page.setText(Integer.toString(index + 1));
- }
- }
- });
-
- JLabel maxPage = new JLabel(" of " + images.size());
-
- JButton next = new JButton(
- IconGenerator.get(Icon.arrow_right, Size.x32));
- next.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- next();
- }
- });
-
- JButton last = new JButton(
- IconGenerator.get(Icon.arrow_double_right, Size.x32));
- last.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- last();
- }
- });
+ navbar = new NavBar(1, images.size());
// Rotate
JButton left = new JButton(IconGenerator.get(Icon.turn_left, Size.x32));
// Add to toolbar
- toolBar.add(first);
- toolBar.add(previous);
- toolBar.add(page);
- toolBar.add(maxPage);
- toolBar.add(next);
- toolBar.add(last);
+ toolBar.add(navbar);
toolBar.add(sep());
}
private void listen() {
+ navbar.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ index = navbar.getIndex() - 1;
+ display(index, Rotation.NONE, true);
+ }
+ });
area.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
case KeyEvent.VK_DOWN:
if (!scroll(0,
scroll.getViewport().getViewRect().height / 2)) {
- next();
+ navbar.next();
}
break;
case KeyEvent.VK_PAGE_DOWN:
if (!scroll(0, scroll.getViewport().getViewRect().height)) {
- next();
+ navbar.next();
}
break;
case KeyEvent.VK_RIGHT:
if (!scroll(scroll.getViewport().getViewRect().width / 2,
0)) {
- next();
+ navbar.next();
}
break;
case KeyEvent.VK_LEFT:
if (!scroll(-scroll.getViewport().getViewRect().width / 2,
0)) {
- previous();
+ navbar.previous();
}
break;
case KeyEvent.VK_BACK_SPACE:
case KeyEvent.VK_UP:
if (!scroll(0,
-scroll.getViewport().getViewRect().width / 2)) {
- previous();
+ navbar.previous();
}
break;
case KeyEvent.VK_PAGE_UP:
if (!scroll(0, -scroll.getViewport().getViewRect().width)) {
- previous();
+ navbar.previous();
}
break;
case KeyEvent.VK_HOME:
- first();
+ navbar.first();
break;
case KeyEvent.VK_END:
- last();
+ navbar.last();
break;
default:
consume = false;
public void mouseClicked(MouseEvent e) {
super.mouseReleased(e);
if (e.getButton() == MouseEvent.BUTTON1) {
- next();
+ navbar.next();
} else {
- previous();
+ navbar.previous();
}
}
});
return !scroll.getViewport().getViewRect().equals(before);
}
-
- private synchronized void next() {
- index++;
- if (index >= images.size()) {
- index = images.size() - 1;
- } else {
- updatePage();
- display(index, Rotation.NONE, true);
- }
- }
-
- private synchronized void previous() {
- index--;
- if (index < 0) {
- index = 0;
- } else {
- updatePage();
- display(index, Rotation.NONE, true);
- }
- }
-
- private synchronized void first() {
- index = 0;
- updatePage();
- display(index, Rotation.NONE, true);
- }
-
- private synchronized void last() {
- index = images.size() - 1;
- updatePage();
- display(index, Rotation.NONE, true);
- }
-
- private void updatePage() {
- page.setText(Integer.toString(index + 1));
- }
}