001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ade.galleries.client.ui;
029
030import org.opencms.ade.galleries.client.CmsCategoriesTabHandler;
031import org.opencms.ade.galleries.client.Messages;
032import org.opencms.ade.galleries.shared.CmsGallerySearchBean;
033import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId;
034import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.SortParams;
035import org.opencms.gwt.client.ui.CmsList;
036import org.opencms.gwt.client.ui.I_CmsListItem;
037import org.opencms.gwt.client.ui.input.CmsCheckBox;
038import org.opencms.gwt.client.ui.input.category.CmsDataValue;
039import org.opencms.gwt.client.ui.tree.CmsTree;
040import org.opencms.gwt.client.ui.tree.CmsTreeItem;
041import org.opencms.gwt.shared.CmsCategoryBean;
042import org.opencms.gwt.shared.CmsCategoryTreeEntry;
043import org.opencms.util.CmsStringUtil;
044
045import java.util.ArrayList;
046import java.util.HashMap;
047import java.util.LinkedHashMap;
048import java.util.List;
049import java.util.Map;
050
051import com.google.gwt.event.logical.shared.OpenEvent;
052import com.google.gwt.event.logical.shared.OpenHandler;
053import com.google.gwt.user.client.ui.Label;
054
055/**
056 * Provides the widget for the categories tab.<p>
057 *
058 * It displays the available categories in the given sort order.
059 *
060 * @since 8.0.
061 */
062public class CmsCategoriesTab extends A_CmsListTab {
063
064    /**
065     * Handles the change of the item selection.<p>
066     */
067    private class SelectionHandler extends A_SelectionHandler {
068
069        /** The category path as id for the selected category. */
070        private String m_categoryPath;
071
072        /**
073         * Constructor.<p>
074         *
075         * @param categoryPath as id for the selected category
076         * @param checkBox the reference to the checkbox
077         */
078        public SelectionHandler(String categoryPath, CmsCheckBox checkBox) {
079
080            super(checkBox);
081            m_categoryPath = categoryPath;
082        }
083
084        /**
085         * @see org.opencms.ade.galleries.client.ui.A_CmsListTab.A_SelectionHandler#onSelectionChange()
086         */
087        @Override
088        protected void onSelectionChange() {
089
090            if (getCheckBox().isChecked()) {
091                getTabHandler().onSelectCategory(m_categoryPath);
092            } else {
093                getTabHandler().onDeselectCategory(m_categoryPath);
094            }
095
096        }
097    }
098
099    /** Map of the categories by path. */
100    private Map<String, CmsCategoryBean> m_categories;
101
102    /** The flag to indicate when the categories are opened for the fist time. */
103    private boolean m_isInitOpen;
104
105    /** The tab handler. */
106    private CmsCategoriesTabHandler m_tabHandler;
107
108    /**
109     * Constructor.<p>
110     *
111     * @param tabHandler the tab handler
112     */
113    public CmsCategoriesTab(CmsCategoriesTabHandler tabHandler) {
114
115        super(GalleryTabId.cms_tab_categories);
116        m_tabHandler = tabHandler;
117        m_isInitOpen = false;
118        init();
119    }
120
121    /**
122     * Fill the content of the categories tab panel.<p>
123     *
124     * @param categoryRoot the category tree root entry
125     * @param selected the selected categories
126     */
127    public void fillContent(List<CmsCategoryTreeEntry> categoryRoot, List<String> selected) {
128
129        setInitOpen(true);
130
131        updateContentTree(categoryRoot, selected);
132    }
133
134    /**
135     * @see org.opencms.ade.galleries.client.ui.A_CmsTab#getParamPanels(org.opencms.ade.galleries.shared.CmsGallerySearchBean)
136     */
137    @Override
138    public List<CmsSearchParamPanel> getParamPanels(CmsGallerySearchBean searchObj) {
139
140        List<CmsSearchParamPanel> result = new ArrayList<CmsSearchParamPanel>();
141        for (String categoryPath : searchObj.getCategories()) {
142            CmsCategoryBean categoryItem = m_categories.get(categoryPath);
143            String title = "";
144            if (categoryItem != null) {
145                title = categoryItem.getTitle();
146            }
147            if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
148                title = categoryPath;
149            }
150            CmsSearchParamPanel panel = new CmsSearchParamPanel(
151                Messages.get().key(Messages.GUI_PARAMS_LABEL_CATEGORIES_0),
152                this);
153            panel.setContent(title, categoryPath);
154            result.add(panel);
155        }
156        return result;
157    }
158
159    /**
160     * Returns the isInitOpen.<p>
161     *
162     * @return the isInitOpen
163     */
164    public boolean isInitOpen() {
165
166        return m_isInitOpen;
167    }
168
169    /**
170     * Opens the first level in the categories tree.<p>
171     */
172    public void openFirstLevel() {
173
174        if (!m_categories.isEmpty()) {
175            for (int i = 0; i < m_scrollList.getWidgetCount(); i++) {
176                CmsTreeItem item = (CmsTreeItem)m_scrollList.getItem(i);
177                item.setOpen(true);
178            }
179        }
180    }
181
182    /**
183     * Sets the isInitOpen.<p>
184     *
185     * @param isInitOpen the isInitOpen to set
186     */
187    public void setInitOpen(boolean isInitOpen) {
188
189        m_isInitOpen = isInitOpen;
190    }
191
192    /**
193     * Deselect the categories  in the category list.<p>
194     *
195     * @param categories the categories to deselect
196     */
197    public void uncheckCategories(List<String> categories) {
198
199        for (String category : categories) {
200            CmsTreeItem item = searchTreeItem(m_scrollList, category);
201            item.getCheckBox().setChecked(false);
202        }
203    }
204
205    /**
206     * Updates the content of the categories list.<p>
207     *
208     * @param categoriesBeans the updates list of categories tree item beans
209     * @param selectedCategories the categories to select in the list by update
210     */
211    public void updateContentList(List<CmsCategoryBean> categoriesBeans, List<String> selectedCategories) {
212
213        clearList();
214        if (m_categories == null) {
215            m_categories = new HashMap<String, CmsCategoryBean>();
216        }
217        if ((categoriesBeans != null) && !categoriesBeans.isEmpty()) {
218            for (CmsCategoryBean categoryBean : categoriesBeans) {
219                m_categories.put(categoryBean.getPath(), categoryBean);
220                // set the list item widget
221                CmsDataValue dataValue = new CmsDataValue(
222                    600,
223                    3,
224                    CmsCategoryBean.SMALL_ICON_CLASSES,
225                    categoryBean.getTitle(),
226                    CmsStringUtil.isNotEmptyOrWhitespaceOnly(categoryBean.getDescription())
227                    ? categoryBean.getDescription()
228                    : categoryBean.getPath());
229                // the checkbox
230                CmsCheckBox checkBox = new CmsCheckBox();
231                if ((selectedCategories != null) && selectedCategories.contains(categoryBean.getPath())) {
232                    checkBox.setChecked(true);
233                }
234                SelectionHandler selectionHandler = new SelectionHandler(categoryBean.getPath(), checkBox);
235                checkBox.addClickHandler(selectionHandler);
236                dataValue.addClickHandler(selectionHandler);
237                dataValue.setUnselectable();
238                // set the category list item and add to list
239                CmsTreeItem listItem = new CmsTreeItem(false, checkBox, dataValue);
240                listItem.setSmallView(true);
241                listItem.setId(categoryBean.getPath());
242                addWidgetToList(listItem);
243            }
244        } else {
245            showIsEmptyLabel();
246        }
247    }
248
249    /**
250     * Updates the content of th categories tree.<p>
251     *
252     * @param treeEntries the root category entry
253     * @param selectedCategories the categories to select after update
254     */
255    @SuppressWarnings("unchecked")
256    public void updateContentTree(List<CmsCategoryTreeEntry> treeEntries, List<String> selectedCategories) {
257
258        clearList();
259        if (m_categories == null) {
260            m_categories = new HashMap<String, CmsCategoryBean>();
261        }
262        if ((treeEntries != null) && !treeEntries.isEmpty()) {
263            // add the first level and children
264            for (CmsCategoryTreeEntry category : treeEntries) {
265                // set the category tree item and add to list
266                CmsTreeItem treeItem = buildTreeItem(category, selectedCategories);
267                treeItem.setTree((CmsTree<CmsTreeItem>)m_scrollList);
268                addChildren(treeItem, category.getChildren(), selectedCategories);
269                addWidgetToList(treeItem);
270                treeItem.setOpen(true, false);
271            }
272        } else {
273            showIsEmptyLabel();
274        }
275    }
276
277    /**
278     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#createScrollList()
279     */
280    @Override
281    protected CmsList<? extends I_CmsListItem> createScrollList() {
282
283        CmsTree<CmsTreeItem> tree = new CmsTree<CmsTreeItem>();
284        tree.addOpenHandler(new OpenHandler<CmsTreeItem>() {
285
286            public void onOpen(OpenEvent<CmsTreeItem> event) {
287
288                onContentChange();
289            }
290        });
291        return tree;
292    }
293
294    /**
295     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#getSortList()
296     */
297    @Override
298    protected LinkedHashMap<String, String> getSortList() {
299
300        LinkedHashMap<String, String> list = new LinkedHashMap<String, String>();
301        list.put(SortParams.tree.name(), Messages.get().key(Messages.GUI_SORT_LABEL_HIERARCHIC_0));
302        list.put(SortParams.title_asc.name(), Messages.get().key(Messages.GUI_SORT_LABEL_TITLE_ASC_0));
303        list.put(SortParams.title_desc.name(), Messages.get().key(Messages.GUI_SORT_LABEL_TITLE_DECS_0));
304
305        return list;
306    }
307
308    /**
309     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#getTabHandler()
310     */
311    @Override
312    protected CmsCategoriesTabHandler getTabHandler() {
313
314        return m_tabHandler;
315    }
316
317    /**
318     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#hasQuickFilter()
319     */
320    @Override
321    protected boolean hasQuickFilter() {
322
323        // allow filter if not in tree mode
324        return SortParams.tree != SortParams.valueOf(m_sortSelectBox.getFormValueAsString());
325    }
326
327    /**
328     * Adds children item to the category tree and select the categories.<p>
329     *
330     * @param parent the parent item
331     * @param children the list of children
332     * @param selectedCategories the list of categories to select
333     */
334    private void addChildren(CmsTreeItem parent, List<CmsCategoryTreeEntry> children, List<String> selectedCategories) {
335
336        if (children != null) {
337            for (CmsCategoryTreeEntry child : children) {
338                // set the category tree item and add to parent tree item
339                CmsTreeItem treeItem = buildTreeItem(child, selectedCategories);
340                if ((selectedCategories != null) && selectedCategories.contains(child.getPath())) {
341                    parent.setOpen(true);
342                    openParents(parent);
343                }
344                parent.addChild(treeItem);
345                addChildren(treeItem, child.getChildren(), selectedCategories);
346            }
347        }
348    }
349
350    /**
351     * Builds a tree item for the given category.<p>
352     *
353     * @param category the category
354     * @param selectedCategories the selected categories
355     *
356     * @return the tree item widget
357     */
358    private CmsTreeItem buildTreeItem(CmsCategoryTreeEntry category, List<String> selectedCategories) {
359
360        m_categories.put(category.getPath(), category);
361        // set the list item widget
362        CmsDataValue dataValue = new CmsDataValue(
363            600,
364            3,
365            CmsCategoryBean.SMALL_ICON_CLASSES,
366            category.getTitle(),
367            CmsStringUtil.isNotEmptyOrWhitespaceOnly(category.getDescription())
368            ? category.getDescription()
369            : category.getPath());
370
371        // the checkbox
372        CmsCheckBox checkBox = new CmsCheckBox();
373        if ((selectedCategories != null) && selectedCategories.contains(category.getPath())) {
374            checkBox.setChecked(true);
375        }
376        SelectionHandler selectionHandler = new SelectionHandler(category.getPath(), checkBox);
377        checkBox.addClickHandler(selectionHandler);
378        dataValue.addClickHandler(selectionHandler);
379        dataValue.addButton(createSelectButton(selectionHandler));
380        dataValue.setUnselectable();
381        // set the category tree item and add to list
382        CmsTreeItem treeItem = new CmsTreeItem(true, checkBox, dataValue);
383        treeItem.setSmallView(true);
384        treeItem.setId(category.getPath());
385        return treeItem;
386    }
387
388    /**
389     * Goes up the tree and opens the parents of the item.<p>
390     *
391     * @param item the child item to start from
392     */
393    private void openParents(CmsTreeItem item) {
394
395        if (item != null) {
396            item.setOpen(true);
397            openParents(item.getParentItem());
398        }
399    }
400
401    /**
402     * Shows the tab list is empty label.<p>
403     */
404    private void showIsEmptyLabel() {
405
406        Label isEmptyLabel = new Label(Messages.get().key(Messages.GUI_TAB_CATEGORIES_IS_EMPTY_0));
407        CmsTreeItem treeItem = new CmsTreeItem(false, isEmptyLabel);
408        treeItem.setSmallView(true);
409        m_scrollList.add(treeItem);
410    }
411}