Class Library: HTML Document Objects II

Paragraph. An array of DocElements (TextStrings and/or Boxes). Although in a formal sense this class implements the HTML <p> tag, its role in document rendering is much bigger than this little tag might suggest. The paragraph, as conceptualized here, is both the basic Document element and is itself a complex collection of text and boxes. The methods of this class, starting with flow() which is called by the write() method of the data stream handler Doc object, do the actual under-the-hood work of getting a complex HTML document onto the viewer's screen.

package earthstones
import java.awt.*;
java.applet.*;
java.util.*;
class declaration public class Paragraph extends DocElement
variables Vector data = null; Defines the data variable as a Vector to hold the Paragraph's ordered collection of TextStrings and Boxes.
private Document document; The document to which this paragraph belongs
TextPanel panel = null; The user-interface panel into which the paragraph is rendered.
The next two variables are set by the findBox() method.
Box box = null; Set the the first Box element encountered in the paragraph's data vector.
Paragraph tail = null; Set to the elements of the data vector which occur after the first Box element.
Paragraph orphan = null; Set to the collection of elements of the paragraph's data vector that fail to fit in the available space when the paragraph is rendered into the space beside a Box element.
TextString bullet = null; Set to the value of the paragraph's bullet character (typically defined in a bitmapped image file).
boolean wrapBullet = false; If set, bullet is wrapped by paragraph text (i.e., only first line is indented by bullet). Set by <ul wrapbullet> tag. Note that when a bullet is set for a paragraph outside a <ul> list (using the <p bullet=...> tag.
boolean noneBetween = false; Set by <p> and <ul compact> tags to cancel the usual interparagraph spacing defined by the fontMetric parameters addabove and addBelow
String align = "LEFT"; This parameter is currently set in Document.loadHtml but not implemented in this class' show method.
private int width = 0; Total width of paragraph, including hspace and indent.
int indent = 0; Indents paragraph from left.
int hspace = 0; Creates hspace on left and right of paragragh.
boolean autoScale = false; When set, paragraph width will automatically be scaled by resFactor. Set to false by GImage which sets paragraph width to width of image which handles scaling. Set to false here by default because paragraph sizing is generally handled by Document.
constructors Paragraph(Container app, int wid) 1) Calls super(app).
2) Sets width to wid.
3) Calls init().
4) Sets panel = new TextPanel(webApp, width).
Paragraph(Container app, int wid, TextPanel pnl) Generally a new TextPanel is created along with the paragraph. This next constructor allows for the re-use of a panel instead (e.g., by Hint).
This constructor:
1) Calls super(app).
2) Sets width to wid.
3) Calls init().
4) Sets panel = pnl.
5) Calls resize(width, panel.size().height).
Paragraph(Container app, Document doc) 1) Calls super(app).
2) Sets width to doc.width().
3) Calls init().
4) Sets document = doc.
5) Sets panel = new TextPanel(webApp, width).
Paragraph(Container app, int wid, boolean scale) 1) Calls super(app).
2) Sets width to wid.
3) Sets autoScale = scale;
3) Calls init().
4) Sets document = doc.
5) Sets panel = new TextPanel(webApp, width).
methods public void init() Initializes data to a new Vector object.
These methods which set some of Paragraph's values are more complex that the usual methods which simply set a single variable.
public void setWidth(int wid) 1) Sets width variable to wid.
2) If autoscale is set, resizes panel to scaled value of width.
3) Otherwise, resizes panel to width.
public void setDocument(Document doc) 1) Sets document variable to doc.
2) If orphan is null, sets orphan = new Paragraph(webApp, document).
3) If tail is null, sets tail = new Paragraph(webApp, document).
public void setPanel(TextPanel pnl) 1) Sets panel equal to pnl.
2) Calls setWidth(width).
public void setBullet(String type, int nested) This method is called by setAttrib() and by HtmlTag.setExtTag() while setting parameters of the <LI> tag. It sets paragraph's bullet character to that specified by type but does not add bullet to paragraph's data vector. The nested parameter indicates the number of nested list levels and is used in setting the indent variable for the Paragraph object which represents this list element.
These methods add and remove DocElements from Paragraph's data Vector.
public void add(DocElement element) Adds element to paragraph's data vector and sets its isFirst variable if it is the first element in the paragraph.
public void remove(DocElement element) Removes element from paragraph's data vector and, if necessary, resets its isFirst variable.
public Paragraph append(Paragraph par) Appends the elements of paragraph par to this paragraph by calling the add() method which resets the isFirst variable if necessary.
public void add(TextString element, boolean orphan) This method adds a TextString object to the current paragraph.
The following 4 methods add String objects to the current paragraph by creating and adding new TextString objects. TextStrings added to the paragraph assume the properties of the paragraph unless they are explicitly specified.
public void addText(String text, int style,
int size, String fnt)
public void addText(String text, int style,
int size)
public void addText(String text, int style)
public void addText(String text)
public TextString newTextString() This method creates and returns a new TextString object whose attributes have been set to those of the Paragraph.
public Paragraph setAttrib(Index attrib) This method sets the paragraph's variables to values read from its HTML <p> tag.
public void flow(int x, int y) This crucial method is responsible for rendering the paragraph's collection of Box and TextString elements onto the page.
Note: Document's width has already been set and should not be changed in flow() and its helper methods. Instead, each method adds a panel to the current document.panels vector and then resets the document cursor for the next panel which determines its size.
This method:
1) Calls findBox();
2) If data is not null, resets orphan to a new Paragraph object and calls showText(x, y).
3) If orphan is now not null, either appends it to tail or calls orphan.showText(x, y) depending upon context.
4) If box is not null, calls showBox(x, y).
5) If tail is not null, calls tail.flow(x, y) to continue an iterative process until all of the original paragraph data have been rendered.
public boolean findBox() This method locates the first Box element in this paragraph. If found, it sets the instance variable box and removes all subsequent DocElements from its data variable, placing them in tail instead. Note that the orphan variable is not affected by this method.
private void showBox(int x, int y) 1) Shows the element specified by the box variable into the document cursor, relocates the resulting panel to location (x, y), and adds it to document.panels.
2) Adds any links set for this box to document.panel.links.
3) Resets the document cursor.
public void showText(int x, int y) 1) Shows the element specified by the box variable into the document cursor, relocates the resulting panel to location (x, y), and adds it to document.panels.
2) Calls the collectLinks() to adds any links set for its text strings to document.panel.links.
3) Resets the document cursor.
public Vector collectLinks(int x, int y) This method collects and returns a vector containing all the paragraph's hyperlinks. Note that the link's hotspot is moved before adding. Also must add a copy of the link to the panel's collection rather than the link itself because the drawParagraph() method will be called in subsequent paint calls, which will obliterate the new (x, y) coordinates. Note: In the case of a Table object included withing a paragraph, any links have already been collected in its links Vector and is simply appended here to the document's links Vector.
The methods showBox() and showText() rely upon the document cursor to tell them where to render their DocElements. Just as a blinking cursor on a character-oriented video screen marks an insertion point or caret at which the next character is to appear, the document cursor is a rectangle whose coordinates mark the boundaries of the white space within which the next DocElement is to be rendered. Initially, the document cursor is the entire page: a rectangle whose width is document.getLineWidth() and whose height is infinite (set to the constant Document.INF = 9999). As (left- and right-aligned) Box elements appear in the Paragraph's stream of DocElements, the cursor becomes, for a time, a narrower and much shorter rectangle which shifts to the right and left on the page. At some points, where the vertical positions of left- and right-aligned Box elements overlap for a bit, the document becomes a still narrower channel down the middle of the page.
The actual work of setting the document's cursor variable is accomplished by calling the document's various setCursor methods. Under the simplest conditions that occur, showBox() and showText() calls these document methods directly. The next two Paragraph methods provide additional help in setting the cursor under more complex conditions.
private Rectangle getCursor(int ypos) This method iterates through the list of wrappable boxes (stored in document.boxes) so far encountered in rendering the document of which this paragraph is a part and returns a rectangle which serves as a potential cursor. (The method should probably be called getPotentialCursor()). If ypos is still within a box's bounding rectangle, the potential cursor's width is reduced by the width of that box. If instead ypos is now beyond the box's y-boundry, the element is eliminated from the list of boxes. The height of the rectangle returned by the method is the height of the still unwrapped portion of the first box still in the list. Under some conditions showBox() calls this method directly and uses its result to the call the appropriate document.setCursor() method.
private void setCursor(int ypos) This method is called by showText(). It may call document.setCursor() immediately or may use the result of getCursor() to call the appropriate form of the document.setCursor() method. It also may decide that the results of the getCursor() method yield a rectangle that is too narrow to accomodate any text; it then skips that space and calls the next iteration of getCursor(). Under some of the more complicated conditions,
public Vector collectLinks(int x, int y)
The paragraph's show() methods link the Paragraph data structure with its user-interface counterpart, the instance panel of TextPanel. It is the methods of TextPanel that perform the actual text rendering into the panel component.
public TextPanel show(int x, int y,
int wd, int ht, int rHt)
1) Calls this.resize(wd, ht, rHt) which forces the TextPanel panel to be redrawn to reflect is new width wd, height ht, and ruleHeight rHt.
2) Moves panel to (x, y).
3) If necessary, adjust the height of panel.
public TextPanel show(int x, int y,
int wd)
Returns the result of show(x, y, wd, Document.INF, 0).
public TextPanel show(int x, int y,
int wd, int ht)
Returns the result of show(x, y, wd, ht, 0).
public TextPanel show(int x, int y,
int wd, int ht, int rHt,
Color clr)
Sets panel's ruleColor to clr and returns the result of show(x, y, wd, ht, rHt).
private synchronized Dimension resize(int wd, int ht, int rHt) This method defines the link between the Paragraph and TextPanel objects. This method:
1) Calls setWidth(wd) to set the width of paragraph to wd.
2) Sets panel's ruleHeight to rHt.
3) Calls panel.setParagraph(this, ht). From here, the methods of TextPanel take over the work.
4) Returns panel's dimensions.
These methods set and return a few of Paragraph's variables.
public int width()
public void setIndent(int val)
public Document document()

Document. An array of Paragraphs. This class' methods perform the work of parsing the HTML stream and creating the DocElement objects which make up the document.

package earthstones
import java.awt.*;
java.net.*;
java.util.*;
java.applet.*;
class declaration public class Document extends DocElement
class constants public static final int INF = 9999; Used to set panel's height to "infinity."
variables DataBuffer data = null; Defines the data variable as a DataBuffer. Elements are the document's paragraphs.
EventManagerPanel panel = null; The panel into which the document is rendered. An instance of EventManagerPanel is used in order to manage user-interface events such as hyperlinks and hints.
URLConnection urlCnct = null; if set, defines a previously opened URLConnection as alternative to source as the HTML data stream for the document.
String source = ""; The URL string specifying the document's data stream (unless URLConnection is set). Absolute URLs are used as specified; otherwise path is interpreted as relative to the main (host) applet's documentBase (i.e., the path of the HTML document containing its <applet> tag). A default value is set in init().

Note: If source ends with the file extension .html or .htm, the HTML source will be interpreted and rendered; if it ends with .gif, .jpg, or .jpeg the image file will be displayed with its default dimensions scaled for the viewer's screen resolution; any other files will be treated as plain text files.
String previous = ""; The source for the previous document. This feature is not currently implemented.
String next = ""; The source for the next document. This feature is not currently implemented.
Panel cursor = null; The document's cursor which is reset during document rendering to reflect the rectangle into which the next DocElement will be rendered.
Panel defaultCursor = null; Set in init() to reflect the initial document cursor.
Vector boxes = null; Collects the bounding rectangles of the wrappable boxes encountered in the document.
DataBuffer results = null; Set by Form and contains the results of the form's GET or POST action for further processing by the programmer. Unless the form's noShow attribute is set, these results are automatically presented to the viewer.
private boolean scroll = true; Set by the DocumentPanel to reserve room for a vertical scroll bar.
private boolean setHScroll = false; If set at the time the document is is rendered, this flag signals its DocumentPanel object to add a horizontal scroll bar. Currently this is set only by a Table object when its <table> tag requests a width greater than that of the document's line width. If set, setHScroll will override the DocumentPanel's hScroll variable set at the time its update() method is called.
private int mode =
DocumentPanel.DOCUMENT;
The document's mode (see DocumentPanel constants for definitions). May be reset by constructor form which takes mode as an argument).
These variables set the document's margins. These values typically remain set to zero and the margins around the document are set by positioning its DocumentPanel object on the page. This is the case in JSite. JDoc (as a stand-alone applet) makes provision for setting these values in the <applet> tag.
private int leftMargin = 0;
private int rightMargin = 0;
private int topMargin = 0;
private int bottomMargin = 0;
private int scrollMargin = 10; When vertical scrollbar is set, this value determines the white-space between the text and the scroll bar.
boolean plainText = false; When set, document is interpreted as CRLF-delimited lines of plain text rather than as HTML code and text.
private int width = 0; The total width of document, including left, right, and scrollbar margins.
private int height = 0; The document's total height exclusive of top and bottom margins.
constructors Document(Container app) Creates Document instance.
Document(Container app, boolean alt) Creates Document instance and sets isAlt to alt.
Document(Container app, int wid) Creates Document instance and sets width to wid.
Document(Container app, int wid, int md) Also sets document's mode to md.
Document(Container app, int wid, int hmar, int vmar) Creates Document instance and sets width to wid, leftMargin and rightMargin to hmar, and topMargin and bottomMargin to vmar.
Document(Container app, int wid, int lmar, int rmar, int tmar, int bmar) Creates Document instance and sets width to wid, leftMargin to lmar, rightMargin to rmar, topMargin to tmar, and bottomMargin to bmar.
Document(Container app, int wid, int lmar, int rmar, int tmar,
int bmar, int smar)
Creates Document instance and sets width to wid, leftMargin to lmar, rightMargin to rmar, topMargin to tmar, bottomMargin to bmar, and scrollMargin to smar.
methods public void init() If WebSite.web(webApp).thePage is set:
1) Calls setWidth(width).
2a) If mode ISGRAPHIC:
2a1) If mode is GRAPHIC_DOC (i.e., left-hand graphic panel is to display an alternative document), source is set to thePage.altSource().
2a2) Otherwise, the document's data buffer is initialized and an ImageBox is added to it whose data variable has been set to Web.theImage (i.e, the image to be displayed in the graphic panel--which may be randomly selected).
2b) Otherwise docment source is set to the HTML file sectionId/[cont] chapterId/[cont]
pageId/Text.htm
.
3) If source does not end with .htm or .html, the plainText variable is set.
If thePage is not set the source and width variables must be set by the user. Note: Currently setWidth ASSUMES a scaled value if thePage defaults are not used. This means that document source file and width must be explicitly set AFTER document is created and BEFORE invoking DocumentPanel.update(doc, scrl).
public void setSource(String src) 1) If src specifies a .gif, .jpg, or .jpeg file it is treated as an image: an instance of ImagePanel is created for source src and added to the document's data buffer; the document's mode is set to DocumentPanel.GRAPHIC; and the data buffer's isLoaded variable is set which will bypass the read() method when show() is called. Note that the image's default dimensions will be used and that these will be scaled by the value Web.resFactor() to correspond to the user's screen resolution.
2) Otherwise,
2a) For file extensions .html or .htm, source src is rendered as an HTML document.
2b) Otherwise, source src is rendered as a plain text document.
public void add(Paragraph element) This method adds a paragraph to the document.
The next series of methods are defined for convenience in creating new document elements (i.e., instances of DocElement). Were necessary, this document instance is set in the DocElement's document variable. In all cases the copyAttrib() method is called to set its font characteristics set to those of this document. Note that these methods do NOT actually add the element to the document.
public Paragraph newParagraph() Returns a new paragraph with its width set to the document's printable width.
public ImageBox newImageBox(boolean insert) Returns a new ImageBox with its data variable initialized to a new GImage object and its isInsert variable set to insert.
public TextBox newTextBox() Returns a new TextBox object.
public Table newTable() Returns a new Table object whose width has been initialized to the document's printable width.
public Form newForm() Returns a new Form object whose width has been initialized to the document's printable width.
public int getLineWidth() Returns the document's printable width = width - leftMargin - rightMargin. If the scroll variable is set, this amount is further reduced by the value of DocumentPanel.scrollBarWidth. Note that the latter is not the same as the document's scrollMargin. The scrollBarWidth is the actual width of the scrollbar; the scrollMargin is the interval between the text and the scrollbar. Finally, the rightMargin, if set, is the distance between the scrollbar (if present) and the right edge of the DocumentPanel.
These methods are used to set the document's cursor and defaultCursor variables.
public void setDefaultCursor() Sets the default cursor to a rectangle whose width is equal to getLineWidth() and whose height is set to Document.INF. Note that topMargin is handled by DocumentPanel, not by Document (i.e., the topMargin, if set, is NOT included in the instance panel of EventManagerPanel but IS included in the instance of DocumentPanel (a scrolling panel) into which panel is eventually placed.
public void setCursor() Returns a copy of the defaultCursor.
public void setCursor(int y) Returns a copy of the defaultCursor whose vertical coordinate has been set to y.
public void setCursor(int x, int y, int wid) Returns a copy of the defaultCursor which has been moved to the location (x, y) and whose width has been reset to wid.
public void setCursor(int x, int y, int wid, int ht) Returns a copy of the defaultCursor which has been moved to the location (x, y) and whose dimensions have been reset to wid and ht.
public Panel copyDefaultCursor() Returns a new Panel object with a null Layout object whose dimensions are those of the defaultCursor.
The next two methods involve modifications of the document's dimensions and thus its cursors.
public void setWidth(int wid) If wid is zero (i.e., it's width has not yet been set), set it based on values in Web.thePage:
1) If mode is ISGRAPIC (i.e., document will be displayed in Web.graphic), width is set to the value of WebSite.web(webApp).getWidth() (i.e., the width of the space otherwise reserved for the graphic panel.
2) Otherwise, (i.e., display is in Web.document) width is set to the remaining available space when the width of the graphic panel and the margins are subtracted from the overall page width.
If the value of wid is now different than that of width:
3) Width is reset to wid.
4) The panels variable is set to null which forces the document to be redrawn in the show() method.
5) The methods setDefaultCursor() and setCursor() are called.
public void setScroll(boolean val) 1) The scroll variable is set to val.
2) The panels variable is set to null which forces the document to be redrawn in the show() method.
3) The methods setDefaultCursor() and setCursor() are called.
Note that both forms of the show() method use the current values for the margins.
public EventManagerPanel show() 1) If panel has already been set, returns panel.
2) Otherwise,
2a) If the document's data buffer is not empty (e.g., has been programatically set as in the init() method for GRAPHIC mode), sets the buffer's isLoaded variable;
2b) Calls read() to read the document's data.
3) Calls render() to render the elements in the data buffer to its user-interface panel.
public EventManagerPanel show(int x, int y) Calls show(), moves resulting panel to location (x, y), adjusts the size of panel to accomodate this shift in location, and returns the panel.
The next two methods manage the three-stage, multi-threaded process of reading a document stream, parsing its HTML tags and representing them as DocElement objects, and rendering these elements to the user interface.
public void read() Uses two different Data subclasses in sequence to read Document's data stream and set its data variable:
1) Creates an instance input of Html or Txt (for a plain text document), reads the document stream and stores the results (extended tags or CRLF-delimited lines, respectively) in its data buffer input.data.
2) Creates an instance of HtmlTag which reads input.data, interprets its HTML tags (or, for plain text, treats each line as a new paragraph), and writes the results to the Document's data variable.
public void render() Creates an instance of Doc which reads Document's data buffer and renders each paragraph onto user-interface panels which are added to the document's panel variable.
The next two methods are called by Paragraph.showBox() and Paragraph.showText() and to add a panel pnl to the document's user interface panel. They continuously resize and repaint the panel so that the initial elements of a long document can be displayed to the user while the rest of it is still being read and rendered.
public synchronized void addPanel(Panel pnl, boolean addThis) 1) When addThis is set (i.e., except for tables), panel.add(pnl) and pnl.repaint() are called.
2) Regardless, panel's height is resized to panel.size().height + pnl.size().height and the document panel (Web.document or Web.altDoc) is repainted.
public synchronized void addPanel(Panel pnl) Calls addPanel(pnl, true).
public String getBullet(String aType) Returns a string referencing the bullet character corresponding to the bullet type aType. Method is called by loadHtml() as well as Paragraph.setBullet().
These variables set and return the document's various margins.
public void setLeftMargin(int val)
public void setRightMargin(int val)
public void setTopMargin(int val)
public void setBottomMargin(int val)
public void setScrollMargin(int val)
public int leftMargin()
public int rightMargin()
public int topMargin()
public int bottomMargin()
public int scrollMargin()
public int width()
public int height()
public int mode()
public boolean setHScroll()
public void setSetHScroll(boolean val)