GeoWidgets

User's and developer's guide

Last updated 2005-10-11

Note that this is a document in progress.

Some sections might be incomplete.

Contents

1 What is GeoWidgets?	1

1.1 Goals of the project	1

1.2 Current state	1

1.3 Planned widgets	2

1.4 Where to go from here?	2

2 Using GeoWidgets in your application	3

2.1 Using the Swing widgets	3

2.1.1 JUnitComboBox	3

2.1.2 JAxisDirComboBox	3

2.1.3 J...AssemblyPanel (e.g. JProjectedCRSAssemblyPanel)	4

2.2 Using the SWT/JFace widgets	5

2.2.1 UnitComboBox	5

2.2.2 CRSElementPropertyViewer	5

3 GeoWidgets Eclipse projects	7

4 Checking out and building GeoWidgets	8

5 GeoWidgets development guidelines and help	9

5.1 The GUI framework	9

5.1.1 Localization support	9

5.1.2 The factory finder	10

5.1.3 Logging support	10

5.1.4 UI factories	11

5.1.5 Validation support	12

5.1.6 The base widgets	13

5.1.7 Final note	13

5.2 Design concepts used	13

5.3 Other design guidelines	14

6 Literatur	15

What is GeoWidgets?

GeoWidgets is a Java library of graphical user interface (GUI) widgets for geographic applications based on GeoTools. More specifically GeoWidgets is supposed to contain a consistend and easy framework to create such widgets with different GUI toolkits (and their derivatives), such as f.e. Swing, SWT, Java, JFace, SwingWT. It already contains some implementations of such widgets.

Note that GeoWidgets is not supposed to be a ready-to-use full-blown GIS, it just wants to support building one. It is geared towards GIS developers, not GIS users.

Goals of the project

Goals of the GeoWidgets project are to:

support a consistent look and feel through all the widgets of one GUI toolkit, but allow users to customize things like colors and sizes (and the Swing Look&Feel, if applies).

allow to build completely different looking implementations of the same functionality

separate out code that is independent from the GUI toolkit used and code that depends on a certain GUI toolkit, such as Swing or SWT/JFace

be completely localized

support logging

support validation of user inputs

be easy to deploy in applications

utilize GeoTools for the functions “behind the scenes” where possible, but allow alternative implementations.

make it easy to set up the project for developers using the well-known Eclipse Java IDE.

Current state

The table shows what functionality is already there and for which functions there exist widgets for which GUI toolkits.

Module	GUI-indep.	Swing	SWT	JFace*	other
Framework	X	X	X	n.n.	-
CRS (Georeferencing related): - Unit dropdown - Coordinate axis direction dropdown - CRS assembly widgets	X X X	X X X	X - -	X - X	- - -

* JFace or widgets from the Eclipse Rich Client Platform, which builds on JFace.

n.n.=not needed

See chapter to find out what each widget or set of widgets can be used for.

Planned widgets

GeoWidgets, when it is mature, is supposed to hold all widgets necessary for usual GIS applications. This includes Map panes, legends, styling widgets, the referencing widgets and other ones that certain people might contribute.

Where to go from here?

If you just want to deploy an existing widget, you will probably be interested in how to use the library and how to use certain widgets. These aspects are covered in chapter 2.

Developers of GeoWidgets will be interested in how to set up Eclipse (as the favoured IDE) to develop own widget implementations or create functionality (e.g. models) for new widgets. A general introduction is given in chapter 3 and checking out GeoWidgets from the Subversion repository (SVN) and building it is covered in chapter 4. More technical help and guidlines for developers are given in chapter 5.

Using GeoWidgets in your application

For every widget its class and executable Test class are given. The latter often shows a nice example of how to use the widget's API. It is usually not a JUnit test.

Using the Swing widgets

The Swing widgets are either subclasses of existing widgets with convenience functions added, or they are panels that contain combinations of existing widgets that communicate with each other behind the scenes.

JUnitComboBox

org.geowidgets.crs.widgets.swing.JUnitComboBox / Test_SwingUnitCombo

A dropdown list that contains linear, angular or both kinds of units. The Units specification JSR-108 as used in GeoTools is used here. Public API:

public JUnitComboBox(int unitType, boolean sorted)

public Unit getSelectedUnit()

public void setSelectedUnit(Unit u)

The above constructor/functions do not need much explanation:

unitType is a IUnitModel.UNIT_XXX constant such as IUnitModel.UNIT_LINEAR.

When setting the unit with setSelectedUnit it may happen that the unit is not in the list of default units. In this case the Unit is inserted into the dropdown by its abbreviation, since the Unit object does not contain a name. It can be selected and (if selected) gets returned as any other unit.

The widget's model is org.geowidgets.model.units.IUnitModel. It can be implemented, but the existing two implementation, especially EPSG_UnitModel, are usually sufficient to deliver all units needed by the georeferencing objects defined by the EPSG database. The default implementation uses all EPSG units that are supported by GeoTools. The alternative model does not require the EPSG database and just uses the most common units supported by the Units framework. Both models support localization.

JAxisDirComboBox

org.geowidgets.crs.widgets.swing.JAxisDirComboBox / (No separate test class)

A dropdown list that contains axis directions, such as “Up” and “West”. Public API:

public JAxisDirComboBox()

public AxisDirection getSelectedAxisDirection()

public void setAxisDirection(AxisDirection dir)

The usage is self-explaining. The default model of the axis direction dropdown currently uses the axis directions available in GeoTools, since the EPSG factory is a bit circumstancial to use when it comes to “just getting all possible directions”.

J...AssemblyPanel (e.g. JProjectedCRSAssemblyPanel)

org.geowidgets.crs.widgets.swing.JProjectedCRSAssemblyPanel, JGeographicCRSAssemblyPanel, JEllipsoidAssemblyPanel, etc. / Test_SwingCRSWidgets

This set of widgets, commonly referred to as CRS assembly widgets, allow to select a CRS-related object, such as f.e. a geographic CRS or an ellipsoid, from a list of default units or to build it from its components and/or parameters. The user has the choice. The widgets are nested: If, for example, when the user chooses to create a custom geographic CRS, a panel is shown that uses a JGeodeticDatumAssemblyPanel and a JCSAssemblyPanel to let the user select geodetic datum and ellipsoidal CS – or again, build custom ones.

These widgets are tightly related to the European Petroleum Survey Group's EPSG database, which contains almost all coordinate systems, datums, ellipsoids etc. that one could imagine.

Currently following objects can be handled: Twodimensional projected and geographic CRS, projections (also known as conversions in GeoTools), 2D and 3D cartesian and ellipsoidal coordinate systems, geodetic datums and ellipsoids. Threedimensional CRS are supposed to be supported as well, but this has not been tested yet and might be incomplete.

The public API is similar for each of the widgets. It is shown here for the JGeographicCRSAssemblyPanel:

public JGeographicCRSAssemblyPanel(Color c, int dim)

public GeographicCRS getCRS() throws FactoryException

public void setCRS(GeographicCRS crs)

All of the objects are not real-time objects. That is, they do not build/edit the objects as soon as the user does some change. This explains why no support for listeners exist. The widgets are build to build deliver the selected or assembled objects triggered by some event, lets say, when the user pressed an OK button. (If someone is interested in real-time objects: This can be done, I just didn't consider it necessary and it's easier this way.)

All widgets support custom colors, but the color argument can be null to use the color defined by the corresponding UI factory. Some widgets have the dimension argument, which determines if for example a 2D or 3D coordinate system is required.

There is no access to child widgets. A JGeographicCRSAssemblyPanel can only be queried for the selected GeographicCRS, not for the GeodeticDatum that might be involved. However the returned object (the GeographicCRS) can be queried for its components like the GeodeticDatum.

Using the SWT/JFace widgets

Since SWT classes are not supposed to be subclassed, most SWT and JFace classes in GeoWidgets do contain existing SWT or JFace widgets, and some extend Composite.

UnitComboBox

org.geowidgets.crs.widgets.swt.UnitComboBox / Test_SWTUnitCombo

A dropdown list that contains linear, angular or both kinds of units. Public API:

public UnitComboBox(Composite parent, int unitType, boolean sorted)

public Unit getSelectedUnit()

public void setSelectedUnit(Unit u)

public Combo getCombo()

The usage is similar to the JUnitComboBox (p. ), except that the widget has the getCombo() method in order to allow direct access to the wrapped dropdown list. Again, it is possible to use the setSelectedUnit() method to add any unit to the list that is not yet included.

As with the Swing version, the JUnitComboBox, this widget does not give the currently selected unit in real time and has no listeners. However it would be possible to add listener support and real time behaviour, if needed.

CRSElementPropertyViewer

org.geowidgets.crs.widgets.propertysheet.CRSElementPropertyViewer /
Test_PropertyCRSElementWidget

A property view for CRS objects. CRS objects can be selected and their attributes and child objects can be changed.

Although this widget can be directly used outside Eclipse, the widget itself is just a few lines of code. What makes it working, is its model, consisting of the public inner class

CRSElementPropertyViewer.CRSPropertySourceProvicer

and the PropertySources to be found in package
org.geowidgets.crs.widgets.propertysheet.propertysources, such as

PCRS_PropertySource, GCRS_PropertySource, EL_PropertySource, ...

(Where PCRS stands for projected coordinate reference system, EL for ellipsoid a.s.o.)

The major point is that the property source provider and these property sources extend Eclipse interfaces, so these objects can presumably be used in an existing property framework either in the Eclipse IDE or in an Eclipse Rich Client Platform based program such as uDig.

Each of these property sources manages its object in real time (in contrast to the Swing CRS assembly widgets, see above) and determines what attributes and child objects the object has and how to edit them.

The public API developed for the CRSElementPropertyViewer currently consists of three functions:

public CRSElementPropertyViewer(Composite parent, int style, T content)

public T getContent()

public boolean setContent(T root)

with <T> being the object type that the property viewer currently handles: Thanks to Java5 generics a property viewer for, lets say, ellipsoids is created with the following code:

Ellipsoid el = DefaultEllipsoid.WGS84;

CRSElementPropertyViewer<Ellipsoid> tree

= new CRSElementPropertyViewer<Ellipsoid>(parent, SWT.NONE, el);

The class Test_PropertyCRSElementWidget gives more examples of this.

The getContent() and setContent() are the methods to retrieve or to change the object being edited.

There are currently no listeners, so real-time use is not yet possible, but since it would be nice to have (at least optional) I will try to include listeners as soon as possible.

GeoWidgets Eclipse projects

This chapter introduces developers and other volunteers to the project structure of the GeoWidgets Eclipse project. As you will see in the next chapter it does not require much work to get GeoWidgets running in Eclipse after a checkout.

There are two projects currently set up in the project's SVN trunk: Stable and Instable. “Stable” on the one hand contains packages that are considered at least alpha quality, that is, they need not be 100% stable or mature, but should at least be usable. Their package structure and API is expected to change only slightly till they will be considered mature. On the other hand, “Instable” contains packages that are in active development and maybe simply “play around and test different approaches”. The “GeoWidgets_Instable” project extends “GeoWidgets_Stable”, so the instable source code can rely on already existing classes.

Following guidelines are suggested:

Only the “Stable” project is released as “milestone” releases. The “Instable” project is to be accessible via SVN or on request only.

The stable releases (1.0.0, 1.0.1 etc., in contrast to milestone releases) can only consist of classes from the “Stable” project.

The “Stable” project is subject of quality rules. This includes that the source code must be completely documented (JavaDoc) and that JUnit tests or other executable test classes must exist – both until the next milestone release, preferably earlier.

Within each project separate source code directories exist for different sub projects, each of which is concerned with a specific widget or set of widgets. Additionally there is a “src-main”source folder that contains the widget framework, some basic (general) widgets and utility classes.

These guidelines are subject to change, and suggestions are welcome.

Checking out and building GeoWidgets

If you work in Eclipse under Windows, using Subclipse is the easiest way to checkout GeoWidgets:

Download and install Subclipse into Eclipse. At http://subclipse.tigris.org/ you will get information on how to update Eclipse with Subclipse.

Use the manual import as described at
http://udig.refractions.net/confluence/display/UDIG/Source+Code,
with the difference that the SVN repository is located at
http://svn.geotools.org/geotools/trunk/spike/geowidgets.
You should find two directories below this one: “Stable” and “Instable”. They correspond to the two projects described in the previous chapter.

“Clean” the project if it does not happen automatically. This will downloaded missing libraries or get them from your Maven repository.
Caution: Sometimes the download of some libraries from SourceForge fails. It might happen then that Eclipse seems to “freeze”. If this takes very long try to restart Eclipse.

The project should theoretically build afterwards.
Note: For reasons unknown to me, it may happen that, although the library download was successful, the project will not build and will show missing dependencies. There is a funny workaround: Open the “build.xml”, edit a [space] character somewhere, delete it (not undo!) and save the file. The project should now recompile properly.
If anyone comes across a solution that stops this problem, let me know.

Optional: Run the JUnit tests. Start src-main/test/JUnit_GeoWidgets. Note that the test
initially uses the HSQL version of the EPSG database. You can edit the classpath to include epsg-access-2.X.X.jar in order to test Access functionality.

Optional: To build a release, open the Ant View in Eclipse and register “build.xml” there. It should you the ant targets. Choose

"_GeoWidgets.createRelease" to create all the archives and pack them to a release.

"_GeoWidgets.createjar.bin" to create the binary jar only

"_GeoWidgets.createjar.src" to create the source code jar only

If you work under another OS, you will have to install Subversion and do the checkout manually. There is a good HowTo documentation about that at uDig, and it works similar with GeoWidgets. The documentation can be found at the uDig project, currently under

http://udig.refractions.net/confluence/display/UDIG/Source+Code and

http://udig.refractions.net/confluence/display/UDIG/Subversion .

Please give feedback if all the above works for you or why not.

GeoWidgets development guidelines and help

In this chapter some guidelines are given how to best use the current GUI framework, and suggestions are given on how to fulfill the goals mentioned at the beginning of this document. Of course, suggestions to improve things and any good ideas is general are welcome at every time.

The GUI framework

Looking at the source code you will notice that there is more than one source directory. Specifically, the framework has its own source tree (src-main) and every group of related widgets has another one (e.g. src-crs for the referencing widgets). By definition the widget-specific code will depend on src-main, but src-main must never depend ony code in any of the other. specific widgets, although it may contain code that is relevant for one or some of the widgets only. This opens the possibility to add/remove widget groups from the build without running into trouble.

The directory src-main contains the GUI framework, that is, all things that apply to all or many widgets. Currently this means:

Localization support (Translation of messages to other languages.)

Logging support (Logging problems and diagnostics to console and/or file.)

UI factoris (Provide a consistent look and feel.)

Validation support (Allows to check if user inputs/selections are valid or not.)

If you consider writing new widgets or new widget implementations for other GUI toolkits be sure to use the provided framwork instead of reinventing the wheel. Should you feel that some component needs improvement, you are free to improve it.

The framework is deliberately kept simple and consists of a handful of files each. Below is explained how to use each component. If further code samples are needed, just look how the existing code uses the framework.

Localization support

As a rule of thumb, only code that is currently being worked on, might temporarily contain unlocalized Strings and messages. All widgets to be released must be localized as good as possible, including error messages. If you are not familiar with localization support in Eclipse, please read the appropriate sections in the Eclipse help first.

Localization support is done through the class

org.geowidgets.framework.Res.java,

which contains convenience functions that return localized Strings. It also contains constants for the currently available resource bundles. In 90% of all cases you will call it this way:

Res.get(Res.WIDGETS, "err.SomeMessage")

In the above example, WIDGETS is the constant for the shared resource bundle, which is supposed to contain general (error) messages or Strings that might be reusable. Beside this there exist currently the constants UNITS and CRS, which contain localized unit names and localized Strings for the referencing widgets respectively. When a new widget group is to be created within GeoTools, a new constant must be declared pointing to the new, widget group specific resource bundle. Again, reusable Strings should be added to the WIDGETS resource bundle.

The second argument is of course the key. A hierarchical structure is recommended, such as for example the prefix “err” for errors or “msg” for information messages to make keys easy to find. For eclipse users there exist quite useful resource bundle managers as Eclipse plugins. I use the “ResourceBundle Editor” (RBE), which is available as v0.6 (or meanwhile higher). Its main advantages are that it keeps the resource file clean and sorted, groups Strings by their prefix, avoids duplicate entries and signals if the translation is missing for certain Strings.

The class Res also contains convenience functions to create Strings with placeholders or as HTML String (for html labels or such things).

Please do not forget to mark non-localizable Strings as such in order to keep the warnings in Eclipse to a minimum.

The factory finder

Analogue to GeoTools there exists a central object that returns factories. This object is

org.geowidgets.framework.GWFactoryFinder

The idea behind this is, that all the factories can get replaced by subclasses of them to customize certain aspects of GeoWidgets, such as f.e. ui colors. These subclasses can then be registered at the GWFactoryFinder and are later returned on the appropriate request.

All factories are supposed to be singletons. This means that they should get constructed though a static function like “SomeFactory.getDefault();”.

Pending: Alternatively there could be one “base” factory with static functions to set and get the default factory. So this “registering” would happen at the “base factory” and would make the FactoryFinder obsolete. Are there any drawbacks?

Logging support

Logging support is very simple: There is one factory that returns the preconfigured logger to use for all geowidgets. The recommended way to use it is to define following class variable:

protected static final Logger LOGGER =
GWFactoryFinder.getLoggerFactory().getLogger();

As can be seen the “logging factory” is one of the classes registered as the default one at the GWFactoryFinder. One could subclass it and change for instance the logging level or add file logging, which is not on by default. The default logging level is FINE and the default logger produces compact one-line messages thanks to a formatter from the GeoTools project. Note that the default logger is set up for localization using the default WIDGETS resource bundle.

The actual logging is then done as in following example for a localized warning (localization key given as argument) which was caused by some exception:

LOGGER.log(Level.WARNING, "err.SomeException", myException);

If the default logging factory is used, this will show a one-line message on the console.

Please log all nontrivial exceptions and errors that arise (Level.Warning resp. Level.Severe). Please also log all other relevant things (whatever "relevant" means).

UI factories

The UI factories helps to keep a consistent look and feel between the widgets of one GUI toolkit. It should be clear that differences between toolkits such as Swing/SWT are unavoidable. It should also be clear that the UI factories are only one of three facts that determine how the widget will show up in the end:

Within Swing the look and feel is determined by the Swing “look and feel” that is currently activated. Within SWT and other operating system dependent toolkits the look and feel depends ont the one selected by the user, such as the KDE styles or the style in MS Windows.
So the Swing or OS look and feel determine the general look and feel.

Within one GUI toolkit several implementations for one and the same functionality are possible. For example there are several possibilities of how to design a dialog to choose a coordinate reference system.
So the implementation determines the overall layout and the “how to use” for the widget.

The UI factories. Their scope lies within the bounds given by the first two. They mainly determine colors, fonts, insets (the separation between adjacent UI elements such as text fields) and similar things.

It is required that every UI element, be it a simple label or a dropdown or anything else, be either created or customized by the appropriate UI factory using customize(myUIElement) or similar. All specific changes to these objects must be applied afterwards. Should there not yet be an appropriate implementation for this UI element in the appropriate UI factory, it has to be created. Only this way can it be assured that the look and feel is really applied to the UI elements in the widgets.

Pending: This is not so important for SWT/JFace. Should they still support customization?

You will notice that there exist several such factories and more than one for one GUI toolkit. This is because there are some things that apply to all widgets (and even all GUI toolkits),while most other functions require a certain GUI toolkit and some are widget group specific.

In general, when adding a new widget specific factory be sure to create appropriate functions in the GWFactoryFinder for setting and getting it from there. (Just copy and adapt the existing functions.)

Note that there is one default layout for each GUI toolkit set (GridBagLayout for Swing and GridLayout for SWT for example). It is highly recommended to use these layout to support the consistent look and feel and to take advantage of several functions of the UI factories.

Please not that the UI factories support also functions to showing message dialogs to the user. All sort of message types, such as f.e. warning messages, are supported. Please use these UI factory methods instead of directly calling OptionPane (or whatever the GUI toolkit offers).

Validation support

Should validation support be needed, the existing one can be used or extended to validate user inputs and selections. (You may implement your own validation support, but the existing one is really simple to use and flexible. If you implement your own, please have an eye on how it looks at the existing widgets, so the behaviour is somewhat consistent between the widgets.)

The existing implementation builds on three columns:

a wrapper for the ui element(s) to be validated. Basically this adds validation support to them and allows to retrieve the relevant objects from the ui element to change or edit them.

a validator (IValidationListener). This is the class that knows “what's right and wrong”. It listens on some UI element(s) for changes done by the user and evaluates these changes. There can be more than one listener on one UI element.

a notifier (IValidationNotifier). This class listens at a validator and, depending on the validation result, takes actions to signal the result to the user. For example it might change the background color of the UI element to red or green, change the tooltip, activate or deactivate a button and/or print an error message to some predefined place (as is common in Eclipse dialogs). There can be more than one notifier listening for results at one validator.

Look at the “JEllipsoidAssemblyPanel” to see how validation is actually used to require input in certain text fields. Here is one example:

this.val_Ea = new JValidatedTextComponent<JTextField>(t_Ea,

new SimpleTextFieldValidator(

ERR_PARAMS, t_Ea, 1.0, Double.MAX_VALUE),

new BackgroundColorNotifier(t_Ea, badColor, null));

In this case the wrapper ( JValidatedTextComponent) wraps around the text field t_Ea and adds a SimpleTextFieldValidator and a BackgroundColorNotifier to it. In the constructor of the former ERR_PARAMS points to a constant holding the error message to show if the validation fails, t_Ea is the text component whose text to check and the other argument define minimum and maximum value acceptable for the numerical input. The latter, the notifier, will change the color of t_Ea between badColor and its normal color (argument null), depending on the result.

When building new implementations of validators, you should use the existing abstract base classe (“_Validator”). It takes away a lot of boring management functions and only leaves implementing the actually evaluating task to you.

Have a look at the existing implementations in the ....validation.impl package, especially the “SimpleTextFieldValidator” and the “BackgroundColorNotifier” to see how easy it is to create new implementations that might f. .e. evaluate toggle buttons or checkboxes.

The base widgets

The package org.geowidgets.framework.basewidgets contains some very generic widgets or UI related classes which might be extended for several different purposes and be reused in different widgets. In case these base widgets need to be modified either ensure that this does not negatively affect other children of these widgets or apply the changes within your child class.

See the classes' Javadoc for details about the available base widgets.

Final note

The above rules and recommendations concerning the strict usage of the framework within GeoTools apply only to the GeoTools source classes. Test cases, sample applications and classes in the “Instable” project do, as an example, not need to localize every single String used and need not strictly use the UI factories. Developers of “Instable classes” may defer localization and such to when the code gets mature enough to be released.

Design concepts used

Basically there are several possibilities how to design the source code of one and the same widget. But there are two things that should be considered:

The first one is to keep GUI toolkit dependent code and general code separate. In the CRS assembly widgets the model contains all the reusable code while the GUI toolkit dependent implementations, which use the model, are kept slim. Also Widget UI implementations for one GUI toolkit such as Swing or SWT must not have dependencies on other UI window toolkit libraries, except to AWT, since it is part of core Java.

The second issue is that, if possible, the Geotools implementations should be used, but only as one implementation of many. This means either using GeoAPI (or GeoTools) interfaces or, where necessary, creating own interfaces, for which the GeoTools code provides one possible implementation.

Other design guidelines

Since GeoWidgets is based on Java5, please use type safe collections.

Try to avoid dependencies to exotic libraries if possible. This is especially important for the main framework. (Some widgets might need UI elements from other libraries to do cool stuff.) Also, please use code or libraries included in GeoTools if you have the choice.

Try not to duplicate code that exists (or should exist) in GeoTools/GeoAPI. I know this is hard sometimes but the GeoTools guys will help you with this, from my experience.

Literatur

Keine bisher.

Links:

Geotools: http://geotools.codehaus.org/

uDig: http://udig.refractions.net/confluence/display/UDIG/Home

GeoWidgets license

GeoWidgets is licensed under the GNU Lesser Public License (LGPL). It can be viewed at
http://www.gnu.org/copyleft/lesser.html.

6 Literatur

15

Matthias Basler

2005-07-28T17:27:32