Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Very interesting

Very interesting

Tutorial Details:

User interfaces for object-oriented systems, Part 3
User interfaces for object-oriented systems, Part 3
By: By Allen Holub
The incredible transmogrifying widget
This month's Java Toolbox continues the object-oriented design/GUI theme by looking at a Collection wrapper that makes it easy to present a visual proxy, as I described in the September Java Toolbox . The wrapper, called a Bag , works just like a Collection -- it implements the java.util.Collection interface. It can, however, create a visual proxy for itself when asked.
Build user interfaces for object-oriented systems: Read the whole series!
Part 1. What is an object? The theory behind building object-oriented user interfaces
Part 2. The visual-proxy architecture
Part 3. The incredible transmogrifying widget
Part 4. Menu negotiation
Part 5. Useful stuff
Part 6. An RPN-calculator application demonstrates object-oriented UI principles
The associated proxy can display the list of elements as a list; a button that, when pressed, pops up a frame containing the list; or a combo box. The display strategy is automatic, controlled by the size of the proxy. The list is used if there's enough space, the button is used when space is tight, and the combo box is used in an in-between situation. Moreover, several such proxies can simultaneously display the same underlying Collection (presumably, on different screens). When the Collection is changed at the model level -- by someone adding or removing a member, for example -- all the proxies will redraw themselves to reflect the change. The notion of selection is supported: When a user selects an element from the UI, a model-level object that's registered as a listener will receive notification. If several proxies are displayed, they can stay in synch with each other. If you select from one, the selections in the others will change as well. (This behavior isn't required, however.)
You may want to download the code from my Web site (see Resources ) and play with this thing a bit to see how it works. Figure 1 illustrates three visual proxies simultaneously displaying the same underlying Collection . The proxy on the left is large enough to have represented itself as a list. The one at the top is a bit smaller, so it has represented itself as a combo box, while the one in the bottom right is smaller still, so it has represented itself as button, which when pressed pops up the frame window that's shown. (The button is disabled as long as the frame window is visible; it's re-enabled automatically when you close the frame.) If you resize any of these windows, they'll transmogrify into one or the other of these three forms as they get larger or smaller. Moreover, if you select a line in any of them, the other two will change to reflect that selection.
Figure 1. The Bag's visual proxy in action
This sort of dynamic adaptability is essential when implementing user interfaces using the architecture that I described in the July and September columns (which you should read before proceeding -- I assume that you're familiar with the architecture I presented in those articles). In this architecture, a control layer builds a presentation from visual proxies of attributes that are provided by an abstraction-layer object. The abstraction layer cannot know the context in which the proxy will be asked to display itself, so the proxy must accommodate whatever space is available automatically.
If the proxy wasn't adaptive in this way, the coupling between the abstraction and presentation layers would be too tight. In an HR application, for example, an employee's identity attribute might want to display a name, an employee ID, and a photograph. Moreover, it will indeed display all three items when there's enough space. If space is tight, the proxy might display itself as a button with the employee's name as the label. If pressed, the button will throw up a frame with the additional information. Adaptability is the key. In any event, all well-written Java applications should make no assumptions about the display environment. The same application that's runs on the 20-inch monitor on your desktop might also have to run on a Palm Pilot at some juncture.
Unfortunately, most of Java's built-in widgets don't work in an adaptable way out of the box. We all wish that the font size on a button's label would grow as the button grows (if it's placed in a GridBag or Grid , for example), but that's not how it works. Instead, you usually end up with minuscule text in on a huge gray button or a button that's too small for the label to print in its entirety. On the other hand, since most Swing widgets support the notion of a renderer -- an object whose job is to draw all or part of the widget -- it's relatively easy to build a set of adaptive widgets on top of Swing. That's what I've done here.
Letting the proxy out of the Bag
Before looking at the implementation, let's look at how it's used. Listing 1 shows the test class from the Bag implementation. Notice that a Bag is as easy to use as a Collection . Indeed, it's just a Collection that can produce its own UI when asked.
The main() method ( Listing 1, line 26 ) creates a Collection by wrapping a LinkedList in a Bag , then adds a few elements to the underlying Collection through the Bag . Note that the Bag is a Collection in a real sense, so you can treat it exactly like one without difficulty (or accessed through a Collection reference). The Bag contains the actual data structure, however. (It's passed in as a constructor argument.)
The Bag is an example of the Gang-of-Four Decorator pattern (see Resources ). A Decorator adds capabilities to the decorated item without using implementation inheritance ( extends ). The java.io package includes many examples of the Decorator pattern. The BufferedInputStream , for example, decorates another InputStream by adding buffering. You don't know whether you're dealing with an actual InputStream or a decorated one when you call read() , however. The BufferedInputStream , therefore, adds the ability to buffer input to a raw InputStream . Similarly, a Bag decorates a Collection in order to add the ability to create a visual proxy on demand.
The Collection object is only wrapped -- it's passed the Bag constructor -- and you can access it directly, rather than through the wrapper, if you like. But as is the case with the java.io Decorators, you should use direct access with care. For example, it would be dangerous to directly access an InputStream that was simultaneously accessed via a BufferedInputStream Decorator elsewhere in the program. In the case of a Bag , it's perfectly safe to examine the wrapped Collection -- traverse it with an iterator, look something up in it, and so on -- without going through the Bag wrapper. Don't modify the wrapped Collection directly, however, do it via the Bag wrapper. If you do decide to directly modify the contained Collection (rather than via the Bag object), be aware that none of the exposed proxies will reflect your modifications. On the other hand, you may want such behavior.
As is the case with many Decorators, the Bag supports a few operations over and above the ones defined in the Collection interface. I invoke one of these -- addActionListener() -- on line 44 to add a listener that reports selected items by printing them onto the console window.
A few lines down, I create (and display) three identical visual proxies by calling create_ui() , which I'll examine momentarily. Then I enter a while loop that adds whatever lines you type on the console window to the current Collection . (This text will appear in all three of the proxy windows.)
The create_ui() method at the top of the listing mimics the behavior of the control object: It creates a frame, retrieves a visual proxy from the Bag (which it treats as a generic «displayable» object, as described last month ), then sets up a listener to handle the window-closing event on the frame and pops the frame into existence.
Listing 1 ( /src/com/holub/ui/Bag.java ): Testing the Bag
1: public static class Test
2: {
3: public void create_ui( Collection aggregate )
4: {
5: JFrame frame = new JFrame();
6:
7: // Get the visual proxy and shove it into the Frame
8:
9: User_interface displayable = (User_interface)aggregate;
10: frame.getContentPane().add(
11: displayable.visual_proxy("Attribute", true) );
12:
13: // Set up a window-closing handler and pop the frame up.
14:
15: frame.addWindowListener
16: ( new WindowAdapter()
17: { public void windowClosing( WindowEvent e )
18: { System.exit(0);
19: }
20: }
21: );
22: frame.pack();
23: frame.show();
24: }
25:
26: public static void main( String[] args ) throws Exception
27: {
28: Collection aggregate = new Bag( new LinkedList(), "outer" );
29: aggregate.add("A");
30: aggregate.add("B");
31: aggregate.add("C");
32: aggregate.add("D");
33:
34: // You need to treat it as a Bag (as compared to a generic
35: // Collection) to install an ActionListener, thus the cast.
36: // It has to be final because it's referenced by the inner-
37: // class object. Note that the listener will report all the
38: // selections associated with displaying the initial UI.
39: // There will be two such notifications (one for the list
40: // and one for the drop-down) for each of the three proxies.
41: // If you don't want this behavior, install the listener
42: // after the visual proxy has been displayed.
43:
44: final Bag the_bag = (Bag) aggregate;
45: the_bag.addActionListener
46: ( new ActionListener()
47: { public void actionPerformed( ActionEvent e )
48: { System.out.println( "Selected " + the_bag.top() );
49: }
50: }
51: );
52:
53: create_ui( aggregate );
54: create_ui( aggregate );
55: create_ui( aggregate );
56:
57: // Transfer all lines typed on the console to the collection.
58:
59: String s;
60: while( (s = com.holub.tools.Std.in().readLine()) != null )
61: { com.hol


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Very interesting

View Tutorial:
Very interesting

Related Tutorials:

Automating WWW Exploration
Automating WWW Exploration
 
Results of first-ever JVM server benchmark revealed - JavaWorld - December 1997
Results of first-ever JVM server benchmark revealed - JavaWorld - December 1997
 
Programming Java threads in the real world, Part 5 - JavaWorld - February 1999
Programming Java threads in the real world, Part 5 - JavaWorld - February 1999
 
An introduction to agents - JavaWorld June 1998
An introduction to agents - JavaWorld June 1998
 
StringBuffer versus String - JavaWorld March 2000
StringBuffer versus String - JavaWorld March 2000
 
Apple announces Java 2 plans at MacWorld
Apple announces Java 2 plans at MacWorld
 
Use the JVM Profiler Interface for accurate timing - JavaWorld
Use the JVM Profiler Interface for accurate timing - JavaWorld
 
Sun lets Jini Starter Kit 1.1 out of the bottle - JavaWorld December 2000
Sun lets Jini Starter Kit 1.1 out of the bottle - JavaWorld December 2000
 
C#: A language alternative or just J--?, Part 2 - JavaWorld December 2000
C#: A language alternative or just J--?, Part 2 - JavaWorld December 2000
 
Become a programming Picasso with JHotDraw - JavaWorld February 2001
Become a programming Picasso with JHotDraw - JavaWorld February 2001
 
Java security evolution and concepts, Part 2
Java security evolution and concepts, Part 2
 
How to build an interpreter in Java, Part 1: The BASICs (JavaWorld / May 1997 / by Chuck McManis)
How to build an interpreter in Java, Part 1: The BASICs (JavaWorld / May 1997 / by Chuck McManis)
 
Interesting informations
Interesting informations
 
Very interesting article
Very interesting article
 
Very interesting
Very interesting
 
Very interesting
Very interesting
 
Interesting concept ...
Interesting concept ...
 
Very interesting
Very interesting
 
JSyntaxColor 1.2.7
JSyntaxColor 1.2.7 JSyntaxColor is a library for coloring in real time user text input.
 
Very interesting tutorial
Introducing the JavaMail API The JavaMail API is an optional package (standard extension) for reading, composing, and sending electronic messages. You use the package to create Mail User Agent (MUA) type programs, similar to Eudora, Pine, and Microsoft O
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.