Wednesday, April 30, 2008

JavaBuilder for Swing : more binding updates

I think my initial instinct to put the bindings on the YAML side were right after all. But, this requires much larger changes.

I think I have the right approach though...I will define bindings as a totally stand-alone separate root node, after all the UI elements have been created. Unlike JavaFX, I will not put the binding definition directly into the property value (since that entails an ugly hack like "bind: binding expression"). This way we will have a very clear separation of concerns, just like with the "layout" component (i.e. not putting layout info at the control level, but in a separate node of its own).

Here's a sample of what it *may* look like on the YAML side:
(see the "binding" node at the end):
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/binding/BindingFrame3.yaml

I did major updates to the core engine to support multiple root nodes, so major instabilities in the code right now (probably)...will continue on this.

And now for something completely different: the new Agile baritones

Time to take a break from all this JavaBuilder madness and remember my other great passion: guitars!

I already own the amazing black Agile AB-3500 baritone (perfect for those brewtal riffz tuned to B), but Rondo Music has shown up the new model, in amazing tribal green flame maple finish:

http://www.rondomusic.com/product931.html

Man, if I didn't only have all those bills to pay I would get this beauty in a second...

Tuesday, April 29, 2008

JavaBuilder for Swing : now with two-way binding support!

I am happy to announce the first working support for binding in JavaBuilders, with full support for two way binding!

I realised I had the wrong idea initially (i.e. putting binding info in the YAML file). Instead in belongs on the Java side. This is especially important once I start adding support for EL binding (that's scheduled for later this week).

Here's the sample YAML build file:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/binding/BindingFrame1.yaml
and the corresponding Java file:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/binding/BindingFrame1.java

And here is the resulting window when it opens:

The initial field values get populated from the Java side via the two-way binding (see the constructor code).

We modify it on the screen, press OK (the OK button is wired from YAML to execute the save() method) and we get:
Voila!

This is starting to make Swing programming look really a lot like JSF where the YAML file has all the layout/creation info and the corresponding Java class looks like a JSF backing bean, with just the relevant properties and event methods.

New code drop with this features to celebrate this:
http://javabuilders.googlecode.com/files/javabuilder.swing.0.0.2008-04-30.zip

In other news, the @Name annotation was changed to @Alias to more clearly indicate what it really does.

Plans for the next short future:
a) support for EL binding, e.g.

@Bind("{fName.text} {lName.text}")
private String fullName;

although this would be read-only of course (from YAML to Java, not two-way).

b) initial investigation of integration with a validation framework (maybe Hibernate Validators, if it's not JPA specific)

c) finished the MouseListener handler to provide support for the following events:

onMouseClicked
onMouseDoubleClicked
onMouseRightClicked
onMouseEnter
onMouseExited
onMousePressed
onMouseReleased

See sample:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/TestFrame.yaml

Stay tuned!

Monday, April 28, 2008

JavaBuilder for Swing : automatically populating variable references and introducing Javascript-style event handlers

Thanks to the feedback from the previous post, the JavaBuilder now automatically populates the instance variables on the calling Java class with the ones defined in the build file.

However, the area of concern is refactoring of course. if someone changes the variable name on the Java side it becomes out of sync with the name defined in the YAML file and runtime exceptions will occur.

So, as an optional feature to proof the JavaBuilder concept against refactoring, I have introduced an @Name annotation that basically maps the Java instance variable to the name of the control as it was created in the build file.

You can see it in the YAML file (e.g. the "fNameLabel"):
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/test/org/javabuilders/swing/test/TestFrame.yaml

and in the corresponding Java file:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/test/org/javabuilders/swing/test/TestFrame.java

And here it is:
@Name("fNameField") private JTextField  firstNameTextField;
Also, you may have noticed some new things in the YAML file such as:
onFocus
onFocusLost
onKeyPressed
onKeyReleased
onKeyTyped
onAction
This is work in progress to add simple Javascript-style event handlers that will automatically call a corresponding method on the Java side. This reduces the verbosity of code required to create KeyListeners, FocusListeners, MouseListeners, etc.

It's still work in progress, but it will basically find any method on the Java side with the same name as defined in YAML and either zero arguments (e.g. save()) or with one argument that is compatible with the type that generated the event, e.g.

YAML:
- JButton: {name: editButton, text: button.edit, onAction: edit}
Java:
private void edit(JButton sender) {
JOptionPane.showMessageDialog(this, "Edit invoked from sender with name: " + sender.getName());
}
I plan to enhance it further to automatically recognize event-specific arguments, e.g.:
private void onLastNameKeyPressed(KeyEvent event) {
this.setTitle("Last name key pressed: " + event.getKeyChar());
}
but that's not there yet...coming soon this week, I hope, time permitting. I think the initial concepts of the JavaBuilder are slowly nicely coming together.

P.S. I mentioned this before, but the JavaBuilder concept is NOT Swing-specific. Swing is just the first domain that I am using as a proof of concept. There are some *very* early proofs of a working builder for SWT, but it's just working code to prove this will work across multiple domains. I will only start seriously working on the SWT builder once the Swing one is done.

See some early SWT code samples here:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swt/src/org/javabuilders/swt/
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swt/test/org/javabuilders/swt/test/TestShell.yaml

P.S.S. Also, I have settled on the Apache Wicket approach of forcing the Java and YAML files to have the same name and to be in the same package. It's a good idea and will follow the convention over configuration principle.

P.S.S.S. I also plan to add the @Name support for the Java event methods as well, to also proof them in case of refactoring. List of things to do grows by the day...

[EDIT 2008-04-29]
Latest code drop available:
http://javabuilders.googlecode.com/files/javabuilder.swing.0.0.2008-04-29.zip

Saturday, April 26, 2008

Java Builder for Swing: a complete complex layout sample

Had a chance to code a bit more on my vacation during the last 2 weeks, so the Java Builders project has made a big step forward.

I took the ZoneLayout sample from a previous post and re-created it (but using label separators instead of nested JPanels):

with full proper support for resizing:


with included support for internationalization and with the buttons hooked up via action commands to the main frame (e.g. clicking the OK button):


First, the resource file with all the internationalized content:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/test/Resources.properties

Next the actual YAML file with the layout and properties:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/TestFrame.yaml

and here's the Java JFrame that builds itself from this file:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/TestFrame.java

Let's have a quick look at the YAML file and go over some of the details of the visual layout part (which uses MigLayout under the hood) to explain some of the parameters:
sepName+*     : the "+" is for horizotal span, "*" indicates full remainder of the row
>fNameLabel : the ">" is to indicate the label should be right aligned
fNameField=1 : the "=1" defines a size group, all controls that equal to the same number
should be of the same size
textArea+4+3 : "+4+3" indicates span 4 columns, 3 rows

So, any comments? Suggestions?

Thursday, April 24, 2008

Java Builders challenge : send me your most complex UIs

As part of the work on the Java Swing Builder:

http://javabuilders.org

I have worked on samples of simple to medium complexity layouts. So far, so good.

However, I would appreciate some screenshots of really complex, typical day-to-day UIs you may have done in Swing (or any other UI toolkit for that matter) so I can make sure I handle even the biggest ones well.

Send them to JACEK99 AT GMAIL DOT COM.

thanks!

Friday, April 04, 2008

Java Builders - taking on the ZoneLayout example for complex GUI

I had a look at Zone layout and wanted to tackle the complex example they show:

This is how I *think* the Java Builder file would look like to accomplish this (notice I removed the explicit MigLayout declaration, assumed it is there by default and moved the "constraints" node to the container level, instead of beneath the layout manager node):
JPanel:
name: mainPanel
content:
- JPanel: #the name panel
name: namePanel
title: Name
content:
- JLabel: {name: fNameLabel, text: "First Name:"}
- JTextField: {name: fName}
- JLabel: {name: lNameLabel, text: "Last Name:"}
- JTextField: {name: lName}
- JLabel: {name: titleLabel, text: "Title:"}
- JTextField: {name: title}
- JLabel: {name: nickNameLabel, text: "Nickname:"}
- JTextField: {name: nickName}
- JLabel: {name: displayLabel, text: "Display Format:"}
- JComboBox: {name: display}
layout: |
>fNameLabel fName >lNameLabel lName
>titleLabel title >nickNameLabel nickName
>displayLabel display+3
- JPanel: #the email panel
name: emailPanel
title: E-mail
content:
- JLabel: {name: emailLabel, text: "Email:"}
- JTextField: {name: email}
- JList: {name: items}
- JButton: {name: addButton, text: Add}
- JButton: {name: editButton, text: Edit}
- JButton: {name: removeButton, text: Remove}
- JButton: {name: advButton, text: Advanced}
layout: |
>emailLabel email addButton+1+4
items+2+3 editButton [grow] #row constraint
removeButton
advButton
[grow] #column constraint
- JPanel: #the ok/cancel buttons panel
name: buttonsPanel
content:
- JButton: {name: okButton, text: OK}
- JButton: {name: cancelButton, text: Cancel}
layout: |
cancelButton okButton
constraints: #add special MigLayout tags to identify these as OK/Cancel buttons
- okButton: ok
- cancelButton: cancel
- layout: | #put it all together for the entire panel
[gap 5px] #optional layout constraints
namePanel
emailPanel [grow] #each row may end with optional row constraints
buttonsPanel [right]
[grow]
#each column may have optional column constraints at the bottom


So, what do you think? Took me about 10 minutes to type this in by hand, including thinking about how to incorporate the MigLayout row/column constraints into the picture.

P.S. An interesting variation if the JPanel's are removed and instead replaced with just a customized JSeparator that has a label embedded in it (similar to most of the examples in FormsLayout and MigLayout sample apps). That allows to put everything at the same level and in one layout node, e.g.


JPanel:
name: mainPanel
content:
- JBSeparator: {name: nameSep, text: Name}
- JLabel: {name: fNameLabel, text: "First Name:"}
- JTextField: {name: fName}
- JLabel: {name: lNameLabel, text: "Last Name:"}
- JTextField: {name: lName}
- JLabel: {name: titleLabel, text: "Title:"}
- JTextField: {name: title}
- JLabel: {name: nickNameLabel, text: "Nickname:"}
- JTextField: {name: nickName}
- JLabel: {name: displayLabel, text: "Display Format:"}
- JComboBox: {name: display}
- JBSeparator: {name: emailSep, text: E-mail}
- JLabel: {name: emailLabel, text: "Email:"}
- JTextField: {name: email}
- JList: {name: items}
- JButton: {name: addButton, text: Add}
- JButton: {name: editButton, text: Edit}
- JButton: {name: removeButton, text: Remove}
- JButton: {name: advButton, text: Advanced}
- JButton: {name: okButton, text: OK}
- JButton: {name: cancelButton, text: Cancel}
layout: |
nameSep+5
>fNameLabel fName >lNameLabel lName+2
>titleLabel title >nickNameLabel nickName+2
>displayLabel display+4
emailSep+5
>emailLabel email+3 addButton
items+3+3 editButton [grow]
removeButton
advButton
>cancelButton+5,>okButton
[grow]
constraints:
- okButton: ok
- cancelButton: cancel


Interesting...

P.S.S. Just to clarify, the "layout" node would be basically translated to standard MigLayout code, something like this:


setLayout(new MigLayout("","[][][][][][][grow]","[][grow]");

add(nameSep,"cell 0 0, span 5");

add(fNameLabel,"cell 1 0, right");
add(fName,"cell 1 1, fill");
add(lNameLabel,"cell 1 2, right");
add(lName,"cell 1 3, span 2");

add(titleLabel,"cell 2 0, right");
add(title,"cell 2 1, fill");
add(nickNameLabel,"cell 2 2, right");
add(nickNameLabel,"cell 2 3, span 2");

add(displayLabel,"cell 3 0, right");
add(display,"cell 3 1, fill, span 4");

add(emailSep,"cell 4 0, span 5");

add(emailLabel,"cell 5 0, right");
add(email, "cell 5 1, fill, span 3");
add(addButton,"cell 5 4, fill");

add(items, "cell 6 0, span 3 3, fill");
add(editButton,"cell 6 4, fill");
add(removeButton,"cell 7 4, fill")
add(advButton,"cell 8 4, fill");

add(cancelButton,"cell 9 0, right, span 5, split, cancel");
add(okButton,"right");


Code could be a bit off, but that's what it would most likely translate into...

Thursday, April 03, 2008

Java Builders - laying out Swing controls in text...crazy or just crazy productive?

I had a small epiphany last week...there is something to be said about seeing a screen in a GUI builder and at least getting some idea as to what it looks like.

So, assuming we still want this layout:


what if instead explicitly defining the constraints like this:
JFrame:
name: myFrame
title: Frame
content:
- JPanel:
name: groupLayoutPanel
content:
- JLabel: {name: label, text: "Find What:"}
- JTextField: {name: textField}
- JCheckBox: {name: caseCheckBox, text: Match Case}
- JCheckBox: {name: wholeCheckBox, text: Whole Words}
- JCheckBox: {name: wrapCheckBox, text: Wrap Around}
- JCheckBox: {name: searchBackwardsCheckBox, text: Search Backwards}
- JButton: {name: findButton, text: Find}
- JButton: {name: cancelButton, text: Cancel}
MigLayout:
constraints:
- label: cell 0 0
- textField: cell 1 0 4 1, grow
- caseCheckBox: cell 1 1
- wholeCheckBox: cell 2 1
- wrapCheckBox: cell 1 2
- searchBackwardsCheckBox: cell 2 2
- findButton: cell 5 0, grow
- cancelButton: cell 5 1, grow
we actually laid it out in text, with some simple hints:


JFrame:
name: myFrame
title: Frame
content:
- JPanel:
name: groupLayoutPanel
content:
- JLabel: {name: label, text: "Find What:"}
- JTextField: {name: textField}
- JCheckBox: {name: caseCheckBox, text: Match Case}
- JCheckBox: {name: wholeCheckBox, text: Whole Words}
- JCheckBox: {name: wrapCheckBox, text: Wrap Around}
- JCheckBox: {name: searchBackwardsCheckBox, text: Search Backwards}
- JButton: {name: findButton, text: Find}
- JButton: {name: cancelButton, text: Cancel}
layout: |
>label textField+2 findButton
caseCheckBox wholeCheckBox cancelButton
wrapCheckBox searchBackwardsCheckBox


Basically, the rows are defined by the fact the controls are in the same row.
The columns are automatically inferred from how the controls are aligned in the actual
"layout" node.

Some simple symbols in front of the name to indicate horizontal and vertical alignment:
> : halign right
| : halign center
/ : valign bottom
- : valign middle

and after the control name the span information

+2 : span horizontally 2 cells
+1+2 : span 1 cell horizontally, 2 cells vertically

Behind the scenes everything would be converted to regular MigLayout of course.
And I would still allow a separate constraints section to allow adding more specific
MigLayout constraints, but the ones above probably cover 80%/90% of the most common cases.

A trip down insanity lane? Or the best idea since sliced bread?

I'm still not sure myself...but I can see one making some layouts very quickly with this and
just by looking at the file getting a rough idea of what it actually looks like once
running.