Declarative Programming, emphasizing UI Generation at Runtime
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Declarative Programming, emphasizing UI Generation at Runtime

on

  • 2,951 views

Graphical User Interfaces are described in XML documents that are parsed at runtime and rendered into UI-Widgets. While open-source projects like Thinlet and Swixml focus mainly on the GUI, they are ...

Graphical User Interfaces are described in XML documents that are parsed at runtime and rendered into UI-Widgets. While open-source projects like Thinlet and Swixml focus mainly on the GUI, they are also good examples for how declarative programming can be done in Java.

Statistics

Views

Total Views
2,951
Views on SlideShare
1,041
Embed Views
1,910

Actions

Likes
0
Downloads
5
Comments
0

5 Embeds 1,910

http://wolfpaulus.com 1902
http://translate.googleusercontent.com 3
http://www.google.ca 3
http://www.google.com 1
http://www.google.hr 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Declarative Programming, emphasizing UI Generation at Runtime Presentation Transcript

  • 1. Declarative Programming :UI-Generation at Runtime with SwixML wolfpaulus.com Wolf Paulus
  • 2. 1. Declarative Programming 2. Reflection and Introspection in JAVA 3. Thinlets, Declarative GUI Toolkit for Java 4. Theodore, a Thinlet XUL Editor 1.Demo and Code 5. Swixml, GUI Generation Engine 6. Custom Tags and Bindings 7. Mapping of private members 1. Code, Demo and more Code© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 3. Wikipedia: Declarative programming concentrates on expressing a set of conditions, describing a solution space, but leaves finding a solution to an engine, dedicated to a certain class of problems.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 4. Writing programs in a declarative style in an imperative programming language usually requires lots of runtime information.* *for Java, this means Reflection & Introspection© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 5. Wikipedia: Computational reflection is the ability of a program to observe and possibly modify its high level structure. It is most common in high-level virtual machine programming languages like Smalltalk, and less common in lower-level programming languages like C.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 6. Reflection in Java Java allows a program to discover information about the fields, methods, and constructors of loaded classes. Also, a Java program can instantiate a class and operate on the underlying objects, (within security restrictions.) Reflection is the process of looking at an object during run time in order to understand its features or properties. Where the reflection process analyzes the object itself to discover the object’s properties, Introspection relies on the class to provide information on its behalf.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 7. Reflection package com.carlsbadcubes.codecamp; import java.lang.reflect.Method; import java.util.Vector; public class Reflector { /** * Find all methods that can be called on the given object that * <li> start with the prefix <i>set</i> </li> * <li> take only a single parameter </li> * <li> and have the return type <i>void</i></li> * @param client <code>Object</code> * @return <code>Vector</code> containing possibly setters methods */ public static Vector<Method> getSetters(final Object client) { Vector<Method> setters = new Vector<Method>(); Method[] methods = client.getClass().getMethods(); for (Method method : methods) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && method.getReturnType() == void.class) { setters.add(method); } } return setters; } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 8. Reflection TestCase package com.carlsbadcubes.codecamp; import junit.framework.TestCase; import javax.swing.*; import java.lang.reflect.Method; import java.util.Vector; public class ReflectorTest extends TestCase { public void testFindSetters() { Object obj = new JLabel("hello"); Vector<Method> setters = Reflector.getSetters(obj); TestCase.assertTrue(setters != null); TestCase.assertTrue(0 < setters.size()); for (Method setter : setters) System.out.println( setter.getDeclaringClass().getName() +":"+ setter); } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 9. Methods found: javax.swing.JLabel public void javax.swing.JLabel.setUI(javax.swing.plaf.LabelUI) public void javax.swing.JLabel.setText(java.lang.String) public void javax.swing.JLabel.setIcon(javax.swing.Icon) public void javax.swing.JLabel.setDisabledIcon(javax.swing.Icon) public void javax.swing.JLabel.setVerticalAlignment(int) public void javax.swing.JLabel.setHorizontalAlignment(int) public void javax.swing.JLabel.setVerticalTextPosition(int) public void javax.swing.JLabel.setHorizontalTextPosition(int) public void javax.swing.JLabel.setIconTextGap(int) public void javax.swing.JLabel.setDisplayedMnemonicIndex(int) public void javax.swing.JLabel.setDisplayedMnemonic(int) public void javax.swing.JLabel.setDisplayedMnemonic(char) public void javax.swing.JLabel.setLabelFor(java.awt.Component)© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 10. javax.swing.JComponent public void javax.swing.JComponent.setEnabled(boolean) public void javax.swing.JComponent.setVisible(boolean) public void javax.swing.JComponent.setForeground(java.awt.Color) public void javax.swing.JComponent.setBackground(java.awt.Color) public void javax.swing.JComponent.setFont(java.awt.Font) public void javax.swing.JComponent.setNextFocusableComponent(java.awt.Component) public void javax.swing.JComponent.setRequestFocusEnabled(boolean) public void javax.swing.JComponent.setVerifyInputWhenFocusTarget(boolean) public void javax.swing.JComponent.setPreferredSize(java.awt.Dimension) public void javax.swing.JComponent.setMaximumSize(java.awt.Dimension) public void javax.swing.JComponent.setMinimumSize(java.awt.Dimension) public void javax.swing.JComponent.setBorder(javax.swing.border.Border) public void javax.swing.JComponent.setAlignmentY(float) public void javax.swing.JComponent.setAlignmentX(float) public void javax.swing.JComponent.setInputVerifier(javax.swing.InputVerifier) public void javax.swing.JComponent.setDebugGraphicsOptions(int) public final void javax.swing.JComponent.setActionMap(javax.swing.ActionMap) public static void javax.swing.JComponent.setDefaultLocale(java.util.Locale) public void javax.swing.JComponent.setToolTipText(java.lang.String) public void javax.swing.JComponent.setAutoscrolls(boolean) public void javax.swing.JComponent.setTransferHandler(javax.swing.TransferHandler) public void javax.swing.JComponent.setOpaque(boolean) public void javax.swing.JComponent.setDoubleBuffered(boolean)© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 11. java.awt.Container public void java.awt.Container.setLayout(java.awt.LayoutManager) public void java.awt.Container.setFocusTraversalPolicy(java.awt.FocusTraversalPolicy) public void java.awt.Container.setFocusCycleRoot(boolean) java.awt.Component public void java.awt.Component.setName(java.lang.String) public void java.awt.Component.setSize(java.awt.Dimension) public synchronized void java.awt.Component.setDropTarget(java.awt.dnd.DropTarget) public void java.awt.Component.setLocale(java.util.Locale) public void java.awt.Component.setLocation(java.awt.Point) public void java.awt.Component.setBounds(java.awt.Rectangle) public void java.awt.Component.setCursor(java.awt.Cursor) public void java.awt.Component.setIgnoreRepaint(boolean) public void java.awt.Component.setFocusable(boolean) public void java.awt.Component.setFocusTraversalKeysEnabled(boolean) public void java.awt.Component.setComponentOrientation(java.awt.ComponentOrientation)© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 12. Introspection package com.carlsbadcubes.codecamp; import java.lang.reflect.*; public class Introspector { /** * Trys to instantiate a given class using its default constructor * then its sets its name using a setName(String name) method. * @param classname <code>String</code> - name of the class to be loaded and instantiated * @param name <code>String</code> - parameter to be used in a setName method * @return <code>Object</code> of the given class or null. */ public static Object createNamedInstance(String classname, String name) { Object obj = null; try { Class cls = Class.forName(classname); // shortcut would be to just call cls.newInstance(); Constructor ctor = cls.getConstructor(); // gets the default ctor if available. obj = ctor.newInstance(); // call with empty parameter array Method method = cls.getMethod("setName", String.class); method.invoke(obj, name ); } catch (ClassNotFoundException e) { // intent. empty } catch (NoSuchMethodException e) { // intent. empty } catch (InstantiationException e) { // intent. empty } catch (IllegalAccessException e) { // intent. empty } catch (InvocationTargetException e) { // intent. empty } return obj; } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 13. Introspection package com.carlsbadcubes.codecamp; import java.lang.reflect.*; public class Introspector { public static Object createNamedInstance( String classname, String name ) { !Object obj = null; !try { ! ! ! Class cls = Class.forName( classname ); // shortcut would be to just call cls.newInstance(); Constructor ctor = cls.getConstructor(); // gets the default ctor obj = ctor.newInstance(); // call with empty parameter array Method method = cls.getMethod( "setName", String.class ); method.invoke( obj, name ); ! ! ! } catch (Exception e) { // intent. empty !} !return obj; } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 14. Introspection TestCase package com.carlsbadcubes.codecamp; import junit.framework.TestCase; import javax.swing.*; public class IntrospectorTest extends TestCase { public void testInstatiate() { ! ! Object obj = ! ! Introspector.createNamedInstance("javax.swing.JLabel", "myLabel"); ! ! TestCase.assertTrue( obj != null ); ! TestCase.assertTrue( JLabel.class.equals(obj.getClass()) ); ! TestCase.assertEquals( "myLabel", ((JLabel) obj).getName() ); ! } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 15. Declarative Programming for GUIs Alternative to code generation Decouple GUI Definition from Code Expressive and Compact Maintainable and Independent© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 16. XUL - XAML - MXML • Separating the GUI layout from the GUI logic (event-handlers) is not new - describing the UI in XML is methodology de jour. • Xml User Interface Language is a markup language for describing user interfaces. • XUL Engine (a.k.a XUL Motor) converts XML descriptors into a User Interface at Runtime. • XUL dialects exist for almost any platform and for many programming languages.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 17. XUL ENGINES Mozilla - http://www.mozilla.org Runs on Mac OS, Linux, Solaris, FreeBSD, Irix, BeOS, HPUX, OS/2, BSD, and more Luxor - http://luxor-xul.sourceforge.net Xul toolkit includes web server, portal engine, template engine, scripting interpreter etc. SwixML - http://www.swixml.org Tiny (less than 50k) XUL Motor in Java for creating Swing UIs for apps or applets Xoetrope XUI -http://www.xoetrope.com/xui XUL motor in Java for building AWT UIs running on Java 1.1.8 and up; Thinlets - http://www.thinlet.com Tiny XUL Motor in Java (less than 40k); designed for applets or mobile devices; runs even on Java 1.1; no Swing support.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 18. Joshua Marinacci, Member of Sun’s Swing Team: “The net result of working with SwixML is delivering better-looking applications in less time, and that is always a good thing.” Ben Galbraith, author of Professional JSP 2.0 and Professional Apache Tomcat: “SwixML is the most mature XUL/Swing offering. If youre looking for a way to define your Swing UIs in XML, SwixML is one of the best choices around.” Rick Jelliffe, CTO of Topologi: “By moving to SwixML, we reduced source code size by 500k and improved maintainability and startup time.” Kate Rhodes: “I think that SwixML is the easiest way to define a Swing layout, period.” Hans Mueller, CTO for Suns Desktop Division: ”When defining Java Swing GUIs declaratively, SwixML is the strongest example.”© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 19. http://www.swixml.org/TS-7122.pdf© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 20. • SwiXml, is a small GUI generating engine for Java applications and applets. Graphical User Interfaces are described in XML documents that are parsed at runtime and rendered into javax.swing objects.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 21. Swixml, a different XUL Motor focus is completely on javax.swing. Programmers knowing Swing can immediately start writing descriptors. No additional XML dialect has to be learned: Class names translate into tags and method names into attributes. fast - since no additional layers had to be added on top of the Swing objects. small - despite the fact that the swixml.jar file is only about 50 Kbyte in size, almost all Swing objects and widgets are supported.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 22. Inside Swixml Hello World - XUL Descriptor <?xml version="1.0" encoding="UTF-8"?> <frame size="440,380" title="Hello SWIXML World"> <panel constraints="BorderLayout.NORTH"> <label font="ARIAL-BOLD-16" foreground="blue" text="Hello World!"/> </panel> <panel constraints="BorderLayout.SOUTH"> <button text="Click Here" /> </panel> </frame>© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 23. Inside Swixml Hello World - Java Code public class Foo { public Foo() throws Exception { new SwingEngine().render( "xul/gui.xml").setVisible( true ); } public static void main( String[] args ) throws Exception { new Foo(); } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 24. Inside Swixml Simple Editor - XUL Descriptor <?xml version="1.0" encoding="UTF-8"?> <frame size="440,380" title="Hello SWIXML World"> <panel constraints="BorderLayout.NORTH"> <label font="ARIAL-BOLD-16" foreground="green" text="Swixml Editor"/> </panel> <scrollpane><editorpane id=”ep”/></scrollpane> <panel constraints="BorderLayout.SOUTH"> <button text="Click Here" action=”show”/> </panel> </frame>© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 25. Inside Swixml Simple Editor - Java Code public class Foo { private JEditorPane ep; public Action show = new AbstractAction() { public void actionPerformed( ActionEvent event ) { new SwingEngine().render( new StringReader( ep.getText() ) ).setVisible( true ); } }; public Foo() throws Exception { new SwingEngine( this ).render( "xul/gui.xml").setVisible( true ); } public static void main( String[] args ) throws Exception { new Foo(); } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 26. Inside the Swixml Motor Swixml introspects all the registered classes for their constructors and set-methods. In case a setter methods parameters can be constructed by converting a String, the setter gets registered and can be called through an xml attribute. <label text="My blue label" color="blue"/> works, because a JLabels setText(String s) methods takes a String typed parameter and Swixml provides a ColorConverter, capable of converting a String into a java.awt.Color typed object. There is also the initclass attribute, which is useful when the class that is represented by the tag name, needs to be instantiated by something other than the default-contructor. <combobox initclass="com.xyz.ComboModel" /> instantiates a JComboBox class by using the constructor that takes a ComboBoxModel parameter: JComboBox(ComboBoxModel aModel)© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 27. Mapping private members private void mapMembers( Object obj, Class cls ) { if (obj != null && cls != null && !Object.class.equals( cls )) { Field[] flds = cls.getDeclaredFields(); for (int i = 0; i < flds.length; i++) { Object widget = idmap.get( flds[i].getName() ); if ( widget != null && flds[i].getType().isAssignableFrom ( widget.getClass() ) && !Modifier.isTransient( flds[i].getModifiers() )) { try { boolean accessible = flds[i].isAccessible(); flds[i].setAccessible(true); flds[i].set(obj, widget); flds[i].setAccessible( accessible ); } catch ( .. ) { } } } mapMembers( obj, cls.getSuperclass() ); } }© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 28. Don’t get me wrong ... Ive talked a lot about how declarative programming and especially UI definition takes up less lines of code.  But there are hundreds of lines of parser code supporting the declarative UI definition, remember he two phases: Declaration and Interpretation?  I would rather see you think about where you can take advantage of declarative programming, like in areas where you want to abstract functionality to gain flexibility in maintenance or extensibility.© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 29. Q&A© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com
  • 30. Thanks for coming© 2003-2006 Carlsbad Cubes© 2009 wolfpaulus.com