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:
164
src/menu.h
164
src/menu.h
@@ -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
|
||||
|
||||
@@ -379,7 +379,7 @@ void TagEditor::SwitchTo()
|
||||
TagTypes->AddSeparator();
|
||||
TagTypes->AddOption("Filename");
|
||||
TagTypes->AddSeparator();
|
||||
TagTypes->AddOption("Options", 1, 1, 0);
|
||||
TagTypes->AddOption("Options", 1, 1);
|
||||
TagTypes->AddSeparator();
|
||||
TagTypes->AddOption("Reset");
|
||||
TagTypes->AddOption("Save");
|
||||
@@ -1222,7 +1222,7 @@ void DealWithFilenames(SongList &v)
|
||||
if (!patterns_list.empty())
|
||||
{
|
||||
Main->AddSeparator();
|
||||
Main->AddOption("Recent patterns", 1, 1, 0);
|
||||
Main->AddOption("Recent patterns", 1, 1);
|
||||
Main->AddSeparator();
|
||||
for (vector<string>::const_iterator it = patterns_list.begin(); it != patterns_list.end(); it++)
|
||||
Main->AddOption(*it);
|
||||
|
||||
Reference in New Issue
Block a user