/************************************************************************/
/* Copyright 1998 MBARI							*/
/************************************************************************/
#ifndef _PERIODICHANDLER_H
#define _PERIODICHANDLER_H
static char PeriodicHandler_h_id[] = "$Header: /u/oreilly/rov/tmacs/RCS/PeriodicHandler.h,v 1.6 1998/12/18 21:07:21 oreilly Exp $";

/*
$Log: PeriodicHandler.h,v $
Revision 1.6  1998/12/18 21:07:21  oreilly
Added documentation

Revision 1.5  1997/10/03 09:38:41  oreilly
*** empty log message ***

 * Revision 1.4  97/03/20  12:36:19  12:36:19  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.3  96/10/28  09:13:53  09:13:53  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
*/

#include "SList.h"
#include "DmGuiObject.h"
#include "RegisteredItem.h"

class PeriodicHandler;

/*
CLASS 
RegisteredPeriod

DESCRIPTION
RegisteredPeriod lists DmGuiObjects to be updated at a specific
interval.

AUTHOR
Tom O'Reilly
*/
class RegisteredPeriod : public RegisteredItem
{
  friend class PeriodicHandler;

  public:
  
  RegisteredPeriod(int interval);
  ~RegisteredPeriod() 
  {
  }

  private:
  int _interval;
};


class DmGuiApp;


/*
CLASS 
PeriodicHandler

DESCRIPTION
Maintains list of update periods and associated DmGuiObjects; invokes 
updateGui() method of DmGuiObjects at appropriate intervals.

A DmGuiObject is associated with a particular period by the registerObj()
function.

PeriodicHandler maintains a single Xt timer; the timeout interval is set to 
a value which is the largest common denominator of all registered intervals. 
For example, if intervals 150 and 200 have been registered, PeriodicHandler's 
Xt timeout interval is set to 50. At timeout, function 
PeriodicHandler::handleTimeout() determines which intervals have "expired", 
and calls DmGuiObject::updateGui() for all DmGuiObjects associated
with the expired interval(s). 


AUTHOR
Tom O'Reilly
*/
class PeriodicHandler
{
  friend class DmGuiApp;
  
  public:
  PeriodicHandler();
  ~PeriodicHandler() 
  {
    ;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Register DmGuiObject at requested interval
  registerObj(DmGuiObject *guiObj, int interval);
  
  ///////////////////////////////////////////////////////////////////
  // Unregister DmGuiObject item
  unregisterObj(DmGuiObject *);
  
  ///////////////////////////////////////////////////////////////////
  // Start periodic timer, reset accumulated time
  void start(void) 
  {
    _running = TRUE;
    _accumulated = 0;
    timerInterval();
    restart();
  }
  
  ///////////////////////////////////////////////////////////////////
  // Stop handler's timer 
  void stop(void)
  {
    XtRemoveTimeOut(_timerId);
    _running = FALSE;
  }
  

  ///////////////////////////////////////////////////////////////////
  // Restart handler's timer
  void restart(void) 
  {
     _timerId = XtAppAddTimeOut(theApplication->appContext(), _timerInterval, 
			       &PeriodicHandler::timerCallback, 
			       (XtPointer )this);
  }

  
  protected:

  ///////////////////////////////////////////////////////////////////
  // Accumulated time since timers started
  int _accumulated;    

  int _timerInterval;

  int _maxInterval;
  
  XtIntervalId _timerId;
  
  SList<RegisteredPeriod *> _periodList;

  ///////////////////////////////////////////////////////////////////
  // Called when timer expires. Determine which registered periods 
  // have timed-out, and call updateGui() for all associated DmGuiObjects.
  void handleTimeout(void);

  ///////////////////////////////////////////////////////////////////
  // Determine interval at which to run timer, such that all registered
  // intervals will get sampled. This is the greatest integer by which all
  // intervals are divisible.
  int timerInterval(void);
  
  MBool _running;
  
  private:
  
  ///////////////////////////////////////////////////////////////////
  // timerCallback() is called when timer expires 
  static void timerCallback(XtPointer clientData, XtIntervalId *id);
};


#endif
