1 package be
.nikiroo
.fanfix_swing
.gui
.book
;
4 import java
.awt
.Graphics
;
5 import java
.awt
.Graphics2D
;
6 import java
.awt
.Polygon
;
7 import java
.awt
.Rectangle
;
8 import java
.awt
.image
.BufferedImage
;
9 import java
.io
.ByteArrayInputStream
;
10 import java
.io
.ByteArrayOutputStream
;
11 import java
.io
.IOException
;
12 import java
.io
.InputStream
;
13 import java
.net
.MalformedURLException
;
15 import javax
.imageio
.ImageIO
;
17 import be
.nikiroo
.fanfix
.Instance
;
18 import be
.nikiroo
.fanfix
.data
.MetaData
;
19 import be
.nikiroo
.fanfix
.library
.BasicLibrary
;
20 import be
.nikiroo
.fanfix
.reader
.ui
.GuiReaderBookInfo
;
21 import be
.nikiroo
.utils
.Image
;
22 import be
.nikiroo
.utils
.ui
.ImageUtilsAwt
;
23 import be
.nikiroo
.utils
.ui
.UIUtils
;
26 * This class can create a cover icon ready to use for the graphical
31 class BookCoverImager
{
32 // TODO: export some of the configuration options?
33 static final int COVER_WIDTH
= 100;
34 static final int COVER_HEIGHT
= 150;
35 static final int SPINE_WIDTH
= 5;
36 static final int SPINE_HEIGHT
= 5;
37 static final int HOFFSET
= 20;
38 static final Color SPINE_COLOR_BOTTOM
= new Color(180, 180, 180);
39 static final Color SPINE_COLOR_RIGHT
= new Color(100, 100, 100);
40 static final Color BORDER
= Color
.black
;
42 public static final Color UNCACHED_ICON_COLOR
= Color
.green
.darker();
43 // new Color(0, 80, 220);
45 public static final int TEXT_HEIGHT
= 50;
46 public static final int TEXT_WIDTH
= COVER_WIDTH
+ 40;
50 static public Color
getBackground(boolean enabled
, boolean selected
, boolean hovered
) {
51 Color color
= new Color(255, 255, 255, 0);
53 } else if (selected
&& !hovered
) {
54 color
= new Color(80, 80, 100, 40);
55 } else if (!selected
&& hovered
) {
56 color
= new Color(230, 230, 255, 100);
57 } else if (selected
&& hovered
) {
58 color
= new Color(200, 200, 255, 100);
65 * Draw a partially transparent overlay if needed depending upon the selection
66 * and mouse-hover states on top of the normal component, as well as a possible
67 * "cached" icon if the item is cached.
69 * @param g the {@link Graphics} to paint onto
70 * @param enabled draw an enabled overlay
71 * @param selected draw a selected overlay
72 * @param hovered draw a hovered overlay
73 * @param cached draw a non-cached overlay if needed
75 static public void paintOverlay(Graphics g
, boolean enabled
, boolean selected
, boolean hovered
, boolean cached
) {
76 Rectangle clip
= g
.getClipBounds();
77 if (clip
.getWidth() <= 0 || clip
.getHeight() <= 0) {
83 int xOffset
= (TEXT_WIDTH
- COVER_WIDTH
) - 1;
84 int yOffset
= HOFFSET
;
89 g
.drawRect(xOffset
, yOffset
, COVER_WIDTH
, COVER_HEIGHT
);
96 int[] xs
= new int[] { xOffset
, xOffset
+ SPINE_WIDTH
, xOffset
+ w
+ SPINE_WIDTH
, xOffset
+ w
};
97 int[] ys
= new int[] { yOffset
+ h
, yOffset
+ h
+ SPINE_HEIGHT
, yOffset
+ h
+ SPINE_HEIGHT
, yOffset
+ h
};
98 g
.setColor(SPINE_COLOR_BOTTOM
);
99 g
.fillPolygon(new Polygon(xs
, ys
, xs
.length
));
100 xs
= new int[] { xOffset
+ w
, xOffset
+ w
+ SPINE_WIDTH
, xOffset
+ w
+ SPINE_WIDTH
, xOffset
+ w
};
101 ys
= new int[] { yOffset
, yOffset
+ SPINE_HEIGHT
, yOffset
+ h
+ SPINE_HEIGHT
, yOffset
+ h
};
102 g
.setColor(SPINE_COLOR_RIGHT
);
103 g
.fillPolygon(new Polygon(xs
, ys
, xs
.length
));
105 Color color
= getBackground(enabled
, selected
, hovered
);
108 g
.fillRect(clip
.x
, clip
.y
, clip
.width
, clip
.height
);
110 UIUtils
.drawEllipse3D(g
, UNCACHED_ICON_COLOR
, COVER_WIDTH
+ HOFFSET
+ 30, 10, 20, 20, cached
);
114 * Generate a cover icon based upon the given {@link MetaData}.
116 * @param lib the library the meta comes from
117 * @param meta the {@link MetaData}
121 static public java
.awt
.Image
generateCoverImage(BasicLibrary lib
, MetaData meta
) {
122 return generateCoverImage(lib
, BookInfo
.fromMeta(lib
, meta
));
126 * The width of a cover image.
130 static public int getCoverWidth() {
131 return SPINE_WIDTH
+ COVER_WIDTH
;
135 * The height of a cover image.
139 static public int getCoverHeight() {
140 return COVER_HEIGHT
+ HOFFSET
;
144 * Generate a cover icon based upon the given {@link GuiReaderBookInfo}.
146 * @param lib the library the meta comes from (can be NULL)
147 * @param info the {@link GuiReaderBookInfo}
151 static public java
.awt
.Image
generateCoverImage(BasicLibrary lib
, BookInfo info
) {
152 BufferedImage resizedImage
= null;
153 String id
= getIconId(info
);
155 InputStream in
= Instance
.getInstance().getCache().getFromCache(id
);
158 resizedImage
= ImageUtilsAwt
.fromImage(new Image(in
));
161 } catch (IOException e
) {
162 Instance
.getInstance().getTraceHandler().error(e
);
166 if (resizedImage
== null) {
170 cover
= info
.getBaseImage(lib
);
173 resizedImage
= new BufferedImage(getCoverWidth(), getCoverHeight(), BufferedImage
.TYPE_4BYTE_ABGR
);
175 Graphics2D g
= resizedImage
.createGraphics();
177 g
.setColor(Color
.white
);
178 g
.fillRect(0, HOFFSET
, COVER_WIDTH
, COVER_HEIGHT
);
181 BufferedImage coverb
= ImageUtilsAwt
.fromImage(cover
);
182 g
.drawImage(coverb
, 0, HOFFSET
, COVER_WIDTH
, COVER_HEIGHT
, null);
184 g
.setColor(Color
.black
);
185 g
.drawLine(0, HOFFSET
, COVER_WIDTH
, HOFFSET
+ COVER_HEIGHT
);
186 g
.drawLine(COVER_WIDTH
, HOFFSET
, 0, HOFFSET
+ COVER_HEIGHT
);
192 // Only save image with a cover, not the X thing
193 if (id
!= null && cover
!= null) {
194 ByteArrayOutputStream out
= new ByteArrayOutputStream();
195 ImageIO
.write(resizedImage
, "png", out
);
196 byte[] imageBytes
= out
.toByteArray();
197 in
= new ByteArrayInputStream(imageBytes
);
198 Instance
.getInstance().getCache().addToCache(in
, id
);
202 } catch (MalformedURLException e
) {
203 Instance
.getInstance().getTraceHandler().error(e
);
204 } catch (IOException e
) {
205 Instance
.getInstance().getTraceHandler().error(e
);
213 * Manually clear the icon set for this item.
215 * @param info the info about the story or source/type or author
217 static public void clearIcon(BookInfo info
) {
218 String id
= getIconId(info
);
219 Instance
.getInstance().getCache().removeFromCache(id
);
223 * Get a unique ID from this {@link GuiReaderBookInfo} (note that it can be a
224 * story, a fake item for a source/type or a fake item for an author).
226 * @param info the info or NULL for a generic (non unique!) ID
227 * @return the unique ID
229 static private String
getIconId(BookInfo info
) {
230 return (info
== null ?
"" : info
.getId() + ".") + "book-thumb_" + SPINE_WIDTH
+ "x" + COVER_WIDTH
+ "+"
231 + SPINE_HEIGHT
+ "+" + COVER_HEIGHT
+ "@" + HOFFSET
;