I've almost got my prototype ready for testing but I'm having a initialization problem. My markup reads:

          <div wicket:id="imageRow" class="floatfix">
            <div wicket:id="imageCell" class="imageColumn">
                foo
            </div>
          </div>

and wicket is complaining about not finding "imageCell" even though I bind it on the Java end using:

add(imageRow);
imageRow.add(imageCell);

I suspect DataView uses some sort of special magic implementation for add(). Can you please take a look (see attached file) and see if you can find something wrong?

I'm initializing one DataView for the imageRow, passing in a IDataProvider. Then I initialize another DataView for imageCell, pass in imageRow into the constructor.

Thanks,
Gili

Igor Vaynberg wrote:
I don't understand what you are talking about below...share state? In order
for your markup to be nested like that you are going to have to add "column"
to "row" which will make "row" repeat "column" dataprovider.count() times.
Not sure that's what you want.....

Why don't you try it and tell us if it works.

-Igor

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Gili
Sent: Tuesday, August 16, 2005 10:36 PM
To: wicket-user@lists.sourceforge.net
Subject: Re: [Wicket-user] Re: ColumnedDataProvider startIndex problems


<sigh> I said I disliked the idea of outputting HTML from Java code because this is very much like plain servlets or JSP, both of which are notoriously ugly doing this. Well anyway, if this component is fully theoretical, I guess I can't very well "try it".

        How about this idea?

<div wicket:id="row">
        <div wicket:id="column">
                cell data
        </div>
</div>

It would sort of work like ColumnedDataProvider did but cleaner. In the above example you'd have two instances of the same class (similar to ListView, I'm going to call it MyListView) that would share the same state information. So, allow me to walk you through the rendering process chronologically:

1) Construct MyListView for row, pass in IDataProvider into constructor 2) Construct MyListView for column, pass in row MyListView into constructor 3) Now, when populateItem() is invoked for either the row or column, the item's getIndex() will be shared among the two... what this means is that the index will be relative to the original IDataProvider, not relative to the MyListView passed into the constructor. populateItem() will be passed a DataItem for both row and column.

See what I mean? It's very flexible in that you can nested multiple layers but at the same time the overall state is shared so you know what your actual index is.

        What do you think?

Gili

Igor Vaynberg wrote:

You don't, that was the concept I proposed earlier and the one you said was bad :)



http://www.mail-archive.com/wicket-user@lists.sourceforge.net/msg04192

.html

-Igor




-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Gili
Sent: Tuesday, August 16, 2005 10:10 PM
To: wicket-user@lists.sourceforge.net
Subject: Re: [Wicket-user] Re: ColumnedDataProvider startIndex problems


        Where do I find the renderer Java class?

Gili

Igor Vaynberg wrote:


This would be really easy with the renderer :)

try something like this, maybe it will work

<div wicket:id="maindataview">
        <div wicket:id="rowview">
                [cell markup]
        </div>
        <div class="floatfix"/>
</div>

-Igor




-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Gili
Sent: Tuesday, August 16, 2005 10:02 PM
To: wicket-user@lists.sourceforge.net
Subject: Re: [Wicket-user] Re: ColumnedDataProvider startIndex problems


        Ok, turns out that using DataView is no good :(

        The markup contains:

        <div wicket:id="imageRow" class="floatfix">
          <div class="imageColumn">
            cell data
          </div>
        </div>

and I only want to issue a "imageRow" once every X columns. The problem, I just realized, is that the imageRow tag wraps a single imageColumn tag and I'd really like for it to wrap multiple imageColumn tags. Any ideas, short of outputting multiple

columns in a


single call to populateItem()? Now I am beginning to see

why it is a


bad idea to only have a concept of cells :(

        I can see how to get this working under DataView but it

will result


in a very unelegant solution :(

Gili

Gili wrote:



 Right, I think I prefer this method now. I think what

is really


missing in the end is the documentation aspect, not

Javadoc but a
full-fledged Wiki example for how to use it to produce rows

and columns.



Time-allowing, I'll try posting something to that effect in

the near



future.


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software

Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices Agile & Plan-Driven Development * Managing

Projects & Teams


* Testing & QA Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf _______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user








-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices Agile & Plan-Driven Development * Managing

Projects & Teams


* Testing & QA Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf _______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user


--
http://www.desktopbeautifier.com/


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices Agile & Plan-Driven Development * Managing

Projects & Teams
* Testing & QA Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf _______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user








-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices Agile & Plan-Driven Development * Managing

Projects & Teams
* Testing & QA Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf _______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user


--
http://www.desktopbeautifier.com/


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user








-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user


--
http://www.desktopbeautifier.com/
/*
 * $Id: DataView.java,v 1.13 2005/08/16 01:19:57 ivaynberg Exp $ $Revision: 1.13 $
 * $Date: 2005/08/16 01:19:57 $
 *
 * ==============================================================================
 * 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.contrib.dataview;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import wicket.WicketRuntimeException;
import wicket.model.IModel;
import wicket.model.Model;
import wicket.version.undo.Change;

/**
 * A DataView holds DataItem children.
 *
 * @see wicket.markup.html.list.ListView
 *
 * @author Igor Vaynberg
 *
 *
 */
public abstract class DataView extends OrderedRepeatingView
{
  /** Index of the first item to show */
  private int firstIndex = 0;
  protected int currentIndex;
  
  /** Max number (not index) of items to show */
  private int viewSize = Integer.MAX_VALUE;
  
  private boolean useOptimizedItemRemoval = false;
  private DataView parent;
  private DataView child;
  
  /**
   * A cache of DataProvider.size() with a lifecycle of the request. This is
   * necessary because DataProvider.size() might be an expensive operation
   * such as a select count query.
   *
   */
  private int cachedItemCount = -1;
  
  /**
   * @see wicket.Component#Component(String)
   */
  public DataView(final String id)
  {
    super(id);
  }
  
  /**
   * @see wicket.Component#Component(String, IModel)
   */
  public DataView(final String id, final IModel model)
  {
    super(id, model);
    
    if (model == null)
    {
      throw new IllegalArgumentException(
        "Null models are not allowed. If you have no model, you may prefer a Loop instead");
    }
  }
  
  /**
   * @param id
   *            See Component
   * @param dataProvider
   *            DataProvider for the dataview items
   */
  public DataView(final String id, final IDataProvider dataProvider)
  {
    this(id, new Model(dataProvider));
  }
  
  /**
   * @param id
   *            See Component
   * @param dataView
   *            DataView to wrap
   */
  public DataView(final String id, final DataView dataView)
  {
    this(id, new Model(dataView.getDataProvider()));
    this.parent = dataView;
    this.parent.child = this;
  }
  
  /**
   * convinience function for getting DataProvider out of the model
   *
   * @return DataProvider for the dataview
   */
  protected final IDataProvider getDataProvider()
  {
    if (parent!=null)
      return parent.getDataProvider();
    IDataProvider dataProvider = (IDataProvider)getModelObject();
    return (dataProvider != null) ? dataProvider : EmptyDataProvider.INSTANCE;
  }
  
  /**
   * Returns the total number of items available through the DataProvider
   *
   * @return number of items
   */
  public final int getItemCount()
  {
    if (parent!=null)
      return parent.getItemCount();
    if (cachedItemCount < 0)
    {
      cachedItemCount = getDataProvider().size();
    }
    return cachedItemCount;
  }
  
  /** Utitility function to reset the cachedItemCount cache */
  private void clearCachedItemCount()
  {
    if (parent!=null)
    {
      parent.clearCachedItemCount();
      return;
    }
    cachedItemCount = -1;
  }
  
  /**
   * Get index of first cell in page. Default is: 0.
   *
   * @return Index of first cell in page. Default is: 0
   */
  public final int getStartIndex()
  {
    if (parent!=null)
      return parent.getStartIndex();
    return this.firstIndex;
  }
  
  /**
   * Set the index of the first item to render
   *
   * @param startIndex
   *            First index of model object's list to display
   * @return This
   */
  public DataView setStartIndex(final int startIndex)
  {
    if (parent!=null)
      return parent.setStartIndex(startIndex);
    this.firstIndex = startIndex;
    
    if (firstIndex < 0)
    {
      firstIndex = 0;
    }
    else if (firstIndex >= getItemCount())
    {
      firstIndex = 0;
    }
    
    return this;
  }
  
  /**
   * Based on the model object's list size, firstIndex and view size,
   * determine what the view size really will be. E.g. default for viewSize is
   * Integer.MAX_VALUE, if not set via setViewSize(). If the underlying list
   * has 10 elements, the value returned by getViewSize() will be 10 if
   * startIndex = 0.
   *
   * @return The number of items to be populated and rendered.
   */
  public int getViewSize()
  {
    if (parent!=null)
      return parent.getViewSize();
    int size = this.viewSize;
    
    final int modelSize = getItemCount();
    if (firstIndex > modelSize)
    {
      return 0;
    }
    
    if ((size == Integer.MAX_VALUE) || ((firstIndex + size) > modelSize))
    {
      size = modelSize - firstIndex;
    }
    
    // firstIndex + size must be smaller than Integer.MAX_VALUE
    if ((Integer.MAX_VALUE - size) < firstIndex)
    {
      throw new IllegalStateException(
        "firstIndex + size must be smaller than Integer.MAX_VALUE");
    }
    
    return size;
  }
  
  /**
   * Define the maximum number of items to render. Default: render all.
   *
   * @param size
   *            Number of items to display
   * @return This
   */
  public DataView setViewSize(final int size)
  {
    if (parent!=null)
      return parent.setViewSize(size);
    this.viewSize = size;
    
    if (viewSize < 0)
    {
      viewSize = Integer.MAX_VALUE;
    }
    
    return this;
  }
  
  /**
   * @see wicket.MarkupContainer#internalOnBeginRequest()
   */
  protected void internalOnBeginRequest()
  {
    if (useOptimizedItemRemoval)
    {
      populateItemsOIR();
    }
    else
    {
      populateItems(0);
    }
  }
  
  /**
   * @return The resulting index
   */
  private int populateItems(int index)
  {
    final IDataProvider dataProvider = getDataProvider();
    final int size = getViewSize();
    removeAll();
    if (size > 0)
    {
      Iterator it = dataProvider.iterator(firstIndex, size);
      while (it.hasNext() && index < size)
      {
        final Object object = it.next();
        final String id = generateChildId();
        final IModel model = dataProvider.model(object);
        
        DataItem item = newItem(id, index, model);
        add(item);
        if (child==null)
        {
          populateItem(item);
          index++;
        }
        else
        {
          populateItem(item);
          index = child.populateItems(index);
        }
      }
    }
    return index;
  }
  
  private void populateItemsOIR()
  {
    final IDataProvider dataProvider = getDataProvider();
    final int size = getViewSize();
    
    if (size > 0)
    {
      Iterator it = null;
      
      final Map modelToItem = new HashMap(size());
      it = iterator();
      while (it.hasNext())
      {
        final DataItem item = (DataItem)it.next();
        modelToItem.put(item.getModel(), item);
      }
      
      removeAll();
      
      it = dataProvider.iterator(firstIndex, size);
      
      int index = 0;
      while (it.hasNext() && index < size)
      {
        final Object object = it.next();
        final IModel model = dataProvider.model(object);
        
        final DataItem oldItem = (DataItem)modelToItem.get(model);
        
        if (oldItem == null)
        {
          DataItem item = newItem(generateChildId(), index, model);
          add(item);
          populateItem(item);
        }
        else
        {
          oldItem.setIndex(index);
          add(oldItem);
        }
        index++;
      }
    }
    else
    {
      removeAll();
    }
    
  }
  
  
  /**
   * @see wicket.MarkupContainer#internalOnEndRequest()
   */
  protected void internalOnEndRequest()
  {
    super.internalOnEndRequest();
    clearCachedItemCount();
  }
  
  /**
   * Create a new DataItem for list item at index.
   *
   * @param id
   *            component id for the new data item
   * @param index
   *            the index of the new data item
   * @param model
   *            the model for the new data item
   *
   * @return DataItem created DataItem
   */
  protected DataItem newItem(final String id, int index, final IModel model)
  {
    return new DataItem(id, index, model);
  }
  
  /**
   * Populate a given item.
   * <p>
   * <b>be carefull</b> to add any components to the list item. So, don't do:
   *
   * <pre>
   * add(new Label(&quot;foo&quot;, &quot;bar&quot;));
   * </pre>
   *
   * but:
   *
   * <pre>
   * item.add(new Label(&quot;foo&quot;, &quot;bar&quot;));
   * </pre>
   *
   * </p>
   *
   * @param item
   *            The item to populate
   */
  protected abstract void populateItem(final DataItem item);
  
  
  /**
   * used internally for when there is no IDataProvider set as model.
   *
   * @author Christian Essl
   *
   */
  private static final class EmptyDataProvider implements IDataProvider
  {
    
    final static EmptyDataProvider INSTANCE = new EmptyDataProvider();
    
    /**
     * @see wicket.contrib.dataview.IDataProvider#iterator(int, int)
     */
    public Iterator iterator(int first, int count)
    {
      return new Iterator()
      {
        
        public boolean hasNext()
        {
          return false;
        }
        
        public Object next()
        {
          throw new IndexOutOfBoundsException();
        }
        
        public void remove()
        {
          throw new UnsupportedOperationException();
        }
        
      };
    }
    
    /**
     * @see wicket.contrib.dataview.IDataProvider#size()
     */
    public int size()
    {
      return 0;
    }
    
    /**
     * @see wicket.contrib.dataview.IDataProvider#model(java.lang.Object)
     */
    public IModel model(Object object)
    {
      throw new WicketRuntimeException("object is not supplied by this IDataProvider");
    }
  }
  
  /**
   * enables or disables the use of optimized item removal behavior
   *
   * @param oir
   *            true enables oir, false disables it
   * @return this
   */
  public DataView setUseOptimizedItemRemoval(final boolean oir)
  {
    if (useOptimizedItemRemoval != oir)
    {
      addStateChange(new Change()
      {
        private final boolean old = !oir;
        
        public void undo()
        {
          useOptimizedItemRemoval = old;
        }
      });
      useOptimizedItemRemoval = oir;
    }
    return this;
  }
  
  /**
   * @return true if optimized item removal is enabled, false otherwise
   */
  public boolean getUseOptimizedItemRemoval()
  {
    return useOptimizedItemRemoval;
  }
}

Reply via email to