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.CmsGalleriesTabHandler;
031import org.opencms.ade.galleries.client.Messages;
032import org.opencms.ade.galleries.client.ui.css.I_CmsLayoutBundle;
033import org.opencms.ade.galleries.shared.CmsGalleryFolderBean;
034import org.opencms.ade.galleries.shared.CmsGalleryGroup;
035import org.opencms.ade.galleries.shared.CmsGallerySearchBean;
036import org.opencms.ade.galleries.shared.CmsGalleryTreeEntry;
037import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId;
038import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.SortParams;
039import org.opencms.gwt.client.CmsCoreProvider;
040import org.opencms.gwt.client.rpc.CmsRpcAction;
041import org.opencms.gwt.client.ui.CmsListItem;
042import org.opencms.gwt.client.ui.CmsListItemWidget;
043import org.opencms.gwt.client.ui.CmsPushButton;
044import org.opencms.gwt.client.ui.CmsSimpleListItem;
045import org.opencms.gwt.client.ui.I_CmsButton;
046import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
047import org.opencms.gwt.client.ui.contextmenu.I_CmsActionHandler;
048import org.opencms.gwt.client.ui.externallink.CmsEditExternalLinkDialog;
049import org.opencms.gwt.client.ui.input.CmsCheckBox;
050import org.opencms.gwt.client.ui.tree.CmsTreeItem;
051import org.opencms.gwt.client.util.CmsEmbeddedDialogHandler;
052import org.opencms.gwt.client.util.CmsScrollToBottomHandler;
053import org.opencms.gwt.shared.CmsGwtConstants;
054import org.opencms.util.CmsStringUtil;
055import org.opencms.util.CmsUUID;
056
057import java.util.ArrayList;
058import java.util.Collections;
059import java.util.HashMap;
060import java.util.Iterator;
061import java.util.LinkedHashMap;
062import java.util.List;
063import java.util.Map;
064
065import com.google.common.collect.Lists;
066import com.google.gwt.core.client.Scheduler;
067import com.google.gwt.core.client.Scheduler.RepeatingCommand;
068import com.google.gwt.event.dom.client.ClickEvent;
069import com.google.gwt.event.dom.client.ClickHandler;
070import com.google.gwt.user.client.Timer;
071import com.google.gwt.user.client.ui.Label;
072
073/**
074 * Provides the widget for the galleries(folder) tab.<p>
075 *
076 * It displays the available gallery folders in the given order.
077 *
078 * @since 8.0.
079 */
080public class CmsGalleriesTab extends A_CmsListTab {
081
082    /**
083     * A class which generates list items incrementally to fill the galleries tab.<p>
084     */
085    protected class ListItemGenerator implements Iterator<CmsTreeItem> {
086
087        /** The internal iterator over the gallery beans. */
088        protected Iterator<CmsGalleryFolderBean> m_beanIterator;
089
090        /** True if output should be grouped. */
091        protected boolean m_useGroups;
092
093        /**
094         * Creates a new instance.<p>
095         * @param folders the list of folders for which to generate list items
096         * @param grouped true if the list items should be displayed in groups (this assumes the items have already been sorted correctly)
097         */
098        public ListItemGenerator(List<CmsGalleryFolderBean> folders, boolean grouped) {
099
100            if (folders == null) {
101                folders = new ArrayList<CmsGalleryFolderBean>();
102            }
103
104            m_beanIterator = folders.iterator();
105            m_useGroups = grouped;
106        }
107
108        /**
109         * @see java.util.Iterator#hasNext()
110         */
111        public boolean hasNext() {
112
113            return m_beanIterator.hasNext();
114        }
115
116        /**
117         * @see java.util.Iterator#next()
118         */
119        public CmsTreeItem next() {
120
121            CmsGalleryFolderBean gallery = m_beanIterator.next();
122            CmsTreeItem treeItem = createTreeItem(gallery, m_selectedGalleries, false, m_useGroups);
123            return treeItem;
124        }
125
126        /**
127         * @see java.util.Iterator#remove()
128         */
129        public void remove() {
130
131            throw new UnsupportedOperationException();
132        }
133    }
134
135    /**
136     * Command for adding more list items to the list of publish items.<p>
137     */
138    protected class MoreItemsCommand implements RepeatingCommand {
139
140        /** The number of items left to add. */
141        private int m_numItems;
142
143        /**
144         * Creates a new instance.<p>
145         *
146         * @param numItems the maximal number of items to add
147         */
148        public MoreItemsCommand(int numItems) {
149
150            m_numItems = numItems;
151        }
152
153        /**
154         * @see com.google.gwt.core.client.Scheduler.RepeatingCommand#execute()
155         */
156        public boolean execute() {
157
158            if (m_numItems == 0) {
159                setLoading(false);
160                onContentChange();
161                return false;
162            }
163            boolean hasMore = m_itemIterator.hasNext();
164            if (!hasMore) {
165                setLoading(false);
166                onContentChange();
167                return false;
168            } else {
169                CmsTreeItem treeItem = m_itemIterator.next();
170                CmsGalleryGroup group = (CmsGalleryGroup)treeItem.getData();
171                if ((group != null) && (group != m_lastGroup)) {
172                    m_lastGroup = group;
173                    CmsSimpleListItem header = new CmsSimpleListItem();
174                    header.getElement().setInnerText(getGroupName(group));
175                    String groupHeaderClass = I_CmsLayoutBundle.INSTANCE.galleryDialogCss().groupHeader();
176                    header.addStyleName(groupHeaderClass);
177                    addWidgetToList(header);
178                }
179
180                addWidgetToList(treeItem);
181            }
182            m_numItems -= 1;
183            return true;
184        }
185    }
186
187    /**
188     * A class which generates tree items incrementally to fill the galleries tab.<p>
189     */
190    protected class TreeItemGenerator implements Iterator<CmsTreeItem> {
191
192        /** The internal iterator over the gallery beans. <p> */
193        protected Iterator<CmsGalleryTreeEntry> m_beanIterator;
194
195        /**
196         * Creates a new instance.<p>
197         *
198         * @param folders the folders from which to generate list items
199         */
200        public TreeItemGenerator(List<CmsGalleryTreeEntry> folders) {
201
202            if (folders == null) {
203                folders = new ArrayList<CmsGalleryTreeEntry>();
204            }
205
206            m_beanIterator = folders.iterator();
207        }
208
209        /**
210         * @see java.util.Iterator#hasNext()
211         */
212        public boolean hasNext() {
213
214            return m_beanIterator.hasNext();
215        }
216
217        /**
218         * @see java.util.Iterator#next()
219         */
220        public CmsTreeItem next() {
221
222            CmsGalleryTreeEntry gallery = m_beanIterator.next();
223            CmsTreeItem treeItem = createTreeItem(gallery, m_selectedGalleries, true, false);
224            addChildren(treeItem, gallery.getChildren(), m_selectedGalleries);
225            treeItem.setOpen(true);
226            return treeItem;
227        }
228
229        /**
230         * @see java.util.Iterator#remove()
231         */
232        public void remove() {
233
234            throw new UnsupportedOperationException();
235        }
236    }
237
238    /**
239     * Handles the change of the item selection.<p>
240     */
241    private class SelectionHandler extends A_SelectionHandler {
242
243        /** The gallery path as id for the selected gallery. */
244        private String m_galleryPath;
245
246        /**
247         * Constructor.<p>
248         *
249         * @param gallerPath as id for the selected category
250         * @param checkBox the reference to the checkbox
251         */
252        public SelectionHandler(String gallerPath, CmsCheckBox checkBox) {
253
254            super(checkBox);
255            m_galleryPath = gallerPath;
256            m_selectionHandlers.add(this);
257        }
258
259        /**
260         * @see org.opencms.ade.galleries.client.ui.A_CmsListTab.A_SelectionHandler#onSelectionChange()
261         */
262        @Override
263        protected void onSelectionChange() {
264
265            if (getCheckBox().isChecked()) {
266                getTabHandler().onSelectGallery(m_galleryPath);
267            } else {
268                getTabHandler().onDeselectGallery(m_galleryPath);
269            }
270
271        }
272
273        /**
274         * @see org.opencms.ade.galleries.client.ui.A_CmsListTab.A_SelectionHandler#selectBeforeGoingToResultTab()
275         */
276        @Override
277        protected void selectBeforeGoingToResultTab() {
278
279            for (SelectionHandler otherHandler : m_selectionHandlers) {
280                if ((otherHandler != this)
281                    && (otherHandler.getCheckBox() != null)
282                    && otherHandler.getCheckBox().isChecked()) {
283                    otherHandler.getCheckBox().setChecked(false);
284                    otherHandler.onSelectionChange();
285                }
286            }
287            getCheckBox().setChecked(true);
288            onSelectionChange();
289        }
290    }
291
292    /** The batch size for adding new elements to the tab.<p> */
293    protected static final int LOAD_BATCH_SIZE = 50;
294
295    /** The labels to display for groups. */
296    protected Map<CmsGalleryGroup, String> m_groupLabels = new HashMap<>();
297
298    /** An iterator which produces new list items which should be added to the tab.<p> */
299    protected Iterator<CmsTreeItem> m_itemIterator;
300
301    /** The group of the gallery folder list item that was last rendered. */
302    protected CmsGalleryGroup m_lastGroup;
303
304    /** List of selected galleries. */
305    protected List<String> m_selectedGalleries;
306
307    /** The selection handlers. */
308    List<SelectionHandler> m_selectionHandlers = Lists.newArrayList();
309
310    /** Map of gallery folders by path. */
311    private Map<String, CmsGalleryFolderBean> m_galleries;
312
313    /** Flag which indicates whether new elements are currently being inserted into the galleries tab.<p> */
314    private boolean m_loading;
315
316    /** The tab handler. */
317    private CmsGalleriesTabHandler m_tabHandler;
318
319    /**
320     * Constructor.<p>
321     *
322     * @param tabHandler the tab handler
323     */
324    public CmsGalleriesTab(CmsGalleriesTabHandler tabHandler) {
325
326        super(GalleryTabId.cms_tab_galleries);
327        getList().addScrollHandler(new CmsScrollToBottomHandler(new Runnable() {
328
329            public void run() {
330
331                if (!isLoading()) {
332                    loadMoreItems();
333                }
334            }
335        }));
336        m_tabHandler = tabHandler;
337        m_galleries = new HashMap<String, CmsGalleryFolderBean>();
338        init();
339    }
340
341    /**
342     * Opens the 'optimize gallery' dialog for the given structure id of a gallery
343     *
344     * @param id the structure id of a gallery
345     */
346    public static void openOptimizeGalleryDialog(CmsUUID id) {
347
348        CmsEmbeddedDialogHandler dialogHandler = new CmsEmbeddedDialogHandler(new I_CmsActionHandler() {
349
350            public void leavePage(String targetUri) {
351
352                // not supported
353            }
354
355            public void onSiteOrProjectChange(String sitePath, String serverLink) {
356
357                // not supported
358            }
359
360            public void refreshResource(CmsUUID structureId) {
361
362            }
363        });
364        dialogHandler.openDialog(
365            "org.opencms.ui.actions.CmsGalleryOptimizeDialogAction",
366            CmsGwtConstants.CONTEXT_TYPE_FILE_TABLE,
367            Collections.singletonList(id));
368
369    }
370
371    /**
372     * Fill the content of the galleries tab panel.<p>
373     *
374     * @param galleryInfos the gallery info beans
375     * @param selectedGalleries the list of galleries to select
376     * @param grouped true if the items should be broken into groups
377     */
378    public void fillContent(List<CmsGalleryFolderBean> galleryInfos, List<String> selectedGalleries, boolean grouped) {
379
380        clearList();
381        m_lastGroup = null;
382        m_selectedGalleries = selectedGalleries;
383        if (!galleryInfos.isEmpty()) {
384            for (CmsGalleryFolderBean galleryInfo : galleryInfos) {
385                m_galleries.put(galleryInfo.getPath(), galleryInfo);
386            }
387            m_itemIterator = new ListItemGenerator(galleryInfos, grouped);
388            loadMoreItems();
389        } else {
390            showIsEmptyLabel();
391        }
392        onContentChange();
393    }
394
395    /**
396     * @see org.opencms.ade.galleries.client.ui.A_CmsTab#getParamPanels(org.opencms.ade.galleries.shared.CmsGallerySearchBean)
397     */
398    @Override
399    public List<CmsSearchParamPanel> getParamPanels(CmsGallerySearchBean searchObj) {
400
401        List<CmsSearchParamPanel> result = new ArrayList<CmsSearchParamPanel>();
402        for (String galleryPath : searchObj.getGalleries()) {
403            CmsGalleryFolderBean galleryBean = m_galleries.get(galleryPath);
404            if (galleryBean != null) {
405                String title = galleryBean.getTitle();
406                if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
407                    title = galleryBean.getPath();
408                }
409                CmsSearchParamPanel panel = new CmsSearchParamPanel(
410                    Messages.get().key(Messages.GUI_PARAMS_LABEL_GALLERIES_0),
411                    this);
412                panel.setContent(title, galleryPath);
413                result.add(panel);
414            }
415        }
416        return result;
417    }
418
419    /**
420     * Returns the value of the "loading" flag, which indicates whether new elements are currently being added into the galleries tab.<p>
421     *
422     * @return the "loading" flag
423     */
424    public boolean isLoading() {
425
426        return m_loading;
427
428    }
429
430    /**
431     * @see org.opencms.ade.galleries.client.ui.A_CmsTab#onSelection()
432     */
433    @Override
434    public void onSelection() {
435
436        super.onSelection();
437        Timer timer = new Timer() {
438
439            @Override
440            public void run() {
441
442                m_quickSearch.setFocus(true);
443            }
444        };
445        timer.schedule(20);
446    }
447
448    /**
449     * Sets the "loading" flag.<p>
450     *
451     * @param loading the new value of the loading flag
452     */
453    public void setLoading(boolean loading) {
454
455        m_loading = loading;
456    }
457
458    /**
459    * De-selects the galleries in the galleries list.<p>
460    *
461    * @param galleries the galleries to deselect
462    */
463    public void uncheckGalleries(List<String> galleries) {
464
465        for (String gallery : galleries) {
466            CmsListItem item = searchTreeItem(m_scrollList, gallery);
467            if (item != null) {
468                item.getCheckBox().setChecked(false);
469            }
470        }
471    }
472
473    /**
474     * Update the galleries list.<p>
475     *
476     * @param galleries the new gallery list
477     * @param selectedGalleries the list of galleries to select
478     * @param useGroups true if the galleries should be broken into groups (this assumes the galleries have already been sorted correctly)
479     */
480    public void updateListContent(
481        List<CmsGalleryFolderBean> galleries,
482        List<String> selectedGalleries,
483        boolean useGroups) {
484
485        clearList();
486        fillContent(galleries, selectedGalleries, useGroups);
487    }
488
489    /**
490     * Update the galleries tree.<p>
491     *
492     * @param galleryTreeEntries the new gallery tree list
493     * @param selectedGalleries the list of galleries to select
494     */
495    public void updateTreeContent(List<CmsGalleryTreeEntry> galleryTreeEntries, List<String> selectedGalleries) {
496
497        clearList();
498        m_selectedGalleries = selectedGalleries;
499        if (!galleryTreeEntries.isEmpty()) {
500            m_itemIterator = new TreeItemGenerator(galleryTreeEntries);
501            loadMoreItems();
502        } else {
503            showIsEmptyLabel();
504        }
505        onContentChange();
506    }
507
508    /**
509     * Adds children to the gallery tree and select the galleries.<p>
510     *
511     * @param parent the parent item
512     * @param children the list of children
513     * @param selectedGalleries the list of galleries to select
514     */
515    protected void addChildren(CmsTreeItem parent, List<CmsGalleryTreeEntry> children, List<String> selectedGalleries) {
516
517        if (children != null) {
518            for (CmsGalleryTreeEntry child : children) {
519                // set the category tree item and add to parent tree item
520                CmsTreeItem treeItem = createTreeItem(child, selectedGalleries, true, false);
521                if ((selectedGalleries != null) && selectedGalleries.contains(child.getPath())) {
522                    parent.setOpen(true);
523                    openParents(parent);
524                }
525                parent.addChild(treeItem);
526                addChildren(treeItem, child.getChildren(), selectedGalleries);
527            }
528        }
529    }
530
531    /**
532     * Creates a tree item widget used in list and tree view of this tab.<p>
533     *
534     * @param galleryInfo the gallery folder bean
535     * @param selectedGalleries the selected galleries
536     * @param forTree <code>true</code> if the item is used within tree view
537     * @param useGroups true if the gallery tree items should be broken into groups
538     *
539     * @return the tree item
540     */
541    protected CmsTreeItem createTreeItem(
542        CmsGalleryFolderBean galleryInfo,
543        List<String> selectedGalleries,
544        boolean forTree,
545        boolean useGroups) {
546
547        CmsListItemWidget listItemWidget = new CmsListItemWidget(galleryInfo);
548        listItemWidget.setUnselectable();
549        CmsCheckBox checkBox = new CmsCheckBox();
550        SelectionHandler selectionHandler = new SelectionHandler(galleryInfo.getPath(), checkBox);
551        checkBox.addClickHandler(selectionHandler);
552        listItemWidget.addClickHandler(selectionHandler);
553        if ((selectedGalleries != null) && selectedGalleries.contains(galleryInfo.getPath())) {
554            checkBox.setChecked(true);
555        }
556
557        if (galleryInfo.isEditable()) {
558
559            CmsPushButton optimizeButton = new CmsPushButton(I_CmsButton.EDIT_SMALL);
560            optimizeButton.setText(null);
561            optimizeButton.setTitle(Messages.get().key(Messages.GUI_TAB_GALLERIES_OPTIMIZE_BUTTON_0));
562            optimizeButton.setButtonStyle(ButtonStyle.FONT_ICON, null);
563            optimizeButton.addClickHandler(event -> {
564                event.stopPropagation(); // click event on gallery box triggers search, we don't want that
565                CmsUUID id = galleryInfo.getId();
566                openOptimizeGalleryDialog(id);
567            });
568
569            String uploadAction = galleryInfo.getUploadAction();
570
571            if (null != uploadAction) {
572                CmsPushButton uploadButton = new CmsPushButton(I_CmsButton.UPLOAD_SMALL);
573                uploadButton.setText(null);
574                uploadButton.setTitle(Messages.get().key(Messages.GUI_GALLERY_UPLOAD_TITLE_1, galleryInfo.getPath()));
575                uploadButton.setButtonStyle(ButtonStyle.FONT_ICON, null);
576                uploadButton.addClickHandler(new ClickHandler() {
577
578                    public void onClick(ClickEvent event) {
579
580                        // prevent event from bubbling up to surrounding widget
581                        event.stopPropagation();
582
583                        CmsRpcAction<CmsUUID> action = new CmsRpcAction<CmsUUID>() {
584
585                            @Override
586                            public void execute() {
587
588                                start(0, true);
589                                CmsCoreProvider.getVfsService().getStructureId(galleryInfo.getPath(), this);
590                            }
591
592                            @Override
593                            protected void onResponse(CmsUUID result) {
594
595                                stop(false);
596                                List<CmsUUID> resultIds = new ArrayList<>();
597                                resultIds.add(result);
598                                CmsEmbeddedDialogHandler.openDialog(
599                                    uploadAction,
600                                    resultIds,
601                                    id -> getTabHandler().updateIndex());
602                            }
603
604                        };
605                        action.execute();
606
607                    }
608                });
609                listItemWidget.addButton(uploadButton);
610
611            } else {
612                if (CmsEditExternalLinkDialog.LINK_GALLERY_RESOURCE_TYPE_NAME.equals(galleryInfo.getType())) {
613                    CmsPushButton createExternalLink = createNewExternalLinkButton(galleryInfo.getPath());
614                    if (createExternalLink != null) {
615                        listItemWidget.addButton(createExternalLink);
616                    }
617                } else {
618                    if (!CmsCoreProvider.get().isUploadDisabled()) {
619                        String uploadPath = CmsStringUtil.joinPaths(
620                            CmsCoreProvider.get().getSiteRoot(),
621                            galleryInfo.getPath());
622                        if (CmsCoreProvider.get().getUploadRestriction().isUploadEnabled(uploadPath)) {
623                            listItemWidget.addButton(createUploadButtonForTarget(galleryInfo.getPath(), false));
624                        }
625                    }
626                }
627            }
628            if (galleryInfo.isOptimizable()) {
629                listItemWidget.addButton(optimizeButton);
630            }
631        }
632        listItemWidget.addButton(createSelectButton(selectionHandler));
633        if (m_tabHandler.hasGalleriesSelectable()) {
634            CmsPushButton selectButton = createSelectResourceButton(
635                galleryInfo.getPath(),
636                CmsUUID.getNullUUID(),
637                "",
638                "");
639            listItemWidget.addButton(selectButton);
640        }
641
642        CmsTreeItem treeItem = new CmsTreeItem(forTree, checkBox, listItemWidget);
643        if (useGroups) {
644            treeItem.setData(galleryInfo.getGroup());
645        }
646        if (galleryInfo.getGroup() != null) {
647            m_groupLabels.putIfAbsent(galleryInfo.getGroup(), galleryInfo.getGroupLabel());
648        }
649        treeItem.setId(galleryInfo.getPath());
650        return treeItem;
651    }
652
653    /**
654     * Gets the label to display for a group.
655     *
656     * @param group the gallery group
657     * @return the label to display for the gallery group
658     */
659    protected String getGroupName(CmsGalleryGroup group) {
660
661        if (m_groupLabels.containsKey(group)) {
662            return m_groupLabels.get(group);
663        } else {
664            return "" + group;
665        }
666    }
667
668    /**
669     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#getSortList()
670     */
671    @Override
672    protected LinkedHashMap<String, String> getSortList() {
673
674        LinkedHashMap<String, String> list = new LinkedHashMap<String, String>();
675        list.put(SortParams.grouped.name(), Messages.get().key(Messages.GUI_SORT_LABEL_GROUPED_0));
676        list.put(SortParams.grouped_title.name(), Messages.get().key(Messages.GUI_SORT_LABEL_GROUPED_TITLE_0));
677        list.put(SortParams.title_asc.name(), Messages.get().key(Messages.GUI_SORT_LABEL_TITLE_ASC_0));
678        list.put(SortParams.title_desc.name(), Messages.get().key(Messages.GUI_SORT_LABEL_TITLE_DECS_0));
679        list.put(SortParams.type_asc.name(), Messages.get().key(Messages.GUI_SORT_LABEL_TYPE_ASC_0));
680        list.put(SortParams.type_desc.name(), Messages.get().key(Messages.GUI_SORT_LABEL_TYPE_DESC_0));
681        list.put(SortParams.tree.name(), Messages.get().key(Messages.GUI_SORT_LABEL_HIERARCHIC_0));
682
683        return list;
684    }
685
686    /**
687     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#getTabHandler()
688     */
689    @Override
690    protected CmsGalleriesTabHandler getTabHandler() {
691
692        return m_tabHandler;
693    }
694
695    /**
696     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#hasQuickFilter()
697     */
698    @Override
699    protected boolean hasQuickFilter() {
700
701        // allow filter if not in tree mode
702        return SortParams.tree != SortParams.valueOf(m_sortSelectBox.getFormValueAsString());
703    }
704
705    /**
706     * Adds more gallery list items to display in the tab, if available.<p>
707     */
708    protected void loadMoreItems() {
709
710        setLoading(true);
711        MoreItemsCommand cmd = new MoreItemsCommand(30);
712        Scheduler.get().scheduleFixedDelay(cmd, 1);
713    }
714
715    /**
716     * Goes up the tree and opens the parents of the item.<p>
717     *
718     * @param item the child item to start from
719     */
720    private void openParents(CmsTreeItem item) {
721
722        if (item != null) {
723            item.setOpen(true);
724            openParents(item.getParentItem());
725        }
726    }
727
728    /**
729     * Shows the tab list is empty label.<p>
730     */
731    private void showIsEmptyLabel() {
732
733        CmsSimpleListItem item = new CmsSimpleListItem();
734        Label isEmptyLabel = new Label(Messages.get().key(Messages.GUI_TAB_GALLERIES_IS_EMPTY_0));
735        item.add(isEmptyLabel);
736        m_scrollList.add(item);
737    }
738}