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