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].
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].