menu: make m_highlight/m_beginning unsigned

This commit is contained in:
Andrzej Rybczak
2012-08-31 05:55:49 +02:00
parent c3d04b866f
commit 970727fab2

View File

@@ -537,11 +537,16 @@ template <typename T> struct Menu : public Window, public List
ReverseIterator Rend() { return ReverseIterator(Begin()); } ReverseIterator Rend() { return ReverseIterator(Begin()); }
ConstReverseIterator Rend() const { return ConstReverseIterator(Begin()); } ConstReverseIterator Rend() const { return ConstReverseIterator(Begin()); }
protected: private:
/// Clears filter, filtered data etc. /// Clears filter, filtered data etc.
/// ///
void ClearFiltered(); void ClearFiltered();
bool isHighlightable(size_t pos)
{
return !(*m_options_ptr)[pos]->isSeparator() && !(*m_options_ptr)[pos]->isInactive();
}
ItemDisplayer m_item_displayer; ItemDisplayer m_item_displayer;
ItemStringifier m_get_string_helper; ItemStringifier m_get_string_helper;
@@ -554,8 +559,8 @@ protected:
std::vector<size_t> m_filtered_positions; std::vector<size_t> m_filtered_positions;
std::set<size_t> m_found_positions; std::set<size_t> m_found_positions;
int itsBeginning; size_t m_beginning;
int itsHighlight; size_t m_highlight;
Color m_highlight_color; Color m_highlight_color;
bool m_highlight_enabled; bool m_highlight_enabled;
@@ -585,8 +590,8 @@ template <typename T> Menu<T>::Menu(size_t startx,
m_item_displayer(0), m_item_displayer(0),
m_get_string_helper(0), m_get_string_helper(0),
m_options_ptr(&m_options), m_options_ptr(&m_options),
itsBeginning(0), m_beginning(0),
itsHighlight(0), m_highlight(0),
m_highlight_color(itsBaseColor), m_highlight_color(itsBaseColor),
m_highlight_enabled(1), m_highlight_enabled(1),
m_cyclic_scroll_enabled(0), m_cyclic_scroll_enabled(0),
@@ -600,8 +605,8 @@ template <typename T> Menu<T>::Menu(const Menu &m) : Window(m),
m_item_displayer(m.m_item_displayer), m_item_displayer(m.m_item_displayer),
m_get_string_helper(m.m_get_string_helper), m_get_string_helper(m.m_get_string_helper),
m_options_ptr(m.m_options_ptr), m_options_ptr(m.m_options_ptr),
itsBeginning(m.itsBeginning), m_beginning(m.m_beginning),
itsHighlight(m.itsHighlight), m_highlight(m.m_highlight),
m_highlight_color(m.m_highlight_color), m_highlight_color(m.m_highlight_color),
m_highlight_enabled(m.m_highlight_enabled), m_highlight_enabled(m.m_highlight_enabled),
m_cyclic_scroll_enabled(m.m_cyclic_scroll_enabled), m_cyclic_scroll_enabled(m.m_cyclic_scroll_enabled),
@@ -706,9 +711,9 @@ template <typename T> void Menu<T>::Move(size_t from, size_t to)
template <typename T> bool Menu<T>::Goto(size_t y) template <typename T> bool Menu<T>::Goto(size_t y)
{ {
if (!m_options_ptr->at(itsBeginning+y) || m_options_ptr->at(itsBeginning+y)->isInactive()) if (!isHighlightable(m_beginning+y))
return false; return false;
itsHighlight = itsBeginning+y; m_highlight = m_beginning+y;
return true; return true;
} }
@@ -719,63 +724,59 @@ template <typename T> void Menu<T>::Refresh()
Window::Refresh(); Window::Refresh();
return; return;
} }
int MaxBeginning = m_options_ptr->size() < itsHeight ? 0 : m_options_ptr->size()-itsHeight;
if (itsBeginning < itsHighlight-int(itsHeight)+1) // highlighted position is off the screen size_t max_beginning = m_options_ptr->size() < itsHeight ? 0 : m_options_ptr->size()-itsHeight;
itsBeginning = itsHighlight-itsHeight+1; m_beginning = std::min(m_beginning, max_beginning);
if (itsBeginning < 0) // if highlighted position is off the screen, make it visible
itsBeginning = 0; m_highlight = std::min(m_highlight, m_beginning+itsHeight-1);
else if (itsBeginning > MaxBeginning) // if highlighted position is invalid, correct it
itsBeginning = MaxBeginning; m_highlight = std::min(m_highlight, m_options_ptr->size()-1);
if (!m_options_ptr->empty() && itsHighlight > int(m_options_ptr->size())-1) if (!isHighlightable(m_highlight))
itsHighlight = m_options_ptr->size()-1;
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive()) // it shouldn't be here
{ {
Scroll(wUp); Scroll(wUp);
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive()) if (isHighlightable(m_highlight))
Scroll(wDown); Scroll(wDown);
} }
size_t line = 0; size_t line = 0;
for (size_t &i = (m_drawn_position = itsBeginning); i < itsBeginning+itsHeight; ++i) m_drawn_position = m_beginning;
for (size_t &i = m_drawn_position; i < m_beginning+itsHeight; ++i, ++line)
{ {
GotoXY(0, line); GotoXY(0, line);
if (i >= m_options_ptr->size()) if (i >= m_options_ptr->size())
{ {
for (; line < itsHeight; ++line) for (; line < itsHeight; ++line)
mvwhline(itsWindow, line, 0, 32, itsWidth); mvwhline(itsWindow, line, 0, KEY_SPACE, itsWidth);
break; break;
} }
if ((*m_options_ptr)[i]->isSeparator()) if ((*m_options_ptr)[i]->isSeparator())
{ {
mvwhline(itsWindow, line++, 0, 0, itsWidth); mvwhline(itsWindow, line, 0, 0, itsWidth);
continue; continue;
} }
if ((*m_options_ptr)[i]->isBold()) if ((*m_options_ptr)[i]->isBold())
*this << fmtBold; *this << fmtBold;
if (m_highlight_enabled && int(i) == itsHighlight) if (m_highlight_enabled && i == m_highlight)
{ {
*this << fmtReverse; *this << fmtReverse;
*this << m_highlight_color; *this << m_highlight_color;
} }
mvwhline(itsWindow, line, 0, 32, itsWidth); mvwhline(itsWindow, line, 0, KEY_SPACE, itsWidth);
if ((*m_options_ptr)[i]->isSelected() && m_selected_prefix) if ((*m_options_ptr)[i]->isSelected() && m_selected_prefix)
*this << *m_selected_prefix; *this << *m_selected_prefix;
if (m_item_displayer) if (m_item_displayer)
m_item_displayer(*this, (*m_options_ptr)[i]->value()); m_item_displayer(*this, (*m_options_ptr)[i]->value());
if ((*m_options_ptr)[i]->isSelected() && m_selected_suffix) if ((*m_options_ptr)[i]->isSelected() && m_selected_suffix)
*this << *m_selected_suffix; *this << *m_selected_suffix;
if (m_highlight_enabled && int(i) == itsHighlight) if (m_highlight_enabled && i == m_highlight)
{ {
*this << clEnd; *this << clEnd;
*this << fmtReverseEnd; *this << fmtReverseEnd;
} }
if ((*m_options_ptr)[i]->isBold()) if ((*m_options_ptr)[i]->isBold())
*this << fmtBoldEnd; *this << fmtBoldEnd;
line++;
} }
Window::Refresh(); Window::Refresh();
} }
@@ -784,120 +785,96 @@ template <typename T> void Menu<T>::Scroll(Where where)
{ {
if (m_options_ptr->empty()) if (m_options_ptr->empty())
return; return;
int MaxHighlight = m_options_ptr->size()-1; size_t max_highlight = m_options_ptr->size()-1;
int MaxBeginning = m_options_ptr->size() < itsHeight ? 0 : m_options_ptr->size()-itsHeight; size_t max_beginning = m_options_ptr->size() < itsHeight ? 0 : m_options_ptr->size()-itsHeight;
int MaxCurrentHighlight = itsBeginning+itsHeight-1; size_t max_visible_highlight = m_beginning+itsHeight-1;
switch (where) switch (where)
{ {
case wUp: case wUp:
{ {
if (itsHighlight <= itsBeginning && itsHighlight > 0) if (m_highlight <= m_beginning && m_highlight > 0)
{ --m_beginning;
itsBeginning--; if (m_highlight == 0)
}
if (itsHighlight == 0)
{ {
if (m_cyclic_scroll_enabled) if (m_cyclic_scroll_enabled)
return Scroll(wEnd); return Scroll(wEnd);
break; break;
} }
else else
{ --m_highlight;
itsHighlight--; if (!isHighlightable(m_highlight))
} Scroll(m_highlight == 0 && !m_cyclic_scroll_enabled ? wDown : wUp);
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive())
{
Scroll(itsHighlight == 0 && !m_cyclic_scroll_enabled ? wDown : wUp);
}
break; break;
} }
case wDown: case wDown:
{ {
if (itsHighlight >= MaxCurrentHighlight && itsHighlight < MaxHighlight) if (m_highlight >= max_visible_highlight && m_highlight < max_highlight)
{ ++m_beginning;
itsBeginning++; if (m_highlight == max_highlight)
}
if (itsHighlight == MaxHighlight)
{ {
if (m_cyclic_scroll_enabled) if (m_cyclic_scroll_enabled)
return Scroll(wHome); return Scroll(wHome);
break; break;
} }
else else
{ ++m_highlight;
itsHighlight++; if (!isHighlightable(m_highlight))
} Scroll(m_highlight == max_highlight && !m_cyclic_scroll_enabled ? wUp : wDown);
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive())
{
Scroll(itsHighlight == MaxHighlight && !m_cyclic_scroll_enabled ? wUp : wDown);
}
break; break;
} }
case wPageUp: case wPageUp:
{ {
if (m_cyclic_scroll_enabled && itsHighlight == 0) if (m_cyclic_scroll_enabled && m_highlight == 0)
return Scroll(wEnd); return Scroll(wEnd);
itsHighlight -= itsHeight; if (m_highlight < itsHeight)
itsBeginning -= itsHeight; m_highlight = 0;
if (itsBeginning < 0) else
{ m_highlight -= itsHeight;
itsBeginning = 0; if (m_beginning < itsHeight)
if (itsHighlight < 0) m_beginning = 0;
itsHighlight = 0; else
} m_beginning -= itsHeight;
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive()) if (!isHighlightable(m_highlight))
{ Scroll(m_highlight == 0 && !m_cyclic_scroll_enabled ? wDown : wUp);
Scroll(itsHighlight == 0 && !m_cyclic_scroll_enabled ? wDown : wUp);
}
break; break;
} }
case wPageDown: case wPageDown:
{ {
if (m_cyclic_scroll_enabled && itsHighlight == MaxHighlight) if (m_cyclic_scroll_enabled && m_highlight == max_highlight)
return Scroll(wHome); return Scroll(wHome);
itsHighlight += itsHeight; m_highlight += itsHeight;
itsBeginning += itsHeight; m_beginning += itsHeight;
if (itsBeginning > MaxBeginning) m_beginning = std::min(m_beginning, max_beginning);
{ m_highlight = std::min(m_highlight, max_highlight);
itsBeginning = MaxBeginning; if (!isHighlightable(m_highlight))
if (itsHighlight > MaxHighlight) Scroll(m_highlight == max_highlight && !m_cyclic_scroll_enabled ? wUp : wDown);
itsHighlight = MaxHighlight;
}
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive())
{
Scroll(itsHighlight == MaxHighlight && !m_cyclic_scroll_enabled ? wUp : wDown);
}
break; break;
} }
case wHome: case wHome:
{ {
itsHighlight = 0; m_highlight = 0;
itsBeginning = 0; m_beginning = 0;
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive()) if (!isHighlightable(m_highlight))
{ Scroll(wDown);
Scroll(itsHighlight == 0 ? wDown : wUp);
}
break; break;
} }
case wEnd: case wEnd:
{ {
itsHighlight = MaxHighlight; m_highlight = max_highlight;
itsBeginning = MaxBeginning; m_beginning = max_beginning;
if ((*m_options_ptr)[itsHighlight]->isSeparator() || (*m_options_ptr)[itsHighlight]->isInactive()) if (!isHighlightable(m_highlight))
{ Scroll(wUp);
Scroll(itsHighlight == MaxHighlight ? wUp : wDown);
}
break; break;
} }
} }
if (m_autocenter_cursor) if (m_autocenter_cursor)
Highlight(itsHighlight); Highlight(m_highlight);
} }
template <typename T> void Menu<T>::Reset() template <typename T> void Menu<T>::Reset()
{ {
itsHighlight = 0; m_highlight = 0;
itsBeginning = 0; m_beginning = 0;
} }
template <typename T> void Menu<T>::ClearFiltered() template <typename T> void Menu<T>::ClearFiltered()
@@ -936,8 +913,12 @@ template <typename T> void Menu<T>::GetSelected(std::vector<size_t> &v) const
template <typename T> void Menu<T>::Highlight(size_t pos) template <typename T> void Menu<T>::Highlight(size_t pos)
{ {
itsHighlight = pos; m_highlight = pos;
itsBeginning = pos-itsHeight/2; size_t half_height = itsHeight/2;
if (pos < half_height)
m_beginning = 0;
else
m_beginning = pos-half_height;
} }
template <typename T> size_t Menu<T>::Size() const template <typename T> size_t Menu<T>::Size() const
@@ -947,13 +928,13 @@ template <typename T> size_t Menu<T>::Size() const
template <typename T> size_t Menu<T>::Choice() const template <typename T> size_t Menu<T>::Choice() const
{ {
return itsHighlight; return m_highlight;
} }
template <typename T> size_t Menu<T>::RealChoice() const template <typename T> size_t Menu<T>::RealChoice() const
{ {
size_t result = 0; size_t result = 0;
for (auto it = m_options_ptr->begin(); it != m_options_ptr->begin()+itsHighlight; ++it) for (auto it = m_options_ptr->begin(); it != m_options_ptr->begin()+m_highlight; ++it)
if (!(*it)->isInactive()) if (!(*it)->isInactive())
result++; result++;
return result; return result;
@@ -990,7 +971,7 @@ template <typename T> void Menu<T>::NextFound(bool wrap)
{ {
if (m_found_positions.empty()) if (m_found_positions.empty())
return; return;
std::set<size_t>::iterator next = m_found_positions.upper_bound(itsHighlight); std::set<size_t>::iterator next = m_found_positions.upper_bound(m_highlight);
if (next != m_found_positions.end()) if (next != m_found_positions.end())
Highlight(*next); Highlight(*next);
else if (wrap) else if (wrap)
@@ -1001,7 +982,7 @@ template <typename T> void Menu<T>::PrevFound(bool wrap)
{ {
if (m_found_positions.empty()) if (m_found_positions.empty())
return; return;
std::set<size_t>::iterator prev = m_found_positions.lower_bound(itsHighlight); std::set<size_t>::iterator prev = m_found_positions.lower_bound(m_highlight);
if (prev != m_found_positions.begin()) if (prev != m_found_positions.begin())
Highlight(*--prev); Highlight(*--prev);
else if (wrap) else if (wrap)
@@ -1045,10 +1026,10 @@ template <typename T> const std::string &Menu<T>::GetFilter()
template <typename T> std::string Menu<T>::GetItem(size_t pos) template <typename T> std::string Menu<T>::GetItem(size_t pos)
{ {
if (m_options_ptr->at(pos) && m_get_string_helper) std::string result;
return m_get_string_helper((*m_options_ptr)[pos]->value()); if (m_get_string_helper)
else result = m_get_string_helper((*m_options_ptr)[pos]->value());
return ""; return result;
} }
template <typename T> typename Menu<T>::Item &Menu<T>::Back() template <typename T> typename Menu<T>::Item &Menu<T>::Back()
@@ -1063,12 +1044,12 @@ template <typename T> const typename Menu<T>::Item &Menu<T>::Back() const
template <typename T> typename Menu<T>::Item &Menu<T>::Current() template <typename T> typename Menu<T>::Item &Menu<T>::Current()
{ {
return *(*m_options_ptr)[itsHighlight]; return *(*m_options_ptr)[m_highlight];
} }
template <typename T> const typename Menu<T>::Item &Menu<T>::Current() const template <typename T> const typename Menu<T>::Item &Menu<T>::Current() const
{ {
return *(*m_options_ptr)[itsHighlight]; return *(*m_options_ptr)[m_highlight];
} }
template <typename T> typename Menu<T>::Item &Menu<T>::at(size_t pos) template <typename T> typename Menu<T>::Item &Menu<T>::at(size_t pos)
@@ -1083,11 +1064,13 @@ template <typename T> const typename Menu<T>::Item &Menu<T>::at(size_t pos) cons
template <typename T> const typename Menu<T>::Item &Menu<T>::operator[](size_t pos) const template <typename T> const typename Menu<T>::Item &Menu<T>::operator[](size_t pos) const
{ {
assert(m_options_ptr->size() > pos);
return *(*m_options_ptr)[pos]; return *(*m_options_ptr)[pos];
} }
template <typename T> typename Menu<T>::Item &Menu<T>::operator[](size_t pos) template <typename T> typename Menu<T>::Item &Menu<T>::operator[](size_t pos)
{ {
assert(m_options_ptr->size() > pos);
return *(*m_options_ptr)[pos]; return *(*m_options_ptr)[pos];
} }