rendered paste bodypackage com.sas.jobindsats.ui.palette;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import wicket.AttributeModifier;import wicket.Component;import wicket.markup.ComponentTag;import wicket.markup.html.PackageResourceReference;import wicket.markup.html.WebMarkupContainer;import wicket.markup.html.basic.Label;import wicket.markup.html.form.IChoiceRenderer;import wicket.markup.html.image.Image;import wicket.markup.html.panel.Panel;import wicket.model.IModel;import wicket.model.Model;import com.sas.jobindsats.ui.palette.component.Choices;import com.sas.jobindsats.ui.palette.component.Recorder;import com.sas.jobindsats.ui.palette.component.Selection;/** * Palette is a component that allows the user to easily select and order * multiple items by moving them from one select box into another. * * @author Igor Vaynberg ( ivaynberg ) * */public class Palette extends Panel { private static final long serialVersionUID = 1L; /** collection containing all available choices */ private IModel choicesModel; /** * choice render used to render the choices in both available and selected * collections */ private IChoiceRenderer choiceRenderer; /** number of rows to show in the select boxes */ private int rows; /** * recorder component used to track user's selection. it is updated by * javascript on changes. */ private Recorder recorderComponent; /** * component used to represent all available choices. by default this is a * select box with multiple attribute */ private Component choicesComponent; /** * component used to represent selected items. by default this is a select * box with multiple attribute */ private Component selectionComponent; /** reference to the palette's javascript resource */ private static final PackageResourceReference javascript = new PackageResourceReference( Palette.class, "palette.js"); /** reference to default up buttom image */ private static final PackageResourceReference upImage = new PackageResourceReference( Palette.class, "up.gif"); /** reference to default down button image */ private static final PackageResourceReference downImage = new PackageResourceReference( Palette.class, "down.gif"); /** reference to default remove button image */ private static final PackageResourceReference removeImage = new PackageResourceReference( Palette.class, "remove.gif"); /** reference to default add buttom image */ private static final PackageResourceReference addImage = new PackageResourceReference( Palette.class, "add.gif"); /** * @param id * component id * @param model * model representing collection of user's selections * @param choicesModel * model representing collection of all available choices * @param choiceRenderer * render used to render choices * @param rows * number of choices to be visible on the screen with out * scrolling * @param allowOrder * allow user to move selections up and down */ public Palette(String id, IModel model, IModel choicesModel, IChoiceRenderer choiceRenderer, int rows, boolean allowOrder) { super(id, model); this.choicesModel = choicesModel; this.choiceRenderer = choiceRenderer; this.rows = rows; recorderComponent = newRecorderComponent(); recorderComponent.setOutputMarkupId(true); add(recorderComponent); choicesComponent = newChoicesComponent(); choicesComponent.setOutputMarkupId(true); add(choicesComponent); selectionComponent = newSelectionComponent(); add(selectionComponent); add(newAddAllComponent()); add(newRemoveAllComponent()); add(newAddComponent()); add(newRemoveComponent()); add(newUpComponent().setVisible(allowOrder)); add(newDownComponent().setVisible(allowOrder)); /* * add(newAvailableHeader(AVAILABLE_HEADER_ID)); * add(newSelectedHeader(SELECTED_HEADER_ID)); */ addJavascript(); } /** * adds the component used to represent the link the the javascript file to * the header */ private void addJavascript() { IModel srcReplacement = new Model() { private static final long serialVersionUID = 1L; public Object getObject(Component component) { return urlFor(javascript); }; }; WebMarkupContainer javascript = new WebMarkupContainer("javascript"); javascript.add(new AttributeModifier("src", true, srcReplacement)); add(javascript); } public void resetSelectedChoices() { clearRecorder(); } private void clearRecorder() { getRecorderComponent().setModelObject(""); getRecorderComponent().invalid(); } /** * @return iterator over selected choices */ public Iterator getSelectedChoices() { return getRecorderComponent().getSelectedChoices(); } /** * @return iterator over unselected choices */ public Iterator getUnselectedChoices() { return getRecorderComponent().getUnselectedChoices(); } /** * factory method to create the tracker component * * @return tracker component */ private Recorder newRecorderComponent() { // create component that will keep track of selections return new Recorder("recorder", this) { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("id", getMarkupId()); } public void updateModel() { super.updateModel(); Palette.this.updateModel(); } }; } /** * factory method for the available items header * * @param componentId * component id of the returned header component * * @return available items component */ protected Component newAvailableHeader(String componentId) { return new Label(componentId, "Available"); } /** * factory method for the selected items header * * @param componentId * component id of the returned header component * * @return header component */ protected Component newSelectedHeader(String componentId) { return new Label(componentId, "Selected"); } /** * factory method for the add all component * * @return add all component */ protected Component newAddAllComponent() { return new WebMarkupContainer("addall") { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("href", Palette.this.getAddAllJS()); } }; } /** * factory method for the remove all component * * @return remove all component */ protected Component newRemoveAllComponent() { return new WebMarkupContainer("removeall") { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("href", Palette.this.getRemoveAllJS()); } }; } /** * factory method for the move down component * * @return move down component */ protected Component newDownComponent() { return new WebMarkupContainer("moveDownButton") { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("onclick", Palette.this.getDownOnClickJS()); } }.add(new Image("image", downImage)); } /** * factory method for the move up component * * @return move up component */ protected Component newUpComponent() { return new WebMarkupContainer("moveUpButton") { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("onclick", Palette.this.getUpOnClickJS()); } } .add(new Image("image", upImage)) ; } /** * factory method for the remove component * * @return remove component */ protected Component newRemoveComponent() { return new WebMarkupContainer("removeButton") { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("onclick", Palette.this.getRemoveOnClickJS()); } } .add(new Image("image", removeImage)) ; } /** * factory method for the addcomponent * * @return add component */ protected Component newAddComponent() { return new WebMarkupContainer("addButton") { private static final long serialVersionUID = 1L; protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.getAttributes().put("onclick", Palette.this.getAddOnClickJS());/* tag.getAttributes().put("ondblclick", Palette.this.getRemoveOnClickJS());*/ } } .add(new Image("image", addImage)) ; } /** * factory method for the selected items component * * @return selected items component */ protected Component newSelectionComponent() { return new Selection("selection", this); } /** * factory method for the available items component * * @return available items component */ protected Component newChoicesComponent() { return new Choices("choices", this); } private Component getChoicesComponent() { return choicesComponent; } private Component getSelectionComponent() { return selectionComponent; } private Recorder getRecorderComponent() { return recorderComponent; } /** * @return collection representing all available items */ public Collection getChoices() { return (Collection) choicesModel.getObject(this); } /** * @return collection representing selected items */ public Collection getModelCollection() { return (Collection) getModelObject(); } /** * @return choice renderer */ public IChoiceRenderer getChoiceRenderer() { return choiceRenderer; } /** * @return items visible without scrolling */ public int getRows() { return rows; } /** * update the model upon form processing */ protected final void updateModel() { // prepare model Collection model = new ArrayList(); // (Collection) // getModelObject(); // model.clear(); // update model Iterator it = getRecorderComponent().getSelectedChoices(); while (it.hasNext()) { final Object selectedChoice = it.next(); model.add(selectedChoice); } // fix for not calling setObject super.getModel().setObject(this, model); } /** * builds javascript handler call * * @param funcName * name of javascript function to call * @return string representing the call tho the function with palette params */ protected String buildJSCall(String funcName) { return new StringBuffer(funcName).append("('").append( getChoicesComponent().getMarkupId()).append("','").append( getSelectionComponent().getMarkupId()).append("','").append( getRecorderComponent().getMarkupId()).append("');").toString(); } /** * @return choices component on focus javascript handler */ public String getChoicesOnFocusJS() { return buildJSCall("paletteChoicesOnFocus"); } /** * @return selection component on focus javascript handler */ public String getSelectionOnFocusJS() { return buildJSCall("paletteSelectionOnFocus"); } /** * @return add all action javascript handler */ public String getAddAllJS() { return buildJSCall("javascript:paletteAddAll"); } /** * @return remove all action javascript handler */ public String getRemoveAllJS() { return buildJSCall("javascript:paletteRemoveAll"); } /** * @return add action javascript handler */ public String getAddOnClickJS() { return buildJSCall("paletteAdd"); } /** * @return remove action javascript handler */ public String getRemoveOnClickJS() { return buildJSCall("paletteRemove"); } /** * @return move up action javascript handler */ public String getUpOnClickJS() { return buildJSCall("paletteMoveUp"); } /** * @return move down action javascript handler */ public String getDownOnClickJS() { return buildJSCall("paletteMoveDown"); } protected void internalOnDetach() { super.internalOnDetach(); // we need to manually detach the choices model since it is not attached // to a component // an alternative might be to attach it to one of the subcomponents choicesModel.detach(); } protected void onModelChanged() { super.onModelChanged(); if (recorderComponent != null) { recorderComponent.reCreateModel(); } }}