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

org.bidib.wizard.mvc.railcomplus.controller.RailcomPlusController Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
package org.bidib.wizard.mvc.railcomplus.controller;

import java.util.Collection;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import org.bidib.jbidibc.core.AddressData;
import org.bidib.jbidibc.core.DefaultMessageListener;
import org.bidib.jbidibc.core.RcPlusBindData;
import org.bidib.jbidibc.core.RcPlusDecoderAnswerData;
import org.bidib.jbidibc.core.RcPlusFeedbackBindData;
import org.bidib.jbidibc.core.RcPlusUniqueIdData;
import org.bidib.jbidibc.core.TidData;
import org.bidib.jbidibc.core.enumeration.AddressTypeEnum;
import org.bidib.jbidibc.core.enumeration.RcPlusAcknowledge;
import org.bidib.jbidibc.core.enumeration.RcPlusDecoderType;
import org.bidib.jbidibc.core.enumeration.RcPlusPhase;
import org.bidib.wizard.comm.Communication;
import org.bidib.wizard.comm.CommunicationFactory;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.mvc.common.view.DockKeys;
import org.bidib.wizard.mvc.main.controller.MainControllerInterface;
import org.bidib.wizard.mvc.main.model.MainModel;
import org.bidib.wizard.mvc.main.model.Node;
import org.bidib.wizard.mvc.main.model.listener.NodeListListener;
import org.bidib.wizard.mvc.railcomplus.model.RailcomPlusDecoderModel;
import org.bidib.wizard.mvc.railcomplus.model.RailcomPlusModel;
import org.bidib.wizard.mvc.railcomplus.model.listener.DecoderAddressListener;
import org.bidib.wizard.mvc.railcomplus.view.RailcomPlusView;
import org.bidib.wizard.mvc.railcomplus.view.listener.RailcomPlusViewListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vlsolutions.swing.docking.Dockable;
import com.vlsolutions.swing.docking.DockableState;
import com.vlsolutions.swing.docking.DockingConstants;
import com.vlsolutions.swing.docking.DockingDesktop;
import com.vlsolutions.swing.docking.DockingUtilities;
import com.vlsolutions.swing.docking.RelativeDockablePosition;
import com.vlsolutions.swing.docking.TabbedDockableContainer;

public class RailcomPlusController implements NodeListListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(RailcomPlusController.class);

    private DefaultMessageListener messageListener;

    private RailcomPlusModel railcomPlusModel;

    private RailcomPlusView railcomPlusView;

    private final DockingDesktop desktop;

    private final Node node;

    private final MainModel mainModel;

    public RailcomPlusController(final MainModel mainModel, final DockingDesktop desktop, final Node node) {
        this.mainModel = mainModel;
        this.desktop = desktop;
        this.node = node;
    }

    public void start(final MainControllerInterface mainController) {

        // check if the railcom view is already opened
        String searchKey = DockKeys.RAILCOM_PLUS_VIEW;
        LOGGER.info("Search for view with key: {}", searchKey);
        Dockable view = desktop.getContext().getDockableByKey(searchKey);
        if (view != null) {
            LOGGER.info("Select the existing railcom plus view instead of open a new one.");
            selectWindow(view);
            return;
        }

        LOGGER.info("Create new RailcomPlusView.");
        railcomPlusModel = new RailcomPlusModel();

        railcomPlusView = new RailcomPlusView(railcomPlusModel);

        DockableState[] dockables = desktop.getDockables();
        LOGGER.info("Current dockables: {}", new Object[] { dockables });
        if (dockables.length > 1) {

            DockableState tabPanelNodeDetails = null;
            // search the node details tab panel
            for (DockableState dockable : dockables) {

                if (DockKeys.DOCKKEY_TAB_PANEL.equals(dockable.getDockable().getDockKey())) {
                    LOGGER.info("Found the tab panel dockable.");
                    tabPanelNodeDetails = dockable;

                    break;
                }
            }

            Dockable dock = desktop.getDockables()[1].getDockable();
            if (tabPanelNodeDetails != null) {
                LOGGER.info("Add the railcom plus view to the node details panel.");
                dock = tabPanelNodeDetails.getDockable();

                TabbedDockableContainer container = DockingUtilities.findTabbedDockableContainer(dock);
                int order = 0;
                if (container != null) {
                    order = container.getTabCount();
                }
                LOGGER.info("Add new railcomPlusView at order: {}", order);

                desktop.createTab(dock, railcomPlusView, order, true);
            }
            else {
                desktop.split(dock, railcomPlusView, DockingConstants.SPLIT_RIGHT);
                // desktop.setDockableHeight(railcomPlusView, 0.2d);
            }
        }
        else {
            desktop.addDockable(railcomPlusView, RelativeDockablePosition.RIGHT);
        }

        final Communication communication = CommunicationFactory.getInstance();

        railcomPlusView.addRailcomPlusViewListener(new RailcomPlusViewListener() {

            private Node getCommandStationNode() {

                // search the command station node
                Collection nodes = mainController.getNodes();
                Node commandStationNode = null;
                for (Node node : nodes) {
                    if (node.isCommandStation()) {
                        commandStationNode = node;
                        LOGGER.info("Found a command station node: {}", commandStationNode);

                        break;
                    }
                }
                return commandStationNode;
            }

            @Override
            public void readTid() {
                LOGGER.info("Query the TID.");

                Node commandStationNode = getCommandStationNode();
                if (commandStationNode == null) {
                    LOGGER.warn("No command station node available! Operation aborted!");

                    // show dialog
                    JOptionPane.showMessageDialog(null,
                        Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                    return;
                }

                // clear the current TID
                railcomPlusModel.setTid(null);

                communication.getRcPlusTid(commandStationNode.getNode());
            }

            @Override
            public void updateSid() {

                TidData tidData = railcomPlusModel.getTid();
                if (tidData != null) {

                    int sid = tidData.getSid();
                    sid++;
                    LOGGER.info("Incremented the SID: {}", sid);

                    Node commandStationNode = getCommandStationNode();
                    if (commandStationNode == null) {
                        LOGGER.warn("No command station node available! Operation aborted!");

                        // show dialog
                        JOptionPane.showMessageDialog(null,
                            Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                        return;
                    }

                    communication.setRcPlusTid(commandStationNode.getNode(), new TidData(tidData.getUniqueId(), sid));

                }
                else {
                    LOGGER.warn("No TID available! Operation aborted!");

                    // TODO add I18N
                    JOptionPane.showMessageDialog(null, "No TID available! Read TID before update SID!");
                }
            }

            @Override
            public void updateTid() {

                TidData tidData = railcomPlusModel.getTid();
                if (tidData != null) {
                    int sid = tidData.getSid();
                    RcPlusUniqueIdData uniqueId = tidData.getUniqueId();
                    uniqueId = new RcPlusUniqueIdData(/* uniqueId.getMun() + 1 */0x0D0C0B0A, uniqueId.getMid());
                    LOGGER.info("Incremented the TID: {}", uniqueId);

                    Node commandStationNode = getCommandStationNode();
                    if (commandStationNode == null) {
                        LOGGER.warn("No command station node available! Operation aborted!");

                        // show dialog
                        JOptionPane.showMessageDialog(null,
                            Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                        return;
                    }

                    communication.setRcPlusTid(commandStationNode.getNode(), new TidData(uniqueId, sid));
                }
                else {
                    LOGGER.warn("No TID available! Operation aborted!");

                    // TODO add I18N
                    JOptionPane.showMessageDialog(null, "No TID available! Read TID before update SID!");
                }
            }

            public void pingOnce(RcPlusPhase phase) {
                Node commandStationNode = getCommandStationNode();
                if (commandStationNode == null) {
                    LOGGER.warn("No command station node available! Operation aborted!");

                    // show dialog
                    JOptionPane.showMessageDialog(null,
                        Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                    return;
                }

                communication.sendPingOnce(commandStationNode.getNode(), phase);
            }

            @Override
            public void ping(int interval) {
                Node commandStationNode = getCommandStationNode();
                if (commandStationNode == null) {
                    LOGGER.warn("No command station node available! Operation aborted!");

                    // show dialog
                    JOptionPane.showMessageDialog(null,
                        Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                    return;
                }

                communication.sendPing(commandStationNode.getNode(), interval);
            }

            @Override
            public void find(RcPlusPhase phase, RcPlusUniqueIdData decoder) {
                Node commandStationNode = getCommandStationNode();
                if (commandStationNode == null) {
                    LOGGER.warn("No command station node available! Operation aborted!");

                    // show dialog
                    JOptionPane.showMessageDialog(null,
                        Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                    return;
                }

                communication.sendFind(commandStationNode.getNode(), phase, decoder);
            }

            @Override
            public void bind(RcPlusBindData bindData) {
                Node commandStationNode = getCommandStationNode();
                if (commandStationNode == null) {
                    LOGGER.warn("No command station node available! Operation aborted!");

                    // show dialog
                    JOptionPane.showMessageDialog(null,
                        Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                    return;
                }

                communication.sendBind(commandStationNode.getNode(), bindData);
            }

        });

        try {
            // Create the message listener for the railcom plus messages
            messageListener = new DefaultMessageListener() {

                @Override
                public void csRcPlusTid(final byte[] address, final TidData tid) {
                    LOGGER.info("Received the TID: {}, address: {}", tid, address);

                    if (SwingUtilities.isEventDispatchThread()) {
                        railcomPlusModel.setTid(tid);
                    }
                    else {
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                railcomPlusModel.setTid(tid);
                            }
                        });
                    }
                }

                @Override
                public void csRcPlusPingAcknState(byte[] address, RcPlusPhase phase, RcPlusAcknowledge acknState) {
                    LOGGER.info("Received the ping ackn state: {}, phase: {}, address:{}", acknState, phase, address);
                    // no implementation
                }

                @Override
                public void csRcPlusBindAnswer(byte[] address, RcPlusDecoderAnswerData decoderAnswer) {
                    LOGGER.info("Received the bind answer: {}, address:{}", decoderAnswer, address);
                    // no implementation
                }

                @Override
                public void csRcPlusFindAnswer(byte[] address, RcPlusPhase phase, RcPlusDecoderAnswerData decoderAnswer) {
                    LOGGER.info("Received the find answer: {}, phase: {}, address:{}", decoderAnswer, phase, address);
                    // no implementation
                }

                @Override
                public void feedbackRcPlusBindAccepted(
                    byte[] address, int detectorNum, RcPlusDecoderType decoderType,
                    RcPlusFeedbackBindData rcPlusBindAccepted) {

                    LOGGER.info(
                        "Received the feedback bind accepted answer: {}, detectorNum: {}, decoderType: {}, address:{}",
                        rcPlusBindAccepted, detectorNum, decoderType, address);
                }

                @Override
                public void feedbackRcPlusPongNew(
                    byte[] address, int detectorNum, RcPlusPhase phase, RcPlusDecoderType decoderType,
                    RcPlusUniqueIdData uniqueId) {

                    LOGGER.info(
                        "Received the feedback PONG NEW, uniqueId: {}, detectorNum: {}, decoderType: {}, address:{}",
                        uniqueId, detectorNum, decoderType, address);

                    RailcomPlusDecoderModel decoder = new RailcomPlusDecoderModel();
                    decoder.setDecoderMun(uniqueId.getMun());
                    decoder.setDecoderManufacturer(uniqueId.getMid());

                    railcomPlusModel.addDecoder(decoder);
                }

                @Override
                public void feedbackRcPlusPongOkay(
                    byte[] address, int detectorNum, RcPlusPhase phase, RcPlusDecoderType decoderType,
                    RcPlusUniqueIdData uniqueId) {

                    LOGGER.info(
                        "Received the feedback PONG OKAY, uniqueId: {}, detectorNum: {}, decoderType: {}, address:{}",
                        uniqueId, detectorNum, decoderType, address);

                    RailcomPlusDecoderModel decoder = new RailcomPlusDecoderModel();
                    decoder.setDecoderMun(uniqueId.getMun());
                    decoder.setDecoderManufacturer(uniqueId.getMid());

                    railcomPlusModel.addDecoder(decoder);
                }
            };

            CommunicationFactory.addMessageListener(messageListener);

        }
        catch (Exception ex) {
            LOGGER.warn("Add message listener for railcom+ messages failed.", ex);
        }

        railcomPlusView.addDecoderAddressListener(new DecoderAddressListener() {

            private Node getCommandStationNode() {

                // search the command station node
                Collection nodes = mainController.getNodes();
                Node commandStationNode = null;
                for (Node node : nodes) {
                    if (node.isCommandStation()) {
                        commandStationNode = node;
                        LOGGER.info("Found a command station node: {}", commandStationNode);

                        break;
                    }
                }
                return commandStationNode;
            }

            @Override
            public void setAddress(RailcomPlusDecoderModel decoder) {

                LOGGER.info("Set address of decoder: {}", decoder);

                Node commandStationNode = getCommandStationNode();
                if (commandStationNode == null) {
                    LOGGER.warn("No command station node available! Operation aborted!");

                    // show dialog
                    JOptionPane.showMessageDialog(null,
                        Resources.getString(RailcomPlusController.class, "no_commandstation_available"));
                    return;
                }

                try {
                    RcPlusUniqueIdData uniqueIdData =
                        new RcPlusUniqueIdData(decoder.getDecoderMun(), decoder.getDecoderManufacturer());
                    AddressData address =
                        new AddressData(decoder.getDecoderAddress(), AddressTypeEnum.LOCOMOTIVE_FORWARD);

                    RcPlusBindData bindData = new RcPlusBindData(uniqueIdData, address);
                    communication.sendBind(commandStationNode.getNode(), bindData);
                }
                catch (Exception ex) {
                    LOGGER.warn("Set decoder address failed.", ex);
                }
            }
        });

        // add the node list listener
        mainModel.addNodeListListener(this);
    }

    private void selectWindow(Dockable dockable) {

        TabbedDockableContainer container = DockingUtilities.findTabbedDockableContainer(dockable);
        if (container != null) {
            container.setSelectedDockable(dockable);
        }
        else {
            LOGGER.warn("Container not available, select component directly.");
            dockable.getComponent().requestFocusInWindow();
        }
    }

    @Override
    public void listChanged() {
        LOGGER.info("The node list has changed.");
    }

    @Override
    public void nodeChanged() {
        LOGGER.debug("The node has changed, current node in model: {}", node);
        if (SwingUtilities.isEventDispatchThread()) {
            internalNodeChanged();
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    internalNodeChanged();
                }
            });
        }
    }

    private void internalNodeChanged() {

        LOGGER.debug("handle node has changed, node: {}", node);

        if (node != null && node.equals(mainModel.getSelectedNode())) {
            LOGGER.debug("The node in the model has not changed.");
            return;
        }

        // check if we must close the scenery panel
        // Dockable dmxSceneryDockable = desktop.getContext().getDockableByKey("DmxSceneryView");
        if (railcomPlusView != null) {
            LOGGER.info("Close the railcomPlusView panel: {}", railcomPlusView);

            desktop.close(railcomPlusView);
        }

        // unregister node list listener
        mainModel.removeNodeListListener(this);
    }

    @Override
    public void nodeStateChanged() {
    }

    @Override
    public void listNodeAdded(Node node) {
    }

    @Override
    public void listNodeRemoved(Node node) {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy