use vector of pointers to options rather than vector of options

this way I can implement options filtering with much less effort.
This commit is contained in:
Andrzej Rybczak
2009-02-17 10:03:21 +01:00
parent 32bac776e7
commit 2cb9b46135
2 changed files with 78 additions and 90 deletions

View File

@@ -56,16 +56,18 @@ template <class T> class Menu : public Window, public List
struct Option struct Option
{ {
Option() : Item(0), isBold(0), isSelected(0), isStatic(0), haveSeparator(0) { } Option() : isBold(0), isSelected(0), isStatic(0) { }
T *Item; Option(const T &t, bool is_bold, bool is_static) :
Item(t), isBold(is_bold), isSelected(0), isStatic(is_static) { }
T Item;
bool isBold; bool isBold;
bool isSelected; bool isSelected;
bool isStatic; bool isStatic;
bool haveSeparator;
}; };
typedef typename std::vector<Option>::iterator option_iterator; typedef typename std::vector<Option *>::iterator option_iterator;
typedef typename std::vector<Option>::const_iterator option_const_iterator; typedef typename std::vector<Option *>::const_iterator option_const_iterator;
public: public:
Menu(size_t, size_t, size_t, size_t, const std::string &, Color, Border); Menu(size_t, size_t, size_t, size_t, const std::string &, Color, Border);
@@ -77,9 +79,9 @@ template <class T> class Menu : public Window, public List
void Reserve(size_t size); void Reserve(size_t size);
void ResizeBuffer(size_t size); void ResizeBuffer(size_t size);
void AddOption(const T &item = T(), bool is_bold = 0, bool is_static = 0, bool have_separator = 0); void AddOption(const T &item, bool is_bold = 0, bool is_static = 0);
void AddSeparator(); void AddSeparator();
void InsertOption(size_t pos, const T &Item = T(), bool is_bold = 0, bool is_static = 0, bool have_separator = 0); void InsertOption(size_t pos, const T &Item, bool is_bold = 0, bool is_static = 0);
void InsertSeparator(size_t pos); void InsertSeparator(size_t pos);
void DeleteOption(size_t pos); void DeleteOption(size_t pos);
void IntoSeparator(size_t pos); void IntoSeparator(size_t pos);
@@ -128,7 +130,7 @@ template <class T> class Menu : public Window, public List
ItemDisplayer itsItemDisplayer; ItemDisplayer itsItemDisplayer;
void *itsItemDisplayerUserdata; void *itsItemDisplayerUserdata;
std::vector<Option> itsOptions; std::vector<Option *> itsOptions;
int itsBeginning; int itsBeginning;
int itsHighlight; int itsHighlight;
@@ -173,7 +175,7 @@ template <class T> Menu<T>::Menu(const Menu &m) : Window(m)
template <class T> Menu<T>::~Menu() template <class T> Menu<T>::~Menu()
{ {
for (option_iterator it = itsOptions.begin(); it != itsOptions.end(); it++) for (option_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
delete it->Item; delete *it;
} }
template <class T> void Menu<T>::Reserve(size_t size) template <class T> void Menu<T>::Reserve(size_t size)
@@ -185,51 +187,35 @@ template <class T> void Menu<T>::ResizeBuffer(size_t size)
{ {
itsOptions.resize(size); itsOptions.resize(size);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
if (!itsOptions[i].Item) if (!itsOptions[i])
itsOptions[i].Item = new T(); itsOptions[i] = new Option();
} }
template <class T> void Menu<T>::AddOption(const T &item, bool is_bold, bool is_static, bool have_separator) template <class T> void Menu<T>::AddOption(const T &item, bool is_bold, bool is_static)
{ {
Option o; itsOptions.push_back(new Option(item, is_bold, is_static));
o.Item = new T(item);
o.isBold = is_bold;
o.isStatic = is_static;
o.haveSeparator = have_separator;
itsOptions.push_back(o);
} }
template <class T> void Menu<T>::AddSeparator() template <class T> void Menu<T>::AddSeparator()
{ {
Option o; itsOptions.push_back(0);
o.isStatic = true;
o.haveSeparator = true;
itsOptions.push_back(o);
} }
template <class T> void Menu<T>::InsertOption(size_t pos, const T &item, bool is_bold, bool is_static, bool have_separator) template <class T> void Menu<T>::InsertOption(size_t pos, const T &item, bool is_bold, bool is_static)
{ {
Option o; itsOptions.insert(itsOptions.begin()+pos, new Option(item, is_bold, is_static));
o.Item = new T(item);
o.isBold = is_bold;
o.isStatic = is_static;
o.haveSeparator = have_separator;
itsOptions.insert(itsOptions.begin()+pos, o);
} }
template <class T> void Menu<T>::InsertSeparator(size_t pos) template <class T> void Menu<T>::InsertSeparator(size_t pos)
{ {
Option o; itsOptions.insert(itsOptions.begin()+pos, 0);
o.isStatic = true;
o.haveSeparator = true;
itsOptions.insert(itsOptions.begin()+pos, o);
} }
template <class T> void Menu<T>::DeleteOption(size_t pos) template <class T> void Menu<T>::DeleteOption(size_t pos)
{ {
if (itsOptions.empty()) if (itsOptions.empty())
return; return;
delete itsOptions.at(pos).Item; delete itsOptions.at(pos);
itsOptions.erase(itsOptions.begin()+pos); itsOptions.erase(itsOptions.begin()+pos);
if (itsOptions.empty()) if (itsOptions.empty())
Window::Clear(); Window::Clear();
@@ -237,18 +223,15 @@ template <class T> void Menu<T>::DeleteOption(size_t pos)
template <class T> void Menu<T>::IntoSeparator(size_t pos) template <class T> void Menu<T>::IntoSeparator(size_t pos)
{ {
if (itsOptions.at(pos).Item) delete itsOptions.at(pos);
delete itsOptions[pos].Item; itsOptions[pos] = 0;
itsOptions[pos].Item = 0;
itsOptions[pos].isBold = false;
itsOptions[pos].isSelected = false;
itsOptions[pos].isStatic = true;
itsOptions[pos].haveSeparator = true;
} }
template <class T> void Menu<T>::BoldOption(int index, bool bold) template <class T> void Menu<T>::BoldOption(int index, bool bold)
{ {
itsOptions.at(index).isBold = bold; if (!itsOptions.at(index))
return;
itsOptions[index]->isBold = bold;
} }
template <class T> template <class T>
@@ -283,26 +266,31 @@ template <class T> void Menu<T>::Refresh()
mvwhline(itsWindow, line, 0, 32, itsWidth); mvwhline(itsWindow, line, 0, 32, itsWidth);
break; break;
} }
if (itsOptions[i].isBold) if (!itsOptions[i]) // separator
{
mvwhline(itsWindow, line++, 0, 0, itsWidth);
continue;
}
if (itsOptions[i]->isBold)
Bold(1); Bold(1);
if (highlightEnabled && int(i) == itsHighlight) if (highlightEnabled && int(i) == itsHighlight)
{ {
Reverse(1); Reverse(1);
*this << itsHighlightColor; *this << itsHighlightColor;
} }
mvwhline(itsWindow, line, 0, !itsOptions[i].haveSeparator*32, itsWidth); mvwhline(itsWindow, line, 0, 32, itsWidth);
if (itsOptions[i].isSelected && itsSelectedPrefix) if (itsOptions[i]->isSelected && itsSelectedPrefix)
*this << *itsSelectedPrefix; *this << *itsSelectedPrefix;
if (itsItemDisplayer && itsOptions[i].Item) if (itsItemDisplayer)
itsItemDisplayer(*itsOptions[i].Item, itsItemDisplayerUserdata, this); itsItemDisplayer(itsOptions[i]->Item, itsItemDisplayerUserdata, this);
if (itsOptions[i].isSelected && itsSelectedSuffix) if (itsOptions[i]->isSelected && itsSelectedSuffix)
*this << *itsSelectedSuffix; *this << *itsSelectedSuffix;
if (highlightEnabled && int(i) == itsHighlight) if (highlightEnabled && int(i) == itsHighlight)
{ {
*this << clEnd; *this << clEnd;
Reverse(0); Reverse(0);
} }
if (itsOptions[i].isBold) if (itsOptions[i]->isBold)
Bold(0); Bold(0);
line++; line++;
} }
@@ -333,7 +321,7 @@ template <class T> void Menu<T>::Scroll(Where where)
{ {
itsHighlight--; itsHighlight--;
} }
if (itsOptions[itsHighlight].isStatic) if (!itsOptions[itsHighlight] || itsOptions[itsHighlight]->isStatic)
{ {
Scroll(itsHighlight == 0 ? wDown : wUp); Scroll(itsHighlight == 0 ? wDown : wUp);
} }
@@ -354,7 +342,7 @@ template <class T> void Menu<T>::Scroll(Where where)
{ {
itsHighlight++; itsHighlight++;
} }
if (itsOptions[itsHighlight].isStatic) if (!itsOptions[itsHighlight] || itsOptions[itsHighlight]->isStatic)
{ {
Scroll(itsHighlight == MaxHighlight ? wUp : wDown); Scroll(itsHighlight == MaxHighlight ? wUp : wDown);
} }
@@ -370,7 +358,7 @@ template <class T> void Menu<T>::Scroll(Where where)
if (itsHighlight < 0) if (itsHighlight < 0)
itsHighlight = 0; itsHighlight = 0;
} }
if (itsOptions[itsHighlight].isStatic) if (!itsOptions[itsHighlight] || itsOptions[itsHighlight]->isStatic)
{ {
Scroll(itsHighlight == 0 ? wDown: wUp); Scroll(itsHighlight == 0 ? wDown: wUp);
} }
@@ -386,7 +374,7 @@ template <class T> void Menu<T>::Scroll(Where where)
if (itsHighlight > MaxHighlight) if (itsHighlight > MaxHighlight)
itsHighlight = MaxHighlight; itsHighlight = MaxHighlight;
} }
if (itsOptions[itsHighlight].isStatic) if (!itsOptions[itsHighlight] || itsOptions[itsHighlight]->isStatic)
{ {
Scroll(itsHighlight == MaxHighlight ? wUp : wDown); Scroll(itsHighlight == MaxHighlight ? wUp : wDown);
} }
@@ -396,7 +384,7 @@ template <class T> void Menu<T>::Scroll(Where where)
{ {
itsHighlight = 0; itsHighlight = 0;
itsBeginning = 0; itsBeginning = 0;
if (itsOptions[itsHighlight].isStatic) if (!itsOptions[itsHighlight] || itsOptions[itsHighlight]->isStatic)
{ {
Scroll(itsHighlight == 0 ? wDown : wUp); Scroll(itsHighlight == 0 ? wDown : wUp);
} }
@@ -406,7 +394,7 @@ template <class T> void Menu<T>::Scroll(Where where)
{ {
itsHighlight = MaxHighlight; itsHighlight = MaxHighlight;
itsBeginning = MaxBeginning; itsBeginning = MaxBeginning;
if (itsOptions[itsHighlight].isStatic) if (!itsOptions[itsHighlight] || itsOptions[itsHighlight]->isStatic)
{ {
Scroll(itsHighlight == MaxHighlight ? wUp : wDown); Scroll(itsHighlight == MaxHighlight ? wUp : wDown);
} }
@@ -424,7 +412,7 @@ template <class T> void Menu<T>::Reset()
template <class T> void Menu<T>::Clear(bool clrscr) template <class T> void Menu<T>::Clear(bool clrscr)
{ {
for (option_iterator it = itsOptions.begin(); it != itsOptions.end(); it++) for (option_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
delete it->Item; delete *it;
itsOptions.clear(); itsOptions.clear();
if (clrscr) if (clrscr)
Window::Clear(); Window::Clear();
@@ -432,33 +420,41 @@ template <class T> void Menu<T>::Clear(bool clrscr)
template <class T> bool Menu<T>::isBold(int id) template <class T> bool Menu<T>::isBold(int id)
{ {
return itsOptions.at(id == -1 ? itsHighlight : id).isBold; return itsOptions.at(id == -1 ? itsHighlight : id)->isBold;
} }
template <class T> void Menu<T>::Select(int id, bool value) template <class T> void Menu<T>::Select(int id, bool value)
{ {
itsOptions.at(id).isSelected = value; if (!itsOptions.at(id))
return;
itsOptions[id]->isSelected = value;
} }
template <class T> void Menu<T>::Static(int id, bool value) template <class T> void Menu<T>::Static(int id, bool value)
{ {
itsOptions.at(id).isStatic = value; if (!itsOptions.at(id))
return;
itsOptions[id]->isStatic = value;
} }
template <class T> bool Menu<T>::isSelected(int id) const template <class T> bool Menu<T>::isSelected(int id) const
{ {
return itsOptions.at(id == -1 ? itsHighlight : id).isSelected; if (!itsOptions.at(id == -1 ? itsHighlight : id))
return 0;
return itsOptions[id == -1 ? itsHighlight : id]->isSelected;
} }
template <class T> bool Menu<T>::isStatic(int id) const template <class T> bool Menu<T>::isStatic(int id) const
{ {
return itsOptions.at(id == -1 ? itsHighlight : id).isStatic; if (!itsOptions.at(id == -1 ? itsHighlight : id))
return 1;
return itsOptions[id == -1 ? itsHighlight : id]->isStatic;
} }
template <class T> bool Menu<T>::hasSelected() const template <class T> bool Menu<T>::hasSelected() const
{ {
for (option_const_iterator it = itsOptions.begin(); it != itsOptions.end(); it++) for (option_const_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
if (it->isSelected) if (*it && (*it)->isSelected)
return true; return true;
return false; return false;
} }
@@ -466,7 +462,7 @@ template <class T> bool Menu<T>::hasSelected() const
template <class T> void Menu<T>::GetSelected(std::vector<size_t> &v) const template <class T> void Menu<T>::GetSelected(std::vector<size_t> &v) const
{ {
for (size_t i = 0; i < itsOptions.size(); i++) for (size_t i = 0; i < itsOptions.size(); i++)
if (itsOptions[i].isSelected) if (itsOptions[i]->isSelected)
v.push_back(i); v.push_back(i);
} }
@@ -490,73 +486,65 @@ template <class T> size_t Menu<T>::RealChoice() const
{ {
size_t result = 0; size_t result = 0;
for (option_const_iterator it = itsOptions.begin(); it != itsOptions.begin()+itsHighlight; it++) for (option_const_iterator it = itsOptions.begin(); it != itsOptions.begin()+itsHighlight; it++)
if (!it->isStatic) if (*it && !(*it)->isStatic)
result++; result++;
return result; return result;
} }
template <class T> T &Menu<T>::Back() template <class T> T &Menu<T>::Back()
{ {
if (itsOptions.back().Item) if (!itsOptions.back())
return *itsOptions.back().Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions.back()->Item;
} }
template <class T> const T &Menu<T>::Back() const template <class T> const T &Menu<T>::Back() const
{ {
if (itsOptions.back().Item) if (!itsOptions.back())
return *itsOptions.back().Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions.back()->Item;
} }
template <class T> T &Menu<T>::Current() template <class T> T &Menu<T>::Current()
{ {
if (itsOptions.at(itsHighlight).Item) if (!itsOptions.at(itsHighlight))
return *itsOptions.at(itsHighlight).Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions[itsHighlight]->Item;
} }
template <class T> const T &Menu<T>::Current() const template <class T> const T &Menu<T>::Current() const
{ {
if (itsOptions.at(itsHighlight).Item) if (!itsOptions.at(itsHighlight))
return *itsOptions.at(itsHighlight).Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions[itsHighlight]->Item;
} }
template <class T> T &Menu<T>::at(size_t i) template <class T> T &Menu<T>::at(size_t i)
{ {
if (itsOptions.at(i).Item) if (!itsOptions.at(i))
return *itsOptions.at(i).Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions[i]->Item;
} }
template <class T> const T &Menu<T>::at(size_t i) const template <class T> const T &Menu<T>::at(size_t i) const
{ {
if (itsOptions.at(i).Item) if (!itsOptions.at(i))
return *itsOptions.at(i).Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions.at(i)->Item;
} }
template <class T> const T &Menu<T>::operator[](size_t i) const template <class T> const T &Menu<T>::operator[](size_t i) const
{ {
if (itsOptions[i].Item) if (!itsOptions[i])
return *itsOptions[i].Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions[i]->Item;
} }
template <class T> T &Menu<T>::operator[](size_t i) template <class T> T &Menu<T>::operator[](size_t i)
{ {
if (itsOptions[i].Item) if (!itsOptions[i])
return *itsOptions[i].Item;
else
throw InvalidItem(); throw InvalidItem();
return itsOptions[i]->Item;
} }
template <class T> Menu<T> *Menu<T>::EmptyClone() const template <class T> Menu<T> *Menu<T>::EmptyClone() const

View File

@@ -379,7 +379,7 @@ void TagEditor::SwitchTo()
TagTypes->AddSeparator(); TagTypes->AddSeparator();
TagTypes->AddOption("Filename"); TagTypes->AddOption("Filename");
TagTypes->AddSeparator(); TagTypes->AddSeparator();
TagTypes->AddOption("Options", 1, 1, 0); TagTypes->AddOption("Options", 1, 1);
TagTypes->AddSeparator(); TagTypes->AddSeparator();
TagTypes->AddOption("Reset"); TagTypes->AddOption("Reset");
TagTypes->AddOption("Save"); TagTypes->AddOption("Save");
@@ -1222,7 +1222,7 @@ void DealWithFilenames(SongList &v)
if (!patterns_list.empty()) if (!patterns_list.empty())
{ {
Main->AddSeparator(); Main->AddSeparator();
Main->AddOption("Recent patterns", 1, 1, 0); Main->AddOption("Recent patterns", 1, 1);
Main->AddSeparator(); Main->AddSeparator();
for (vector<string>::const_iterator it = patterns_list.begin(); it != patterns_list.end(); it++) for (vector<string>::const_iterator it = patterns_list.begin(); it != patterns_list.end(); it++)
Main->AddOption(*it); Main->AddOption(*it);