001/*
002
003 * This library is part of OpenCms -
004 * the Open Source Content Management System
005 *
006 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
007 *
008 * This library is free software; you can redistribute it and/or
009 * modify it under the terms of the GNU Lesser General Public
010 * License as published by the Free Software Foundation; either
011 * version 2.1 of the License, or (at your option) any later version.
012 *
013 * This library is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016 * Lesser General Public License for more details.
017 *
018 * For further information about Alkacon Software, please see the
019 * company website: http://www.alkacon.com
020 *
021 * For further information about OpenCms, please see the
022 * project website: http://www.opencms.org
023 *
024 * You should have received a copy of the GNU Lesser General Public
025 * License along with this library; if not, write to the Free Software
026 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
027 */
028
029package org.opencms.ade.galleries.client.ui;
030
031import org.opencms.ade.galleries.client.CmsVfsTabHandler;
032import org.opencms.ade.galleries.client.Messages;
033import org.opencms.ade.galleries.shared.CmsGallerySearchBean;
034import org.opencms.ade.galleries.shared.CmsVfsEntryBean;
035import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants;
036import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId;
037import org.opencms.file.CmsResource;
038import org.opencms.gwt.client.CmsCoreProvider;
039import org.opencms.gwt.client.ui.CmsList;
040import org.opencms.gwt.client.ui.I_CmsListItem;
041import org.opencms.gwt.client.ui.input.A_CmsSelectBox;
042import org.opencms.gwt.client.ui.input.CmsCheckBox;
043import org.opencms.gwt.client.ui.input.CmsFilterSelectBox;
044import org.opencms.gwt.client.ui.input.category.CmsDataValue;
045import org.opencms.gwt.client.ui.tree.A_CmsLazyOpenHandler;
046import org.opencms.gwt.client.ui.tree.CmsLazyTree;
047import org.opencms.gwt.client.ui.tree.CmsLazyTreeItem;
048import org.opencms.util.CmsStringUtil;
049import org.opencms.util.CmsUUID;
050
051import java.util.ArrayList;
052import java.util.Collection;
053import java.util.Collections;
054import java.util.HashMap;
055import java.util.HashSet;
056import java.util.LinkedHashMap;
057import java.util.List;
058import java.util.Map;
059import java.util.Set;
060
061import com.google.gwt.event.dom.client.ClickEvent;
062import com.google.gwt.event.logical.shared.CloseEvent;
063import com.google.gwt.event.logical.shared.CloseHandler;
064import com.google.gwt.event.logical.shared.OpenEvent;
065import com.google.gwt.event.logical.shared.OpenHandler;
066import com.google.gwt.user.client.rpc.AsyncCallback;
067
068/**
069 * The tab widget for selecting folders from the VFS tree.<p>
070 *
071 * @since 8.0.0
072 */
073public class CmsVfsTab extends A_CmsListTab {
074
075    /**
076     * Handles the change of the item selection.<p>
077     */
078    private class SelectionHandler extends A_SelectionHandler {
079
080        /** The category path as id for the selected category. */
081        private CmsVfsEntryBean m_vfsEntry;
082
083        /**
084         * Constructor.<p>
085         *
086         * @param vfsEntry the vfs entry represented by the list item
087         * @param checkBox the reference to the checkbox
088         */
089        public SelectionHandler(CmsVfsEntryBean vfsEntry, CmsCheckBox checkBox) {
090
091            super(checkBox);
092            m_vfsEntry = vfsEntry;
093            m_selectionHandlers.add(this);
094        }
095
096        /**
097         * @see org.opencms.ade.galleries.client.ui.A_CmsListTab.A_SelectionHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
098         */
099        @Override
100        public void onClick(ClickEvent event) {
101
102            if (isIncludeFiles()) {
103                super.onClick(event);
104            } else if (getTabHandler().hasSelectResource()) {
105                String selectPath = m_tabHandler.getSelectPath(m_vfsEntry);
106                getTabHandler().selectResource(
107                    selectPath,
108                    m_vfsEntry.getStructureId(),
109                    m_vfsEntry.getDisplayName(),
110                    I_CmsGalleryProviderConstants.RESOURCE_TYPE_FOLDER);
111            }
112        }
113
114        /**
115         * @see org.opencms.ade.galleries.client.ui.A_CmsListTab.A_SelectionHandler#onSelectionChange()
116         */
117        @Override
118        protected void onSelectionChange() {
119
120            if (isIncludeFiles()) {
121                getTabHandler().onSelectFolder(m_vfsEntry.getRootPath(), getCheckBox().isChecked());
122            }
123        }
124
125        /**
126         * @see org.opencms.ade.galleries.client.ui.A_CmsListTab.A_SelectionHandler#selectBeforeGoingToResultTab()
127         */
128        @Override
129        protected void selectBeforeGoingToResultTab() {
130
131            for (SelectionHandler otherHandler : m_selectionHandlers) {
132                if ((otherHandler != this)
133                    && (otherHandler.getCheckBox() != null)
134                    && otherHandler.getCheckBox().isChecked()) {
135                    otherHandler.getCheckBox().setChecked(false);
136                    otherHandler.onSelectionChange();
137                }
138            }
139            getCheckBox().setChecked(true);
140            onSelectionChange();
141        }
142    }
143
144    /** The tab handler. */
145    protected CmsVfsTabHandler m_tabHandler;
146
147    /** The selection handlers for the current tab. */
148    List<SelectionHandler> m_selectionHandlers = new ArrayList<SelectionHandler>();
149
150    /** Flag indicating files are included. */
151    private boolean m_includeFiles;
152
153    /** Flag which indicates whether the tab has been initialized. */
154    private boolean m_initialized;
155
156    /** A map of tree items indexed by VFS path. */
157    private Map<String, CmsLazyTreeItem> m_itemsByPath = new HashMap<String, CmsLazyTreeItem>();
158
159    /** The list of tree items. */
160    private List<CmsLazyTreeItem> m_treeItems = new ArrayList<CmsLazyTreeItem>();
161
162    /**
163     * Constructor.<p>
164     *
165     * @param tabHandler the tab handler
166     * @param includeFiles the include files flag
167     */
168    public CmsVfsTab(CmsVfsTabHandler tabHandler, boolean includeFiles) {
169
170        super(GalleryTabId.cms_tab_vfstree);
171        m_tabHandler = tabHandler;
172        m_includeFiles = includeFiles;
173        init();
174    }
175
176    /**
177     * Checks the check boxes for the selected folders.<p>
178     *
179     * @param folders the folders for which to check the check boxes
180     */
181    public void checkFolders(Set<String> folders) {
182
183        if (folders != null) {
184            for (String folder : folders) {
185                CmsLazyTreeItem item = m_itemsByPath.get(folder);
186                if ((item != null) && (item.getCheckBox() != null)) {
187                    item.getCheckBox().setChecked(true);
188                }
189            }
190        }
191
192    }
193
194    /**
195     * Sets the initial folders in the VFS tab.<p>
196     *
197     * @param entries the root folders to display
198     */
199    public void fillInitially(List<CmsVfsEntryBean> entries) {
200
201        fillInitially(entries, null);
202    }
203
204    /**
205     * Sets the initial folders in the VFS tab.<p>
206     *
207     * @param entries the root folders to display
208     * @param selectedSiteRoot site root that should be selected in the select box
209     */
210    public void fillInitially(List<CmsVfsEntryBean> entries, String selectedSiteRoot) {
211
212        clear();
213        for (CmsVfsEntryBean entry : entries) {
214            if (entry != null) {
215                CmsLazyTreeItem item = createItem(entry);
216                addWidgetToList(item);
217            }
218        }
219        if (null != selectedSiteRoot) {
220            selectSite(selectedSiteRoot);
221        }
222        m_initialized = true;
223    }
224
225    /**
226     * @see org.opencms.ade.galleries.client.ui.A_CmsTab#getParamPanels(org.opencms.ade.galleries.shared.CmsGallerySearchBean)
227     */
228    @Override
229    public List<CmsSearchParamPanel> getParamPanels(CmsGallerySearchBean searchObj) {
230
231        List<CmsSearchParamPanel> result = new ArrayList<CmsSearchParamPanel>();
232        for (String folder : searchObj.getFolders()) {
233            CmsSearchParamPanel panel = new CmsSearchParamPanel(
234                Messages.get().key(Messages.GUI_PARAMS_LABEL_FOLDERS_0),
235                this);
236            panel.setContent(folder, folder);
237            result.add(panel);
238        }
239        return result;
240    }
241
242    /**
243     * Checks if the tab is initialized.<p>
244     *
245     * @return true if the tab is initialized
246     */
247    public boolean isInitialized() {
248
249        return m_initialized;
250    }
251
252    /**
253     * This method is called when the VFS tree preload data is received.<p>
254     *
255     * @param vfsPreloadData the VFS tree preload data
256     */
257    public void onReceiveVfsPreloadData(CmsVfsEntryBean vfsPreloadData) {
258
259        String siteRoot = vfsPreloadData.getSiteRoot();
260        fillInitially(Collections.singletonList(vfsPreloadData), siteRoot);
261    }
262
263    /**
264     * Un-checks the check boxes for each folder passed in the <code>folders</code> parameter.<p>
265     *
266     * @param folders the folders for which the check boxes should be unchecked
267     */
268    public void uncheckFolders(Collection<String> folders) {
269
270        for (String folder : folders) {
271            CmsLazyTreeItem item = m_itemsByPath.get(folder);
272            if ((item != null) && (item.getCheckBox() != null)) {
273                item.getCheckBox().setChecked(false);
274            }
275        }
276    }
277
278    /**
279     * Clears the contents of the tab and resets the mapping from tree items to VFS beans.<p>
280     */
281    protected void clear() {
282
283        clearList();
284        m_selectionHandlers.clear();
285        m_treeItems.clear();
286    }
287
288    /**
289     * Helper method for creating a VFS tree item widget from a VFS entry bean.<p>
290     *
291     * @param vfsEntry the VFS entry bean
292     *
293     * @return the tree item widget
294     */
295    protected CmsLazyTreeItem createItem(final CmsVfsEntryBean vfsEntry) {
296
297        String name = null;
298        String rootPath = vfsEntry.getRootPath();
299        if (rootPath.equals("/") || rootPath.equals("")) {
300            name = "/";
301        } else {
302            name = CmsResource.getName(vfsEntry.getRootPath());
303
304            if (name.endsWith("/")) {
305                name = name.substring(0, name.length() - 1);
306            }
307        }
308        CmsDataValue dataValue = new CmsDataValue(
309            600,
310            3,
311            vfsEntry.getSmallIconClasses(),
312            name,
313            vfsEntry.getDisplayName());
314        if (vfsEntry.isSearchMatch()) {
315            dataValue.setSearchMatch(true);
316        }
317        dataValue.setUnselectable();
318        if (vfsEntry.isEditable()) {
319            if (!CmsCoreProvider.get().isUploadDisabled()) {
320                if (CmsCoreProvider.get().getUploadRestriction().isUploadEnabled(vfsEntry.getRootPath())) {
321                    dataValue.addButton(createUploadButtonForTarget(vfsEntry.getRootPath(), true));
322                }
323            }
324        }
325        CmsLazyTreeItem result;
326        SelectionHandler selectionHandler;
327        CmsCheckBox checkbox = null;
328        if (isIncludeFiles()) {
329            checkbox = new CmsCheckBox();
330            result = new CmsLazyTreeItem(checkbox, dataValue, true);
331            selectionHandler = new SelectionHandler(vfsEntry, checkbox);
332            checkbox.addClickHandler(selectionHandler);
333            dataValue.addClickHandler(selectionHandler);
334            dataValue.addButton(createSelectButton(selectionHandler));
335        } else {
336            result = new CmsLazyTreeItem(dataValue, true);
337            selectionHandler = new SelectionHandler(vfsEntry, null);
338        }
339        // we need this in a final variable to access it in the click handler
340        if (getTabHandler().hasSelectResource()) {
341            String selectPath = m_tabHandler.getSelectPath(vfsEntry);
342            dataValue.addButton(
343                createSelectResourceButton(
344                    selectPath,
345                    vfsEntry.getStructureId(),
346                    vfsEntry.getDisplayName(),
347                    I_CmsGalleryProviderConstants.RESOURCE_TYPE_FOLDER));
348        }
349        result.setData(vfsEntry);
350        m_itemsByPath.put(vfsEntry.getRootPath(), result);
351        result.setLeafStyle(false);
352        result.setSmallView(true);
353        m_treeItems.add(result);
354        if (vfsEntry.getChildren() != null) {
355            for (CmsVfsEntryBean child : vfsEntry.getChildren()) {
356                result.addChild(createItem(child));
357            }
358            result.onFinishLoading();
359            result.setOpen(true, false);
360            if (vfsEntry.getChildren().isEmpty()) {
361                result.setLeafStyle(true);
362            }
363        }
364
365        return result;
366    }
367
368    /**
369     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#createScrollList()
370     */
371    @Override
372    protected CmsList<? extends I_CmsListItem> createScrollList() {
373
374        CmsLazyTree<CmsLazyTreeItem> tree = new CmsLazyTree<CmsLazyTreeItem>(
375            new A_CmsLazyOpenHandler<CmsLazyTreeItem>() {
376
377                /**
378                 * @see org.opencms.gwt.client.ui.tree.I_CmsLazyOpenHandler#load(org.opencms.gwt.client.ui.tree.CmsLazyTreeItem, java.lang.Runnable)
379                 */
380                public void load(final CmsLazyTreeItem target, final Runnable loadCallback) {
381
382                    CmsVfsEntryBean entry = target.getData();
383                    String path = entry.getRootPath();
384                    AsyncCallback<List<CmsVfsEntryBean>> callback = new AsyncCallback<List<CmsVfsEntryBean>>() {
385
386                        /**
387                         * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
388                         */
389                        public void onFailure(Throwable caught) {
390
391                            // should never be called
392
393                        }
394
395                        /**
396                         * @see com.google.gwt.user.client.rpc.AsyncCallback#onSuccess(java.lang.Object)
397                         */
398                        public void onSuccess(List<CmsVfsEntryBean> result) {
399
400                            for (CmsVfsEntryBean childEntry : result) {
401                                CmsLazyTreeItem item = createItem(childEntry);
402                                target.addChild(item);
403                            }
404                            target.onFinishLoading();
405                            loadCallback.run();
406                        }
407                    };
408
409                    m_tabHandler.getSubFolders(path, callback);
410
411                }
412
413                @Override
414                public void onFinishOpen(CmsLazyTreeItem target) {
415
416                    onContentChange();
417                }
418
419            });
420        tree.addOpenHandler(new OpenHandler<CmsLazyTreeItem>() {
421
422            public void onOpen(OpenEvent<CmsLazyTreeItem> event) {
423
424                Set<CmsUUID> ids = getOpenElementIds();
425                CmsVfsEntryBean entry = event.getTarget().getData();
426                ids.add(entry.getStructureId());
427                getTabHandler().onChangeTreeState(ids);
428                onContentChange();
429            }
430
431        });
432        tree.addCloseHandler(new CloseHandler<CmsLazyTreeItem>() {
433
434            public void onClose(CloseEvent<CmsLazyTreeItem> event) {
435
436                Set<CmsUUID> ids = getOpenElementIds();
437                CmsVfsEntryBean entry = event.getTarget().getData();
438                ids.remove(entry.getStructureId());
439                getTabHandler().onChangeTreeState(ids);
440            }
441
442        });
443        return tree;
444    }
445
446    /**
447     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#createSelectBox(java.util.LinkedHashMap)
448     */
449    @Override
450    protected A_CmsSelectBox<?> createSelectBox(LinkedHashMap<String, String> options) {
451
452        CmsFilterSelectBox box = new CmsFilterSelectBox(options);
453        return box;
454    }
455
456    /**
457     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#getSortList()
458     */
459    @Override
460    protected LinkedHashMap<String, String> getSortList() {
461
462        return m_tabHandler.getSortList();
463    }
464
465    /**
466     * @see org.opencms.ade.galleries.client.ui.A_CmsTab#getTabHandler()
467     */
468    @Override
469    protected CmsVfsTabHandler getTabHandler() {
470
471        return m_tabHandler;
472    }
473
474    /**
475     * @see org.opencms.ade.galleries.client.ui.A_CmsListTab#hasQuickFilter()
476     */
477    @Override
478    protected boolean hasQuickFilter() {
479
480        return true;
481    }
482
483    /**
484     * Returns if files are included.<p>
485     *
486     * @return <code>true</code> if files are included
487     */
488    protected boolean isIncludeFiles() {
489
490        return m_includeFiles;
491    }
492
493    /**
494     * Collects the structure ids belonging to open tree entries.<p>
495     *
496     * @return the structure ids for  the open tree entries
497     */
498    Set<CmsUUID> getOpenElementIds() {
499
500        Set<CmsUUID> ids = new HashSet<CmsUUID>();
501        for (CmsLazyTreeItem item : m_treeItems) {
502            CmsVfsEntryBean entry = item.getData();
503            if (item.isOpen()) {
504                ids.add(entry.getStructureId());
505            }
506        }
507        return ids;
508    }
509
510    /**
511     * Selects a specific site.<p>
512     *
513     * @param siteRoot the site root
514     */
515    private void selectSite(String siteRoot) {
516
517        if (m_sortSelectBox == null) {
518            return;
519        }
520        Map<String, String> options = ((CmsFilterSelectBox)m_sortSelectBox).getItems();
521        String option = null;
522        for (Map.Entry<String, String> entry : options.entrySet()) {
523            if (CmsStringUtil.comparePaths(entry.getKey(), siteRoot)) {
524                option = entry.getKey();
525                break;
526            }
527        }
528        if (option != null) {
529            m_sortSelectBox.setFormValue(option, false);
530        }
531    }
532
533}