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.groupeditor; 029 030import org.opencms.ade.containerpage.client.CmsContainerpageController; 031import org.opencms.ade.containerpage.client.CmsContainerpageController.ElementRemoveMode; 032import org.opencms.ade.containerpage.client.CmsContainerpageHandler; 033import org.opencms.ade.containerpage.client.CmsContainerpageUtil; 034import org.opencms.ade.containerpage.client.Messages; 035import org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel; 036import org.opencms.ade.containerpage.client.ui.CmsElementOptionBar; 037import org.opencms.ade.containerpage.client.ui.CmsGroupContainerElementPanel; 038import org.opencms.ade.containerpage.client.ui.css.I_CmsLayoutBundle; 039import org.opencms.ade.containerpage.shared.CmsContainerElement; 040import org.opencms.ade.containerpage.shared.CmsContainerElementData; 041import org.opencms.ade.containerpage.shared.CmsInheritanceContainer; 042import org.opencms.ade.containerpage.shared.CmsInheritanceInfo; 043import org.opencms.gwt.client.ui.CmsPushButton; 044import org.opencms.gwt.client.ui.CmsToggleButton; 045import org.opencms.gwt.client.ui.I_CmsButton.ButtonColor; 046import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle; 047import org.opencms.gwt.client.ui.input.CmsTextBox; 048import org.opencms.gwt.client.util.CmsDebugLog; 049import org.opencms.gwt.client.util.CmsDomUtil; 050import org.opencms.gwt.client.util.CmsDomUtil.Tag; 051import org.opencms.gwt.client.util.I_CmsSimpleCallback; 052import org.opencms.util.CmsUUID; 053 054import java.util.ArrayList; 055import java.util.Iterator; 056import java.util.List; 057import java.util.Map; 058 059import com.google.gwt.dom.client.Element; 060import com.google.gwt.dom.client.Style.Display; 061import com.google.gwt.dom.client.Style.Float; 062import com.google.gwt.dom.client.Style.Unit; 063import com.google.gwt.event.dom.client.ClickEvent; 064import com.google.gwt.event.dom.client.ClickHandler; 065import com.google.gwt.user.client.DOM; 066import com.google.gwt.user.client.ui.RootPanel; 067import com.google.gwt.user.client.ui.Widget; 068import com.google.web.bindery.event.shared.HandlerRegistration; 069 070/** 071 * The inheritance container editor.<p> 072 * 073 * @since 8.5.0 074 */ 075public class CmsInheritanceContainerEditor extends A_CmsGroupEditor { 076 077 /** Css class to mark hidden elements. */ 078 private static final String HIDDEN_ELEMENT_CLASS = I_CmsLayoutBundle.INSTANCE.containerpageCss().hiddenElement(); 079 080 /** Css class to hide elements. */ 081 private static final String HIDDEN_ELEMENT_OVERLAY_CLASS = I_CmsLayoutBundle.INSTANCE.containerpageCss().hiddenElementOverlay(); 082 083 /** Css class to hide elements. */ 084 private static final String HIDE_ELEMENTS_CLASS = I_CmsLayoutBundle.INSTANCE.containerpageCss().hideElements(); 085 086 /** The editor instance. */ 087 private static CmsInheritanceContainerEditor INSTANCE; 088 089 /** A flag which indicates whether the inheritance configuration needs to be updated. */ 090 private boolean m_changedInheritanceInfo; 091 092 /** Flag which indicates whether the settings of an inheritance group element have been edited. */ 093 private boolean m_editedSettings; 094 095 /** The description input. */ 096 private CmsTextBox m_inputDescription; 097 098 /** The title input. */ 099 private CmsTextBox m_inputTitle; 100 101 /** A handler which keeps track of whether elements have been dropped. */ 102 private CmsDropListener m_moveHandler; 103 104 /** The handler registration to remove the drop handler. */ 105 private HandlerRegistration m_moveHandlerRegistration; 106 107 /** Click handler for the option buttons. */ 108 private ClickHandler m_optionClickHandler; 109 110 /** The show removed elements button. */ 111 private CmsToggleButton m_showElementsButton; 112 113 /** 114 * Constructor.<p> 115 * 116 * @param groupContainer the group container widget 117 * @param controller the container page controller 118 * @param handler the container page handler 119 */ 120 protected CmsInheritanceContainerEditor( 121 CmsGroupContainerElementPanel groupContainer, 122 CmsContainerpageController controller, 123 CmsContainerpageHandler handler) { 124 125 super(groupContainer, controller, handler); 126 m_optionClickHandler = new ClickHandler() { 127 128 public void onClick(ClickEvent event) { 129 130 I_CmsGroupEditorOption optionButton = (I_CmsGroupEditorOption)event.getSource(); 131 ((CmsPushButton)optionButton).clearHoverState(); 132 CmsDomUtil.ensureMouseOut(((CmsPushButton)optionButton).getElement().getParentElement()); 133 optionButton.onClick(event); 134 } 135 }; 136 // Loading data of all contained elements including inherit container element 137 getController().getElements(getElementIds(), new I_CmsSimpleCallback<Map<String, CmsContainerElementData>>() { 138 139 public void execute(Map<String, CmsContainerElementData> arg) { 140 141 setInheritContainerData(arg); 142 } 143 }); 144 getGroupContainerWidget().addStyleName(HIDE_ELEMENTS_CLASS); 145 m_moveHandler = new CmsDropListener(); 146 m_moveHandlerRegistration = getController().getDndController().addController(m_moveHandler); 147 148 } 149 150 /** 151 * Returns the inheritance container editor instance.<p> 152 * 153 * @return the editor instance 154 */ 155 public static CmsInheritanceContainerEditor getInstance() { 156 157 return INSTANCE; 158 } 159 160 /** 161 * Opens the inheritance container editor.<p> 162 * 163 * @param groupContainer the group-container 164 * @param controller the container-page controller 165 * @param handler the container-page handler 166 * 167 * @return the editor instance 168 */ 169 public static CmsInheritanceContainerEditor openInheritanceContainerEditor( 170 CmsGroupContainerElementPanel groupContainer, 171 CmsContainerpageController controller, 172 CmsContainerpageHandler handler) { 173 174 // making sure only a single instance of the group-container editor is open 175 if (INSTANCE != null) { 176 CmsDebugLog.getInstance().printLine("group-container editor already open"); 177 } else { 178 CmsInheritanceContainerEditor editor = new CmsInheritanceContainerEditor( 179 groupContainer, 180 controller, 181 handler); 182 RootPanel.get().add(editor); 183 editor.openDialog(Messages.get().key(Messages.GUI_INHERITANCECONTAINER_CAPTION_0)); 184 groupContainer.refreshHighlighting(); 185 INSTANCE = editor; 186 } 187 return INSTANCE; 188 } 189 190 /** 191 * Clears the instance reference.<p> 192 */ 193 private static void clear() { 194 195 INSTANCE = null; 196 } 197 198 /** 199 * Method which should be called after the settings of an element in the inheritance containerhave been edited.<p> 200 */ 201 public void onSettingsEdited() { 202 203 m_editedSettings = true; 204 } 205 206 /** 207 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#reinitializeButtons() 208 */ 209 @Override 210 public void reinitializeButtons() { 211 212 // nothing to do, will be handled else where 213 } 214 215 /** 216 * Either removes the locally configured element or hides the inherited element.<p> 217 * 218 * @param elementWidget the element widget 219 */ 220 public void removeElement(CmsContainerPageElementPanel elementWidget) { 221 222 if (elementWidget.getInheritanceInfo().isNew()) { 223 getHandler().removeElement(elementWidget, ElementRemoveMode.saveAndCheckReferences); 224 } else { 225 elementWidget.getInheritanceInfo().setVisible(false); 226 elementWidget.addStyleName(HIDDEN_ELEMENT_CLASS); 227 Element elementOverlay = DOM.createDiv(); 228 elementOverlay.setClassName(HIDDEN_ELEMENT_OVERLAY_CLASS); 229 elementWidget.getElement().appendChild(elementOverlay); 230 getGroupContainerWidget().add(elementWidget); 231 updateButtonVisibility(elementWidget); 232 m_showElementsButton.enable(); 233 getGroupContainerWidget().refreshHighlighting(); 234 } 235 m_changedInheritanceInfo = true; 236 } 237 238 /** 239 * Sets the option bar on the element widget.<p> 240 * 241 * @param elementWidget the element widget 242 */ 243 public void setOptionBar(CmsContainerPageElementPanel elementWidget) { 244 245 if (elementWidget.hasViewPermission()) { 246 elementWidget.setElementOptionBar(createOptionBar(elementWidget)); 247 updateButtonVisibility(elementWidget); 248 } else { 249 elementWidget.setElementOptionBar(null); 250 } 251 } 252 253 /** 254 * Shows a formerly hidden element and sets the visibility info to true.<p> 255 * 256 * @param elementWidget the element widget 257 */ 258 public void showElement(CmsContainerPageElementPanel elementWidget) { 259 260 int index = 0; 261 for (index = 0; index < getGroupContainerWidget().getWidgetCount(); index++) { 262 if (CmsDomUtil.hasClass(HIDDEN_ELEMENT_CLASS, getGroupContainerWidget().getWidget(index).getElement())) { 263 break; 264 } 265 } 266 getGroupContainerWidget().insert(elementWidget, index); 267 elementWidget.getInheritanceInfo().setVisible(true); 268 elementWidget.removeStyleName(HIDDEN_ELEMENT_CLASS); 269 updateButtonVisibility(elementWidget); 270 getGroupContainerWidget().refreshHighlighting(); 271 List<Element> elements = CmsDomUtil.getElementsByClass( 272 HIDDEN_ELEMENT_OVERLAY_CLASS, 273 Tag.div, 274 elementWidget.getElement()); 275 for (Element element : elements) { 276 element.removeFromParent(); 277 } 278 if (CmsDomUtil.getElementsByClass( 279 HIDDEN_ELEMENT_OVERLAY_CLASS, 280 Tag.div, 281 getGroupContainerWidget().getElement()).isEmpty()) { 282 // if no other hidden elements present disable toggle button 283 m_showElementsButton.disable(Messages.get().key(Messages.GUI_INHERITANCECONTAINER_NO_HIDDEN_ELEMENTS_0)); 284 } 285 m_changedInheritanceInfo = true; 286 } 287 288 /** 289 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#addButtons() 290 */ 291 @Override 292 protected void addButtons() { 293 294 addCancelButton(); 295 addSaveButton(); 296 m_showElementsButton = new CmsToggleButton(); 297 m_showElementsButton.setText(Messages.get().key(Messages.GUI_INHERITANCECONTAINER_SHOW_HIDDEN_0)); 298 m_showElementsButton.setDownFace(Messages.get().key(Messages.GUI_INHERITANCECONTAINER_HIDE_ELEMENTS_0), null); 299 m_showElementsButton.setUseMinWidth(true); 300 m_showElementsButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.RED); 301 m_showElementsButton.addClickHandler(new ClickHandler() { 302 303 public void onClick(ClickEvent event) { 304 305 toggleElementVisibility(); 306 } 307 }); 308 m_showElementsButton.disable(Messages.get().key(Messages.GUI_INHERITANCECONTAINER_NO_HIDDEN_ELEMENTS_0)); 309 m_showElementsButton.getElement().getStyle().setFloat(Float.LEFT); 310 addButton(m_showElementsButton); 311 CmsPushButton breakUpButton = new CmsPushButton(); 312 breakUpButton.setText(Messages.get().key(Messages.GUI_BUTTON_BREAK_UP_TEXT_0)); 313 breakUpButton.setUseMinWidth(true); 314 breakUpButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.RED); 315 breakUpButton.addClickHandler(new ClickHandler() { 316 317 public void onClick(ClickEvent event) { 318 319 breakUpContainer(); 320 } 321 }); 322 breakUpButton.getElement().getStyle().setFloat(Float.LEFT); 323 breakUpButton.getElement().getStyle().setMarginLeft(0, Unit.PX); 324 addButton(breakUpButton); 325 } 326 327 /** 328 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#addInputFields() 329 */ 330 @Override 331 protected void addInputFields() { 332 333 m_inputTitle = new CmsTextBox(); 334 addInputField(Messages.get().key(Messages.GUI_GROUPCONTAINER_LABEL_TITLE_0), m_inputTitle); 335 m_inputDescription = new CmsTextBox(); 336 addInputField(Messages.get().key(Messages.GUI_GROUPCONTAINER_LABEL_DESCRIPTION_0), m_inputDescription); 337 } 338 339 /** 340 * Breaks up the group container inserting all visible elements into the parent container instead.<p> 341 */ 342 protected void breakUpContainer() { 343 344 List<String> clientIds = new ArrayList<String>(); 345 for (Widget w : getGroupContainerWidget()) { 346 if (w instanceof CmsContainerPageElementPanel) { 347 CmsContainerPageElementPanel elementWidget = (CmsContainerPageElementPanel)w; 348 if ((elementWidget.getInheritanceInfo() == null) || elementWidget.getInheritanceInfo().isVisible()) { 349 clientIds.add(elementWidget.getId()); 350 } 351 } 352 } 353 int index = getIndexPosition(); 354 for (String clientId : clientIds) { 355 try { 356 CmsContainerElementData elementData = getController().getCachedElement(clientId); 357 CmsContainerPageElementPanel containerElement = getController().getContainerpageUtil().createElement( 358 elementData, 359 getParentContainer(), 360 false); 361 getParentContainer().insert(containerElement, index); 362 index++; 363 } catch (Exception e) { 364 CmsDebugLog.getInstance().printLine(e.getMessage()); 365 } 366 } 367 getController().addToRecentList(getGroupContainerWidget().getId(), null); 368 getController().unlockResource( 369 new CmsUUID(CmsContainerpageController.getServerId(m_elementData.getClientId()))); 370 closeDialog(true); 371 getController().setPageChanged(); 372 } 373 374 /** 375 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#cancelEdit() 376 */ 377 @Override 378 protected void cancelEdit() { 379 380 removeAllChildren(); 381 for (CmsContainerPageElementPanel element : getBackUpElements()) { 382 getGroupContainerWidget().add(element); 383 } 384 if (getBackUpElements().size() == 0) { 385 getGroupContainerWidget().addStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().emptyGroupContainer()); 386 } 387 getController().unlockResource( 388 new CmsUUID(CmsContainerpageController.getServerId(m_elementData.getClientId()))); 389 closeDialog(false); 390 } 391 392 /** 393 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#clearInstance() 394 */ 395 @Override 396 protected void clearInstance() { 397 398 clear(); 399 } 400 401 /** 402 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#closeDialog(boolean) 403 */ 404 @Override 405 protected void closeDialog(boolean breakingUp) { 406 407 m_moveHandlerRegistration.removeHandler(); 408 getGroupContainerWidget().removeStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().hideElements()); 409 super.closeDialog(breakingUp); 410 } 411 412 /** 413 * @see org.opencms.ade.containerpage.client.ui.groupeditor.A_CmsGroupEditor#saveEdit() 414 */ 415 @Override 416 protected void saveEdit() { 417 418 List<CmsContainerElement> elements = new ArrayList<CmsContainerElement>(); 419 boolean moved = m_moveHandler.isDropped(); 420 m_changedInheritanceInfo |= moved; 421 m_changedInheritanceInfo |= m_editedSettings; 422 for (Widget widget : getGroupContainerWidget()) { 423 if (widget instanceof CmsContainerPageElementPanel) { 424 CmsContainerPageElementPanel elementWidget = (CmsContainerPageElementPanel)widget; 425 CmsInheritanceInfo inheritanceInfo = elementWidget.getInheritanceInfo(); 426 if (inheritanceInfo == null) { 427 inheritanceInfo = new CmsInheritanceInfo(null, true, true); 428 m_changedInheritanceInfo = true; 429 } 430 CmsContainerElement element = getController().getCachedElement(elementWidget.getId()).copy(); 431 element.setInheritanceInfo(inheritanceInfo); 432 elements.add(element); 433 } 434 } 435 CmsInheritanceContainer container = new CmsInheritanceContainer(); 436 container.setElementsChanged(m_changedInheritanceInfo); 437 container.setElementsMoved(moved); 438 container.setNew(getGroupContainerWidget().isNew()); 439 container.setClientId(getGroupContainerWidget().getId()); 440 container.setTitle(m_inputTitle.getText()); 441 container.setDescription(m_inputDescription.getText()); 442 container.setName(m_elementData.getInheritanceName()); 443 container.setElements(elements); 444 getController().saveInheritContainer(container, getGroupContainerWidget()); 445 closeDialog(false); 446 } 447 448 /** 449 * Sets the loaded element data.<p> 450 * 451 * @param elementsData the elements data 452 */ 453 protected void setInheritContainerData(Map<String, CmsContainerElementData> elementsData) { 454 455 m_elementData = elementsData.get(getGroupContainerWidget().getId()); 456 if (m_elementData != null) { 457 m_inputDescription.setFormValueAsString(m_elementData.getDescription()); 458 m_inputTitle.setFormValueAsString(m_elementData.getTitle()); 459 removeAllChildren(); 460 CmsContainerpageUtil util = getController().getContainerpageUtil(); 461 for (CmsInheritanceInfo info : m_elementData.getInheritanceInfos()) { 462 if (info.isVisible()) { 463 CmsContainerElementData element = getController().getCachedElement(info.getClientId()); 464 try { 465 CmsContainerPageElementPanel elementWidget = util.createElement( 466 element, 467 getGroupContainerWidget(), 468 false); 469 elementWidget.setInheritanceInfo(info); 470 setOptionBar(elementWidget); 471 getGroupContainerWidget().add(elementWidget); 472 } catch (Exception e) { 473 CmsDebugLog.getInstance().printLine(e.getMessage()); 474 } 475 } 476 } 477 boolean hasInvisible = false; 478 for (CmsInheritanceInfo info : m_elementData.getInheritanceInfos()) { 479 if (!info.isVisible()) { 480 CmsContainerElementData element = getController().getCachedElement(info.getClientId()); 481 try { 482 CmsContainerPageElementPanel elementWidget = util.createElement( 483 element, 484 getGroupContainerWidget(), 485 false); 486 elementWidget.setInheritanceInfo(info); 487 elementWidget.addStyleName(HIDDEN_ELEMENT_CLASS); 488 setOptionBar(elementWidget); 489 getGroupContainerWidget().add(elementWidget); 490 Element elementOverlay = DOM.createDiv(); 491 elementOverlay.setClassName(HIDDEN_ELEMENT_OVERLAY_CLASS); 492 elementWidget.getElement().appendChild(elementOverlay); 493 hasInvisible = true; 494 } catch (Exception e) { 495 CmsDebugLog.getInstance().printLine(e.getMessage()); 496 } 497 } 498 } 499 if (hasInvisible) { 500 m_showElementsButton.enable(); 501 } 502 } 503 504 getGroupContainerWidget().refreshHighlighting(); 505 setSaveEnabled(true, null); 506 } 507 508 /** 509 * Toggles the visibility of hidden elements.<p> 510 */ 511 protected void toggleElementVisibility() { 512 513 if (CmsDomUtil.hasClass(HIDE_ELEMENTS_CLASS, getGroupContainerWidget().getElement())) { 514 getGroupContainerWidget().removeStyleName(HIDE_ELEMENTS_CLASS); 515 } else { 516 getGroupContainerWidget().addStyleName(HIDE_ELEMENTS_CLASS); 517 } 518 getGroupContainerWidget().refreshHighlighting(); 519 } 520 521 /** 522 * Creates an option bar for the given element.<p> 523 * 524 * @param elementWidget the element widget 525 * 526 * @return the option bar 527 */ 528 private CmsElementOptionBar createOptionBar(CmsContainerPageElementPanel elementWidget) { 529 530 CmsElementOptionBar optionBar = new CmsElementOptionBar(elementWidget); 531 CmsPushButton button = new CmsRemoveOptionButton(elementWidget, this); 532 button.addClickHandler(m_optionClickHandler); 533 optionBar.add(button); 534 535 button = new CmsFavoritesOptionButton(elementWidget, this); 536 button.addClickHandler(m_optionClickHandler); 537 optionBar.add(button); 538 539 button = new CmsSettingsOptionButton(elementWidget, this); 540 button.addClickHandler(m_optionClickHandler); 541 optionBar.add(button); 542 543 button = new CmsInfoOptionButton(elementWidget, this); 544 button.addClickHandler(m_optionClickHandler); 545 optionBar.add(button); 546 547 button = new CmsAddOptionButton(elementWidget, this); 548 button.addClickHandler(m_optionClickHandler); 549 optionBar.add(button); 550 551 button = new CmsInheritedOptionButton(elementWidget, this); 552 optionBar.add(button); 553 554 button = new CmsMoveOptionButton(elementWidget, this); 555 // setting the drag and drop handler 556 button.addMouseDownHandler(getController().getDndHandler()); 557 optionBar.add(button); 558 559 button = new CmsEditOptionButton(elementWidget, this); 560 button.addClickHandler(m_optionClickHandler); 561 optionBar.add(button); 562 563 return optionBar; 564 } 565 566 /** 567 * Updates the visibility of the option bar buttons of the given element.<p> 568 * 569 * @param elementWidget the element widget 570 */ 571 private void updateButtonVisibility(CmsContainerPageElementPanel elementWidget) { 572 573 Iterator<Widget> it = elementWidget.getElementOptionBar().iterator(); 574 while (it.hasNext()) { 575 Widget w = it.next(); 576 if (w instanceof I_CmsGroupEditorOption) { 577 if (((I_CmsGroupEditorOption)w).checkVisibility()) { 578 w.getElement().getStyle().clearDisplay(); 579 } else { 580 w.getElement().getStyle().setDisplay(Display.NONE); 581 } 582 } 583 } 584 } 585}