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;
029
030import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
031import org.opencms.gwt.client.util.CmsPositionBean;
032import org.opencms.gwt.client.util.CmsStyleVariable;
033
034import com.google.gwt.core.client.GWT;
035import com.google.gwt.dom.client.DivElement;
036import com.google.gwt.dom.client.Element;
037import com.google.gwt.dom.client.Style;
038import com.google.gwt.dom.client.Style.Unit;
039import com.google.gwt.uibinder.client.UiBinder;
040import com.google.gwt.uibinder.client.UiField;
041import com.google.gwt.user.client.Window;
042import com.google.gwt.user.client.ui.Composite;
043import com.google.gwt.user.client.ui.HTML;
044
045/**
046 * A Widget to display a highlighting border around a specified position.<p>
047 *
048 * @since 8.0.0
049 */
050public class CmsHighlightingBorder extends Composite {
051
052    /** Enumeration of available border colours. */
053    public enum BorderColor {
054        /** Color blue. */
055        blue(I_CmsLayoutBundle.INSTANCE.highlightCss().colorBlue()),
056
057        /** Color grey. */
058        grey(I_CmsLayoutBundle.INSTANCE.highlightCss().colorGrey()),
059
060        /** Color red. */
061        red(I_CmsLayoutBundle.INSTANCE.highlightCss().colorRed()),
062
063        /** Solid grey. */
064        solidGrey(I_CmsLayoutBundle.INSTANCE.highlightCss().colorSolidGrey());
065
066        /** CSS class used to display the border colour. */
067        private String m_cssClass;
068
069        /**
070         * Constructor.<p>
071         *
072         * @param cssClass the CSS class to display the border colour
073         */
074        private BorderColor(String cssClass) {
075
076            m_cssClass = cssClass;
077        }
078
079        /**
080         * Returns the associated CSS class.<p>
081         *
082         * @return the CSS class
083         */
084        public String getCssClass() {
085
086            return m_cssClass;
087        }
088    }
089
090    /** The ui-binder interface for this composite. */
091    interface I_CmsHighlightingBorderUiBinder extends UiBinder<HTML, CmsHighlightingBorder> {
092        // GWT interface, nothing to do here
093    }
094
095    /** The default border offset to the given position. */
096    private static final int BORDER_OFFSET = 4;
097
098    /** The border width. */
099    private static final int BORDER_WIDTH = 2;
100
101    /** The ui-binder instance. */
102    private static I_CmsHighlightingBorderUiBinder uiBinder = GWT.create(I_CmsHighlightingBorderUiBinder.class);
103
104    /** The bottom border. */
105    @UiField
106    protected DivElement m_borderBottom;
107
108    /** The left border. */
109    @UiField
110    protected DivElement m_borderLeft;
111
112    /** The right border. */
113    @UiField
114    protected DivElement m_borderRight;
115
116    /** The top border. */
117    @UiField
118    protected DivElement m_borderTop;
119
120    /** The border offset. */
121    private int m_borderOffset;
122
123    /** The style variable used to change the color of the border. */
124    private CmsStyleVariable m_colorVariable;
125
126    /** The positioning parent element. */
127    private Element m_positioningParent;
128
129    /**
130     * Constructor.<p>
131     *
132     * @param position the position data
133     * @param color the border color
134     */
135    public CmsHighlightingBorder(CmsPositionBean position, BorderColor color) {
136
137        this(position.getHeight(), position.getWidth(), position.getLeft(), position.getTop(), color, BORDER_OFFSET);
138    }
139
140    /**
141     * Constructor.<p>
142     *
143     * @param position the position data
144     * @param color the border color
145     * @param borderOffset the border offset
146     */
147    public CmsHighlightingBorder(CmsPositionBean position, BorderColor color, int borderOffset) {
148
149        this(position.getHeight(), position.getWidth(), position.getLeft(), position.getTop(), color, borderOffset);
150    }
151
152    /**
153     * Constructor.<p>
154     *
155     * @param positioningParent the element the border is positioned around, position is set relative to it
156     * @param color the border color
157     */
158    public CmsHighlightingBorder(Element positioningParent, BorderColor color) {
159
160        m_borderOffset = BORDER_OFFSET;
161        initWidget(uiBinder.createAndBindUi(this));
162        m_colorVariable = new CmsStyleVariable(getWidget());
163        m_colorVariable.setValue(color.getCssClass());
164        m_positioningParent = positioningParent;
165        resetPosition();
166    }
167
168    /**
169     * Constructor.<p>
170     *
171     * @param height the height
172     * @param width the width
173     * @param positionLeft the absolute left position
174     * @param positionTop the absolute top position
175     * @param color the border color
176     * @param borderOffset the border offset
177     */
178    public CmsHighlightingBorder(
179        int height,
180        int width,
181        int positionLeft,
182        int positionTop,
183        BorderColor color,
184        int borderOffset) {
185
186        m_borderOffset = borderOffset;
187        initWidget(uiBinder.createAndBindUi(this));
188        m_colorVariable = new CmsStyleVariable(getWidget());
189        m_colorVariable.setValue(color.getCssClass());
190        setPosition(height, width, positionLeft, positionTop);
191    }
192
193    /**
194     * Enables the border animation.<p>
195     * (Is enabled by default)<p>
196     *
197     * @param animated <code>true</code> to enable border animation
198     */
199    public void enableAnimation(boolean animated) {
200
201        if (animated) {
202            addStyleName(I_CmsLayoutBundle.INSTANCE.highlightCss().animated());
203        } else {
204            removeStyleName(I_CmsLayoutBundle.INSTANCE.highlightCss().animated());
205        }
206    }
207
208    /**
209     * Hides the border.<p>
210     */
211    public void hide() {
212
213        setVisible(false);
214    }
215
216    /**
217     * Recalculates the position and dimension when a positioning parent is given.<p>
218     */
219    public void resetPosition() {
220
221        // fail if no positioning parent given
222        assert m_positioningParent != null;
223        if (m_positioningParent != null) {
224            setPosition(m_positioningParent.getOffsetHeight(), m_positioningParent.getOffsetWidth(), 0, 0);
225        }
226    }
227
228    /**
229     * Sets the color of the border.<p>
230     *
231     * @param color the color of the border
232     */
233    public void setColor(BorderColor color) {
234
235        m_colorVariable.setValue(color.getCssClass());
236    }
237
238    /**
239     * Sets the border position.<p>
240     *
241     * @param position the position data
242     */
243    public void setPosition(CmsPositionBean position) {
244
245        setPosition(position.getHeight(), position.getWidth(), position.getLeft(), position.getTop());
246    }
247
248    /**
249     * Sets the border position.<p>
250     *
251     * @param height the height
252     * @param width the width
253     * @param positionLeft the absolute left position
254     * @param positionTop the absolute top position
255     */
256    public void setPosition(int height, int width, int positionLeft, int positionTop) {
257
258        positionLeft -= m_borderOffset;
259
260        // make sure highlighting does not introduce additional horizontal scroll-bars
261        if ((m_positioningParent == null) && (positionLeft < 0)) {
262            // position left should not be negative
263            width += positionLeft;
264            positionLeft = 0;
265        }
266        width += (2 * m_borderOffset) - BORDER_WIDTH;
267        if ((m_positioningParent == null)
268            && (Window.getClientWidth() < (width + positionLeft))
269            && (Window.getScrollLeft() == 0)) {
270            // highlighting should not extend over the right hand
271            width = Window.getClientWidth() - (positionLeft + BORDER_WIDTH);
272        }
273        Style style = getElement().getStyle();
274        style.setLeft(positionLeft, Unit.PX);
275        style.setTop(positionTop - m_borderOffset, Unit.PX);
276        setHeight((height + (2 * m_borderOffset)) - BORDER_WIDTH);
277        setWidth(width);
278    }
279
280    /**
281     * Shows the border.<p>
282     */
283    public void show() {
284
285        setVisible(true);
286    }
287
288    /**
289     * Sets the highlighting height.<p>
290     *
291     * @param height the height
292     */
293    private void setHeight(int height) {
294
295        m_borderRight.getStyle().setHeight(height, Unit.PX);
296        m_borderLeft.getStyle().setHeight(height, Unit.PX);
297        m_borderBottom.getStyle().setTop(height, Unit.PX);
298    }
299
300    /**
301     * Sets the highlighting width.<p>
302     *
303     * @param width the width
304     */
305    private void setWidth(int width) {
306
307        m_borderTop.getStyle().setWidth(width + BORDER_WIDTH, Unit.PX);
308        m_borderBottom.getStyle().setWidth(width + BORDER_WIDTH, Unit.PX);
309        m_borderRight.getStyle().setLeft(width, Unit.PX);
310    }
311
312}