/**
   * Set delay time (ms). The simulation loop delays given value every simulated millisecond. If the
   * value is zero there is no delay. If the value is negative, the simulation loop delays 1ms every
   * (-time) simulated milliseconds.
   *
   * <p>Examples: time=0: no sleeping (simulation runs as fast as possible). time=10: simulation
   * delays 10ms every simulated millisecond. time=-5: simulation delays 1ms every 5 simulated
   * milliseconds.
   *
   * <p>Special case: time=Integer.MIN_VALUE: simulation tries to execute at real time.
   *
   * @param time New delay time value
   */
  public void setDelayTime(int time) {
    if (time == Integer.MIN_VALUE) {
      /* Special case: real time */
      delayTime = Integer.MIN_VALUE;
      delayPeriod = Integer.MIN_VALUE;
      delayLastSim = System.currentTimeMillis();
    } else if (time < 0) {
      delayTime = 1;
      delayPeriod = -time;
    } else {
      delayTime = time;
      delayPeriod = 1; /* minimum */
    }

    invokeSimulationThread(
        new Runnable() {
          public void run() {
            if (!delayEvent.isScheduled()) {
              scheduleEvent(
                  delayEvent,
                  currentSimulationTime - (currentSimulationTime % MILLISECOND) + MILLISECOND);
            }
            Simulation.this.setChanged();
            Simulation.this.notifyObservers(this);
          }
        });
  }
 public void actionPerformed(ActionEvent e) {
   Runnable r =
       new Runnable() {
         public void run() {
           reset();
         }
       };
   if (simulation.isRunning()) {
     simulation.invokeSimulationThread(r);
   } else {
     r.run();
   }
 }
  /**
   * Add millisecond observer. This observer is notified once every simulated millisecond.
   *
   * @see #deleteMillisecondObserver(Observer)
   * @param newObserver Observer
   */
  public void addMillisecondObserver(Observer newObserver) {
    millisecondObservable.addObserver(newObserver);
    hasMillisecondObservers = true;

    invokeSimulationThread(
        new Runnable() {
          public void run() {
            if (!millisecondEvent.isScheduled()) {
              scheduleEvent(
                  millisecondEvent,
                  currentSimulationTime - (currentSimulationTime % MILLISECOND) + MILLISECOND);
            }
          }
        });
  }
  /**
   * Removes a mote from this simulation
   *
   * @param mote Mote to remove
   */
  public void removeMote(final Mote mote) {

    /* Simulation is running, remove mote in simulation loop */
    Runnable removeMote =
        new Runnable() {
          public void run() {
            motes.remove(mote);
            currentRadioMedium.unregisterMote(mote, Simulation.this);

            /* Dispose mote interface resources */
            mote.removed();
            for (MoteInterface i : mote.getInterfaces().getInterfaces()) {
              i.removed();
            }

            setChanged();
            notifyObservers(mote);

            /* Loop through all scheduled events.
             * Delete all events associated with deleted mote. */
            TimeEvent ev = eventQueue.peekFirst();
            while (ev != null) {
              if (ev instanceof MoteTimeEvent) {
                if (((MoteTimeEvent) ev).getMote() == mote) {
                  ev.remove();
                }
              }
              ev = ev.nextEvent;
            }
          }
        };

    if (!isRunning()) {
      /* Simulation is stopped, remove mote immediately */
      removeMote.run();
    } else {
      /* Remove mote from simulation thread */
      invokeSimulationThread(removeMote);
    }

    getGUI().closeMotePlugins(mote);
  }
  /**
   * Adds a mote to this simulation
   *
   * @param mote Mote to add
   */
  public void addMote(final Mote mote) {
    Runnable addMote =
        new Runnable() {
          public void run() {
            if (mote.getInterfaces().getClock() != null) {
              if (maxMoteStartupDelay > 0) {
                mote.getInterfaces()
                    .getClock()
                    .setDrift(
                        -getSimulationTime() - randomGenerator.nextInt((int) maxMoteStartupDelay));
              } else {
                mote.getInterfaces().getClock().setDrift(-getSimulationTime());
              }
            }

            motes.add(mote);
            currentRadioMedium.registerMote(mote, Simulation.this);

            /* Notify mote interfaces that node was added */
            for (MoteInterface i : mote.getInterfaces().getInterfaces()) {
              i.added();
            }

            setChanged();
            notifyObservers(mote);
          }
        };

    if (!isRunning()) {
      /* Simulation is stopped, add mote immediately */
      addMote.run();
    } else {
      /* Add mote from simulation thread */
      invokeSimulationThread(addMote);
    }
  }