package org.sigmah.client.ui.widget.form; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import org.sigmah.client.ui.widget.Loadable; import org.sigmah.client.ui.widget.button.Button; import com.extjs.gxt.ui.client.core.El; import com.extjs.gxt.ui.client.core.XDOM; import com.extjs.gxt.ui.client.event.ComponentEvent; import com.extjs.gxt.ui.client.util.BaseEventPreview; import com.extjs.gxt.ui.client.util.Rectangle; import com.extjs.gxt.ui.client.widget.ComponentHelper; import com.extjs.gxt.ui.client.widget.form.FileUploadField; import com.extjs.gxt.ui.client.widget.form.TextField; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.InputElement; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.AbstractImagePrototype; /** * An upload field represented by a simple button. This component is based on {@link FileUploadField}. * * @author tmi (v1.3) * @author Denis Colliot (dcolliot@ideia.fr) (v2.0) * @see com.extjs.gxt.ui.client.widget.form.FileUploadField */ public class ButtonFileUploadField extends TextField<String> implements Loadable { private final BaseEventPreview focusPreview; private El file; private Button button; private String buttonCaption; private String accept; private AbstractImagePrototype buttonIcon; /** * Creates a new file upload field. */ public ButtonFileUploadField() { focusPreview = new BaseEventPreview(); focusPreview.setAutoHide(false); ensureVisibilityOnSizing = true; setWidth(150); } public String getButtonCaption() { return buttonCaption; } public void setButtonCaption(String buttonCaption) { this.buttonCaption = buttonCaption; } /** * A comma-separated list of content types that a server processing this form will handle correctly. * * @return The comma-separated list of content types. */ public String getAccept() { if (rendered) { return getFileInput().getAccept(); } return accept; } /** * A comma-separated list of content types that a server processing this form will handle correctly. * * @param accept * The comma-separated list of content types. */ public void setAccept(String accept) { this.accept = accept; if (rendered) { getFileInput().setAccept(accept); } } /** * Returns the button icon. * * @return The button icon. */ public AbstractImagePrototype getButtonIconStyle() { return buttonIcon; } /** * Sets the button icon. * * @param buttonIcon * The button icon. */ public void setButtonIcon(AbstractImagePrototype buttonIcon) { this.buttonIcon = buttonIcon; } /** * Returns the file input element. You should not store a reference to this. When resetting this field the file input * will change. * * @return The underlying input element. */ public InputElement getFileInput() { return (InputElement) file.dom.cast(); } /** * Callback executed on {@code OnChange} event. */ private void onChange() { setValue(getFileInput().getValue()); } /** * Creates the underlying file input. */ private void createFileInput() { if (file != null) { el().removeChild(file.dom); } final InputElement fileElement = Document.get().createFileInputElement(); file = new El((Element) fileElement.cast()); file.addEventsSunk(Event.ONCHANGE | Event.FOCUSEVENTS); file.setId(XDOM.getUniqueId()); file.addStyleName("x-form-file"); file.setTabIndex(-1); getFileInput().setName(name); getFileInput().setAccept(accept); file.insertInto(getElement(), 1); if (file != null) { file.setEnabled(isEnabled()); } } // ------------------------------------------------------------------------------------------- // // Loadable implementation. // // ------------------------------------------------------------------------------------------- /** * {@inheritDoc} */ @Override public void setLoading(boolean loading) { button.setLoading(loading); } /** * {@inheritDoc} */ @Override public boolean isLoading() { return button.isLoading(); } // ------------------------------------------------------------------------------------------- // // TextField overridden methods. // // ------------------------------------------------------------------------------------------- /** * {@inheritDoc} */ @Override public String getName() { if (rendered) { final String n = file.dom.getAttribute("name"); if (!n.equals("")) { return n; } } return super.getName(); } /** * {@inheritDoc} */ @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if ((event.getTypeInt() != Event.ONCLICK) && ((Element) event.getEventTarget().cast()).isOrHasChild(file.dom)) { button.onBrowserEvent(event); } } /** * {@inheritDoc} */ @Override public void onComponentEvent(ComponentEvent ce) { super.onComponentEvent(ce); switch (ce.getEventTypeInt()) { case Event.ONCHANGE: onChange(); break; } } /** * {@inheritDoc} */ @Override public void reset() { super.reset(); createFileInput(); } /** * {@inheritDoc} */ @Override public void setName(String name) { this.name = name; if (rendered) { file.dom.removeAttribute("name"); if (name != null) { ((InputElement) file.dom.cast()).setName(name); } } } /** * {@inheritDoc} */ @Override public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; if (button != null) { button.setEnabled(!readOnly); } if (file != null) { file.setEnabled(!readOnly); } } /** * {@inheritDoc} */ @Override protected void afterRender() { super.afterRender(); el().removeStyleName(fieldStyle); } /** * {@inheritDoc} */ @Override protected void doAttachChildren() { super.doAttachChildren(); ComponentHelper.doAttach(button); } /** * {@inheritDoc} */ @Override protected void doDetachChildren() { super.doDetachChildren(); ComponentHelper.doDetach(button); } /** * {@inheritDoc} */ @Override protected El getFocusEl() { return el(); } /** * {@inheritDoc} */ @Override protected El getInputEl() { return el(); } /** * {@inheritDoc} */ @Override protected El getStyleEl() { return el(); } /** * {@inheritDoc} */ @Override protected void onBlur(ComponentEvent ce) { final Rectangle rec = button.el().getBounds(); if (rec.contains(BaseEventPreview.getLastXY())) { ce.stopEvent(); return; } super.onBlur(ce); focusPreview.remove(); } /** * {@inheritDoc} */ @Override protected void onDetach() { super.onDetach(); if (focusPreview != null) { focusPreview.remove(); } } /** * {@inheritDoc} */ @Override protected void onFocus(ComponentEvent ce) { focusPreview.add(); } /** * {@inheritDoc} */ @Override protected void onRender(Element target, int index) { final El wrap = new El(DOM.createDiv()); wrap.addStyleName("x-form-field-wrap"); wrap.addStyleName("x-form-file-wrap"); setElement(wrap.dom, target, index); createFileInput(); button = Forms.button(buttonCaption != null ? buttonCaption : "..."); button.addStyleName("x-form-file-btn"); button.setIcon(buttonIcon); button.render(wrap.dom); super.onRender(target, index); super.setReadOnly(true); } /** * {@inheritDoc} */ @Override protected void onResize(int width, int height) { super.onResize(width, height); el().setWidth(button.getWidth()); } }