diff --git a/ColorUI.cpp b/ColorUI.cpp index 39bdc47..e23ba48 100644 --- a/ColorUI.cpp +++ b/ColorUI.cpp @@ -1,8 +1,9 @@ #include "ColorUI.h" +#include #include #include -namespace _ColorUI_Internal_Namespace +namespace _cns { class _auto_init_console_info_class @@ -92,6 +93,8 @@ inline int _ConsoleColor2winBackColor(ConsoleColor conColor) return BACKGROUND_RED | BACKGROUND_GREEN; case ConsoleColor::white: return BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; + default: + return 0; } } @@ -160,7 +163,7 @@ KEY GetUserInputKey() } } -int GetAction(int& cid,int MinVal,int MaxVal,int EscapeVal=MaxVal) +int GetAction(int& cid,int MinVal,int MaxVal,int EscapeVal) { KEY t=GetUserInputKey(); switch(t) @@ -197,9 +200,432 @@ int GetAction(int& cid,int MinVal,int MaxVal,int EscapeVal=MaxVal) } } -}/// End of namespace _ColorUI_Internal_Namespace +}/// End of namespace _cns ColorSelection::ColorSelection() +{ + frontColorNormal=ConsoleColor::white; + backColorNormal=ConsoleColor::black; + frontColorActivate=ConsoleColor::black; + backColorActivate=ConsoleColor::yellow; + _is_active=false; + _pframe=nullptr; +} + +//virtual +ColorSelection::~ColorSelection() { } + +//virtual +void ColorSelection::drawText() +{ + if(_is_active) + { + _cns::cprint(frontColorActivate,backColorActivate); + } + else + { + _cns::cprint(frontColorNormal,backColorNormal); + } + + printf("%s",text.c_str()); +} + +//virtual +void ColorSelection::drawInfo() +{ + printf("%s",info.c_str()); +} + +bool ColorSelection::hasInfo() +{ + return !info.empty(); +} + +//virtual +void ColorSelection::onActivate() +{ + _is_active=true; +} + +//virtual +void ColorSelection::onDeActivate() +{ + _is_active=false; +} + +ColorFrame* ColorSelection::getFrame() +{ + return _pframe; +} + +void ColorSelection::setFrame(ColorFrame* pFrame) +{ + _pframe=pFrame; +} + +//virtual +int ColorSelection::onClick() +{ + return 0; +} + +//virtual +int ColorSelection::onDelete() +{ + return 0; +} + +ColorPage::ColorPage() +{ + titleFrontColor=ConsoleColor::black; + titleBackColor=ConsoleColor::lightblue; + textFrontColor=ConsoleColor::white; + textBackColor=ConsoleColor::black; + _curActive=0; + _pframe=nullptr; +} + +//virtual +ColorPage::~ColorPage() +{ + +} + +void ColorPage::add(ColorSelection* p) +{ + _vec.push_back(p); +} + +int ColorPage::del(ColorSelection* p) +{ + auto iter=std::find(_vec.begin(),_vec.end(),p); + if(iter==_vec.end()) + { + /// Object to delete is Not Found + return 1; + } + + if(_curActive==iter-_vec.begin()+1) + { + /// Current Activated Selection is to be deleted. + _curActive=0; + _vec.erase(iter); + } + else + { + ColorSelection* _curActive_ptr=_vec.at(_curActive-1); + _vec.erase(iter); + _curActive=std::find(_vec.begin(),_vec.end(),_curActive_ptr)-_vec.begin()+1; + } + + return 0; +} + +int ColorPage::getSelectionSize() const +{ + return _vec.size(); +} + +int ColorPage::getCurrentActive() const +{ + return _curActive; +} + + +ColorFrame* ColorPage::getFrame() +{ + return _pframe; +} + +void ColorPage::setFrame(ColorFrame* pFrame) +{ + _pframe=pFrame; +} + +//virtual +void ColorPage::draw() +{ + if(!title.empty()) + { + _cns::cprint(titleFrontColor,titleBackColor); + printf("%s\n",title.c_str()); + } + if(!text.empty()) + { + _cns::cprint(textFrontColor,textBackColor); + printf("%s\n",text.c_str()); + } + if(!_curActive) // _curActive==0 + { + if(!_vec.empty()) + { + _curActive=1; + onSelectionOver(_curActive); + } + } + for(auto iter=_vec.begin();iter!=_vec.end();++iter) + { + if(!(*iter)->text.empty()) + { + (*iter)->drawText(); + } + else + { + _cns::cprint(); + printf("(Empty Selection)"); + } + printf("\n"); + } + _cns::cprint(); + printf("---------------\n"); + if(_vec.at(_curActive-1)->hasInfo()) + { + _vec.at(_curActive-1)->drawInfo(); + printf("\n"); + } + _cns::cprint(); +} + +//virtual +int ColorPage::onLoad() +{ + return 0; +} + +//virtual +void ColorPage::onBackground() +{ + +} + +//virtual +void ColorPage::onForeground() +{ + +} + +//virtual +int ColorPage::onUnload() +{ + for(auto& ptr:_vec) + { + if(!ptr->onDelete()) + { + delete ptr; + } + } + _vec.clear(); + _curActive=0; + return 0; +} + +//virtual +void ColorPage::onSelectionOver(int id) +{ + _vec.at(_curActive-1)->onDeActivate(); + _vec.at(id-1)->onActivate(); + _curActive=id; +} + +//virtual +int ColorPage::onActive(int id) +{ + return _vec.at(id-1)->onClick(); +} + +//protected +std::vector& ColorPage::_getvec() +{ + return _vec; +} + +ColorFrame::ColorFrame() +{ + _home_page=nullptr; + _cur_page=nullptr; + _next_page=nullptr; + _delete_home_page_on_dtor=true; + _has_started=false; +} + +void ColorFrame::setHomePage(ColorPage* pPage,bool deleteOnRemove) +{ + if(_has_started) return; + _home_page=pPage; + _delete_home_page_on_dtor=deleteOnRemove; +} + +ColorPage* ColorFrame::getHomePage() +{ + return _home_page; +} + +void ColorFrame::jumpTo(ColorPage* nextPage) +{ + _next_page=nextPage; +} + +void ColorFrame::clearScreen() +{ + _cns::cprint(); + system("cls"); +} + +void ColorFrame::clearInput() +{ + fflush(stdin); +} + +void ColorFrame::enterInputMode() +{ + clearInput(); +} + +void ColorFrame::exitInputMode() +{ + clearInput(); +} + +void ColorFrame::run() +{ + /// A Frame can only be started once. + if(_has_started) return; + + _has_started=true; + + /// No Home Page + if(_home_page==nullptr) return; + _cur_page=_home_page; + + _cur_page->onLoad(); + + bool stop=false; + int cid=0; + while(!stop) + { + clearScreen(); + _cur_page->draw(); + if(_cur_page->getSelectionSize()>0) + { + cid=_cur_page->getCurrentActive(); + if(_cns::GetAction(cid,1,_cur_page->getSelectionSize(),_cur_page->getSelectionSize())) + { + /// Confirmed Key Pressed. + switch(_cur_page->onActive(cid)) + { + case 0: + { + if(_next_page!=nullptr) + { + /// New Page! + /// Bring Current Page to Background + _cur_page->onBackground(); + _stk.push(_cur_page); + + /// Load New Page + _cur_page=_next_page; + _next_page=nullptr; + _cur_page->onLoad(); + } + else + { + /// No New Page. Go Straight. + } + } + break; + case 1: + { + /// Unload Current Page + if(_cur_page->onUnload()==0) + { + delete _cur_page; + } + _cur_page=nullptr; + + /// Bring Previous Page to Foreground. + if(_stk.empty()) + { + stop=true; + } + else + { + _cur_page=_stk.top(); + _stk.pop(); + _cur_page->onForeground(); + } + } + break; + case 2: + default: + stop=true; + break; + } + } + else + { + /// If not confirmed , just go ahead. + } + } + else + { + /// No Selection on this page + /// Unload Current Page + if(_cur_page->onUnload()==0) + { + delete _cur_page; + } + _cur_page=nullptr; + + /// Bring Previous Page to Foreground. + if(_stk.empty()) + { + stop=true; + } + else + { + _cur_page=_stk.top(); + _stk.pop(); + _cur_page->onForeground(); + } + } + } + + if(_cur_page) + { + if(_cur_page->onUnload()==0) + { + delete _cur_page; + } + _cur_page=nullptr; + } + while(!_stk.empty()) + { + _cur_page=_stk.top(); + _cur_page->onForeground(); + if(_cur_page->onUnload()==0) + { + delete _cur_page; + } + } + _cur_page=nullptr; +} + +ColorInputModeGuard::ColorInputModeGuard(ColorFrame* f) +{ + _pframe=f; + if(_pframe) + { + _pframe->enterInputMode(); + } +} + +ColorInputModeGuard::~ColorInputModeGuard() +{ + if(_pframe) + { + _pframe->exitInputMode(); + } +} diff --git a/ColorUI.h b/ColorUI.h index 8b6beef..96712f2 100644 --- a/ColorUI.h +++ b/ColorUI.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include enum class ConsoleColor { black=0,red=1,green=2,yellow=3,blue=4,purple=5,lightblue=6,deepgreen=6,white=7 }; @@ -21,8 +21,8 @@ public: virtual void drawInfo(); bool hasInfo(); - void onActivate(); - void onDeActivate(); + virtual void onActivate(); + virtual void onDeActivate(); ColorFrame* getFrame(); void setFrame(ColorFrame*); @@ -31,6 +31,9 @@ public: /// return 1 to return last page.(If no page to return, exit the program) /// return 0 to continue running.(If you want to change page, you should return 0) (default) virtual int onClick(); + + /// return 0 tells the frame to delete this selection. (default) + virtual int onDelete(); private: bool _is_active; ColorFrame* _pframe; @@ -46,11 +49,12 @@ public: virtual ~ColorPage(); /// Add and delete ColorSelections. - void add(ColorSelection* p); - int del(ColorSelection* p); + void add(ColorSelection*); + int del(ColorSelection*); /// Called by ColorFrame (mostly). Let Frame know how many selections have been added. - int getSelectionSize(); + int getSelectionSize() const; + int getCurrentActive() const; ColorFrame* getFrame(); void setFrame(ColorFrame*); @@ -69,16 +73,16 @@ public: /// Called when a selection is selected or unselected. virtual void onSelectionOver(int id); - virtual void onSelectionOut(int id); /// Returns ColorSelection::onClick() virtual int onActive(int id); protected: /// Get internal selection list, for derived class use. - std::list& _getlst(); + std::vector& _getvec(); private: - std::list _lst; + std::vector _vec; int _curActive; + ColorFrame* _pframe; }; class ColorFrame @@ -87,8 +91,9 @@ public: ColorFrame(); ~ColorFrame(); - void setHomePage(ColorPage*); ColorPage* getHomePage(); + /// Home Page Can ONLY be set before run. + void setHomePage(ColorPage*,bool deleteOnRemove=true); void run(); @@ -101,11 +106,16 @@ public: void enterInputMode(); void exitInputMode(); + /// [ONLY FOR EXPERIMENTAL USE] + void clearScreen(); + void clearInput(); private: ColorPage* _home_page; ColorPage* _cur_page; ColorPage* _next_page; + bool _delete_home_page_on_dtor; + bool _has_started; std::stack _stk; }; @@ -114,4 +124,6 @@ class ColorInputModeGuard public: ColorInputModeGuard(ColorFrame* f); ~ColorInputModeGuard(); +private: + ColorFrame* _pframe; };