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.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.ui.Button;
049import com.vaadin.ui.Button.ClickEvent;
050import com.vaadin.ui.Button.ClickListener;
051import com.vaadin.ui.CssLayout;
052import com.vaadin.ui.Window;
053import com.vaadin.v7.shared.ui.label.ContentMode;
054import com.vaadin.v7.ui.CustomField;
055import com.vaadin.v7.ui.Label;
056import com.vaadin.v7.ui.TextField;
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.I_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    public void setBasePath(String path) {
162
163        m_basePath = path;
164    }
165
166    /**
167     * Method to set cms object to make it possible to user other site context.<p>
168     *
169     * @param cms Object to use
170     */
171    public void setCmsObject(CmsObject cms) {
172
173        m_cms = cms;
174    }
175
176    /**
177     * Sets the default path to open if no Path is selected yet.<p>
178     *
179     * @param path to be opened
180     */
181    public void setDefaultPath(String path) {
182
183        m_defaultPath = path;
184        if (!m_defaultPath.endsWith("/")) {
185            m_defaultPath += "/";
186        }
187        //Add some chars.. only the parent is considered
188        m_defaultPath += "aa";
189    }
190
191    /**
192     * Sets the visibility of the file select button.<p>
193     *
194     * @param visible boolean
195     */
196    public void setFileSelectButtonVisible(boolean visible) {
197
198        m_fileselectVisible = visible;
199        if (m_fileSelectButton != null) {
200            m_fileSelectButton.setVisible(visible);
201        }
202    }
203
204    /**
205     * Sets the caption of the file select dialog.<p>
206     *
207     * @param caption the caption
208     */
209    public void setFileSelectCaption(String caption) {
210
211        m_fileSelectCaption = caption;
212    }
213
214    /**
215     * Sets the filter to use for reading resources.<p>
216     *
217     * @param filter the new filter
218     */
219    public void setResourceFilter(CmsResourceFilter filter) {
220
221        m_filter = filter;
222
223    }
224
225    /**
226     * Sets the start with sitemap view flag.<p>
227     *
228     * @param startWithSitemapView the start with sitemap view flag
229     */
230    public void setStartWithSitempaView(boolean startWithSitemapView) {
231
232        m_startWithSitemapView = startWithSitemapView;
233    }
234
235    /**
236     * Gets the options object.<p>
237     *
238     * @return Options
239     */
240    protected Options getOptions() {
241
242        Options options = new Options();
243        return options;
244    }
245
246    /**
247     * @see com.vaadin.ui.CustomField#initContent()
248     */
249    @Override
250    protected CssLayout initContent() {
251
252        CssLayout layout = new CssLayout();
253        if (m_fileselectVisible) {
254            layout.addStyleName("o-fileselect");
255        }
256        layout.setWidth("100%");
257        // layout.setSpacing(true);
258        layout.addComponent(m_textField);
259        if (m_fileselectVisible) {
260            Label spacer = new Label("");
261            spacer.addStyleName("o-fileselect-spacer");
262            spacer.setContentMode(ContentMode.HTML);
263            spacer.setValue("<div></div>");
264            layout.addComponent(spacer);
265        }
266        m_fileSelectButton = new Button("");
267        m_fileSelectButton.addStyleName(OpenCmsTheme.BUTTON_ICON);
268        m_fileSelectButton.setIcon(FontOpenCms.GALLERY);
269        m_fileSelectButton.addStyleName("o-fileselect-button");
270        m_fileSelectButton.setEnabled(m_fileselectVisible);
271        if (m_fileselectVisible) {
272            layout.addComponent(m_fileSelectButton);
273        }
274        m_fileSelectButton.addClickListener(new ClickListener() {
275
276            /** Serial version id. */
277            private static final long serialVersionUID = 1L;
278
279            public void buttonClick(ClickEvent event) {
280
281                openFileSelector();
282            }
283        });
284        return layout;
285    }
286
287    /**
288     * Opens the file selector dialog.<p>
289     */
290    protected void openFileSelector() {
291
292        try {
293
294            final Window window = CmsBasicDialog.prepareWindow(DialogWidth.max);
295            window.setCaption(m_fileSelectCaption != null ? m_fileSelectCaption : getWindowCaption());
296            A_CmsUI.get().addWindow(window);
297            CmsResourceSelectDialog fileSelect;
298
299            //Switch if cms object was set.
300            if (m_cms == null) {
301                fileSelect = new CmsResourceSelectDialog(m_filter, A_CmsUI.getCmsObject(), getOptions());
302            } else {
303                fileSelect = new CmsResourceSelectDialog(m_filter, m_cms, getOptions());
304            }
305            if (m_diableSiteSwitch) {
306                fileSelect.disableSiteSwitch();
307            }
308            fileSelect.showSitemapView(m_startWithSitemapView);
309
310            T value = getValue();
311            if (value instanceof CmsResource) {
312                fileSelect.showStartResource((CmsResource)value);
313            } else if (value instanceof String) {
314                if (CmsStringUtil.isEmptyOrWhitespaceOnly((String)value)) {
315                    fileSelect.openPath(m_defaultPath);
316                } else {
317                    fileSelect.openPath((String)value);
318                }
319            }
320
321            window.setContent(fileSelect);
322            fileSelect.addSelectionHandler(new I_CmsSelectionHandler<CmsResource>() {
323
324                public void onSelection(CmsResource selected) {
325
326                    if (!resourceIsValid(selected)) {
327                        return;
328                    }
329                    setResourceValue(selected);
330                    window.close();
331
332                }
333            });
334        } catch (CmsException e) {
335            LOG.error(e.getLocalizedMessage(), e);
336            CmsErrorDialog.showErrorDialog(e);
337        }
338    }
339
340    /**
341     * Checks if the given resource is valid according to require Folder or File.<p>
342     *
343     * @param resource to check
344     * @return true if resource is valid
345     */
346    protected boolean resourceIsValid(CmsResource resource) {
347
348        if (!resource.getRootPath().startsWith(m_basePath)) {
349            return false;
350        }
351        if (m_requireFile & resource.isFolder()) {
352            return false;
353        }
354        if (m_requireFolder & resource.isFile()) {
355            return false;
356        }
357        return true;
358    }
359
360    /**
361     * Sets the field value.<p>
362     *
363     * @param resource the resource
364     */
365    protected abstract void setResourceValue(CmsResource resource);
366
367    private String getWindowCaption() {
368
369        if (m_requireFolder) {
370            return CmsVaadinUtils.getMessageText(org.opencms.ui.components.Messages.GUI_FOLDER_SELECT_CAPTION_0);
371        }
372        return CmsVaadinUtils.getMessageText(org.opencms.ui.components.Messages.GUI_FILE_SELECT_CAPTION_0);
373    }
374}