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