001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.acacia.client; 029 030import org.opencms.acacia.client.CmsUndoRedoHandler.ChangeType; 031import org.opencms.acacia.client.css.I_CmsLayoutBundle; 032import org.opencms.acacia.client.entity.I_CmsEntityBackend; 033import org.opencms.acacia.client.ui.CmsAttributeValueView; 034import org.opencms.acacia.client.ui.CmsInlineEntityWidget; 035import org.opencms.acacia.client.widgets.I_CmsFormEditWidget; 036import org.opencms.acacia.shared.CmsEntity; 037import org.opencms.acacia.shared.CmsEntityAttribute; 038import org.opencms.acacia.shared.CmsType; 039import org.opencms.gwt.client.dnd.CmsDNDHandler; 040import org.opencms.gwt.client.dnd.CmsDNDHandler.Orientation; 041import org.opencms.gwt.client.ui.CmsTabbedPanel; 042import org.opencms.gwt.client.util.CmsMoveAnimation; 043 044import java.util.ArrayList; 045import java.util.List; 046 047import com.google.gwt.dom.client.Element; 048import com.google.gwt.dom.client.Style.Position; 049import com.google.gwt.dom.client.Style.Unit; 050import com.google.gwt.event.logical.shared.ResizeHandler; 051import com.google.gwt.user.client.Command; 052import com.google.gwt.user.client.ui.FlowPanel; 053import com.google.gwt.user.client.ui.Panel; 054import com.google.gwt.user.client.ui.Widget; 055 056/** 057 * The attribute handler. Handles value changes, addition of new values, remove and move operations on values.<p> 058 */ 059public class CmsAttributeHandler extends CmsRootHandler { 060 061 /** The global widget resize handler. */ 062 private static ResizeHandler m_resizeHandler; 063 064 /** The scroll element. */ 065 private static Element m_scrollElement; 066 067 /** The attribute name. */ 068 private String m_attributeName; 069 070 /** The attribute type. */ 071 private CmsType m_attributeType; 072 073 /** Registered attribute values. */ 074 private List<CmsAttributeValueView> m_attributeValueViews; 075 076 /** The attribute drag and drop handler. */ 077 private CmsDNDHandler m_dndHandler; 078 079 /** The entity. */ 080 private CmsEntity m_entity; 081 082 /** The entity back end instance. */ 083 private I_CmsEntityBackend m_entityBackEnd; 084 085 /** The entity type. */ 086 private CmsType m_entityType; 087 088 /** The parent attribute handler. */ 089 private I_CmsAttributeHandler m_parentHandler; 090 091 /** The single value index. */ 092 private int m_singleValueIndex; 093 094 /** The widget service. */ 095 private I_CmsWidgetService m_widgetService; 096 097 /** 098 * Constructor.<p> 099 * 100 * @param entityBackEnd the entity back end instance 101 * @param entity the entity 102 * @param attributeName the attribute name 103 * @param widgetService the widget service 104 */ 105 public CmsAttributeHandler( 106 I_CmsEntityBackend entityBackEnd, 107 CmsEntity entity, 108 String attributeName, 109 I_CmsWidgetService widgetService) { 110 111 // single value handling is disable by default 112 m_singleValueIndex = -1; 113 m_entityBackEnd = entityBackEnd; 114 m_entity = entity; 115 m_attributeName = attributeName; 116 m_widgetService = widgetService; 117 m_attributeValueViews = new ArrayList<CmsAttributeValueView>(); 118 if (!getAttributeType().isSimpleType()) { 119 int count = 0; 120 CmsEntityAttribute attribute = entity.getAttribute(attributeName); 121 if (attribute != null) { 122 count = attribute.getValueCount(); 123 } 124 initHandlers(count); 125 } 126 } 127 128 /** 129 * Clears the error styles on the given tabbed panel.<p> 130 * 131 * @param tabbedPanel the tabbed panel 132 */ 133 public static void clearErrorStyles(CmsTabbedPanel<?> tabbedPanel) { 134 135 for (int i = 0; i < tabbedPanel.getTabCount(); i++) { 136 Widget tab = tabbedPanel.getTabWidget(i); 137 tab.setTitle(null); 138 tab.getParent().removeStyleName(I_CmsLayoutBundle.INSTANCE.form().hasError()); 139 tab.getParent().removeStyleName(I_CmsLayoutBundle.INSTANCE.form().hasWarning()); 140 } 141 } 142 143 /** 144 * Returns the global widget resize handler.<p> 145 * 146 * @return the global widget resize handler 147 */ 148 public static ResizeHandler getResizeHandler() { 149 150 return m_resizeHandler; 151 } 152 153 /** 154 * Returns <code>true</code> if a global widget resize handler is present.<p> 155 * 156 * @return <code>true</code> if a global widget resize handler is present 157 */ 158 public static boolean hasResizeHandler() { 159 160 return m_resizeHandler != null; 161 } 162 163 /** 164 * Sets the global widget resize handler.<p> 165 * 166 * @param handler the resize handler 167 */ 168 public static void setResizeHandler(ResizeHandler handler) { 169 170 m_resizeHandler = handler; 171 } 172 173 /** 174 * Sets the scroll element. To be used for automatic scrolling during drag and drop.<p> 175 * 176 * @param scrollElement the scroll element 177 */ 178 public static void setScrollElement(Element scrollElement) { 179 180 m_scrollElement = scrollElement; 181 } 182 183 /** 184 * Adds a new attribute value below the reference view.<p> 185 * 186 * @param reference the reference value view 187 */ 188 public void addNewAttributeValue(CmsAttributeValueView reference) { 189 190 // make sure not to add more values than allowed 191 int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); 192 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 193 boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); 194 if (mayHaveMore) { 195 if (getAttributeType().isSimpleType()) { 196 int valueIndex = reference.getValueIndex() + 1; 197 String defaultValue = m_widgetService.getDefaultAttributeValue( 198 m_attributeName, 199 getSimplePath(valueIndex)); 200 I_CmsFormEditWidget widget = m_widgetService.getAttributeFormWidget(m_attributeName); 201 202 boolean insertLast = false; 203 if (reference.getElement().getNextSiblingElement() == null) { 204 m_entity.addAttributeValue(m_attributeName, defaultValue); 205 insertLast = true; 206 } else { 207 valueIndex = reference.getValueIndex() + 1; 208 m_entity.insertAttributeValue(m_attributeName, defaultValue, valueIndex); 209 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 210 } 211 CmsAttributeValueView valueWidget = reference; 212 if (reference.hasValue()) { 213 valueWidget = new CmsAttributeValueView( 214 this, 215 m_widgetService.getAttributeLabel(m_attributeName), 216 m_widgetService.getAttributeHelp(m_attributeName)); 217 if (m_widgetService.isDisplaySingleLine(m_attributeName)) { 218 valueWidget.setCompactMode(CmsAttributeValueView.COMPACT_MODE_SINGLE_LINE); 219 } 220 if (insertLast) { 221 ((FlowPanel)reference.getParent()).add(valueWidget); 222 } else { 223 ((FlowPanel)reference.getParent()).insert(valueWidget, valueIndex); 224 } 225 226 } 227 valueWidget.setValueWidget(widget, defaultValue, defaultValue, true); 228 } else { 229 CmsEntity value = m_entityBackEnd.createEntity(null, getAttributeType().getId()); 230 insertValueAfterReference(value, reference); 231 } 232 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 233 if (handler.isIntitalized()) { 234 handler.addChange(m_entity.getId(), m_attributeName, reference.getValueIndex() + 1, ChangeType.add); 235 } 236 } 237 updateButtonVisisbility(); 238 } 239 240 /** 241 * Adds a new attribute value and adds the required widgets to the editor DOM.<p> 242 * 243 * @param value the value entity 244 */ 245 public void addNewAttributeValue(CmsEntity value) { 246 247 // make sure not to add more values than allowed 248 int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); 249 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 250 boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); 251 if (mayHaveMore && value.getTypeName().equals(m_attributeType.getId())) { 252 m_entity.addAttributeValue(m_attributeName, value); 253 int valueIndex = m_entity.getAttribute(m_attributeName).getValueCount() - 1; 254 CmsAttributeValueView valueView = null; 255 if ((m_attributeValueViews.size() == 1) && !m_attributeValueViews.get(0).hasValue()) { 256 valueView = m_attributeValueViews.get(0); 257 } else { 258 valueView = new CmsAttributeValueView( 259 this, 260 m_widgetService.getAttributeLabel(m_attributeName), 261 m_widgetService.getAttributeHelp(m_attributeName)); 262 } 263 264 CmsRenderer.setAttributeChoice(m_widgetService, valueView, getAttributeType()); 265 ((FlowPanel)m_attributeValueViews.get(0).getParent()).add(valueView); 266 267 insertHandlers(valueIndex); 268 I_CmsEntityRenderer renderer = m_widgetService.getRendererForAttribute(m_attributeName, getAttributeType()); 269 valueView.setValueEntity(renderer, value); 270 271 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 272 if (handler.isIntitalized()) { 273 handler.addChange(m_entity.getId(), m_attributeName, valueIndex, ChangeType.add); 274 } 275 } 276 } 277 278 /** 279 * Adds a new attribute value and adds the required widgets to the editor DOM.<p> 280 * 281 * @param value the simple value 282 */ 283 public void addNewAttributeValue(String value) { 284 285 // make sure not to add more values than allowed 286 int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); 287 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 288 boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); 289 if (mayHaveMore && getAttributeType().isSimpleType()) { 290 I_CmsFormEditWidget widget = m_widgetService.getAttributeFormWidget(m_attributeName); 291 m_entity.addAttributeValue(m_attributeName, value); 292 int valueCount = m_entity.getAttribute(m_attributeName).getValueCount(); 293 String defaultValue = m_widgetService.getDefaultAttributeValue( 294 m_attributeName, 295 getSimplePath(valueCount - 1)); 296 CmsAttributeValueView valueView = null; 297 if ((m_attributeValueViews.size() == 1) && !m_attributeValueViews.get(0).hasValue()) { 298 valueView = m_attributeValueViews.get(0); 299 valueView.setActive(); 300 // setActive may have reset the value, so we set it again 301 m_entity.setAttributeValue(m_attributeName, value, valueCount - 1); 302 valueView.getValueWidget().setValue(value); 303 } else { 304 valueView = new CmsAttributeValueView( 305 this, 306 m_widgetService.getAttributeLabel(m_attributeName), 307 m_widgetService.getAttributeHelp(m_attributeName)); 308 if (m_widgetService.isDisplaySingleLine(m_attributeName)) { 309 valueView.setCompactMode(CmsAttributeValueView.COMPACT_MODE_SINGLE_LINE); 310 } 311 ((FlowPanel)m_attributeValueViews.get(0).getParent()).add(valueView); 312 valueView.setValueWidget(widget, value, defaultValue, true); 313 } 314 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 315 if (handler.isIntitalized()) { 316 handler.addChange( 317 m_entity.getId(), 318 m_attributeName, 319 m_entity.getAttribute(m_attributeName).getValueCount() - 1, 320 ChangeType.add); 321 } 322 updateButtonVisisbility(); 323 } 324 } 325 326 /** 327 * Adds a new attribute value below the reference index.<p> 328 * This will not execute any DOM manipulations.<p> 329 * 330 * @param referenceIndex the reference value index 331 */ 332 public void addNewAttributeValueToEntity(int referenceIndex) { 333 334 // make sure not to add more values than allowed 335 int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); 336 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 337 boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); 338 if (mayHaveMore) { 339 if (getAttributeType().isSimpleType()) { 340 String defaultValue = m_widgetService.getDefaultAttributeValue( 341 m_attributeName, 342 getSimplePath(referenceIndex + 1)); 343 if ((attribute == null) || (attribute.getValueCount() == (referenceIndex + 1))) { 344 m_entity.addAttributeValue(m_attributeName, defaultValue); 345 } else { 346 m_entity.insertAttributeValue(m_attributeName, defaultValue, referenceIndex + 1); 347 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 348 } 349 } else { 350 CmsEntity value = m_entityBackEnd.createEntity(null, m_attributeType.getId()); 351 if ((attribute == null) || (attribute.getValueCount() == (referenceIndex + 1))) { 352 m_entity.addAttributeValue(m_attributeName, value); 353 } else { 354 m_entity.insertAttributeValue(m_attributeName, value, referenceIndex + 1); 355 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 356 } 357 insertHandlers(referenceIndex + 1); 358 } 359 } 360 } 361 362 /** 363 * Adds a new choice attribute value.<p> 364 * 365 * @param reference the reference value view 366 * @param choicePath the path of the selected (possibly nested) choice attribute, consisting of attribute names 367 */ 368 public void addNewChoiceAttributeValue(CmsAttributeValueView reference, List<String> choicePath) { 369 370 CmsValueFocusHandler.getInstance().clearFocus(); 371 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 372 if (isChoiceHandler()) { 373 addChoiceOption(reference, choicePath); 374 } else { 375 addComplexChoiceValue(reference, choicePath); 376 } 377 updateButtonVisisbility(); 378 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 379 if (handler.isIntitalized()) { 380 handler.addChange(m_entity.getId(), m_attributeName, reference.getValueIndex() + 1, ChangeType.choice); 381 } 382 } 383 384 /** 385 * Applies a value change to the entity data as well as to the value view widget.<p> 386 * 387 * @param value the value 388 * @param valueIndex the value index 389 */ 390 public void changeValue(String value, int valueIndex) { 391 392 m_attributeValueViews.get(valueIndex).getValueWidget().setValue(value, false); 393 changeEntityValue(value, valueIndex); 394 } 395 396 /** 397 * @see org.opencms.acacia.client.CmsRootHandler#collectSimplePath(org.opencms.acacia.client.I_CmsAttributeHandler) 398 */ 399 @Override 400 public String collectSimplePath(I_CmsAttributeHandler childHandler) { 401 402 int index = -1; 403 for (int i = 0; i < m_handlers.size(); i++) { 404 if (m_handlers.get(i).get(childHandler.getAttributeName()) == childHandler) { 405 index = i; 406 break; 407 } 408 } 409 if (index == -1) { 410 throw new RuntimeException("Child handler is not properly registered."); 411 } 412 return getSimplePath(index) + "/"; 413 } 414 415 /** 416 * Creates a sequence of nested entities according to a given path of choice attribute names.<p> 417 * 418 * @param value the entity into which the new entities for the given path should be inserted 419 * @param choicePath the path of choice attributes 420 */ 421 public void createNestedEntitiesForChoicePath(CmsEntity value, List<String> choicePath) { 422 423 CmsEntity parentValue = value; 424 for (String attributeChoice : choicePath) { 425 CmsType choiceType = m_entityBackEnd.getType(parentValue.getTypeName()).getAttributeType( 426 CmsType.CHOICE_ATTRIBUTE_NAME); 427 CmsEntity choice = m_entityBackEnd.createEntity(null, choiceType.getId()); 428 parentValue.addAttributeValue(CmsType.CHOICE_ATTRIBUTE_NAME, choice); 429 CmsType choiceOptionType = choiceType.getAttributeType(attributeChoice); 430 if (choiceOptionType.isSimpleType()) { 431 String choiceValue = m_widgetService.getDefaultAttributeValue(attributeChoice, getSimplePath(0)); 432 choice.addAttributeValue(attributeChoice, choiceValue); 433 break; 434 } else { 435 CmsEntity choiceValue = m_entityBackEnd.createEntity(null, choiceOptionType.getId()); 436 choice.addAttributeValue(attributeChoice, choiceValue); 437 parentValue = choiceValue; 438 } 439 } 440 } 441 442 /** 443 * Destroys the attribute handler instance.<p> 444 */ 445 public void destroy() { 446 447 m_attributeName = null; 448 m_attributeType = null; 449 m_attributeValueViews.clear(); 450 m_attributeValueViews = null; 451 m_dndHandler = null; 452 m_entity = null; 453 m_entityType = null; 454 m_entityBackEnd = null; 455 m_widgetService = null; 456 } 457 458 /** 459 * Returns the attribute name.<p> 460 * 461 * @return the attribute name 462 */ 463 @Override 464 public String getAttributeName() { 465 466 return m_attributeName; 467 } 468 469 /** 470 * Returns the attribute type.<p> 471 * 472 * @return the attribute type 473 */ 474 public CmsType getAttributeType() { 475 476 if (m_attributeType == null) { 477 m_attributeType = getEntityType().getAttributeType(m_attributeName); 478 } 479 return m_attributeType; 480 } 481 482 /** 483 * Returns the drag and drop handler.<p> 484 * 485 * @return the drag and drop handler 486 */ 487 public CmsDNDHandler getDNDHandler() { 488 489 if (m_dndHandler == null) { 490 m_dndHandler = new CmsDNDHandler(new CmsAttributeDNDController()); 491 m_dndHandler.setOrientation(Orientation.VERTICAL); 492 m_dndHandler.setScrollEnabled(true); 493 m_dndHandler.setScrollElement(m_scrollElement); 494 } 495 return m_dndHandler; 496 } 497 498 /** 499 * Returns the entity id.<p> 500 * 501 * @return the entity id 502 */ 503 public String getEntityId() { 504 505 return m_entity.getId(); 506 } 507 508 /** 509 * Gets the maximum occurrence of the attribute.<p> 510 * 511 * @return the maximum occurrence 512 */ 513 public int getMaxOccurence() { 514 515 return getEntityType().getAttributeMaxOccurrence(m_attributeName); 516 } 517 518 /** 519 * Returns the simple value path for the given index.<p> 520 * This will use the last fragment of the attribute name and concatenate it with the parent path.<p> 521 * If the given index equals -1 no value index will be appended 522 * 523 * @param index the value index 524 * 525 * @return the simple path 526 */ 527 public String getSimplePath(int index) { 528 529 String simpleName = m_attributeName.substring(m_attributeName.lastIndexOf("/") + 1); 530 String result = m_parentHandler.collectSimplePath(this) + simpleName; 531 if (index != -1) { 532 result += "[" + (index + 1) + "]"; 533 } 534 return result; 535 } 536 537 /** 538 * Gets the widget service.<p> 539 * 540 * @return the widget service 541 */ 542 public I_CmsWidgetService getWidgetService() { 543 544 return m_widgetService; 545 } 546 547 /** 548 * Handles value changes from the view.<p> 549 * 550 * @param reference the attribute value reference 551 * @param value the value 552 */ 553 public void handleValueChange(CmsAttributeValueView reference, String value) { 554 555 handleValueChange(reference.getValueIndex(), value); 556 } 557 558 /** 559 * Handles value changes from the view.<p> 560 * 561 * @param valueIndex the value index 562 * @param value the value 563 */ 564 public void handleValueChange(int valueIndex, String value) { 565 566 if (isSingleValueHandler()) { 567 valueIndex = m_singleValueIndex; 568 } 569 changeEntityValue(value, valueIndex); 570 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 571 if (handler.isIntitalized()) { 572 handler.addChange(m_entity.getId(), m_attributeName, valueIndex, ChangeType.value); 573 } 574 } 575 576 /** 577 * Return true if there is a single remaining value, which is optional.<p> 578 * 579 * @return true if this has only one optional value 580 */ 581 public boolean hasSingleOptionalValue() { 582 583 return ((getEntityType().getAttributeMinOccurrence(m_attributeName) == 0) 584 && (m_entity.getAttribute(m_attributeName) != null) 585 && (m_entity.getAttribute(m_attributeName).getValueCount() == 1)); 586 } 587 588 /** 589 * Returns if there is a value view widget registered for the given index.<p> 590 * 591 * @param valueIndex the value index 592 * 593 * @return <code>true</code> if there is a value view widget registered for the given index 594 */ 595 public boolean hasValueView(int valueIndex) { 596 597 return m_attributeValueViews.size() > valueIndex; 598 } 599 600 /** 601 * Adds a new attribute value and adds the required widgets to the editor DOM.<p> 602 * 603 * @param value the value entity 604 * @param index the position in which to insert the new value 605 * @param container the widget containing the attribute value views 606 */ 607 public void insertNewAttributeValue(CmsEntity value, int index, Panel container) { 608 609 // make sure not to add more values than allowed 610 int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); 611 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 612 boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); 613 if (mayHaveMore && value.getTypeName().equals(m_attributeType.getId())) { 614 m_entity.insertAttributeValue(m_attributeName, value, index); 615 int valueIndex = index; 616 CmsAttributeValueView valueView = null; 617 if ((m_attributeValueViews.size() == 1) && !m_attributeValueViews.get(0).hasValue()) { 618 valueView = m_attributeValueViews.get(0); 619 } else { 620 valueView = new CmsAttributeValueView( 621 this, 622 m_widgetService.getAttributeLabel(m_attributeName), 623 m_widgetService.getAttributeHelp(m_attributeName)); 624 } 625 CmsRenderer.setAttributeChoice(m_widgetService, valueView, getAttributeType()); 626 m_attributeValueViews.remove(valueView); 627 m_attributeValueViews.add(index, valueView); 628 629 ((FlowPanel)container).insert(valueView, index); 630 631 insertHandlers(valueIndex); 632 633 I_CmsEntityRenderer renderer = m_widgetService.getRendererForAttribute(m_attributeName, getAttributeType()); 634 valueView.setValueEntity(renderer, value); 635 636 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 637 if (handler.isIntitalized()) { 638 handler.addChange(m_entity.getId(), m_attributeName, valueIndex, ChangeType.add); 639 } 640 } 641 } 642 643 /** 644 * Returns if this is a choice handler.<p> 645 * 646 * @return <code>true</code> if this is a choice handler 647 */ 648 public boolean isChoiceHandler() { 649 650 return CmsType.CHOICE_ATTRIBUTE_NAME.equals(m_attributeName); 651 } 652 653 /** 654 * Moves the give attribute value from one position to another.<p> 655 * 656 * @param valueView the value to move 657 * @param currentPosition the current position 658 * @param targetPosition the target position 659 */ 660 public void moveAttributeValue(CmsAttributeValueView valueView, int currentPosition, int targetPosition) { 661 662 if (currentPosition == targetPosition) { 663 return; 664 } 665 FlowPanel parent = (FlowPanel)valueView.getParent(); 666 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 667 valueView.removeFromParent(); 668 m_attributeValueViews.remove(valueView); 669 CmsAttributeValueView valueWidget = null; 670 if (isChoiceHandler()) { 671 removeHandlers(currentPosition); 672 CmsEntity value = m_entity.getAttribute(m_attributeName).getComplexValues().get(currentPosition); 673 m_entity.removeAttributeValue(m_attributeName, currentPosition); 674 m_entity.insertAttributeValue(m_attributeName, value, targetPosition); 675 String attributeChoice = getChoiceName(targetPosition); 676 CmsType optionType = getAttributeType().getAttributeType(attributeChoice); 677 valueWidget = new CmsAttributeValueView( 678 this, 679 m_widgetService.getAttributeLabel(attributeChoice), 680 m_widgetService.getAttributeHelp(attributeChoice)); 681 if (optionType.isSimpleType() && m_widgetService.isDisplaySingleLine(attributeChoice)) { 682 valueWidget.setCompactMode(CmsAttributeValueView.COMPACT_MODE_SINGLE_LINE); 683 } 684 parent.insert(valueWidget, targetPosition); 685 insertHandlers(targetPosition); 686 if (optionType.isSimpleType()) { 687 valueWidget.setValueWidget( 688 m_widgetService.getAttributeFormWidget(attributeChoice), 689 value.getAttribute(attributeChoice).getSimpleValue(), 690 m_widgetService.getDefaultAttributeValue(attributeChoice, getSimplePath(targetPosition)), 691 true); 692 } else { 693 valueWidget.setValueEntity( 694 m_widgetService.getRendererForAttribute(attributeChoice, getAttributeType()), 695 value.getAttribute(attributeChoice).getComplexValue()); 696 } 697 698 List<CmsChoiceMenuEntryBean> menuEntries = CmsRenderer.getChoiceEntries(getAttributeType(), true); 699 for (CmsChoiceMenuEntryBean menuEntry : menuEntries) { 700 valueWidget.addChoice(m_widgetService, menuEntry); 701 } 702 } else if (getAttributeType().isSimpleType()) { 703 String value = m_entity.getAttribute(m_attributeName).getSimpleValues().get(currentPosition); 704 m_entity.removeAttributeValue(m_attributeName, currentPosition); 705 m_entity.insertAttributeValue(m_attributeName, value, targetPosition); 706 valueWidget = new CmsAttributeValueView( 707 this, 708 m_widgetService.getAttributeLabel(m_attributeName), 709 m_widgetService.getAttributeHelp(m_attributeName)); 710 if (m_widgetService.isDisplaySingleLine(m_attributeName)) { 711 valueWidget.setCompactMode(CmsAttributeValueView.COMPACT_MODE_SINGLE_LINE); 712 } 713 parent.insert(valueWidget, targetPosition); 714 valueWidget.setValueWidget( 715 m_widgetService.getAttributeFormWidget(m_attributeName), 716 value, 717 m_widgetService.getDefaultAttributeValue(m_attributeName, getSimplePath(targetPosition)), 718 true); 719 } else { 720 removeHandlers(currentPosition); 721 CmsEntity value = m_entity.getAttribute(m_attributeName).getComplexValues().get(currentPosition); 722 m_entity.removeAttributeValue(m_attributeName, currentPosition); 723 m_entity.insertAttributeValue(m_attributeName, value, targetPosition); 724 valueWidget = new CmsAttributeValueView( 725 this, 726 m_widgetService.getAttributeLabel(m_attributeName), 727 m_widgetService.getAttributeHelp(m_attributeName)); 728 parent.insert(valueWidget, targetPosition); 729 insertHandlers(targetPosition); 730 valueWidget.setValueEntity( 731 m_widgetService.getRendererForAttribute(m_attributeName, getAttributeType()), 732 value); 733 if (getAttributeType().getAttributeType(CmsType.CHOICE_ATTRIBUTE_NAME) != null) { 734 List<CmsChoiceMenuEntryBean> menuEntries = CmsRenderer.getChoiceEntries(getAttributeType(), false); 735 for (CmsChoiceMenuEntryBean entry : menuEntries) { 736 valueWidget.addChoice(m_widgetService, entry); 737 } 738 } 739 } 740 m_attributeValueViews.remove(valueWidget); 741 m_attributeValueViews.add(targetPosition, valueWidget); 742 updateButtonVisisbility(); 743 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 744 if (handler.isIntitalized()) { 745 handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.sort); 746 } 747 } 748 749 /** 750 * Moves the reference value down in the value list.<p> 751 * 752 * @param reference the reference value 753 */ 754 public void moveAttributeValueDown(final CmsAttributeValueView reference) { 755 756 final int index = reference.getValueIndex(); 757 if (index >= (m_entity.getAttribute(m_attributeName).getValueCount() - 1)) { 758 return; 759 } 760 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 761 reference.hideAllButtons(); 762 Element parent = reference.getElement().getParentElement(); 763 parent.getStyle().setPosition(Position.RELATIVE); 764 final Element placeHolder = reference.getPlaceholder(null); 765 int top = reference.getElement().getOffsetTop(); 766 int left = reference.getElement().getOffsetLeft(); 767 int width = reference.getOffsetWidth(); 768 reference.getElement().getStyle().setPosition(Position.ABSOLUTE); 769 reference.getElement().getStyle().setZIndex(5); 770 parent.insertAfter(placeHolder, reference.getElement().getNextSibling()); 771 reference.getElement().getStyle().setTop(top, Unit.PX); 772 reference.getElement().getStyle().setLeft(left, Unit.PX); 773 reference.getElement().getStyle().setWidth(width, Unit.PX); 774 new CmsMoveAnimation(reference.getElement(), top, left, placeHolder.getOffsetTop(), left, new Command() { 775 776 public void execute() { 777 778 clearMoveAnimationStyles(placeHolder, reference); 779 moveAttributeValue(reference, index, index + 1); 780 781 } 782 }).run(200); 783 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 784 if (handler.isIntitalized()) { 785 handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.sort); 786 } 787 } 788 789 /** 790 * Moves the reference value up in the value list.<p> 791 * 792 * @param reference the reference value 793 */ 794 public void moveAttributeValueUp(final CmsAttributeValueView reference) { 795 796 final int index = reference.getValueIndex(); 797 if (index == 0) { 798 return; 799 } 800 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 801 reference.hideAllButtons(); 802 Element parent = reference.getElement().getParentElement(); 803 parent.getStyle().setPosition(Position.RELATIVE); 804 final Element placeHolder = reference.getPlaceholder(null); 805 int top = reference.getElement().getOffsetTop(); 806 int left = reference.getElement().getOffsetLeft(); 807 int width = reference.getOffsetWidth(); 808 reference.getElement().getStyle().setPosition(Position.ABSOLUTE); 809 reference.getElement().getStyle().setZIndex(5); 810 parent.insertBefore(placeHolder, reference.getElement().getPreviousSibling()); 811 reference.getElement().getStyle().setTop(top, Unit.PX); 812 reference.getElement().getStyle().setLeft(left, Unit.PX); 813 reference.getElement().getStyle().setWidth(width, Unit.PX); 814 new CmsMoveAnimation(reference.getElement(), top, left, placeHolder.getOffsetTop(), left, new Command() { 815 816 public void execute() { 817 818 clearMoveAnimationStyles(placeHolder, reference); 819 moveAttributeValue(reference, index, index - 1); 820 821 } 822 }).run(200); 823 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 824 if (handler.isIntitalized()) { 825 handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.sort); 826 } 827 } 828 829 /** 830 * Registers an attribute value view.<p> 831 * 832 * @param attributeValue the attribute value view 833 */ 834 public void registerAttributeValue(CmsAttributeValueView attributeValue) { 835 836 m_attributeValueViews.add(attributeValue); 837 } 838 839 /** 840 * Removes the reference attribute value view.<p> 841 * 842 * @param reference the reference view 843 */ 844 public void removeAttributeValue(CmsAttributeValueView reference) { 845 846 removeAttributeValue(reference, false); 847 } 848 849 /** 850 * Removes the reference attribute value view.<p> 851 * 852 * @param reference the reference view 853 * @param force <code>true</code> if the widget should be removed even if it is the last one 854 */ 855 public void removeAttributeValue(CmsAttributeValueView reference, boolean force) { 856 857 CmsAttributeHandler parentHandler = null; 858 CmsAttributeValueView parentView = null; 859 boolean removeParent = false; 860 861 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 862 if (isChoiceHandler() && attribute.isSingleValue()) { 863 // removing last choice value, so remove choice itself 864 parentHandler = (CmsAttributeHandler)m_parentHandler; 865 parentView = reference.getParentView(); 866 removeParent = true; 867 } 868 869 if (attribute.isSingleValue() && !force) { 870 871 reference.removeValue(); 872 if (!attribute.isSimpleValue()) { 873 removeHandlers(0); 874 } 875 m_entity.removeAttribute(m_attributeName); 876 } else { 877 int index = reference.getValueIndex(); 878 if (attribute.isComplexValue()) { 879 removeHandlers(index); 880 CmsEntity value = attribute.getComplexValues().get(index); 881 m_entity.removeAttributeValue(m_attributeName, index); 882 m_entityBackEnd.removeEntity(value.getId()); 883 } else { 884 m_entity.removeAttributeValue(m_attributeName, index); 885 } 886 reference.removeFromParent(); 887 m_attributeValueViews.remove(reference); 888 889 } 890 updateButtonVisisbility(); 891 if (removeParent && (parentHandler != null) && (parentView != null)) { 892 parentHandler.removeAttributeValue(parentView); 893 parentView.setCollapsed(false); 894 } 895 CmsUndoRedoHandler handler = CmsUndoRedoHandler.getInstance(); 896 if (handler.isIntitalized()) { 897 handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.remove); 898 } 899 900 } 901 902 /** 903 * Removes the attribute value from the given index, also manipulating the editor DOM to display the change.<p> 904 * 905 * @param valueIndex the value index 906 */ 907 public void removeAttributeValue(int valueIndex) { 908 909 if (m_attributeValueViews.size() > valueIndex) { 910 removeAttributeValue(m_attributeValueViews.get(valueIndex)); 911 } 912 } 913 914 /** 915 * Removes the attribute value (and corresponding widget) with the given index, and returns 916 * the parent widget.<p> 917 * 918 * @param valueIndex the value index 919 * @param force <code>true</code> if the widget should be removed even if it is the last one 920 * 921 * @return the parent widget 922 */ 923 public Panel removeAttributeValueAndReturnPrevParent(int valueIndex, boolean force) { 924 925 if (m_attributeValueViews.size() > valueIndex) { 926 CmsAttributeValueView view = m_attributeValueViews.get(valueIndex); 927 Panel result = (Panel)view.getParent(); 928 removeAttributeValue(view, force); 929 return result; 930 } 931 return null; 932 933 } 934 935 /** 936 * Removes the attribute value with the given index.<p> 937 * This will not execute any DOM manipulations.<p> 938 * 939 * @param valueIndex the index of the attribute value to remove 940 */ 941 public void removeAttributeValueFromEntity(int valueIndex) { 942 943 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 944 if (attribute.isSingleValue()) { 945 if (attribute.isComplexValue()) { 946 removeHandlers(0); 947 } 948 m_entity.removeAttribute(m_attributeName); 949 } else { 950 if (attribute.isComplexValue()) { 951 removeHandlers(valueIndex); 952 CmsEntity value = attribute.getComplexValues().get(valueIndex); 953 m_entity.removeAttributeValue(m_attributeName, valueIndex); 954 m_entityBackEnd.removeEntity(value.getId()); 955 } else { 956 m_entity.removeAttributeValue(m_attributeName, valueIndex); 957 } 958 } 959 } 960 961 /** 962 * Removes validation messages for all views associated with this attribute handler.<p> 963 */ 964 public void removeValidationMessages() { 965 966 for (CmsAttributeValueView view : m_attributeValueViews) { 967 view.removeValidationMessage(); 968 } 969 } 970 971 /** 972 * Sets the error message for the given value index.<p> 973 * 974 * @param valueIndex the value index 975 * @param message the error message 976 * @param tabbedPanel the forms tabbed panel if available 977 */ 978 public void setErrorMessage(int valueIndex, String message, CmsTabbedPanel<?> tabbedPanel) { 979 980 if (!m_attributeValueViews.isEmpty()) { 981 FlowPanel parent = (FlowPanel)m_attributeValueViews.get(0).getParent(); 982 CmsAttributeValueView valueView = (CmsAttributeValueView)parent.getWidget(valueIndex); 983 valueView.setErrorMessage(message); 984 if (tabbedPanel != null) { 985 int tabIndex = tabbedPanel.getTabIndex(valueView.getElement()); 986 if (tabIndex > -1) { 987 Widget tab = tabbedPanel.getTabWidget(tabIndex); 988 tab.setTitle("This tab has errors."); 989 tab.getParent().removeStyleName(I_CmsLayoutBundle.INSTANCE.form().hasWarning()); 990 tab.getParent().addStyleName(I_CmsLayoutBundle.INSTANCE.form().hasError()); 991 } 992 993 } 994 } 995 } 996 997 /** 998 * @see org.opencms.acacia.client.CmsRootHandler#setHandlerById(java.lang.String, org.opencms.acacia.client.CmsAttributeHandler) 999 */ 1000 @Override 1001 public void setHandlerById(String attributeName, CmsAttributeHandler handler) { 1002 1003 if (m_parentHandler != null) { 1004 m_parentHandler.setHandlerById(attributeName, handler); 1005 } 1006 } 1007 1008 /** 1009 * Sets the parent attribute handler.<p> 1010 * 1011 * @param handler the parent attribute handler 1012 */ 1013 public void setParentHandler(I_CmsAttributeHandler handler) { 1014 1015 m_parentHandler = handler; 1016 } 1017 1018 /** 1019 * Sets the warning message for the given value index.<p> 1020 * 1021 * @param valueIndex the value index 1022 * @param message the warning message 1023 * @param tabbedPanel the forms tabbed panel if available 1024 */ 1025 public void setWarningMessage(int valueIndex, String message, CmsTabbedPanel<?> tabbedPanel) { 1026 1027 if (!m_attributeValueViews.isEmpty()) { 1028 FlowPanel parent = (FlowPanel)m_attributeValueViews.get(0).getParent(); 1029 CmsAttributeValueView valueView = (CmsAttributeValueView)parent.getWidget(valueIndex); 1030 valueView.setWarningMessage(message); 1031 if (tabbedPanel != null) { 1032 int tabIndex = tabbedPanel.getTabIndex(valueView.getElement()); 1033 if (tabIndex > -1) { 1034 Widget tab = tabbedPanel.getTabWidget(tabIndex); 1035 tab.setTitle("This tab has warnings."); 1036 tab.getParent().addStyleName(I_CmsLayoutBundle.INSTANCE.form().hasWarning()); 1037 } 1038 1039 } 1040 } 1041 } 1042 1043 /** 1044 * Updates the add, remove and sort button visibility on the given inline widget or all registered attribute value views.<p> 1045 * 1046 * @param inlineWidget the inline widget 1047 */ 1048 public void updateButtonVisibilty(CmsInlineEntityWidget inlineWidget) { 1049 1050 int minOccurrence = 0; 1051 int maxOccurrence = 0; 1052 if (isChoiceHandler()) { 1053 minOccurrence = 0; 1054 maxOccurrence = getEntityType().getChoiceMaxOccurrence(); 1055 } else { 1056 minOccurrence = getEntityType().getAttributeMinOccurrence(m_attributeName); 1057 maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); 1058 } 1059 CmsEntityAttribute attribute = m_entity.getAttribute(m_attributeName); 1060 boolean mayHaveMore = (maxOccurrence > minOccurrence) 1061 && ((((attribute == null) && (!getAttributeType().isSimpleType() || (inlineWidget != null))) 1062 || ((attribute != null) && (attribute.getValueCount() < maxOccurrence)))); 1063 boolean needsRemove = false; 1064 boolean needsSort = false; 1065 if ((isChoiceHandler() || !getEntityType().isChoice()) && m_entity.hasAttribute(m_attributeName)) { 1066 int valueCount = m_entity.getAttribute(m_attributeName).getValueCount(); 1067 needsRemove = (maxOccurrence > minOccurrence) && (valueCount > minOccurrence); 1068 needsSort = !isSingleValueHandler() && (valueCount > 1); 1069 } 1070 if (inlineWidget != null) { 1071 boolean mayEdit = (attribute != null) && (attribute.getValueCount() > inlineWidget.getAttributeIndex()); 1072 inlineWidget.updateButtonVisibility(mayEdit, mayHaveMore, needsRemove, needsSort); 1073 } else { 1074 for (CmsAttributeValueView value : m_attributeValueViews) { 1075 value.updateButtonVisibility(mayHaveMore, needsRemove, needsSort); 1076 } 1077 } 1078 } 1079 1080 /** 1081 * Updates the add, remove and sort button visibility on all registered attribute value views.<p> 1082 */ 1083 public void updateButtonVisisbility() { 1084 1085 updateButtonVisibilty(null); 1086 } 1087 1088 /** 1089 * Returns if the attribute handler is handling a single value only.<p> 1090 * 1091 * @return <code>true</code> if the attribute handler is handling a single value only 1092 */ 1093 protected boolean isSingleValueHandler() { 1094 1095 return m_singleValueIndex > -1; 1096 } 1097 1098 /** 1099 * Sets the single value index.<p> 1100 * 1101 * @param valueIndex the value index 1102 */ 1103 protected void setSingleValueIndex(int valueIndex) { 1104 1105 m_singleValueIndex = valueIndex; 1106 } 1107 1108 /** 1109 * Clears the inline styles used during move animation.<p> 1110 * 1111 * @param placeHolder the animation place holder 1112 * @param reference the moved attribute widget 1113 */ 1114 void clearMoveAnimationStyles(Element placeHolder, CmsAttributeValueView reference) { 1115 1116 placeHolder.removeFromParent(); 1117 reference.getElement().getParentElement().getStyle().clearPosition(); 1118 reference.getElement().getStyle().clearPosition(); 1119 reference.getElement().getStyle().clearWidth(); 1120 reference.getElement().getStyle().clearZIndex(); 1121 reference.showButtons(); 1122 } 1123 1124 /** 1125 * Adds a new choice option.<p> 1126 * 1127 * @param reference the reference view 1128 * @param choicePath the choice attribute path 1129 */ 1130 private void addChoiceOption(CmsAttributeValueView reference, List<String> choicePath) { 1131 1132 String attributeChoice = choicePath.get(0); 1133 CmsType optionType = getAttributeType().getAttributeType(attributeChoice); 1134 int valueIndex = reference.getValueIndex() + 1; 1135 CmsEntity choiceEntity = m_entityBackEnd.createEntity(null, getAttributeType().getId()); 1136 CmsAttributeValueView valueWidget = reference; 1137 if (reference.hasValue()) { 1138 valueWidget = new CmsAttributeValueView( 1139 this, 1140 m_widgetService.getAttributeLabel(attributeChoice), 1141 m_widgetService.getAttributeHelp(attributeChoice)); 1142 if (optionType.isSimpleType() && m_widgetService.isDisplaySingleLine(attributeChoice)) { 1143 valueWidget.setCompactMode(CmsAttributeValueView.COMPACT_MODE_SINGLE_LINE); 1144 } 1145 } 1146 1147 List<CmsChoiceMenuEntryBean> menuEntries = CmsRenderer.getChoiceEntries(getAttributeType(), true); 1148 for (CmsChoiceMenuEntryBean menuEntry : menuEntries) { 1149 valueWidget.addChoice(m_widgetService, menuEntry); 1150 } 1151 1152 m_entity.insertAttributeValue(m_attributeName, choiceEntity, valueIndex); 1153 ((FlowPanel)reference.getParent()).insert(valueWidget, valueIndex); 1154 insertHandlers(valueWidget.getValueIndex()); 1155 1156 if (optionType.isSimpleType()) { 1157 String defaultValue = m_widgetService.getDefaultAttributeValue(attributeChoice, getSimplePath(valueIndex)); 1158 I_CmsFormEditWidget widget = m_widgetService.getAttributeFormWidget(attributeChoice); 1159 choiceEntity.addAttributeValue(attributeChoice, defaultValue); 1160 valueWidget.setValueWidget(widget, defaultValue, defaultValue, true); 1161 } else { 1162 CmsEntity value = m_entityBackEnd.createEntity(null, optionType.getId()); 1163 choiceEntity.addAttributeValue(attributeChoice, value); 1164 List<String> remainingAttributeNames = tail(choicePath); 1165 createNestedEntitiesForChoicePath(value, remainingAttributeNames); 1166 I_CmsEntityRenderer renderer = m_widgetService.getRendererForAttribute(attributeChoice, optionType); 1167 valueWidget.setValueEntity(renderer, value); 1168 } 1169 updateButtonVisisbility(); 1170 1171 } 1172 1173 /** 1174 * Adds a new complex value which corresponds to a choice element.<p> 1175 * 1176 * @param reference the reference view 1177 * @param choicePath the path of choice attribute names 1178 */ 1179 private void addComplexChoiceValue(CmsAttributeValueView reference, List<String> choicePath) { 1180 1181 CmsEntity value = m_entityBackEnd.createEntity(null, getAttributeType().getId()); 1182 CmsEntity parentValue = value; 1183 for (String attributeChoice : choicePath) { 1184 CmsType choiceType = m_entityBackEnd.getType(parentValue.getTypeName()).getAttributeType( 1185 CmsType.CHOICE_ATTRIBUTE_NAME); 1186 CmsEntity choice = m_entityBackEnd.createEntity(null, choiceType.getId()); 1187 parentValue.addAttributeValue(CmsType.CHOICE_ATTRIBUTE_NAME, choice); 1188 CmsType choiceOptionType = choiceType.getAttributeType(attributeChoice); 1189 if (choiceOptionType.isSimpleType()) { 1190 String choiceValue = m_widgetService.getDefaultAttributeValue(attributeChoice, getSimplePath(0)); 1191 choice.addAttributeValue(attributeChoice, choiceValue); 1192 break; 1193 } else { 1194 CmsEntity choiceValue = m_entityBackEnd.createEntity(null, choiceOptionType.getId()); 1195 choice.addAttributeValue(attributeChoice, choiceValue); 1196 parentValue = choiceValue; 1197 } 1198 } 1199 insertValueAfterReference(value, reference); 1200 if (getMaxOccurence() == 1) { 1201 reference.setCollapsed(true); 1202 } 1203 } 1204 1205 /** 1206 * Changes the attribute value.<p> 1207 * 1208 * @param valueIndex the attribute value index 1209 * @param value the value 1210 */ 1211 private void changeEntityValue(String value, int valueIndex) { 1212 1213 if (getEntityType().isChoice()) { 1214 CmsEntity choice = m_entity.getAttribute(CmsType.CHOICE_ATTRIBUTE_NAME).getComplexValues().get(valueIndex); 1215 String attributeName = getChoiceName(valueIndex); 1216 if (attributeName != null) { 1217 choice.setAttributeValue(attributeName, value, 0); 1218 } 1219 } else { 1220 m_entity.setAttributeValue(m_attributeName, value, valueIndex); 1221 } 1222 } 1223 1224 /** 1225 * Returns the attribute choice name for the given index.<p> 1226 * 1227 * @param valueIndex the value index 1228 * 1229 * @return the attribute choice name 1230 */ 1231 private String getChoiceName(int valueIndex) { 1232 1233 if (isChoiceHandler()) { 1234 CmsEntity choice = m_entity.getAttribute(CmsType.CHOICE_ATTRIBUTE_NAME).getComplexValues().get(valueIndex); 1235 if (choice != null) { 1236 for (String option : getAttributeType().getAttributeNames()) { 1237 if (choice.hasAttribute(option)) { 1238 return option; 1239 1240 } 1241 } 1242 } 1243 } 1244 return null; 1245 } 1246 1247 /** 1248 * Returns the entity type.<p> 1249 * 1250 * @return the entity type 1251 */ 1252 private CmsType getEntityType() { 1253 1254 if (m_entityType == null) { 1255 m_entityType = m_entityBackEnd.getType(m_entity.getTypeName()); 1256 } 1257 return m_entityType; 1258 } 1259 1260 /** 1261 * Inserts an entity value after the given reference.<p> 1262 * 1263 * @param value the entity value 1264 * @param reference the reference 1265 */ 1266 private void insertValueAfterReference(CmsEntity value, CmsAttributeValueView reference) { 1267 1268 int valueIndex = -1; 1269 if (reference.getElement().getNextSiblingElement() == null) { 1270 m_entity.addAttributeValue(m_attributeName, value); 1271 } else { 1272 valueIndex = reference.getValueIndex() + 1; 1273 m_entity.insertAttributeValue(m_attributeName, value, valueIndex); 1274 } 1275 CmsAttributeValueView valueWidget = reference; 1276 if (reference.hasValue()) { 1277 valueWidget = new CmsAttributeValueView( 1278 this, 1279 m_widgetService.getAttributeLabel(m_attributeName), 1280 m_widgetService.getAttributeHelp(m_attributeName)); 1281 CmsRenderer.setAttributeChoice(m_widgetService, valueWidget, getAttributeType()); 1282 if (valueIndex == -1) { 1283 ((FlowPanel)reference.getParent()).add(valueWidget); 1284 m_attributeValueViews.remove(valueWidget); 1285 m_attributeValueViews.add(valueWidget); 1286 } else { 1287 ((FlowPanel)reference.getParent()).insert(valueWidget, valueIndex); 1288 m_attributeValueViews.remove(valueWidget); 1289 m_attributeValueViews.add(valueIndex, valueWidget); 1290 m_widgetService.addChangedOrderPath(getSimplePath(-1)); 1291 } 1292 1293 } 1294 valueIndex = valueWidget.getValueIndex(); 1295 insertHandlers(valueIndex); 1296 I_CmsEntityRenderer renderer = m_widgetService.getRendererForAttribute(m_attributeName, getAttributeType()); 1297 valueWidget.setValueEntity(renderer, value); 1298 } 1299 1300 /** 1301 * Creates a list consisting of all but the first element of another list.<p> 1302 * 1303 * @param values the list 1304 * 1305 * @return the tail of the list 1306 */ 1307 private List<String> tail(List<String> values) { 1308 1309 List<String> result = new ArrayList<String>(); 1310 boolean first = true; 1311 for (String value : values) { 1312 if (!first) { 1313 result.add(value); 1314 } 1315 first = false; 1316 } 1317 return result; 1318 1319 } 1320}