diff options
-rw-r--r-- | gui/listbox.cpp | 131 | ||||
-rw-r--r-- | gui/objects.hpp | 6 |
2 files changed, 71 insertions, 66 deletions
diff --git a/gui/listbox.cpp b/gui/listbox.cpp index d82736e39..be2b48698 100644 --- a/gui/listbox.cpp +++ b/gui/listbox.cpp @@ -58,45 +58,41 @@ GUIListBox::GUIListBox(xml_node<>* node) : GUIScrollList(node) DataManager::GetValue(mVariable, currentValue); } else - allowSelection = false; // allows using listbox as a read-only list + allowSelection = false; // allows using listbox as a read-only list or menu // Get the data for the list child = FindNode(node, "listitem"); if (!child) return; while (child) { - ListData data; + ListItem item; attr = child->first_attribute("name"); if (!attr) continue; - data.displayName = gui_parse_text(attr->value()); - data.variableValue = gui_parse_text(child->value()); - if (child->value() == currentValue) { - data.selected = 1; - } else { - data.selected = 0; - } - data.action = NULL; + item.displayName = gui_parse_text(attr->value()); + item.variableValue = gui_parse_text(child->value()); + item.selected = (child->value() == currentValue); + item.action = NULL; xml_node<>* action = child->first_node("action"); if (action) { - data.action = new GUIAction(action); + item.action = new GUIAction(action); allowSelection = true; } xml_node<>* variable_name = child->first_node("data"); if (variable_name) { attr = variable_name->first_attribute("variable"); if (attr) { - data.variableName = attr->value(); - if (DataManager::GetIntValue(data.variableName) == 0) - data.selected = 0; - else - data.selected = 1; + item.variableName = attr->value(); + item.selected = (DataManager::GetIntValue(item.variableName) != 0); allowSelection = true; isCheckList = true; } } - mList.push_back(data); + LoadConditions(child, item.mConditions); + + mListItems.push_back(item); + mVisibleItems.push_back(mListItems.size()-1); child = child->next_sibling("listitem"); } @@ -128,37 +124,46 @@ int GUIListBox::NotifyVarChange(const std::string& varName, const std::string& v if(!isConditionTrue()) return 0; - if (isCheckList) { - int i, listSize = mList.size(); - - for (i = 0; i < listSize; i++) { - if (mList.at(i).variableName == varName) { - if (value == "0") { - mList.at(i).selected = 0; - } else { - mList.at(i).selected = 1; - } - } - } - mUpdate = 1; - return 0; - } // Check to see if the variable that we are using to store the list selected value has been updated if (varName == mVariable) { - int i, listSize = mList.size(); - currentValue = value; + mUpdate = 1; + } - for (i = 0; i < listSize; i++) { - if (mList.at(i).variableValue == currentValue) { - mList.at(i).selected = 1; - SetVisibleListLocation(i); - } else - mList.at(i).selected = 0; + std::vector<size_t> mVisibleItemsOld; + std::swap(mVisibleItemsOld, mVisibleItems); + for (size_t i = 0; i < mListItems.size(); i++) { + ListItem& item = mListItems[i]; + // update per-item visibility condition + bool itemVisible = UpdateConditions(item.mConditions, varName); + if (itemVisible) + mVisibleItems.push_back(i); + + if (isCheckList) + { + if (item.variableName == varName) { + item.selected = (value != "0"); + mUpdate = 1; + } + } + else if (varName == mVariable) { + if (item.variableValue == currentValue) { + item.selected = 1; + SetVisibleListLocation(mVisibleItems.empty() ? 0 : mVisibleItems.size()-1); + } else { + item.selected = 0; + } } - mUpdate = 1; - return 0; } + + if (mVisibleItemsOld != mVisibleItems) { + mUpdate = 1; // some item's visibility has changed + if (firstDisplayedItem >= mVisibleItems.size()) { + // all items in the view area were removed - make last item visible + SetVisibleListLocation(mVisibleItems.empty() ? 0 : mVisibleItems.size()-1); + } + } + return 0; } @@ -173,15 +178,16 @@ void GUIListBox::SetPageFocus(int inFocus) size_t GUIListBox::GetItemCount() { - return mList.size(); + return mVisibleItems.size(); } void GUIListBox::RenderItem(size_t itemindex, int yPos, bool selected) { // note: the "selected" parameter above is for the currently touched item // don't confuse it with the more persistent "selected" flag per list item used below - ImageResource* icon = mList.at(itemindex).selected ? mIconSelected : mIconUnselected; - const std::string& text = mList.at(itemindex).displayName; + ListItem& item = mListItems[mVisibleItems[itemindex]]; + ImageResource* icon = item.selected ? mIconSelected : mIconUnselected; + const std::string& text = item.displayName; RenderStdItem(yPos, selected, icon, text.c_str()); } @@ -189,27 +195,24 @@ void GUIListBox::RenderItem(size_t itemindex, int yPos, bool selected) void GUIListBox::NotifySelect(size_t item_selected) { if (!isCheckList) { - for (size_t i = 0; i < mList.size(); i++) { - mList.at(i).selected = 0; + // deselect all items, even invisible ones + for (size_t i = 0; i < mListItems.size(); i++) { + mListItems[i].selected = 0; } } - if (item_selected < mList.size()) { - ListData& data = mList.at(item_selected); - if (isCheckList) { - if (data.selected) { - data.selected = 0; - DataManager::SetValue(data.variableName, "0"); - } else { - data.selected = 1; - DataManager::SetValue(data.variableName, "1"); - } - } else { - data.selected = 1; - string str = data.variableValue; // [check] should this set currentValue instead? - DataManager::SetValue(mVariable, str); - } - if (data.action) - data.action->doActions(); + + ListItem& item = mListItems[mVisibleItems[item_selected]]; + + if (isCheckList) { + int selected = 1 - item.selected; + item.selected = selected; + DataManager::SetValue(item.variableName, selected ? "1" : "0"); + } else { + item.selected = 1; + string str = item.variableValue; // [check] should this set currentValue instead? + DataManager::SetValue(mVariable, str); } + if (item.action) + item.action->doActions(); mUpdate = 1; } diff --git a/gui/objects.hpp b/gui/objects.hpp index 99bf0dbfa..7028956ad 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -632,16 +632,18 @@ public: virtual void NotifySelect(size_t item_selected); protected: - struct ListData { + struct ListItem { std::string displayName; std::string variableName; std::string variableValue; unsigned int selected; GUIAction* action; + std::vector<Condition> mConditions; }; protected: - std::vector<ListData> mList; + std::vector<ListItem> mListItems; + std::vector<size_t> mVisibleItems; // contains indexes in mListItems of visible items only std::string mVariable; std::string currentValue; ImageResource* mIconSelected; |