org.bidib.wizard.mvc.main.model.MacroTableModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bidibwizard-client Show documentation
Show all versions of bidibwizard-client Show documentation
jBiDiB BiDiB Wizard Client Application POM
package org.bidib.wizard.mvc.main.model;
import java.util.List;
import java.util.Objects;
import javax.swing.table.DefaultTableModel;
import org.bidib.wizard.api.locale.Resources;
import org.bidib.wizard.api.model.Flag;
import org.bidib.wizard.api.model.Macro;
import org.bidib.wizard.api.model.MacroSaveState;
import org.bidib.wizard.api.model.function.AccessoryOkayFunction;
import org.bidib.wizard.api.model.function.BacklightPortAction;
import org.bidib.wizard.api.model.function.Delayable;
import org.bidib.wizard.api.model.function.FlagFunction;
import org.bidib.wizard.api.model.function.Function;
import org.bidib.wizard.api.model.function.InputFunction;
import org.bidib.wizard.api.model.function.MacroFunction;
import org.bidib.wizard.api.model.function.MotorPortAction;
import org.bidib.wizard.api.model.function.PortAware;
import org.bidib.wizard.api.model.function.RandomDelayFunction;
import org.bidib.wizard.api.model.function.ServoMoveQueryFunction;
import org.bidib.wizard.api.model.function.ServoPortAction;
import org.bidib.wizard.api.model.listener.MacroListener;
import org.bidib.wizard.client.common.uils.SwingUtils;
import org.bidib.wizard.model.ports.BacklightPort;
import org.bidib.wizard.model.ports.InputPort;
import org.bidib.wizard.model.ports.MotorPort;
import org.bidib.wizard.model.ports.Port;
import org.bidib.wizard.model.ports.ServoPort;
import org.bidib.wizard.model.status.AccessoryOkayStatus;
import org.bidib.wizard.model.status.BidibStatus;
import org.bidib.wizard.model.status.MacroStatus;
import org.bidib.wizard.mvc.main.view.table.Reorderable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MacroTableModel extends DefaultTableModel implements MacroListener, Reorderable {
private static final Logger LOGGER = LoggerFactory.getLogger(MacroTableModel.class);
private static final long serialVersionUID = 1L;
public static final int COLUMN_STEP = 0;
public static final int COLUMN_DELAY = 1;
public static final int COLUMN_PORT_TYPE = 2;
public static final int COLUMN_ACTION = 3;
public static final int COLUMN_PORT_NUMBER = 4;
public static final int COLUMN_EXTRA = 5;
private String[] columnNames;
private Macro macro;
private final MainModel model;
public MacroTableModel(final MainModel model) {
this.model = model;
initialize();
setColumnIdentifiers(columnNames);
}
protected void initialize() {
columnNames =
new String[] { Resources.getString(getClass(), "step"), Resources.getString(getClass(), "delay"),
Resources.getString(getClass(), "portType"), Resources.getString(getClass(), "action"),
Resources.getString(getClass(), "portNumber"), Resources.getString(getClass(), "extra") };
}
private void addRow(Function extends BidibStatus> function, int functionIndex) {
Object[] rowData = new Object[columnNames.length];
for (int column = 0; column < columnNames.length; column++) {
rowData[column] = getRowData(column, function, functionIndex);
}
addRow(rowData);
}
@Override
public Class> getColumnClass(int column) {
switch (column) {
case COLUMN_DELAY:
return Integer.class;
case COLUMN_PORT_TYPE:
return Object.class;
case COLUMN_ACTION:
return Object.class;
case COLUMN_PORT_NUMBER:
return Object.class;
case COLUMN_EXTRA:
return Integer.class;
default:
return String.class;
}
}
private Object getRowData(int column, Function extends BidibStatus> function, int functionIndex) {
Object result = null;
switch (column) {
case COLUMN_STEP:
// result = (functionIndex + 1) + ". " + Resources.getString(getClass(), "step");
result = Integer.toString(functionIndex + 1);
break;
case COLUMN_DELAY:
if (function != null) {
if (function instanceof Delayable) {
result = ((Delayable) function).getDelay();
}
else if (function instanceof RandomDelayFunction) {
result = ((RandomDelayFunction) function).getMaximumValue();
}
}
break;
case COLUMN_PORT_TYPE:
result = function;
break;
case COLUMN_ACTION:
if (function != null) {
result = function.getAction();
}
break;
case COLUMN_PORT_NUMBER:
if (function != null) {
LOGGER.info("Current function: {}", function);
if (function instanceof AccessoryOkayFunction) {
result = ((AccessoryOkayFunction) function).getInput();
}
else if (function instanceof InputFunction) {
result = ((InputFunction) function).getInput();
}
else if (function instanceof MacroFunction) {
result = model.getMacros().get(((MacroFunction) function).getMacroId());
}
else if (function instanceof FlagFunction) {
result = ((FlagFunction) function).getFlag();
}
else if (function instanceof PortAware) {
result = ((PortAware>) function).getPort();
}
}
break;
case COLUMN_EXTRA:
if (function != null) {
if (function instanceof ServoPortAction) {
result = ((ServoPortAction) function).getValue();
}
else if (function instanceof BacklightPortAction) {
result = ((BacklightPortAction) function).getValue();
}
else if (function instanceof MotorPortAction) {
result = ((MotorPortAction) function).getValue();
}
}
break;
}
return result;
}
@Override
public Object getValueAt(int row, int column) {
Object result = super.getValueAt(row, column);
if (result != null && column == COLUMN_EXTRA) {
Function extends BidibStatus> function = macro.getFunction(row);
if (function instanceof ServoPortAction) {
ServoPort port = ((ServoPortAction) function).getPort();
if (port != null) {
result = port.getRelativeValue(Integer.parseInt(result.toString()));
}
}
else if (function instanceof BacklightPortAction) {
BacklightPort port = ((BacklightPortAction) function).getPort();
if (port != null) {
result = port.getRelativeValue(Integer.parseInt(result.toString()));
}
}
else if (function instanceof MotorPortAction) {
MotorPort port = ((MotorPortAction) function).getPort();
if (port != null) {
result = Integer.parseInt(result.toString());
}
}
}
return result;
}
private void insertRow(int row, Function extends BidibStatus> function, int functionIndex) {
Object[] rowData = new Object[columnNames.length];
for (int column = 0; column < columnNames.length; column++) {
rowData[column] = getRowData(column, function, functionIndex);
}
insertRow(row, rowData);
}
@Override
public boolean isCellEditable(int row, int column) {
boolean editable = true;
switch (column) {
case COLUMN_EXTRA:
Function> function = macro.getFunction(row);
if (function instanceof ServoPortAction) {
ServoPort port = ((ServoPortAction) function).getPort();
if (port == null) {
editable = false;
}
}
break;
default:
break;
}
return editable;
}
private void renumberSteps() {
for (int row = 0; row < getRowCount(); row++) {
Object rowData = getRowData(0, (Function>) getValueAt(row, 2), row);
// rowData = (row + 1) + ". " + Resources.getString(getClass(), "step");
rowData = Integer.toString(row + 1);
setValueAt(rowData, row, 0);
}
}
public void setMacro(Macro macro) {
LOGGER.debug("Set the macro: {}", macro);
// remove all rows
setRowCount(0);
if (this.macro != null) {
this.macro.removeMacroListener(this);
}
// set the macro
this.macro = macro;
if (macro != null) {
for (int index = 0; index < macro.getFunctionCount(); index++) {
addRow(macro.getFunction(index), index);
}
macro.addMacroListener(this);
}
}
@Override
public void setValueAt(Object value, int row, int column) {
boolean valueChanged = false;
switch (column) {
case COLUMN_DELAY:
Function extends BidibStatus> function = macro.getFunction(row);
if (function instanceof Delayable) {
int delayValue = Integer.parseInt(value.toString());
if (delayValue != ((Delayable) function).getDelay()) {
((Delayable) function).setDelay(delayValue);
valueChanged = true;
}
super.setValueAt(value, row, column);
}
else if (function instanceof RandomDelayFunction) {
int maxValue = Integer.parseInt(value.toString());
if (maxValue != ((RandomDelayFunction) function).getMaximumValue()) {
((RandomDelayFunction) function).setMaximumValue(maxValue);
valueChanged = true;
}
super.setValueAt(value, row, column);
}
break;
case COLUMN_PORT_TYPE:
if (value != null
&& (macro.getFunction(row) == null || value.getClass() != macro.getFunction(row).getClass())) {
try {
function = (Function>) ((Function>) value).clone();
macro.replaceFunction(row, function);
for (int col = columnNames.length - 1; col > 0; col--) {
super.setValueAt(getRowData(col, function, row), row, col);
}
valueChanged = true;
}
catch (Exception e) {
LOGGER.warn("Set new functions for selected port type failed.");
throw new RuntimeException(e);
}
}
else {
LOGGER.info("Port type has not been changed.");
}
break;
case COLUMN_ACTION:
function = macro.getFunction(row);
if (function != null) {
if (!Objects.equals(value, function.getAction())) {
// the action has been changed
LOGGER.info("The macro action has been changed: {}", value);
BidibStatus macroStatus = (BidibStatus) value;
function.setAction(macroStatus);
if (function instanceof AccessoryOkayFunction) {
if (AccessoryOkayStatus.NO_FEEDBACK
.equals(((AccessoryOkayFunction) function).getAction())) {
// no input selected if 'no feedback'
((AccessoryOkayFunction) function).setInput((InputPort) null);
super.setValueAt(null, row, column + 1);
}
else {
// show the combobox if not already displayed
Object currentValue = getValueAt(row, column + 1);
((AccessoryOkayFunction) function).setInput((InputPort) currentValue);
super.setValueAt(currentValue, row, column + 1);
}
}
else if (function instanceof ServoMoveQueryFunction) {
// show the combobox if not already displayed
Object currentValue = getValueAt(row, column + 1);
((ServoMoveQueryFunction) function).setPort((ServoPort) currentValue);
super.setValueAt(currentValue, row, column + 1);
}
else if (function instanceof MacroFunction) {
if (MacroStatus.END.equals(((MacroFunction) function).getAction())) {
// no macro selected if END
((MacroFunction) function).setMacroId(0);
super.setValueAt(null, row, column + 1);
}
else {
// show the combobox if not already displayed
Object currentValue = getValueAt(row, column + 1);
if (currentValue instanceof Macro) {
((MacroFunction) function).setMacroId(((Macro) currentValue).getId());
}
else {
((MacroFunction) function).setMacroId(0);
}
super.setValueAt(currentValue, row, column + 1);
}
}
super.setValueAt(value, row, column);
valueChanged = true;
}
}
else {
LOGGER.info("No function available.");
}
break;
case COLUMN_PORT_NUMBER:
function = macro.getFunction(row);
if (function instanceof AccessoryOkayFunction) {
if (!Objects.equals(((AccessoryOkayFunction) function).getInput(), value)) {
((AccessoryOkayFunction) function).setInput((InputPort) value);
super.setValueAt(value, row, column);
valueChanged = true;
}
}
else if (function instanceof InputFunction) {
if (!Objects.equals(((InputFunction) function).getInput(), value)) {
((InputFunction) function).setInput((InputPort) value);
super.setValueAt(value, row, column);
valueChanged = true;
}
}
else if (function instanceof MacroFunction) {
List macros = model.getMacros();
int index = macros.indexOf(value);
if (!Objects.equals(((MacroFunction) function).getMacroId(), index)) {
LOGGER.info("Set the macro at index: {}", index);
((MacroFunction) function).setMacroId(index);
super.setValueAt(value, row, column);
valueChanged = true;
}
}
else if (function instanceof FlagFunction) {
FlagFunction flagFunction = (FlagFunction) function;
if (!Objects.equals(flagFunction.getFlag(), value)) {
flagFunction.setFlag((Flag) value);
super.setValueAt(value, row, column);
valueChanged = true;
}
}
else if (function instanceof PortAware) {
if (!Objects.equals(((PortAware>) function).getPort(), value)) {
((PortAware>) function).setPort((Port>) value);
super.setValueAt(value, row, column);
valueChanged = true;
}
}
break;
case COLUMN_EXTRA:
function = macro.getFunction(row);
if (function instanceof ServoPortAction) {
ServoPort port = ((ServoPortAction) function).getPort();
if (port != null) {
int intValue = port.getAbsoluteValue(Integer.parseInt(value.toString()));
int oldValue = ((ServoPortAction) function).getValue();
if (oldValue != intValue) {
((ServoPortAction) function).setValue(intValue);
super.setValueAt(intValue, row, column);
valueChanged = true;
}
}
}
else if (function instanceof BacklightPortAction) {
BacklightPort port = ((BacklightPortAction) function).getPort();
if (port != null) {
int intValue = BacklightPort.getAbsoluteValue(Integer.parseInt(value.toString()));
int oldValue = ((BacklightPortAction) function).getValue();
if (oldValue != intValue) {
((BacklightPortAction) function).setValue(intValue);
super.setValueAt(intValue, row, column);
valueChanged = true;
}
}
}
else if (function instanceof MotorPortAction) {
MotorPort port = ((MotorPortAction) function).getPort();
if (port != null) {
int intValue = Integer.parseInt(value.toString());
int oldValue = ((MotorPortAction) function).getValue();
if (oldValue != intValue) {
((MotorPortAction) function).setValue(intValue);
super.setValueAt(intValue, row, column);
valueChanged = true;
}
}
}
break;
default:
super.setValueAt(value, row, column);
}
if (valueChanged) {
LOGGER.info("The current value was changed, set the pending changes state.");
macro.setMacroSaveState(MacroSaveState.PENDING_CHANGES);
}
}
@Override
public void functionsAdded(int macroId, int row, Function extends BidibStatus>[] functions) {
LOGGER.info("functions were added, macroId: {}, row: {}", macroId, row);
SwingUtils.executeInEDT(() -> {
if (macro == null || macroId != macro.getId()) {
LOGGER.info("Functions of other macro were added.");
return;
}
if (functions != null) {
for (int index = 0; index < functions.length; index++) {
insertRow(row + index, functions[index], row);
}
}
else {
insertRow(row, (Function extends BidibStatus>) null, row);
}
renumberSteps();
});
}
@Override
public void functionRemoved(int macroId, int row) {
SwingUtils.executeInEDT(() -> {
if (macro == null || macroId != macro.getId()) {
LOGGER.info("Functions of other macro were removed.");
return;
}
removeRow(row);
renumberSteps();
});
}
@Override
public void functionsRemoved(int macroId) {
SwingUtils.executeInEDT(() -> {
if (macro == null || macroId != macro.getId()) {
LOGGER.info("Functions of other macro were removed.");
return;
}
setRowCount(0);
});
}
@Override
public void reorder(int fromIndex, int toIndex, int rowCount) {
LOGGER.info("reorder, fromIndex: {}, toIndex: {}, rowCount: {}", fromIndex, toIndex, rowCount);
if (fromIndex < toIndex) {
for (int row = 0; row < rowCount; row++) {
LOGGER.info("I. Move row: {}, fromIndex: {}, toIndex: {}", row, fromIndex, toIndex);
macro.moveFunction(fromIndex, toIndex);
}
}
else { // fromIndex > toIndex
for (int row = 0; row < rowCount; row++) {
LOGGER.info("II. Move row: {}, fromIndex: {}, toIndex: {}", row, fromIndex, toIndex);
macro.moveFunction(fromIndex + (rowCount - 1), toIndex);
}
}
renumberSteps();
}
private void moveRow(int srcRow, int targetRow, Function extends BidibStatus> function) {
Object[] rowData = new Object[columnNames.length];
int functionIndex = 0;
for (int column = 0; column < columnNames.length; column++) {
rowData[column] = getRowData(column, function, functionIndex);
}
LOGGER.info("Remove srcRow: {}, targetRow: {}, rowData: {}", srcRow, targetRow, rowData);
removeRow(srcRow);
if (targetRow > srcRow) {
insertRow(targetRow, rowData);
}
else {
insertRow(targetRow, rowData);
}
}
@Override
public void functionMoved(int macroId, int fromIndex, int toIndex, Function extends BidibStatus> fromFunction) {
SwingUtils.executeInEDT(() -> {
LOGGER
.info("functionMoved, macroId: {}, fromIndex: {}, toIndex: {}, fromFunction: {}", macroId, fromIndex,
toIndex, Function.getDebugString(fromFunction));
if (macro == null || macroId != macro.getId()) {
LOGGER.info("Functions of other macro were moved.");
return;
}
moveRow(fromIndex, toIndex, fromFunction);
});
}
}