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