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.ade.containerpage.client.ui;
029
030import org.opencms.ade.containerpage.client.CmsContainerpageController;
031import org.opencms.ade.containerpage.shared.CmsContainerElement;
032import org.opencms.ade.containerpage.shared.CmsElementLockInfo;
033import org.opencms.gwt.client.dnd.CmsDNDHandler.Orientation;
034import org.opencms.gwt.client.dnd.I_CmsDraggable;
035import org.opencms.gwt.client.dnd.I_CmsDropTarget;
036import org.opencms.gwt.client.ui.CmsHighlightingBorder;
037import org.opencms.gwt.client.util.CmsDomUtil;
038import org.opencms.gwt.client.util.CmsPositionBean;
039import org.opencms.util.CmsUUID;
040
041import java.util.ArrayList;
042import java.util.Collections;
043import java.util.Iterator;
044import java.util.List;
045
046import com.google.gwt.dom.client.Element;
047import com.google.gwt.dom.client.Style.Display;
048import com.google.gwt.dom.client.Style.Unit;
049import com.google.gwt.user.client.ui.RootPanel;
050import com.google.gwt.user.client.ui.Widget;
051
052/**
053 * Group-container element. To be used for content elements within a container-page.<p>
054 * The group-container acts as a draggable element and if edited as a container.<p>
055 *
056 * @since 8.0.0
057 */
058public class CmsGroupContainerElementPanel extends CmsContainerPageElementPanel implements I_CmsDropContainer {
059
060    /** Processed children of the group. */
061    private List<CmsContainerPageElementPanel> m_children;
062
063    /** The container type. */
064    private String m_containerId;
065
066    /** The editing marker. Used to highlight the container background while editing. */
067    private Element m_editingMarker;
068
069    /** The editing placeholder. Used within group-container editing. */
070    private Element m_editingPlaceholder;
071
072    /** The cached highlighting position. */
073    private CmsPositionBean m_ownPosition;
074
075    /** The placeholder element. */
076    private Element m_placeholder;
077
078    /** The index of the current placeholder position. */
079    private int m_placeholderIndex = -1;
080
081    /** The resource type name. */
082    private String m_resourceType;
083
084    /**
085     * Constructor.<p>
086     *
087     * @param element the DOM element
088     * @param parent the drag parent
089     * @param clientId the client id
090     * @param sitePath the element site-path
091     * @param resourceType the resource type name
092     * @param noEditReason the no edit reason, if empty, editing is allowed
093     * @param title the resource title
094     * @param subTitle the sub title
095     * @param hasSettings should be true if the element has settings which can be edited
096     * @param hasViewPermission indicates if the current user has view permissions on the element resource
097     * @param hasWritePermission indicates if the current user has write permissions on the element resource
098     * @param releasedAndNotExpired <code>true</code> if the element resource is currently released and not expired
099     * @param elementView the element view of the element
100     * @param iconClasses the resource type icon CSS classes
101     */
102    public CmsGroupContainerElementPanel(
103        Element element,
104        I_CmsDropContainer parent,
105        String clientId,
106        String sitePath,
107        String resourceType,
108        String noEditReason,
109        String title,
110        String subTitle,
111        boolean hasSettings,
112        boolean hasViewPermission,
113        boolean hasWritePermission,
114        boolean releasedAndNotExpired,
115        CmsUUID elementView,
116        String iconClasses) {
117
118        super(
119            element,
120            parent,
121            clientId,
122            sitePath,
123            noEditReason,
124            new CmsElementLockInfo(null, false),
125            title,
126            subTitle,
127            resourceType,
128            hasSettings,
129            hasViewPermission,
130            hasWritePermission,
131            releasedAndNotExpired,
132            true,
133            false,
134            null,
135            false,
136            elementView,
137            iconClasses);
138        m_resourceType = resourceType;
139    }
140
141    /**
142     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#addDndChild(org.opencms.gwt.client.dnd.I_CmsDropTarget)
143     */
144    public void addDndChild(I_CmsDropTarget child) {
145
146        throw new UnsupportedOperationException("Element groups do not support nested containers");
147    }
148
149    /**
150     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#adoptElement(org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel)
151     */
152    public void adoptElement(CmsContainerPageElementPanel containerElement) {
153
154        assert getElement().equals(containerElement.getElement().getParentElement());
155        getChildren().add(containerElement);
156        adopt(containerElement);
157    }
158
159    /**
160     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#checkMaxElementsOnEnter()
161     */
162    public void checkMaxElementsOnEnter() {
163
164        // TODO: implement
165
166    }
167
168    /**
169     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#checkMaxElementsOnLeave()
170     */
171    public void checkMaxElementsOnLeave() {
172
173        // TODO: implement
174
175    }
176
177    /**
178     * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#checkPosition(int, int, Orientation)
179     */
180    public boolean checkPosition(int x, int y, Orientation orientation) {
181
182        // ignore orientation
183        int scrollTop = getElement().getOwnerDocument().getScrollTop();
184        // use cached position
185        int relativeTop = (y + scrollTop) - m_ownPosition.getTop();
186        if ((relativeTop > 0) && (m_ownPosition.getHeight() > relativeTop)) {
187            // cursor is inside the height of the element, check horizontal position
188            int scrollLeft = getElement().getOwnerDocument().getScrollLeft();
189            int relativeLeft = (x + scrollLeft) - m_ownPosition.getLeft();
190            return (relativeLeft > 0) && (m_ownPosition.getWidth() > relativeLeft);
191        }
192        return false;
193    }
194
195    /**
196     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#clearDnDChildren()
197     */
198    public void clearDnDChildren() {
199
200        // nothing todo
201    }
202
203    /**
204     * Clears the editing placeholder reference.<p>
205     */
206    public void clearEditingPlaceholder() {
207
208        m_editingPlaceholder = null;
209        m_editingMarker = null;
210    }
211
212    /**
213     * Returns the container id.<p>
214     *
215     * @return the container id
216     */
217    public String getContainerId() {
218
219        return m_containerId;
220    }
221
222    /**
223     * @see org.opencms.gwt.client.dnd.I_CmsNestedDropTarget#getDnDChildren()
224     */
225    public List<I_CmsDropTarget> getDnDChildren() {
226
227        return null;
228    }
229
230    /**
231     * Gets the consumed group elements.<p>
232     *
233     * @return the list of children
234     */
235    public List<CmsContainerPageElementPanel> getGroupChildren() {
236
237        if (m_children == null) {
238            // can happen when saving element groups
239            return Collections.emptyList();
240        }
241        return m_children;
242    }
243
244    /**
245     * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#getPlaceholderIndex()
246     */
247    public int getPlaceholderIndex() {
248
249        return m_placeholderIndex;
250    }
251
252    /**
253     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#getPositionInfo()
254     */
255    public CmsPositionBean getPositionInfo() {
256
257        return m_ownPosition;
258    }
259
260    /**
261     * @see org.opencms.gwt.client.dnd.I_CmsNestedDropTarget#hasDnDChildren()
262     */
263    public boolean hasDnDChildren() {
264
265        return false;
266    }
267
268    /**
269     * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#hideEditableListButtons()
270     */
271    @Override
272    public void hideEditableListButtons() {
273
274        Iterator<Widget> it = iterator();
275        while (it.hasNext()) {
276            Widget child = it.next();
277            if (child instanceof CmsContainerPageElementPanel) {
278                ((CmsContainerPageElementPanel)child).hideEditableListButtons();
279            }
280        }
281    }
282
283    /**
284     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#highlightContainer()
285     */
286    public void highlightContainer() {
287
288        highlightContainer(CmsPositionBean.getBoundingClientRect(getElement()));
289    }
290
291    /**
292     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#highlightContainer(org.opencms.gwt.client.util.CmsPositionBean)
293     */
294    public void highlightContainer(CmsPositionBean positionInfo) {
295
296        // remove any remaining highlighting
297        if (m_highlighting != null) {
298            m_highlighting.removeFromParent();
299        }
300        // cache the position info, to be used during drag and drop
301        m_ownPosition = positionInfo;
302        if (m_editingPlaceholder != null) {
303            m_editingPlaceholder.getStyle().setHeight(m_ownPosition.getHeight() + 10, Unit.PX);
304        }
305        if (m_editingMarker != null) {
306            m_editingMarker.getStyle().setHeight(m_ownPosition.getHeight() + 4, Unit.PX);
307            m_editingMarker.getStyle().setWidth(m_ownPosition.getWidth() + 4, Unit.PX);
308        }
309        m_highlighting = new CmsHighlightingBorder(m_ownPosition, CmsHighlightingBorder.BorderColor.red);
310        RootPanel.get().add(m_highlighting);
311    }
312
313    /**
314     * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#initInlineEditor(org.opencms.ade.containerpage.client.CmsContainerpageController)
315     */
316    @Override
317    public void initInlineEditor(CmsContainerpageController controller) {
318
319        // don to anything
320    }
321
322    /**
323     * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#insertPlaceholder(com.google.gwt.dom.client.Element, int, int, Orientation)
324     */
325    public void insertPlaceholder(Element placeholder, int x, int y, Orientation orientation) {
326
327        m_placeholderIndex = -1;
328        m_placeholder = placeholder;
329        m_placeholder.getStyle().setDisplay(Display.NONE);
330        repositionPlaceholder(x, y, orientation);
331    }
332
333    /**
334     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#isDetailOnly()
335     */
336    public boolean isDetailOnly() {
337
338        return false;
339    }
340
341    /**
342     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#isDetailView()
343     */
344    public boolean isDetailView() {
345
346        return false;
347    }
348
349    /**
350     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#isEditable()
351     */
352    public boolean isEditable() {
353
354        return hasWritePermission();
355    }
356
357    /**
358     * Returns if this element represents a group container.<p>
359     *
360     * @return <code>true</code> if this element represents a group container
361     */
362    public boolean isGroupContainer() {
363
364        return CmsContainerElement.GROUP_CONTAINER_TYPE_NAME.equals(m_resourceType);
365    }
366
367    /**
368     * Returns if this element represents an inherit container.<p>
369     *
370     * @return <code>true</code> if this element represents an inherit container
371     */
372    public boolean isInheritContainer() {
373
374        return CmsContainerElement.INHERIT_CONTAINER_TYPE_NAME.equals(m_resourceType);
375    }
376
377    /**
378     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#onConsumeChildren(java.util.List)
379     */
380    public void onConsumeChildren(List<CmsContainerPageElementPanel> children) {
381
382        m_children = new ArrayList<CmsContainerPageElementPanel>(children);
383    }
384
385    /**
386     * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#onDrop(org.opencms.gwt.client.dnd.I_CmsDraggable)
387     */
388    public void onDrop(I_CmsDraggable draggable) {
389
390        // nothing to do
391
392    }
393
394    /**
395     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#refreshHighlighting()
396     */
397    public void refreshHighlighting() {
398
399        refreshHighlighting(CmsPositionBean.getBoundingClientRect(getElement()));
400    }
401
402    /**
403     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#refreshHighlighting(org.opencms.gwt.client.util.CmsPositionBean)
404     */
405    public void refreshHighlighting(CmsPositionBean positionInfo) {
406
407        m_ownPosition = positionInfo;
408        if (m_editingPlaceholder != null) {
409            m_editingPlaceholder.getStyle().setHeight(m_ownPosition.getHeight() + 10, Unit.PX);
410        }
411        if (m_editingMarker != null) {
412            m_editingMarker.getStyle().setHeight(m_ownPosition.getHeight() + 4, Unit.PX);
413            m_editingMarker.getStyle().setWidth(m_ownPosition.getWidth() + 4, Unit.PX);
414        }
415        if (m_highlighting != null) {
416            m_highlighting.setPosition(m_ownPosition);
417        }
418    }
419
420    /**
421     * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#removeHighlighting()
422     */
423    @Override
424    public void removeHighlighting() {
425
426        if (m_highlighting != null) {
427            m_highlighting.removeFromParent();
428            m_highlighting = null;
429        }
430    }
431
432    /**
433     * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#removePlaceholder()
434     */
435    public void removePlaceholder() {
436
437        if (m_placeholder != null) {
438            m_placeholder.removeFromParent();
439            m_placeholder = null;
440        }
441        m_placeholderIndex = -1;
442    }
443
444    /**
445     * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#repositionPlaceholder(int, int, Orientation)
446     */
447    public void repositionPlaceholder(int x, int y, Orientation orientation) {
448
449        int oldIndex = m_placeholderIndex;
450        switch (orientation) {
451            case HORIZONTAL:
452                m_placeholderIndex = CmsDomUtil.positionElementInside(
453                    m_placeholder,
454                    getElement(),
455                    m_placeholderIndex,
456                    x,
457                    -1);
458                break;
459            case VERTICAL:
460                m_placeholderIndex = CmsDomUtil.positionElementInside(
461                    m_placeholder,
462                    getElement(),
463                    m_placeholderIndex,
464                    -1,
465                    y);
466                break;
467            case ALL:
468            default:
469                m_placeholderIndex = CmsDomUtil.positionElementInside(
470                    m_placeholder,
471                    getElement(),
472                    m_placeholderIndex,
473                    x,
474                    y);
475                break;
476        }
477        if (oldIndex != m_placeholderIndex) {
478            m_ownPosition = CmsPositionBean.getBoundingClientRect(getElement());
479        }
480    }
481
482    /**
483     * Sets the container id.<p>
484     *
485     * @param containerId the container id to set
486     */
487    public void setContainerId(String containerId) {
488
489        m_containerId = containerId;
490    }
491
492    /**
493     * Sets the editing marker. Used to highlight the container background while editing.<p>
494     *
495     * @param editingMarker the editing marker element
496     */
497    public void setEditingMarker(Element editingMarker) {
498
499        m_editingMarker = editingMarker;
500    }
501
502    /**
503     * Sets the editing placeholder.<p>
504     *
505     * @param editingPlaceholder the editing placeholder element
506     */
507    public void setEditingPlaceholder(Element editingPlaceholder) {
508
509        m_editingPlaceholder = editingPlaceholder;
510    }
511
512    /**
513     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#setPlaceholderVisibility(boolean)
514     */
515    public void setPlaceholderVisibility(boolean visible) {
516
517        if (visible) {
518            m_placeholder.getStyle().clearDisplay();
519        } else {
520            m_placeholder.getStyle().setDisplay(Display.NONE);
521        }
522    }
523
524    /**
525     * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#showEditableListButtons()
526     */
527    @Override
528    public void showEditableListButtons() {
529
530        Iterator<Widget> it = iterator();
531        while (it.hasNext()) {
532            Widget child = it.next();
533            if (child instanceof CmsContainerPageElementPanel) {
534                ((CmsContainerPageElementPanel)child).showEditableListButtons();
535            }
536        }
537    }
538
539    /**
540     * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#updateOptionBarPosition()
541     */
542    @Override
543    public void updateOptionBarPosition() {
544
545        for (Widget widget : this) {
546            if (widget instanceof CmsContainerPageElementPanel) {
547                ((CmsContainerPageElementPanel)widget).updateOptionBarPosition();
548            }
549        }
550    }
551
552    /**
553     * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#updatePositionInfo()
554     */
555    public void updatePositionInfo() {
556
557        m_ownPosition = CmsPositionBean.getBoundingClientRect(getElement());
558    }
559}