All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.mvc.main.model.MacroTableModel Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
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 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 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 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 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 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[] 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) 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 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 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);
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy