package be.nikiroo.fanfix.reader.ui;
import java.awt.BorderLayout;
+import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
-import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Story;
import be.nikiroo.fanfix.reader.Reader;
/**
* A book item presented in a {@link GuiReaderFrame}.
+ * <p>
+ * Can be a story, or a comic or... a group.
*
* @author niki
*/
*
* @param book
* the {@link GuiReaderBook} itself
- * @param e
- * the {@link MouseEvent} that generated this call
+ * @param target
+ * the target component for the popup
+ * @param x
+ * the X position of the click/request (in case of popup
+ * request from the keyboard, the center of the target is
+ * selected as point of reference)
+ * @param y
+ * the Y position of the click/request (in case of popup
+ * request from the keyboard, the center of the target is
+ * selected as point of reference)
*/
- public void popupRequested(GuiReaderBook book, MouseEvent e);
+ public void popupRequested(GuiReaderBook book, Component target, int x,
+ int y);
}
private static final long serialVersionUID = 1L;
private Date lastClick;
private List<BookActionListener> listeners;
- private MetaData meta;
+ private GuiReaderBookInfo info;
private boolean cached;
+ private boolean seeWordCount;
/**
* Create a new {@link GuiReaderBook} item for the given {@link Story}.
*
* @param reader
* the associated reader
- * @param meta
- * the story {@link MetaData} or source (if no LUID)
+ * @param info
+ * the information about the story to represent
* @param cached
* TRUE if it is locally cached
* @param seeWordCount
* TRUE to see word counts, FALSE to see authors
*/
- public GuiReaderBook(Reader reader, MetaData meta, boolean cached,
+ public GuiReaderBook(Reader reader, GuiReaderBookInfo info, boolean cached,
boolean seeWordCount) {
+ this.info = info;
this.cached = cached;
- this.meta = meta;
-
- String optSecondary = meta.getAuthor();
- if (seeWordCount) {
- if (meta.getWords() >= 4000) {
- optSecondary = "" + (meta.getWords() / 1000) + "k";
- } else if (meta.getWords() > 0) {
- optSecondary = "" + meta.getWords();
- } else {
- optSecondary = "";
- }
-
- if (!optSecondary.isEmpty()) {
- if (meta.isImageDocument()) {
- optSecondary += " images";
- } else {
- optSecondary += " words";
- }
- }
- }
-
- if (optSecondary != null && !optSecondary.isEmpty()) {
- optSecondary = "(" + optSecondary + ")";
- } else {
- optSecondary = "";
- }
+ this.seeWordCount = seeWordCount;
icon = new JLabel(GuiReaderCoverImager.generateCoverIcon(
- reader.getLibrary(), getMeta()));
- title = new JLabel(
- String.format(
- "<html>"
- + "<body style='width: %d px; height: %d px; text-align: center'>"
- + "%s" + "<br>" + "<span style='color: %s;'>"
- + "%s" + "</span>" + "</body>" + "</html>",
- GuiReaderCoverImager.TEXT_WIDTH,
- GuiReaderCoverImager.TEXT_HEIGHT, meta.getTitle(),
- AUTHOR_COLOR, optSecondary));
+ reader.getLibrary(), info));
+
+ title = new JLabel();
+ updateTitle();
setLayout(new BorderLayout(10, 10));
add(icon, BorderLayout.CENTER);
/**
* The book current selection state.
+ * <p>
+ * Setting this value to true can cause a "select" action to occur if the
+ * previous state was "unselected".
*
* @param selected
* TRUE if it is selected
if (this.selected != selected) {
this.selected = selected;
repaint();
+
+ if (selected) {
+ select();
+ }
}
}
*
* @return TRUE if it is mouse-hovered
*/
- private boolean isHovered() {
+ public boolean isHovered() {
return this.hovered;
}
* @param hovered
* TRUE if it is mouse-hovered
*/
- private void setHovered(boolean hovered) {
+ public void setHovered(boolean hovered) {
if (this.hovered != hovered) {
this.hovered = hovered;
repaint();
addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
- if (e.isPopupTrigger()) {
+ if (isEnabled() && e.isPopupTrigger()) {
popup(e);
}
}
@Override
public void mousePressed(MouseEvent e) {
- if (e.isPopupTrigger()) {
+ if (isEnabled() && e.isPopupTrigger()) {
popup(e);
}
}
}
lastClick = now;
+ e.consume();
}
}
private void click(boolean doubleClick) {
- for (BookActionListener listener : listeners) {
- if (doubleClick) {
- listener.action(GuiReaderBook.this);
- } else {
- listener.select(GuiReaderBook.this);
- }
+ if (doubleClick) {
+ action();
+ } else {
+ select();
}
}
private void popup(MouseEvent e) {
- for (BookActionListener listener : listeners) {
- listener.select((GuiReaderBook.this));
- listener.popupRequested(GuiReaderBook.this, e);
- }
+ GuiReaderBook.this
+ .popup(GuiReaderBook.this, e.getX(), e.getY());
+ e.consume();
}
});
}
}
/**
- * The Library {@link MetaData} of the book represented by this item.
+ * Cause an action to occur on this {@link GuiReaderBook}.
+ */
+ public void action() {
+ for (BookActionListener listener : listeners) {
+ listener.action(GuiReaderBook.this);
+ }
+ }
+
+ /**
+ * Cause a select event on this {@link GuiReaderBook}.
+ * <p>
+ * Have a look at {@link GuiReaderBook#setSelected(boolean)}.
+ */
+ private void select() {
+ for (BookActionListener listener : listeners) {
+ listener.select(GuiReaderBook.this);
+ }
+ }
+
+ /**
+ * Request a popup.
+ *
+ * @param target
+ * the target component for the popup
+ * @param x
+ * the X position of the click/request (in case of popup request
+ * from the keyboard, the center of the target should be selected
+ * as point of reference)
+ * @param y
+ * the Y position of the click/request (in case of popup request
+ * from the keyboard, the center of the target should be selected
+ * as point of reference)
+ */
+ public void popup(Component target, int x, int y) {
+ for (BookActionListener listener : listeners) {
+ listener.select((GuiReaderBook.this));
+ listener.popupRequested(GuiReaderBook.this, target, x, y);
+ }
+ }
+
+ /**
+ * The information about the book represented by this item.
*
* @return the meta
*/
- public MetaData getMeta() {
- return meta;
+ public GuiReaderBookInfo getInfo() {
+ return info;
}
/**
}
/**
- * Paint the item, then call {@link GuiReaderBook#paintOverlay(Graphics)}.
+ * Update the title, paint the item, then call
+ * {@link GuiReaderCoverImager#paintOverlay(Graphics, boolean, boolean, boolean, boolean)}
+ * .
*/
@Override
public void paint(Graphics g) {
+ updateTitle();
super.paint(g);
GuiReaderCoverImager.paintOverlay(g, isEnabled(), isSelected(),
isHovered(), isCached());
}
+
+ /**
+ * Update the title with the currently registered information.
+ */
+ private void updateTitle() {
+ String optSecondary = info.getSecondaryInfo(seeWordCount);
+ title.setText(String
+ .format("<html>"
+ + "<body style='width: %d px; height: %d px; text-align: center'>"
+ + "%s" + "<br>" + "<span style='color: %s;'>" + "%s"
+ + "</span>" + "</body>" + "</html>",
+ GuiReaderCoverImager.TEXT_WIDTH,
+ GuiReaderCoverImager.TEXT_HEIGHT, info.getMainInfo(),
+ AUTHOR_COLOR, optSecondary));
+ }
}