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;
029
030import org.opencms.gwt.client.CmsCoreProvider;
031import org.opencms.gwt.client.Messages;
032import org.opencms.gwt.client.ui.CmsPushButton;
033import org.opencms.gwt.client.ui.I_CmsAutoHider;
034import org.opencms.gwt.client.ui.I_CmsButton;
035import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
036import org.opencms.gwt.client.ui.I_CmsButton.Size;
037import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry;
038import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory;
039import org.opencms.gwt.shared.CmsLinkBean;
040import org.opencms.util.CmsStringUtil;
041
042import java.util.List;
043import java.util.Map;
044
045import com.google.common.base.Optional;
046import com.google.gwt.core.client.GWT;
047import com.google.gwt.dom.client.Style;
048import com.google.gwt.dom.client.Style.Cursor;
049import com.google.gwt.dom.client.Style.Position;
050import com.google.gwt.dom.client.Style.Unit;
051import com.google.gwt.dom.client.Style.Visibility;
052import com.google.gwt.event.dom.client.ClickEvent;
053import com.google.gwt.event.dom.client.ClickHandler;
054import com.google.gwt.uibinder.client.UiBinder;
055import com.google.gwt.uibinder.client.UiField;
056import com.google.gwt.user.client.ui.Composite;
057import com.google.gwt.user.client.ui.HorizontalPanel;
058import com.google.gwt.user.client.ui.Panel;
059
060/**
061 * Widget for selecting an internal or external link.<p>
062 *
063 * @since 8.0.0
064 */
065public class CmsLinkSelector extends Composite implements I_CmsFormWidget, I_CmsHasGhostValue {
066
067    /**
068     * The UI Binder interface for this widget.<p>
069     */
070    protected interface I_CmsLinkSelectorUiBinder extends UiBinder<Panel, CmsLinkSelector> {
071        // binder interface
072    }
073
074    /** The widget type. */
075    public static final String WIDGET_TYPE = "link";
076
077    /** The ui binder for this widget. */
078    private static I_CmsLinkSelectorUiBinder uibinder = GWT.create(I_CmsLinkSelectorUiBinder.class);
079
080    /** The button for editing the link. */
081    @UiField
082    protected CmsPushButton m_editButton;
083
084    /** The check box for setting the link to external or internal. */
085    @UiField
086    protected CmsCheckBox m_externalCheckbox;
087
088    /** The row containing the input field and the gallery edit button. */
089    @UiField
090    protected HorizontalPanel m_inputRow;
091
092    /** The text box containing the current link. */
093    @UiField
094    protected CmsTextBox m_textbox;
095
096    /** The HTML id of the field. */
097    private String m_id;
098
099    /** True if the widget is in "internal" mode. */
100    private boolean m_internal;
101
102    /**
103     * Constructs a new gallery widget.<p>
104     */
105    public CmsLinkSelector() {
106
107        initWidget(uibinder.createAndBindUi(this));
108        m_id = m_textbox.getId();
109        String label = Messages.get().key(Messages.GUI_LINK_CHECKBOX_EXTERNAL_0);
110        m_externalCheckbox.setText(label);
111        m_inputRow.setCellWidth(m_textbox.getTextBox(), "330px");
112        m_editButton.setButtonStyle(ButtonStyle.FONT_ICON, null);
113        m_editButton.setImageClass(I_CmsButton.PEN_SMALL);
114        m_editButton.addClickHandler(new ClickHandler() {
115
116            public void onClick(ClickEvent event) {
117
118                openGalleryDialog();
119            }
120        });
121        m_externalCheckbox.addClickHandler(new ClickHandler() {
122
123            public void onClick(ClickEvent event) {
124
125                userChangedExternal(m_externalCheckbox.isChecked());
126            }
127        });
128        setInternal(false);
129    }
130
131    /**
132     * Initializes this class.<p>
133     */
134    public static void initClass() {
135
136        // registers a factory for creating new instances of this widget
137        CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() {
138
139            /**
140             * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional)
141             */
142            public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) {
143
144                return new CmsLinkSelector();
145            }
146        });
147    }
148
149    /**
150     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue()
151     */
152    public String getApparentValue() {
153
154        return getFormValueAsString();
155    }
156
157    /**
158     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFieldType()
159     */
160    public FieldType getFieldType() {
161
162        return FieldType.STRING;
163    }
164
165    /**
166     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValue()
167     */
168    public Object getFormValue() {
169
170        return m_textbox.getFormValue();
171    }
172
173    /**
174     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValueAsString()
175     */
176    public String getFormValueAsString() {
177
178        String link = m_textbox.getFormValueAsString();
179        return m_internal + "|" + link;
180    }
181
182    /**
183     * Returns the selected link target string.<p>
184     *
185     * @return the link target string
186     */
187    public String getLink() {
188
189        return m_textbox.getFormValueAsString();
190    }
191
192    /**
193     * Returns the selected link as a bean.<p>
194     *
195     * @return the selected link as a bean
196     */
197    public CmsLinkBean getLinkBean() {
198
199        String link = m_textbox.getText();
200        if (CmsStringUtil.isEmptyOrWhitespaceOnly(link)) {
201            return null;
202        }
203        return new CmsLinkBean(m_textbox.getText(), m_internal);
204    }
205
206    /**
207     * Returns the text box of this widget.<p>
208     *
209     * @return the CmsTextBox.
210     */
211    public CmsTextBox getTextBox() {
212
213        return m_textbox;
214    }
215
216    /**
217     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#isEnabled()
218     */
219    public boolean isEnabled() {
220
221        return !m_textbox.isReadOnly();
222    }
223
224    /**
225     * Returns true if the widget is in internal mode.
226     *
227     * @return true if the widget is in internal mode
228     */
229    public boolean isInternal() {
230
231        return m_internal;
232    }
233
234    /**
235     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#reset()
236     */
237    public void reset() {
238
239        m_textbox.reset();
240    }
241
242    /**
243     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider)
244     */
245    public void setAutoHideParent(I_CmsAutoHider autoHideParent) {
246
247        // do nothing
248    }
249
250    /**
251     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setEnabled(boolean)
252     */
253    public void setEnabled(boolean enabled) {
254
255        m_textbox.setReadOnly(!enabled);
256    }
257
258    /**
259     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setErrorMessage(java.lang.String)
260     */
261    public void setErrorMessage(String errorMessage) {
262
263        // do nothing
264    }
265
266    /**
267     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setFormValueAsString(java.lang.String)
268     */
269    public void setFormValueAsString(String value) {
270
271        boolean internal = true;
272        String link = "";
273
274        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(value)) {
275            List<String> tokens = CmsStringUtil.splitAsList(value, "|");
276            internal = Boolean.parseBoolean(tokens.get(0));
277            link = tokens.get(1);
278        }
279        setInternal(internal);
280        m_textbox.setFormValueAsString(link);
281
282    }
283
284    /**
285     * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostMode(boolean)
286     */
287    public void setGhostMode(boolean ghostMode) {
288
289        m_textbox.setGhostMode(ghostMode);
290    }
291
292    /**
293     * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostValue(java.lang.String, boolean)
294     */
295    public void setGhostValue(String value, boolean isGhostMode) {
296
297        m_textbox.setGhostValue(value, isGhostMode);
298    }
299
300    /**
301     * Sets the widget's mode to internal or external.<p>
302     *
303     * @param internal if true, sets the mode to internal, else to external
304     */
305    public void setInternal(boolean internal) {
306
307        m_internal = internal;
308        m_textbox.setReadOnly(internal);
309        m_editButton.setEnabled(internal);
310        m_editButton.getElement().getStyle().setVisibility(internal ? Visibility.VISIBLE : Visibility.HIDDEN);
311        //m_editButton.setVisible(internal);
312        m_externalCheckbox.setChecked(!internal);
313    }
314
315    /**
316     * Sets the link target.<p>
317     *
318     * @param link the link target
319     */
320    public void setLink(String link) {
321
322        if (link == null) {
323            link = "";
324        }
325        m_textbox.setFormValueAsString(link);
326    }
327
328    /**
329     * Sets the link from a bean.<p>
330     *
331     * @param link the link bean
332     */
333    public void setLinkBean(CmsLinkBean link) {
334
335        if (link == null) {
336            link = new CmsLinkBean("", true);
337        }
338        m_textbox.setFormValueAsString(link.getLink());
339        setInternal(link.isInternal());
340    }
341
342    /**
343     * Sets the name of the input field.<p>
344     *
345     * @param name of the input field
346     * */
347    public void setName(String name) {
348
349        m_textbox.setName(name);
350
351    }
352
353    /**
354     * Creates the URL for the gallery dialog IFrame.<p>
355     *
356     * @return the URL for the gallery dialog IFrame
357     */
358    protected String buildGalleryUrl() {
359
360        String basePath = "/system/workplace/commons/gallery.jsp";
361        return CmsCoreProvider.get().link(basePath + "?dialogmode=widget&fieldid=" + m_id);
362    }
363
364    /**
365     * Internal method which opens the gallery dialog.<p>
366     */
367    protected void openGalleryDialog() {
368
369        String title = org.opencms.gwt.client.Messages.get().key(
370            org.opencms.gwt.client.Messages.GUI_GALLERY_SELECT_DIALOG_TITLE_0);
371        final CmsFramePopup popup = new CmsFramePopup(title, buildGalleryUrl());
372        popup.setCloseHandler(new Runnable() {
373
374            public void run() {
375
376                m_textbox.setGhostMode(false);
377
378            }
379
380        });
381        popup.setId(m_id);
382        popup.getFrame().setSize("700px", "490px");
383        popup.center();
384
385        CmsPushButton button = new CmsPushButton(I_CmsButton.DELETE_SMALL);
386        button.setButtonStyle(ButtonStyle.FONT_ICON, null);
387        button.setSize(Size.small);
388        Style style = button.getElement().getStyle();
389        style.setRight(4, Unit.PX);
390        style.setTop(0, Unit.PX);
391        style.setPosition(Position.ABSOLUTE);
392        style.setCursor(Cursor.POINTER);
393        button.addClickHandler(new ClickHandler() {
394
395            /**
396             * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
397             */
398            public void onClick(ClickEvent event) {
399
400                popup.hide();
401            }
402        });
403
404        popup.insertFront(button);
405    }
406
407    /**
408     * Called if the user changed the state to internal or external.<p>
409     *
410     * @param external if the new state is "external"
411     */
412    protected void userChangedExternal(boolean external) {
413
414        if (!external) {
415            m_textbox.setFormValueAsString("");
416        }
417        setInternal(!external);
418    }
419
420}