The scrollable text window is useful, but the client may want other kinds of windows as well. The client should be able to define a new window class while still taking advantage of WinMgr and the existing event-passing scheme.
You can support this by changing Win to an abstract class descended from Interactor. We'll change the name of our text window class to TextWin and derive it from Win. Win acts as the base for any type of window, including those that the client defines. WinMgr treats all the windows it manages as generic Win objects and passes events to them. Furthermore, a scroll bar considers its parent to be a generic Win, so it can be a child of any type of window, not just text windows.
Thus, Win provides a polymorphic interface through which WinMgr and ScrollBar can access all windows. To a lesser degree, Win can also permit code reuse if you give it the common characteristics of all windows (for example, a data member to store a title and a function to set the title).
The revised window hierarchy is shown in Figure 10.6.
Suppose you want an editable text window. Such a window should have all the scrolling and cursor movement capabilities of the non-editable window already defined, plus the ability to accept text from the user. This situation calls for inheritance.
You can define a class EditWin that derives from TextWin. Since a pointer to a derived class object can be treated like a pointer to a base class object, you can insert these editable windows into WinMgr.
The main difference between TextWin and EditWin is in their behavior. When a printable character is received from the keyboard, TextWin ignores it. EditWin responds by writing that character at the current cursor location and moving the cursor one space to the right. EditWin and TextWin respond identically to all other events, such as mouse clicks or cursor key presses.
The new behavior must be implemented in the handleEvent function of EditWin, overriding the handleEvent function of TextWin. However, it is not necessary to reimplement all the behavior that the windows share. The handleEvent function of EditWin can call the handleEvent function of TextWin and pass it all events that it doesn't handle itself. For example:
EditWin::handleEvent( Event &action )
{
switch ( action.getType() )
{
KBD_EVENT:
KbdEvent &keyAction = (KbdEvent &) action;
if ( printable( keyAction.val() ) )
// Modify text buffer, move cursor
else // Pass on other keyboard events
TextWin::handleEvent( action );
break;
default: // Pass on all other events
TextWin::handleEvent( action );
break;
};
};
In this manner, EditWin can reuse selected portions of TextWin's event handling. This technique, having a derived class's member function call the base class's member function, can be used in many situations.