You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
450 lines
9.0 KiB
450 lines
9.0 KiB
/*************************************************************************** |
|
* Copyright (C) 2008 by Andrzej Rybczak * |
|
* electricityispower@gmail.com * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
* * |
|
* This program is distributed in the hope that it will be useful, * |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|
* GNU General Public License for more details. * |
|
* * |
|
* You should have received a copy of the GNU General Public License * |
|
* along with this program; if not, write to the * |
|
* Free Software Foundation, Inc., * |
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
|
***************************************************************************/ |
|
|
|
#include "menu.h" |
|
#include "misc.h" |
|
|
|
int Menu::count_length(string str) |
|
{ |
|
if (str.empty()) |
|
return 0; |
|
|
|
bool collect = false; |
|
int length = 0; |
|
|
|
#ifdef UTF8_ENABLED |
|
wstring str2 = ToWString(str); |
|
wstring tmp; |
|
#else |
|
string &str2 = str; |
|
string tmp; |
|
#endif |
|
|
|
for (int i = 0; i < str2.length(); i++, length++) |
|
{ |
|
if (str2[i] == '[') |
|
collect = 1; |
|
|
|
if (collect) |
|
tmp += str2[i]; |
|
|
|
if (str2[i] == ']') |
|
collect = 0; |
|
|
|
if (!collect && !tmp.empty()) |
|
{ |
|
if (is_valid_color(TO_STRING(tmp))) |
|
length -= tmp.length(); |
|
tmp.clear(); |
|
} |
|
} |
|
return length; |
|
} |
|
|
|
void Menu::AddOption(const string &str, LOCATION location, HAVE_SEPARATOR separator) |
|
{ |
|
itsLocations.push_back(location); |
|
itsOptions.push_back(str); |
|
itsSeparators.push_back(separator); |
|
itsStaticOptions.push_back(0); |
|
itsBold.push_back(0); |
|
} |
|
|
|
void Menu::AddBoldOption(const string &str, LOCATION location, HAVE_SEPARATOR separator) |
|
{ |
|
itsLocations.push_back(location); |
|
itsOptions.push_back(str); |
|
itsSeparators.push_back(separator); |
|
itsStaticOptions.push_back(0); |
|
itsBold.push_back(1); |
|
} |
|
|
|
void Menu::AddStaticOption(const string &str, LOCATION location, HAVE_SEPARATOR separator) |
|
{ |
|
itsLocations.push_back(location); |
|
itsOptions.push_back(str); |
|
itsSeparators.push_back(separator); |
|
itsStaticOptions.push_back(1); |
|
itsBold.push_back(0); |
|
itsStaticsNumber++; |
|
} |
|
|
|
void Menu::AddStaticBoldOption(const string &str, LOCATION location, HAVE_SEPARATOR separator) |
|
{ |
|
itsLocations.push_back(location); |
|
itsOptions.push_back(str); |
|
itsSeparators.push_back(separator); |
|
itsStaticOptions.push_back(1); |
|
itsBold.push_back(1); |
|
itsStaticsNumber++; |
|
} |
|
|
|
void Menu::AddSeparator() |
|
{ |
|
AddStaticOption("", lLeft, 1); |
|
} |
|
|
|
void Menu::UpdateOption(int index, string str, LOCATION location, HAVE_SEPARATOR separator) |
|
{ |
|
try |
|
{ |
|
itsLocations.at(index-1) = location; |
|
itsOptions.at(index-1) = str; |
|
itsSeparators.at(index-1) = separator; |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
} |
|
} |
|
|
|
void Menu::BoldOption(int index, IS_BOLD bold) |
|
{ |
|
try |
|
{ |
|
itsBold.at(index-1) = bold; |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
} |
|
} |
|
|
|
void Menu::MakeStatic(int index, IS_STATIC stat) |
|
{ |
|
try |
|
{ |
|
if (stat && !itsStaticOptions.at(index-1)) |
|
itsStaticsNumber++; |
|
if (!stat && itsStaticOptions.at(index-1)) |
|
itsStaticsNumber--; |
|
itsStaticOptions.at(index-1) = stat; |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
} |
|
} |
|
|
|
string Menu::GetCurrentOption() const |
|
{ |
|
try |
|
{ |
|
return itsOptions.at(itsHighlight); |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
return ""; |
|
} |
|
} |
|
|
|
string Menu::GetOption(int i) const |
|
{ |
|
try |
|
{ |
|
return itsOptions.at(i-1); |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
return ""; |
|
} |
|
} |
|
|
|
void Menu::DeleteOption(int no) |
|
{ |
|
try |
|
{ |
|
if (itsStaticOptions.at(no-1)) |
|
itsStaticsNumber--; |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
return; |
|
} |
|
itsLocations.erase(itsLocations.begin()+no-1); |
|
itsOptions.erase(itsOptions.begin()+no-1); |
|
itsStaticOptions.erase(itsStaticOptions.begin()+no-1); |
|
itsSeparators.erase(itsSeparators.begin()+no-1); |
|
itsBold.erase(itsBold.begin()+no-1); |
|
/*if (itsBeginning > 0 && itsBeginning == itsOptions.size()-itsHeight) |
|
itsBeginning--; |
|
Go(UP);*/ |
|
Window::Clear(); |
|
} |
|
|
|
void Menu::Display() |
|
{ |
|
Window::show_border(); |
|
Refresh(); |
|
} |
|
|
|
void Menu::Refresh() |
|
{ |
|
if (!itsOptions.empty() && is_static()) |
|
if (itsHighlight == 0) |
|
Go(DOWN); |
|
else |
|
Go(UP); |
|
|
|
if (MaxChoice() < GetChoice() && !Empty()) |
|
Highlight(MaxChoice()); |
|
|
|
if (itsHighlight > itsBeginning+itsHeight) |
|
Highlight(itsBeginning+itsHeight); |
|
|
|
int line = 0; |
|
int last; |
|
|
|
if (itsOptions.size() < itsHeight) |
|
last = itsOptions.size(); |
|
else |
|
last = itsBeginning+itsHeight; |
|
|
|
int check = 0; |
|
bool next = 1; |
|
for (int i = last-1; i > itsBeginning && next; i--) |
|
{ |
|
next = 0; |
|
try |
|
{ |
|
itsSeparators.at(i); |
|
} |
|
catch (std::out_of_range) |
|
{ |
|
check++; |
|
next = 1; |
|
} |
|
} |
|
itsBeginning -= check; |
|
last -= check; |
|
|
|
for (int i = itsBeginning; i < last; i++) |
|
{ |
|
if (i == itsHighlight && itsHighlightEnabled) |
|
{ |
|
Reverse(1); |
|
SetColor(itsHighlightColor); |
|
} |
|
if (itsBold[i]) |
|
Bold(1); |
|
|
|
int ch = itsSeparators[i] ? 0 : 32; |
|
mvwhline(itsWindow,line, 0, ch, itsWidth); |
|
|
|
int strlength = itsLocations[i] != lLeft && BBEnabled ? count_length(itsOptions[i]) : itsOptions[i].length(); |
|
|
|
if (strlength) |
|
{ |
|
int x = 0; |
|
|
|
if (itsLocations[i] == lCenter) |
|
{ |
|
for (; x < (itsWidth-strlength-(!ch ? 4 : 0))/2; x++); |
|
if (!ch) |
|
{ |
|
AltCharset(1); |
|
mvwaddstr(itsWindow, line, x, "u "); |
|
AltCharset(0); |
|
x += 2; |
|
} |
|
} |
|
if (itsLocations[i] == lRight) |
|
{ |
|
for (; x < (itsWidth-strlength); x++) |
|
if (!ch) |
|
{ |
|
AltCharset(1); |
|
mvwaddstr(itsWindow, line, x, "u "); |
|
AltCharset(0); |
|
x += 2; |
|
} |
|
} |
|
|
|
WriteXY(x, line, itsOptions[i], 0); |
|
|
|
if (!ch && (itsLocations[i] == lCenter || itsLocations[i] == lLeft)) |
|
{ |
|
x += strlength; |
|
AltCharset(1); |
|
mvwaddstr(itsWindow, line, x, " t"); |
|
AltCharset(0); |
|
} |
|
} |
|
line++; |
|
|
|
if (i == itsHighlight && itsHighlightEnabled) |
|
{ |
|
Reverse(0); |
|
SetColor(itsBaseColor); |
|
} |
|
if (itsBold[i]) |
|
Bold(0); |
|
} |
|
wrefresh(itsWindow); |
|
} |
|
|
|
void Menu::Go(WHERE where) |
|
{ |
|
if (Empty()) return; |
|
int MaxHighlight = itsOptions.size()-1; |
|
int MaxBeginning; |
|
if (itsOptions.size() < itsHeight) |
|
MaxBeginning = 0; |
|
else MaxBeginning = itsOptions.size()-itsHeight; |
|
int MaxCurrentHighlight = itsBeginning+itsHeight-1; |
|
switch (where) |
|
{ |
|
case UP: |
|
{ |
|
if (itsHighlight <= itsBeginning && itsHighlight > 0) itsBeginning--; // for scrolling |
|
if (itsHighlight == 0) |
|
break; |
|
else |
|
itsHighlight--; |
|
if (is_static()) |
|
{ |
|
if (itsHighlight == 0) |
|
Go(DOWN); |
|
else |
|
Go(UP); |
|
} |
|
break; |
|
} |
|
case DOWN: |
|
{ |
|
if (itsHighlight >= MaxCurrentHighlight && itsHighlight < MaxHighlight) itsBeginning++; // scroll |
|
if (itsHighlight == MaxHighlight) |
|
break; |
|
else |
|
itsHighlight++; |
|
if (is_static()) |
|
{ |
|
if (itsHighlight == MaxHighlight) |
|
Go(UP); |
|
else |
|
Go(DOWN); |
|
} |
|
break; |
|
} |
|
case PAGE_UP: |
|
{ |
|
itsHighlight -= itsHeight; |
|
itsBeginning -= itsHeight; |
|
if (itsBeginning < 0) |
|
{ |
|
itsBeginning = 0; |
|
if (itsHighlight < 0) itsHighlight = 0; |
|
} |
|
if (is_static()) |
|
{ |
|
if (itsHighlight == 0) |
|
Go(DOWN); |
|
else |
|
Go(UP); |
|
} |
|
break; |
|
} |
|
case PAGE_DOWN: |
|
{ |
|
itsHighlight += itsHeight; |
|
itsBeginning += itsHeight; |
|
if (itsBeginning > MaxBeginning) |
|
{ |
|
itsBeginning = MaxBeginning; |
|
if (itsHighlight > MaxHighlight) itsHighlight = MaxHighlight; |
|
} |
|
if (is_static()) |
|
{ |
|
if (itsHighlight == MaxHighlight) |
|
Go(UP); |
|
else |
|
Go(DOWN); |
|
} |
|
break; |
|
} |
|
case HOME: |
|
{ |
|
itsHighlight = 0; |
|
itsBeginning = 0; |
|
if (is_static()) |
|
{ |
|
if (itsHighlight == 0) |
|
Go(DOWN); |
|
else |
|
Go(UP); |
|
} |
|
break; |
|
} |
|
case END: |
|
{ |
|
itsHighlight = MaxHighlight; |
|
itsBeginning = MaxBeginning; |
|
if (is_static()) |
|
{ |
|
if (itsHighlight == MaxHighlight) |
|
Go(UP); |
|
else |
|
Go(DOWN); |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void Menu::Highlight(int which) |
|
{ |
|
if (which <= itsOptions.size()) |
|
itsHighlight = which-1; |
|
|
|
if (which > itsHeight) |
|
itsBeginning = itsHighlight-itsHeight/2; |
|
else |
|
itsBeginning = 0; |
|
} |
|
|
|
void Menu::Reset() |
|
{ |
|
itsHighlight = 0; |
|
itsBeginning = 0; |
|
} |
|
|
|
void Menu::Clear(bool clear_screen) |
|
{ |
|
itsOptions.clear(); |
|
itsStaticOptions.clear(); |
|
itsSeparators.clear(); |
|
itsLocations.clear(); |
|
itsBold.clear(); |
|
itsStaticsNumber = 0; |
|
if (clear_screen) |
|
Window::Clear(); |
|
} |
|
|
|
int Menu::GetRealChoice() const |
|
{ |
|
int real_choice = 0; |
|
vector<IS_STATIC>::const_iterator it = itsStaticOptions.begin(); |
|
for (int i = 0; i < itsHighlight; it++, i++) |
|
if (!*it) real_choice++; |
|
|
|
return real_choice+1; |
|
} |
|
|
|
Menu Menu::EmptyClone() |
|
{ |
|
return Menu(GetStartX(),GetStartY(),GetWidth(),GetHeight(),itsTitle,itsBaseColor,itsBorder); |
|
}
|
|
|