001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.ajax.markup.html.navigation.paging;
018
019import org.apache.wicket.Component;
020import org.apache.wicket.MarkupContainer;
021import org.apache.wicket.Page;
022import org.apache.wicket.ajax.AjaxRequestTarget;
023import org.apache.wicket.markup.html.link.AbstractLink;
024import org.apache.wicket.markup.html.navigation.paging.IPageable;
025import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
026import org.apache.wicket.markup.html.navigation.paging.PagingNavigation;
027import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
028import org.apache.wicket.markup.repeater.AbstractRepeater;
029
030/**
031 * A Wicket panel component to draw and maintain a complete page navigator, meant to be easily added
032 * to any PageableListView. A navigation which contains links to the first and last page, the
033 * current page +- some increment and which supports paged navigation bars (@see
034 * PageableListViewNavigationWithMargin).
035 * <p>
036 * <strong>NOTE</strong> To use the <code>AjaxPagingNavigator</code>, you <i>have</i> to put your
037 * <code>ListView</code> in a <code>WebMarkupContainer</code>, otherwise it is not possible to
038 * update the contents of the listview using Ajax.
039 * 
040 * @since 1.2
041 * 
042 * @author Martijn Dashorst
043 */
044public class AjaxPagingNavigator extends PagingNavigator
045{
046        private static final long serialVersionUID = 1L;
047
048        /** The pageable component that needs to be updated. */
049        private final IPageable pageable;
050
051        /**
052         * Constructor.
053         * 
054         * @param id
055         *            See Component
056         * @param pageable
057         *            The pageable component the page links are referring to.
058         */
059        public AjaxPagingNavigator(final String id, final IPageable pageable)
060        {
061                this(id, pageable, null);
062        }
063
064        /**
065         * Constructor.
066         * 
067         * @param id
068         *            See Component
069         * @param pageable
070         *            The pageable component the page links are referring to.
071         * @param labelProvider
072         *            The label provider for the link text.
073         */
074        public AjaxPagingNavigator(final String id, final IPageable pageable,
075                final IPagingLabelProvider labelProvider)
076        {
077                super(id, pageable, labelProvider);
078                this.pageable = pageable;
079                setOutputMarkupId(true);
080        }
081
082        /**
083         * Create a new increment link. May be subclassed to make use of specialized links, e.g. Ajaxian
084         * links.
085         * 
086         * @param id
087         *            the link id
088         * @param pageable
089         *            the pageable to control
090         * @param increment
091         *            the increment
092         * @return the increment link
093         */
094        @Override
095        protected AbstractLink newPagingNavigationIncrementLink(String id, IPageable pageable, int increment)
096        {
097                return new AjaxPagingNavigationIncrementLink(id, pageable, increment);
098        }
099
100        /**
101         * Create a new pagenumber link. May be subclassed to make use of specialized links, e.g.
102         * Ajaxian links.
103         * 
104         * @param id
105         *            the link id
106         * @param pageable
107         *            the pageable to control
108         * @param pageNumber
109         *            the page to jump to
110         * @return the pagenumber link
111         */
112        @Override
113        protected AbstractLink newPagingNavigationLink(String id, IPageable pageable, int pageNumber)
114        {
115                return new AjaxPagingNavigationLink(id, pageable, pageNumber);
116        }
117
118        /**
119         * @see org.apache.wicket.markup.html.navigation.paging.PagingNavigator#newNavigation(java.lang.String,
120         *      org.apache.wicket.markup.html.navigation.paging.IPageable,
121         *      org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider)
122         */
123        @Override
124        protected PagingNavigation newNavigation(final String id, final IPageable pageable,
125                final IPagingLabelProvider labelProvider)
126        {
127                return new AjaxPagingNavigation(id, pageable, labelProvider);
128        }
129
130        /**
131         * Override this method to specify the markup container where your IPageable is part of. This
132         * default implementation tries to find a parent which is not an {@link AbstractRepeater} and outputs
133         * its markup id. This is necessary as ListViews can't be updated themselves.
134         * 
135         * @param target
136         *            the request target to add the components that need to be updated in the ajax
137         *            event.
138         * @see Component#getOutputMarkupId()
139         */
140        protected void onAjaxEvent(AjaxRequestTarget target)
141        {
142                // Update a parental container of the pageable, this assumes that the pageable is a component.
143                Component container = ((Component)pageable);
144                while (container instanceof AbstractRepeater || container.getOutputMarkupId() == false)
145                {
146                        Component parent = container.getParent();
147                        if (parent == null) {
148                                break;
149                        }
150                        container = parent;
151                }
152                target.add(container);
153
154                // in case the navigator is not contained by the container, we have
155                // to add it to the response
156                if (((MarkupContainer)container).contains(this, true) == false)
157                {
158                        target.add(this);
159                }
160        }
161}