[luxor-xul-develop] Possible method for extending XUL tag set in Luxor
Status: Beta
Brought to you by:
vamp201
From: mhenderson <mhe...@be...> - 2002-08-30 18:11:18
|
Hi, I looked over the 1.0b5 source code and tried a technique to externalize the mapping from xul element tag (<button>, etc) to the XULNode class. I modified XulLoader.java: /* ** Luxor - XML User Interface Language (XUL) Toolkit ** Copyright (c) 2001, 2002 by Gerald Bauer ** ** This program is free software. ** ** You may redistribute it and/or modify it under the terms of the GNU ** General Public License as published by the Free Software Foundation. ** Version 2 of the license should be included with this distribution in ** the file LICENSE, as well as License.html. If the license is not ** included with this distribution, you may find a copy at the FSF web ** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the ** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA. ** ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR ** REDISTRIBUTION OF THIS SOFTWARE. ** */ package luxor.core; import java.lang.reflect.*; import java.io.*; import java.util.*; import org.jdom.*; import org.jdom.input.*; import luxor.core.box.*; import luxor.core.data.*; import luxor.core.grid.*; import luxor.core.input.*; import luxor.core.menu.*; import luxor.core.misc.*; import luxor.core.portal.*; import luxor.core.tab.*; import luxor.core.table.*; import luxor.core.toolbar.*; import luxor.core.widget.*; import luxor.core.xslt.*; import houston.*; import luxor.*; public class XulLoader { private static Properties defMap; static { try { defMap = new Properties(); defMap.load(XulLoader.class.getResourceAsStream("XulNodeMap.properties")); } catch (Exception ex) { } } private static String getDefClassNameForType(String type) { return (String)defMap.get(type); } static Logger T = Logger.getLogger( XulLoader.class ); private XulManager _manager; public XulLoader( XulManager manager ) { _manager = manager; } public void load( String name ) { try { T.debug( "loading xul file " + name ); InputStream in = _manager.getResourceAsStream( name ); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build( in ); Element xul = doc.getRootElement(); createElements( null, xul ); T.debug( "xul file " + name + " successfully loaded" ); } catch( JDOMException jex ) { Xul.error( "failed to load xul file '" + name + "': " + jex.toString() ); } } protected void createElements( XulContainer parent, Element element ) { String type = element.getName(); if( type.equals( Xul.Element.XUL ) ) { parent = new XulDef( element, _manager ); } else { try { String defClassName = getDefClassNameForType(type); Class defClass = Class.forName(defClassName); Class[] types = new Class[] { Element.class, }; Constructor constructor = defClass.getConstructor(types); Object[] args = new Object[] { element }; XulNode def = (XulNode)constructor.newInstance(args); parent.add(def); parent = (def instanceof XulContainer) ? (XulContainer)def : null; } catch (Exception ex) { System.out.println("Exception: " + ex); ex.printStackTrace(); Xul.syntax( "unsupported element '" + type + "'" ); } } if (parent != null) { // process children List list = element.getChildren(); for( Iterator it = list.iterator(); it.hasNext(); ) { Element child = ( Element ) it.next(); createElements( parent, child ); } } } } // END of source and added a properties file: anim=luxor.core.misc.AnimDef box=luxor.core.box.BoxDef button=luxor.core.input.ButtonDef caption=luxor.core.box.CaptionDef checkbox=luxor.core.input.CheckBoxDef choice=luxor.core.input.ChoiceDef col=luxor.core.widget.ColDef colgroup=luxor.core.widget.ColGroupDef column=luxor.core.grid.ColumnDef columns=luxor.core.grid.ColumnsDef command=luxor.core.misc.CommandDef componentref=luxor.core.widget.ComponentRef datagrid=luxor.core.widget.DataGridDef displayurl=luxor.core.menu.DisplayUrlDef entry=luxor.core.data.ListEntryDef gadgetluxor.core.widget.ComponentRef grid=luxor.core.grid.GridDef groupbox=luxor.core.box.GroupBoxDef hbox=luxor.core.box.HBoxDef icon=luxor.core.misc.IconDef iframe=luxor.core.widget.IFrameDef image=luxor.core.widget.ImageDef key=luxor.core.misc.KeyDef keyset=luxor.core.misc.KeySetDef # more fancy synomym for componentref label=luxor.core.input.LabelDef list=luxor.core.data.ListDef map=luxor.core.data.MapDef mchoice=luxor.core.input.MChoiceDef menu=luxor.core.menu.MenuDef menubar=luxor.core.menu.MenuBarDef menuitem=luxor.core.menu.MenuItemDef menupopup=luxor.core.menu.MenuPopupDef menuref=luxor.core.menu.MenuRef menuseparator=luxor.core.menu.MenuSeparatorDef password=luxor.core.input.PasswordDef popup=luxor.core.menu.PopupDef portal=luxor.core.PortalDef portlet=luxor.core.PortletRef pre=luxor.core.misc.PreDef row=luxor.core.grid.RowDef rows=luxor.core.grid.RowsDef separator=luxor.core.widget.SeparatorDef spacer=luxor.core.widget.SpacerDef stylesheet=luxor.core.xslt.StylesheetDef tab=luxor.core.tab.TabDef tabbox=luxor.core.tab.TabBoxDef table=luxor.core.table.TableDef tabpanel=luxor.core.tab.TabPanelDef tabpanels=luxor.core.tab.TabPanelsDef tabs=luxor.core.tab.TabsDef td=luxor.core.table.TableDataDef text=luxor.core.input.TextDef textarea=luxor.core.input.TextAreaDef toolbar=luxor.core.toolbar.ToolBarDef toolbarbutton=luxor.core.toolbar.ToolBarButtonDef toolbarseparator=luxor.core.toolbar.ToolBarSeparatorDef tr=luxor.core.table.TableRowDef tree=luxor.core.widget.TreeDef vbox=luxor.core.box.VBoxDef I tested this with box.jnlp in ramses and it seemd to work. It's just a quick hack, and it might be better to use an xml file format where the content can be extended eg: <xul-tag name="button" node="luxor.core.input.ButtonDef" /> One benefit here is that the set of tags can be extended, especially if the 'discovery' mechanism searches for these tag mapping files on the class path. I would prefer to have a separate class to deal with this mapping (XulNodeMap?) and let XulLoader deal with it via an interface. The implementation of the interface could be decided from a config file which would make the thing pluggable (Swing/SWT?) What do you think? Mike |