    001// Copyright 2007-2013 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007//     http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.corelib.components;
    016
    017import org.apache.tapestry5.Block;
    018import org.apache.tapestry5.ComponentResources;
    019import org.apache.tapestry5.MarkupWriter;
    020import org.apache.tapestry5.PropertyOverrides;
    021import org.apache.tapestry5.annotations.*;
    022import org.apache.tapestry5.beanmodel.PropertyModel;
    023import org.apache.tapestry5.commons.Messages;
    024import org.apache.tapestry5.grid.ColumnSort;
    025import org.apache.tapestry5.grid.GridModel;
    026import org.apache.tapestry5.grid.GridSortModel;
    027import org.apache.tapestry5.http.services.Request;
    028import org.apache.tapestry5.internal.InternalConstants;
    029import org.apache.tapestry5.ioc.annotations.Inject;
    030
    031import java.util.List;
    032
    033/**
    034 * Renders out the column headers for the grid, including links (where appropriate) to control column sorting.
    035 *
    036 * @tapestrydoc
    037 */
    038@SupportsInformalParameters
    039@Events(InternalConstants.GRID_INPLACE_UPDATE + " (internal event)")
    040public class GridColumns
    041{
    042    /**
    043     * The object that provides access to bean and data models, which is typically the enclosing Grid component.
    044     */
    045    @Parameter(value = "componentResources.container")
    046    private GridModel gridModel;
    047
    048    /**
    049     * If true, then the CSS class on each &lt;TH&gt; element will be omitted, which can reduce the amount of output
    050     * from the component overall by a considerable amount. Leave this as false, the default, when you are leveraging
    051     * the CSS to customize the look and feel of particular columns.
    052     */
    053    @Parameter
    054    private boolean lean;
    055
    056    /**
    057     * Where to look for informal parameter Blocks used to override column headers.  The default is to look for such
    058     * overrides in the GridColumns component itself, but this is usually overridden.
    059     */
    060    @Parameter("this")
    061    private PropertyOverrides overrides;
    062
    063    /**
    064     * If not null, then each link is output as a link to update the specified zone.
    065     */
    066    @Parameter
    067    private String zone;
    068
    069    @SuppressWarnings("unused")
    070    @Component(
    071            parameters = {"event=sort", "disabled=sortDisabled", "context=columnModel.id", "zone=inherit:zone"})
    072    private EventLink sort;
    073
    074    @Inject
    075    private Messages messages;
    076
    077    @Inject
    078    private Block standardHeader;
    079
    080    /**
    081     * Optional output parameter that stores the current column index.
    082     */
    083    @Parameter
    084    @Property
    085    private int index;
    086
    087    /**
    088     * Caches the index of the last column.
    089     */
    090    private int lastColumnIndex;
    091
    092    @Property(write = false)
    093    private PropertyModel columnModel;
    094
    095    @Inject
    096    private ComponentResources resources;
    097
    098    @Inject
    099    private Request request;
    100
    101    void setupRender()
    102    {
    103        lastColumnIndex = gridModel.getDataModel().getPropertyNames().size() - 1;
    104    }
    105
    106    public boolean isSortDisabled()
    107    {
    108        return !columnModel.isSortable();
    109    }
    110
    111    private ColumnSort getSortForColumn()
    112    {
    113        GridSortModel sortModel = gridModel.getSortModel();
    114
    115        String columnId = columnModel.getId();
    116
    117        return sortModel.getColumnSort(columnId);
    118    }
    119
    120    void onBeginRenderFromLoop(MarkupWriter writer) {
    121
    122        if (!lean) {
    123            writer.attributes("data-grid-property", columnModel.getId());
    124        }
    125        if(!isSortDisabled()){
    126            switch (getSortForColumn())
    127            {
    128                case ASCENDING:
    129                    writer.attributes("data-grid-column-sort", "ascending");
    130                    break;
    131
    132                case DESCENDING:
    133                    writer.attributes("data-grid-column-sort", "descending");
    134                default:
    135                    writer.attributes("data-grid-column-sort", "sortable");
    136            }
    137        }
    138
    139        if (index == 0) {
    140            writer.attributes("data-grid-column", "first");
    141        }
    142
    143        if (index == lastColumnIndex) {
    144            writer.attributes("data-grid-column", "last");
    145        }
    146    }
    147
    148    public boolean isActiveSortColumn()
    149    {
    150        return getSortForColumn() != ColumnSort.UNSORTED;
    151    }
    152
    153    /**
    154     * Normal, non-Ajax event handler.
    155     */
    156
    157    boolean onSort(String columnId)
    158    {
    159        gridModel.getSortModel().updateSort(columnId);
    160
    161        if (request.isXHR())
    162        {
    163            resources.triggerEvent(InternalConstants.GRID_INPLACE_UPDATE, null, null);
    164        }
    165
    166        return true;
    167    }
    168
    169
    170    public List<String> getColumnNames()
    171    {
    172        return gridModel.getDataModel().getPropertyNames();
    173    }
    174
    175
    176    public void setColumnName(String columnName)
    177    {
    178        columnModel = gridModel.getDataModel().get(columnName);
    179    }
    180
    181
    182    public Block getBlockForColumn()
    183    {
    184        Block override = overrides.getOverrideBlock(columnModel.getId() + "Header");
    185
    186        if (override != null) return override;
    187
    188        return standardHeader;
    189    }
    190
    191    /**
    192     * Returns null or "true", depending on whether the Grid is rendering for in-place updates or not ("true"
    193     * means in-place updates). The affects whether the data-inplace-grid-links attribute will be rendered or not.
    194     *
    195     */
    196    public String getInplaceGridLinks()
    197    {
    198        return zone == null ? null : "true";
    199    }
    200}