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