Lot of fixes + first (bad, ugly) working GUI
[fanfix.git] / src / be / nikiroo / fanfix / output / Html.java
1 package be.nikiroo.fanfix.output;
2
3 import java.io.File;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.io.InputStream;
7
8 import javax.imageio.ImageIO;
9
10 import be.nikiroo.fanfix.Instance;
11 import be.nikiroo.fanfix.bundles.Config;
12 import be.nikiroo.fanfix.data.Chapter;
13 import be.nikiroo.fanfix.data.MetaData;
14 import be.nikiroo.fanfix.data.Paragraph;
15 import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
16 import be.nikiroo.fanfix.data.Story;
17 import be.nikiroo.utils.IOUtils;
18 import be.nikiroo.utils.StringUtils;
19
20 class Html extends BasicOutput {
21 private File dir;
22 protected FileWriter writer;
23 private boolean inDialogue = false;
24 private boolean inNormal = false;
25
26 @Override
27 public File process(Story story, File targetDir, String targetName)
28 throws IOException {
29 String targetNameOrig = targetName;
30
31 File target = new File(targetDir, targetName);
32 target.mkdir();
33 dir = target;
34
35 targetName = new File(targetName, "index").getPath();
36 targetName += getDefaultExtension();
37
38 target = new File(targetDir, targetName);
39
40 writer = new FileWriter(target);
41 try {
42 super.process(story, targetDir, targetNameOrig);
43 } finally {
44 writer.close();
45 writer = null;
46 }
47
48 String format = Instance.getConfig()
49 .getString(Config.IMAGE_FORMAT_COVER).toLowerCase();
50 if (story.getMeta().getCover() != null) {
51 ImageIO.write(story.getMeta().getCover(), format, new File(dir,
52 "cover." + format));
53 }
54
55 return target;
56 }
57
58 @Override
59 public String getDefaultExtension() {
60 return ".html";
61 }
62
63 @Override
64 protected void writeStoryHeader(Story story) throws IOException {
65 String title = "";
66 String tags = "";
67 String author = "";
68 Chapter resume = null;
69 if (story.getMeta() != null) {
70 MetaData meta = story.getMeta();
71 title = meta.getTitle();
72 resume = meta.getResume();
73 if (meta.getTags() != null) {
74 for (String tag : meta.getTags()) {
75 if (!tags.isEmpty()) {
76 tags += ", ";
77 }
78 tags += tag;
79 }
80
81 if (!tags.isEmpty()) {
82 tags = "(" + tags + ")";
83 }
84 }
85 author = meta.getAuthor();
86 }
87
88 String format = Instance.getConfig()
89 .getString(Config.IMAGE_FORMAT_COVER).toLowerCase();
90
91 InputStream inStyle = getClass().getResourceAsStream("html.style.css");
92 if (inStyle == null) {
93 throw new IOException("Cannot find style.css resource");
94 }
95 try {
96 IOUtils.write(inStyle, new File(dir, "style.css"));
97 } finally {
98 inStyle.close();
99 }
100
101 writer.write("<!DOCTYPE html>");
102 writer.write("\n<html>");
103 writer.write("\n<head>");
104 writer.write("\n <meta http-equiv='content-type' content='text/html; charset=utf-8'>");
105 writer.write("\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>");
106 writer.write("\n <link rel='stylesheet' type='text/css' href='style.css'>");
107 writer.write("\n <title>" + StringUtils.xmlEscape(title) + "</title>");
108 writer.write("\n</head>");
109 writer.write("\n<body>\n");
110
111 writer.write("\n <div class=\"titlepage\">");
112 writer.write("\n <h1>" + StringUtils.xmlEscape(title) + "</h1>");
113 writer.write("\n <div class=\"type\">" + StringUtils.xmlEscape(tags)
114 + "</div>");
115 writer.write("\n <div class=\"cover\">");
116 writer.write("\n <img src=\"cover." + format + "\"></img>");
117 writer.write("\n </div>");
118 writer.write("\n <div class=\"author\">"
119 + StringUtils.xmlEscape(author) + "</div>");
120 writer.write("\n </div>");
121
122 writer.write("\n <hr/><br/>");
123
124 if (resume != null) {
125 for (Paragraph para : resume) {
126 writeParagraph(para);
127 }
128 if (inDialogue) {
129 writer.write(" </div>\n");
130 inDialogue = false;
131 }
132 if (inNormal) {
133 writer.write(" </div>\n");
134 inNormal = false;
135 }
136 }
137
138 writer.write("\n <br/>");
139 }
140
141 @Override
142 protected void writeStoryFooter(Story story) throws IOException {
143 writer.write("</body>\n");
144 }
145
146 @Override
147 protected void writeChapterHeader(Chapter chap) throws IOException {
148 String nameOrNumber;
149 if (chap.getName() != null && !chap.getName().isEmpty()) {
150 nameOrNumber = chap.getName();
151 } else {
152 nameOrNumber = Integer.toString(chap.getNumber());
153 }
154
155 writer.write("\n <h2>");
156 writer.write("\n <span class='chap'>Chapter <span class='chapnumber'>"
157 + chap.getNumber() + "</span>:</span> ");
158 writer.write("\n <span class='chaptitle'>"
159 + StringUtils.xmlEscape(nameOrNumber) + "</span>");
160 writer.write("\n </h2>");
161 writer.write("\n ");
162 writer.write("\n <div class='chapter_content'>\n");
163
164 inDialogue = false;
165 inNormal = false;
166 }
167
168 @Override
169 protected void writeChapterFooter(Chapter chap) throws IOException {
170 if (inDialogue) {
171 writer.write(" </div>\n");
172 inDialogue = false;
173 }
174 if (inNormal) {
175 writer.write(" </div>\n");
176 inNormal = false;
177 }
178
179 writer.write("\n </div>");
180 }
181
182 @Override
183 protected void writeParagraphHeader(Paragraph para) throws IOException {
184 if (para.getType() == ParagraphType.QUOTE && !inDialogue) {
185 writer.write(" <div class='dialogues'>\n");
186 inDialogue = true;
187 } else if (para.getType() != ParagraphType.QUOTE && inDialogue) {
188 writer.write(" </div>\n");
189 inDialogue = false;
190 }
191
192 if (para.getType() == ParagraphType.NORMAL && !inNormal) {
193 writer.write(" <div class='normals'>\n");
194 inNormal = true;
195 } else if (para.getType() != ParagraphType.NORMAL && inNormal) {
196 writer.write(" </div>\n");
197 inNormal = false;
198 }
199
200 switch (para.getType()) {
201 case BLANK:
202 writer.write(" <div class='blank'></div>");
203 break;
204 case BREAK:
205 writer.write(" <hr/>");
206 break;
207 case NORMAL:
208 writer.write(" <span class='normal'>");
209 break;
210 case QUOTE:
211 writer.write(" <div class='dialogue'>&mdash; ");
212 break;
213 case IMAGE:
214 // TODO
215 writer.write("<a href='"
216 + StringUtils.xmlEscapeQuote(para.getContent()) + "'>"
217 + StringUtils.xmlEscape(para.getContent()) + "</a>");
218 break;
219 }
220 }
221
222 @Override
223 protected void writeParagraphFooter(Paragraph para) throws IOException {
224 switch (para.getType()) {
225 case NORMAL:
226 writer.write("</span>\n");
227 break;
228 case QUOTE:
229 writer.write("</div>\n");
230 break;
231 default:
232 writer.write("\n");
233 break;
234 }
235 }
236
237 @Override
238 protected void writeTextLine(ParagraphType type, String line)
239 throws IOException {
240 switch (type) {
241 case QUOTE:
242 case NORMAL:
243 writer.write(decorateText(StringUtils.xmlEscape(line)));
244 break;
245 default:
246 break;
247 }
248 }
249
250 @Override
251 protected String enbold(String word) {
252 return "<strong>" + word + "</strong>";
253 }
254
255 @Override
256 protected String italize(String word) {
257 return "<emph>" + word + "</emph>";
258 }
259 }