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.ui.I_CmsButton;
031import org.opencms.gwt.client.ui.I_CmsTruncable;
032import org.opencms.gwt.client.ui.css.I_CmsInputCss;
033import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle;
034import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
035import org.opencms.gwt.client.ui.input.form.CmsFieldTooltip.Data;
036import org.opencms.util.CmsStringUtil;
037
038import java.util.Arrays;
039import java.util.List;
040
041import com.google.common.base.Supplier;
042import com.google.common.base.Suppliers;
043import com.google.gwt.core.client.GWT;
044import com.google.gwt.dom.client.Style.Unit;
045import com.google.gwt.event.dom.client.ClickEvent;
046import com.google.gwt.event.dom.client.ClickHandler;
047import com.google.gwt.event.dom.client.MouseOutEvent;
048import com.google.gwt.event.dom.client.MouseOutHandler;
049import com.google.gwt.event.dom.client.MouseOverEvent;
050import com.google.gwt.event.dom.client.MouseOverHandler;
051import com.google.gwt.uibinder.client.UiBinder;
052import com.google.gwt.uibinder.client.UiField;
053import com.google.gwt.user.client.ui.Composite;
054import com.google.gwt.user.client.ui.Label;
055import com.google.gwt.user.client.ui.Panel;
056import com.google.gwt.user.client.ui.Widget;
057
058/**
059 * A row in a properties form.<p>
060 *
061 * This widget contains both a label and a panel into which an input widget for the form field can be placed.
062 * These widgets are next to each other horizontally.
063 *
064 * @since 8.0.0
065 */
066public class CmsFormRow extends Composite implements I_CmsTruncable {
067
068    /** The ui binder interface for this widget. */
069    protected interface I_CmsFormRowUiBinder extends UiBinder<Widget, CmsFormRow> {
070        // uibinder
071    }
072
073    /** The width of the label. */
074    public static final int LABEL_WIDTH = 160;
075
076    /** The width of the opener. */
077    public static final int OPENER_WIDTH = 16;
078
079    /** The default widget container width. */
080    public static final int WIDGET_CONTAINER_WIDTH = 370;
081
082    /** The required right margin. */
083    public static final int WIDGET_MARGIN_RIGHT = 15;
084
085    /** The CSS bundle used for this widget. */
086    protected static I_CmsInputCss CSS = I_CmsInputLayoutBundle.INSTANCE.inputCss();
087
088    /** The ui binder instance for this form row. */
089    private static I_CmsFormRowUiBinder uiBinder = GWT.create(I_CmsFormRowUiBinder.class);
090
091    /** List of style names for the help icon. */
092    public static List<String> ICON_STYLES = Arrays.asList(
093        I_CmsButton.ICON_FONT,
094        I_CmsButton.ICON_CIRCLE_HELP,
095        I_CmsLayoutBundle.INSTANCE.buttonCss().cmsFontIconButton(),
096        I_CmsLayoutBundle.INSTANCE.buttonCss().hoverBlack(),
097        I_CmsLayoutBundle.INSTANCE.buttonCss().helpIcon());
098
099    /** The label used for displaying the information icon. */
100    @UiField
101    protected Panel m_icon;
102
103    /** The label for the form row. */
104    @UiField
105    protected Label m_label;
106
107    /** The widget container for the form row. */
108    @UiField
109    protected Panel m_widgetContainer;
110
111    /**
112     * The default constructor.
113     */
114    public CmsFormRow() {
115
116        Widget main = uiBinder.createAndBindUi(this);
117        initWidget(main);
118        main.addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().highTextBoxes());
119    }
120
121    /**
122     * Returns the width of the label as a string.<p>
123     *
124     * @return the width of the label as a string
125     */
126    public static String getLabelWidth() {
127
128        return LABEL_WIDTH + "px";
129    }
130
131    /**
132     * Returns the width of the opener as a string.<p>
133     *
134     * @return the width of the opener as a string
135     */
136    public static String getOpenerWidth() {
137
138        return OPENER_WIDTH + "px";
139    }
140
141    /**
142     * Returns the left margin of the widget container as a string.<p>
143     *
144     * @return the left margin of the widget container as a string
145     */
146    public static String getWidgetContainerLeftMargin() {
147
148        return OPENER_WIDTH + LABEL_WIDTH + "px";
149    }
150
151    /**
152     * Returns the left margin of the widget container as a string.<p>
153     *
154     * @return the left margin of the widget container as a string
155     */
156    public static String getWidgetContainerWidth() {
157
158        return WIDGET_CONTAINER_WIDTH + "px";
159    }
160
161    /**
162     * Installs the DOM event handlers for displaying tooltips on a help icon.<p>
163     *
164     * The supplier passed in should not create a new tooltip data instance each time,
165     * but cache the different possible tooltip data instances.
166     *
167     * @param icon the help icon
168     * @param dataSupplier provides the tooltip data at the time the DOM events occur
169     */
170    public static void installTooltipEventHandlers(final Panel icon, final Supplier<Data> dataSupplier) {
171
172        icon.addDomHandler(new MouseOverHandler() {
173
174            public void onMouseOver(MouseOverEvent event) {
175
176                CmsFieldTooltip.getHandler().buttonHover(dataSupplier.get());
177            }
178        }, MouseOverEvent.getType());
179
180        icon.addDomHandler(new MouseOutHandler() {
181
182            public void onMouseOut(MouseOutEvent event) {
183
184                CmsFieldTooltip.getHandler().buttonOut(dataSupplier.get());
185            }
186
187        }, MouseOutEvent.getType());
188
189        icon.addDomHandler(new ClickHandler() {
190
191            public void onClick(ClickEvent event) {
192
193                CmsFieldTooltip.getHandler().buttonClick(dataSupplier.get());
194
195            }
196        }, ClickEvent.getType());
197    }
198
199    /**
200     * Gets the icon.<p>
201     *
202     * @return the icon
203     */
204    public Panel getIcon() {
205
206        return m_icon;
207    }
208
209    /**
210     * Returns the label for the form row.<p>
211     *
212     * @return the label for the form row
213     */
214    public Label getLabel() {
215
216        return m_label;
217    }
218
219    /**
220     * Returns the widget container for the form row.<p>
221     *
222     * @return the widget container for the form row
223     */
224    public Panel getWidgetContainer() {
225
226        return m_widgetContainer;
227    }
228
229    /**
230     * Initializes the style for the info button.<p>
231     */
232    public void initInfoStyle() {
233
234        m_icon.addStyleName(I_CmsButton.ICON_FONT);
235        m_icon.addStyleName(I_CmsButton.ICON_CIRCLE_HELP);
236        m_icon.addStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsFontIconButton());
237        m_icon.addStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().hoverBlack());
238        m_icon.addStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().helpIcon());
239    }
240
241    /**
242     * Shows the info icon and sets the information text as its title.<p>
243     *
244     * @param info the info
245     * @param isHtml true if info should be interpreted as HTML rather than plain text
246     */
247    public void setInfo(final String info, final boolean isHtml) {
248
249        if (info != null) {
250            if (!CmsStringUtil.isEmptyOrWhitespaceOnly(info)) {
251                initInfoStyle();
252                final Data tooltipData = new CmsFieldTooltip.Data(m_icon, info, isHtml);
253                final Panel icon = m_icon;
254                final Supplier<Data> dataSupplier = Suppliers.ofInstance(tooltipData);
255                installTooltipEventHandlers(icon, dataSupplier);
256            }
257        }
258    }
259
260    /**
261     * @see org.opencms.gwt.client.ui.I_CmsTruncable#truncate(java.lang.String, int)
262     */
263    public void truncate(String textMetricsKey, int clientWidth) {
264
265        if (clientWidth > (WIDGET_CONTAINER_WIDTH + OPENER_WIDTH + LABEL_WIDTH + WIDGET_MARGIN_RIGHT)) {
266            int availableWidth = clientWidth - OPENER_WIDTH - WIDGET_MARGIN_RIGHT;
267            int widgetContainerWidth = (int)Math.round(
268                1.00 * availableWidth * ((1.00 + WIDGET_CONTAINER_WIDTH) / (WIDGET_CONTAINER_WIDTH + LABEL_WIDTH)));
269            int labelWidth = availableWidth - widgetContainerWidth;
270            m_label.setWidth(labelWidth + "px");
271            m_widgetContainer.setWidth(widgetContainerWidth + "px");
272            m_widgetContainer.getElement().getStyle().setMarginLeft(labelWidth + OPENER_WIDTH, Unit.PX);
273            for (Widget widget : m_widgetContainer) {
274                if (widget instanceof I_CmsTruncable) {
275                    ((I_CmsTruncable)widget).truncate(textMetricsKey, widgetContainerWidth);
276                }
277            }
278        }
279    }
280
281}