1 package be
.nikiroo
.fanfix
.reader
.ui
;
3 import java
.awt
.BorderLayout
;
4 import java
.awt
.Graphics
;
5 import java
.awt
.event
.MouseEvent
;
6 import java
.awt
.event
.MouseListener
;
7 import java
.util
.ArrayList
;
9 import java
.util
.EventListener
;
10 import java
.util
.List
;
12 import javax
.swing
.JLabel
;
13 import javax
.swing
.JPanel
;
15 import be
.nikiroo
.fanfix
.data
.Story
;
16 import be
.nikiroo
.fanfix
.reader
.Reader
;
19 * A book item presented in a {@link GuiReaderFrame}.
23 class GuiReaderBook
extends JPanel
{
25 * Action on a book item.
29 interface BookActionListener
extends EventListener
{
31 * The book was selected (single click).
34 * the {@link GuiReaderBook} itself
36 public void select(GuiReaderBook book
);
39 * The book was double-clicked.
42 * the {@link GuiReaderBook} itself
44 public void action(GuiReaderBook book
);
47 * A popup menu was requested for this {@link GuiReaderBook}.
50 * the {@link GuiReaderBook} itself
52 * the {@link MouseEvent} that generated this call
54 public void popupRequested(GuiReaderBook book
, MouseEvent e
);
57 private static final long serialVersionUID
= 1L;
59 private static final String AUTHOR_COLOR
= "#888888";
60 private static final long doubleClickDelay
= 200; // in ms
64 private boolean selected
;
65 private boolean hovered
;
66 private Date lastClick
;
68 private List
<BookActionListener
> listeners
;
69 private GuiReaderBookInfo info
;
70 private boolean cached
;
71 private boolean seeWordCount
;
74 * Create a new {@link GuiReaderBook} item for the given {@link Story}.
77 * the associated reader
79 * the information about the story to represent
81 * TRUE if it is locally cached
83 * TRUE to see word counts, FALSE to see authors
85 public GuiReaderBook(Reader reader
, GuiReaderBookInfo info
, boolean cached
,
86 boolean seeWordCount
) {
89 this.seeWordCount
= seeWordCount
;
91 icon
= new JLabel(GuiReaderCoverImager
.generateCoverIcon(
92 reader
.getLibrary(), info
));
97 setLayout(new BorderLayout(10, 10));
98 add(icon
, BorderLayout
.CENTER
);
99 add(title
, BorderLayout
.SOUTH
);
105 * The book current selection state.
107 * @return the selection state
109 public boolean isSelected() {
114 * The book current selection state.
116 * Setting this value to true can cause a "select" action to occur if the
117 * previous state was "unselected".
120 * TRUE if it is selected
122 public void setSelected(boolean selected
) {
123 if (this.selected
!= selected
) {
124 this.selected
= selected
;
134 * The item mouse-hover state.
136 * @return TRUE if it is mouse-hovered
138 private boolean isHovered() {
143 * The item mouse-hover state.
146 * TRUE if it is mouse-hovered
148 private void setHovered(boolean hovered
) {
149 if (this.hovered
!= hovered
) {
150 this.hovered
= hovered
;
156 * Setup the mouse listener that will activate {@link BookActionListener}
159 private void setupListeners() {
160 listeners
= new ArrayList
<GuiReaderBook
.BookActionListener
>();
161 addMouseListener(new MouseListener() {
163 public void mouseReleased(MouseEvent e
) {
164 if (isEnabled() && e
.isPopupTrigger()) {
170 public void mousePressed(MouseEvent e
) {
171 if (isEnabled() && e
.isPopupTrigger()) {
177 public void mouseExited(MouseEvent e
) {
182 public void mouseEntered(MouseEvent e
) {
187 public void mouseClicked(MouseEvent e
) {
189 Date now
= new Date();
190 if (lastClick
!= null
191 && now
.getTime() - lastClick
.getTime() < doubleClickDelay
) {
202 private void click(boolean doubleClick
) {
210 private void popup(MouseEvent e
) {
211 for (BookActionListener listener
: listeners
) {
212 listener
.select((GuiReaderBook
.this));
213 listener
.popupRequested(GuiReaderBook
.this, e
);
222 * Add a new {@link BookActionListener} on this item.
227 public void addActionListener(BookActionListener listener
) {
228 listeners
.add(listener
);
232 * Cause an action to occur on this {@link GuiReaderBook}.
234 public void action() {
235 for (BookActionListener listener
: listeners
) {
236 listener
.action(GuiReaderBook
.this);
241 * Cause a select event on this {@link GuiReaderBook}.
243 private void select() {
244 for (BookActionListener listener
: listeners
) {
245 listener
.select(GuiReaderBook
.this);
250 * The information about the book represented by this item.
254 public GuiReaderBookInfo
getInfo() {
259 * This item {@link GuiReader} library cache state.
261 * @return TRUE if it is present in the {@link GuiReader} cache
263 public boolean isCached() {
268 * This item {@link GuiReader} library cache state.
271 * TRUE if it is present in the {@link GuiReader} cache
273 public void setCached(boolean cached
) {
274 if (this.cached
!= cached
) {
275 this.cached
= cached
;
281 * Update the title, paint the item, then call
282 * {@link GuiReaderCoverImager#paintOverlay(Graphics, boolean, boolean, boolean, boolean)}
286 public void paint(Graphics g
) {
289 GuiReaderCoverImager
.paintOverlay(g
, isEnabled(), isSelected(),
290 isHovered(), isCached());
294 * Update the title with the currently registered information.
296 private void updateTitle() {
297 String optSecondary
= info
.getSecondaryInfo(seeWordCount
);
300 + "<body style='width: %d px; height: %d px; text-align: center'>"
301 + "%s" + "<br>" + "<span style='color: %s;'>" + "%s"
302 + "</span>" + "</body>" + "</html>",
303 GuiReaderCoverImager
.TEXT_WIDTH
,
304 GuiReaderCoverImager
.TEXT_HEIGHT
, info
.getMainInfo(),
305 AUTHOR_COLOR
, optSecondary
));