// Purpose.  Mediator
//
// Discussion.  On the left: Node objs  #include <iostream.h>
// interact directly with each other,
// recursion is required, removing a    class Node {
// Node is hard, and it is not possi-   public:
// ble to remove the first node.  On       Node( int v ) { val_ = v; }
// the right: a "mediating" List class     int getVal()  { return val_; }
// focuses and simplifies all the ad-   private:
// ministrative responsibilities, and      int  val_;
// the recursion (which does not scale  };
// up well) has been eliminated.
                                        class List {
#include <iostream.h>                   public:
                                           List() {
class Node {                                  for (int i=0; i < 10; i++)
public:                                          arr_[i] = 0;
   Node( int v, Node* n ) {                      num_ = 0;
      val_ = v;                            }
      next_ = n;                           void addNode( Node* n ) {
   }                                          arr_[num_++] = n;
   void traverse() {                       }
      cout << val_ << "  ";                void traverse() {
      if (next_)                              for (int i=0; i < num_; i++)
         next_->traverse();                      cout << arr_[i]->getVal()
      else                                          << "  ";
         cout << endl;                        cout << endl;
   }                                       }
   void removeNode( int v ) {              void removeNode( int v ) {
      Node*  ptr = (Node*) 1;                 int  i, j;
      removeNode_( v, &ptr );                 for (i=0; i < num_; i++)
   }                                             if (arr_[i]->getVal() == v)
private:                                         {
   int    val_;                                     for (j=i; j < num_; j++)
   Node*  next_;                                       arr_[j] = arr_[j+1];
   void removeNode_(int v, Node** n) {              num_--;
      if (val_ == v)                                break;
         *n = next_;                             }
      else                                 }
      {                                 private:
         next_->removeNode_( v, n );       Node*  arr_[10];
         if (*n != (Node*) 1)              int    num_;
         {                              };
            next_ = *n;
            *n = (Node*) 1;             void main( void )
         }                              {
      }                                    List  lst;
   }                                       Node  one( 11 ),  two( 22 );
};                                         Node  thr( 33 ),  fou( 44 );
                                           lst.addNode( &one );
void main( void )                          lst.addNode( &two );
{                                          lst.addNode( &thr );
   Node  fou( 44, 0 );                     lst.addNode( &fou );
   Node  thr( 33, &fou );                  lst.traverse();
   Node  two( 22, &thr );                  lst.removeNode( 44 );
   Node  one( 11, &two );                  lst.traverse();
   one.traverse();                         lst.removeNode( 11 );
   one.removeNode( 44 );                   lst.traverse();
   one.traverse();                      }
   one.removeNode( 22 );
   one.traverse();                      // 11  22  33  44
}                                       // 11  22  33
                                        // 22  33
// 11  22  33  44
// 11  22  33
// 11  33



// Purpose.  Mediator design pattern demo.
//
// Discussion.  Though partitioning a system into many objects generally
// enhances reusability, proliferating interconnections tend to reduce it
// again.  You can avoid this problem by capsulating the interconnections
// (i.e. the collective behavior) in a separate "mediator" object.  A
// mediator is responsible for controlling and coordinating the
// interactions of a group of objects.  In this example, the dialog box
// object is functioning as the mediator.  Child widgets of the dialog box
// do not know, or care, who their siblings are.  Whenever a simulated
// user interaction occurs in a child widget [Widget::changed()], the
// widget does nothing except "delegate" that event to its parent dialog
// box [_mediator->widgetChanged( this )].
// FileSelectionDialog::widgetChanged() encapsulates all collective
// behavior for the dialog box (it serves as the hub of communication).
// The user may choose to "interact" with a simulated: filter edit field,
// directories list, files list, or selection edit field.

#include <iostream.h>

class FileSelectionDialog;

class Widget {
public:
      Widget( FileSelectionDialog* mediator, char* name ) {
            _mediator = mediator;
            strcpy( _name, name); }
      virtual void changed();
      virtual void updateWidget() = 0;
      virtual void queryWidget() = 0;
protected:
      char                 _name[20];
private:
      FileSelectionDialog* _mediator;
};

class List : public Widget {
public:
      List( FileSelectionDialog* dir, char* name ) : Widget( dir, name ) { }
    void queryWidget()  { cout << "   " << _name << " list queried" << endl; }
      void updateWidget() { cout << "   " << _name << " list updated" << endl; }
};

class Edit : public Widget {
public:
    Edit( FileSelectionDialog* dir, char* name ): Widget( dir, name ) { }
    void queryWidget()  { cout << "   " << _name << " edit queried" << endl; }
    void updateWidget() { cout << "   " << _name << " edit updated" << endl; }
};


class FileSelectionDialog {
public:
      enum Widgets { FilterEdit, DirList, FileList, SelectionEdit };
      FileSelectionDialog() {
            _components[FilterEdit]    = new Edit( this, "filter" );
            _components[DirList]       = new List( this, "dir" );
            _components[FileList]      = new List( this, "file" );
            _components[SelectionEdit] = new Edit( this, "selection" ); }
      virtual ~FileSelectionDialog();
      void handleEvent( int which ) {
            _components[which]->changed(); }
      virtual void widgetChanged( Widget* theChangedWidget ) {
            if (theChangedWidget == _components[FilterEdit] ) {
                  _components[FilterEdit]->    queryWidget();
                  _components[DirList]->       updateWidget();
                  _components[FileList]->      updateWidget();
                  _components[SelectionEdit]-> updateWidget(); }
            else if (theChangedWidget == _components[DirList] ) {
                  _components[DirList]->       queryWidget();
                  _components[FileList]->      updateWidget();
                  _components[FilterEdit]->    updateWidget();
                  _components[SelectionEdit]-> updateWidget(); }
            else if (theChangedWidget == _components[FileList] ) {
                  _components[FileList]->      queryWidget();
                  _components[SelectionEdit]-> updateWidget(); }
            else if (theChangedWidget == _components[SelectionEdit] ) {
                  _components[SelectionEdit]-> queryWidget();
                  cout << "   file opened" << endl; } }
private:
      Widget* _components[4];
};

FileSelectionDialog::~FileSelectionDialog() {
      for (int i=0; i < 3; i++)
            delete _components[i]; }


void Widget::changed() {
      _mediator->widgetChanged( this ); }


void main() {
      FileSelectionDialog fileDialog;
      int                 i;

      cout << "Exit[0], Filter[1], Dir[2], File[3], Selection[4]: ";
      cin >> i;

      while (i)
      {
            fileDialog.handleEvent( i-1 );
            cout << "Exit[0], Filter[1], Dir[2], File[3], Selection[4]: ";
            cin >> i;
      }
}

// Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 1
//    filter edit queried
//    dir list updated
//    file list updated
//    selection edit updated
// Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 2
//    dir list queried
//    file list updated
//    filter edit updated
//    selection edit updated
// Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 3
//    file list queried
//    selection edit updated
// Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 4
//    selection edit queried
//    file opened
// Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 3
//    file list queried
//    selection edit updated