Bxml2Java is a project mainly written in Java, it's free.
this is new version of BXML to Java translator with declarative style code generation
bxml2java(new version of BXML-to-Java-converter with declarative style code generation)
This is released with Apache 2 licence.
Apache Pivot uses a XML file called BXML. This tool converts a BXML file to equivalent Java source code.
There are some limitations: 1) javascript is not supported. 2) Listner is not mapped to Java.
The Design:
This tool generate Java code from BXML file with declarative style Java codes. Compared to the previous approach, it is more consise, and does not use any variables(almost). (see the sample generated code)
Installation:
This is designed as an extension of the current Apache Pivot source code line. The current project has minimal files. In order to build this tool, copy the folder into the latest pivot folder created by checking out by svn. (this will override BXMLSerializer.java, so you may need to copy the original before this)
Bugs: This is not completed version. But the framework would be sound. Some of the problem is related to final classes in the Pivot class. It fails because this generaes anonymous class for the final classes. So it is necessary to modify the original Pivot code to avoid this problem(change final to none final). (TreeVire.Columns, a few more classes)
The main test program I used is the StackTrader. This sample generated code is now working.(I fixed a few issues) the new sample code is attached in this file.
How to run/test:
Use eclipse to build and run this tool.
You can run BXML2JavaConverterTest.java. this will convert all bxml files under tutorial folder, and generate java source files in the same folder. The generated Java file name starts with "_". so it is easy to distinguish generated file from others.
Examples: stock_tracker_window.bxml
<?xml version="1.0" encoding="UTF-8"?> <stocktracker:StockTrackerWindow title="%stockTracker" maximized="true" xmlns:bxml="http://pivot.apache.org/bxml" xmlns:content="org.apache.pivot.wtk.content" xmlns:stocktracker="org.apache.pivot.tutorials.stocktracker" xmlns="org.apache.pivot.wtk">
</stocktracker:StockTrackerWindow>
detail_pane.bxml
<?xml version="1.0" encoding="UTF-8"?> <BoxPane orientation="vertical" styles="{fill:true}" xmlns:bxml="http://pivot.apache.org/bxml" xmlns:stocktracker="org.apache.pivot.tutorials.stocktracker" xmlns="org.apache.pivot.wtk">
<Separator/>
<Form styles="{padding:0, fill:true, showFlagIcons:false, showFlagHighlight:false,
leftAlignLabels:true}">
<Form.Section>
<bxml:define>
<stocktracker:ValueMapping bxml:id="valueMapping"/>
<stocktracker:ChangeMapping bxml:id="changeMapping"/>
<stocktracker:VolumeMapping bxml:id="volumeMapping"/>
</bxml:define>
<Label bxml:id="valueLabel" Form.label="%value"
textKey="value" textBindMapping="$valueMapping"
styles="{horizontalAlignment:'right'}"/>
<Label bxml:id="changeLabel" Form.label="%change"
textKey="change" textBindMapping="$changeMapping"
styles="{horizontalAlignment:'right'}"/>
<Label bxml:id="openingValueLabel" Form.label="%openingValue"
textKey="openingValue" textBindMapping="$valueMapping"
styles="{horizontalAlignment:'right'}"/>
<Label bxml:id="highValueLabel" Form.label="%highValue"
textKey="highValue" textBindMapping="$valueMapping"
styles="{horizontalAlignment:'right'}"/>
<Label bxml:id="lowValueLabel" Form.label="%lowValue"
textKey="lowValue" textBindMapping="$valueMapping"
styles="{horizontalAlignment:'right'}"/>
<Label bxml:id="volumeLabel" Form.label="%volume"
textKey="volume" textBindMapping="$volumeMapping"
styles="{horizontalAlignment:'right'}"/>
</Form.Section>
</Form>
======================================= first one will include the seconde bxml file.
following Java codes are converted from stock_tracker_window.bxml:
package org.apache.pivot.tutorials.stocktracker;
import java.net.; import org.apache.pivot.wtk.converter.CodeEmitterRuntime; import org.apache.pivot.wtk.; import org.apache.pivot.wtk.content.; import org.apache.pivot.wtk.effects.easing.; import org.apache.pivot.wtk.effects.; import org.apache.pivot.wtk.media.; import org.apache.pivot.wtk.skin.; import org.apache.pivot.wtk.text.; import org.apache.pivot.wtk.validation.; import org.apache.pivot.collections.adapter.; import org.apache.pivot.collections.concurrent.; import org.apache.pivot.collections.immutable.; import org.apache.pivot.collections.*; import org.apache.pivot.util.Resources; import org.apache.pivot.beans.Bindable;
public class TestCodeGenerator1 implements Application { private Window window = null;
@Override
public void startup(Display display, Map<String, String> properties) throws Exception {
//BXMLSerializer bxmlSerializer = new BXMLSerializer();
//window = (Window)bxmlSerializer.readObject(getClass().getResource("stock_tracker_window.bxml"));
final Object obj = create();
if (obj instanceof Window) {;
window = (Window)obj;
} else if (obj instanceof Component) {
window = new Window();
window.setContent((Component)obj);
window.setTitle("stock_tracker_window.bxml");
} else {
System.out.println("getComponent returned object with type: "+obj.getClass());
}
window.open(display);
}
@Override
public boolean shutdown(boolean optional) {
if (window != null) {
window.close();
}
return false;
}
@Override
public void suspend() {
}
@Override
public void resume() {
}
public static void main(String[] args) {
DesktopApplicationContext.main(TestCodeGenerator1.class, args);
}
static StockTrackerWindow create() throws Exception {
return new StockTrackerWindow() {{
final Map<String, Object> namespace = new HashMap<String, Object>();
setTitle("Pivot Stock Tracker");
setMaximized(true);
setContent(new TablePane() {{
setStyles("{padding:8, horizontalSpacing:6, verticalSpacing:6}");
// columns(): READ_ONLY_PROPERTY
getColumns().add(new TablePane.Column() {{
setWidth(1, true);
}}); // INSTANCE, name: <TablePane.Column>
getRows().add(new TablePane.Row() {{
setHeight(-1);
add(new Label() {{
setText("Pivot Stock Tracker");
setStyles("{font:{size:14, bold:true}, verticalAlignment:'center'}");
}}); // INSTANCE, name: <Label>
}}); // INSTANCE, name: <TablePane.Row>
getRows().add(new TablePane.Row() {{
setHeight(1, true);
add(new SplitPane() {{
setSplitRatio(0.4f);
// left(): WRITABLE_PROPERTY
setLeft(new Border() {{
setStyles("{color:10}");
setContent(new ScrollPane() {{
setHorizontalScrollBarPolicy(ScrollPane.ScrollBarPolicy.FILL_TO_CAPACITY);
setVerticalScrollBarPolicy(ScrollPane.ScrollBarPolicy.FILL_TO_CAPACITY);
setView(new StackPane() {{
add(new TableView() {{
namespace.put("stocksTableView", this);
setSelectMode(TableView.SelectMode.MULTI);
setStyles("{showHorizontalGridLines:false}");
// columns(): READ_ONLY_PROPERTY
getColumns().add(new TableView.Column() {{
setName("symbol");
setHeaderData("Symbol");
setWidth(1, true);
}}); // INSTANCE, name: <TableView.Column>
getColumns().add(new TableView.Column() {{
setName("value");
setHeaderData("Value");
setWidth(1, true);
// cellRenderer(): WRITABLE_PROPERTY
setCellRenderer(new TableViewNumberCellRenderer() {{
setStyles("{horizontalAlignment:'right'}");
setNumberFormat("$0.00");
}}); // INSTANCE, name: <content:TableViewNumberCellRenderer>
}}); // INSTANCE, name: <TableView.Column>
getColumns().add(new TableView.Column() {{
setName("change");
setHeaderData("Change");
setWidth(1, true);
// cellRenderer(): WRITABLE_PROPERTY
setCellRenderer(new ChangeCellRenderer() {{
setStyles("{horizontalAlignment:'right'}");
setNumberFormat("+0.00;-0.00");
}}); // INSTANCE, name: <stocktracker:ChangeCellRenderer>
}}); // INSTANCE, name: <TableView.Column>
}}); // INSTANCE, name: <TableView>
}}); // INSTANCE, name: <StackPane>
// columnHeader(): WRITABLE_PROPERTY
setColumnHeader(new TableViewHeader() {{
setTableView((TableView)namespace.get("stocksTableView"));
setSortMode(TableViewHeader.SortMode.SINGLE_COLUMN);
}}); // INSTANCE, name: <TableViewHeader>
}}); // INSTANCE, name: <ScrollPane>
}}); // INSTANCE, name: <Border>
// right(): WRITABLE_PROPERTY
setRight(new Border() {{
setStyles("{padding:6, color:10}");
setContent(new BoxPane() {{
namespace.put("detailPane", this);
setOrientation(Orientation.VERTICAL);
setStyles("{fill:true}");
add(new Label() {{
setTextKey("companyName");
setStyles("{font:{size:12, bold:true}}");
}}); // INSTANCE, name: <Label>
add(new Separator() {{
}}); // INSTANCE, name: <Separator>
add(new Form() {{
setStyles("{padding:0, fill:true, showFlagIcons:false, showFlagHighlight:false, leftAlignLabels:true}");
getSections().add(new Form.Section() {{
final ValueMapping valueMapping_0 = (new ValueMapping() {{
namespace.put("valueMapping", this);
}}); // INSTANCE, name: <stocktracker:ValueMapping>
final ChangeMapping changeMapping_1 = (new ChangeMapping() {{
namespace.put("changeMapping", this);
}}); // INSTANCE, name: <stocktracker:ChangeMapping>
final VolumeMapping volumeMapping_2 = (new VolumeMapping() {{
namespace.put("volumeMapping", this);
}}); // INSTANCE, name: <stocktracker:VolumeMapping>
add(new Label() {{
namespace.put("valueLabel", this);
setTextKey("value");
setTextBindMapping(valueMapping_0);
setStyles("{horizontalAlignment:'right'}");
Form.setLabel(this, "Value");
}}); // INSTANCE, name: <Label>
add(new Label() {{
namespace.put("changeLabel", this);
setTextKey("change");
setTextBindMapping(changeMapping_1);
setStyles("{horizontalAlignment:'right'}");
Form.setLabel(this, "Change");
}}); // INSTANCE, name: <Label>
add(new Label() {{
namespace.put("openingValueLabel", this);
setTextKey("openingValue");
setTextBindMapping(valueMapping_0);
setStyles("{horizontalAlignment:'right'}");
Form.setLabel(this, "Open");
}}); // INSTANCE, name: <Label>
add(new Label() {{
namespace.put("highValueLabel", this);
setTextKey("highValue");
setTextBindMapping(valueMapping_0);
setStyles("{horizontalAlignment:'right'}");
Form.setLabel(this, "High");
}}); // INSTANCE, name: <Label>
add(new Label() {{
namespace.put("lowValueLabel", this);
setTextKey("lowValue");
setTextBindMapping(valueMapping_0);
setStyles("{horizontalAlignment:'right'}");
Form.setLabel(this, "Low");
}}); // INSTANCE, name: <Label>
add(new Label() {{
namespace.put("volumeLabel", this);
setTextKey("volume");
setTextBindMapping(volumeMapping_2);
setStyles("{horizontalAlignment:'right'}");
Form.setLabel(this, "Volume");
}}); // INSTANCE, name: <Label>
}}); // INSTANCE, name: <Form.Section>
}}); // INSTANCE, name: <Form>
CodeEmitterRuntime.initialize(this, namespace);
}}); // INSTANCE, name: <BoxPane>
}}); // INSTANCE, name: <Border>
}}); // INSTANCE, name: <SplitPane>
}}); // INSTANCE, name: <TablePane.Row>
getRows().add(new TablePane.Row() {{
setHeight(-1);
add(new BoxPane() {{
setStyles("{horizontalAlignment:'left', verticalAlignment:'center'}");
add(new Label() {{
setText("Symbol");
setStyles("{font:{bold:true}}");
}}); // INSTANCE, name: <Label>
add(new TextInput() {{
namespace.put("symbolTextInput", this);
setTextSize(10);
setMaximumLength(8);
}}); // INSTANCE, name: <TextInput>
add(new LinkButton() {{
namespace.put("addSymbolButton", this);
setEnabled(false);
setTooltipText("Add symbol");
setButtonData(new ButtonData() {{
setIcon(new URL("file:/share/workspace/pivot/tutorials/src/org/apache/pivot/tutorials/stocktracker/add.png"));
}}); // INSTANCE, name: <content:ButtonData>
}}); // INSTANCE, name: <LinkButton>
add(new LinkButton() {{
namespace.put("removeSymbolsButton", this);
setEnabled(false);
setTooltipText("Remove selected symbols");
setButtonData(new ButtonData() {{
setIcon(new URL("file:/share/workspace/pivot/tutorials/src/org/apache/pivot/tutorials/stocktracker/delete.png"));
}}); // INSTANCE, name: <content:ButtonData>
}}); // INSTANCE, name: <LinkButton>
}}); // INSTANCE, name: <BoxPane>
}}); // INSTANCE, name: <TablePane.Row>
getRows().add(new TablePane.Row() {{
setHeight(-1);
add(new TablePane() {{
// columns(): READ_ONLY_PROPERTY
getColumns().add(new TablePane.Column() {{
setWidth(1, true);
}}); // INSTANCE, name: <TablePane.Column>
getColumns().add(new TablePane.Column() {{
setWidth(-1);
}}); // INSTANCE, name: <TablePane.Column>
getRows().add(new TablePane.Row() {{
add(new BoxPane() {{
add(new Label() {{
setText("Last Update");
}}); // INSTANCE, name: <Label>
add(new Label() {{
namespace.put("lastUpdateLabel", this);
}}); // INSTANCE, name: <Label>
}}); // INSTANCE, name: <BoxPane>
add(new BoxPane() {{
setStyles("{horizontalAlignment:'right'}");
add(new Label() {{
setText("Data provided by");
}}); // INSTANCE, name: <Label>
add(new LinkButton() {{
namespace.put("yahooFinanceButton", this);
setButtonData("Yahoo! Finance");
}}); // INSTANCE, name: <LinkButton>
}}); // INSTANCE, name: <BoxPane>
}}); // INSTANCE, name: <TablePane.Row>
}}); // INSTANCE, name: <TablePane>
}}); // INSTANCE, name: <TablePane.Row>
}}); // INSTANCE, name: <TablePane>
CodeEmitterRuntime.bind(this, namespace, "stocksTableView");
CodeEmitterRuntime.bind(this, namespace, "symbolTextInput");
CodeEmitterRuntime.bind(this, namespace, "addSymbolButton");
CodeEmitterRuntime.bind(this, namespace, "removeSymbolsButton");
CodeEmitterRuntime.bind(this, namespace, "detailPane");
CodeEmitterRuntime.bind(this, namespace, "lastUpdateLabel");
CodeEmitterRuntime.bind(this, namespace, "yahooFinanceButton");
CodeEmitterRuntime.initialize(this, namespace);
}};
}
}
========================
calathus 1/2/2011