View Source

h2. Generate UI with annotations
QuickBuild has a [bean editor] which is able to generate UI through annotations for below situations:
* View or edit steps.
* View or edit repositories.
* View or edit plugin settings.

Let's demonstrate this by enhancing myplugin to log the message supplied by user instead of just a hard coded "hello world". To do so, we create another class _MyAnotherStep.java_ like below:
{code}
package com.example.myplugin;

import org.hibernate.validator.NotEmpty;

import com.pmease.quickbuild.Context;
import com.pmease.quickbuild.annotation.Editable;
import com.pmease.quickbuild.annotation.Scriptable;
import com.pmease.quickbuild.stepsupport.Step;

@Editable(category="examples", name="print message",
description="This step prints an user defined message into the build log.")
public class MyAnotherStep extends Step {

private static final long serialVersionUID = 1L;

private String message;

// UI annotations must be applied to the getter method
@Editable(order=100, name="Your Message", description="Specify your message here.")
@NotEmpty
@Scriptable
public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

@Override
public void run() {
// Make sure to call getters to access scriptable fields, otherwise,
// the enclosed script will not be executed
Context.getLogger().info(getMessage());
}

}
{code}

And modify _MyPlugin.java_ to include this newly created step type as another extension:
{code}
package com.example.myplugin;

import com.pmease.quickbuild.extensionpoint.StepProvider;
import com.pmease.quickbuild.pluginsupport.AbstractPlugin;
import com.pmease.quickbuild.stepsupport.Step;

public class MyPlugin extends AbstractPlugin {

@Override
public Object[] getExtensions() {
return new Object[] {
new StepProvider() {

@Override
public Class<? extends Step> getStepClass() {
return MyStep.class;
}

},
new StepProvider() {

@Override
public Class<? extends Step> getStepClass() {
return MyAnotherStep.class;
}

}

};
}

}
{code}

Save these classes, and start QuickBuild from Eclipse. You should now be able to see a new step type _print message_ in the _examples_ category. Edit this step by adding it to build execution sequence. Below UI will be presented:
!ui1.png!
Run the build and your supplied message will be printed into build log.

Now let's look at annotations applied to method _MyAnotherStep#getMessage()_:
# UI annotations must be applied to field's getter method.
# The annotation _@Editable_ marks a field as editable and defines display name, order, and description of the field. These attributes are optional:
#* If name is left empty, the field name will be used.
#* If description is left empty, no description will be displayed when you edit the property.
#* If order is left empty, a default value of MAX_INTEGER will be assumed.
# _@NotEmpty_ is an optional constraint annotation telling QuickBuild that this field does not accept empty value.
# _@Scriptable_ is optional and is normally applied to field of String type. It allows the field to make use of QuickBuild's scripting facility. For example, when define the _print message_ step, you may specify the message as _hello $\{user.name\}_ to say hello to current QuickBuild user. Scriptable field needs to be accessed through getter method; otherwise the embedded scripts will not be executed. Method _MyAnotherStep.java#run()_ obeys this rule by executing _Context.getLogger().info(getMessage());_ instead of _Context.getLogger().info(message);_.

For more information on how to annotate classes to generate customized UI, please refer to [bean editor].

h2. Create UI with Wicket
QuickBuild uses [Wicket|http://wicket.apache.org] as its presentation layer. If your plugin contributes tabs/panels to QuickBuild, you will need to have some knowledge of this framework. We demonstrate this by adding a new panel to build overview screen printing "hello world".

First create a class _MyPanel.java_ like below:
{code}
package com.example.myplugin;

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;

import com.pmease.quickbuild.Context;

public class MyPanel extends Panel {

private static final long serialVersionUID = 1L;

public MyPanel(String id) {
super(id);

String userName;
if (Context.getUser() != null)
userName = Context.getUser().getName();
else
userName = "guest";
add(new Label("message", "hello " + userName));
}

}
{code}
And add its html template _MyPanel.html_ like below:
{code}
<wicket:panel>
<div wicket:id="message" class="round-corner" style="padding:16px;"/>
</wicket:panel>
{code}

Finally modify _MyPlugin.java_ to implement extension point _BuildOverviewContribution_:
{code}
package com.example.myplugin;

import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.markup.html.panel.Panel;

import com.pmease.quickbuild.extensionpoint.BuildOverviewContribution;
import com.pmease.quickbuild.extensionpoint.StepProvider;
import com.pmease.quickbuild.extensionpoint.support.PanelCreator;
import com.pmease.quickbuild.pluginsupport.AbstractPlugin;
import com.pmease.quickbuild.stepsupport.Step;

public class MyPlugin extends AbstractPlugin {

@Override
public Object[] getExtensions() {
return new Object[] {
new StepProvider() {

@Override
public Class<? extends Step> getStepClass() {
return MyStep.class;
}

},
new StepProvider() {

@Override
public Class<? extends Step> getStepClass() {
return MyAnotherStep.class;
}

},
new BuildOverviewContribution() {

public List<PanelCreator> getPanelCreators() {
List<PanelCreator> creators = new ArrayList<PanelCreator>();
creators.add(new PanelCreator() {

public Panel getPanel(String id) {
return new MyPanel(id);
}

});
return creators;
}

public int getOrder() {
return 500;
}
}
};
}

}
{code}

Start QuickBuild and switch to build overview screen, you will see a new panel saying hello to current user.

For more details of creating plugin UI with Wicket, refer to plugin _com.pmease.quickbuild.plugin.sample.javancss_ in [plugin examples].