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.extensions.markup.html.repeater.data.sort;
018
019import org.apache.wicket.core.util.string.CssUtils;
020import org.apache.wicket.markup.ComponentTag;
021import org.apache.wicket.markup.html.border.Border;
022import org.apache.wicket.util.string.Strings;
023
024/**
025 * A component that wraps markup with an OrderByLink. This has the advantage of being able to add
026 * the attribute modifier to the wrapping element as opposed to the link, so that it can be attached
027 * to <th> or any other element.
028 * 
029 * For example:
030 * 
031 * <th wicket:id="order-by-border">Heading</th>
032 *
033 * @param <S>
034 *      the type of the sorting parameter
035 * @author Igor Vaynberg ( ivaynberg )
036 * 
037 */
038public class OrderByBorder<S> extends Border
039{
040        private static final long serialVersionUID = 1L;
041
042        public static final String SORT_ASCENDING_CSS_CLASS_KEY = CssUtils.key(OrderByLink.class, "ascending");
043
044        public static final String SORT_DESCENDING_CSS_CLASS_KEY = CssUtils.key(OrderByLink.class, "descending");
045
046        public static final String SORT_NONE_CSS_CLASS_KEY = CssUtils.key(OrderByLink.class, "none");
047
048        private final ISortStateLocator<S> stateLocator;
049
050        private final S property;
051
052        /**
053         * @param id
054         *            see
055         *            {@link OrderByLink#OrderByLink(java.lang.String, java.lang.Object, org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator) }
056         * @param property
057         *            see
058         *            {@link OrderByLink#OrderByLink(java.lang.String, java.lang.Object, org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator) }
059         * @param stateLocator
060         *            see
061         *            {@link OrderByLink#OrderByLink(java.lang.String, java.lang.Object, org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator) }
062         */
063        public OrderByBorder(final String id, final S property,
064                final ISortStateLocator<S> stateLocator)
065        {
066                super(id);
067
068                this.stateLocator = stateLocator;
069                this.property = property;
070
071                OrderByLink<S> link = newOrderByLink("orderByLink", property, stateLocator);
072                addToBorder(link);
073        }
074
075        /**
076         * create new sort order toggling link
077         * 
078         * @param id
079         *            component id
080         * @param property
081         *            sort property
082         * @param stateLocator
083         *            sort state locator
084         * @return link
085         */
086        protected OrderByLink<S> newOrderByLink(final String id, final S property,
087                final ISortStateLocator<S> stateLocator)
088        {
089                return new OrderByLink<S>(id, property, stateLocator)
090                {
091                        private static final long serialVersionUID = 1L;
092
093                        @Override
094                        protected void onSortChanged()
095                        {
096                                OrderByBorder.this.onSortChanged();
097                        }
098                };
099        }
100
101        /**
102         * This method is a hook for subclasses to perform an action after sort has changed
103         */
104        protected void onSortChanged()
105        {
106                // noop
107        }
108
109        @Override
110        public void onComponentTag(final ComponentTag tag)
111        {
112                super.onComponentTag(tag);
113
114                final ISortState<S> sortState = stateLocator.getSortState();
115
116                SortOrder dir = sortState.getPropertySortOrder(property);
117                String cssClass;
118                if (dir == SortOrder.ASCENDING)
119                {
120                        cssClass = getString(SORT_ASCENDING_CSS_CLASS_KEY);
121                }
122                else if (dir == SortOrder.DESCENDING)
123                {
124                        cssClass = getString(SORT_DESCENDING_CSS_CLASS_KEY);
125                }
126                else
127                {
128                        cssClass = getString(SORT_NONE_CSS_CLASS_KEY);
129                }
130
131                if (!Strings.isEmpty(cssClass))
132                {
133                        tag.append("class", cssClass, " ");
134                }
135
136        }
137
138}