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
.MetaData
;
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 {@link MouseEvent} that generated this call
55 public void popupRequested(GuiReaderBook book
, MouseEvent e
);
58 private static final long serialVersionUID
= 1L;
60 private static final String AUTHOR_COLOR
= "#888888";
61 private static final long doubleClickDelay
= 200; // in ms
65 private boolean selected
;
66 private boolean hovered
;
67 private Date lastClick
;
69 private List
<BookActionListener
> listeners
;
70 private MetaData meta
;
71 private boolean cached
;
74 * Create a new {@link GuiReaderBook} item for the given {@link Story}.
77 * the associated reader
79 * the story {@link MetaData} or source (if no LUID)
81 * TRUE if it is locally cached
83 * TRUE to see word counts, FALSE to see authors
85 public GuiReaderBook(Reader reader
, MetaData meta
, boolean cached
,
86 boolean seeWordCount
) {
90 String optSecondary
= meta
.getAuthor();
92 if (meta
.getWords() >= 4000) {
93 optSecondary
= "" + (meta
.getWords() / 1000) + "k";
94 } else if (meta
.getWords() > 0) {
95 optSecondary
= "" + meta
.getWords();
100 if (!optSecondary
.isEmpty()) {
101 if (meta
.isImageDocument()) {
102 optSecondary
+= " images";
104 optSecondary
+= " words";
109 if (optSecondary
!= null && !optSecondary
.isEmpty()) {
110 optSecondary
= "(" + optSecondary
+ ")";
115 icon
= new JLabel(GuiReaderCoverImager
.generateCoverIcon(
116 reader
.getLibrary(), getMeta()));
120 + "<body style='width: %d px; height: %d px; text-align: center'>"
121 + "%s" + "<br>" + "<span style='color: %s;'>"
122 + "%s" + "</span>" + "</body>" + "</html>",
123 GuiReaderCoverImager
.TEXT_WIDTH
,
124 GuiReaderCoverImager
.TEXT_HEIGHT
, meta
.getTitle(),
125 AUTHOR_COLOR
, optSecondary
));
127 setLayout(new BorderLayout(10, 10));
128 add(icon
, BorderLayout
.CENTER
);
129 add(title
, BorderLayout
.SOUTH
);
135 * The book current selection state.
137 * @return the selection state
139 public boolean isSelected() {
144 * The book current selection state.
147 * TRUE if it is selected
149 public void setSelected(boolean selected
) {
150 if (this.selected
!= selected
) {
151 this.selected
= selected
;
157 * The item mouse-hover state.
159 * @return TRUE if it is mouse-hovered
161 private boolean isHovered() {
166 * The item mouse-hover state.
169 * TRUE if it is mouse-hovered
171 private void setHovered(boolean hovered
) {
172 if (this.hovered
!= hovered
) {
173 this.hovered
= hovered
;
179 * Setup the mouse listener that will activate {@link BookActionListener}
182 private void setupListeners() {
183 listeners
= new ArrayList
<GuiReaderBook
.BookActionListener
>();
184 addMouseListener(new MouseListener() {
186 public void mouseReleased(MouseEvent e
) {
187 if (e
.isPopupTrigger()) {
193 public void mousePressed(MouseEvent e
) {
194 if (e
.isPopupTrigger()) {
200 public void mouseExited(MouseEvent e
) {
205 public void mouseEntered(MouseEvent e
) {
210 public void mouseClicked(MouseEvent e
) {
212 Date now
= new Date();
213 if (lastClick
!= null
214 && now
.getTime() - lastClick
.getTime() < doubleClickDelay
) {
224 private void click(boolean doubleClick
) {
225 for (BookActionListener listener
: listeners
) {
227 listener
.action(GuiReaderBook
.this);
229 listener
.select(GuiReaderBook
.this);
234 private void popup(MouseEvent e
) {
235 for (BookActionListener listener
: listeners
) {
236 listener
.select((GuiReaderBook
.this));
237 listener
.popupRequested(GuiReaderBook
.this, e
);
244 * Add a new {@link BookActionListener} on this item.
249 public void addActionListener(BookActionListener listener
) {
250 listeners
.add(listener
);
254 * The Library {@link MetaData} of the book represented by this item.
258 public MetaData
getMeta() {
263 * This item {@link GuiReader} library cache state.
265 * @return TRUE if it is present in the {@link GuiReader} cache
267 public boolean isCached() {
272 * This item {@link GuiReader} library cache state.
275 * TRUE if it is present in the {@link GuiReader} cache
277 public void setCached(boolean cached
) {
278 if (this.cached
!= cached
) {
279 this.cached
= cached
;
285 * Paint the item, then call {@link GuiReaderBook#paintOverlay(Graphics)}.
288 public void paint(Graphics g
) {
290 GuiReaderCoverImager
.paintOverlay(g
, isEnabled(), isSelected(),
291 isHovered(), isCached());