I had a similar need.  I wanted a panel that would display several arbitrary sub-panels side-by-side:
 
abstract public class HorizontalPanelGrouper extends Panel{
   public HorizontalPanelGrouper( String id ) {
      super(id);
      add( "wicketIdForPanel1", createPanel1("wicketIdForPanel1") );  // "wicketIdForPanel1" matches HTML file
      add( "wicketIdForPanel2", createPanel1("wicketIdForPanel2") );  // "wicketIdForPanel2" matches HTML file
      add( "wicketIdForPanel3", createPanel1("wicketIdForPanel3") );  // "wicketIdForPanel3" matches HTML file
   }
   abstract Panel createPanel1(String id);
   abstract Panel createPanel2(String id);
   abstract Panel createPanel3(String id);
}
 
 
Whenever I needed my panel-of-panels I would instantiate an anonymous subclass that overrode the createPanelX methods:
 
Panel p = new HorizontalPanelGrouper(wicketIdForContainerPanel) {
    Panel createPanel1(String id) {
         return new SomePanelClass( id, ...);
    }
    Panel createPanel2(String id) {
         return new AnotherPanelClass( id, ...);
    }
    Panel createPanel3(String id) {
         return new YetAnotherPanelClass( id, ...);
    }
}
 
This way, I didn't have to remember the actual wicket:id used by the HorizontalPanelGrouper's HTML file when creating sub-panels for the HorizontalPanelGroup object.
 
If I wanted to modify the layout, all I had to do was create a trivial subclass (i.e. one which extended the base class without changing or adding anything at the java leve), but associated with a new HTML file.
 
If you wanted a variable number of sub-panels, instead of abstract methods you could have implement some of the sub-panels to be trivially empty panels.  Alternately, you could have HorizontalPanelGrouper implement those methods with empty invisible panels as defaults.  Then you need override only some of the panel-creating functions.
 
The same approach could be used if you wanted a panel containing a ListView of sub-panels: 
 
public class PanelList_Panel extends Panel {
  public PanelList_Panel(String id) {
    super(id);
    add( new ListView("panelList", createPanelList("panelListElement")  ) {  // literal strings are from HTML file
               protected void populateItem(ListItem listItem) {
                   listItem.add( (Panel) listItem.getModelObject() );
               }
             }
       );
  }
  abstract List<Panel> createPanelList( String id );
}
 
When using PanelList_Panel I would create an anonymous subclass that implemented the abstract method:
 
Panel p = new PanelList_Panel( wicketIdForAggregatorPanel ) {
   public List<Panel> createPanelList( String id ) {
        ...CREATE A BUNCH OF PANELS USING id AND ADD THEM TO A java.util.List AND RETURN IT
   }
}
 
When building components, my natural inclination is to make them configurable via constructor parameters and methods to be called post-construction.  With Wicket, however, I frequently had to design my components to accept configuration via the overriding of abstract or default methods by anonymous subclasses.  It felt weird, but eventually I got used to it.  I was a functional programmer in a past life, and it might have felt more natural if I could have passed functions (like C# delegates) as values to my constructors, but Java doesn't make that easy.
 
Alternatively, I suppose I could have built helper classes much like Swing's event-handler classes.  The helper classes could have contained the abstract methods, and I could have passed concrete subclasses to my component constructors.  But I didn't want to have to define seperate helper classes whose only purpose was to contain overrideable methods.

From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Charles A Deal
Sent: Thursday, August 17, 2006 2:44 PM
To: wicket-user@lists.sourceforge.net
Subject: [Wicket-user] Creating Panel to display a list of Panels


I am in the process of attempting to rebuild our non-framework, completely homegrown web application as a Wicket application.  So, I am very new to the Wicket way and find myself struggling with different things such as proper page construction techniques for relatively complex data-enabled pages.  So far, I have been successful in getting a Wicket app running that resembles our existing app, just a lot cleaner.  I am having trouble implementing a GUI comcept that we use quite frequently in our current app.

In our current app, we typically have long pages of data fields available to the user, in an attempt to avoid information overload, we implemented "toggle sections" that hide the contents of a section of the page until the section header  or "twistee" is clicked, at which point the contents become visible.  This is relatively simple in our app, there are two divs, one for the header (name of section, usually one line) and the other for the contents.  The content div is "display:none" when the page loads and when the header is clicked to open, that attribute is removed.  Pretty simple.

I know that I could do the same think in the Wicket app, but it didn't seem to take advantage of Wicket's features.  So, I am seeking to create the described functionality in a more Wicket-minded way.  I am open to suggestions of how YOU would do it, but you'll find my idea below.  Mind  you, that my way doesn't work...yet.

My idea:
Create a panel called ToggleSectionPanel.  If would handle the look-n-feel of the toggle header as well as hold the content that should be shown/hidden.

Given a strutuce like this

WebPage
        ContentPanel
                ToggleSectionPanel (section 1)
                        SomeFieldsPanel
                        SomeOtherFieldsPanel
                ToggleSectionPanel (section 2)
                        EvenMoreFieldsPanel

ContetPanel code initialization snippet
        ToggleSectionPanel tsp = new ToggleSectionPanel("togPanel");
        tsp.setSectionTitle("Section 1");
        tsp.addPanel(new SomeFieldsPanel("panel1"));
        tsp.addPanel(new SomeOtherFieldsPanel("panel1"));
        add(tsp);
               
        tsp = new ToggleSectionPanel("togPanel2");
        tsp.setSectionTitle("Section 2");
        tsp.addPanel(new EvenMoreFieldsPanel("panel1"));
        add(tsp);

ToggleSectionPanel.html
        <wicket:panel>
                <table border="0" width="100%" cellspacing="0">
                        <tr>
                                <td width="20px">
                                        <img wicket:id="toggleImage" width="17" height="15" border="0" />
                                </td>
                                <td class="toggleSectionHeader">
                                        <span wicket:id="sectionTitle">[section title]</span>
                                </td>
                        </tr>
                </table>
                <div wicket:id="panels">
                </div>
        </wicket:panel>

I thought that I might use a ListView to simply write out the panels, but the problem I encountered was that I was adding a Panel in code (new SomeFieldsPanel("panel1")) but I wasn't referencing the id ("panel1") in the html because the listView's ListItems were named by the index.  So, then I thought I could just make a MarkupContainer that would spit out the Panels' markup, but that didn't work either.

public class PanelList extends WebMarkupContainer {
        /**
         * @see wicket.Component#onRender(wicket.markup.MarkupStream)
         */
        @SuppressWarnings("unchecked")
        protected void onRender(final MarkupStream markupStream) {
                final List<Panel> list = (List) getModelObject();

                // Save position in markup stream
                final int markupStart = markupStream.getCurrentIndex();

                if (list != null) {
                        for (Panel p : list) {
                                markupStream.setCurrentIndex(markupStart);
                                p.renderComponent(markupStream);
                        }
                }
        }

I got an error "No Markup found" and it referenced the Panel that was part of the List of Panels.

I know that there is a lot here and I hope that it is coherent, but if anyone can offer me some guidance, it would be MUCH appreciated.


Chuck Deal


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This is a PRIVATE message. If you are not the intended recipient, please delete without copying and kindly advise us by e-mail of the mistake in delivery. NOTE: Regardless of content, this e-mail shall not operate to bind CSC to any order or other contract unless pursuant to explicit written agreement or government initiative expressly permitting the use of e-mail for such purpose.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user

Reply via email to