1 package be
.nikiroo
.fanfix
.reader
.ui
;
3 import java
.awt
.BorderLayout
;
4 import java
.awt
.Component
;
5 import java
.awt
.Graphics
;
6 import java
.awt
.event
.MouseEvent
;
7 import java
.awt
.event
.MouseListener
;
8 import java
.util
.ArrayList
;
10 import java
.util
.EventListener
;
11 import java
.util
.List
;
13 import javax
.swing
.JLabel
;
14 import javax
.swing
.JPanel
;
16 import be
.nikiroo
.fanfix
.data
.Story
;
17 import be
.nikiroo
.fanfix
.reader
.Reader
;
20 * A book item presented in a {@link GuiReaderFrame}.
24 class GuiReaderBook
extends JPanel
{
26 * Action on a book item.
30 interface BookActionListener
extends EventListener
{
32 * The book was selected (single click).
35 * the {@link GuiReaderBook} itself
37 public void select(GuiReaderBook book
);
40 * The book was double-clicked.
43 * the {@link GuiReaderBook} itself
45 public void action(GuiReaderBook book
);
48 * A popup menu was requested for this {@link GuiReaderBook}.
51 * the {@link GuiReaderBook} itself
53 * the target component for the popup
55 * the X position of the click/request (in case of popup
56 * request from the keyboard, the center of the target is
57 * selected as point of reference)
59 * the Y position of the click/request (in case of popup
60 * request from the keyboard, the center of the target is
61 * selected as point of reference)
63 public void popupRequested(GuiReaderBook book
, Component target
, int x
,
67 private static final long serialVersionUID
= 1L;
69 private static final String AUTHOR_COLOR
= "#888888";
70 private static final long doubleClickDelay
= 200; // in ms
74 private boolean selected
;
75 private boolean hovered
;
76 private Date lastClick
;
78 private List
<BookActionListener
> listeners
;
79 private GuiReaderBookInfo info
;
80 private boolean cached
;
81 private boolean seeWordCount
;
84 * Create a new {@link GuiReaderBook} item for the given {@link Story}.
87 * the associated reader
89 * the information about the story to represent
91 * TRUE if it is locally cached
93 * TRUE to see word counts, FALSE to see authors
95 public GuiReaderBook(Reader reader
, GuiReaderBookInfo info
, boolean cached
,
96 boolean seeWordCount
) {
99 this.seeWordCount
= seeWordCount
;
101 icon
= new JLabel(GuiReaderCoverImager
.generateCoverIcon(
102 reader
.getLibrary(), info
));
104 title
= new JLabel();
107 setLayout(new BorderLayout(10, 10));
108 add(icon
, BorderLayout
.CENTER
);
109 add(title
, BorderLayout
.SOUTH
);
115 * The book current selection state.
117 * @return the selection state
119 public boolean isSelected() {
124 * The book current selection state.
126 * Setting this value to true can cause a "select" action to occur if the
127 * previous state was "unselected".
130 * TRUE if it is selected
132 public void setSelected(boolean selected
) {
133 if (this.selected
!= selected
) {
134 this.selected
= selected
;
144 * The item mouse-hover state.
146 * @return TRUE if it is mouse-hovered
148 public boolean isHovered() {
153 * The item mouse-hover state.
156 * TRUE if it is mouse-hovered
158 public void setHovered(boolean hovered
) {
159 if (this.hovered
!= hovered
) {
160 this.hovered
= hovered
;
166 * Setup the mouse listener that will activate {@link BookActionListener}
169 private void setupListeners() {
170 listeners
= new ArrayList
<GuiReaderBook
.BookActionListener
>();
171 addMouseListener(new MouseListener() {
173 public void mouseReleased(MouseEvent e
) {
174 if (isEnabled() && e
.isPopupTrigger()) {
180 public void mousePressed(MouseEvent e
) {
181 if (isEnabled() && e
.isPopupTrigger()) {
187 public void mouseExited(MouseEvent e
) {
192 public void mouseEntered(MouseEvent e
) {
197 public void mouseClicked(MouseEvent e
) {
199 Date now
= new Date();
200 if (lastClick
!= null
201 && now
.getTime() - lastClick
.getTime() < doubleClickDelay
) {
212 private void click(boolean doubleClick
) {
220 private void popup(MouseEvent e
) {
222 .popup(GuiReaderBook
.this, e
.getX(), e
.getY());
229 * Add a new {@link BookActionListener} on this item.
234 public void addActionListener(BookActionListener listener
) {
235 listeners
.add(listener
);
239 * Cause an action to occur on this {@link GuiReaderBook}.
241 public void action() {
242 for (BookActionListener listener
: listeners
) {
243 listener
.action(GuiReaderBook
.this);
248 * Cause a select event on this {@link GuiReaderBook}.
250 * Have a look at {@link GuiReaderBook#setSelected(boolean)}.
252 private void select() {
253 for (BookActionListener listener
: listeners
) {
254 listener
.select(GuiReaderBook
.this);
262 * the target component for the popup
264 * the X position of the click/request (in case of popup request
265 * from the keyboard, the center of the target should be selected
266 * as point of reference)
268 * the Y position of the click/request (in case of popup request
269 * from the keyboard, the center of the target should be selected
270 * as point of reference)
272 public void popup(Component target
, int x
, int y
) {
273 for (BookActionListener listener
: listeners
) {
274 listener
.select((GuiReaderBook
.this));
275 listener
.popupRequested(GuiReaderBook
.this, target
, x
, y
);
280 * The information about the book represented by this item.
284 public GuiReaderBookInfo
getInfo() {
289 * This item {@link GuiReader} library cache state.
291 * @return TRUE if it is present in the {@link GuiReader} cache
293 public boolean isCached() {
298 * This item {@link GuiReader} library cache state.
301 * TRUE if it is present in the {@link GuiReader} cache
303 public void setCached(boolean cached
) {
304 if (this.cached
!= cached
) {
305 this.cached
= cached
;
311 * Update the title, paint the item, then call
312 * {@link GuiReaderCoverImager#paintOverlay(Graphics, boolean, boolean, boolean, boolean)}
316 public void paint(Graphics g
) {
319 GuiReaderCoverImager
.paintOverlay(g
, isEnabled(), isSelected(),
320 isHovered(), isCached());
324 * Update the title with the currently registered information.
326 private void updateTitle() {
327 String optSecondary
= info
.getSecondaryInfo(seeWordCount
);
330 + "<body style='width: %d px; height: %d px; text-align: center'>"
331 + "%s" + "<br>" + "<span style='color: %s;'>" + "%s"
332 + "</span>" + "</body>" + "</html>",
333 GuiReaderCoverImager
.TEXT_WIDTH
,
334 GuiReaderCoverImager
.TEXT_HEIGHT
, info
.getMainInfo(),
335 AUTHOR_COLOR
, optSecondary
));