Package net.sf.mrailsim.signals

Source Code of net.sf.mrailsim.signals.MainSignal

/************************************************************************************

    MRailSim - a model railway simulation program - http://mrailsim.sourceforge.net/
    Copyright (C) 2004,2007  Bernd Arnold

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

   
************************************************************************************/


package net.sf.mrailsim.signals;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import net.sf.mrailsim.rails.Node;
import net.sf.mrailsim.rails.Track;
import net.sf.mrailsim.rails.TrackChangeListener;

public class MainSignal extends Signal {

  private ArrayList<PreSignal> preSignals;
  private boolean manualStop = false;
  private boolean automaticStop = false;
  private AutomaticModule autoModule = null;
 
 
  abstract class AutomaticModule implements TrackChangeListener {
  }
 
 
  class LookaheadModule extends AutomaticModule {
   
    ArrayList<Track> observedTracks;
    int depth;

    LookaheadModule( int depth ) {
      observedTracks = new ArrayList<Track>();

      this.depth = depth;
     
      try {
        addLookaheads( depth, getBoundTrack(), getBoundNode() );
      } catch (Exception e) {
        // TODO Handle right
        e.printStackTrace();
      }
     
      for ( Track t : observedTracks ) {
        t.addChangeListener( this );
      }
    }
   
    private void addLookaheads( int amount, Track trackStart, Node nodeStart ) throws Exception {
      // Don't go any further if this track was already assigned
      if ( observedTracks.indexOf( trackStart ) >= 0 ) {
        return;
      }
     
      observedTracks.add( trackStart );
     
      amount--;
     
      if ( amount == 0 ) {
        return;
      }
     
      HashMap<Node, Track> list = null;
      list = trackStart.getPossibleNextTracksWithNodes( nodeStart );
     
      Set<Node> nodes = list.keySet();
      Iterator<Node> iterator = nodes.iterator();
     
      while ( iterator.hasNext() ) {
        Node node = iterator.next();
        Track track = list.get( node );
        addLookaheads( amount, track, node );
      }
    }

    public void updateFromTrack( Track t ) {
      boolean freeRide = true;
     
      ArrayList<Track> list;
      try {
        list = getBoundTrack().getNextTracks( getBoundNode(), depth - 1, true );
        for ( Track item : list ) {
          if ( item.isOccupied() ) {
            freeRide = false;
            break;
          }
        }
      } catch (Exception e) {
        // May also happen when the way is not completely switched
        // For example, when the signal looks ten tracks ahead and there
        // are switches included, so changing the position of the first switch
        // may end in a dead switch until the dead switch is changed too
        freeRide = false;
      }
      setAutomaticStop( ! freeRide );
    }
   
  }
 
 
  public MainSignal( long id ) {
    super( id );
    preSignals = new ArrayList<PreSignal>();
  }
 
  public void update() {
    if ( autoModule != null ) {
      autoModule.updateFromTrack( null );
    }
  }
 
  public void setBound( Track boundTrack, Node boundNode ) {
    super.setBound( boundTrack, boundNode );

    boundTrack.addMainSignal( this );
  }
 
  public void makeLookaheadSignal( int depth ) {
    autoModule = new LookaheadModule( depth );
  }

  public void registerPreSignal( PreSignal preSignal ) {
    // Only add pre signal if not in list
    if ( ! preSignals.contains( preSignal ) ) {
      preSignals.add( preSignal );
    }
    preSignal.updateFromMain( display );
  }
 
  private void hasChanged() {
    for ( PreSignal item : preSignals ) {
      item.updateFromMain( display );
    }
  }
 
  public void draw( Graphics g ) {
    if ( coordinates != null ) {
      g.setColor( Color.BLACK );
      g.fillRect( coordinates.getX(), coordinates.getY(), 12, 12 );

      if ( display == SignalDisplay.GREEN ) {
        g.setColor( Color.GREEN );
      } else if ( display == SignalDisplay.RED ) {
        g.setColor( Color.RED );
      } else {
        g.setColor( Color.BLACK );
      }

      g.fillOval( coordinates.getX() + 1, coordinates.getY() + 1, 10, 10 );
    }
  }

  public void toggleManualStop() {
    setManualStop( ! manualStop );
  }
 
  public SignalDisplay getDisplay() {
    if ( manualStop) {
      return SignalDisplay.RED;
    }
    else return super.getDisplay();
  }
 
  public String toString() {
    String out = String.format( "Signal: %d\n",
        id );
    out += String.format( "Current display: %s\n" ,
        display );
    out += "Signal type: main signal\n";
    out += String.format( "Automatic (track occupied) stop: %s\n",
        automaticStop );
    out += String.format( "Manual stop: %s\n",
        manualStop );
    if ( getBoundTrack() != null  &&  getBoundNode() != null ) {
      out += String.format( "Bound to: track %d, node %d\n",
          getBoundTrack().getId(), getBoundNode().getId() );
    } else {
      out += "Bound to: -\n";
    }
   
    return out;
  }
 
  void setAutomaticStop( boolean newStop ) {
    SignalDisplay oldDisplay = display;
    automaticStop = newStop;
    display = SignalDisplay.GREEN;

    if ( automaticStop || manualStop ) {
      display = SignalDisplay.RED;
    }
    if ( oldDisplay != display ) {
      hasChanged();
    }
  }
 
  void setManualStop( boolean newStop ) {
    SignalDisplay oldDisplay = display;
    manualStop = newStop;
    display = SignalDisplay.GREEN;

    if ( automaticStop || manualStop ) {
      display = SignalDisplay.RED;
    }
    if ( oldDisplay != display ) {
      hasChanged();
    }
  }

  public void handleMouseClick() {
    toggleManualStop();
  }

}
TOP

Related Classes of net.sf.mrailsim.signals.MainSignal

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.