1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55:
56:
62: public class MinimalHTMLWriter extends AbstractWriter
63: {
64: private StyledDocument doc;
65: private Deque<String> tagStack;
66: private boolean inFontTag = false;
67:
68:
73: public MinimalHTMLWriter(Writer w, StyledDocument doc)
74: {
75: super(w, doc);
76: this.doc = doc;
77: tagStack = new ArrayDeque<String>();
78: }
79:
80:
87: public MinimalHTMLWriter(Writer w, StyledDocument doc, int pos, int len)
88: {
89: super(w, doc, pos, len);
90: this.doc = doc;
91: tagStack = new ArrayDeque<String>();
92: }
93:
94:
97: protected void startFontTag(String style) throws IOException
98: {
99: if( inFontTag() )
100: endOpenTags();
101: writeStartTag("<span style=\""+style+"\">");
102: inFontTag = true;
103: }
104:
105:
108: protected boolean inFontTag()
109: {
110: return inFontTag;
111: }
112:
113:
116: protected void endFontTag() throws IOException
117: {
118: writeEndTag("</span>");
119: inFontTag = false;
120: }
121:
122:
125: public synchronized void write() throws IOException, BadLocationException
126: {
127: writeStartTag("<html>");
128: writeHeader();
129: writeBody();
130: writeEndTag("</html>");
131: }
132:
133:
136: protected void writeStartTag(String tag) throws IOException
137: {
138: indent();
139: write(tag+NEWLINE);
140: incrIndent();
141: }
142:
143:
146: protected void writeEndTag(String endTag) throws IOException
147: {
148: decrIndent();
149: indent();
150: write(endTag+NEWLINE);
151: }
152:
153:
156: protected void writeHeader() throws IOException
157: {
158: writeStartTag("<head>");
159: writeStartTag("<style>");
160: writeStartTag("<!--");
161: writeStyles();
162: writeEndTag("-->");
163: writeEndTag("</style>");
164: writeEndTag("</head>");
165: }
166:
167:
170: protected void writeStartParagraph(Element elem) throws IOException
171: {
172: indent();
173: write("<p class=default>"+NEWLINE);
174: incrIndent();
175: }
176:
177:
180: protected void writeEndParagraph() throws IOException
181: {
182: endOpenTags();
183: writeEndTag("</p>");
184: }
185:
186:
189: protected void writeBody() throws IOException, BadLocationException
190: {
191: writeStartTag("<body>");
192:
193: ElementIterator ei = getElementIterator();
194: Element e = ei.first();
195: boolean inParagraph = false;
196: do
197: {
198: if( e.isLeaf() )
199: {
200: boolean hasNL = (getText(e).indexOf(NEWLINE) != -1);
201: if( !inParagraph && hasText( e ) )
202: {
203: writeStartParagraph(e);
204: inParagraph = true;
205: }
206:
207: if( hasText( e ) )
208: writeContent(e, true);
209:
210: if( hasNL && inParagraph )
211: {
212: writeEndParagraph();
213: inParagraph = false;
214: }
215: else
216: endOpenTags();
217: }
218: }
219: while((e = ei.next()) != null);
220:
221: writeEndTag("</body>");
222: }
223:
224: protected void text(Element elem) throws IOException, BadLocationException
225: {
226: write( getText(elem).trim() );
227: }
228:
229:
232: protected void writeHTMLTags(AttributeSet attr) throws IOException
233: {
234: if(attr.getAttribute(StyleConstants.Bold) != null)
235: if(((Boolean)attr.getAttribute(StyleConstants.Bold)).booleanValue())
236: {
237: write("<b>");
238: tagStack.push("</b>");
239: }
240: if(attr.getAttribute(StyleConstants.Italic) != null)
241: if(((Boolean)attr.getAttribute(StyleConstants.Italic)).booleanValue())
242: {
243: write("<i>");
244: tagStack.push("</i>");
245: }
246: if(attr.getAttribute(StyleConstants.Underline) != null)
247: if(((Boolean)attr.getAttribute(StyleConstants.Underline)).booleanValue())
248: {
249: write("<u>");
250: tagStack.push("</u>");
251: }
252: }
253:
254:
257: protected boolean isText(Element elem)
258: {
259: return (elem.getEndOffset() != elem.getStartOffset());
260: }
261:
262:
265: protected void writeContent(Element elem, boolean needsIndenting)
266: throws IOException, BadLocationException
267: {
268: writeNonHTMLAttributes(elem.getAttributes());
269: if(needsIndenting)
270: indent();
271: writeHTMLTags(elem.getAttributes());
272: if( isText(elem) )
273: text(elem);
274: else
275: writeLeaf(elem);
276:
277: endOpenTags();
278: }
279:
280:
283: protected void writeLeaf(Element e) throws IOException
284: {
285:
286: if(e.getName().equals(StyleConstants.IconElementName))
287: writeImage(e);
288: else
289: writeComponent(e);
290: }
291:
292:
296: protected void writeNonHTMLAttributes(AttributeSet attr) throws IOException
297: {
298: String style = "";
299:
300:
301:
302: if( StyleConstants.getForeground(attr) != null )
303: style = style + "color: " +
304: getColor(StyleConstants.getForeground(attr)) + "; ";
305:
306: style = style + "font-size: "+StyleConstants.getFontSize(attr)+"pt; ";
307: style = style + "font-family: "+StyleConstants.getFontFamily(attr);
308:
309: startFontTag(style);
310: }
311:
312:
315: protected void writeStyles() throws IOException
316: {
317: if(doc instanceof DefaultStyledDocument)
318: {
319: Enumeration<?> styles = ((DefaultStyledDocument)doc).getStyleNames();
320: while(styles.hasMoreElements())
321: writeStyle(doc.getStyle((String)styles.nextElement()));
322: }
323: else
324: {
325: Style s = doc.getStyle("default");
326: if(s != null)
327: writeStyle( s );
328: }
329: }
330:
331:
334: protected void writeAttributes(AttributeSet attr) throws IOException
335: {
336: Enumeration<?> attribs = attr.getAttributeNames();
337: while(attribs.hasMoreElements())
338: {
339: Object attribName = attribs.nextElement();
340: String name = attribName.toString();
341: String output = getAttribute(name, attr.getAttribute(attribName));
342: if( output != null )
343: {
344: indent();
345: write( output + NEWLINE );
346: }
347: }
348: }
349:
350:
353: protected void writeComponent(Element elem) throws IOException
354: {
355: }
356:
357:
361: protected void writeImage(Element elem) throws IOException
362: {
363: }
364:
365:
366:
367:
370: private String getAttribute(String name, Object a) throws IOException
371: {
372: if(name.equals("foreground"))
373: return "foreground:"+getColor((Color)a)+";";
374: if(name.equals("background"))
375: return "background:"+getColor((Color)a)+";";
376: if(name.equals("italic"))
377: return "italic:"+(((Boolean)a).booleanValue() ? "italic;" : ";");
378: if(name.equals("bold"))
379: return "bold:"+(((Boolean)a).booleanValue() ? "bold;" : "normal;");
380: if(name.equals("family"))
381: return "family:" + a + ";";
382: if(name.equals("size"))
383: {
384: int size = ((Integer)a).intValue();
385: int htmlSize;
386: if( size > 24 )
387: htmlSize = 7;
388: else if( size > 18 )
389: htmlSize = 6;
390: else if( size > 14 )
391: htmlSize = 5;
392: else if( size > 12 )
393: htmlSize = 4;
394: else if( size > 10 )
395: htmlSize = 3;
396: else if( size > 8 )
397: htmlSize = 2;
398: else
399: htmlSize = 1;
400:
401: return "size:" + htmlSize + ";";
402: }
403:
404: return null;
405: }
406:
407:
410: private String getColor(Color c)
411: {
412: String r = "00" + Integer.toHexString(c.getRed());
413: r = r.substring(r.length() - 2);
414: String g = "00" + Integer.toHexString(c.getGreen());
415: g = g.substring(g.length() - 2);
416: String b = "00" + Integer.toHexString(c.getBlue());
417: b = b.substring(b.length() - 2);
418: return "#" + r + g + b;
419: }
420:
421:
424: private void endOpenTags() throws IOException
425: {
426: while(tagStack.size() > 0)
427: write(tagStack.pop());
428:
429: if( inFontTag() )
430: {
431: write(""+NEWLINE);
432: endFontTag();
433: }
434: }
435:
436:
439: private void writeStyle(Style s) throws IOException
440: {
441: if( s == null )
442: return;
443:
444: writeStartTag("p."+s.getName()+" {");
445: writeAttributes(s);
446: writeEndTag("}");
447: }
448:
449: private boolean hasText(Element e) throws BadLocationException
450: {
451: return (getText(e).trim().length() > 0);
452: }
453: }