

#include "menudrv.h"
#include "ids.h"

#include "ui/composit.h"
#include "ui/menu.h"
#include "ui/applic.h"
#include "ui/stddlg.h"

typedef UI_EventBinding2 <MenuDriver> MenuBinding;
#if defined(__GNUC__)
template class UI_EventBinding2 <MenuDriver>; // Instantiate the binding
#endif


UI_MenuItemDescriptor ActSubmenu [] = { // Cascaded submenu
  {"&Month"           , ID_SUBMONTH}
, {"&Days"            , ID_SUBDAY}
, {NULL               , 0}
};

UI_MenuItemDescriptor ActMenu [] = {    // Actions pull-down menu
    {"&Add month"     , ID_ADD ,     NULL      }
  , {"&Enable/Disable", ID_DIS ,     ActSubmenu}
  , {"&Remove month"  , ID_REM ,     NULL      }
  , {UIMenu_Separator , NULL   ,     NULL      }
  , {"A&dd times"     , ID_ADDTM,    NULL      }
  , {"Re&move times"  , ID_REMTM,    NULL      }
  , {UIMenu_Separator , NULL   ,     NULL      }
  , {"&Quit"          , ID_QUIT,     NULL      }
  , {NULL             , 0      ,     NULL      }
};

UI_MenuItemDescriptor MonthMnu [] = {   // Month pull-down menu
    {"&Jan"           , ID_JAN}
  , {"&Feb"           , ID_FEB}
  , {"&Mar"           , ID_MAR}
  , {"&Apr"           , ID_APR}
  , {NULL             , 0     }
};

UI_MenuItemDescriptor DaysMenu [] = {   // Days pull-down menu
    {"Monday"         , ID_MON}
  , {"Tuesday"        , ID_TUE}
  , {"Wednesday"      , ID_WED}
  , {"Thursday"       , ID_THU}
  , {"Friday"         , ID_FRI}
  , {NULL             ,      0}
};

UI_MenuItemDescriptor TimesMenu [] = {   // Times pull-down menu
    {"Morning"        , ID_MORN}
  , {"Afternoon"      , ID_AFTER}
  , {"Evening"        , ID_EVE}
  , {NULL             ,      0}
};

UI_MenuItemDescriptor MainMenuDesc [] = {   // Main menu bar
    {"&Action"        , ID_ACT  ,  ActMenu }
  , {"&Month"         , ID_MONTH,  MonthMnu}
  , {"&Day"           , ID_DAYS ,  DaysMenu}
  , {NULL             ,        0,  NULL    }
};

struct DispatcherStruct {
    UI_ViewID              menu_id;
    MenuBinding::MethodPtr method;
    UI_EventType           event;
} FAR dispatch [] = {
    {ID_JAN,      MenuDriver::Inform,         Event_Select}      
  , {ID_FEB,      MenuDriver::Inform,         Event_Select}      
  , {ID_MAR,      MenuDriver::Inform,         Event_Select}      
  , {ID_APR,      MenuDriver::Inform,         Event_Select}      
                                                                          
  , {ID_ADD,      MenuDriver::Add,            Event_Select}           
  , {ID_REM,      MenuDriver::Remove,         Event_Select}           
  , {ID_ADDTM,    MenuDriver::AddTimes,       Event_Select}           
  , {ID_REMTM,    MenuDriver::RemoveTimes,    Event_Select}           
  , {ID_SUBMONTH, MenuDriver::DisableMonth,   Event_Select} 
  , {ID_SUBDAY,   MenuDriver::DisableDays,    Event_Select}   
  , {ID_QUIT,     MenuDriver::Quit,           Event_Select}

  , {ID_MON,      MenuDriver::SetDay,         Event_Select}      
  , {ID_TUE,      MenuDriver::SetDay,         Event_Select}      
  , {ID_WED,      MenuDriver::SetDay,         Event_Select}      
  , {ID_THU,      MenuDriver::SetDay,         Event_Select}      
  , {ID_FRI,      MenuDriver::SetDay,         Event_Select}      
                                                                          
};




MenuDriver::MenuDriver (UI_CompositeVObject* root)
{
    _menu =  new UI_MenuBar (root, MainMenuDesc);
    
    // Add the event dependents:
    for (short i = 0; i < sizeof dispatch/sizeof (DispatcherStruct); i++) {
        UI_ViewID id = dispatch[i].menu_id;
        MenuBinding bind (this, dispatch[i].method, id);
        (*_menu)[id]->AddEventDependent (dispatch[i].event, bind);
    }
    (*_menu)[ID_REM]->Disable();
    _daysEnabled = TRUE;
    _timesShown = FALSE;
    (*_menu)[ID_ADDTM]->Enable();
    (*_menu)[ID_REMTM]->Disable();

    // Make the days menu items checkable:
    (*_menu)[ID_MON]->SetCheck (UI_MenuItem::NotChecked);
    (*_menu)[ID_TUE]->SetCheck (UI_MenuItem::NotChecked);
    (*_menu)[ID_WED]->SetCheck (UI_MenuItem::NotChecked);
    (*_menu)[ID_THU]->SetCheck (UI_MenuItem::NotChecked);
    (*_menu)[ID_FRI]->SetCheck (UI_MenuItem::NotChecked);

    _checkedObjectID = 0;
}




bool MenuDriver::Inform (UI_Event&, UI_ViewID itemID)
{
    CL_String s = (*_menu)[itemID]->Title();
    s.Replace ("&", "");
    UI_StandardDialog ("You chose '" + s + "'", "YACL Menu Demo",
                       YACLApp()->MainWindow());
    return TRUE;
}


bool MenuDriver::SetDay (UI_Event&, UI_ViewID itemID)
{
    CL_String s = (*_menu)[itemID]->Title();
    s.Replace ("&", "");
    UI_StandardDialog ("Selected  '" + s + "'", "YACL Menu Demo",
                       YACLApp()->MainWindow());
    if (_checkedObjectID)
        (*_menu)[_checkedObjectID]->SetCheck (UI_MenuItem::NotChecked);
    (*_menu)[itemID]->SetCheck (UI_MenuItem::Checked);
    _checkedObjectID = itemID;
    return TRUE;
}


bool MenuDriver::Add (UI_Event&, UI_ViewID)
{
    _menu->AddSeparator (ID_MONTH);
    _menu->Add (ID_MAY, "Ma&y", ID_MONTH);
    (*_menu)[ID_ADD]->Disable();
    (*_menu)[ID_REM]->Enable();
    UI_StandardDialog ("Added an item to Month menu", "YACL Menu Demo");
    return TRUE;
}


bool MenuDriver::Remove (UI_Event&, UI_ViewID)
{
    _menu->Remove (ID_MAY);
    _menu->RemoveSeparator (ID_MONTH, 3);
    (*_menu)[ID_REM]->Disable();
    (*_menu)[ID_ADD]->Enable();
    UI_StandardDialog ("Removed an item from Month menu", "YACL Menu Demo",
                       YACLApp()->MainWindow());
    return TRUE;
}



bool MenuDriver::DisableMonth (UI_Event&, UI_ViewID)
{
    UI_MenuItem* m = (*_menu)[ID_MONTH];
    m->ToggleEnabledState();
    if (m->IsEnabled())
        m->Title() = "&Month";
    else
        m->Title() = "No month";
    return TRUE;
}


bool MenuDriver::DisableDays  (UI_Event&, UI_ViewID)
{
    short n = _menu->ChildCount (ID_DAYS);
    for (short i = 0; i < n; i++)
        _menu->Child(ID_DAYS, i)->ToggleEnabledState();
    char* msg = _daysEnabled ? " disabled" : " enabled";
    UI_StandardDialog (CL_String ("All days ") + msg, "YACL Menu Demo",
                       YACLApp()->MainWindow());
    _daysEnabled = _daysEnabled ? FALSE : TRUE;
    return TRUE;
}



bool MenuDriver::AddTimes (UI_Event&, UI_ViewID)
{
    _menu->Add (ID_TIMES, "&Times",     _menu->RootID(), 1);
    _menu->Add (ID_MORN,  "&Morning",   ID_TIMES);
    _menu->Add (ID_AFTER, "&Afternoon", ID_TIMES);
    _menu->Add (ID_EVE,   "&Evening",   ID_TIMES);
    _timesShown = TRUE;
    (*_menu)[ID_REMTM]->Enable();
    (*_menu)[ID_ADDTM]->Disable();
    return TRUE;
}

bool MenuDriver::RemoveTimes (UI_Event&, UI_ViewID)
{
    _menu->Remove (ID_TIMES);
    _timesShown = FALSE;
    (*_menu)[ID_ADDTM]->Enable();
    (*_menu)[ID_REMTM]->Disable();
    return TRUE;
}


bool MenuDriver::Quit (UI_Event&, UI_ViewID)
{
    YACLApp()->End();
    return TRUE;
}


