1 package be
.nikiroo
.fanfix
.reader
;
3 import java
.awt
.BorderLayout
;
5 import java
.awt
.Graphics
;
6 import java
.awt
.Graphics2D
;
7 import java
.awt
.Polygon
;
8 import java
.awt
.Rectangle
;
9 import java
.awt
.event
.MouseEvent
;
10 import java
.awt
.event
.MouseListener
;
11 import java
.awt
.image
.BufferedImage
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Date
;
14 import java
.util
.EventListener
;
15 import java
.util
.List
;
17 import javax
.swing
.ImageIcon
;
18 import javax
.swing
.JLabel
;
19 import javax
.swing
.JPanel
;
21 import be
.nikiroo
.fanfix
.data
.MetaData
;
24 * A book item presented in a {@link LocalReaderFrame}.
28 class LocalReaderBook
extends JPanel
{
30 * Action on a book item.
34 interface BookActionListener
extends EventListener
{
36 * The book was selected (single click).
39 * the {@link LocalReaderBook} itself
41 public void select(LocalReaderBook book
);
44 * The book was double-clicked.
47 * the {@link LocalReaderBook} itself
49 public void action(LocalReaderBook book
);
52 private static final int COVER_WIDTH
= 100;
53 private static final int COVER_HEIGHT
= 150;
54 private static final int SPINE_WIDTH
= 5;
55 private static final int SPINE_HEIGHT
= 5;
56 private static final int HOFFSET
= 20;
57 private static final Color SPINE_COLOR_BOTTOM
= new Color(180, 180, 180);
58 private static final Color SPINE_COLOR_RIGHT
= new Color(100, 100, 100);
59 private static final int TEXT_WIDTH
= COVER_WIDTH
+ 40;
60 private static final int TEXT_HEIGHT
= 50;
61 private static final String AUTHOR_COLOR
= "#888888";
62 private static final long serialVersionUID
= 1L;
66 private boolean selected
;
67 private boolean hovered
;
68 private Date lastClick
;
69 private long doubleClickDelay
= 200; // in ms
70 private List
<BookActionListener
> listeners
;
72 private boolean cached
;
74 public LocalReaderBook(MetaData meta
, boolean cached
) {
75 this.luid
= meta
.getLuid();
78 if (meta
.getCover() != null) {
79 BufferedImage resizedImage
= new BufferedImage(SPINE_WIDTH
80 + COVER_WIDTH
, SPINE_HEIGHT
+ COVER_HEIGHT
+ HOFFSET
,
81 BufferedImage
.TYPE_4BYTE_ABGR
);
82 Graphics2D g
= resizedImage
.createGraphics();
83 g
.setColor(Color
.white
);
84 g
.fillRect(0, HOFFSET
, COVER_WIDTH
, COVER_HEIGHT
);
85 g
.drawImage(meta
.getCover(), 0, HOFFSET
, COVER_WIDTH
, COVER_HEIGHT
,
89 icon
= new JLabel(new ImageIcon(resizedImage
));
91 // TODO: a big black "X" ?
92 icon
= new JLabel(" [ no cover ] ");
95 String optAuthor
= meta
.getAuthor();
96 if (optAuthor
!= null && !optAuthor
.isEmpty()) {
97 optAuthor
= "(" + optAuthor
+ ")";
102 + "<body style='width: %d px; height: %d px; text-align: center'>"
103 + "%s" + "<br>" + "<span style='color: %s;'>"
104 + "%s" + "</span>" + "</body>" + "</html>",
105 TEXT_WIDTH
, TEXT_HEIGHT
, meta
.getTitle(), AUTHOR_COLOR
,
108 this.setLayout(new BorderLayout(10, 10));
109 this.add(icon
, BorderLayout
.CENTER
);
110 this.add(title
, BorderLayout
.SOUTH
);
117 * The book current selection state.
119 * @return the selected
121 public boolean isSelected() {
126 * The book current selection state.
129 * the selected to set
131 public void setSelected(boolean selected
) {
132 this.selected
= selected
;
136 private void setHovered(boolean hovered
) {
137 this.hovered
= hovered
;
141 private void setupListeners() {
142 listeners
= new ArrayList
<LocalReaderBook
.BookActionListener
>();
143 addMouseListener(new MouseListener() {
144 public void mouseReleased(MouseEvent e
) {
147 public void mousePressed(MouseEvent e
) {
150 public void mouseExited(MouseEvent e
) {
154 public void mouseEntered(MouseEvent e
) {
158 public void mouseClicked(MouseEvent e
) {
160 Date now
= new Date();
161 if (lastClick
!= null
162 && now
.getTime() - lastClick
.getTime() < doubleClickDelay
) {
173 private void click(boolean doubleClick
) {
174 for (BookActionListener listener
: listeners
) {
176 listener
.action(this);
178 listener
.select(this);
183 public void addActionListener(BookActionListener listener
) {
184 listeners
.add(listener
);
187 public String
getLuid() {
192 * This boos is cached into the {@link LocalReader} library.
196 public boolean isCached() {
201 * This boos is cached into the {@link LocalReader} library.
206 public void setCached(boolean cached
) {
207 this.cached
= cached
;
211 public void paint(Graphics g
) {
214 int h
= COVER_HEIGHT
;
216 int xOffset
= (TEXT_WIDTH
- COVER_WIDTH
) - 4;
218 int[] xs
= new int[] { xOffset
, xOffset
+ SPINE_WIDTH
,
219 xOffset
+ w
+ SPINE_WIDTH
, xOffset
+ w
};
220 int[] ys
= new int[] { HOFFSET
+ h
, HOFFSET
+ h
+ SPINE_HEIGHT
,
221 HOFFSET
+ h
+ SPINE_HEIGHT
, HOFFSET
+ h
};
222 g
.setColor(SPINE_COLOR_BOTTOM
);
223 g
.fillPolygon(new Polygon(xs
, ys
, xs
.length
));
224 xs
= new int[] { xOffset
+ w
, xOffset
+ w
+ SPINE_WIDTH
,
225 xOffset
+ w
+ SPINE_WIDTH
, xOffset
+ w
};
226 ys
= new int[] { HOFFSET
, HOFFSET
+ SPINE_HEIGHT
,
227 HOFFSET
+ h
+ SPINE_HEIGHT
, HOFFSET
+ h
};
228 g
.setColor(SPINE_COLOR_RIGHT
);
229 g
.fillPolygon(new Polygon(xs
, ys
, xs
.length
));
231 Color color
= new Color(255, 255, 255, 0);
233 } else if (selected
&& !hovered
) {
234 color
= new Color(80, 80, 100, 40);
235 } else if (!selected
&& hovered
) {
236 color
= new Color(230, 230, 255, 100);
237 } else if (selected
&& hovered
) {
238 color
= new Color(200, 200, 255, 100);
241 Rectangle clip
= g
.getClipBounds();
243 g
.setColor(Color
.green
);
244 g
.fillOval(clip
.x
+ clip
.width
- 30, 10, 20, 20);
248 g
.fillRect(clip
.x
, clip
.y
, clip
.width
, clip
.height
);