package org.gnue.forms; import javax.swing.JFrame; import java.awt.Dimension; import java.awt.BorderLayout; import java.io.InputStream; import java.io.IOException; import java.util.Vector; import java.util.Enumeration; import java.net.URL; import java.net.MalformedURLException; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; import java.beans.VetoableChangeListener; import java.beans.PropertyVetoException; /** * The ViewFrame is the main window used to display GNU Enterprise Forms. * * When a document is loaded, a new ViewFrame is created with the content * of the document displayed in the content pane * * @see javax.swing.JFrame#getContentPane() * @see javax.swing.JFrame#setContentPane(java.awt.Container) */ public class ViewFrame extends JFrame implements ContainerController, DirectionKind { /** * The property name for the location of this Frame */ public static String locationProperty = "location"; /** * A string representation of the location of the current document * * For URLs, this will be the absulute form of the URL. For local * files, it will be the full path to the document *
* This is a constrained property. Any registered listeners will be
* notified each time a request to change this property is made.
* If any of the listeners veto the change, the property will retain
* its old value. Otherwise the property will be set to the new
* value.
*
* @see #locationProperty
*/
protected String url;
/**
* The Object containing modelling data for this Frame
*
* This is a bounded property. Any registered listeners will be notified
* each time this property is changed.
*
* @see #modelProperty
*/
protected Object model;
private Vector listenerList;
/**
* Create a new ViewFrame.
*
* This ViewFrame will have an initially empty content pane. Use
* setLocation()
to load a Forms document
*
* @see #setLocation(java.lang.String)
*/
public ViewFrame()
{
this(null);
}
/**
* Create a new ViewFrame and display the document at the specified location
*
* @param location the location of the document
*/
public ViewFrame(String url)
{
super("GNUe Forms");
System.out.println("ViewFrame::ViewFrame(java.lang.String)");
listenerList = new Vector();
addVetoableChangeListener(new LocationObserver());
addPropertyChangeListener(new FrameInitializer());
setURL(url);
}
/**
* Returns a string representation of the location of the document
* being displayed
*
* @return the location of the current document, or null
* if no document is being displayed
*/
public String
getURL()
{
return url;
}
/**
* Specify the location of the document to be displayed by this frame
*
* The new document will take the place of the currently displayed
* document
*
* @param url the new location
*/
public void
setURL(String url)
{
System.out.println("ViewFrame->setURL(java.lang.String)");
String oldLoc = this.url;
this.url = url;
if (oldLoc == null || !(url.equalsIgnoreCase(oldLoc)))
{
try
{
fireVetoableChange(locationProperty, oldLoc, url);
}
catch (PropertyVetoException veto)
{
this.url = oldLoc;
}
}
}
/**
* Register the specified listener to be notified when a constrained
* property has changed
*
* @param listener the listener
* @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
*/
public void
addVetoableChangeListener(VetoableChangeListener listener)
{
listenerList.addElement(listener);
}
/**
* Remove the specified the listener from the list of objects being
* notified when a constrained property changes
*
* @param listener
* @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
public void
removeVetoableChangeListener(VetoableChangeListener listener)
{
listenerList.removeElement(listener);
}
protected void
fireVetoableChange(String property,
java.lang.Object oldValue,
java.lang.Object newValue) throws PropertyVetoException
{
Enumeration listeners = listenerList.elements();
PropertyChangeEvent event =
new PropertyChangeEvent(this, property, oldValue, newValue);
while (listeners.hasMoreElements())
{
try
{
VetoableChangeListener listener =
(VetoableChangeListener)listeners.nextElement();
listener.vetoableChange(event);
}
catch (ClassCastException cce)
{
}
}
}
// ControllerContainer methods
public Controller
getParentController()
{
return null;
}
/**
* Return the object responsible for providing modelling data
* for this Frame
*
* @return the model
* @see #setModel(java.lang.Object)
*/
public Object
getModel()
{
return model;
}
/**
* Specify the object to provide modelling data for this Frame
*
* @param model the model
* @see #getModel()
*/
public void
setModel(Object model)
{
System.out.println("ViewFrame->setModel()");
Object oldModel = this.model;
this.model = model;
firePropertyChange(Controller.modelProperty, oldModel, model);
}
public void
transferFocus(int dir)
{
}
public Controller[]
getTraversibleComponents()
{
try
{
Form form = (Form)getModel();
Page[] pages = form.pages();
Controller[] retval = new Controller[pages.length];
for (int i = 0; i < pages.length; i++)
{
Controller controller = new PageController();
controller.setModel(pages[i]);
retval[i] = controller;
}
return retval;
}
catch (NullPointerException npe)
{
return null;
}
}
/**
* This class ensures that a new Form
object is associated
* with this Frame each time the location changes
*/
class LocationObserver
implements VetoableChangeListener
{
public void
vetoableChange(PropertyChangeEvent event) throws PropertyVetoException
{
System.out.println("ViewFrame::LocationObserver->vetoableChange()");
if (event.getPropertyName().equals(locationProperty))
{
try
{
setModel(FormManager.parseURL((String)event.getNewValue()));
}
catch (IOException ioe)
{
System.err.println(ioe);
throw new PropertyVetoException(ioe.getMessage(), event);
}
}
}
}
/**
* This class sets various properties of this Frame when a new model
* is established.
*/
class FrameInitializer
implements PropertyChangeListener
{
public void
propertyChange(PropertyChangeEvent event)
{
System.out.println("ViewFrame::FrameInitializer->propertyChange()");
if (event.getPropertyName().equals(Controller.modelProperty))
{
Form form = (Form)event.getNewValue();
String title = form.getTitle();
int width = form.getWidth()*8;
int height = form.getHeight()*22;
if (title.equals(""))
{
ViewFrame.this.setTitle("GNUe Forms - Untitled");
}
else
{
ViewFrame.this.setTitle("GNUe Forms - " + title);
}
if (width == 0 || height == 0)
{
ViewFrame.this.pack();
}
else
{
ViewFrame.this.setSize(width, height);
}
PageController firstPage = new PageController();
firstPage.setModel(form.getFirstPage());
ViewFrame.this.getContentPane().add(firstPage, BorderLayout.CENTER);
}
}
}
/**
* This class handles registering PropertyChangeListeners whenever
* a new model is specified
*
* @see #setModel(java.lang.Object)
*/
class FormListenerRegistrar
implements PropertyChangeListener
{
public void
propertyChange(PropertyChangeEvent event)
{
if (event.getPropertyName().equals(Controller.modelProperty))
{
Form form = (Form)event.getNewValue();
form.addVetoableChangeListener(new FormDimensionObserver());
}
}
}
/**
* This makes sure that the width
and height
* attributes of the underlying model are accurately reflected
* by this frame
*/
class FormDimensionObserver
implements VetoableChangeListener
{
public void
vetoableChange(PropertyChangeEvent event) throws PropertyVetoException
{
if (event.getPropertyName().equals(Form.dimensionProperty))
{
Dimension dim = (Dimension)event.getNewValue();
if (dim.width < 0 || dim.height < 0)
{
throw new PropertyVetoException("dimensions must be positive",
event);
}
ViewFrame.this.setSize(dim);
}
}
}
}