home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK4 / SAMPLES / CPPTUTOR / OOD / EVENT.H$ / EVENT
Encoding:
Text File  |  1991-11-06  |  9.9 KB  |  400 lines

  1. /********************************************************************
  2.  
  3.  FILE: EVENT.H
  4.  
  5.  Defines base class for events and predefined event types.
  6.  
  7.                     (Event)
  8.                       |
  9.      ----------------------------------
  10.      |          |          |          |
  11.   KbdEvent  MouseEvent  ScrlEvent  PushEvent
  12.  
  13. ********************************************************************/
  14.  
  15. #if !defined( _EVENT_H_ )
  16.  
  17. #define _EVENT_H_
  18.  
  19. #include "misc.h"
  20.  
  21. enum EventType { KBD_EVENT = 1,
  22.                  MOUSE_EVENT,
  23.                  SCRL_EVENT,
  24.                  PUSH_EVENT };
  25.  
  26. /********************************************************************
  27.  
  28.  Event
  29.  
  30.  Defines a base class for all types of events.
  31.  
  32.  Public Interface:
  33.  
  34.     getType - returns type of event
  35.  
  36. ********************************************************************/
  37.  
  38. class Event
  39. {
  40. public:
  41.     virtual EventType getType() const = 0;
  42.     virtual ~Event() {}
  43. };
  44.  
  45. /********************************************************************
  46.  
  47.  KbdEvent
  48.  
  49.  Defines events generated by the keyboard. Each event contains
  50.  an ASCII character and a scancode, allowing cursor keys to be
  51.  read.
  52.  
  53.  Public Interface:
  54.  
  55.      KbdEvent - constructor taking two characters, an ASCII value
  56.          and a scan code (0 if none)
  57.      val - returns value of key pressed. The value is returned as
  58.          an integer with the scan code in the high word (0 if none)
  59.          and the ASCII value in the low word. This allows the value
  60.          to be compared directly with chars (through the built-in
  61.          conversion).
  62.  
  63.  (inherited from Event)
  64.  
  65.      getType - redefined to return KBD_EVENT
  66.  
  67. ********************************************************************/
  68.  
  69.  
  70. class KbdEvent : public Event
  71. {
  72. public:
  73.     KbdEvent(char one, char two = 0);
  74.     // use default copy-constructor (memberwise initialization)
  75.     // use default operator= (memberwise assignment)
  76.     EventType getType() const;
  77.     unsigned int val() const;
  78. private:
  79.     char ascii;
  80.     char scancode;
  81. };
  82.  
  83. inline KbdEvent::KbdEvent( char one, char two )
  84. {
  85.     ascii = one;
  86.     scancode = two;
  87. }
  88.  
  89. inline EventType KbdEvent::getType() const
  90. {
  91.     return KBD_EVENT;
  92. }
  93.  
  94. inline unsigned int KbdEvent::val() const
  95. {
  96.     return ((unsigned int) scancode << 8) |
  97.            (unsigned char) ascii;
  98. }
  99.  
  100. /********************************************************************
  101.  
  102.  MouseEvent
  103.  
  104.  Defines events generated by the mouse. Each event contains the
  105.  position at which the event occurred and the status of the mouse
  106.  buttons during the event.
  107.  
  108.  Public Interface:
  109.  
  110.      MouseEvent - constructor taking the position of the event and
  111.          an integer representing the button status
  112.  
  113.      getPosition - returns position at which event occurred
  114.  
  115.      getButton - returns status of mouse buttons, encoded as
  116.          an integer.
  117.  
  118.  (inherited from Event)
  119.      getType - redefined to return MOUSE_EVENT
  120.  
  121. ********************************************************************/
  122.  
  123. class MouseEvent : public Event
  124. {
  125. public:
  126.     MouseEvent( Point pos, int but );
  127.     // use default copy-constructor (memberwise initialization)
  128.     // use default operator= (memberwise assignment)
  129.     EventType getType() const;
  130.     Point getPosition() const;
  131.     int   getButton() const;
  132. private:
  133.     MouseStatus status;
  134. };
  135.  
  136. inline MouseEvent::MouseEvent( Point pos, int but )
  137. {
  138.     status.position = pos;
  139.     status.button = but;
  140. }
  141.  
  142. inline EventType MouseEvent::getType() const
  143. {
  144.     return MOUSE_EVENT;
  145. }
  146.  
  147. inline Point MouseEvent::getPosition() const
  148. {
  149.     return status.position;
  150. }
  151.  
  152. inline int MouseEvent::getButton() const
  153. {
  154.     return status.button;
  155. }
  156.  
  157. /********************************************************************
  158.  
  159.  ScrollEvent
  160.  
  161.  Defines a request for scrolling. Each event contains the direction
  162.  and distance of scrolling requested, and a pointer to the
  163.  ScrollBar that generated the event.
  164.  
  165.  Public Interface:
  166.  
  167.      ScrollEvent - constructor taking flags indicating the direction
  168.          and distance of scrolling, and the scroll bar that originated
  169.          the event
  170.  
  171.      getDirection - returns direction
  172.  
  173.      getDistance - returns distances
  174.  
  175.      getSource - returns pointer to ScrollBar that generated the
  176.          event
  177.  
  178.  (inherited from Event)
  179.  
  180.      getType - redefined to return SCRL_EVENT
  181.  
  182. ********************************************************************/
  183.  
  184. class ScrollBar;
  185.  
  186. enum DirType { FORWARD = 1, BACKWARD };
  187.  
  188. enum DistType{ LINE = 1, PAGE };
  189.  
  190. class ScrollEvent : public Event
  191. {
  192. public:
  193.     ScrollEvent( DirType dir, DistType dist, ScrollBar *src );
  194.     // use default copy-constructor (memberwise initialization)
  195.     // use default operator= (memberwise assignment)
  196.     EventType  getType() const;
  197.     DirType    getDirection() const;
  198.     DistType   getDistance() const;
  199.     ScrollBar *getSource() const;
  200. private:
  201.     DirType    direction;
  202.     DistType   distance;
  203.     ScrollBar *const source;
  204. };
  205.  
  206. inline ScrollEvent::ScrollEvent( DirType dir, DistType dist, ScrollBar *src )
  207. : source( src )
  208. {
  209.     direction = dir;
  210.     distance = dist;
  211. }
  212.  
  213. inline EventType ScrollEvent::getType() const
  214. {
  215.     return SCRL_EVENT;
  216. }
  217.  
  218. inline DirType ScrollEvent::getDirection() const
  219. {
  220.     return direction;
  221. }
  222.  
  223. inline DistType ScrollEvent::getDistance() const
  224. {
  225.     return distance;
  226. }
  227.  
  228. inline ScrollBar *ScrollEvent::getSource() const
  229. {
  230.     return source;
  231. }
  232.  
  233. /********************************************************************
  234.  
  235.  PushEvent
  236.  
  237.  Defines a button press event. Each event contains a pointer to
  238.  the PushButton that generated it.
  239.  
  240.  Public Interface:
  241.  
  242.      PushEvent - constructor taking the push button that generated the
  243.          event
  244.  
  245.      getSource - returns pointer to PushButton that generated
  246.          the event
  247.  
  248.  (inherited from Event)
  249.  
  250.      getType - redefined to return PUSH_EVENT
  251.  
  252. ********************************************************************/
  253.  
  254. class PushButton;
  255.  
  256. class PushEvent : public Event
  257. {
  258. public:
  259.     PushEvent( PushButton *src ) : source( src ) {}
  260.     // use default copy-constructor (memberwise initialization)
  261.     // use default operator= (memberwise assignment)
  262.     EventType   getType() const;
  263.     PushButton *getSource() const;
  264. private:
  265.     PushButton *const source;
  266. };
  267.  
  268. inline EventType PushEvent::getType() const
  269. {
  270.     return PUSH_EVENT;
  271. }
  272.  
  273. inline PushButton *PushEvent::getSource() const
  274. {
  275.     return source;
  276. }
  277.  
  278. /********************************************************************
  279.  
  280.  EventGenerator
  281.  
  282. ********************************************************************/
  283.  
  284. class EventGenerator
  285. {
  286. public:
  287.     EventGenerator();
  288.     Event *getNextEvent();
  289.    ~EventGenerator();
  290. private:
  291.     MouseEvent *getMouseEvent();
  292.     MouseStatus lastStatus;
  293. };
  294.  
  295. /********************************************************************
  296.  
  297.    NOTES ON ALTERNATE IMPLEMENTATIONS
  298.  
  299.    The getType() function of events returns an enumerated type.
  300.    An enum is used for simplicity. Its drawback is that the enum
  301.    must be kept synchronized with the types of events. When a new
  302.    type of event is defined, the enum must be modified, causing
  303.    all previously defined events to be recompiled.
  304.  
  305.    One alternative is to have each class define a static integer member,
  306.    and use its address to identify the class (see Ellis & Stroustrup, p 213):
  307.  
  308.    class Event
  309.    {
  310.    public:
  311.        virtual int *getType();
  312.    };
  313.  
  314.    class KbdEvent : public Event
  315.    {
  316.    public:
  317.        static int rep;
  318.        int *getType() { return &rep; }
  319.    };
  320.  
  321.    void TextWin::handleEvent( Event &action )
  322.    {
  323.        if( action.getType() == &KbdEvent::rep )
  324.        {
  325.           // ...
  326.        }
  327.        else if( action.getType() == &MouseEvent::rep )
  328.        {
  329.           // ...
  330.        }
  331.        else
  332.        //..
  333.    }
  334.  
  335.    This technique guarantees a unique value for each class, and
  336.    lets a new type of event to be defined without having to update
  337.    existing files.
  338.  
  339.    One way to avoid the use of a getType() function altogether,
  340.    and thus avoid performing a switch on the type of event, is to
  341.    use pointers to member functions. To use them, you define a
  342.    separate function to handle each type of event, as follows:
  343.  
  344.    class Win
  345.    {
  346.    public:
  347.        virtual void handleEvent( Event &action ) {}
  348.        virtual void handleKbdEvent( KbdEvent &action ) {}
  349.        virtual void handleMouseEvent( MouseEvent &action ) {}
  350.        //...
  351.    };
  352.  
  353.    With such a design, each type of window overrides the functions
  354.    for the events it responds to. If a window ignores a certain
  355.    type of event, it uses the default implementation, which is
  356.    a null function.
  357.  
  358.    Each Event contains a pointer to the member function that
  359.    receives it.
  360.  
  361.    // pointer to a member function of Win that
  362.    //     takes an Event argument and returns void
  363.    typedef void (Win::*ptrWinFunc)( Event &action );
  364.  
  365.    class MouseEvent : public Event
  366.    {
  367.    public:
  368.        ptrWinFunc getHandler()  { return &Win::handleMouseEvent; }
  369.        // ...
  370.    };
  371.  
  372.    class KbdEvent : public Event
  373.    {
  374.    public:
  375.        ptrWinFunc getHandler()  { return &Win::handleKbdEvent; }
  376.        // ...
  377.    };
  378.  
  379.    The handleEvent function receives an Event, gets a pointer to
  380.    a member function from it, and calls that function, passing
  381.    the Event to it.
  382.  
  383.    void Win::handleEvent( Event &action )
  384.    {
  385.        // get handler function from Event
  386.        ptrWinFunc eventHandler = action.getHandler();
  387.        // pass Event to it
  388.        (this->*eventHandler)( action );
  389.    }
  390.  
  391.    This approach provides faster execution than a switch statement.
  392.    The main drawback is that if you define a new type of event,
  393.    you have to modify the interface to Win by adding a new function
  394.    that handles the event.
  395.  
  396. ********************************************************************/
  397.  
  398.  
  399. #endif // _EVENT_H_
  400.