/* * Copyright (c) 2011, grossmann * 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.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.jowidgets.api.controller.IDisposeListener; import org.jowidgets.api.controller.IParentListener; import org.jowidgets.api.controller.ITabFolderListener; import org.jowidgets.api.controller.ITabSelectionEvent; import org.jowidgets.api.widgets.IContainer; import org.jowidgets.api.widgets.IPopupMenu; import org.jowidgets.api.widgets.ITabFolder; import org.jowidgets.api.widgets.ITabItem; import org.jowidgets.api.widgets.descriptor.ITabFolderDescriptor; import org.jowidgets.api.widgets.descriptor.ITabItemDescriptor; import org.jowidgets.common.types.Dimension; import org.jowidgets.impl.base.delegate.ControlDelegate; import org.jowidgets.impl.event.TabSelectionEvent; import org.jowidgets.impl.spi.SpiBluePrintFactory; import org.jowidgets.impl.spi.blueprint.ITabItemBluePrintSpi; import org.jowidgets.impl.widgets.common.wrapper.AbstractTabFolderSpiWrapper; import org.jowidgets.spi.widgets.ITabFolderSpi; import org.jowidgets.spi.widgets.ITabItemSpi; import org.jowidgets.tools.types.VetoHolder; import org.jowidgets.tools.widgets.invoker.ColorSettingsInvoker; import org.jowidgets.tools.widgets.invoker.VisibiliySettingsInvoker; import org.jowidgets.util.Assert; import org.jowidgets.util.TypeCast; public class TabFolderImpl extends AbstractTabFolderSpiWrapper implements ITabFolder { private static final SpiBluePrintFactory SPI_BPF = new SpiBluePrintFactory(); private final ControlDelegate controlDelegate; private final Set<ITabFolderListener> tabFolderListeners; private final List<TabItemImpl> items; private ITabItem lastSelectedItem; public TabFolderImpl(final ITabFolderSpi widget, final ITabFolderDescriptor descriptor) { super(widget); this.controlDelegate = new ControlDelegate(widget, this); this.tabFolderListeners = new HashSet<ITabFolderListener>(); this.items = new LinkedList<TabItemImpl>(); VisibiliySettingsInvoker.setVisibility(descriptor, this); ColorSettingsInvoker.setColors(descriptor, this); } @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()) { final List<TabItemImpl> itemsCopy = new LinkedList<TabItemImpl>(items); //clear the children to avoid that children will be removed //unnecessarily from its parent container on dispose invocation items.clear(); for (final TabItemImpl item : itemsCopy) { item.dispose(); } controlDelegate.dispose(); } } @Override public IPopupMenu createPopupMenu() { return controlDelegate.createPopupMenu(); } @Override public ITabItem addItem(final ITabItemDescriptor descriptor) { final ITabItemBluePrintSpi tabItemBluePrintSpi = SPI_BPF.tabItem(); tabItemBluePrintSpi.setSetup(descriptor); final ITabItemSpi tabItemSpi = getWidget().addItem(tabItemBluePrintSpi); final TabItemImpl result = new TabItemImpl(tabItemSpi, descriptor, this); items.add(result); if (items.size() == 1) { setSelectedItem(0); result.setSelected(true); } return result; } @Override public ITabItem addItem(final int index, final ITabItemDescriptor descriptor) { final ITabItemBluePrintSpi tabItemBluePrintSpi = SPI_BPF.tabItem(); tabItemBluePrintSpi.setSetup(descriptor); final ITabItemSpi tabItemSpi = getWidget().addItem(index, tabItemBluePrintSpi); final TabItemImpl result = new TabItemImpl(tabItemSpi, descriptor, this); items.add(index, result); if (items.size() == 1) { setSelectedItem(0); result.setSelected(true); } return result; } @Override public void removeItem(final ITabItem item) { Assert.paramNotNull(item, "item"); final int index = items.indexOf(item); if (index != -1) { getWidget().removeItem(index); final TabItemImpl itemImpl = items.remove(index); if (itemImpl.getSelectedState()) { itemImpl.setSelected(false); } itemImpl.dispose(); } } @Override public void removeItem(final int index) { final ITabItem itemToRemove = getItem(index); if (itemToRemove != null) { removeItem(itemToRemove); } } protected void itemClosed(final TabItemImpl tabItemImpl) { items.remove(tabItemImpl); } @Override public void removeAllItems() { for (final ITabItem item : new LinkedList<ITabItem>(items)) { removeItem(item); } } @Override public void setSelectedItem(final ITabItem item) { final int itemIndex = getItemIndex(item); getWidget().setSelectedItem(itemIndex); } @Override public ITabItem getSelectedItem() { final int selectedIndex = getWidget().getSelectedIndex(); if (selectedIndex != -1) { return items.get(selectedIndex); } return null; } @Override public void detachItem(final ITabItem item) { Assert.paramNotNull(item, "item"); final int itemIndex = items.indexOf(item); if (itemIndex == -1) { throw new IllegalArgumentException("Item '" + item + "' is not attached to this folder."); } if (item.isDetached()) { throw new IllegalArgumentException("The item is already detached."); } final TabItemImpl itemImpl = TypeCast.toType(item, TabItemImpl.class); getWidget().detachItem(itemImpl.getWidget()); items.remove(itemIndex); itemImpl.setDetached(true); } @Override public void attachItem(final ITabItem item) { attachItem(null, item); } @Override public void attachItem(final int index, final ITabItem item) { attachItem(Integer.valueOf(index), item); } private void attachItem(final Integer index, final ITabItem item) { Assert.paramNotNull(item, "item"); if (!item.isDetached()) { throw new IllegalArgumentException("The item is not detached."); } final TabItemImpl itemImpl = TypeCast.toType(item, TabItemImpl.class); if (index != null) { getWidget().attachItem(index.intValue(), itemImpl.getWidget()); items.add(index.intValue(), itemImpl); } else { getWidget().attachItem(itemImpl.getWidget()); items.add(itemImpl); } itemImpl.setDetached(false); itemImpl.setParent(this); } @Override public void changeItemIndex(final ITabItem item, final int newIndex) { final int itemIndex = getItemIndex(item); if (item.isDetached()) { throw new IllegalArgumentException("The item is detached."); } if (itemIndex != newIndex) { final TabItemImpl itemImpl = TypeCast.toType(item, TabItemImpl.class); final boolean selected = itemImpl.getSelectedState(); detachItem(item); attachItem(Integer.valueOf(newIndex), item); if (selected) { setSelectedItem(newIndex); itemImpl.setSelected(true); } } } private int getItemIndex(final ITabItem item) { Assert.paramNotNull(item, "item"); final int itemIndex = items.indexOf(item); if (itemIndex == -1) { throw new IllegalArgumentException("Item '" + item + "' is not attached to this folder."); } return itemIndex; } @Override public ITabItem getItem(final int index) { return items.get(index); } @Override public int getIndex(final ITabItem item) { Assert.paramNotNull(item, "item"); return items.indexOf(item); } @Override public List<ITabItem> getItems() { return new LinkedList<ITabItem>(items); } @Override public void addTabFolderListener(final ITabFolderListener listener) { tabFolderListeners.add(listener); } @Override public void removeTabFolderListener(final ITabFolderListener listener) { tabFolderListeners.remove(listener); } @Override public Dimension getMinSize() { int width = 0; int height = 0; for (final TabItemImpl item : items) { final Dimension minSize = item.getMinSize(); if (minSize != null) { width = Math.max(width, minSize.getWidth()); height = Math.max(height, minSize.getHeight()); } } return getWidget().computeDecoratedSize(new Dimension(width, height)); } @Override public Dimension getPreferredSize() { int width = 0; int height = 0; for (final TabItemImpl item : items) { final Dimension prefSize = item.getPreferredSize(); if (prefSize != null) { width = Math.max(width, prefSize.getWidth()); height = Math.max(height, prefSize.getHeight()); } } return getWidget().computeDecoratedSize(new Dimension(width, height)); } protected void fireOnDeselection(final VetoHolder vetoHolder, final ITabItem deselectedItem, final ITabItem newSelectedItem) { if (items.contains(deselectedItem)) { final ITabSelectionEvent selectionEvent = new TabSelectionEvent(deselectedItem, newSelectedItem); for (final ITabFolderListener listener : tabFolderListeners) { listener.onDeselection(vetoHolder, selectionEvent); } } } protected void fireItemSelected(final ITabItem newSelectedItem) { final ITabSelectionEvent selectionEvent = new TabSelectionEvent(lastSelectedItem, newSelectedItem); for (final ITabFolderListener listener : tabFolderListeners) { listener.itemSelected(selectionEvent); } lastSelectedItem = newSelectedItem; } protected List<TabItemImpl> getItemsImpl() { return new LinkedList<TabItemImpl>(items); } }