#ifndef _DMGUIOBJECT_H
#define _DMGUIOBJECT_H
static char DmGuiObject_h_id[] = "$Header: /usr/tiburon/unix/gui/tmacs/RCS/DmGuiObject.h,v 1.6 1997/10/03 09:29:27 oreilly Exp $";

/*
$Log: DmGuiObject.h,v $
Revision 1.6  1997/10/03 09:29:27  oreilly
*** empty log message ***

 * Revision 1.5  97/09/10  08:48:46  08:48:46  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.4  97/08/12  14:38:09  14:38:09  oreilly (Thomas C. O'Reilly)
 * Popup menu to plot object's DmObjects
 * 
 * Revision 1.3  97/03/20  12:33:46  12:33:46  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.2  96/10/28  09:13:35  09:13:35  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
*/


#include <stdio.h>
#include "Vk/VkComponent.h"
#include "Vk/VkApp.h"
#include "Vk/VkPopupMenu.h"
#include "DataManager.h"
#include "SList.h"
#include "ErrorHandler.h"
#include "Preference.h"

#define TRUE ~FALSE

#define dprintf if (debug) fprintf

#define DmGuiObjectPopupName "dmGuiObjectPopup"
#define CheckSticky True

const int Aperiodic = -1;
const int AperiodicGuaranteed = -2;

class DmGuiApp;
class PeriodicHandler;
class AperiodicHandler;

/* 
DmGuiObject Contains one or more DmObjects, and Gui components to 
display the DmObject values and/or modify DmObject values.

Responsibilities:
  Reads values from associated DmObject(s)
  Displays values to user via GUI components
  Reads user input to GUI components
  Writes user input values to DmObject(s)

How to derive classes:
  Method addDmObject() must be called for each created DmObject.
*/
class DmGuiObject : public VkComponent, public ErrorHandler {
  friend class PeriodicHandler;
  friend class AperiodicHandler; 

  public:

  DmGuiObject(const char *name, Widget parent);

  /* Destructor deletes all DmObjects */
  ~DmGuiObject();

  virtual const char *className() 
  {
    return "DmGuiObject";
  }
  
  // Set consume period for all consumer DmObject(s) in DmGuiObject
  virtual int setConsumePeriod(
			       int millisec
			       );

  // Return consume period for all consumer DmObject(s) in DmGuiObject
  // in milliseconds
  virtual int getConsumePeriod()
  {
    return _consumePeriod;
  }
  
  // Read DmObject(s), update Gui components based on new DM values 
  // (either from periodic timeout or aperiodic arrival of new data)
  virtual void updateGui(
			 DM_Item handle = 0 // i: DM handle which changed
			                    // (non-null for aperiodic 
                                            // only)
			 ) 
  {
  }
  

  // Receive update information from another DmGuiObject
  virtual void updateFromPeer(
			      DmGuiObject *peer,
			      void *clientData
			      )
  {
  }

  // Start i/o from DmObject(s)
  virtual int startDm();
  
  // Stop i/o from DmObject(s)
  virtual int stopDm();
  
  virtual int startProvide();
  virtual int startConsume();
  virtual int stopProvide();

  // Stop consuming dmObjects (except those that are consumed by a 
  // sticky consumer, if checkSticky == True).
  virtual int stopConsume(Boolean checkSticky = False);

  MBool provideEnabled()
  {
    return _provideEnabled;
  }
  
  MBool consumeEnabled()
  {
    return _consumeEnabled;
  }
  
  // Enable writing user input to DmObject(s)
  virtual void enableUserInput()  // was pure
  {
  }
  

  // Disable writing user input to DmObject(s)
  virtual void disableUserInput() // was pure
  {
  }
  

  // Pointer to cooperating DmGuiObject
  DmGuiObject *peer()
  {
    return _peer;
  }

  // Return number of consumers
  int nConsumers()
  {
    return _consumerDmObjectList.length();
  }
  

  // Return number of providers
  int nProviders()
  {
    return _providerDmObjectList.length();
  }  

  Boolean stickyConsumer()
  {
    return _stickyConsumer;
  }
  
  void setStickyConsumer(Boolean value);
  
  Boolean consumes(DM_Item dmItem);

  virtual int loadPreferences(DynArray<Preference *> *preferences, 
			      char *errorBuf);

  virtual int savePreferences(DynArray<Preference *> *preferences,
			      char *errorBuf);
  
  protected:

  /* Derived classes MUST create and destroy DmObjects using the functions
     addDmObject() and deleteDmObject()
  */
  int addDmObject(
		  DmObject *dmObject, 
		  DmRoleFlags flags
		  );
  
  void deleteDmObject(
		      DmObject *dmObject
		      );
  

  // Exit gracefully
  void exit(int status);
  
  // Get pointer to DmGuiApp
  static DmGuiApp *getDmGuiApp(); 

  Period _consumePeriod;
  Period _providePeriod;

  // Indicates if consumers and providers are active
  MBool _provideEnabled;
  MBool _consumeEnabled;  

  // Cooperating DmGuiObject (often is NULL)
  DmGuiObject *_peer;

  // Post menu showing options in response to button press
  virtual void postOptions(XEvent *event);

  // Menu posted by postOption  
  static VkPopupMenu *_popupMenu;


  /* Event handler to display options.
     Must be accessible to subclasses. */
  static void eventHandler(Widget w, XtPointer clientData, XEvent *event);

  /* Other DmGuiObjects won't stop consuming any of this one's consumed 
     items. */
  Boolean _stickyConsumer;
  
  private:
  
  // Linked lists of provider and consumer DmObjects
  SList<DmObject *> _providerDmObjectList;
  SList<DmObject *> _consumerDmObjectList;  

  Period millisecToPeriod(int millisec);
  MBool validMillisec(int millisec);

  // Add options to popup menu
  void addOptionItems();

  static void plotDmItemCallback(Widget w,
				 XtPointer clientData,
				 XtPointer callData);
};


#endif
