001: /*
002: * $Id: RepeatingView.java 461935 2006-08-24 15:42:45Z ivaynberg $ $Revision:
003: * 3878 $ $Date: 2006-08-24 17:42:45 +0200 (Thu, 24 Aug 2006) $
004: *
005: * ==================================================================== Licensed
006: * under the Apache License, Version 2.0 (the "License"); you may not use this
007: * file except in compliance with the License. You may obtain a copy of the
008: * License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.extensions.markup.html.repeater;
019:
020: import java.util.Iterator;
021:
022: import wicket.Component;
023: import wicket.markup.MarkupStream;
024: import wicket.markup.html.WebMarkupContainer;
025: import wicket.model.IModel;
026:
027: /**
028: * <p>
029: * A repeater view that renders all of its children, using its body markup, in
030: * the order they were added.
031: *
032: * </p>
033: * Example:
034: * <p>
035: * <u>Java:</u>
036: *
037: * <pre>
038: * RepeatingView view = new RepeatingView("repeater");
039: * view.add(new Label("1", "hello"));
040: * view.add(new Label("2", "goodbye"));
041: * view.add(new Label("3", "good morning"));
042: * </pre>
043: *
044: * </p>
045: * <p>
046: * <u>Markup:</u>
047: *
048: * <pre>
049: * <ul><li wicket:id="repeater"></li></ul>
050: * </pre>
051: *
052: * </p>
053: * <p>
054: * <u>Yields:</u>
055: *
056: * <pre>
057: * <ul><li>goodbye</li><li>hello</li><li>good morning</li></ul>
058: * </pre>
059: *
060: * To expand a bit: the repeater itself produces no markup, instead every direct
061: * child inherits the entire markup of the repeater. In the example above
062: * reeaters's markup is:
063: *
064: * <pre>
065: * <li wicket:id="repeater"></li>
066: * </pre>
067: *
068: * and so this is the markup that is available to the direct children - the
069: * Label components. So as each label renders it produces a line of the output
070: * that has the <code>li</code>tag.
071: *
072: *
073: * @author Igor Vaynberg ( ivaynberg )
074: *
075: */
076: public class RepeatingView extends WebMarkupContainer {
077: /**
078: *
079: */
080: private static final long serialVersionUID = 1L;
081:
082: /** Counter used for generating unique child component ids. */
083: private long childIdCounter = 0;
084:
085: /** @see Component#Component(String) */
086: public RepeatingView(String id) {
087: super (id);
088: }
089:
090: /** @see Component#Component(String, IModel) */
091: public RepeatingView(String id, IModel model) {
092: super (id, model);
093: }
094:
095: /**
096: * Generates a unique id string. This makes it easy to add items to be
097: * rendered w/out having to worry about generating unique id strings in your
098: * code.
099: *
100: * @return unique child id
101: */
102: public String newChildId() {
103: childIdCounter++;
104:
105: if (childIdCounter == Long.MAX_VALUE) {
106: // mmm yeah...like this will ever happen
107: throw new RuntimeException(
108: "generateChildId() out of space.");
109: }
110:
111: return String.valueOf(childIdCounter);
112: }
113:
114: /**
115: * Renders all child items in no specified order
116: *
117: * @param markupStream
118: * The markup stream
119: */
120: protected void onRender(final MarkupStream markupStream) {
121: final int markupStart = markupStream.getCurrentIndex();
122:
123: Iterator it = renderIterator();
124: if (it.hasNext()) {
125: do {
126: markupStream.setCurrentIndex(markupStart);
127: renderChild((Component) it.next());
128: } while (it.hasNext());
129: } else {
130: markupStream.skipComponent();
131: }
132: }
133:
134: /**
135: * Returns an iterator for the collection of child components to be
136: * rendered.
137: *
138: * Child component are rendered in the order they are in the iterator. Since
139: * we use the iterator returned by wicket's
140: * <code>MarkupContainer#iterator()</code> method and that method does not
141: * guarantee any kind of ordering neither do we. This method can be
142: * overridden by subclasses to create an ordering scheme, see
143: * <code>OrderedRepeatingView#renderIterator()</code>.
144: *
145: * @return iterator over child components to be rendered
146: */
147: protected Iterator renderIterator() {
148: return iterator();
149: }
150:
151: /**
152: * Render a single child. This method can be overridden to modify how a
153: * single child component is rendered.
154: *
155: * @param child
156: * Child component to be rendered
157: */
158: protected void renderChild(final Component child) {
159: child.render(getMarkupStream());
160: }
161:
162: }
|