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.client;
029
030import org.opencms.gwt.client.ui.input.upload.CmsFileInput;
031import org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton;
032import org.opencms.gwt.client.ui.input.upload.I_CmsUploadButtonHandler;
033import org.opencms.gwt.client.util.CmsDomUtil;
034
035import java.util.ArrayList;
036import java.util.Collections;
037import java.util.Iterator;
038import java.util.List;
039
040import com.google.gwt.dom.client.Element;
041import com.google.gwt.dom.client.Style.Display;
042import com.google.gwt.event.dom.client.ChangeEvent;
043import com.google.gwt.event.dom.client.ChangeHandler;
044import com.google.gwt.event.shared.HandlerRegistration;
045import com.google.gwt.user.client.DOM;
046import com.google.gwt.user.client.Event;
047import com.google.gwt.user.client.ui.HasWidgets;
048import com.google.gwt.user.client.ui.Widget;
049import com.vaadin.client.ui.VButton;
050
051/**
052 * A Vaadin based upload button.<p>
053 */
054public class CmsUploadButton extends VButton implements I_CmsUploadButton, HasWidgets {
055
056    /** The button handler. */
057    private I_CmsUploadButtonHandler m_buttonHandler;
058
059    /** The current file input element. */
060    private CmsFileInput m_fileInput;
061
062    /** The input change handler registration. */
063    private HandlerRegistration m_inputChangeHandlerRegistration;
064
065    /** List of used input elements. */
066    private List<CmsFileInput> m_usedInputs;
067
068    /**
069     * Constructor.<p>
070     *
071     * @param buttonHandler the button handler
072     */
073    public CmsUploadButton(I_CmsUploadButtonHandler buttonHandler) {
074        super();
075        addStyleName("o-upload-button");
076        m_buttonHandler = buttonHandler;
077        m_buttonHandler.setButton(this);
078        m_usedInputs = new ArrayList<CmsFileInput>();
079        createFileInput();
080    }
081
082    /**
083     * @see com.google.gwt.user.client.ui.HasWidgets#add(com.google.gwt.user.client.ui.Widget)
084     */
085    public void add(Widget w) {
086
087        throw new UnsupportedOperationException("Adding widgets to the upload button is not allowed.");
088    }
089
090    /**
091     * @see com.google.gwt.user.client.ui.HasWidgets#clear()
092     */
093    public void clear() {
094
095        throw new UnsupportedOperationException("Clear is not supported by the upload button.");
096    }
097
098    /**
099     * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton#createFileInput()
100     */
101    public CmsFileInput createFileInput() {
102
103        // remove the current file input field and add a new one
104        CmsFileInput previous = m_fileInput;
105
106        if (m_fileInput != null) {
107            m_fileInput.getElement().getStyle().setDisplay(Display.NONE);
108        }
109        m_fileInput = new CmsFileInput();
110        m_usedInputs.add(m_fileInput);
111        if (m_inputChangeHandlerRegistration != null) {
112            m_inputChangeHandlerRegistration.removeHandler();
113        }
114
115        m_inputChangeHandlerRegistration = m_fileInput.addChangeHandler(new ChangeHandler() {
116
117            public void onChange(ChangeEvent event) {
118
119                onInputChange();
120            }
121        });
122        m_buttonHandler.initializeFileInput(m_fileInput);
123        getElement().appendChild(m_fileInput.getElement());
124        m_fileInput.sinkEvents(Event.ONCHANGE);
125        m_fileInput.setParent(this);
126        return previous;
127    }
128
129    /**
130     * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton#getButtonHandler()
131     */
132    public I_CmsUploadButtonHandler getButtonHandler() {
133
134        return m_buttonHandler;
135    }
136
137    /**
138     * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
139     */
140    public Iterator<Widget> iterator() {
141
142        return m_fileInput != null
143        ? Collections.<Widget> singletonList(m_fileInput).iterator()
144        : Collections.<Widget> emptyIterator();
145    }
146
147    /**
148     * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton#reinitButton(org.opencms.gwt.client.ui.input.upload.I_CmsUploadButtonHandler)
149     */
150    public void reinitButton(I_CmsUploadButtonHandler buttonHandler) {
151
152        for (CmsFileInput input : m_usedInputs) {
153            input.onDetach();
154            input.getElement().removeFromParent();
155        }
156        m_usedInputs.clear();
157        m_buttonHandler = buttonHandler;
158        m_buttonHandler.setButton(this);
159        createFileInput();
160    }
161
162    /**
163     * @see com.google.gwt.user.client.ui.HasWidgets#remove(com.google.gwt.user.client.ui.Widget)
164     */
165    @Override
166    public boolean remove(Widget w) {
167
168        // Validate.
169        if (w != m_fileInput) {
170            return false;
171        }
172        // Orphan.
173        try {
174            m_fileInput.setParent(null);
175
176        } finally {
177            // Physical detach.
178            Element elem = w.getElement();
179            DOM.getParent(elem).removeChild(elem);
180
181            // Logical detach.
182            m_fileInput = null;
183        }
184        return true;
185    }
186
187    /**
188     * @see com.google.gwt.user.client.ui.Widget#doAttachChildren()
189     */
190    @Override
191    protected void doAttachChildren() {
192
193        if ((m_fileInput != null) && !m_fileInput.isAttached()) {
194            m_fileInput.onAttach();
195        }
196    }
197
198    /**
199     * Handles the input change.<p>
200     */
201    void onInputChange() {
202
203        // hack to reset the hover state
204        CmsDomUtil.clearHover(getElement());
205        m_buttonHandler.onChange(m_fileInput);
206    }
207
208    /**
209     * Sets the upload enabled.<p>
210     *
211     * @param enabled the enabled flag
212     */
213    void setUploadEnabled(boolean enabled) {
214
215        m_fileInput.setVisible(enabled);
216    }
217}