Step 2 – Making the GUI

Winforms over Java1! Not as freaky as you might think. We basically just employ the Adapter design pattern in a larger scale.

‘Xept that, ImageList.setTransparentColor() made me want to pull my hairs out. Ended up copying each image, in an implementation dependent way. I must find a better solution if any other bitmap format is to be used in the application.

Since we’ve already started by creating stubs to all classes and methods needed, and even guessing some of the inharitance, we can now manually implement all of the Winforms classes used in our application2. Luckily for us, Winform is a very primitive framework: for instance, you always specify location and sizes of components manually, in pixels. Implementing the same in Swing isn’t very hard: a Form holds a JDialog3 and it’s content pane, diverting most of it’s methods directly to the appropriate JDialog’s methods, and returning the content pane as the Controls property.

The content pane is of a type that we just now define: WinformJPanel. It extends JPanel with the methods that Winforms’ Controls have (Add, AddRange, and SetFocusOrder). SetFocusOrder() goes a long way: A TraversingPolicy is implemented based on a mapping from a component to it’s index, to allow the focus order to change when adding a control. We set the layout to null, in order to allow pixel-positioning of controls.

Winforms’ Form class can be used as either a dialog or as a full-fledged window. The distinction is made by the method you use to display it – ShowDialog() or ShowWindow(). In Swing, you are supposed to instantiate a different class – JDialog or JFrame, and use setVisible(true) for both. After some time trying to answer all needs in a single WinformForm class, I’ve finally decided to split it to two, and have the one window in the system extend WinformWindow instead. It would take a lot of refactoring now to really clean the differences up, but it’s easier that waym as it lets the WinformForm class always be modal.

Actually, I’ve cheated a bit here – the Form isn’t blocking just its parent, as you might wish it did, but rather the entire application. I trust the Swing guys that will never cause a deadlock.

Most controls’ implementations are straightforward: Label is JLabel, Button is JButton, NumericUpDown is JSpinner... Only a few differences require intervention:

In Winform, a control is a part of its dialog parent: so a button has a DialogResult property, which affects its parent. The tab order is determined by providing the controls with a TabIndex property. These are dealt with by the WinformJPanel.Add() we’ve implemented to replace the Controls property of Form.

Another difference is with response to user input, mostly mouse events: While Winform created an event for the controls for each possible user-input, Swing prefers a MouseListener (etc.) for each class of user inputs: mouse events, keyboard input, model changes... I’ve decided to keep the Winform API (Almost – events became a simple field), and create a new MouseListener object when adding the control to a window / form. That’s because I assume the layout is complete by this time.

I’ve made a small but critical mistake – I’ve ignored the StopLayout / ResumeLayout methods. I might have made my life easier if I hadn’t.

The ImageList class is not a control, though it looks like one from browsing the code. Rather, it’s just a storage for images, probably loaded from a .RESX file (See more about resources later). The PictureBox class is indeed a control, which we implement with a JLabel.

The dialogs used in Space-Trader are complex – so much so, that I couldn’t just use JDialog and hand it some icon and text (Accept for the FormAlert, which caused a lot of other interference as well. It will, at some point, be refactored as a façade for JDialog, or maybe JOptionPane.)

More about resources: Visual Studio keeps a .RESX file for each form, that holds the pictures and some strings. (Note: it actually holds the pictures, not file names!). I couldn’t read this file, so I created property files for each form with the information needed. For image lists, I referenced an additional property file, where the keys are only used for sorting, and the values are image file names. The images and property files all go into the same jar as the application.

And a word about Labels: Winform’s doesn’t warp their text, so there’s kits if code for it lying around. JLabel will wrap it’s content – if it thinks its HTML. And it thinks anything that is wrapped in “<HTML></HTML>” is.

  1. 1. Warning – must have some familiarity with Winforms and Swing.
  2. 2. The correct way is to stop for a minute here, duplicate the stubs project, and encapsulate all fields into methods (Creating a script to aid us). This way, if you ever need to do it again, you just install the fields project, reference it, run the script and replace the it with the real implementation – now that the API is the same.
  3. 3. In one case – a JFrame. I’ll cover that one in a bit.