sábado, 10 de maio de 2014

The Prototype Project has been created!

Hello.
My last post was about finding or developing a library in which a handler could create and bind automatically fields of some JavaBean to the JavaFx view.
Last post's link.
I've created a project as prototype of this feature. It's called FXControlCreator, and it can be found at GitHub here. Today I'm gonna describe what is developed there, how it works and what I'm gonna do next. I worked with Netbeans 8.0 and Java 8.

What I wanted when I started this project was a way to define an annotation to a JavaBean property. This annotation would be read by a handler and this handler would create at runtime the JavaFx controls to the view. So, lets see what I've done until now.

The first thing I'm gonna show is the annotation I abstracted. It's called FXControl.


 @Retention(RetentionPolicy.RUNTIME)  
 @Target({ElementType.FIELD, ElementType.METHOD})  
 public @interface FXControl {  
   String label() default "";  
   Class<? extends WhenCreate>[] when() default {Ever.class};  
   Class<? extends ControlFactory> factory();  
 }  


- label: it describes the text that fits as a label for the control created at the view.
- when: it describes when the handler must create the control. The default option is Ever.class. You can create other options by adding some interface that inherits WhenCreate, for example: InModeMaintenance.class, InModeView.class, etc.
- factory: it describes the implementation of ControlFactory. This implementation is responsible for instanciate the control.


 public interface ControlFactory<T extends Control, P extends Property> {  
   T createFor(P property);  
 }  
The base structure of the feature is an interface called ViewHandler, it describes the method handleControlCreation. This method recieves a PaneHandler, a WhereCreate class, and the java objects.


public interface ViewHandler {  
   void handleControlCreation(PaneHandler handler, Class<? extends WhenCreate> when, Object... objects);  
 }  
-PaneHandler: It's an interface that describes how the handler will add a new control inside.


public interface PaneHandler {  
   void addControl(FXControl annotation, Property property) throws CanNotInstanceControlCreator;  
 }  
So, that's all the structure of the project until now. Lets see an sample implementation of the responsabilities described above.


I created a class called TestProperty, and above the getter of it's property I defined the FxControl annotation. At the annotation I informed the control factory TextFieldFactory and it's label.


 public class TestProperty {  
   protected StringProperty property;  
   public TestProperty() {  
     this.property = new SimpleStringProperty();  
   }  
   public String getText() {  
     return property.get();  
   }  
   @FXControl(label = "Text Property" , factory = TextFieldFactory.class)  
   public StringProperty getProperty() {  
     return property;  
   }  
 }  
At my view controller I called an implementation of the ViewHandler to create the controls for the TestProperty object at initialize method. The handler was GridPaneViewHandler, because the main pane of my window was a GridPane.
I included a button in which I could test if the binding between the control and the property was working fine, and I defined the handleButtonAction as the action event of this button.
 public class FXMLController implements Initializable {  
   @FXML  
   private Label label;  
   @FXML  
   private GridPane pane;  
   private TestProperty test = new TestProperty();  
   @FXML  
   private void handleButtonAction(ActionEvent event) {  
     label.setText(test.getText());  
   }  
   @Override  
   public void initialize(URL url, ResourceBundle rb) {  
     new GridPaneViewHandler().handleControlCreation(new GridPaneHandler(pane), Ever.class, test);  
   }    
 }  


And this was the result. We can see that the automact creation of the TextField and it's label worked fine.




When I type something inside the control and click at the button, the label below the button shows what I type. So the binding worked fine too.




That's all until now folks! I've got already some things to develop subsequently.
- I'll find a way to pass atribute details to the control factory. For example, the width of the TextField.
- I'll implement new features to factoring controls and handling views.

Thank you for read my post. I hope you like it and, please, comment.
Bye!

terça-feira, 29 de abril de 2014

What if I develop a new library?

Hello.

There are some days in which I'm searching for a new thing to develop for fun. I was starting up in JavaFX, and I took a liking to it's features.
It seems to me JavaFX is a nice tool for developing rich interfaces. It's Java, so there are a lot of OO things we can do with it.
So, the first thought that came up to my mind was a way to create interfaces faster and automatically bind POJO's or JavaBean's properties to the view, in a programmatic way. This idea was first concepted by Clécius Martinkoski (his blog http://pedreirosdosoftware-pedreiros.rhcloud.com/author/clecius/) in an informal conversation, he is a Java Architect.

What I want is a way to get a class (POJO or JavaBean) and define annotations at it's fields. The annotations would define a label and a type of JavaFx field, for example. Something like this:

class Person{

   @AnnotationName(label = "Name", type = TextJavaFxField.class, width=50)
   private String name;

}

And a handler object, that could get these features by reflection, would create and bind, at runtime, the components at the interface of JavaFX to the object to which the annotations refer.

I looked for some already developed solutions for this problem, but I didn't find a tool that could satisfy what I was hoping for, or maybe I didn't get what the point of their solution was.

What I found was DSL (Domain Specifc Language) and JavaFx interface creation at this post:


Subsequently I'm gonna study and report here if DSL can solve my problem, or if cannot, and why. I'm gonna post my development parts here, comment them and share at GitHub.

If you read this post and think it's interesting, or if you've already worked in a similar problem, or if you know a nice tool that already does what I proposed; please, Share and comment so that I can write posts about them!

Thank you!
Cya.