Webber: A Website Construction Application
HtmlPageReader.java
// HtmlReader extension for reading TagType sub-classes for a HtmlPage
package library.html;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import library.Lib;
/*
The HtmlPageReader class extends and completes the HtmlReader class to provide it with
a list of classes that implement the HTML specification. It has two protected methods
which are called by the HtmlReader; one to return the default tag-object for plain-text
and unrecognized HTML tags and one to return an array of Class objects for the supported
HTML tags.
*/
public class HtmlPageReader extends HtmlReader {
// Tag-object classes
private static Class[] tagClasses = {
htmlTag.class, headTag.class, bodyTag.class,
titleTag.class, brTag.class, pTag.class,
strongTag.class, bTag.class, emTag.class,
iTag.class, uTag.class, hTag.class,
olTag.class, ulTag.class, liTag.class,
dlTag.class, dtTag.class, ddTag.class,
blockquoteTag.class, preTag.class, centerTag.class,
imgTag.class, aTag.class,
};
// Return the list of recognized classes
protected Class[] getTagClasses() { return tagClasses; }
// Return the default class to use for text
protected Class getDefaultTagClass() { return defaultTag.class; }
}
// Generic super-class for all TagType classes
abstract class TagType implements HtmlReader.Tag {
// Defined by subclass constructors
protected String tag;
protected boolean isContainer;
// Set during instantiation via HtmlReader.getTagType()
protected char[] text;
protected int pos, length;
// Default initialization for all TagType subclasses
public HtmlReader.Tag init(char[] text, int pos, int length) {
this.text = text;
this.pos = pos;
this.length = length;
return this;
}
// Get tag ID string
public String getTagId() { return tag; }
// Get tag length
public int getLength() { return length; }
// Get tag position
public int getPos() { return pos; }
// Set tag position
public void setPos(int pos) { this.pos = pos; }
// Set tag text reference
public void setText(char[] text) { this.text = text; }
// Returns true if this is a text tag
public boolean isTextTag() { return (tag==null) && (text[pos]!='<'); }
// Returns true if this is a closing tag
public boolean isClosingTag() { return (text[pos+1]=='/'); }
// Draw the contents of this tag as text on the page
boolean drawText(HtmlPage p, Graphics g) {
return p.drawText(new String(text, pos, length), g);
}
// Draw the contents of this HTML or text tag on the page (in colour)
public boolean drawTag(HtmlPage p, Graphics g) {
g.setColor(isTextTag() ? Color.black : Color.blue);
return drawText(p, g);
}
// Return the next word from pos in s (empty String if none)
private String getParameterWord(String s, int pos) {
int i = pos;
for (int len=s.length(); i < len; ++i) {
char c = s.charAt(i);
if ((c=='>') || Character.isWhitespace(c)) break;
}
return s.substring(pos, i);
}
// Return the next word or quoted string from pos in s
private String getParameterText(String s, int pos) {
return (s.charAt(pos)=='"') ?
Lib.getQuotedString(s, pos) : getParameterWord(s, pos);
}
// Return the offset from pos to the next parameter in s
private int nextParameter(String s, int pos) {
boolean spaced = false;
for (int len=s.length(); pos < len; ++pos) {
char c = s.charAt(pos);
if (Character.isWhitespace(c)) spaced = true;
else if (spaced) return (c=='>') ? -1 : pos;
else if (c=='"') {
String q = Lib.getQuotedString(s, pos);
if (q!=null) pos += 1 + q.length();
}
}
return -1;
}
// Return the value of a parameter as a String
protected String getParameterString(String parameter) {
String s = new String(text, pos+1, length-2), p = parameter + "=";
int len = p.length();
for (int i=nextParameter(s, 0); i!=-1; i=nextParameter(s, i))
if (s.regionMatches(true, i, p, 0, len))
return getParameterText(s, i+len);
return null;
}
}
// Generic default tag object (normal text, title text & unknown tags)
class defaultTag extends TagType {
public defaultTag() { tag = null; isContainer = false; }
// Display text, set page title, or ignore an unknown tag
public boolean action(HtmlPage p, Graphics g) {
if (text[pos]=='<') return true; // Unknown tag
if (p.getHtmlReader().title) { // Title tag
Frame f = Lib.getFrame(p); // Get parent Frame
if (f!=null) f.setTitle(new String(text, pos, length));
return true;
}
return drawText(p, g); // Text tag
}
}
class htmlTag extends TagType {
public htmlTag() { tag = "html"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
return p.getHtmlReader().html = !isClosingTag();
}
}
class headTag extends TagType {
public headTag() { tag = "head"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
p.getHtmlReader().head = !isClosingTag();
return true;
}
}
class bodyTag extends TagType {
public bodyTag() { tag = "body"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
p.getHtmlReader().body = !isClosingTag();
return true;
}
}
class titleTag extends TagType {
public titleTag() { tag = "title"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
p.getHtmlReader().title = !isClosingTag();
return true;
}
}
class brTag extends TagType {
public brTag() { tag = "br"; isContainer = false; }
public boolean action(HtmlPage p, Graphics g) { return p.nextline(g); }
}
class pTag extends TagType {
public pTag() { tag = "p"; isContainer = false; }
public boolean action(HtmlPage p, Graphics g) { return p.newpara(g); }
}
// Generic super-class for selecting bold font
abstract class boldTagType extends TagType {
public boldTagType() { isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
p.setBold(isClosingTag() ? false : true);
return true;
}
}
class strongTag extends boldTagType {
public strongTag() { tag = "strong"; }
}
class bTag extends boldTagType {
public bTag() { tag = "b"; }
}
// Generic super-class for selecting italic font
abstract class italicTagType extends TagType {
public italicTagType() { isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
p.setItalic(isClosingTag() ? false : true);
return true;
}
}
class emTag extends italicTagType {
public emTag() { tag = "em"; }
}
class iTag extends italicTagType {
public iTag() { tag = "i"; }
}
class uTag extends TagType {
public uTag() { tag = "u"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
p.setUnderline(isClosingTag() ? false : true);
return true;
}
}
// Generic class for all heading tags (1-6)
class hTag extends TagType {
static final int size[] = { 32, 24, 18, 16, 12, 10 }; // Heading font sizes
public hTag() { tag = "h"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
if (!isClosingTag()) {
if (!p.newpara(g)) return false;
int i = Character.digit(text[pos+2], 10);
if (i<0) return true; // Invalid character?
if (i>0) i = (i>6) ? 5 : i-1; // Convert to range 0-5
p.setBold(true);
p.setFontSize(size[i]);
} else {
p.setFontSize();
p.setBold(false);
if (!p.newpara(g)) return false;
}
return true;
}
}
// Generic super-class for all tags using indentation (lists, pre & blockquote)
abstract class indentTagType extends TagType {
protected static final int indent = 40; // Indentation step
}
// Generic super-class for all list tags
abstract class listTagType extends indentTagType {
// Insert empty lines at the start or end of a list
public boolean listBreak(HtmlPage p, Graphics g) {
if (p.listDepth<=0) // Not a sub-list?
if (!p.newpara(g)) return false;
return true;
}
}
// Generic super-class for ordered and un-ordered lists
abstract class lTagType extends listTagType implements HtmlReader.Context {
public static final String id = "list";
protected boolean isNumbered;
protected int item;
// Constructor
public lTagType() { isContainer = true; }
// Return context ID string (for Context)
public String getContextId() { return id; }
// Initialize/terminate list
public boolean action(HtmlPage p, Graphics g) {
HtmlReader r = p.getHtmlReader();
if (!isClosingTag()) { // Initialize list
if (!listBreak(p, g)) return false;
item = 0;
p.addIndent(indent);
r.addContext(this);
p.listDepth++;
} else if (p.listDepth > 0) { // Terminate list
p.listDepth--;
r.removeContext(id);
p.addIndent(-indent);
if (!listBreak(p, g)) return false;
}
return true;
}
// Prepare next list item
public boolean nextItem(HtmlPage p, Graphics g) {
if (!p.newline(g)) return false;
String s;
if (isNumbered) s = ++item + ".";
else switch (p.listDepth) {
case 1: s = ""+(char)0x2219; break;
case 2: s = "o"; break;
default: s = ""+(char)0x22C4; break;
}
p.addIndent(-indent/2);
p.drawText(s, g);
p.addIndent(indent/2);
return true;
}
}
class olTag extends lTagType {
public olTag() { tag = "ol"; isNumbered = true; }
}
class ulTag extends lTagType {
public ulTag() { tag = "ul"; isNumbered = false; }
}
class liTag extends TagType {
public liTag() { tag = "li"; isContainer = false; }
public boolean action(HtmlPage p, Graphics g) {
lTagType l = (lTagType)p.getHtmlReader().getContext(lTagType.id);
return (l==null) ? true : l.nextItem(p, g);
}
}
class dlTag extends listTagType implements HtmlReader.Context {
public static final String id = "def";
boolean isDefinition;
// Constructor
public dlTag() { tag = "dl"; isContainer = true; }
// Return context ID string (for Context)
public String getContextId() { return id; }
// Initialize/terminate list
public boolean action(HtmlPage p, Graphics g) {
HtmlReader r = p.getHtmlReader();
if (!isClosingTag()) { // Initialize list
if (!listBreak(p, g)) return false;
isDefinition = false;
r.addContext(this);
p.listDepth++;
} else { // Terminate list
dlTag t = (dlTag)r.getContext(id);
if (t==null) return true;
p.listDepth--;
if (t.isDefinition) p.addIndent(-indent);
r.removeContext(id);
if (!listBreak(p, g)) return false;
}
return true;
}
// Prepare next term/definition
public boolean nextItem(String tag, HtmlPage p, Graphics g) {
if (!p.newline(g)) return false;
if (isDefinition!=tag.equals("dd")) { // Switch state
isDefinition = !isDefinition;
p.addIndent(isDefinition ? indent : -indent);
}
return true;
}
}
// Generic super-class for definition-list items
abstract class dlTagType extends TagType {
public dlTagType() { isContainer = false; }
public boolean action(HtmlPage p, Graphics g) {
dlTag t = (dlTag)p.getHtmlReader().getContext(dlTag.id);
return (t==null) ? true : t.nextItem(tag, p, g);
}
}
class dtTag extends dlTagType {
public dtTag() { tag = "dt"; }
}
class ddTag extends dlTagType {
public ddTag() { tag = "dd"; }
}
class blockquoteTag extends indentTagType {
public blockquoteTag() { tag = "blockquote"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
if (!p.newpara(g)) return false;
p.addIndents(isClosingTag() ? -indent : indent);
return true;
}
}
class preTag extends TagType {
public preTag() { tag = "pre"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
if (!p.newpara(g)) return false;
if (!isClosingTag()) {
p.setPreformat(true);
p.setTeleFont();
} else {
p.setNormalFont();
p.setPreformat(false);
}
return true;
}
}
class centerTag extends TagType {
public centerTag() { tag = "center"; isContainer = true; }
public boolean action(HtmlPage p, Graphics g) {
if (!p.newline(g)) return false;
p.setCentre(!isClosingTag());
return true;
}
}
class imgTag extends TagType {
private static final String // String constants
src = "src", align = "align", // Parameter strings
as[] = { "bottom", "middle", "top" }; // Alignment strings
public imgTag() { tag = "img"; isContainer = false; } // Constructor
public boolean action(HtmlPage p, Graphics g) { // Action handler
Toolkit t = Toolkit.getDefaultToolkit(); // Get system toolkit
String s = getParameterString(src); // Source file parameter
if (s==null) return true; // No source file?
String ap = getParameterString(align); // Alignment parameter
int a = (ap==null) ? 0 : Lib.getStringIndex(as, ap, true);
Image i; // Image reference
Object o = p.getHref(s); // Resolve filename
if (o==null) return true; // Bad filename?
i = (o instanceof URL) ? // URL or local file?
t.getImage((URL)o) : t.getImage((String)o);
if (i!=null) p.drawImage(i, a, g); // Draw the image
return true;
}
}
class aTag extends TagType implements HtmlPage.ClickListener {
private static final String href = "href"; // String constant
public aTag() { tag = "a"; isContainer = true; } // Constructor
public boolean action(HtmlPage p, Graphics g) { // Action handler
if (!isClosingTag()) { // Open anchor?
if (getParameterString(href)==null) return true; // Reference?
p.addClickArea(this); // Start active area
g.setColor(p.getLinkColor()); // Set link colour
p.setUnderline(true); // Enable underlining
} else { // Close anchor
if (!p.endClickArea()) return true; // End active area?
p.setUnderline(false); // Disable underlining
g.setColor(p.getNormalColor()); // Set normal colour
}
return true;
}
public void mouseClicked(HtmlPage p) { // Click handler
p.openUrl(getParameterString(href)); // Load linked file
}
}
Go To:
Source Code