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

SYS-CON.TV
Cloud Expo & Virtualization 2009 East
PLATINUM SPONSORS:
IBM
Smarter Business Solutions Through Dynamic Infrastructure
IBM
Smarter Insights: How the CIO Becomes a Hero Again
Microsoft
Windows Azure
GOLD SPONSORS:
Appsense
Why VDI?
CA
Maximizing the Business Value of Virtualization in Enterprise and Cloud Computing Environments
ExactTarget
Messaging in the Cloud - Email, SMS and Voice
Freedom OSS
Stairway to the Cloud
Sun
Sun's Incubation Platform: Helping Startups Serve the Enterprise
POWER PANELS:
Cloud Computing & Enterprise IT: Cost & Operational Benefits
How and Why is a Flexible IT Infrastructure the Key To the Future?
Click For 2008 West
Event Webcasts
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

Latest Cloud Developer Stories
Swisscom, the Swiss telecom, is going into the cloud business. Its subsidiary Swisscom IT Services AG has signed up with Red Hat as a Certified Cloud Provider and launched a public cloud Infrastructure-as-a-Service (IaaS) cloud targeting enterprise-class customers primarily in ...
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)....
In a surprise move on Tuesday, January 10, Oracle wheeled out its Big Data Appliance. That’s the one it said in October would be ready sometime in the first half. Only nobody believed it meant early in the first half. Heck, it’s not even clear anybody thought Oracle could make ...
Rackspace Hosting, the service leader in cloud computing, on Thursday announced its acquisition of SharePoint911, an industry leader in SharePoint consulting, training, and "JumpStart" services within SharePoint. The unification of both companies provides capabilities to deliver ...
CloudLinux, Inc., on Thursday released CafeFS 3, a virtualized file system for shared hosters that cages each customer within its own virtualized file system. CageFS becomes part of CloudLinux OS at no additional charge. CloudLinux OS, the only commercially-supported Linux OS m...
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

Breaking Cloud Computing News

NASHVILLE, Tenn., Feb. 16, 2012 /PRNewswire/ -- Brookdale Senior Living Inc. (NYSE: BKD) (the "Co...