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.gwt.client.ui.input.form;
029
030import org.opencms.gwt.client.Messages;
031import org.opencms.gwt.client.ui.CmsPopup;
032import org.opencms.gwt.client.ui.CmsPushButton;
033import org.opencms.gwt.client.ui.input.I_CmsFormField;
034import org.opencms.gwt.client.util.CmsDomUtil;
035
036import java.util.Map;
037
038import com.google.gwt.core.client.Scheduler;
039import com.google.gwt.core.client.Scheduler.ScheduledCommand;
040import com.google.gwt.dom.client.Element;
041import com.google.gwt.event.dom.client.ClickEvent;
042import com.google.gwt.event.dom.client.ClickHandler;
043import com.google.gwt.event.dom.client.KeyCodes;
044import com.google.gwt.event.logical.shared.CloseEvent;
045import com.google.gwt.event.logical.shared.CloseHandler;
046import com.google.gwt.event.shared.HandlerRegistration;
047import com.google.gwt.user.client.DOM;
048import com.google.gwt.user.client.Event;
049import com.google.gwt.user.client.Event.NativePreviewEvent;
050import com.google.gwt.user.client.Event.NativePreviewHandler;
051import com.google.gwt.user.client.Window;
052import com.google.gwt.user.client.ui.PopupPanel;
053
054/**
055 * A dialog containing a form.<p>
056 *
057 * @since 8.0.0
058 */
059public class CmsFormDialog extends CmsPopup {
060
061    /** The maximum dialog width. */
062    public static final int MAX_DIALOG_WIDTH = 930;
063
064    /** The dialog width. */
065    public static final int STANDARD_DIALOG_WIDTH = 700;
066
067    /** The widget containing the form fields. */
068    protected CmsForm m_form;
069
070    /** The form handler for this dialog. */
071    protected I_CmsFormHandler m_formHandler;
072
073    /** The OK button of this dialog. */
074    private CmsPushButton m_okButton;
075
076    /** The event preview handler registration. */
077    private HandlerRegistration m_previewHandlerRegistration;
078
079    /**
080     * Constructs a new form dialog with a given title.<p>
081     *
082     * @param title the title of the form dialog
083     * @param form the form to use
084     */
085    public CmsFormDialog(String title, CmsForm form) {
086
087        this(title, form, -1);
088    }
089
090    /**
091     * Constructs a new form dialog with a given title.<p>
092     *
093     * @param title the title of the form dialog
094     * @param form the form to use
095     * @param dialogWidthObj the dialog width (if null, don't set any width; if negative, set default width)
096     */
097    public CmsFormDialog(String title, CmsForm form, Integer dialogWidthObj) {
098
099        super(title, -1);
100        setGlassEnabled(true);
101        setAutoHideEnabled(false);
102        setModal(true);
103        // check the available width for this dialog
104
105        if (dialogWidthObj != null) {
106            int dialogWidth = dialogWidthObj.intValue();
107            int windowWidth = Window.getClientWidth();
108            if (dialogWidth > 0) {
109                // reduce the dialog width if necessary
110                if ((windowWidth - 50) < dialogWidth) {
111                    dialogWidth = windowWidth - 50;
112                }
113            } else {
114                dialogWidth = (windowWidth - 100) > STANDARD_DIALOG_WIDTH ? windowWidth - 100 : STANDARD_DIALOG_WIDTH;
115                dialogWidth = dialogWidth > MAX_DIALOG_WIDTH ? MAX_DIALOG_WIDTH : dialogWidth;
116            }
117            setWidth(dialogWidth);
118        }
119        addButton(createCancelButton());
120        m_okButton = createOkButton();
121        addButton(m_okButton);
122        m_form = form;
123
124        addCloseHandler(new CloseHandler<PopupPanel>() {
125
126            public void onClose(CloseEvent<PopupPanel> event) {
127
128                removePreviewHandler();
129            }
130        });
131    }
132
133    /**
134     * @see org.opencms.gwt.client.ui.CmsPopup#center()
135     */
136    @Override
137    public void center() {
138
139        initContent();
140        registerPreviewHandler();
141        super.center();
142        notifyWidgetsOfOpen();
143    }
144
145    /**
146     * Gets the form of this dialog.<p>
147     *
148     * @return the form of this dialog
149     */
150    public CmsForm getForm() {
151
152        return m_form;
153    }
154
155    /**
156     * Returns the 'OK' button.<p>
157     *
158     * @return the 'OK' button
159     */
160    public CmsPushButton getOkButton() {
161
162        return m_okButton;
163    }
164
165    /**
166     * Sets the form handler for this form dialog.<p>
167     *
168     * @param formHandler the new form handler
169     */
170    public void setFormHandler(I_CmsFormHandler formHandler) {
171
172        m_form.setFormHandler(formHandler);
173    }
174
175    /**
176     * Enables/disables the OK button.<p>
177     *
178     * @param enabled if true, enables the OK button, else disables it
179     */
180    public void setOkButtonEnabled(final boolean enabled) {
181
182        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
183
184            /**
185             * @see com.google.gwt.core.client.Scheduler.ScheduledCommand#execute()
186             */
187            public void execute() {
188
189                // The event handling of GWT gets confused if we don't execute this as a scheduled command
190                getOkButton().setDown(false);
191                getOkButton().setEnabled(enabled);
192            }
193        });
194
195    }
196
197    /**
198     * @see org.opencms.gwt.client.ui.CmsPopup#show()
199     */
200    @Override
201    public void show() {
202
203        initContent();
204        registerPreviewHandler();
205        super.show();
206        notifyWidgetsOfOpen();
207    }
208
209    /**
210     * Initializes the form content.<p>
211     */
212    protected void initContent() {
213
214        setMainContent(m_form.getWidget());
215    }
216
217    /**
218     * Called when the cancel button is clicked.
219     */
220    protected void onClickCancel() {
221
222        hide();
223    }
224
225    /**
226     * The method which should be called when the user clicks on the OK button of the dialog.<p>
227     */
228    protected void onClickOk() {
229
230        m_form.validateAndSubmit();
231    }
232
233    /**
234     * Registers the 'Enter' and 'Esc' shortcut action handler.<p>
235     */
236    protected void registerPreviewHandler() {
237
238        if (m_previewHandlerRegistration == null) {
239            NativePreviewHandler eventPreviewHandler = new NativePreviewHandler() {
240
241                public void onPreviewNativeEvent(NativePreviewEvent event) {
242
243                    Event nativeEvent = Event.as(event.getNativeEvent());
244                    if (DOM.eventGetType(nativeEvent) == Event.ONKEYDOWN) {
245                        int keyCode = nativeEvent.getKeyCode();
246                        if (keyCode == KeyCodes.KEY_ESCAPE) {
247                            onClickCancel();
248                        } else if (keyCode == KeyCodes.KEY_ENTER) {
249                            Element element = CmsDomUtil.getActiveElement();
250                            boolean isTextarea = (element != null) && element.getTagName().equalsIgnoreCase("textarea");
251                            if (!isTextarea) {
252                                onClickOk();
253                            }
254                        }
255                    }
256                }
257            };
258            m_previewHandlerRegistration = Event.addNativePreviewHandler(eventPreviewHandler);
259        }
260    }
261
262    /**
263     * Removes the 'Enter' and 'Esc' shortcut action handler.<p>
264     */
265    protected void removePreviewHandler() {
266
267        if (m_previewHandlerRegistration != null) {
268            m_previewHandlerRegistration.removeHandler();
269            m_previewHandlerRegistration = null;
270        }
271    }
272
273    /**
274     * Creates the cancel button.<p>
275     *
276     * @return the cancel button
277     */
278    private CmsPushButton createCancelButton() {
279
280        addDialogClose(null);
281
282        CmsPushButton button = new CmsPushButton();
283        button.setText(Messages.get().key(Messages.GUI_CANCEL_0));
284        button.setUseMinWidth(true);
285        button.addClickHandler(new ClickHandler() {
286
287            /**
288             * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
289             */
290            public void onClick(ClickEvent event) {
291
292                onClickCancel();
293
294            }
295        });
296        return button;
297    }
298
299    /**
300     * Creates the OK button.<p>
301     *
302     * @return the OK button
303     */
304    private CmsPushButton createOkButton() {
305
306        CmsPushButton button = new CmsPushButton();
307        button.setText(Messages.get().key(Messages.GUI_OK_0));
308        button.setUseMinWidth(true);
309        button.addClickHandler(new ClickHandler() {
310
311            /**
312             * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
313             */
314            public void onClick(ClickEvent event) {
315
316                onClickOk();
317            }
318        });
319        return button;
320    }
321
322    /**
323     * Tells all widgets that the dialog has been opened.<p>
324     */
325    private void notifyWidgetsOfOpen() {
326
327        for (Map.Entry<String, I_CmsFormField> fieldEntry : m_form.getFields().entrySet()) {
328            fieldEntry.getValue().getWidget().setAutoHideParent(this);
329        }
330    }
331
332}