/*
* 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.equipment;
import com.trollworks.gcs.character.GURPSCharacter;
import com.trollworks.gcs.common.DataFile;
import com.trollworks.gcs.common.ListFile;
import com.trollworks.gcs.library.LibraryFile;
import com.trollworks.gcs.menu.edit.Incrementable;
import com.trollworks.gcs.menu.edit.TechLevelIncrementable;
import com.trollworks.gcs.template.Template;
import com.trollworks.gcs.widgets.outline.ListOutline;
import com.trollworks.gcs.widgets.outline.ListRow;
import com.trollworks.gcs.widgets.outline.MultipleRowUndo;
import com.trollworks.gcs.widgets.outline.RowPostProcessor;
import com.trollworks.gcs.widgets.outline.RowUndo;
import com.trollworks.toolkit.annotation.Localize;
import com.trollworks.toolkit.collections.FilteredIterator;
import com.trollworks.toolkit.ui.widget.outline.OutlineModel;
import com.trollworks.toolkit.ui.widget.outline.Row;
import com.trollworks.toolkit.utility.Localization;
import com.trollworks.toolkit.utility.text.Numbers;
import java.awt.EventQueue;
import java.awt.dnd.DropTargetDragEvent;
import java.util.ArrayList;
import java.util.List;
/** An outline specifically for equipment. */
public class EquipmentOutline extends ListOutline implements Incrementable, TechLevelIncrementable {
@Localize("Increment Quantity")
@Localize(locale = "de", value = "Anzahl erhöhen")
@Localize(locale = "ru", value = "Увеличить количество")
@Localize(locale = "es", value = "Aumentar cantidad")
private static String INCREMENT;
@Localize("Decrement Quantity")
@Localize(locale = "de", value = "Anzahl verringen")
@Localize(locale = "ru", value = "Уменьшить количество")
@Localize(locale = "es", value = "Disminuir cantidad")
private static String DECREMENT;
static {
Localization.initialize();
}
private static OutlineModel extractModel(DataFile dataFile) {
if (dataFile instanceof GURPSCharacter) {
return ((GURPSCharacter) dataFile).getEquipmentRoot();
}
if (dataFile instanceof Template) {
return ((Template) dataFile).getEquipmentModel();
}
if (dataFile instanceof LibraryFile) {
return ((LibraryFile) dataFile).getEquipmentList().getModel();
}
return ((ListFile) dataFile).getModel();
}
/**
* Create a new equipment outline.
*
* @param dataFile The owning data file.
*/
public EquipmentOutline(DataFile dataFile) {
this(dataFile, extractModel(dataFile));
}
/**
* Create a new equipment outline.
*
* @param dataFile The owning data file.
* @param model The {@link OutlineModel} to use.
*/
public EquipmentOutline(DataFile dataFile, OutlineModel model) {
super(dataFile, model, Equipment.ID_LIST_CHANGED);
EquipmentColumn.addColumns(this, dataFile);
}
@Override
public String getDecrementTitle() {
return DECREMENT;
}
@Override
public String getIncrementTitle() {
return INCREMENT;
}
@Override
public boolean canDecrement() {
return (mDataFile instanceof GURPSCharacter || mDataFile instanceof Template) && selectionHasLeafRows(true);
}
@Override
public boolean canIncrement() {
return (mDataFile instanceof GURPSCharacter || mDataFile instanceof Template) && selectionHasLeafRows(false);
}
private boolean selectionHasLeafRows(boolean requireQtyAboveZero) {
for (Equipment equipment : new FilteredIterator<>(getModel().getSelectionAsList(), Equipment.class)) {
if (!equipment.canHaveChildren() && (!requireQtyAboveZero || equipment.getQuantity() > 0)) {
return true;
}
}
return false;
}
@SuppressWarnings("unused")
@Override
public void decrement() {
List<RowUndo> undos = new ArrayList<>();
for (Equipment equipment : new FilteredIterator<>(getModel().getSelectionAsList(), Equipment.class)) {
if (!equipment.canHaveChildren()) {
int qty = equipment.getQuantity();
if (qty > 0) {
RowUndo undo = new RowUndo(equipment);
equipment.setQuantity(qty - 1);
if (undo.finish()) {
undos.add(undo);
}
}
}
}
if (!undos.isEmpty()) {
repaintSelection();
new MultipleRowUndo(undos);
}
}
@SuppressWarnings("unused")
@Override
public void increment() {
List<RowUndo> undos = new ArrayList<>();
for (Equipment equipment : new FilteredIterator<>(getModel().getSelectionAsList(), Equipment.class)) {
if (!equipment.canHaveChildren()) {
RowUndo undo = new RowUndo(equipment);
equipment.setQuantity(equipment.getQuantity() + 1);
if (undo.finish()) {
undos.add(undo);
}
}
}
if (!undos.isEmpty()) {
repaintSelection();
new MultipleRowUndo(undos);
}
}
@Override
public boolean canIncrementTechLevel() {
return checkTechLevel(0);
}
@Override
public boolean canDecrementTechLevel() {
return checkTechLevel(1);
}
private boolean checkTechLevel(int minLevel) {
for (Equipment equipment : new FilteredIterator<>(getModel().getSelectionAsList(), Equipment.class)) {
if (getCurrentTechLevel(equipment) >= minLevel) {
return true;
}
}
return false;
}
private static int getCurrentTechLevel(Equipment equipment) {
String tl = equipment.getTechLevel();
if (tl != null) {
tl = tl.trim();
if (!tl.isEmpty()) {
for (int i = tl.length(); --i >= 0;) {
if (!Character.isDigit(tl.charAt(i))) {
return -1;
}
}
return Numbers.extractInteger(tl, -1, 0, Integer.MAX_VALUE, false);
}
}
return -1;
}
@SuppressWarnings("unused")
@Override
public void incrementTechLevel() {
List<RowUndo> undos = new ArrayList<>();
for (Equipment equipment : new FilteredIterator<>(getModel().getSelectionAsList(), Equipment.class)) {
int tl = getCurrentTechLevel(equipment);
if (tl >= 0) {
RowUndo undo = new RowUndo(equipment);
equipment.setTechLevel(Integer.toString(tl + 1));
if (undo.finish()) {
undos.add(undo);
}
}
}
if (!undos.isEmpty()) {
repaintSelection();
new MultipleRowUndo(undos);
}
}
@SuppressWarnings("unused")
@Override
public void decrementTechLevel() {
List<RowUndo> undos = new ArrayList<>();
for (Equipment equipment : new FilteredIterator<>(getModel().getSelectionAsList(), Equipment.class)) {
if (!equipment.canHaveChildren()) {
int tl = getCurrentTechLevel(equipment);
if (tl >= 1) {
RowUndo undo = new RowUndo(equipment);
equipment.setTechLevel(Integer.toString(tl - 1));
if (undo.finish()) {
undos.add(undo);
}
}
}
}
if (!undos.isEmpty()) {
repaintSelection();
new MultipleRowUndo(undos);
}
}
@Override
protected boolean isRowDragAcceptable(DropTargetDragEvent dtde, Row[] rows) {
return !getModel().isLocked() && rows.length > 0 && rows[0] instanceof Equipment;
}
@Override
public void convertDragRowsToSelf(List<Row> list) {
OutlineModel model = getModel();
Row[] rows = model.getDragRows();
boolean forSheetOrTemplate = mDataFile instanceof GURPSCharacter || mDataFile instanceof Template;
ArrayList<ListRow> process = new ArrayList<>();
for (Row element : rows) {
Equipment equipment = new Equipment(mDataFile, (Equipment) element, true);
model.collectRowsAndSetOwner(list, equipment, false);
if (forSheetOrTemplate) {
addRowsToBeProcessed(process, equipment);
}
}
if (forSheetOrTemplate && !process.isEmpty()) {
EventQueue.invokeLater(new RowPostProcessor(this, process));
}
}
}