/*
* Copyright (c) 1998-2017 by Richard A. Wilkes. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, version 2.0. If a copy of the MPL was not distributed with
* this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This Source Code Form is "Incompatible With Secondary Licenses", as
* defined by the Mozilla Public License, version 2.0.
*/
package com.trollworks.gcs.prereq;
import com.trollworks.gcs.common.EditorPanel;
import com.trollworks.gcs.widgets.outline.ListRow;
import com.trollworks.toolkit.annotation.Localize;
import com.trollworks.toolkit.ui.UIUtilities;
import com.trollworks.toolkit.ui.image.StdImage;
import com.trollworks.toolkit.ui.layout.FlexGrid;
import com.trollworks.toolkit.ui.layout.FlexRow;
import com.trollworks.toolkit.ui.widget.IconButton;
import com.trollworks.toolkit.utility.Localization;
import java.awt.event.ActionEvent;
import javax.swing.JComboBox;
import javax.swing.JComponent;
/** A generic prerequisite editor panel. */
public abstract class PrereqEditor extends EditorPanel {
@Localize("Remove this prerequisite")
@Localize(locale = "de", value = "Diese Bedingung entfernen")
@Localize(locale = "ru", value = "Удалить это требование")
@Localize(locale = "es", value = "Eliminar este prerrequisito")
private static String REMOVE_PREREQ_TOOLTIP;
@Localize("Remove this prerequisite list")
@Localize(locale = "de", value = "Diese Bedingungsliste entfernen")
@Localize(locale = "ru", value = "Удалить этот список требований")
@Localize(locale = "es", value = "Eliminar esta lista de prerrequisitos")
private static String REMOVE_PREREQ_LIST_TOOLTIP;
@Localize("has")
@Localize(locale = "de", value = "hat")
@Localize(locale = "ru", value = "имеет")
@Localize(locale = "es", value = "tiene")
private static String HAS;
@Localize("doesn't have")
@Localize(locale = "de", value = "hat nicht")
@Localize(locale = "ru", value = "не имеет")
@Localize(locale = "es", value = "no tiene")
private static String DOES_NOT_HAVE;
@Localize("advantage")
@Localize(locale = "de", value = "Vorteil")
@Localize(locale = "ru", value = "преимущество")
@Localize(locale = "es", value = "ventaja")
private static String ADVANTAGE;
@Localize("attribute")
@Localize(locale = "de", value = "Attribut")
@Localize(locale = "ru", value = "атрибут")
@Localize(locale = "es", value = "atributo")
private static String ATTRIBUTE;
@Localize("contained weight")
@Localize(locale = "de", value = "Zuladung")
@Localize(locale = "ru", value = "содержит вес")
@Localize(locale = "es", value = "peso del contenido")
private static String CONTAINED_WEIGHT;
@Localize("skill")
@Localize(locale = "de", value = "Fertigkeit")
@Localize(locale = "ru", value = "умение")
@Localize(locale = "es", value = "habilidad")
private static String SKILL;
@Localize("spell(s)")
@Localize(locale = "de", value = "Zauber")
@Localize(locale = "ru", value = "заклинание(я)")
@Localize(locale = "es", value = "sortilegio(s)")
private static String SPELL;
static {
Localization.initialize();
}
private static final String CHANGE_BASE_TYPE = "ChangeBaseType"; //$NON-NLS-1$
private static final String CHANGE_HAS = "ChangeHas"; //$NON-NLS-1$
private static final Class<?>[] BASE_TYPES = new Class<?>[] { AttributePrereq.class, AdvantagePrereq.class, SkillPrereq.class, SpellPrereq.class, ContainedWeightPrereq.class };
/** The prerequisite this panel represents. */
protected Prereq mPrereq;
/** The row this prerequisite will be attached to. */
protected ListRow mRow;
private int mDepth;
private JComboBox<Object> mBaseTypeCombo;
/**
* Creates a new prerequisite editor panel.
*
* @param row The owning row.
* @param prereq The prerequisite to edit.
* @param depth The depth of this prerequisite.
* @return The newly created editor panel.
*/
public static PrereqEditor create(ListRow row, Prereq prereq, int depth) {
if (prereq instanceof PrereqList) {
return new ListPrereqEditor(row, (PrereqList) prereq, depth);
}
if (prereq instanceof AdvantagePrereq) {
return new AdvantagePrereqEditor(row, (AdvantagePrereq) prereq, depth);
}
if (prereq instanceof SkillPrereq) {
return new SkillPrereqEditor(row, (SkillPrereq) prereq, depth);
}
if (prereq instanceof SpellPrereq) {
return new SpellPrereqEditor(row, (SpellPrereq) prereq, depth);
}
if (prereq instanceof AttributePrereq) {
return new AttributePrereqEditor(row, (AttributePrereq) prereq, depth);
}
if (prereq instanceof ContainedWeightPrereq) {
return new ContainedWeightPrereqEditor(row, (ContainedWeightPrereq) prereq, depth);
}
return null;
}
/**
* Creates a new generic prerequisite editor panel.
*
* @param row The owning row.
* @param prereq The prerequisite to edit.
* @param depth The depth of this prerequisite.
*/
protected PrereqEditor(ListRow row, Prereq prereq, int depth) {
super(20 * depth);
mRow = row;
mPrereq = prereq;
mDepth = depth;
rebuild();
}
/** Rebuilds the contents of this panel with the current prerequisite settings. */
protected final void rebuild() {
removeAll();
FlexGrid grid = new FlexGrid();
FlexRow left = new FlexRow();
FlexRow right = new FlexRow();
if (mPrereq.getParent() != null) {
AndOrLabel andOrLabel = new AndOrLabel(mPrereq);
add(andOrLabel);
left.add(andOrLabel);
}
grid.add(left, 0, 0);
rebuildSelf(left, grid, right);
if (mDepth > 0) {
IconButton button = new IconButton(StdImage.REMOVE, mPrereq instanceof PrereqList ? REMOVE_PREREQ_LIST_TOOLTIP : REMOVE_PREREQ_TOOLTIP, () -> remove());
add(button);
right.add(button);
}
grid.add(right, 0, 2);
grid.apply(this);
revalidate();
repaint();
}
/**
* Sub-classes must implement this method to add any components they want to be visible.
*
* @param left The left-side {@link FlexRow}, situated in grid row 0, column 0.
* @param grid The general {@link FlexGrid}. Add items in column 1.
* @param right The right-side {@link FlexRow}, situated in grid row 0, column 2.
*/
protected abstract void rebuildSelf(FlexRow left, FlexGrid grid, FlexRow right);
/**
* @param has The current value of the "has" attribute.
* @return The {@link JComboBox} that allows the "has" attribute to be changed.
*/
protected JComboBox<Object> addHasCombo(boolean has) {
return addComboBox(CHANGE_HAS, new Object[] { HAS, DOES_NOT_HAVE }, has ? HAS : DOES_NOT_HAVE);
}
/** @return The {@link JComboBox} that allows the base prereq type to be changed. */
protected JComboBox<Object> addChangeBaseTypeCombo() {
Object[] choices = new Object[] { ATTRIBUTE, ADVANTAGE, SKILL, SPELL, CONTAINED_WEIGHT };
Class<?> type = mPrereq.getClass();
Object current = choices[0];
for (int i = 0; i < BASE_TYPES.length; i++) {
if (type.equals(BASE_TYPES[i])) {
current = choices[i];
break;
}
}
mBaseTypeCombo = addComboBox(CHANGE_BASE_TYPE, choices, current);
return mBaseTypeCombo;
}
/** @return The depth of this prerequisite. */
public int getDepth() {
return mDepth;
}
/** @return The underlying prerequisite. */
public Prereq getPrereq() {
return mPrereq;
}
private void remove() {
JComponent parent = (JComponent) getParent();
int index = UIUtilities.getIndexOf(parent, this);
int count = countSelfAndDescendents(mPrereq);
for (int i = 0; i < count; i++) {
parent.remove(index);
}
mPrereq.removeFromParent();
parent.revalidate();
parent.repaint();
}
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (CHANGE_BASE_TYPE.equals(command)) {
Class<?> type = BASE_TYPES[mBaseTypeCombo.getSelectedIndex()];
if (!mPrereq.getClass().equals(type)) {
JComponent parent = (JComponent) getParent();
PrereqList list = mPrereq.getParent();
int lIndex = list.getIndexOf(mPrereq);
try {
Prereq prereq = (Prereq) type.getConstructor(PrereqList.class).newInstance(list);
if (prereq instanceof HasPrereq && mPrereq instanceof HasPrereq) {
((HasPrereq) prereq).has(((HasPrereq) mPrereq).has());
}
list.add(lIndex, prereq);
list.remove(mPrereq);
parent.add(create(mRow, prereq, mDepth), UIUtilities.getIndexOf(parent, this));
} catch (Exception exception) {
// Shouldn't have a failure...
exception.printStackTrace(System.err);
}
parent.remove(this);
parent.revalidate();
parent.repaint();
ListPrereqEditor.setLastItemType(type);
}
} else if (CHANGE_HAS.equals(command)) {
((HasPrereq) mPrereq).has(((JComboBox<?>) event.getSource()).getSelectedIndex() == 0);
} else {
super.actionPerformed(event);
}
}
private int countSelfAndDescendents(Prereq prereq) {
int count = 1;
if (prereq instanceof PrereqList) {
for (Prereq one : ((PrereqList) prereq).getChildren()) {
count += countSelfAndDescendents(one);
}
}
return count;
}
}