
wicket.extensions.markup.html.form.palette.Palette Maven / Gradle / Ivy
/*
* $Id: Palette.java 5231 2006-04-02 01:34:49 +0200 (Sun, 02 Apr 2006) joco01 $ $Revision: 5231 $
* $Date: 2006-04-02 01:34:49 +0200 (Sun, 02 Apr 2006) $
*
* ==============================================================================
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package wicket.extensions.markup.html.form.palette;
import java.util.Collection;
import java.util.Iterator;
import wicket.AttributeModifier;
import wicket.Component;
import wicket.extensions.markup.html.form.palette.component.Choices;
import wicket.extensions.markup.html.form.palette.component.Recorder;
import wicket.extensions.markup.html.form.palette.component.Selection;
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;
/**
* 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 String SELECTED_HEADER_ID = "selectedHeader";
private static final String AVAILABLE_HEADER_ID = "availableHeader";
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();
add(recorderComponent);
choicesComponent = newChoicesComponent();
add(choicesComponent);
selectionComponent = newSelectionComponent();
add(selectionComponent);
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);
}
/**
* @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", getPath());
}
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 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 = (Collection)getModelObject();
model.clear();
// update model
Iterator it = getRecorderComponent().getSelectedChoices();
while (it.hasNext())
{
final Object selectedChoice = it.next();
model.add(selectedChoice);
}
}
/**
* 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().getPath())
.append("','").append(getSelectionComponent().getPath()).append("','").append(
getRecorderComponent().getPath()).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 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();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy