Java Database Application Library


Get JDAL (Java Database Application Library) at SourceForge.net. Fast, secure and Free Open Source software downloads

AbstractView


Introduction


AbstractView is the principal template ( Template , GoF) of JDAL Swing. Although it is possible to use the different functions provided by JDAL Swing in an independent form, AbstractView permits you condense the development work of forms in one unique job: Implement the method buildPanel().

AbstractView supports the automatic way of the following commune jobs in the development of Swing forms:


The process of building a form based on Abstractview can be summarised in the following steps:



Data Binding


AbstractView supports at the moment two forms of realizing the binding of data between user interface controls and the domain models:

In both cases, in creating binding between a Swing component and a property of the model, it will undertake the following actions:

<

Finally, AbstractView provides three template methods to customize the data binding process:



Structure


AbstractView delegates much of the work in strategies or support classes of JDAL. It is interesting to take a look as you might be interested in using them directly o personalising the behaviours.



CompositeBinder

Performs all work in data binding between the conttols and models. It can be used independently outside of AbstractView. It is not necessary to extend JDAL classes to dispose of data binding system. You can find more information in the data binding chapter..

ErrorProcessor

Processing strategy of binding errors. The implementation by default, BackgroundErrorProcessor changes the colour of the background of the controls that have failed and add a tooltip with the information of the error.

BinderFactory

PropertyBinder factory, CompositeBinder uses it to find the Binder appropriate for each type of control.

ControlAccessorFactory

Allow access to generic Swing controls. That is to say, perform control operations without the specific knowledge of the type of control.

ControlInitializer

Strategy of control initialization, usually with data from the respositories or other entities. The implementatión by default DefaultControlInitializer is able to detect annotationes JPA and the annotation @Reference of JDAL Core.



Example


Model

We will create a View for the following Project entity:

@Entity
@Table(name="project")
public class Project  {
 
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	protected Long id;     
	@NotEmpty
	protected String name = ""; 
	@ManyToOne
	private Company customer;
	@NotNull
	private Double amount;
	@ManyToOne
	private Bid bid;
	private String description;
	@OneToMany(mappedBy="project")
	private Set<Work> works;
	@OneToMany(mappedBy="project", targetEntity=ProjectAttachment.class, cascade=CascadeType.ALL, orphanRemoval=true)
	private List<Attachment> attachments;
	@ManyToMany(cascade=CascadeType.ALL)
	private Set<User> users;
 
	// Accessors, Mutators and Behavior Omited.

View

The target objective is to create a form to edit projects with the following specification:/p>




The following is the code of the projects form using AbstracView


public class ProjectView extends AbstractView<Project> {
 
	private JTextField name = new JTextField();
	private JComboBox customer = new JComboBox();
	private JComboBox bid = new JComboBox();
	private JTextField amount = new JTextField();
	private JTextArea description = new JTextArea(5, 0);
	/** ManyToMany editor */
	private Selector<User> users = new Selector<User>();
	@Autowired
	/** inner view to show edit attachments */
	private AttachmentView attachments;
	/** service to initialize entities */
	private PersistentService<Project, Long> service;
 
 
	public ProjectView() {
		this(new Project());
	}
 
	/**
	 * @param model 
	 */
	public ProjectView(Project model) {
		super(model);
	}
 
	/**
	 * Init method, called by container after property sets
	 */
	public void init() {
		service.initialize(getModel());   // initialize model, ie drop Hibernate Proxies
		getControlInitializer().setInitializeEntities(true);  /
		users.init();  // initialize Selector
		autobind();    // the binding code 
		FormUtils.link(customer, bid, "bids");  // link customer and bids
	}
 
	/**
	 * {@inheritDoc}
	 */
	@Override
	protected JComponent buildPanel() {
		// create a Box form builder to build the form
		BoxFormBuilder fb  = new BoxFormBuilder(FormUtils.createTitledBorder(getMessage("Project.title")));
		fb.row();
		fb.startBox();    // first Box (name, customer, bid and amount
		fb.setFixedHeight(true); //  fixed height on resizes
		fb.add(getMessage("Name"), name);
		fb.row();
		fb.add(getMessage("Customer"), customer);
		fb.row();
		fb.add(getMessage("Bid"), bid);
		fb.row();
		fb.add(getMessage("Amount"), amount);
		fb.endBox();     // end first box
		fb.row();
		fb.startBox();   // second box for description
		fb.add(FormUtils.newLabelForBox(getMessage("Description")));
		fb.row(Short.MAX_VALUE);    // let this row to be as higher as it can.
		fb.add(new JScrollPane(description));
		fb.endBox();     // end second box
		fb.row();
		fb.startBox();   // third box for user selector 
		fb.row();
		fb.add(new SeparatorTitled(getMessage("Users")));
		fb.row(Short.MAX_VALUE);  // let this row to be as higher as it can.
		fb.add(users);
		fb.endBox();     // end third box
		fb.row();
		fb.startBox();   // last box for attachment
		fb.row();
		fb.add(new SeparatorTitled(getMessage("Attachments")));
		fb.row(Short.MAX_VALUE);  // let this row to be as higher as it can.
		fb.add(attachments.getPanel());
		fb.endBox();    // end last box.
 
		return = fb.getForm();  // return the JCompoenent
	}
 
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onSetModel(Project project) {
		if (service != null)
			service.initialize(project);
	}
 
	/**
	 * @return the service
	 */
	public PersistentService<Project, Long> getService() {
		return service;
	}
 
	/**
	 * @param service the service to set
	 */
	public void setService(PersistentService<Project, Long> service) {
		this.service = service;
	}
 
}
 

Context Configuration

...
 
<!-- Persistent Serivice for Projects -->    
<jdal:service entity="info.joseluismartin.gefa.model.Project"/> 
 
<!-- Generic context service -->
<bean id="contextService" class="info.joseluismartin.logic.ContextPersistentManager" />
 
<!-- Configure factories and related swing dependences -->
<swing:defaults /> 
 
<!-- JSR-303 Validation -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
 
<bean id="errorProcessor" class="info.joseluismartin.gui.validation.BackgroundErrorProcessor" />
 
 <!-- Actions -->
 <bean id="acceptAction" class="info.joseluismartin.gui.action.ViewSaveAction" scope="prototype">
        <property name="icon" value="/images/16x16/dialog-ok.png"/>
        <property name="service" ref="objectService"/>
        <property name="name" value="Accept"/>
 </bean>
 
 <bean id="cancelAction" class="info.joseluismartin.gui.action.DialogCancelAction" scope="prototype">
        <property name="icon" value="/images/16x16/dialog-cancel.png"/>
        <property name="name" value="Cancel"/>
 </bean>
 
 
 <!-- Base definition for Editors  -->
 <bean id="editor" abstract="true" >
        <property name="acceptAction" ref="acceptAction" />
        <property name="cancelAction" ref="cancelAction" />
        <property name="dialogWidth" value="800" />
        <property name="dialogHeight" value="600" />
  </bean>
 
 
 <!-- Base definition for Views -->  
 <bean id="view" abstract="true" >
        <property name="controlAccessorFactory" ref="controlAccessorFactory" />
        <property name="binderFactory" ref="binderFactory" />
        <property name="controlInitializer" ref="controlInitializer" />
        <property name="validator"  ref="validator" />
        <property name="errorProcessors">
            <list>
                <ref bean="errorProcessor" />
            </list>
        </property>
 </bean>
 
 <!--  Default Control Initializer -->
 <bean id="controlInitializer" class="info.joseluismartin.gui.bind.AnnotationControlInitializer">
        <property name="persistentService" ref="contextService" />
 </bean>
 
<!-- Our Project View -->
<bean id="projectView" class="info.joseluismartin.gefa.ui.ProjectView" parent="view" scope="prototype" >
        <property name="service" ref="projectService" />
</bean>
 
<!-- Our Project Editor -->
<bean id="projectEditor" class="info.joseluismartin.gui.ViewDialog" parent="editor" scope="prototype">
        <property name="view" ref="projectView" />
</bean>
 
...

Now, we can get instances of the project editor by the bean "projectEditor".