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}.
22 * Can be a story, or a comic or... a group.
26 class GuiReaderBook
extends JPanel
{
28 * Action on a book item.
32 interface BookActionListener
extends EventListener
{
34 * The book was selected (single click).
37 * the {@link GuiReaderBook} itself
39 public void select(GuiReaderBook book
);
42 * The book was double-clicked.
45 * the {@link GuiReaderBook} itself
47 public void action(GuiReaderBook book
);
50 * A popup menu was requested for this {@link GuiReaderBook}.
53 * the {@link GuiReaderBook} itself
55 * the target component for the popup
57 * the X position of the click/request (in case of popup
58 * request from the keyboard, the center of the target is
59 * selected as point of reference)
61 * the Y position of the click/request (in case of popup
62 * request from the keyboard, the center of the target is
63 * selected as point of reference)
65 public void popupRequested(GuiReaderBook book
, Component target
, int x
,
69 private static final long serialVersionUID
= 1L;
71 private static final String AUTHOR_COLOR
= "#888888";
72 private static final long doubleClickDelay
= 200; // in ms
76 private boolean selected
;
77 private boolean hovered
;
78 private Date lastClick
;
80 private List
<BookActionListener
> listeners
;
81 private GuiReaderBookInfo info
;
82 private boolean cached
;
83 private boolean seeWordCount
;
86 * Create a new {@link GuiReaderBook} item for the given {@link Story}.
89 * the associated reader
91 * the information about the story to represent
93 * TRUE if it is locally cached
95 * TRUE to see word counts, FALSE to see authors
97 public GuiReaderBook(Reader reader
, GuiReaderBookInfo info
, boolean cached
,
98 boolean seeWordCount
) {
100 this.cached
= cached
;
101 this.seeWordCount
= seeWordCount
;
103 icon
= new JLabel(GuiReaderCoverImager
.generateCoverIcon(
104 reader
.getLibrary(), info
));
106 title
= new JLabel();
109 setLayout(new BorderLayout(10, 10));
110 add(icon
, BorderLayout
.CENTER
);
111 add(title
, BorderLayout
.SOUTH
);
117 * The book current selection state.
119 * @return the selection state
121 public boolean isSelected() {
126 * The book current selection state.
128 * Setting this value to true can cause a "select" action to occur if the
129 * previous state was "unselected".
132 * TRUE if it is selected
134 public void setSelected(boolean selected
) {
135 if (this.selected
!= selected
) {
136 this.selected
= selected
;
146 * The item mouse-hover state.
148 * @return TRUE if it is mouse-hovered
150 public boolean isHovered() {
155 * The item mouse-hover state.
158 * TRUE if it is mouse-hovered
160 public void setHovered(boolean hovered
) {
161 if (this.hovered
!= hovered
) {
162 this.hovered
= hovered
;
168 * Setup the mouse listener that will activate {@link BookActionListener}
171 private void setupListeners() {
172 listeners
= new ArrayList
<GuiReaderBook
.BookActionListener
>();
173 addMouseListener(new MouseListener() {
175 public void mouseReleased(MouseEvent e
) {
176 if (isEnabled() && e
.isPopupTrigger()) {
182 public void mousePressed(MouseEvent e
) {
183 if (isEnabled() && e
.isPopupTrigger()) {
189 public void mouseExited(MouseEvent e
) {
194 public void mouseEntered(MouseEvent e
) {
199 public void mouseClicked(MouseEvent e
) {
201 Date now
= new Date();
202 if (lastClick
!= null
203 && now
.getTime() - lastClick
.getTime() < doubleClickDelay
) {
214 private void click(boolean doubleClick
) {
222 private void popup(MouseEvent e
) {
224 .popup(GuiReaderBook
.this, e
.getX(), e
.getY());
231 * Add a new {@link BookActionListener} on this item.
236 public void addActionListener(BookActionListener listener
) {
237 listeners
.add(listener
);
241 * Cause an action to occur on this {@link GuiReaderBook}.
243 public void action() {
244 for (BookActionListener listener
: listeners
) {
245 listener
.action(GuiReaderBook
.this);
250 * Cause a select event on this {@link GuiReaderBook}.
252 * Have a look at {@link GuiReaderBook#setSelected(boolean)}.
254 private void select() {
255 for (BookActionListener listener
: listeners
) {
256 listener
.select(GuiReaderBook
.this);
264 * the target component for the popup
266 * the X position of the click/request (in case of popup request
267 * from the keyboard, the center of the target should be selected
268 * as point of reference)
270 * the Y position of the click/request (in case of popup request
271 * from the keyboard, the center of the target should be selected
272 * as point of reference)
274 public void popup(Component target
, int x
, int y
) {
275 for (BookActionListener listener
: listeners
) {
276 listener
.select((GuiReaderBook
.this));
277 listener
.popupRequested(GuiReaderBook
.this, target
, x
, y
);
282 * The information about the book represented by this item.
286 public GuiReaderBookInfo
getInfo() {
291 * This item {@link GuiReader} library cache state.
293 * @return TRUE if it is present in the {@link GuiReader} cache
295 public boolean isCached() {
300 * This item {@link GuiReader} library cache state.
303 * TRUE if it is present in the {@link GuiReader} cache
305 public void setCached(boolean cached
) {
306 if (this.cached
!= cached
) {
307 this.cached
= cached
;
313 * Update the title, paint the item, then call
314 * {@link GuiReaderCoverImager#paintOverlay(Graphics, boolean, boolean, boolean, boolean)}
318 public void paint(Graphics g
) {
321 GuiReaderCoverImager
.paintOverlay(g
, isEnabled(), isSelected(),
322 isHovered(), isCached());
326 * Update the title with the currently registered information.
328 private void updateTitle() {
329 String optSecondary
= info
.getSecondaryInfo(seeWordCount
);
332 + "<body style='width: %d px; height: %d px; text-align: center'>"
333 + "%s" + "<br>" + "<span style='color: %s;'>" + "%s"
334 + "</span>" + "</body>" + "</html>",
335 GuiReaderCoverImager
.TEXT_WIDTH
,
336 GuiReaderCoverImager
.TEXT_HEIGHT
, info
.getMainInfo(),
337 AUTHOR_COLOR
, optSecondary
));