001: package wicket.examples.ajax.builtin;
002:
003: import java.io.Serializable;
004: import java.util.ArrayList;
005: import java.util.Iterator;
006: import java.util.List;
007:
008: import wicket.ajax.AjaxRequestTarget;
009: import wicket.ajax.markup.html.AjaxFallbackLink;
010: import wicket.ajax.markup.html.form.AjaxCheckBox;
011: import wicket.ajax.markup.html.form.AjaxSubmitButton;
012: import wicket.markup.html.WebMarkupContainer;
013: import wicket.markup.html.basic.Label;
014: import wicket.markup.html.form.Form;
015: import wicket.markup.html.form.TextField;
016: import wicket.markup.html.list.ListItem;
017: import wicket.markup.html.list.ListView;
018: import wicket.model.CompoundPropertyModel;
019: import wicket.model.PropertyModel;
020:
021: /**
022: * Ajax todo list without having to write any JavaScript yourself.
023: *
024: * @author Martijn Dashorst
025: */
026: public class TodoList extends BasePage {
027: /**
028: * The todo object.
029: */
030: public static class TodoItem implements Serializable {
031: /** Is the item done? */
032: private boolean checked;
033:
034: /** Description of the item. */
035: private String text;
036:
037: /** Constructor. */
038: public TodoItem() {
039: }
040:
041: /**
042: * Copy constructor.
043: *
044: * @param item
045: * the item to copy the values from.
046: */
047: public TodoItem(TodoItem item) {
048: this .text = item.text;
049: }
050:
051: /**
052: * @return Returns the checked property.
053: */
054: public boolean isChecked() {
055: return checked;
056: }
057:
058: /**
059: * Sets the checked property.
060: *
061: * @param checked
062: * The checked property to set.
063: */
064: public void setChecked(boolean checked) {
065: this .checked = checked;
066: }
067:
068: /**
069: * Gets the description of the item.
070: *
071: * @return Returns the text.
072: */
073: public String getText() {
074: return text;
075: }
076:
077: /**
078: * Sets the description of the item.
079: *
080: * @param text
081: * The text to set.
082: */
083: public void setText(String text) {
084: this .text = text;
085: }
086: }
087:
088: /**
089: * Container for displaying the todo items in a list.
090: */
091: public class TodoItemsContainer extends WebMarkupContainer {
092: /**
093: * Constructor.
094: *
095: * @param id
096: * the component identifier.
097: */
098: public TodoItemsContainer(String id) {
099: super (id);
100:
101: // let wicket generate a markup-id so the contents can be
102: // updated through an AJAX call.
103: setOutputMarkupId(true);
104:
105: // add the listview to the container
106: add(new ListView("item", items) {
107: protected void populateItem(ListItem item) {
108: // add an AJAX checkbox to the item
109: item.add(new AjaxCheckBox("check",
110: new PropertyModel(item.getModel(),
111: "checked")) {
112: protected void onUpdate(AjaxRequestTarget target) {
113: // no need to do anything, the model is updated by
114: // itself, and we don't have to re-render a
115: // component (the client already has the correct
116: // state).
117: }
118: });
119: // display the text of the todo item
120: item.add(new Label("text", new PropertyModel(item
121: .getModel(), "text")));
122: }
123: });
124: }
125: }
126:
127: /**
128: * Container for showing either the add link, or the addition form.
129: */
130: public class AddItemsContainer extends WebMarkupContainer {
131: /** Visibility toggle so that either the link or the form is visible. */
132: private boolean linkVisible = true;
133:
134: /** Link for displaying the AddTodo form. */
135: private final class AddTodoLink extends AjaxFallbackLink {
136: /** Constructor. */
137: private AddTodoLink(String id) {
138: super (id);
139: }
140:
141: /**
142: * onclick handler.
143: *
144: * @param target
145: * the request target.
146: */
147: public void onClick(AjaxRequestTarget target) {
148: onShowForm(target);
149: }
150:
151: /**
152: * Toggles the visibility with the add form.
153: *
154: * @return <code>true</code> when the add links is visible and the
155: * form isn't.
156: */
157: public boolean isVisible() {
158: return linkVisible;
159: }
160: }
161:
162: /**
163: * Link for removing all completed todos from the list, this link
164: * follows the same visibility rules as the add link.
165: */
166: private final class RemoveCompletedTodosLink extends
167: AjaxFallbackLink {
168: /**
169: * Constructor.
170: *
171: * @param id
172: * component id
173: */
174: public RemoveCompletedTodosLink(String id) {
175: super (id);
176: }
177:
178: /**
179: * @see AjaxFallbackLink#onClick(AjaxRequestTarget)
180: */
181: public void onClick(AjaxRequestTarget target) {
182: onRemoveCompletedTodos(target);
183: }
184:
185: /**
186: * Toggles the visibility with the add form.
187: *
188: * @return <code>true</code> when the add links is visible and the
189: * form isn't.
190: */
191: public boolean isVisible() {
192: return linkVisible;
193: }
194: }
195:
196: /**
197: * Displays a form which offers an edit field and two buttons: one for
198: * adding the todo item, and one for canceling the addition. The
199: * visibility of this component is mutual exclusive with the visibility
200: * of the add-link.
201: */
202: private final class AddTodoForm extends Form {
203: /**
204: * Constructor.
205: *
206: * @param id
207: * the component id.
208: */
209: public AddTodoForm(String id) {
210: super (id, new CompoundPropertyModel(new TodoItem()));
211: setOutputMarkupId(true);
212: add(new TextField("text"));
213: add(new AjaxSubmitButton("add", this ) {
214: protected void onSubmit(AjaxRequestTarget target,
215: Form form) {
216: // retrieve the todo item
217: TodoItem item = (TodoItem) getParent()
218: .getModelObject();
219:
220: // add the item
221: onAdd(item, target);
222: }
223: });
224:
225: add(new AjaxSubmitButton("cancel", this ) {
226: public void onSubmit(AjaxRequestTarget target,
227: Form form) {
228: onCancelTodo(target);
229: }
230: });
231: }
232:
233: /**
234: * Toggles the visibility with the add link. When the link is
235: * visible, the form isn't.
236: *
237: * @return true when the form is visible and the link isn't.
238: */
239: public boolean isVisible() {
240: return !linkVisible;
241: }
242: }
243:
244: /**
245: * Constructor.
246: *
247: * @param id
248: * the component id.
249: */
250: public AddItemsContainer(String id) {
251: super (id);
252: // let wicket generate a markup-id so the contents can be
253: // updated through an AJAX call.
254: setOutputMarkupId(true);
255: add(new AddTodoLink("link"));
256: add(new RemoveCompletedTodosLink("remove"));
257: add(new AddTodoForm("form"));
258: }
259:
260: /**
261: * Called then the add link was clicked, shows the form, and hides the
262: * link.
263: *
264: * @param target
265: * the request target.
266: */
267: void onShowForm(AjaxRequestTarget target) {
268: // toggle the visibility
269: linkVisible = false;
270:
271: // redraw the add container.
272: target.addComponent(this );
273: }
274:
275: void onRemoveCompletedTodos(AjaxRequestTarget target) {
276: List ready = new ArrayList();
277: for (Iterator iter = items.iterator(); iter.hasNext();) {
278: TodoItem todo = (TodoItem) iter.next();
279: if (todo.isChecked()) {
280: ready.add(todo);
281: }
282: }
283: items.removeAll(ready);
284:
285: // repaint our panel
286: target.addComponent(this );
287:
288: // repaint the listview as there was a new item added.
289: target.addComponent(showItems);
290: }
291:
292: /**
293: * Called when the form is submitted through the add button, stores the
294: * todo item, hides the form, displays the add link and updates the
295: * listview.
296: *
297: * @param target
298: * the request target
299: */
300: void onAdd(TodoItem item, AjaxRequestTarget target) {
301: // add the item
302: items.add(new TodoItem(item));
303:
304: // reset the model
305: item.setChecked(false);
306: item.setText("");
307:
308: // toggle the visibility
309: linkVisible = true;
310:
311: // repaint our panel
312: target.addComponent(this );
313:
314: // repaint the listview as there was a new item added.
315: target.addComponent(showItems);
316: }
317:
318: /**
319: * Called when adding a new todo item was canceled. Hides the add form
320: * and displays the add link.
321: *
322: * @param target
323: * the request target.
324: */
325: void onCancelTodo(AjaxRequestTarget target) {
326: // toggle the visibility
327: linkVisible = true;
328:
329: // repaint the panel.
330: target.addComponent(this );
331: }
332: }
333:
334: /**
335: * Container for redrawing the todo items list with an AJAX call.
336: */
337: private WebMarkupContainer showItems;
338:
339: /**
340: * The list of todo items.
341: */
342: static final List items = new ArrayList();
343:
344: /**
345: * Constructor.
346: */
347: public TodoList() {
348: // add the listview container for the todo items.
349: showItems = new TodoItemsContainer("showItems");
350: add(showItems);
351:
352: // add the add container for the todo items.
353: add(new AddItemsContainer("addItems"));
354: }
355: }
|