/*
* Copyright (c) 2014, 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.model.item;
import java.util.LinkedList;
import java.util.List;
import org.jowidgets.api.command.ITreeExpansionAction;
import org.jowidgets.api.model.item.IMenuModel;
import org.jowidgets.api.model.item.IRadioItemModel;
import org.jowidgets.api.model.item.IToolBarItemModel;
import org.jowidgets.api.model.item.ITreeExpansionToolbarItemModelBuilder;
import org.jowidgets.common.widgets.controller.IItemStateListener;
import org.jowidgets.i18n.api.IMessage;
import org.jowidgets.tools.model.item.ActionItemModel;
import org.jowidgets.tools.model.item.MenuModel;
import org.jowidgets.tools.model.item.PopupActionItemModel;
import org.jowidgets.util.Assert;
import org.jowidgets.util.NullCompatibleEquivalence;
import org.jowidgets.util.Tuple;
import org.jowidgets.util.maybe.IMaybe;
import org.jowidgets.util.maybe.Some;
final class TreeExpansionToolbarActionModelBuilderImpl implements ITreeExpansionToolbarItemModelBuilder {
private static final IMessage LEVEL = Messages.getMessage("TreeExpansionToolbarActionModelBuilderImpl.level");
private static final IMessage UNBOUND = Messages.getMessage("TreeExpansionToolbarActionModelBuilderImpl.unbound");
private final List<Tuple<Integer, String>> levels;
private final ITreeExpansionAction action;
private IMaybe<Integer> defaultLevelMaybe;
private boolean exhausted;
TreeExpansionToolbarActionModelBuilderImpl(final ITreeExpansionAction action) {
Assert.paramNotNull(action, "action");
this.action = action;
this.levels = new LinkedList<Tuple<Integer, String>>();
this.exhausted = false;
}
@Override
public ITreeExpansionToolbarItemModelBuilder addUnboundLevel() {
return addUnboundLevel(UNBOUND.get());
}
@Override
public ITreeExpansionToolbarItemModelBuilder addUnboundLevel(final String label) {
checkExhausted();
Assert.paramNotNull(label, "label");
levels.add(new Tuple<Integer, String>(null, label));
return this;
}
@Override
public ITreeExpansionToolbarItemModelBuilder addLevel(final int level) {
return addLevel(level, getDefaultLevelName(level));
}
@Override
public ITreeExpansionToolbarItemModelBuilder addLevel(final int level, final String levelName) {
checkExhausted();
Assert.paramNotNull(levelName, "levelName");
levels.add(new Tuple<Integer, String>(Integer.valueOf(level), levelName));
return this;
}
@Override
public ITreeExpansionToolbarItemModelBuilder setLevels(final int maxLevel) {
return setLevels(maxLevel, true);
}
@Override
public ITreeExpansionToolbarItemModelBuilder setLevels(final int maxLevel, final boolean unboundPossible) {
return setLevels(0, maxLevel, unboundPossible);
}
@Override
public ITreeExpansionToolbarItemModelBuilder setLevels(final int minLevel, final int maxLevel, final boolean unboundPossible) {
checkExhausted();
Assert.paramNotNegative(minLevel, "minLevel");
Assert.paramNotNegative(maxLevel, "maxLevel");
Assert.paramLessOrEqual(minLevel, maxLevel, "minLevel", "maxLevel");
defaultLevelMaybe = null;
levels.clear();
if (unboundPossible) {
addUnboundLevel();
}
for (int level = minLevel; level <= maxLevel; level++) {
addLevel(level);
}
return this;
}
@Override
public ITreeExpansionToolbarItemModelBuilder setDefaultLevel(final int defaultLevel) {
return setDefaultLevelImpl(Integer.valueOf(defaultLevel));
}
@Override
public ITreeExpansionToolbarItemModelBuilder setUnboundDefaultLevel() {
return setDefaultLevelImpl(null);
}
private ITreeExpansionToolbarItemModelBuilder setDefaultLevelImpl(final Integer defaultLevel) {
checkExhausted();
if (!hasDefaultLevel(defaultLevel)) {
throw new IllegalArgumentException("There was now level with the value '" + defaultLevel + "' added yet.");
}
this.defaultLevelMaybe = new Some<Integer>(defaultLevel);
return this;
}
private boolean hasDefaultLevel(final Integer defaultLevel) {
for (final Tuple<Integer, String> level : levels) {
if (NullCompatibleEquivalence.equals(level.getFirst(), defaultLevel)) {
return true;
}
}
return false;
}
private void checkExhausted() {
if (exhausted) {
throw new IllegalStateException("The builder is exhausted. It's a single use builder that can only be used once.");
}
}
private static String getDefaultLevelName(final int level) {
return LEVEL.get() + " " + (level + 1);
}
@Override
public IToolBarItemModel build() {
exhausted = true;
if (levels.size() > 0) {
final IMenuModel levelMenu = buildLevelMenu();
return PopupActionItemModel.builder(action, levelMenu).build();
}
else {
return ActionItemModel.builder(action).build();
}
}
private IMenuModel buildLevelMenu() {
final MenuModel levelMenu = new MenuModel();
final Integer defaultLevel;
if (defaultLevelMaybe != null) {
defaultLevel = defaultLevelMaybe.getValue();
}
else if (levels.size() > 0) {
defaultLevel = levels.iterator().next().getFirst();
}
else {
//levels are empty, default value has no effect
defaultLevel = null;
}
for (final Tuple<Integer, String> levelTuple : levels) {
final String label = levelTuple.getSecond();
final Integer level = levelTuple.getFirst();
final boolean selected = NullCompatibleEquivalence.equals(defaultLevel, level);
addItemListener(levelMenu.addRadioItem(label), level, label, selected);
}
return levelMenu;
}
private void addItemListener(final IRadioItemModel itemModel, final Integer level, final String label, final boolean selected) {
itemModel.addItemListener(new IItemStateListener() {
@Override
public void itemStateChanged() {
if (itemModel.isSelected()) {
action.setPivotLevel(level, label);
}
}
});
if (selected) {
action.setPivotLevel(level, label);
itemModel.setSelected(selected);
}
}
}