Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News


2008 West
DIAMOND SPONSOR:
Data Direct
SOA, WOA and Cloud Computing: The New Frontier for Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
GOLD SPONSORS:
Appsense
User Environment Management – The Third Layer of the Desktop
Cordys
Cloud Computing for Business Agility
EMC
CMIS: A Multi-Vendor Proposal for a Service-Based Content Management Interoperability Standard
Freedom OSS
Practical SOA” Max Yankelevich
Intel
Architecting an Enterprise Service Router (ESR) – A Cost-Effective Way to Scale SOA Across the Enterprise
Sensedia
Return on Assests: Bringing Visibility to your SOA Strategy
Symantec
Managing Hybrid Endpoint Environments
VMWare
Game-Changing Technology for Enterprise Clouds and Applications
Click For 2008 West
Event Webcasts

2008 West
PLATINUM SPONSORS:
Appcelerator
Get ‘Rich’ Quick: Rapid Prototyping for RIA with ZERO Server Code
Keynote Systems
Designing for and Managing Performance in the New Frontier of Rich Internet Applications
GOLD SPONSORS:
ICEsoft
How Can AJAX Improve Homeland Security?
Isomorphic
Beyond Widgets: What a RIA Platform Should Offer
Oracle
REAs: Rich Enterprise Applications
Click For 2008 Event Webcasts
SYS-CON.TV
Top Links You Must Click On


Cascading JFrames
Cascading JFrames

If you haven't tried it yet, Swing is Good. For those of us who've had to wrestle with the java.awt to build GUIs, Swing is a much simpler and more powerful alternative. With its "coming soon" status in the com.sun.java.swing classes in JFC 1.0 upgraded to "officially blessed into Java" as javax.swing in JDK 1.2, Java application developers everywhere should be pleased. Although it's only a Java extension and not part of the core library, we should be fine since right now we really don't need GUI support for doorbells, toasters or electric frying pans.

For general Java programming, Swing works pretty well out of the box. Text fields, text areas, buttons, labels, lists and trees cover a large majority of what the average GUI developer needs. However, for harder-core development, Swing still needs some customization. I'm an infrastructural programmer at heart; every time I need to customize something in Java, I try to do it right, once, and add the improvements to my personal Java packages. Every time I do a new project my toolbox expands a little bit more. While working on a recent project I needed to build a facility for automatically positioning windows. Over the years, I've hacked autopositioning several times in C, C++ and Objective C. This time I decided to do a nice, clean Java implementation.

The Autopositioning Problem
The class that most developers use as the base for a window on a screen in Swing is JFrame. Left to themselves, JFrames are initially positioned at (0,0). When they're shown, each new JFrame will stack up, one on top of the other, with all of their origins at (0,0) - obscuring previously created JFrames, as shown in Figure 1a. In any real application, this gets to be difficult for the user: each new window has to be selected and moved by hand. Autopositioning should be done prior to the first appearance of a window, in a way that lets the user identify it easily in relation to its neighbors. (a) default positions, and (b) cascaded positions

The JFrame inherits the java.awt.Frame lineage, along with its ancestor java.awt.Component handling positioning. A component is positioned using its setBounds() method, and the new intended position and size of the component are provided as arguments. Assuming we know the size, we need to assign a reasonable new (x,y) location to the JFrame for autopositioning prior to the first call to setBounds().

A popular strategy for keeping windows from obscuring each other is by cascading them - staggering them within an area so that new windows roll across it in an orderly fashion, each slightly offset from the previous one, as shown in Figure 1b. When the position reaches a predetermined limit, it's wrapped around and the staggering cycle starts again. Many windowing applications use this strategy today, and it's the one I constructed, but in a very robust way.

The Cascade Object
The workhorse of our code is the Cascade object. A Cascade implements the cascading behavior in one dimension: an instance steps across locations within an area, wrapping around at the end. The object has two principal behaviors, one to get the current location:

public int location ()

and another to increment it:

public void increment ()

When a Cascade is created it is set with default values that implement a default staggering and wrapping behavior. These values will all have set and get methods so that custom cascading may be configured. Each Cascade requires four parameters to implement a robust behavior: an offset, a position, a step and a wrap, related schematically in Figure 2. The location is equal to the offset+position, and when the Cascade is incremented, step is added to position. Position is then effectively adjusted to be within wrap's limits via a modulus function. The values for wrap must be greater than zero, while the values for offset and step may be assigned any value. Although the initial value of position may be set arbitrarily, subsequent values are calculated using the other parameters.

Besides these behaviors, there are the requisite canonical inclusions for serialization, cloning and content-based equality tests. It's always a good practice to throw them in because you never know what you may want to do with the object later, and they're easier to add while you're writing the code rather than as an afterthought. In addition to the default constructor, a version that takes the four parameters is also provided. The source code for the Cascade class appears in Listing 1.

It should be noted that after enough cycles of stepping and wrapping, the generated position will begin to repeat. That's the nature of a modulus function applied to a monotonically increasing value. Even though it can't be eliminated, by choosing the step and wrap values carefully, the cycle of repetition can be made quite long - long enough so that only applications that are incrementing the Cascade many, many times will cause it to cycle.

The PointCascade Object
In order to cascade a two-dimensional location, you simply use two Cascade objects, one for the x dimension, and another for the y dimension. The PointCascade class wraps together two Cascade objects under one interface. It allows access to the underlying Cascades directly or manages them indirectly through messages that take java.awt.Point objects as arguments. The same set and get methods that are provided in Cascade are also provided in PointCascade, but with Points as arguments instead of integers. Methods to set and get the xCascade and yCascade are provided as well.

The signature of the increment() method is the same in the PointCascade as it was in the Cascade, but the PointCascade's location method now returns a Point object. This point is cascaded in x and y - we'll use it to position a JFrame. The staggering and wrapping can be set independently for the x and the y coordinates so a large set of noncycled, cascaded points can be created. However, if the Cascade defaults are used, the x and y coordinates will increment in lockstep, and only points on a diagonal will be generated. Again, the way to overcome this is to set up the parameters of the embedded Cascade objects carefully. By adjusting the step and wrap values of either or both of the Cascade objects, the cascading can be made to behave very differently in x and y. The source code for PointCascade is in Listing 2.

The CascadingJFrame Object
To make JFrames cascade themselves automatically, a new location must be retrieved from the PointCascade object when a new JFrame is created, and then the PointCascade must be incremented. Subsequently, when the JFrame is first positioned, its setBounds() method places the JFrame at the new location. The easiest way to do this in Java is through inheritance.

The CascadingJFrame class is a subclass of JFrame that contains a static PointCascade. After the JFrame has been created, the constructor gets the PointCascade's location, increments the PointCascade to set up for the next invocation and sets an autoposition flag to true. The class also overrides both of the JFrame's setBounds() methods. If the autoposition flag is set, the generated location is used in the call to the JFrame's setBounds() method to do the actual positioning. The PointCascade is static since it has to be shared between all the instances of CascadingJFrame. Each CascadingJFrame stores its generated location, but the PointCascade that generates these locations is a common resource. If any of the PointCascade's values are changed after locations have been generated, only the subsequently generated CascadingJFrame locations will be affected. The CascadingJFrame class has static methods to set and get its underlying PointCascade.

The cascading mechanism can also be negated in certain cases if desired. If the application determines that a particular CascadingJFrame is somehow special, then the initial positioning can either be adjusted by calling the CascadingJFrame's setLocation() method with the special location as a Point, turning off the autopositioning altogether, calling the CascadingJFrame's setAutoposition() method with a false value or using an extended constructor.

With a good understanding of the cascading mechanism, complete control of autopositioning is possible. It's as simple as that.

Multiple Cascades
But we can always make it more robust! It isn't enough to simply cascade. I immediately found that I wanted to have different types of windows cascading in different ways. For instance, in one area of the screen I wanted a stack of small windows, and in another a staggered set of larger ones. Applications all have their own idiosyncrasies; my goal was simply to cover most of the regular ones with the simple CascadingJFrame objects. The solution I implemented was to make the CascadingJFrame class contain multiple static PointCascade objects that could be arbitrarily named by the application. When a CascadingJFrame object is constructed, the application can specify the particular PointCascade to use for autopositioning.

To avoid adding complexity for the developer, the simple, unnamed-PointCascade case should continue to work; the calls to CascadingJFrame without a named PointCascade need to remain available. After all, plenty of applications do not require rigorous control or multiple streams of autopositioning. For most developers, using a single PointCascade would suffice, with only a few odd JFrames positioned directly. For these situations a default PointCascade is managed behind the scenes for the unnamed-PointCascade calls.

To implement the multiple PointCascade objects, the CascadingJFrame is made to contain a static hashtable of named PointCascades instead of just a single static PointCascade. The calls to CascadingJFrame without names are connected to the named calls using the default PointCascade's internal name. This way, when an unnamed PointCascade call comes in, the default PointCascade object is retrieved from the hashtable, used to get the location and incremented. If a named call comes in, the particular PointCascade is looked up, used and incremented. If the specified PointCascade is not in the hashtable, a new one is created and used. In this way the application maintains complete control over the autopositioning namespace. The source code for CascadingJFrame is in Listing 3.

Summary
The overall Design of the CascadingJFrame is shown in Figure 3. The important thing to notice is that the CascadingJFrame class contains the hashtable of PointCascade objects, not a CascadingJFrame instance. The instance simply contains the location that was retrieved from a specific PointCascade and an autoposition flag indicating whether or not the retrieved location should be used. The hashtable is a static - effectively shared by all the CascadingJFrame instances.Figure 3: The cascading JFrame inherits from Swing's JFrame and, in turn,
the java.awt.Component class, which manages positioning. The class
contains a static hashtable whose values are PointCascades and keys are
arbitrary names managed by the developer. The PointCascade contains two orthogonal Cascades, one each for the x and y dimensions. When an
instance of CascadingJFrame is created, the class is accessed to retrieve the
next location for the named PointCascade. When the instance's set-Bounds()
method is subsequently called, the component is autopositioned at the location.

Autopositioning frees the developer's head a little, which is good - one less thing to think about. By providing the popular window-cascading behavior, in multiple streams when desired, sophisticated window positioning may be achieved with relatively little effort - by simply setting a few parameters and inheriting from the CascadingJFrame class. It's also interesting to consider extending additional subclasses that offer alternate positioning policies, or perhaps "position-memory" in which the boundaries of particular windows are written to persistent storage whenever they are moved or resized, and recovered when they are reconstituted by the application in a subsequent session.

Finally, a philosophical note: the best infrastructures are invisible and work automatically. The CascadingJFrame class envelops regular initial window positioning, typically to the degree of letting the applications programmer forget about it. And that is the best an infrastructure developer can hope for...making it so easy for others to do their work that they don't have to concern themselves with the underlying framework. If that goal is achieved, the framework was done right.

About David Anderson
David Anderson is a consulting software engineer at LexisNexis, an online information service in Dayton, Ohio. At night he puts on his Java shoes and cranks out reams of code as a contractor. He has been developing software since 1974.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

Enterprise Open Source Magazine Latest Stories . . .
Apache Deltacloud, the Red Hat-contributed ReSTful API that abstracts differences between clouds so services on any cloud can be managed – provided of course there’s a driver – has graduated from the Apache Foundation’s incubator and is now a full-fledged Top-Level Project (TLP). The...
With Cloud Expo 2012 New York (10th Cloud Expo) just four months away, what better time to start introducing you in greater detail to the distinguished individuals in our incredible Speaker Faculty for the technical and strategy sessions at the conference... We have technical and st...
AMD said late Tuesday that its chief sales officer Emilio Ghilardi had left the company and that CEO and president Rory Read is going to do his job while a replacement is sought. AMD didn’t say why Ghilardi left but it’s assumed Read wants his own people. Read is relatively new to th...
During the lifespan of M3 (Monitis Monitor Manager) there has always been something lacking – timers. M3 execution procedure was outlined in this previous article. The execution mentioned in the latter was a one-time-execution, whereas server monitoring requires periodic invocati...
Red Hat is putting its bought-in Gluster scale-out NAS storage technology, acquired in October, on the Amazon cloud. It’s styled Red Hat Virtual Storage Appliance for Amazon Web Services and other clouds are supposed to follow in short order.
A new episode of the screencast series is now available at the OpenNebula YouTube Channel. This screencast demonstrates the new easily-customizable self-service portal for cloud consumers. Its aim is to offer a simplified access to shared infrastructure for non-IT end users. The scree...
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON Featured Whitepapers
ADS BY GOOGLE