001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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 null, 133 true, 134 false, 135 null, 136 false, 137 elementView, 138 iconClasses, 139 false); 140 m_resourceType = resourceType; 141 } 142 143 /** 144 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#addDndChild(org.opencms.gwt.client.dnd.I_CmsDropTarget) 145 */ 146 public void addDndChild(I_CmsDropTarget child) { 147 148 throw new UnsupportedOperationException("Element groups do not support nested containers"); 149 } 150 151 /** 152 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#adoptElement(org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel) 153 */ 154 public void adoptElement(CmsContainerPageElementPanel containerElement) { 155 156 assert getElement().equals(containerElement.getElement().getParentElement()); 157 getChildren().add(containerElement); 158 adopt(containerElement); 159 } 160 161 /** 162 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#checkMaxElementsOnEnter() 163 */ 164 public void checkMaxElementsOnEnter() { 165 166 // TODO: implement 167 168 } 169 170 /** 171 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#checkMaxElementsOnLeave() 172 */ 173 public void checkMaxElementsOnLeave() { 174 175 // TODO: implement 176 177 } 178 179 /** 180 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#checkPosition(int, int, Orientation) 181 */ 182 public boolean checkPosition(int x, int y, Orientation orientation) { 183 184 // ignore orientation 185 int scrollTop = getElement().getOwnerDocument().getScrollTop(); 186 // use cached position 187 int relativeTop = (y + scrollTop) - m_ownPosition.getTop(); 188 if ((relativeTop > 0) && (m_ownPosition.getHeight() > relativeTop)) { 189 // cursor is inside the height of the element, check horizontal position 190 int scrollLeft = getElement().getOwnerDocument().getScrollLeft(); 191 int relativeLeft = (x + scrollLeft) - m_ownPosition.getLeft(); 192 return (relativeLeft > 0) && (m_ownPosition.getWidth() > relativeLeft); 193 } 194 return false; 195 } 196 197 /** 198 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#clearDnDChildren() 199 */ 200 public void clearDnDChildren() { 201 202 // nothing todo 203 } 204 205 /** 206 * Clears the editing placeholder reference.<p> 207 */ 208 public void clearEditingPlaceholder() { 209 210 m_editingPlaceholder = null; 211 m_editingMarker = null; 212 } 213 214 /** 215 * Returns the container id.<p> 216 * 217 * @return the container id 218 */ 219 public String getContainerId() { 220 221 return m_containerId; 222 } 223 224 /** 225 * @see org.opencms.gwt.client.dnd.I_CmsNestedDropTarget#getDnDChildren() 226 */ 227 public List<I_CmsDropTarget> getDnDChildren() { 228 229 return null; 230 } 231 232 /** 233 * Gets the consumed group elements.<p> 234 * 235 * @return the list of children 236 */ 237 public List<CmsContainerPageElementPanel> getGroupChildren() { 238 239 if (m_children == null) { 240 // can happen when saving element groups 241 return Collections.emptyList(); 242 } 243 return m_children; 244 } 245 246 /** 247 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#getPlaceholderIndex() 248 */ 249 public int getPlaceholderIndex() { 250 251 return m_placeholderIndex; 252 } 253 254 /** 255 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#getPositionInfo() 256 */ 257 public CmsPositionBean getPositionInfo() { 258 259 return m_ownPosition; 260 } 261 262 /** 263 * @see org.opencms.gwt.client.dnd.I_CmsNestedDropTarget#hasDnDChildren() 264 */ 265 public boolean hasDnDChildren() { 266 267 return false; 268 } 269 270 /** 271 * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#hideEditableListButtons() 272 */ 273 @Override 274 public void hideEditableListButtons() { 275 276 Iterator<Widget> it = iterator(); 277 while (it.hasNext()) { 278 Widget child = it.next(); 279 if (child instanceof CmsContainerPageElementPanel) { 280 ((CmsContainerPageElementPanel)child).hideEditableListButtons(); 281 } 282 } 283 } 284 285 /** 286 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#highlightContainer(boolean) 287 */ 288 public void highlightContainer(boolean addSeparators) { 289 290 // separators neither needed nor implemented 291 highlightContainer(CmsPositionBean.getBoundingClientRect(getElement()), addSeparators); 292 } 293 294 /** 295 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#highlightContainer(org.opencms.gwt.client.util.CmsPositionBean, boolean) 296 */ 297 public void highlightContainer(CmsPositionBean positionInfo, boolean separators) { 298 // separators neither needed nor implemented 299 300 // remove any remaining highlighting 301 if (m_highlighting != null) { 302 m_highlighting.removeFromParent(); 303 } 304 // cache the position info, to be used during drag and drop 305 m_ownPosition = positionInfo; 306 if (m_editingPlaceholder != null) { 307 m_editingPlaceholder.getStyle().setHeight(m_ownPosition.getHeight() + 10, Unit.PX); 308 } 309 if (m_editingMarker != null) { 310 m_editingMarker.getStyle().setHeight(m_ownPosition.getHeight() + 4, Unit.PX); 311 m_editingMarker.getStyle().setWidth(m_ownPosition.getWidth() + 4, Unit.PX); 312 } 313 m_highlighting = new CmsHighlightingBorder(m_ownPosition, CmsHighlightingBorder.BorderColor.red); 314 RootPanel.get().add(m_highlighting); 315 } 316 317 /** 318 * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#initInlineEditor(org.opencms.ade.containerpage.client.CmsContainerpageController) 319 */ 320 @Override 321 public void initInlineEditor(CmsContainerpageController controller) { 322 323 // don to anything 324 } 325 326 /** 327 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#insertPlaceholder(com.google.gwt.dom.client.Element, int, int, Orientation) 328 */ 329 public void insertPlaceholder(Element placeholder, int x, int y, Orientation orientation) { 330 331 m_placeholderIndex = -1; 332 m_placeholder = placeholder; 333 m_placeholder.getStyle().setDisplay(Display.NONE); 334 repositionPlaceholder(x, y, orientation); 335 } 336 337 /** 338 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#isDetailOnly() 339 */ 340 public boolean isDetailOnly() { 341 342 return false; 343 } 344 345 /** 346 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#isDetailView() 347 */ 348 public boolean isDetailView() { 349 350 return false; 351 } 352 353 /** 354 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#isEditable() 355 */ 356 public boolean isEditable() { 357 358 return hasWritePermission(); 359 } 360 361 /** 362 * Returns if this element represents a group container.<p> 363 * 364 * @return <code>true</code> if this element represents a group container 365 */ 366 public boolean isGroupContainer() { 367 368 return CmsContainerElement.GROUP_CONTAINER_TYPE_NAME.equals(m_resourceType); 369 } 370 371 /** 372 * Returns if this element represents an inherit container.<p> 373 * 374 * @return <code>true</code> if this element represents an inherit container 375 */ 376 public boolean isInheritContainer() { 377 378 return CmsContainerElement.INHERIT_CONTAINER_TYPE_NAME.equals(m_resourceType); 379 } 380 381 /** 382 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#onConsumeChildren(java.util.List) 383 */ 384 public void onConsumeChildren(List<CmsContainerPageElementPanel> children) { 385 386 m_children = new ArrayList<CmsContainerPageElementPanel>(children); 387 } 388 389 /** 390 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#onDrop(org.opencms.gwt.client.dnd.I_CmsDraggable) 391 */ 392 public void onDrop(I_CmsDraggable draggable) { 393 394 // nothing to do 395 396 } 397 398 /** 399 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#refreshHighlighting() 400 */ 401 public void refreshHighlighting() { 402 403 refreshHighlighting(CmsPositionBean.getBoundingClientRect(getElement())); 404 } 405 406 /** 407 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#refreshHighlighting(org.opencms.gwt.client.util.CmsPositionBean) 408 */ 409 public void refreshHighlighting(CmsPositionBean positionInfo) { 410 411 m_ownPosition = positionInfo; 412 if (m_editingPlaceholder != null) { 413 m_editingPlaceholder.getStyle().setHeight(m_ownPosition.getHeight() + 10, Unit.PX); 414 } 415 if (m_editingMarker != null) { 416 m_editingMarker.getStyle().setHeight(m_ownPosition.getHeight() + 4, Unit.PX); 417 m_editingMarker.getStyle().setWidth(m_ownPosition.getWidth() + 4, Unit.PX); 418 } 419 if (m_highlighting != null) { 420 m_highlighting.setPosition(m_ownPosition); 421 } 422 } 423 424 /** 425 * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#removeHighlighting() 426 */ 427 @Override 428 public void removeHighlighting() { 429 430 if (m_highlighting != null) { 431 m_highlighting.removeFromParent(); 432 m_highlighting = null; 433 } 434 } 435 436 /** 437 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#removePlaceholder() 438 */ 439 public void removePlaceholder() { 440 441 if (m_placeholder != null) { 442 m_placeholder.removeFromParent(); 443 m_placeholder = null; 444 } 445 m_placeholderIndex = -1; 446 } 447 448 /** 449 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#repositionPlaceholder(int, int, Orientation) 450 */ 451 public void repositionPlaceholder(int x, int y, Orientation orientation) { 452 453 int oldIndex = m_placeholderIndex; 454 switch (orientation) { 455 case HORIZONTAL: 456 m_placeholderIndex = CmsDomUtil.positionElementInside( 457 m_placeholder, 458 getElement(), 459 m_placeholderIndex, 460 x, 461 -1); 462 break; 463 case VERTICAL: 464 m_placeholderIndex = CmsDomUtil.positionElementInside( 465 m_placeholder, 466 getElement(), 467 m_placeholderIndex, 468 -1, 469 y); 470 break; 471 case ALL: 472 default: 473 m_placeholderIndex = CmsDomUtil.positionElementInside( 474 m_placeholder, 475 getElement(), 476 m_placeholderIndex, 477 x, 478 y); 479 break; 480 } 481 if (oldIndex != m_placeholderIndex) { 482 m_ownPosition = CmsPositionBean.getBoundingClientRect(getElement()); 483 } 484 } 485 486 /** 487 * Sets the container id.<p> 488 * 489 * @param containerId the container id to set 490 */ 491 public void setContainerId(String containerId) { 492 493 m_containerId = containerId; 494 } 495 496 /** 497 * Sets the editing marker. Used to highlight the container background while editing.<p> 498 * 499 * @param editingMarker the editing marker element 500 */ 501 public void setEditingMarker(Element editingMarker) { 502 503 m_editingMarker = editingMarker; 504 } 505 506 /** 507 * Sets the editing placeholder.<p> 508 * 509 * @param editingPlaceholder the editing placeholder element 510 */ 511 public void setEditingPlaceholder(Element editingPlaceholder) { 512 513 m_editingPlaceholder = editingPlaceholder; 514 } 515 516 /** 517 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#setPlaceholderVisibility(boolean) 518 */ 519 public void setPlaceholderVisibility(boolean visible) { 520 521 if (visible) { 522 m_placeholder.getStyle().clearDisplay(); 523 } else { 524 m_placeholder.getStyle().setDisplay(Display.NONE); 525 } 526 } 527 528 /** 529 * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#showEditableListButtons() 530 */ 531 @Override 532 public void showEditableListButtons() { 533 534 Iterator<Widget> it = iterator(); 535 while (it.hasNext()) { 536 Widget child = it.next(); 537 if (child instanceof CmsContainerPageElementPanel) { 538 ((CmsContainerPageElementPanel)child).showEditableListButtons(); 539 } 540 } 541 } 542 543 /** 544 * @see org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel#updateOptionBarPosition() 545 */ 546 @Override 547 public void updateOptionBarPosition() { 548 549 for (Widget widget : this) { 550 if (widget instanceof CmsContainerPageElementPanel) { 551 ((CmsContainerPageElementPanel)widget).updateOptionBarPosition(); 552 } 553 } 554 } 555 556 /** 557 * @see org.opencms.ade.containerpage.client.ui.I_CmsDropContainer#updatePositionInfo() 558 */ 559 public void updatePositionInfo() { 560 561 m_ownPosition = CmsPositionBean.getBoundingClientRect(getElement()); 562 } 563}