/* * Copyright (c) 2010, grossmann, Lukas Gross * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the jo-widgets.org nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL jo-widgets.org BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.jowidgets.impl.widgets.basic; import java.util.LinkedList; import java.util.List; import org.jowidgets.api.command.IAction; import org.jowidgets.api.controller.IDisposeListener; import org.jowidgets.api.controller.IParentListener; import org.jowidgets.api.model.IListItemListener; import org.jowidgets.api.model.IListItemObservable; import org.jowidgets.api.model.IListModelListener; import org.jowidgets.api.model.item.IActionItemModel; import org.jowidgets.api.model.item.ICheckedItemModel; import org.jowidgets.api.model.item.IContainerItemModel; import org.jowidgets.api.model.item.IItemModel; import org.jowidgets.api.model.item.IItemModelListener; import org.jowidgets.api.model.item.IMenuModel; import org.jowidgets.api.model.item.IPopupActionItemModel; import org.jowidgets.api.model.item.ISeparatorItemModel; import org.jowidgets.api.model.item.IToolBarItemModel; import org.jowidgets.api.model.item.IToolBarModel; import org.jowidgets.api.toolkit.Toolkit; import org.jowidgets.api.widgets.IContainer; import org.jowidgets.api.widgets.IPopupMenu; import org.jowidgets.api.widgets.IToolBar; import org.jowidgets.api.widgets.IToolBarButton; import org.jowidgets.api.widgets.IToolBarContainerItem; import org.jowidgets.api.widgets.IToolBarItem; import org.jowidgets.api.widgets.IToolBarMenu; import org.jowidgets.api.widgets.IToolBarPopupButton; import org.jowidgets.api.widgets.IToolBarToggleButton; import org.jowidgets.api.widgets.blueprint.factory.IBluePrintFactory; import org.jowidgets.api.widgets.descriptor.ISeparatorToolBarItemDescriptor; import org.jowidgets.api.widgets.descriptor.IToolBarButtonDescriptor; import org.jowidgets.api.widgets.descriptor.IToolBarContainerItemDescriptor; import org.jowidgets.api.widgets.descriptor.IToolBarMenuDescriptor; import org.jowidgets.api.widgets.descriptor.IToolBarPopupButtonDescriptor; import org.jowidgets.api.widgets.descriptor.IToolBarToggleButtonDescriptor; import org.jowidgets.api.widgets.descriptor.setup.IContainerSetup; import org.jowidgets.api.widgets.descriptor.setup.IItemSetup; import org.jowidgets.api.widgets.descriptor.setup.IToolBarSetup; import org.jowidgets.common.widgets.descriptor.IWidgetDescriptor; import org.jowidgets.impl.base.delegate.ControlDelegate; import org.jowidgets.impl.base.delegate.ModelViewIndexConverter; import org.jowidgets.impl.event.ListItemObservable; import org.jowidgets.impl.widgets.common.wrapper.AbstractToolBarSpiWrapper; import org.jowidgets.spi.widgets.IToolBarButtonSpi; import org.jowidgets.spi.widgets.IToolBarContainerItemSpi; import org.jowidgets.spi.widgets.IToolBarItemSpi; import org.jowidgets.spi.widgets.IToolBarPopupButtonSpi; import org.jowidgets.spi.widgets.IToolBarSpi; import org.jowidgets.spi.widgets.IToolBarToggleButtonSpi; import org.jowidgets.tools.controller.ListModelAdapter; import org.jowidgets.tools.widgets.invoker.ColorSettingsInvoker; import org.jowidgets.tools.widgets.invoker.VisibiliySettingsInvoker; import org.jowidgets.util.Assert; public class ToolBarImpl extends AbstractToolBarSpiWrapper implements IToolBar, IListItemObservable { private final ControlDelegate controlDelegate; private final List<IToolBarItem> children; private final IListModelListener listModelListener; private final IItemModelListener itemModelListener; private final ModelViewIndexConverter<IItemModel> modelViewConverter; private final ListItemObservable itemObs; private IToolBarModel model; public ToolBarImpl(final IToolBarSpi widgetSpi, final IToolBarSetup setup) { super(widgetSpi); this.controlDelegate = new ControlDelegate(widgetSpi, this); this.children = new LinkedList<IToolBarItem>(); VisibiliySettingsInvoker.setVisibility(setup, this); ColorSettingsInvoker.setColors(setup, this); this.itemObs = new ListItemObservable(); this.modelViewConverter = new ModelViewIndexConverter<IItemModel>(); this.listModelListener = new ListModelAdapter() { @Override public void beforeChildRemove(final int index) { final IToolBarItemModel childModel = getModel().getItems().get(index); final int viewIndex = modelViewConverter.removeModel(childModel, index); childModel.removeItemModelListener(itemModelListener); if (viewIndex != -1) { remove(viewIndex); } pack(); } @Override public void afterChildAdded(final int index) { final IToolBarItemModel addedModel = getModel().getItems().get(index); addChild(index, addedModel); pack(); } }; this.itemModelListener = new IItemModelListener() { @Override public void itemChanged(final IItemModel item) { final boolean visible = item.isVisible(); final int viewIndex = modelViewConverter.markVisibility(item, visible); if (viewIndex != -1) { if (visible) { addChildToView(viewIndex, (IToolBarItemModel) item); } else { remove(viewIndex); } } } }; setModel(Toolkit.getModelFactoryProvider().getItemModelFactory().toolBar()); } @Override public void setModel(final IToolBarModel model) { modelViewConverter.clear(); if (this.model != null) { for (final IItemModel child : model.getItems()) { child.removeItemModelListener(itemModelListener); } this.model.removeListModelListener(listModelListener); removeAll(); } this.model = model; int childModelIndex = 0; for (final IToolBarItemModel childModel : model.getItems()) { addChild(childModelIndex, childModel); childModelIndex++; } model.addListModelListener(listModelListener); pack(); } @Override public IToolBarModel getModel() { return model; } @Override public IContainer getParent() { return controlDelegate.getParent(); } @Override public void setParent(final IContainer parent) { controlDelegate.setParent(parent); } @Override public void addParentListener(final IParentListener<IContainer> listener) { controlDelegate.addParentListener(listener); } @Override public void removeParentListener(final IParentListener<IContainer> listener) { controlDelegate.removeParentListener(listener); } @Override public boolean isReparentable() { return controlDelegate.isReparentable(); } @Override public void addDisposeListener(final IDisposeListener listener) { controlDelegate.addDisposeListener(listener); } @Override public void removeDisposeListener(final IDisposeListener listener) { controlDelegate.removeDisposeListener(listener); } @Override public boolean isDisposed() { return controlDelegate.isDisposed(); } @Override public void dispose() { if (!isDisposed()) { this.model.removeListModelListener(listModelListener); for (final IItemModel child : model.getItems()) { child.removeItemModelListener(itemModelListener); } final List<IToolBarItem> childrenCopy = new LinkedList<IToolBarItem>(children); //clear the children to avoid that children will be removed //unnecessarily from its parent toolbar on dispose invocation children.clear(); for (final IToolBarItem child : childrenCopy) { child.dispose(); } controlDelegate.dispose(); modelViewConverter.dispose(); } } @Override public IPopupMenu createPopupMenu() { return controlDelegate.createPopupMenu(); } @Override public List<IToolBarItem> getChildren() { return new LinkedList<IToolBarItem>(children); } @Override public void remove(final int index) { final IToolBarItem item = children.get(index); children.remove(index); item.dispose(); getWidget().remove(index); } @Override public boolean remove(final IToolBarItem item) { Assert.paramNotNull(item, "item"); final int index = children.indexOf(item); if (index != -1) { remove(index); return true; } else { return false; } } @Override public void removeAll() { for (final IToolBarItem item : getChildren()) { remove(item); } } @Override public IToolBarItem addSeparator() { return addSeparator(null); } @Override public IToolBarItem addSeparator(final int index) { if (index < 0 || index > children.size()) { throw new IllegalArgumentException("Index must be between '0' and '" + children.size() + "'."); } return addSeparator(Integer.valueOf(index)); } private IToolBarItem addSeparator(final Integer index) { if (index != null) { return addItem(index.intValue(), Toolkit.getBluePrintFactory().toolBarSeparator()); } else { return addItem(Toolkit.getBluePrintFactory().toolBarSeparator()); } } @Override public IToolBarButton addAction(final int index, final IAction action) { final IToolBarButton result = addItem(index, Toolkit.getBluePrintFactory().toolBarButton()); result.setAction(action); return result; } @Override public IToolBarButton addAction(final IAction action) { final IToolBarButton result = addItem(Toolkit.getBluePrintFactory().toolBarButton()); result.setAction(action); return result; } @Override public <WIDGET_TYPE extends IToolBarItem> WIDGET_TYPE addItem(final IWidgetDescriptor<? extends WIDGET_TYPE> descriptor) { final WIDGET_TYPE result = addItemInternal(null, descriptor); addToModel(null, result); return result; } @Override public <WIDGET_TYPE extends IToolBarItem> WIDGET_TYPE addItem( final int index, final IWidgetDescriptor<? extends WIDGET_TYPE> descriptor) { if (index < 0 || index > children.size()) { throw new IllegalArgumentException("Index must be between '0' and '" + children.size() + "'."); } final WIDGET_TYPE result = addItemInternal(Integer.valueOf(index), descriptor); addToModel(index, result); return result; } @SuppressWarnings("unchecked") private <WIDGET_TYPE extends IToolBarItem> WIDGET_TYPE addItemInternal( final Integer index, final IWidgetDescriptor<? extends WIDGET_TYPE> descriptor) { Assert.paramNotNull(descriptor, "descriptor"); WIDGET_TYPE result = null; if (IToolBarButtonDescriptor.class.isAssignableFrom(descriptor.getDescriptorInterface())) { final IToolBarButtonSpi toolBarButtonSpi = getWidget().addToolBarButton(index); final IToolBarButton toolBarButton = new ToolBarButtonImpl(this, toolBarButtonSpi, (IItemSetup) descriptor); result = (WIDGET_TYPE) toolBarButton; } else if (IToolBarToggleButtonDescriptor.class.isAssignableFrom(descriptor.getDescriptorInterface())) { final IToolBarToggleButtonSpi toolBarToggleButtonSpi = getWidget().addToolBarToggleButton(index); final IToolBarToggleButton toolBarToggleButton = new ToolBarToggleButtonImpl( this, toolBarToggleButtonSpi, (IItemSetup) descriptor); result = (WIDGET_TYPE) toolBarToggleButton; } else if (IToolBarPopupButtonDescriptor.class.isAssignableFrom(descriptor.getDescriptorInterface())) { final IToolBarPopupButtonSpi toolBarPopupSpi = getWidget().addToolBarPopupButton(index); final IToolBarPopupButton toolBarPopupButton = new ToolBarPopupButtonImpl( this, toolBarPopupSpi, (IItemSetup) descriptor); result = (WIDGET_TYPE) toolBarPopupButton; } else if (IToolBarMenuDescriptor.class.isAssignableFrom(descriptor.getDescriptorInterface())) { final IToolBarButtonSpi toolBarBurronSpi = getWidget().addToolBarButton(index); final IToolBarMenu toolBarMenu = new ToolBarMenuImpl(this, toolBarBurronSpi, (IItemSetup) descriptor); result = (WIDGET_TYPE) toolBarMenu; } else if (IToolBarContainerItemDescriptor.class.isAssignableFrom(descriptor.getDescriptorInterface())) { final IToolBarContainerItemSpi toolBarContainerItemSpi = getWidget().addToolBarContainer(index); final IToolBarContainerItem toolBarContainerItem = new ToolBarContainerItemImpl( this, toolBarContainerItemSpi, (IContainerSetup) descriptor); result = (WIDGET_TYPE) toolBarContainerItem; } else if (ISeparatorToolBarItemDescriptor.class.isAssignableFrom(descriptor.getDescriptorInterface())) { final IToolBarItemSpi toolBarSeparatorItemSpi = getWidget().addSeparator(index); final ToolBarSeparatorItemImpl toolBarSeparatorItem = new ToolBarSeparatorItemImpl(this, toolBarSeparatorItemSpi); result = (WIDGET_TYPE) toolBarSeparatorItem; } else { throw new IllegalArgumentException("Descriptor with type '" + descriptor.getClass().getName() + "' is not supported"); } addToChildren(index, result); itemObs.fireItemAdded(result); return result; } private void addChild(final int modelIndex, final IToolBarItemModel model) { final int viewIndex = modelViewConverter.addModel(model, model.isVisible(), modelIndex); addChildToView(viewIndex, model); model.addItemModelListener(itemModelListener); } private void addChildToView(final int viewIndex, final IToolBarItemModel model) { Assert.paramNotNull(model, "model"); if (viewIndex != -1) { final IBluePrintFactory bpf = Toolkit.getBluePrintFactory(); if (model instanceof IActionItemModel) { addItemInternal(viewIndex, bpf.toolBarButton()).setModel(model); } else if (model instanceof ICheckedItemModel) { addItemInternal(viewIndex, bpf.toolBarToggleButton()).setModel(model); } else if (model instanceof IPopupActionItemModel) { addItemInternal(viewIndex, bpf.toolBarPopupButton()).setModel(model); } else if (model instanceof IContainerItemModel) { addItemInternal(viewIndex, bpf.toolBarContainerItem()).setModel(model); } else if (model instanceof ISeparatorItemModel) { addItemInternal(viewIndex, bpf.toolBarSeparator()).setModel(model); } else if (model instanceof IMenuModel) { addItemInternal(viewIndex, bpf.toolBarMenu()).setModel(model); } else { throw new IllegalArgumentException("Model of type '" + model.getClass().getName() + "' is not supported."); } } } private void addToChildren(final Integer index, final IToolBarItem item) { if (index != null) { children.add(index.intValue(), item); } else { children.add(item); } } private void addToModel(final Integer index, final IToolBarItem item) { model.removeListModelListener(listModelListener); if (index != null) { getModel().addItem(index.intValue(), item.getModel()); } else { getModel().addItem(item.getModel()); } model.addListModelListener(listModelListener); } @Override public void addItemContainerListener(final IListItemListener listener) { itemObs.addItemContainerListener(listener); } @Override public void removeItemContainerListener(final IListItemListener listener) { itemObs.removeItemContainerListener(listener); } }