Webber: A Website Construction Application


HtmlFile.java


// HTML File Link - links one instance of a Viewer and an Editor for a file

package library.html;

import java.io.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;

import library.*;

public class HtmlFile {

	HistoryList history = new HistoryList(16);		// File/URL history
	HtmlViewer viewer = null;				// Viewer window
	HtmlEditor editor = null;				// Editor window
	HtmlWindow active = null;				// Active window
	boolean isModified = false;				// Text modified flag
	boolean isPlain;					// Plain text flag
	String fname;						// Current filename

	private static final String				// String constants
		defaultName = "untitled.html",			// Default filename
		defaultUrl = "index.html";			// Default URL file
	private URL Url = null;					// The URL of the file
	private char[] text;					// The HTML text

	// Constructors
	public HtmlFile() { resetFileData(); }
	public HtmlFile(String fname) { this(fname, null); }
	public HtmlFile(String fname, char[] text) { setFileData(fname, text); }

	// Messages
	protected String msgModified() {
		return	"The text in this file has changed. " +
			"Do you want to save the changes?";
	}
	protected String msgReadError() {
		return	"An error occurred while reading this file. " +
			"Please correct the problem and try again.";
	}
	protected String msgWriteError() {
		return	"An error occurred while writing this file. " +
			"Please correct the problem and try again.";
	}
	protected String msgFormatError() {
		return	"The target is not a HTML file and cannot be displayed.";
	}

	// Report an event to the user (get 'OK')
	private void msgReport(String title, String msg) {
		CommonDialog.getDialog(active, title, msg, CommonDialog.OK, true);
	}

	// Set the HTML text held by this link
	public void setText(char[] text) { this.text = text; }

	// Set the file data (name & text) for this link
	private void setFileData(String fname, char[] text) {
		this.fname = fname;
		setText(text);
		if (viewer!=null) viewer.setFilename(fname);
		if (editor!=null) editor.setFilename(fname);
	}

	// Set the file data for this link to default values
	private void resetFileData() {
		isPlain = false;				// Assume HTML text
		setFileData(defaultName, null);			// Set file/text data
	}

	// Get the HTML text held by this link (editor/viewer override this.text)
	public char[] getText() {
		return	(editor!=null) ? editor.getText() :	// Return editor text
			(viewer!=null) ? viewer.getText() :	// Return viewer text
			text;					// Return initial text
	}

	// Return the partner window of a HtmlWindow (viewer or editor)
	private HtmlWindow getPartner(HtmlWindow w) {
		return (w==viewer) ? (HtmlWindow)editor : (HtmlWindow)viewer;
	}

	// Set the state of the modified flag (updates window titles)
	private void setModified(boolean state) {
		if (isModified==state) return;			// No change
		isModified = state;				// Switch states
		if (viewer!=null) viewer.resetModified();	// Update viewer title
		if (editor!=null) editor.resetModified();	// Update editor title
	}

	// Open or reactivate the viewer for this text
	public void startViewer() {
		if (viewer==null)				// Create a viewer?
			viewer = new HtmlViewer(fname, getText(), this);
		viewer.toFront();
	}

	// Open or reactivate the editor for this text (traps text events)
	public void startEditor() {
		if (editor==null)				// Create an editor?
			editor = new HtmlEditor(fname, getText(), this) {
				// Set flag for first text modification
				public void textValueChanged(TextEvent e) {
					if (!isModified) setModified(true);
				}
			};
		editor.toFront();
	}

	// Create a new HtmlFile containing a copy of the text in this one
	private HtmlFile newHtmlFile() {
		char[] text = getText();			// Get active text
		HtmlFile f = (text==null) ? new HtmlFile(fname) :
		    new HtmlFile(fname, (new String(text)).toCharArray());
		f.isModified = isModified;			// Copy modified flag
		return f;
	}

	// Create a new viewer containing a copy of this text
	protected void newViewer() { newHtmlFile().startViewer(); }

	// Create a new editor containing a copy of this text
	protected void newEditor() { newHtmlFile().startEditor(); }

	// Save text to file fname
	private boolean saveFile(String fname, char[] text) {
		if (text==null) return true;			// No text?
		try { Lib.saveCharFile(fname, text); }		// Write text to file
		catch (IOException e) {				// Write failed?
			msgReport(fname, msgWriteError());	// Report failure
			return false;
		}
		return true;
	}

	// Save the current text and update flags
	private boolean updateFile(String fname, char[] text) {
		if (!saveFile(fname, text)) return false;	// Write text to file
		setModified(false);				// Reset modified flag
		return true;
	}

	// Get a filename and save the current text
	boolean saveTextAs() {
		String name;
		if (Url==null) name = fname;			// Local filename?
		else name = Lib.getUrlFilename(Url, defaultUrl);// URL sourced file
		FileDialog f = new FileDialog(active, "Save As", FileDialog.SAVE);
		name = Lib.getFilename(f, name);		// Input filename
		if (name==null) return false;			// Cancelled?
		if (!updateFile(name, getText())) return false;	// Write text to file
		fname = name;					// Set new filename
		Url = null;					// Disable URL status
		history.add(fname);				// Add to history list
		return true;
	}

	// Save the current text to the current filename (rename if untitled)
	boolean saveText() {
		return	(Url!=null) ? saveTextAs() :		// Non-local file?
			(fname==defaultName) ? saveTextAs() :	// Create new file?
			updateFile(fname, getText());		// Update file
	}

	// Returns true if text is unmodified or has been saved or abandoned
	boolean checkSave() { return checkSave(active, false); }
	boolean checkSave(HtmlWindow win, boolean isPartner) {
		if (!isModified) return true;			// Text not modified?
		if (!isPartner || (getPartner(win)==null))	// Partner not active?
			switch (CommonDialog.getDialog(win, fname, msgModified())) {
			    case CommonDialog.CANCEL:		// Cancelled?
			    	return false;			// Abort operation
			    case CommonDialog.YES:		// Confirmed?
			    	if (!saveText()) return false;	// Save file
			}
		if (win==viewer) viewer = null;			// Kill viewer reference
		else editor = null;				// Kill editor reference
		return true;					// Continue operation
	}

	// Update the contents of a window and destroy it's partner
	private void updateWindow(HtmlWindow win) {
		HtmlWindow p = getPartner(win);			// Get partner window
		if (p!=null) p.dispose();			// Destroy partner
		win.toFront();					// Ensure win is active
		win.setText(text);				// Update HTML text
		setModified(false);				// Reset modified flag
		win.reader.repaint();				// Refresh display
	}

	// Load text from file name
	private boolean loadFile(String name) { return loadFile(name, true); }
	private boolean loadFile(String name, boolean hist) {
		char[] text;
		active.setMessage("Loading file...");		// Report status
		try { text = Lib.loadCharFile(name); }		// Load text from file
		catch (IOException e) {				// Load failed?
			active.setMessage("");			// Clear message
			return false;				// Return failure
		}
		Url = null;					// Reset file URL
		isPlain = name.toLowerCase().endsWith(".txt");	// Plain text or HTML?
		setFileData(name, text);			// Set file name/text
		if (hist) history.add(name);			// Add to history list
		updateWindow(active);				// Update the window
		active.setMessage("Done");			// Report success
		return true;					// Return success
	}

	// Load a local file into the active window and destroy it's partner window
	void openFile() {
		if (!checkSave()) return;			// Save changes
		FileDialog f = new FileDialog(active, "Open", FileDialog.LOAD);
		String s = Lib.getFilename(f, "*.htm*");	// Input filename
		if (s==null) return;				// Cancelled?
		if (!loadFile(s)) msgReport(s, msgReadError());	// Load & report errors
	}

	// Return an absolute URL or a local file reference (a String) for file name
	Object getHref(String name) {
		URL url;
		try {	url = new URL(Url, name);		// Interpret as a URL?
			return url;				// Return a new URL
		} catch (MalformedURLException e) {}		// Not a URL
		return Lib.getCanonicalPath(fname, name);	// Interpret as a file
	}

	// Open and retrieve the contents of a file into the active window
	// The file can be a URL or a local file and absolute or relative to this file
	private int openLocation(String file) { return openLocation(file, true); }
	private int openLocation(String file, boolean hist) {
		URLConnection c;				// Connection object
		char[] text;					// Text object
		Object o;					// Generic object
		URL url;					// URL object
		active.setMessage("Getting " + file);		// Report status
		if ((o = getHref(file))==null) return 1;	// Resolve reference
		if (o instanceof String)			// Local filename?
			return loadFile((String)o, hist)? 0: 1;	// Load local file
		url = (URL)o;					// Get URL object
		active.setMessage("Contacting "+url.getHost());	// Report status
		try { c = url.openConnection(); }		// Open URL connection
		catch (IOException e) { return 1; }		// No connection?
		active.setMessage("Sending request...");	// Report status
		file = c.getContentType();			// Get content type
		if (file==null) return 1;			// Connection error
		if (file.equals("text/plain")) isPlain = true;	// Plain text?
		else if (file.equals("text/html")) isPlain=false;// HTML text?
		else return 2;					// Not a valid type
		active.setMessage("Reading data...");		// Report status
		try { text = Lib.loadCharStream(c.getInputStream()); } // Read data
		catch (IOException e) { return 1; }		// File read error
		Url = url;					// Set current URL
		setFileData(url.toString(), text);		// Set file name/text
		if (hist) history.add(url.toString());		// Add to history list
		updateWindow(active);				// Update the window
		return 0;					// Return success
	}

	// Retrieve a file and report the final outcome
	boolean openUrl(String file) { return openUrl(file, true); }
	boolean openUrl(String file, boolean hist) {
		if (file==null) return false;			// No file specified?
		if (!checkSave()) return false;			// Save changes
		boolean isLoaded = false;
		String msg = "";
		switch (openLocation(file, hist)) {
		    case 0:
			msg = "Done";				// Success
			isLoaded = true;
			break;
		    case 1:
			msgReport(file, msgReadError());	// File read error
			break;
		    case 2:
			msgReport(file, msgFormatError());	// File format error
			break;
		}
		active.setMessage(msg);				// Set message
		return isLoaded;
	}

	// Create a new empty viewer (destroys editor)
	public void emptyViewer() {
		if (!checkSave()) return;			// Save changes
		resetFileData();				// Default file data
		startViewer();					// Activate viewer
		updateWindow(viewer);				// Destroy editor
	}

	// Create a new empty editor (destroys viewer)
	public void emptyEditor() {
		if (!checkSave()) return;			// Save changes
		resetFileData();				// Default file data
		startEditor();					// Activate editor
		updateWindow(editor);				// Destroy viewer
	}

	// Move to the specified relative position in the history list
	void goHistory(int offset) {
		String s = null;
		if (offset < 0)
			while (offset++ < 0) s = history.backward();
		else	while (offset-- > 0) s = history.forward();
		openUrl(s, false);				// Open file (no history)
	}

// Inner-class used to represent a filename/URL history list
class HistoryList extends LinkList {
	private int listSize, listPos;				// List size/position

	// Constructor
	HistoryList(int size) {
		super();
		listPos = -1;					// Empty history
		listSize = size;				// Set maximum size
	}

	// Add a filename/URL after the current position in the list
	void add(String file) {
		++listPos;					// Next list position
		removeLinksAt(listPos, size() - listPos);	// Remove trailing files
		if (size()>=listSize) removeElementAt(0);	// Restrict size
		addElement(file);				// Append filename
	}

	// Move backward to and return the prior filename/URL in the list
	String backward() {
		return (listPos < 1) ? null : (String)elementAt(--listPos);
	}

	// Move forward to and return the next filename/URL in the list
	String forward() {
		return ((listPos+1)>=size()) ? null : (String)elementAt(++listPos);
	}
}

}

Go To: Source Code