001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://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.ui.components.fileselect;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsResource;
032import org.opencms.file.CmsResourceFilter;
033import org.opencms.main.CmsException;
034import org.opencms.main.CmsLog;
035import org.opencms.ui.A_CmsUI;
036import org.opencms.ui.CmsVaadinUtils;
037import org.opencms.ui.FontOpenCms;
038import org.opencms.ui.components.CmsBasicDialog;
039import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
040import org.opencms.ui.components.CmsErrorDialog;
041import org.opencms.ui.components.OpenCmsTheme;
042import org.opencms.ui.components.editablegroup.CmsEditableGroup;
043import org.opencms.ui.components.fileselect.CmsResourceSelectDialog.Options;
044import org.opencms.util.CmsStringUtil;
045
046import org.apache.commons.logging.Log;
047
048import com.vaadin.shared.ui.ContentMode;
049import com.vaadin.ui.Button;
050import com.vaadin.ui.Button.ClickEvent;
051import com.vaadin.ui.Button.ClickListener;
052import com.vaadin.ui.CssLayout;
053import com.vaadin.ui.Label;
054import com.vaadin.ui.TextField;
055import com.vaadin.ui.Window;
056import com.vaadin.v7.ui.CustomField;
057
058/**
059 * Abstract file select field. Used by {@link org.opencms.ui.components.fileselect.CmsPathSelectField}.<p>
060 *
061 * @param <T> the value type
062 */
063public abstract class A_CmsFileSelectField<T> extends CustomField<T> implements CmsEditableGroup.I_HasError {
064
065    /** Logger instance for this class. */
066    private static final Log LOG = CmsLog.getLog(A_CmsFileSelectField.class);
067
068    /** The serial version id. */
069    private static final long serialVersionUID = 1L;
070
071    /** The file select dialog caption. */
072    protected String m_fileSelectCaption;
073
074    /** The filter used for reading resources. */
075    protected CmsResourceFilter m_filter;
076
077    /** The start with sitemap view flag. */
078    protected boolean m_startWithSitemapView;
079
080    /** The text field containing the selected path. */
081    protected TextField m_textField;
082
083    /**Button for open file select dialog. */
084    Button m_fileSelectButton;
085
086    /**Indicates if file select button should be visible. */
087    private boolean m_fileselectVisible = true;
088
089    /**CmsObject instance, doesn't have to be set. In normal case this is null.*/
090    protected CmsObject m_cms;
091
092    /**Indicates if changing the website should be possible. */
093    protected boolean m_diableSiteSwitch;
094
095    /**The default path to be opened in file select dialog if no path was entered before. */
096    private String m_defaultPath = "";
097
098    /**Require the resource to be a folder?*/
099    private boolean m_requireFolder;
100
101    /**Require the resource to be a file?*/
102    private boolean m_requireFile;
103
104    /**Only resources under this (root)path can be selected. */
105    private String m_basePath = "/";
106
107    /**
108     * Creates a new instance.<p>
109     */
110    public A_CmsFileSelectField() {
111
112        m_textField = new TextField();
113        m_textField.setWidth("100%");
114        m_filter = CmsResourceFilter.ONLY_VISIBLE_NO_DELETED;
115    }
116
117    /**
118     * Disables the site switch function.<p>
119     */
120    public void disableSiteSwitch() {
121
122        m_diableSiteSwitch = true;
123    }
124
125    /**
126     * @see org.opencms.ui.components.editablegroup.CmsEditableGroup.I_HasError#hasEditableGroupError()
127     */
128    public boolean hasEditableGroupError() {
129
130        return m_textField.getComponentError() != null;
131    }
132
133    /**
134     * Require the resource to be a file.<p>
135     */
136    public void requireFile() {
137
138        m_requireFile = true;
139        m_requireFolder = false;
140    }
141
142    /**
143     * Require the resource to be a folder.<p>
144     */
145    public void requireFolder() {
146
147        m_requireFile = false;
148        m_requireFolder = true;
149    }
150
151    /**
152     * Resets the type requirements.<p>
153     */
154    public void resetRequireType() {
155
156        m_requireFile = false;
157        m_requireFolder = false;
158
159    }
160
161    /**
162     * Sets the base path.
163     * @param path the base path
164     */
165    public void setBasePath(String path) {
166
167        m_basePath = path;
168    }
169
170    /**
171     * Method to set cms object to make it possible to user other site context.<p>
172     *
173     * @param cms Object to use
174     */
175    public void setCmsObject(CmsObject cms) {
176
177        m_cms = cms;
178    }
179
180    /**
181     * Sets the default path to open if no Path is selected yet.<p>
182     *
183     * @param path to be opened
184     */
185    public void setDefaultPath(String path) {
186
187        m_defaultPath = path;
188        if (!m_defaultPath.endsWith("/")) {
189            m_defaultPath += "/";
190        }
191        //Add some chars.. only the parent is considered
192        m_defaultPath += "aa";
193    }
194
195    /**
196     * Sets the visibility of the file select button.<p>
197     *
198     * @param visible boolean
199     */
200    public void setFileSelectButtonVisible(boolean visible) {
201
202        m_fileselectVisible = visible;
203        if (m_fileSelectButton != null) {
204            m_fileSelectButton.setVisible(visible);
205        }
206    }
207
208    /**
209     * Sets the caption of the file select dialog.<p>
210     *
211     * @param caption the caption
212     */
213    public void setFileSelectCaption(String caption) {
214
215        m_fileSelectCaption = caption;
216    }
217
218    /**
219     * Sets the filter to use for reading resources.<p>
220     *
221     * @param filter the new filter
222     */
223    public void setResourceFilter(CmsResourceFilter filter) {
224
225        m_filter = filter;
226
227    }
228
229    /**
230     * Sets the start with sitemap view flag.<p>
231     *
232     * @param startWithSitemapView the start with sitemap view flag
233     */
234    public void setStartWithSitempaView(boolean startWithSitemapView) {
235
236        m_startWithSitemapView = startWithSitemapView;
237    }
238
239    /**
240     * Gets the options object.<p>
241     *
242     * @return Options
243     */
244    protected Options getOptions() {
245
246        Options options = new Options();
247        return options;
248    }
249
250    /**
251     * @see com.vaadin.ui.CustomField#initContent()
252     */
253    @Override
254    protected CssLayout initContent() {
255
256        CssLayout layout = new CssLayout();
257        if (m_fileselectVisible) {
258            layout.addStyleName("o-fileselect");
259        }
260        layout.setWidth("100%");
261        // layout.setSpacing(true);
262        layout.addComponent(m_textField);
263        if (m_fileselectVisible) {
264            Label spacer = new Label("");
265            spacer.addStyleName("o-fileselect-spacer");
266            spacer.setContentMode(ContentMode.HTML);
267            spacer.setValue("<div></div>");
268            layout.addComponent(spacer);
269        }
270        m_fileSelectButton = new Button("");
271        m_fileSelectButton.addStyleName(OpenCmsTheme.BUTTON_ICON);
272        m_fileSelectButton.setIcon(FontOpenCms.GALLERY);
273        m_fileSelectButton.addStyleName("o-fileselect-button");
274        m_fileSelectButton.setEnabled(m_fileselectVisible);
275        if (m_fileselectVisible) {
276            layout.addComponent(m_fileSelectButton);
277        }
278        m_fileSelectButton.addClickListener(new ClickListener() {
279
280            /** Serial version id. */
281            private static final long serialVersionUID = 1L;
282
283            public void buttonClick(ClickEvent event) {
284
285                openFileSelector();
286            }
287        });
288        return layout;
289    }
290
291    /**
292     * Opens the file selector dialog.<p>
293     */
294    protected void openFileSelector() {
295
296        try {
297
298            final Window window = CmsBasicDialog.prepareWindow(DialogWidth.max);
299            window.setCaption(m_fileSelectCaption != null ? m_fileSelectCaption : getWindowCaption());
300            A_CmsUI.get().addWindow(window);
301            CmsResourceSelectDialog fileSelect;
302
303            //Switch if cms object was set.
304            if (m_cms == null) {
305                fileSelect = new CmsResourceSelectDialog(m_filter, A_CmsUI.getCmsObject(), getOptions());
306            } else {
307                fileSelect = new CmsResourceSelectDialog(m_filter, m_cms, getOptions());
308            }
309            if (m_diableSiteSwitch) {
310                fileSelect.disableSiteSwitch();
311            }
312            fileSelect.showSitemapView(m_startWithSitemapView);
313
314            T value = getValue();
315            if (value instanceof CmsResource) {
316                fileSelect.showStartResource((CmsResource)value);
317            } else if (value instanceof String) {
318                if (CmsStringUtil.isEmptyOrWhitespaceOnly((String)value)) {
319                    fileSelect.openPath(m_defaultPath);
320                } else {
321                    fileSelect.openPath((String)value);
322                }
323            }
324
325            window.setContent(fileSelect);
326            fileSelect.addSelectionHandler(new I_CmsSelectionHandler<CmsResource>() {
327
328                public void onSelection(CmsResource selected) {
329
330                    if (!resourceIsValid(selected)) {
331                        return;
332                    }
333                    setResourceValue(selected);
334                    window.close();
335
336                }
337            });
338        } catch (CmsException e) {
339            LOG.error(e.getLocalizedMessage(), e);
340            CmsErrorDialog.showErrorDialog(e);
341        }
342    }
343
344    /**
345     * Checks if the given resource is valid according to require Folder or File.<p>
346     *
347     * @param resource to check
348     * @return true if resource is valid
349     */
350    protected boolean resourceIsValid(CmsResource resource) {
351
352        if (!resource.getRootPath().startsWith(m_basePath)) {
353            return false;
354        }
355        if (m_requireFile & resource.isFolder()) {
356            return false;
357        }
358        if (m_requireFolder & resource.isFile()) {
359            return false;
360        }
361        return true;
362    }
363
364    /**
365     * Sets the field value.<p>
366     *
367     * @param resource the resource
368     */
369    protected abstract void setResourceValue(CmsResource resource);
370
371    /**
372     * Returns the window caption.
373     * @return the window caption.
374     */
375    private String getWindowCaption() {
376
377        if (m_requireFolder) {
378            return CmsVaadinUtils.getMessageText(org.opencms.ui.components.Messages.GUI_FOLDER_SELECT_CAPTION_0);
379        }
380        return CmsVaadinUtils.getMessageText(org.opencms.ui.components.Messages.GUI_FILE_SELECT_CAPTION_0);
381    }
382}