kawigi.cmd
Class UIHandler

java.lang.Object
  extended by org.xml.sax.helpers.DefaultHandler
      extended by kawigi.cmd.UIHandler
All Implemented Interfaces:
org.xml.sax.ContentHandler, org.xml.sax.DTDHandler, org.xml.sax.EntityResolver, org.xml.sax.ErrorHandler

public class UIHandler
extends org.xml.sax.helpers.DefaultHandler

This class loads UI constructs from XML. This has a bit of magic that needs to be cleaned up a bit, and the answer may be to just set properties' values in such a way that is strongly typed.


Constructor Summary
UIHandler(Dispatcher disp)
          Constructs a new UIHandler to handle an XML GUI specification and create actions using the given Dispatcher.
 
Method Summary
 void characters(char[] ch, int start, int length)
          Notifies us of non-tag characters between tags.
 void endDocument()
          Notifies us that the parser has reached the end of the UI document.
 void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName)
          Notifies us of an end tag being reached.
 void fatalError(org.xml.sax.SAXParseException e)
          Notifies us of any error encountered in parsing.
 java.awt.Container getCurrentComponent()
          Returns the control that we created, or null if we aren't finished.
static java.awt.Container loadMenu(MenuID menu, Dispatcher disp)
          Returns the result of loading of the given MenuID, and actions will be created using the given Dispatcher.
static void reportError(java.lang.Throwable e, boolean warning)
          Prints the stack trace of an error or warning and notifies the user with a dialog.
 void startDocument()
          Called when we begin parsing the GUI XML.
 void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes attributes)
          Called when a start XML tag is encountered.
 void warning(org.xml.sax.SAXParseException e)
          Notifies us of any recoverable warning encountered in parsing.
 
Methods inherited from class org.xml.sax.helpers.DefaultHandler
endPrefixMapping, error, ignorableWhitespace, notationDecl, processingInstruction, resolveEntity, setDocumentLocator, skippedEntity, startPrefixMapping, unparsedEntityDecl
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

UIHandler

public UIHandler(Dispatcher disp)
Constructs a new UIHandler to handle an XML GUI specification and create actions using the given Dispatcher.

Method Detail

loadMenu

public static java.awt.Container loadMenu(MenuID menu,
                                          Dispatcher disp)
Returns the result of loading of the given MenuID, and actions will be created using the given Dispatcher.


getCurrentComponent

public java.awt.Container getCurrentComponent()
Returns the control that we created, or null if we aren't finished.


startDocument

public void startDocument()
Called when we begin parsing the GUI XML.

Specified by:
startDocument in interface org.xml.sax.ContentHandler
Overrides:
startDocument in class org.xml.sax.helpers.DefaultHandler

startElement

public void startElement(java.lang.String uri,
                         java.lang.String localName,
                         java.lang.String qName,
                         org.xml.sax.Attributes attributes)
Called when a start XML tag is encountered. Here, we create the control as specified by the opening tag, but its creation isn't really complete until we get the end tag. This control will be set as the current one, and will be added to the old current control. There are parts of this method that I'm not proud of - in theory, you should be able to put attributes on these tags in the form X="val" and this code will call setX("val") on that control for you, but it's a bit quirky. It doesn't seem to be able to call methods inherited by the controls from their parent classes. It also should work for "setX"s that take strings, booleans and ints as parameters, but the way I do that is really hacky and should be smitten. One solution might be to require the attributes' values to be strongly typed in some way (which makes it easy to be perfectly flexible, but harder for people to learn). Another thing I could do is to absolutely limit these calls to single- parameter setX methods that take primitive types or strings as parameters, and just hope that they aren't overloaded with more than one supported type, and try to coerce the value into one of those types. Either way, this method isn't perfect, it just "works" for the UI we have right now because I made it so :-) There are three attributes that are treated specially (no setX method is called for them). The first is Action, which specifies the ActID for the control, which bounds it to data and an action. The second is MenuID, which if specified, will cause another .ui file to be inserted (this is how the snippet menu is inserted into the right-click menu). The third special attribute is DispatcherName, which tells us that a certain control is some important UI element that actions are going to want global access to, like the main editor.

Specified by:
startElement in interface org.xml.sax.ContentHandler
Overrides:
startElement in class org.xml.sax.helpers.DefaultHandler

characters

public void characters(char[] ch,
                       int start,
                       int length)
Notifies us of non-tag characters between tags. Normally we don't care about what's here, except in the case of Snippet controls. If the current component is a snippet, these characters are part of the "code" in the snippet. Unfortunately, the SAX parser doesn't give us all the contiguous non-tag characters at once, they give us stuff line by line, so when creating the snippets, we have to append the input of each of these calls into the snippet's code.

Specified by:
characters in interface org.xml.sax.ContentHandler
Overrides:
characters in class org.xml.sax.helpers.DefaultHandler

endElement

public void endElement(java.lang.String uri,
                       java.lang.String localName,
                       java.lang.String qName)
Notifies us of an end tag being reached. Once this is called, we are done working with the current component, so we pop its parent off the hierarchy stack and the parent becomes the current component again, unless there is nothing in the stack, which generally means that this is the last end tag in the document.

Specified by:
endElement in interface org.xml.sax.ContentHandler
Overrides:
endElement in class org.xml.sax.helpers.DefaultHandler

endDocument

public void endDocument()
Notifies us that the parser has reached the end of the UI document.

Specified by:
endDocument in interface org.xml.sax.ContentHandler
Overrides:
endDocument in class org.xml.sax.helpers.DefaultHandler

fatalError

public void fatalError(org.xml.sax.SAXParseException e)
Notifies us of any error encountered in parsing.

Specified by:
fatalError in interface org.xml.sax.ErrorHandler
Overrides:
fatalError in class org.xml.sax.helpers.DefaultHandler

warning

public void warning(org.xml.sax.SAXParseException e)
Notifies us of any recoverable warning encountered in parsing.

Specified by:
warning in interface org.xml.sax.ErrorHandler
Overrides:
warning in class org.xml.sax.helpers.DefaultHandler

reportError

public static void reportError(java.lang.Throwable e,
                               boolean warning)
Prints the stack trace of an error or warning and notifies the user with a dialog. Under normal conditions, users shouldn't get any of these dialogs, they are to notify people modifying the UI that something didn't work quite right.