You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/05/01 16:44:26 UTC
svn commit: r940042 - in /click/trunk/click/framework/src/org/apache/click:
Page.java control/AbstractContainer.java control/Container.java
control/FieldSet.java control/Form.java control/Panel.java
util/ContainerUtils.java
Author: sabob
Date: Sat May 1 14:44:26 2010
New Revision: 940042
URL: http://svn.apache.org/viewvc?rev=940042&view=rev
Log:
Added support for replacing a control if another control already exists with matching name. CLK-666
Modified:
click/trunk/click/framework/src/org/apache/click/Page.java
click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java
click/trunk/click/framework/src/org/apache/click/control/Container.java
click/trunk/click/framework/src/org/apache/click/control/FieldSet.java
click/trunk/click/framework/src/org/apache/click/control/Form.java
click/trunk/click/framework/src/org/apache/click/control/Panel.java
click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java
Modified: click/trunk/click/framework/src/org/apache/click/Page.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/Page.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/Page.java (original)
+++ click/trunk/click/framework/src/org/apache/click/Page.java Sat May 1 14:44:26 2010
@@ -359,13 +359,17 @@ public class Page implements Serializabl
// Public Methods ---------------------------------------------------------
/**
- * Add the control to the page. The control will be added to the pages model
- * using the controls name as the key. The Controls parent property will
+ * Add the control to the page. The control will be added to the page model
+ * using the control name as the key. The Controls parent property will
* also be set to the page instance.
- *
- * @param control the control to add
- * @throws IllegalArgumentException if the control is null, or if the name
- * of the control is not defined
+ * <p/>
+ * <b>Please note</b>: if the page contains a control with the same name as
+ * the given control, that control will be replaced by the given control.
+ * If a control has no name defined it cannot be replaced.
+ *
+ * @param control the control to add to the page
+ * @throws IllegalArgumentException if the control is null or if the name
+ * of the control is not defined
*/
public void addControl(Control control) {
if (control == null) {
@@ -376,6 +380,14 @@ public class Page implements Serializabl
+ control.getClass());
}
+ // Check if page already contains a named value
+ Object currentValue = getModel().get(control.getName());
+ if (currentValue != null && currentValue instanceof Control) {
+ Control currentControl = (Control) currentValue;
+ replaceControl(currentControl, control);
+ return;
+ }
+
// Note: set parent first as setParent might veto further processing
control.setParent(this);
@@ -831,11 +843,14 @@ public class Page implements Serializabl
/**
* Add the named object value to the Pages model map.
+ * <p/>
+ * <b>Please note</b>: if the Page contains an object with a matching name,
+ * that object will be replaced by the given value.
*
* @param name the key name of the object to add
* @param value the object to add
* @throws IllegalArgumentException if the name or value parameters are
- * null, or if there is already a named value in the model
+ * null
*/
public void addModel(String name, Object value) {
if (name == null) {
@@ -848,13 +863,8 @@ public class Page implements Serializabl
+ "to " + getClass().getName() + " model";
throw new IllegalArgumentException(msg);
}
- if (getModel().containsKey(name)) {
- String msg = getClass().getName() + " model already contains "
- + "value named " + name;
- throw new IllegalArgumentException(msg);
- } else {
- getModel().put(name, value);
- }
+
+ getModel().put(name, value);
}
/**
@@ -1190,7 +1200,7 @@ public class Page implements Serializabl
* @param location the path to redirect the request to
* @param params the map of request parameter name and value pairs
*/
- public void setRedirect(String location, Map<String, Object> params) {
+ public void setRedirect(String location, Map<String, ? extends Object> params) {
Context context = getContext();
if (StringUtils.isNotBlank(location)) {
if (location.charAt(0) == '/') {
@@ -1260,7 +1270,9 @@ public class Page implements Serializabl
* @throws IllegalArgumentException if the Page Class is not configured
* with a unique path
*/
- public void setRedirect(Class<? extends Page> pageClass, Map<String, Object> params) {
+ public void setRedirect(Class<? extends Page> pageClass,
+ Map<String, ? extends Object> params) {
+
String target = getContext().getPagePath(pageClass);
// If page class maps to a jsp, convert to htm which allows ClickServlet
@@ -1336,4 +1348,39 @@ public class Page implements Serializabl
this.template = template;
}
+ // Private methods --------------------------------------------------------
+
+ /**
+ * Replace the current control with the new control.
+ *
+ * @param currentControl the control currently contained in the page
+ * @param newControl the control to replace the current control container in
+ * the page
+ *
+ * @throws IllegalStateException if the currentControl is not contained in
+ * the page
+ */
+ private void replaceControl(Control currentControl, Control newControl) {
+
+ // Current control and new control are referencing the same object
+ // so we exit early
+ if (currentControl == newControl) {
+ return;
+ }
+
+ int controlIndex = getControls().indexOf(currentControl);
+ if (controlIndex == -1) {
+ throw new IllegalStateException("Cannot replace the given control"
+ + " because it is not present in the page");
+ }
+
+ // Note: set parent first since setParent might veto further processing
+ newControl.setParent(this);
+ currentControl.setParent(null);
+
+ // Set control to current control index
+ getControls().set(controlIndex, newControl);
+
+ addModel(newControl.getName(), newControl);
+ }
}
Modified: click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java Sat May 1 14:44:26 2010
@@ -81,11 +81,15 @@ public abstract class AbstractContainer
/**
* @see org.apache.click.control.Container#add(org.apache.click.Control).
+ * <p/>
+ * <b>Please note</b>: if the container contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
*
* @param control the control to add to the container
* @return the control that was added to the container
- * @throws IllegalArgumentException if the control is null or the container
- * already contains a control with the same name
+ * @throws IllegalArgumentException if the control is null
*/
public Control add(Control control) {
return insert(control, getControls().size());
@@ -95,7 +99,12 @@ public abstract class AbstractContainer
* Add the control to the container at the specified index, and return the
* added instance.
* <p/>
- * <b>Please note</b> if the specified control already has a parent assigned,
+ * <b>Please note</b>: if the container contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
+ * <b>Also note</b> if the specified control already has a parent assigned,
* it will automatically be removed from that parent and inserted into this
* container.
*
@@ -106,13 +115,33 @@ public abstract class AbstractContainer
* @return the control that was added to the container
*
* @throws IllegalArgumentException if the control is null or if the control
- * and container is the same instance or the container already contains
- * a control with the same name or if a Field name is not defined
+ * and container is the same instance
*
* @throws IndexOutOfBoundsException if index is out of range
* <tt>(index < 0 || index > getControls().size())</tt>
*/
public Control insert(Control control, int index) {
+ // Check if panel already contains the control
+ String controlName = control.getName();
+ if (controlName != null) {
+ // Check if container already contains the control
+ Control currentControl = getControlMap().get(control.getName());
+
+ // If container already contains the control do a replace
+ if (currentControl != null) {
+
+ // Current control and new control are referencing the same object
+ // so we exit early
+ if (currentControl == control) {
+ return control;
+ }
+
+ // If the two controls are different objects, we remove the current
+ // control and add the given control
+ return replace(currentControl, control);
+ }
+ }
+
return ContainerUtils.insert(this, control, index, getControlMap());
}
@@ -128,6 +157,28 @@ public abstract class AbstractContainer
}
/**
+ * Replace the control in the container at the specified index, and return
+ * the newly added control.
+ *
+ * @see org.apache.click.control.Container#replace(org.apache.click.Control, org.apache.click.Control)
+ *
+ * @param currentControl the control currently contained in the container
+ * @param newControl the control to replace the current control contained in
+ * the container
+ * @return the new control that replaced the current control
+ *
+ * @throws IllegalArgumentException if the currentControl or newControl is
+ * null
+ * @throws IllegalStateException if the currentControl is not contained in
+ * the container
+ */
+ public Control replace(Control currentControl, Control newControl) {
+ int controlIndex = getControls().indexOf(currentControl);
+ return ContainerUtils.replace(this, currentControl, newControl,
+ controlIndex, getControlMap());
+ }
+
+ /**
* @see org.apache.click.control.Container#getControls().
*
* @return the sequential list of controls held by the container
Modified: click/trunk/click/framework/src/org/apache/click/control/Container.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/Container.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/Container.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/Container.java Sat May 1 14:44:26 2010
@@ -58,6 +58,17 @@ public interface Container extends Contr
Control insert(Control control, int index);
/**
+ * Replace the current control with the new control, and return the newly
+ * added control.
+ *
+ * @param currentControl the control currently contained in the container
+ * @param newControl the control to replace the current control contained in
+ * the container
+ * @return the new control that replaced the current control
+ */
+ Control replace(Control currentControl, Control newControl);
+
+ /**
* Remove the given control from the container, returning true if the
* control was found in the container and removed, or false if the control
* was not found.
Modified: click/trunk/click/framework/src/org/apache/click/control/FieldSet.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/FieldSet.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/FieldSet.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/FieldSet.java Sat May 1 14:44:26 2010
@@ -165,6 +165,11 @@ public class FieldSet extends Field impl
* Add a Field to the FieldSet at the specified index and return the added
* instance.
* <p/>
+ * <b>Please note</b>: if the FieldSet contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Controls can be retrieved from the Map {@link #getControlMap() controlMap}
* where the key is the Control name and value is the Control instance.
* <p/>
@@ -185,10 +190,30 @@ public class FieldSet extends Field impl
* @param index the index at which the control is to be inserted
* @return the control that was added to the FieldSet
* @throws IllegalArgumentException if the control is null, the Field's name
- * is not defined, the container already contains a control with the same
- * name or if the control is neither a Field nor FieldSet
+ * is not defined or if the control is neither a Field nor FieldSet
*/
public Control insert(Control control, int index) {
+ // Check if container already contains the control
+ String controlName = control.getName();
+ if (controlName != null) {
+ Control currentControl = getControlMap().get(controlName);
+
+ // If container already contains the control do a replace
+ if (currentControl != null
+ && !(control instanceof Label)) {
+
+ // Current control and new control are referencing the same object
+ // so we exit early
+ if (currentControl == control) {
+ return control;
+ }
+
+ // If the two controls are different objects, we remove the current
+ // control and add the given control
+ return replace(currentControl, control);
+ }
+ }
+
ContainerUtils.insert(this, control, index, getControlMap());
if (control instanceof Field) {
@@ -219,8 +244,70 @@ public class FieldSet extends Field impl
}
/**
+ * Replace the current control with the new control.
+ *
+ * @param currentControl the current control container in the fieldset
+ * @param newControl the control to replace the current control
+ * @return the new control that replaced the current control
+ *
+ * @throws IllegalArgumentException if the currentControl or newControl is
+ * null
+ * @throws IllegalStateException if the currentControl is not contained in
+ * the fieldset
+ */
+ @Override
+ public Control replace(Control currentControl, Control newControl) {
+ // Current and new control is the same instance - exit early
+ if (currentControl == newControl) {
+ return newControl;
+ }
+
+ int controlIndex = getControls().indexOf(currentControl);
+ Control result = ContainerUtils.replace(this, currentControl, newControl,
+ controlIndex, getControlMap());
+
+ if (newControl instanceof Field) {
+ Field field = (Field) newControl;
+
+ // Replace field in fieldList for fast access
+ if (!(field instanceof Button)) {
+ int fieldIndex = getFieldList().indexOf(currentControl);
+ getFieldList().set(fieldIndex, field);
+ }
+
+ // Set parent form
+ Form form = getForm();
+ field.setForm(form);
+
+ if (currentControl instanceof Field) {
+ // Remove form reference from current control
+ ((Field) currentControl).setForm(null);
+ }
+
+ if (form != null && form.getDefaultFieldSize() > 0) {
+ if (field instanceof TextField) {
+ ((TextField) field).setSize(form.getDefaultFieldSize());
+
+ } else if (field instanceof FileField) {
+ ((FileField) field).setSize(form.getDefaultFieldSize());
+
+ } else if (field instanceof TextArea) {
+ ((TextArea) field).setCols(form.getDefaultFieldSize());
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
* Add a Control to the fieldset and return the added instance.
* <p/>
+ * <b>Please note</b>: if the FieldSet contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Controls can be retrieved from the Map {@link #getControlMap() controlMap}
* where the key is the Control name and value is the Control instance.
* <p/>
@@ -234,8 +321,7 @@ public class FieldSet extends Field impl
* @return the control that was added to the container
*
* @throws IllegalArgumentException if the control is null, the Field's name
- * is not defined, the container already contains a control with the same
- * name or if the control is neither a Field nor FieldSet
+ * is not defined or if the control is neither a Field nor FieldSet
*/
public Control add(Control control) {
return insert(control, getControls().size());
@@ -244,6 +330,11 @@ public class FieldSet extends Field impl
/**
* Add the field to the fieldSet, and set the fields form property.
* <p/>
+ * <b>Please note</b>: if the FieldSet contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Fields can be retrieved from the Map {@link #getFields() fields} where
* the key is the Field name and value is the Field instance.
* <p/>
@@ -253,9 +344,8 @@ public class FieldSet extends Field impl
*
* @param field the field to add to the fieldSet
* @return the field added to this fieldSet
- * @throws IllegalArgumentException if the field is null, the field name
- * is not defined or the fieldSet already contains a control with the same
- * name
+ * @throws IllegalArgumentException if the field is null or the field name
+ * is not defined
*/
public Field add(Field field) {
add((Control) field);
@@ -265,6 +355,11 @@ public class FieldSet extends Field impl
/**
* Add the field to the fieldset and specify the field width in columns.
* <p/>
+ * <b>Please note</b>: if the FieldSet contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Fields can be retrieved from the Map {@link #getFields() fields} where
* the key is the Field name and value is the Field instance.
* <p/>
@@ -276,8 +371,7 @@ public class FieldSet extends Field impl
* @param width the width of the field in table columns
* @return the field added to this fieldset
* @throws IllegalArgumentException if the field is null, field name is
- * not defined, field is a Button or HiddenField, the fieldset already
- * contains a field with the same name or the width < 1
+ * not defined, field is a Button or HiddenField or the width < 1
*/
public Field add(Field field, int width) {
add((Control) field, width);
@@ -287,6 +381,11 @@ public class FieldSet extends Field impl
/**
* Add the control to the fieldset and specify the control's width in columns.
* <p/>
+ * <b>Please note</b>: if the FieldSet contains a control with the same name
+ * as the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Controls can be retrieved from the Map {@link #getControlMap() controlMap}
* where the key is the Control name and value is the Control instance.
* <p/>
@@ -298,8 +397,7 @@ public class FieldSet extends Field impl
* @param width the width of the control in table columns
* @return the control added to this fieldSet
* @throws IllegalArgumentException if the control is null, control is a
- * Button or HiddenField, the fieldSet already contains a control with the
- * same name or the width < 1
+ * Button or HiddenField or the width < 1
*/
public Control add(Control control, int width) {
if (control instanceof Button || control instanceof HiddenField) {
@@ -376,7 +474,7 @@ public class FieldSet extends Field impl
*
* @return the sequential list of controls held by the container
*/
- public List getControls() {
+ public List<Control> getControls() {
if (controls == null) {
controls = new ArrayList();
}
@@ -867,7 +965,7 @@ public class FieldSet extends Field impl
*
* @return the map of controls
*/
- protected Map getControlMap() {
+ protected Map<String, Control> getControlMap() {
if (controlMap == null) {
controlMap = new HashMap();
}
Modified: click/trunk/click/framework/src/org/apache/click/control/Form.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/Form.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/Form.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/Form.java Sat May 1 14:44:26 2010
@@ -697,6 +697,11 @@ public class Form extends AbstractContai
* Add the control to the form at the specified index, and return the
* added instance.
* <p/>
+ * <b>Please note</b>: if the form contains a control with the same name as
+ * the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Controls can be retrieved from the Map {@link #getControlMap() controlMap}
* where the key is the Control name and value is the Control instance.
* <p/>
@@ -711,11 +716,6 @@ public class Form extends AbstractContai
* <b>Please note</b> if the specified control already has a parent assigned,
* it will automatically be removed from that parent and inserted into the
* form.
- * <p/>
- * <b>Also note:</b> Form automatically adds hidden fields to preserve
- * state across requests. Be aware of this when using <tt>insert</tt> as the
- * hidden fields might influence the position of the Control you insert.
- * <em>This restriction might be removed in a future version of Click.</em>
*
* @see Container#insert(org.apache.click.Control, int)
*
@@ -724,8 +724,7 @@ public class Form extends AbstractContai
* @return the control that was added to the container
*
* @throws IllegalArgumentException if the control is null or if the control
- * and container is the same instance or the container already contains
- * a control with the same name or if the Field name is not defined
+ * and container is the same instance or if the Field name is not defined
*
* @throws IndexOutOfBoundsException if index is out of range
* <tt>(index < 0 || index > getControls().size())</tt>
@@ -733,10 +732,31 @@ public class Form extends AbstractContai
@Override
public Control insert(Control control, int index) {
+ // Check if container already contains the control
+ String controlName = control.getName();
+ if (controlName != null) {
+ Control currentControl = getControlMap().get(controlName);
+
+ // If container already contains the control do a replace
+ if (currentControl != null
+ && !(control instanceof Label)) {
+
+ // Current control and new control are referencing the same object
+ // so we exit early
+ if (currentControl == control) {
+ return control;
+ }
+
+ // If the two controls are different objects, replace the current
+ // control with the given control
+ return replace(currentControl, control);
+ }
+ }
+
// Adjust index for hidden fields added by Form. CLK-447
int realIndex = Math.min(index, getControls().size() - insertIndexOffset);
- super.insert(control, realIndex);
+ ContainerUtils.insert(this, control, realIndex, getControlMap());
if (control instanceof Field) {
Field field = (Field) control;
@@ -772,6 +792,11 @@ public class Form extends AbstractContai
/**
* Add a Control to the form and return the added instance.
* <p/>
+ * <b>Please note</b>: if the form contains a control with the same name as
+ * the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Controls can be retrieved from the Map {@link #getControlMap() controlMap}
* where the key is the Control name and value is the Control instance.
* <p/>
@@ -796,6 +821,11 @@ public class Form extends AbstractContai
/**
* Add the field to the form, and set the fields form property.
* <p/>
+ * <b>Please note</b>: if the form contains a control with the same name as
+ * the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Fields can be retrieved from the Map {@link #getFields() fields} where
* the key is the Field name and value is the Field instance.
* <p/>
@@ -817,6 +847,11 @@ public class Form extends AbstractContai
/**
* Add the field to the form and specify the field's width in columns.
* <p/>
+ * <b>Please note</b>: if the form contains a control with the same name as
+ * the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Fields can be retrieved from the Map {@link #getFields() fields} where
* the key is the Field name and value is the Field instance.
* <p/>
@@ -841,6 +876,11 @@ public class Form extends AbstractContai
/**
* Add the control to the form and specify the control's width in columns.
* <p/>
+ * <b>Please note</b>: if the form contains a control with the same name as
+ * the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* Controls can be retrieved from the Map {@link #getControlMap() controlMap}
* where the key is the Control name and value is the Control instance.
* <p/>
@@ -875,6 +915,71 @@ public class Form extends AbstractContai
}
/**
+ * Replace the control in the form at the specified index, and return
+ * the newly added control.
+ *
+ * @see org.apache.click.control.Container#replace(org.apache.click.Control, org.apache.click.Control)
+ *
+ * @param currentControl the control currently contained in the form
+ * @param newControl the control to replace the current control contained in
+ * the form
+ * @return the new control that replaced the current control
+ *
+ * @throws IllegalArgumentException if the currentControl or newControl is
+ * null
+ * @throws IllegalStateException if the currentControl is not contained in
+ * the form
+ */
+ @Override
+ public Control replace(Control currentControl, Control newControl) {
+ // Current and new control is the same instance - exit early
+ if (currentControl == newControl) {
+ return newControl;
+ }
+
+ int controlIndex = getControls().indexOf(currentControl);
+ Control result = ContainerUtils.replace(this, currentControl, newControl,
+ controlIndex, getControlMap());
+
+ if (newControl instanceof Field) {
+ Field field = (Field) newControl;
+
+ if (field instanceof Button) {
+ // Replace field in buttonList for fast access
+ int buttonIndex = getButtonList().indexOf(currentControl);
+ getButtonList().set(buttonIndex, (Button) field);
+
+ } else {
+ // Replace field in fieldList for fast access
+ int fieldIndex = getFieldList().indexOf(currentControl);
+ getFieldList().set(fieldIndex, field);
+ }
+
+ // Set parent form
+ field.setForm(this);
+
+ if (currentControl instanceof Field) {
+ // Remove form reference from current control
+ ((Field) currentControl).setForm(null);
+ }
+
+ if (getDefaultFieldSize() > 0) {
+ if (field instanceof TextField) {
+ ((TextField) field).setSize(getDefaultFieldSize());
+
+ } else if (field instanceof FileField) {
+ ((FileField) field).setSize(getDefaultFieldSize());
+
+ } else if (field instanceof TextArea) {
+ ((TextArea) field).setCols(getDefaultFieldSize());
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
* @see Container#remove(org.apache.click.Control)
*
* @param control the control to remove from the container
Modified: click/trunk/click/framework/src/org/apache/click/control/Panel.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/control/Panel.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/control/Panel.java (original)
+++ click/trunk/click/framework/src/org/apache/click/control/Panel.java Sat May 1 14:44:26 2010
@@ -30,6 +30,7 @@ import org.apache.click.Context;
import org.apache.click.Control;
import org.apache.click.Page;
import org.apache.click.util.ClickUtils;
+import org.apache.click.util.ContainerUtils;
import org.apache.click.util.Format;
import org.apache.click.util.HtmlStringBuffer;
import org.apache.click.util.SessionMap;
@@ -314,9 +315,8 @@ public class Panel extends AbstractConta
*
* @param control the control to add to the container
* @return the control that was added to the container
- * @throws IllegalArgumentException if the control is null, if the name
- * of the control is not defined or the container already contains a
- * control with the same name
+ * @throws IllegalArgumentException if the control is null or if the name
+ * of the control is not defined
*/
public Control addControl(Control control) {
return add(control);
@@ -325,21 +325,22 @@ public class Panel extends AbstractConta
/**
* Add the control to the panel and return the specified control.
* <p/>
+ * <b>Please note</b>: if the Panel contains a control with the same name as
+ * the given control, that control will be
+ * {@link #replace(org.apache.click.Control, org.apache.click.Control) replaced}
+ * by the given control. If a control has no name defined it cannot be replaced.
+ * <p/>
* In addition to the requirements specified by
- * {@link Container#add(org.apache.click.Control)}, note
- * the following:
+ * {@link Container#add(org.apache.click.Control)}, note the following:
* <ul>
* <li>
- * The control's name must be set when adding to a panel.
- * </li>
- * <li>
- * The control will be added to the Panel model using the controls name as
- * the key and can be accessed through {@link #getModel()}. This allows
- * one to reference the control in the Panels template.
+ * If the control name is defined, it will be added to the Panel
+ * {@link #getModel() model} using the control name as the key. The control
+ * can be referenced via it's name from the Panel template.
* </li>
* <li>
* If the specified control is an <tt>instanceof</tt> a Panel, it will
- * also be added to a list of panels and can be accessed through
+ * be added to the list of panels and can be accessed through
* {@link #getPanels()}.
* </li>
* </ul>
@@ -347,15 +348,34 @@ public class Panel extends AbstractConta
*
* @param control the control to add to the container
* @return the control that was added to the container
- * @throws IllegalArgumentException if the control is null or the container
- * already contains a control with the same name
+ * @throws IllegalArgumentException if the control is null
*/
@Override
- public Control add(Control control) {
- super.add(control);
-
+ public Control insert(Control control, int index) {
+ // Check if panel already contains the control
String controlName = control.getName();
if (controlName != null) {
+ // Check if container already contains the control
+ Control currentControl = getControlMap().get(controlName);
+
+ // If container already contains the control do a replace
+ if (currentControl != null) {
+
+ // Current control and new control are referencing the same object
+ // so we exit early
+ if (currentControl == control) {
+ return control;
+ }
+
+ // If the two controls are different objects, we remove the current
+ // control and add the given control
+ return replace(currentControl, control);
+ }
+ }
+
+ ContainerUtils.insert(this, control, index, getControlMap());
+
+ if (controlName != null) {
// If controls name is set, add control to the model
addModel(controlName, control);
}
@@ -368,6 +388,43 @@ public class Panel extends AbstractConta
}
/**
+ * Replace the current control with the new control.
+ *
+ * @param currentControl the current control container in the panel
+ * @param newControl the control to replace the current control
+ * @return the new control that replaced the current control
+ *
+ * @throws IllegalArgumentException if the currentControl or newControl is
+ * null
+ * @throws IllegalStateException if the currentControl is not contained in
+ * the panel
+ */
+ @Override
+ public Control replace(Control currentControl, Control newControl) {
+ // Current and new control is the same instance - exit early
+ if (currentControl == newControl) {
+ return newControl;
+ }
+
+ int controlIndex = getControls().indexOf(currentControl);
+ Control result = ContainerUtils.replace(this, currentControl, newControl,
+ controlIndex, getControlMap());
+
+ String controlName = newControl.getName();
+ if (controlName != null) {
+ // If controls name is set, add control to the model
+ addModel(controlName, newControl);
+ }
+
+ if (newControl instanceof Panel) {
+ int panelIndex = getPanels().indexOf(currentControl);
+ getPanels().set(panelIndex, (Panel) newControl);
+ }
+
+ return result;
+ }
+
+ /**
* @see #remove(org.apache.click.Control)
*
* @deprecated use {@link #remove(org.apache.click.Control)} instead
@@ -445,7 +502,7 @@ public class Panel extends AbstractConta
* Set the panel active flag. The active property is normally managed and
* set by Panel containers.
*
- * <b>Please note</b>: inactive panels do not have their page events
+ * <b>Please note</b>: inactive panels do not have their events
* ({@link #onInit()}, {@link #onProcess()}, {@link #onRender()}) processed.
*
* @param active the active flag
@@ -550,11 +607,14 @@ public class Panel extends AbstractConta
/**
* Add the named object value to the Panels model map.
+ * <p/>
+ * <b>Please note</b>: if the Panel contains an object with a matching name,
+ * that object will be replaced by the given value.
*
* @param name the key name of the object to add
* @param value the object to add
* @throws IllegalArgumentException if the name or value parameters are
- * null, or if there is already a named value in the model
+ * null
*/
public void addModel(String name, Object value) {
if (name == null) {
@@ -567,13 +627,7 @@ public class Panel extends AbstractConta
+ "to " + getClass().getName() + " model";
throw new IllegalArgumentException(msg);
}
- if (getModel().containsKey(name)) {
- String msg = getClass().getName() + " model already contains "
- + "value named " + name;
- throw new IllegalArgumentException(msg);
- } else {
- getModel().put(name, value);
- }
+ getModel().put(name, value);
}
/**
Modified: click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java?rev=940042&r1=940041&r2=940042&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java (original)
+++ click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java Sat May 1 14:44:26 2010
@@ -479,9 +479,13 @@ public class ContainerUtils {
* Add the given control to the container at the specified index, and return
* the added instance.
* <p/>
- * <b>Please note</b> if the specified control already has a parent assigned,
- * it will automatically be removed from that parent and inserted into the
- * container.
+ * <b>Please note</b>: an exception is raised if the container contains a
+ * control with the same name as the given control. It is the responsibility
+ * of the caller to replace existing controls.
+ * <p/>
+ * <b>Also note</b> if the specified control already has a parent assigned,
+ * it will automatically be removed from that parent and inserted as a child
+ * of the container instead.
* <p/>
* This method is useful for developers needing to implement the
* {@link org.apache.click.control.Container} interface but cannot for one
@@ -503,8 +507,7 @@ public class ContainerUtils {
* }
*
* ...
- * }
- * </pre>
+ * } </pre>
*
* @param container the container to insert the given control into
* @param control the control to add to the container
@@ -513,8 +516,7 @@ public class ContainerUtils {
* @return the control that was added to the container
*
* @throws IllegalArgumentException if the control is null or if the control
- * and container is the same instance or the container already contains
- * a control with the same name or if a Field name is not defined
+ * and container is the same instance
*
* @throws IndexOutOfBoundsException if index is out of range
* <tt>(index < 0 || index > container.getControls().size())</tt>
@@ -573,6 +575,113 @@ public class ContainerUtils {
}
/**
+ * Replace the current control in the container at the specified index, and
+ * return the newly added control.
+ * <p/>
+ * <b>Please note</b> if the new control already has a parent assigned,
+ * it will automatically be removed from that parent and inserted as a child
+ * of the container instead.
+ * <p/>
+ * This method is useful for developers needing to implement the
+ * {@link org.apache.click.control.Container} interface but cannot for one
+ * reason or another extend from {@link org.apache.click.control.AbstractContainer}.
+ * For example if the Container already extends from an existing <tt>Control</tt>
+ * such as a <tt>Field</tt>, it won't be possible to extend
+ * <tt>AbstractContainer</tt> as well. In such scenarios instead of
+ * reimplementing {@link org.apache.click.control.Container#replace(org.apache.click.Control, org.apache.click.Control) replace},
+ * one can delegate to this method.
+ * <p/>
+ * For example, a custom Container that extends <tt>Field</tt> and
+ * implements <tt>Container</tt> could implement the <tt>replace</tt> method
+ * as follows:
+ *
+ * <pre class="prettyprint">
+ * public class MyContainer extends Field implements Container {
+ *
+ * public Control replace(Control currentControl, Control newControl) {
+ * int controlIndex = getControls().indexOf(currentControl);
+ * return ContainerUtils.replace(this, currentControl, newControl,
+ * controlIndex, getControlMap());
+ * }
+ *
+ * ...
+ * } </pre>
+ *
+ * @param container the container to insert the new control into
+ * @param currentControl the control currently contained in the container
+ * @param newControl the control to replace the current control contained in
+ * the container
+ * @param controlIndex the index of the current control in the container
+ * @param controlMap the container's map of controls keyed on control name
+ * @return the new control that replaced the current control
+ *
+ * @throws IllegalArgumentException if the currentControl or newControl is
+ * null
+ * @throws IllegalStateException if the controlIndex = -1
+ */
+ public static Control replace(Container container, Control currentControl,
+ Control newControl, int controlIndex, Map<String, Control> controlMap) {
+
+ // Pre conditions start
+
+ // Current and new control is the same instance - exit early
+ if (currentControl == newControl) {
+ return newControl;
+ }
+
+ if (currentControl == null) {
+ throw new IllegalArgumentException("Null current control parameter");
+ }
+ if (newControl == null) {
+ throw new IllegalArgumentException("Null new control parameter");
+ }
+
+ if (controlIndex == -1) {
+ throw new IllegalStateException("Cannot replace the given control"
+ + " because it is not present in the container");
+ }
+
+ // Pre conditions end
+
+ // Check if control already has parent
+ // If parent references the given container, there is no need to remove it
+ Object currentParent = newControl.getParent();
+ if (currentParent != null && currentParent != container) {
+
+ // Remove new control from parent Page or Container
+ if (currentParent instanceof Page) {
+ ((Page) currentParent).removeControl(newControl);
+
+ } else if (currentParent instanceof Container) {
+ ((Container) currentParent).remove(newControl);
+ }
+
+ // Create warning message to users that the parent has been reset
+ logParentReset(container, newControl, currentParent);
+ }
+
+ // Note: set parent first since setParent might veto further processing
+ newControl.setParent(container);
+ currentControl.setParent(null);
+
+ // Replace currentControl with newControl
+ container.getControls().set(controlIndex, newControl);
+
+ // Update controlMap
+ String controlName = newControl.getName();
+ if (controlName != null) {
+ controlMap.put(controlName, newControl);
+ } else {
+ controlName = currentControl.getName();
+
+ if (controlName != null) {
+ controlMap.remove(controlName);
+ }
+ }
+ return newControl;
+ }
+
+ /**
* Remove the given control from the container, returning <tt>true</tt> if
* the control was found in the container and removed, or <tt>false</tt> if
* the control was not found.
@@ -597,8 +706,7 @@ public class ContainerUtils {
* }
*
* ...
- * }
- * </pre>
+ * } </pre>
*
* @param container the container to remove the given control from
* @param control the control to remove from the container