Java tutorial
/* * This library is part of the Acacia Editor - * an open source inline and form based content editor for GWT. * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.alkacon.acacia.client; import com.alkacon.acacia.client.UndoRedoHandler.ChangeType; import com.alkacon.acacia.client.css.I_LayoutBundle; import com.alkacon.acacia.client.ui.AttributeValueView; import com.alkacon.acacia.client.ui.InlineEntityWidget; import com.alkacon.acacia.client.widgets.I_FormEditWidget; import com.alkacon.acacia.shared.Type; import com.alkacon.geranium.client.dnd.DNDHandler; import com.alkacon.geranium.client.dnd.DNDHandler.Orientation; import com.alkacon.geranium.client.ui.TabbedPanel; import com.alkacon.geranium.client.util.MoveAnimation; import com.alkacon.vie.client.I_Vie; import com.alkacon.vie.shared.I_Entity; import com.alkacon.vie.shared.I_EntityAttribute; import com.alkacon.vie.shared.I_Type; import java.util.ArrayList; import java.util.List; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; /** * The attribute handler. Handles value changes, addition of new values, remove and move operations on values.<p> */ public class AttributeHandler extends RootHandler { /** The global widget resize handler. */ private static ResizeHandler m_resizeHandler; /** The scroll element. */ private static Element m_scrollElement; /** The attribute name. */ private String m_attributeName; /** The attribute type. */ private I_Type m_attributeType; /** Registered attribute values. */ private List<AttributeValueView> m_attributeValueViews; /** The attribute drag and drop handler. */ private DNDHandler m_dndHandler; /** The entity. */ private I_Entity m_entity; /** The entity type. */ private I_Type m_entityType; /** The parent attribute handler. */ private I_AttributeHandler m_parentHandler; /** The single value index. */ private int m_singleValueIndex; /** The VIE instance. */ private I_Vie m_vie; /** The widget service. */ private I_WidgetService m_widgetService; /** * Constructor.<p> * * @param vie the VIE instance * @param entity the entity * @param attributeName the attribute name * @param widgetService the widget service */ public AttributeHandler(I_Vie vie, I_Entity entity, String attributeName, I_WidgetService widgetService) { // single value handling is disable by default m_singleValueIndex = -1; m_vie = vie; m_entity = entity; m_attributeName = attributeName; m_widgetService = widgetService; m_attributeValueViews = new ArrayList<AttributeValueView>(); if (!getAttributeType().isSimpleType()) { int count = 0; I_EntityAttribute attribute = entity.getAttribute(attributeName); if (attribute != null) { count = attribute.getValueCount(); } initHandlers(count); } } /** * Clears the error styles on the given tabbed panel.<p> * * @param tabbedPanel the tabbed panel */ public static void clearErrorStyles(TabbedPanel<?> tabbedPanel) { for (int i = 0; i < tabbedPanel.getTabCount(); i++) { Widget tab = tabbedPanel.getTabWidget(i); tab.setTitle(null); tab.getParent().removeStyleName(I_LayoutBundle.INSTANCE.form().hasError()); tab.getParent().removeStyleName(I_LayoutBundle.INSTANCE.form().hasWarning()); } } /** * Returns the global widget resize handler.<p> * * @return the global widget resize handler */ public static ResizeHandler getResizeHandler() { return m_resizeHandler; } /** * Returns <code>true</code> if a global widget resize handler is present.<p> * * @return <code>true</code> if a global widget resize handler is present */ public static boolean hasResizeHandler() { return m_resizeHandler != null; } /** * Sets the global widget resize handler.<p> * * @param handler the resize handler */ public static void setResizeHandler(ResizeHandler handler) { m_resizeHandler = handler; } /** * Sets the scroll element. To be used for automatic scrolling during drag and drop.<p> * * @param scrollElement the scroll element */ public static void setScrollElement(Element scrollElement) { m_scrollElement = scrollElement; } /** * Returns the entity id.<p> * * @return the entity id */ public String getEntityId() { return m_entity.getId(); } /** * @see com.alkacon.acacia.client.RootHandler#setHandlerById(java.lang.String, com.alkacon.acacia.client.AttributeHandler) */ @Override public void setHandlerById(String attributeName, AttributeHandler handler) { if (m_parentHandler != null) { m_parentHandler.setHandlerById(attributeName, handler); } } /** * Adds a new attribute value below the reference view.<p> * * @param reference the reference value view */ public void addNewAttributeValue(AttributeValueView reference) { // make sure not to add more values than allowed int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); I_EntityAttribute attribute = m_entity.getAttribute(m_attributeName); boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); if (mayHaveMore) { if (getAttributeType().isSimpleType()) { String defaultValue = m_widgetService.getDefaultAttributeValue(m_attributeName); I_FormEditWidget widget = m_widgetService.getAttributeFormWidget(m_attributeName); int valueIndex = -1; if (reference.getElement().getNextSiblingElement() == null) { m_entity.addAttributeValue(m_attributeName, defaultValue); } else { valueIndex = reference.getValueIndex() + 1; m_entity.insertAttributeValue(m_attributeName, defaultValue, valueIndex); } AttributeValueView valueWidget = reference; if (reference.hasValue()) { valueWidget = new AttributeValueView(this, m_widgetService.getAttributeLabel(m_attributeName), m_widgetService.getAttributeHelp(m_attributeName)); if (m_widgetService.isDisplaySingleLine(m_attributeName)) { valueWidget.setCompactMode(AttributeValueView.COMPACT_MODE_SINGLE_LINE); } if (valueIndex == -1) { ((FlowPanel) reference.getParent()).add(valueWidget); } else { ((FlowPanel) reference.getParent()).insert(valueWidget, valueIndex); } } valueWidget.setValueWidget(widget, defaultValue, defaultValue, true); } else { I_Entity value = m_vie.createEntity(null, getAttributeType().getId()); insertValueAfterReference(value, reference); } UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, reference.getValueIndex() + 1, ChangeType.add); } } updateButtonVisisbility(); } /** * Adds a new attribute value below the reference index.<p> * * @param referenceIndex the reference value index */ public void addNewAttributeValue(int referenceIndex) { // make sure not to add more values than allowed int maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); I_EntityAttribute attribute = m_entity.getAttribute(m_attributeName); boolean mayHaveMore = ((attribute == null) || (attribute.getValueCount() < maxOccurrence)); if (mayHaveMore) { if (getAttributeType().isSimpleType()) { String defaultValue = m_widgetService.getDefaultAttributeValue(m_attributeName); if ((attribute == null) || (attribute.getValueCount() == (referenceIndex + 1))) { m_entity.addAttributeValue(m_attributeName, defaultValue); } else { m_entity.insertAttributeValue(m_attributeName, defaultValue, referenceIndex + 1); } } else { I_Entity value = m_vie.createEntity(null, m_attributeType.getId()); if ((attribute == null) || (attribute.getValueCount() == (referenceIndex + 1))) { m_entity.addAttributeValue(m_attributeName, value); } else { m_entity.insertAttributeValue(m_attributeName, value, referenceIndex + 1); } insertHandlers(referenceIndex + 1); } } } /** * Adds a new choice attribute value.<p> * * @param reference the reference value view * @param choicePath the path of the selected (possibly nested) choice attribute, consisting of attribute names */ public void addNewChoiceAttributeValue(AttributeValueView reference, List<String> choicePath) { ValueFocusHandler.getInstance().clearFocus(); if (isChoiceHandler()) { addChoiceOption(reference, choicePath); } else { addComplexChoiceValue(reference, choicePath); } updateButtonVisisbility(); UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, reference.getValueIndex() + 1, ChangeType.choice); } } /** * Handles value changes from the view.<p> * * @param reference the attribute value reference * @param value the value */ public void handleValueChange(AttributeValueView reference, String value) { handleValueChange(reference.getValueIndex(), value); } /** * Handles value changes from the view.<p> * * @param valueIndex the value index * @param value the value */ public void handleValueChange(int valueIndex, String value) { changeEntityValue(value, valueIndex); UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, valueIndex, ChangeType.value); } } /** * Applies a value change to the entity data as well as to the value view widget.<p> * * @param value the value * @param valueIndex the value index */ public void changeValue(String value, int valueIndex) { m_attributeValueViews.get(valueIndex).getValueWidget().setValue(value, false); changeEntityValue(value, valueIndex); } /** * Creates a sequence of nested entities according to a given path of choice attribute names.<p> * * @param value the entity into which the new entities for the given path should be inserted * @param choicePath the path of choice attributes */ public void createNestedEntitiesForChoicePath(I_Entity value, List<String> choicePath) { I_Entity parentValue = value; for (String attributeChoice : choicePath) { I_Type choiceType = m_vie.getType(parentValue.getTypeName()) .getAttributeType(Type.CHOICE_ATTRIBUTE_NAME); I_Entity choice = m_vie.createEntity(null, choiceType.getId()); parentValue.addAttributeValue(Type.CHOICE_ATTRIBUTE_NAME, choice); I_Type choiceOptionType = choiceType.getAttributeType(attributeChoice); if (choiceOptionType.isSimpleType()) { String choiceValue = m_widgetService.getDefaultAttributeValue(attributeChoice); choice.addAttributeValue(attributeChoice, choiceValue); break; } else { I_Entity choiceValue = m_vie.createEntity(null, choiceOptionType.getId()); choice.addAttributeValue(attributeChoice, choiceValue); parentValue = choiceValue; } } } /** * Destroys the attribute handler instance.<p> */ public void destroy() { m_attributeName = null; m_attributeType = null; m_attributeValueViews.clear(); m_attributeValueViews = null; m_dndHandler = null; m_entity = null; m_entityType = null; m_vie = null; m_widgetService = null; } /** * Returns the attribute name.<p> * * @return the attribute name */ public String getAttributeName() { return m_attributeName; } /** * Returns the attribute type.<p> * * @return the attribute type */ public I_Type getAttributeType() { if (m_attributeType == null) { m_attributeType = getEntityType().getAttributeType(m_attributeName); } return m_attributeType; } /** * Returns the drag and drop handler.<p> * * @return the drag and drop handler */ public DNDHandler getDNDHandler() { if (m_dndHandler == null) { m_dndHandler = new DNDHandler(new AttributeDNDController()); m_dndHandler.setOrientation(Orientation.VERTICAL); m_dndHandler.setScrollEnabled(true); m_dndHandler.setScrollElement(m_scrollElement); } return m_dndHandler; } /** * Gets the maximum occurrence of the attribute.<p> * * @return the maximum occurrence */ public int getMaxOccurence() { return getEntityType().getAttributeMaxOccurrence(m_attributeName); } /** * Gets the widget service.<p> * * @return the widget service */ public I_WidgetService getWidgetService() { return m_widgetService; } /** * Return true if there is a single remaining value, which is optional.<p> * * @return true if this has only one optional value */ public boolean hasSingleOptionalValue() { return ((getEntityType().getAttributeMinOccurrence(m_attributeName) == 0) && (m_entity.getAttribute(m_attributeName) != null) && (m_entity.getAttribute(m_attributeName).getValueCount() == 1)); } /** * Returns if there is a value view widget registered for the given index.<p> * * @param valueIndex the value index * * @return <code>true</code> if there is a value view widget registered for the given index */ public boolean hasValueView(int valueIndex) { return m_attributeValueViews.size() > valueIndex; } /** * Returns if this is a choice handler.<p> * * @return <code>true</code> if this is a choice handler */ public boolean isChoiceHandler() { return Type.CHOICE_ATTRIBUTE_NAME.equals(m_attributeName); } /** * Moves the give attribute value from one position to another.<p> * * @param valueView the value to move * @param currentPosition the current position * @param targetPosition the target position */ public void moveAttributeValue(AttributeValueView valueView, int currentPosition, int targetPosition) { if (currentPosition == targetPosition) { return; } FlowPanel parent = (FlowPanel) valueView.getParent(); valueView.removeFromParent(); m_attributeValueViews.remove(valueView); AttributeValueView valueWidget = null; if (isChoiceHandler()) { removeHandlers(currentPosition); I_Entity value = m_entity.getAttribute(m_attributeName).getComplexValues().get(currentPosition); m_entity.removeAttributeValue(m_attributeName, currentPosition); m_entity.insertAttributeValue(m_attributeName, value, targetPosition); String attributeChoice = getChoiceName(targetPosition); I_Type optionType = getAttributeType().getAttributeType(attributeChoice); valueWidget = new AttributeValueView(this, m_widgetService.getAttributeLabel(attributeChoice), m_widgetService.getAttributeHelp(attributeChoice)); if (optionType.isSimpleType() && m_widgetService.isDisplaySingleLine(attributeChoice)) { valueWidget.setCompactMode(AttributeValueView.COMPACT_MODE_SINGLE_LINE); } parent.insert(valueWidget, targetPosition); insertHandlers(targetPosition); if (optionType.isSimpleType()) { valueWidget.setValueWidget(m_widgetService.getAttributeFormWidget(attributeChoice), value.getAttribute(attributeChoice).getSimpleValue(), m_widgetService.getDefaultAttributeValue(attributeChoice), true); } else { valueWidget.setValueEntity( m_widgetService.getRendererForAttribute(attributeChoice, getAttributeType()), value.getAttribute(attributeChoice).getComplexValue()); } List<ChoiceMenuEntryBean> menuEntries = Renderer.getChoiceEntries(getAttributeType(), true); for (ChoiceMenuEntryBean menuEntry : menuEntries) { valueWidget.addChoice(m_widgetService, menuEntry); } } else if (getAttributeType().isSimpleType()) { String value = m_entity.getAttribute(m_attributeName).getSimpleValues().get(currentPosition); m_entity.removeAttributeValue(m_attributeName, currentPosition); m_entity.insertAttributeValue(m_attributeName, value, targetPosition); valueWidget = new AttributeValueView(this, m_widgetService.getAttributeLabel(m_attributeName), m_widgetService.getAttributeHelp(m_attributeName)); if (m_widgetService.isDisplaySingleLine(m_attributeName)) { valueWidget.setCompactMode(AttributeValueView.COMPACT_MODE_SINGLE_LINE); } parent.insert(valueWidget, targetPosition); valueWidget.setValueWidget(m_widgetService.getAttributeFormWidget(m_attributeName), value, m_widgetService.getDefaultAttributeValue(m_attributeName), true); } else { removeHandlers(currentPosition); I_Entity value = m_entity.getAttribute(m_attributeName).getComplexValues().get(currentPosition); m_entity.removeAttributeValue(m_attributeName, currentPosition); m_entity.insertAttributeValue(m_attributeName, value, targetPosition); valueWidget = new AttributeValueView(this, m_widgetService.getAttributeLabel(m_attributeName), m_widgetService.getAttributeHelp(m_attributeName)); parent.insert(valueWidget, targetPosition); insertHandlers(targetPosition); valueWidget.setValueEntity(m_widgetService.getRendererForAttribute(m_attributeName, getAttributeType()), value); } updateButtonVisisbility(); UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.sort); } } /** * Moves the reference value down in the value list.<p> * * @param reference the reference value */ public void moveAttributeValueDown(final AttributeValueView reference) { final int index = reference.getValueIndex(); if (index >= (m_entity.getAttribute(m_attributeName).getValueCount() - 1)) { return; } reference.hideAllButtons(); Element parent = reference.getElement().getParentElement(); parent.getStyle().setPosition(Position.RELATIVE); final Element placeHolder = reference.getPlaceholder(null); int top = reference.getElement().getOffsetTop(); int left = reference.getElement().getOffsetLeft(); int width = reference.getOffsetWidth(); reference.getElement().getStyle().setPosition(Position.ABSOLUTE); reference.getElement().getStyle().setZIndex(5); parent.insertAfter(placeHolder, reference.getElement().getNextSibling()); reference.getElement().getStyle().setTop(top, Unit.PX); reference.getElement().getStyle().setLeft(left, Unit.PX); reference.getElement().getStyle().setWidth(width, Unit.PX); new MoveAnimation(reference.getElement(), top, left, placeHolder.getOffsetTop(), left, new Command() { public void execute() { clearMoveAnimationStyles(placeHolder, reference); moveAttributeValue(reference, index, index + 1); } }).run(200); UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.sort); } } /** * Moves the reference value up in the value list.<p> * * @param reference the reference value */ public void moveAttributeValueUp(final AttributeValueView reference) { final int index = reference.getValueIndex(); if (index == 0) { return; } reference.hideAllButtons(); Element parent = reference.getElement().getParentElement(); parent.getStyle().setPosition(Position.RELATIVE); final Element placeHolder = reference.getPlaceholder(null); int top = reference.getElement().getOffsetTop(); int left = reference.getElement().getOffsetLeft(); int width = reference.getOffsetWidth(); reference.getElement().getStyle().setPosition(Position.ABSOLUTE); reference.getElement().getStyle().setZIndex(5); parent.insertBefore(placeHolder, reference.getElement().getPreviousSibling()); reference.getElement().getStyle().setTop(top, Unit.PX); reference.getElement().getStyle().setLeft(left, Unit.PX); reference.getElement().getStyle().setWidth(width, Unit.PX); new MoveAnimation(reference.getElement(), top, left, placeHolder.getOffsetTop(), left, new Command() { public void execute() { clearMoveAnimationStyles(placeHolder, reference); moveAttributeValue(reference, index, index - 1); } }).run(200); UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.sort); } } /** * Registers an attribute value view.<p> * * @param attributeValue the attribute value view */ public void registerAttributeValue(AttributeValueView attributeValue) { m_attributeValueViews.add(attributeValue); } /** * Removes the reference attribute value view.<p> * * @param reference the reference view */ public void removeAttributeValue(AttributeValueView reference) { AttributeHandler parentHandler = null; AttributeValueView parentView = null; boolean removeParent = false; I_EntityAttribute attribute = m_entity.getAttribute(m_attributeName); if (isChoiceHandler() && attribute.isSingleValue()) { // removing last choice value, so remove choice itself parentHandler = (AttributeHandler) m_parentHandler; parentView = reference.getParentView(); removeParent = true; } if (attribute.isSingleValue()) { reference.removeValue(); if (!attribute.isSimpleValue()) { removeHandlers(0); } m_entity.removeAttribute(m_attributeName); } else { int index = reference.getValueIndex(); if (attribute.isComplexValue()) { removeHandlers(index); } m_entity.removeAttributeValue(m_attributeName, index); reference.removeFromParent(); m_attributeValueViews.remove(reference); } updateButtonVisisbility(); if (removeParent && (parentHandler != null) && (parentView != null)) { parentHandler.removeAttributeValue(parentView); parentView.setCollapsed(false); } UndoRedoHandler handler = UndoRedoHandler.getInstance(); if (handler.isIntitalized()) { handler.addChange(m_entity.getId(), m_attributeName, 0, ChangeType.remove); } } /** * Removes the attribute value with the given index.<p> * This will not execute any DOM manipulations.<p> * * @param valueIndex the index of the attribute value to remove */ public void removeAttributeValue(int valueIndex) { I_EntityAttribute attribute = m_entity.getAttribute(m_attributeName); if (attribute.isSingleValue()) { if (attribute.isComplexValue()) { removeHandlers(0); } m_entity.removeAttribute(m_attributeName); } else { if (attribute.isComplexValue()) { removeHandlers(valueIndex); } m_entity.removeAttributeValue(m_attributeName, valueIndex); } } /** * Sets the error message for the given value index.<p> * * @param valueIndex the value index * @param message the error message * @param tabbedPanel the forms tabbed panel if available */ public void setErrorMessage(int valueIndex, String message, TabbedPanel<?> tabbedPanel) { if (!m_attributeValueViews.isEmpty()) { FlowPanel parent = (FlowPanel) m_attributeValueViews.get(0).getParent(); AttributeValueView valueView = (AttributeValueView) parent.getWidget(valueIndex); valueView.setErrorMessage(message); if (tabbedPanel != null) { int tabIndex = tabbedPanel.getTabIndex(valueView.getElement()); if (tabIndex > -1) { Widget tab = tabbedPanel.getTabWidget(tabIndex); tab.setTitle("This tab has errors."); tab.getParent().removeStyleName(I_LayoutBundle.INSTANCE.form().hasWarning()); tab.getParent().addStyleName(I_LayoutBundle.INSTANCE.form().hasError()); } } } } /** * Sets the parent attribute handler.<p> * * @param handler the parent attribute handler */ public void setParentHandler(I_AttributeHandler handler) { m_parentHandler = handler; } /** * Sets the warning message for the given value index.<p> * * @param valueIndex the value index * @param message the warning message * @param tabbedPanel the forms tabbed panel if available */ public void setWarningMessage(int valueIndex, String message, TabbedPanel<?> tabbedPanel) { if (!m_attributeValueViews.isEmpty()) { FlowPanel parent = (FlowPanel) m_attributeValueViews.get(0).getParent(); AttributeValueView valueView = (AttributeValueView) parent.getWidget(valueIndex); valueView.setWarningMessage(message); if (tabbedPanel != null) { int tabIndex = tabbedPanel.getTabIndex(valueView.getElement()); if (tabIndex > -1) { Widget tab = tabbedPanel.getTabWidget(tabIndex); tab.setTitle("This tab has warnings."); tab.getParent().addStyleName(I_LayoutBundle.INSTANCE.form().hasWarning()); } } } } /** * Updates the add, remove and sort button visibility on the given inline widget or all registered attribute value views.<p> * * @param inlineWidget the inline widget */ public void updateButtonVisibilty(InlineEntityWidget inlineWidget) { int minOccurrence = 0; int maxOccurrence = 0; if (isChoiceHandler()) { minOccurrence = 0; maxOccurrence = getEntityType().getChoiceMaxOccurrence(); } else { minOccurrence = getEntityType().getAttributeMinOccurrence(m_attributeName); maxOccurrence = getEntityType().getAttributeMaxOccurrence(m_attributeName); } I_EntityAttribute attribute = m_entity.getAttribute(m_attributeName); boolean mayHaveMore = (maxOccurrence > minOccurrence) && ((((attribute == null) && (!getAttributeType().isSimpleType() || (inlineWidget != null))) || ((attribute != null) && (attribute.getValueCount() < maxOccurrence)))); boolean needsRemove = false; boolean needsSort = false; if ((isChoiceHandler() || !getEntityType().isChoice()) && m_entity.hasAttribute(m_attributeName)) { int valueCount = m_entity.getAttribute(m_attributeName).getValueCount(); needsRemove = (maxOccurrence > minOccurrence) && (valueCount > minOccurrence); needsSort = !isSingleValueHandler() && (valueCount > 1); } if (inlineWidget != null) { boolean mayEdit = (attribute != null) && (attribute.getValueCount() > inlineWidget.getAttributeIndex()); inlineWidget.updateButtonVisibility(mayEdit, mayHaveMore, needsRemove, needsSort); } else { for (AttributeValueView value : m_attributeValueViews) { value.updateButtonVisibility(mayHaveMore, needsRemove, needsSort); } } } /** * Updates the add, remove and sort button visibility on all registered attribute value views.<p> */ public void updateButtonVisisbility() { updateButtonVisibilty(null); } /** * Returns if the attribute handler is handling a single value only.<p> * * @return <code>true</code> if the attribute handler is handling a single value only */ protected boolean isSingleValueHandler() { return m_singleValueIndex > -1; } /** * Sets the single value index.<p> * * @param valueIndex the value index */ protected void setSingleValueIndex(int valueIndex) { m_singleValueIndex = valueIndex; } /** * Clears the inline styles used during move animation.<p> * * @param placeHolder the animation place holder * @param reference the moved attribute widget */ void clearMoveAnimationStyles(Element placeHolder, AttributeValueView reference) { placeHolder.removeFromParent(); reference.getElement().getParentElement().getStyle().clearPosition(); reference.getElement().getStyle().clearPosition(); reference.getElement().getStyle().clearWidth(); reference.getElement().getStyle().clearZIndex(); reference.showButtons(); } /** * Adds a new choice option.<p> * * @param reference the reference view * @param choicePath the choice attribute path */ private void addChoiceOption(AttributeValueView reference, List<String> choicePath) { String attributeChoice = choicePath.get(0); I_Type optionType = getAttributeType().getAttributeType(attributeChoice); int valueIndex = reference.getValueIndex() + 1; I_Entity choiceEntity = m_vie.createEntity(null, getAttributeType().getId()); AttributeValueView valueWidget = reference; if (reference.hasValue()) { valueWidget = new AttributeValueView(this, m_widgetService.getAttributeLabel(attributeChoice), m_widgetService.getAttributeHelp(attributeChoice)); if (optionType.isSimpleType() && m_widgetService.isDisplaySingleLine(attributeChoice)) { valueWidget.setCompactMode(AttributeValueView.COMPACT_MODE_SINGLE_LINE); } } List<ChoiceMenuEntryBean> menuEntries = Renderer.getChoiceEntries(getAttributeType(), true); for (ChoiceMenuEntryBean menuEntry : menuEntries) { valueWidget.addChoice(m_widgetService, menuEntry); } m_entity.insertAttributeValue(m_attributeName, choiceEntity, valueIndex); ((FlowPanel) reference.getParent()).insert(valueWidget, valueIndex); insertHandlers(valueWidget.getValueIndex()); if (optionType.isSimpleType()) { String defaultValue = m_widgetService.getDefaultAttributeValue(attributeChoice); I_FormEditWidget widget = m_widgetService.getAttributeFormWidget(attributeChoice); choiceEntity.addAttributeValue(attributeChoice, defaultValue); valueWidget.setValueWidget(widget, defaultValue, defaultValue, true); } else { I_Entity value = m_vie.createEntity(null, optionType.getId()); choiceEntity.addAttributeValue(attributeChoice, value); List<String> remainingAttributeNames = tail(choicePath); createNestedEntitiesForChoicePath(value, remainingAttributeNames); I_EntityRenderer renderer = m_widgetService.getRendererForAttribute(attributeChoice, optionType); valueWidget.setValueEntity(renderer, value); } updateButtonVisisbility(); } /** * Adds a new complex value which corresponds to a choice element.<p> * * @param reference the reference view * @param choicePath the path of choice attribute names */ private void addComplexChoiceValue(AttributeValueView reference, List<String> choicePath) { I_Entity value = m_vie.createEntity(null, getAttributeType().getId()); I_Entity parentValue = value; for (String attributeChoice : choicePath) { I_Type choiceType = m_vie.getType(parentValue.getTypeName()) .getAttributeType(Type.CHOICE_ATTRIBUTE_NAME); I_Entity choice = m_vie.createEntity(null, choiceType.getId()); parentValue.addAttributeValue(Type.CHOICE_ATTRIBUTE_NAME, choice); I_Type choiceOptionType = choiceType.getAttributeType(attributeChoice); if (choiceOptionType.isSimpleType()) { String choiceValue = m_widgetService.getDefaultAttributeValue(attributeChoice); choice.addAttributeValue(attributeChoice, choiceValue); break; } else { I_Entity choiceValue = m_vie.createEntity(null, choiceOptionType.getId()); choice.addAttributeValue(attributeChoice, choiceValue); parentValue = choiceValue; } } insertValueAfterReference(value, reference); if (getMaxOccurence() == 1) { reference.setCollapsed(true); } } /** * Changes the attribute value.<p> * * @param valueIndex the attribute value index * @param value the value */ private void changeEntityValue(String value, int valueIndex) { if (getEntityType().isChoice()) { I_Entity choice = m_entity.getAttribute(Type.CHOICE_ATTRIBUTE_NAME).getComplexValues().get(valueIndex); String attributeName = getChoiceName(valueIndex); if (attributeName != null) { choice.setAttributeValue(attributeName, value, 0); } } else { m_entity.setAttributeValue(m_attributeName, value, valueIndex); } } /** * Returns the attribute choice name for the given index.<p> * * @param valueIndex the value index * * @return the attribute choice name */ private String getChoiceName(int valueIndex) { if (isChoiceHandler()) { I_Entity choice = m_entity.getAttribute(Type.CHOICE_ATTRIBUTE_NAME).getComplexValues().get(valueIndex); if (choice != null) { for (String option : getAttributeType().getAttributeNames()) { if (choice.hasAttribute(option)) { return option; } } } } return null; } /** * Returns the entity type.<p> * * @return the entity type */ private I_Type getEntityType() { if (m_entityType == null) { m_entityType = m_vie.getType(m_entity.getTypeName()); } return m_entityType; } /** * Inserts an entity value after the given reference.<p> * * @param value the entity value * @param reference the reference */ private void insertValueAfterReference(I_Entity value, AttributeValueView reference) { int valueIndex = -1; if (reference.getElement().getNextSiblingElement() == null) { m_entity.addAttributeValue(m_attributeName, value); } else { valueIndex = reference.getValueIndex() + 1; m_entity.insertAttributeValue(m_attributeName, value, valueIndex); } AttributeValueView valueWidget = reference; if (reference.hasValue()) { valueWidget = new AttributeValueView(this, m_widgetService.getAttributeLabel(m_attributeName), m_widgetService.getAttributeHelp(m_attributeName)); Renderer.setAttributeChoice(m_widgetService, valueWidget, getAttributeType()); if (valueIndex == -1) { ((FlowPanel) reference.getParent()).add(valueWidget); } else { ((FlowPanel) reference.getParent()).insert(valueWidget, valueIndex); } } valueIndex = valueWidget.getValueIndex(); insertHandlers(valueIndex); I_EntityRenderer renderer = m_widgetService.getRendererForAttribute(m_attributeName, getAttributeType()); valueWidget.setValueEntity(renderer, value); } /** * Creates a list consisting of all but the first element of another list.<p> * * @param values the list * * @return the tail of the list */ private List<String> tail(List<String> values) { List<String> result = new ArrayList<String>(); boolean first = true; for (String value : values) { if (!first) { result.add(value); } first = false; } return result; } }