diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index 61833a8d0..72b3d02f2 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -237,7 +237,7 @@ void GuiGameListMenuCtrl::onRenderListOption(Row* row, Point2I currentOffset) // calculate text to be at the center between the arrows GFont* font = profile->mFont; - StringTableEntry text = row->mOptions[row->mSelectedOption]; + StringTableEntry text = row->mOptions[row->mSelectedOption].mDisplayText; S32 textWidth = font->getStrWidth(text); S32 columnWidth = profile->mHitAreaLowerRight.x * xScale - profile->mRightPad - columnSplit; S32 columnCenter = columnSplit + (columnWidth >> 1); @@ -489,15 +489,18 @@ void GuiGameListMenuCtrl::addRow(const char* label, const char* optionsList, boo { static StringTableEntry DELIM = StringTable->insert("\t", true); Row* row = new Row(); - Vector options(__FILE__, __LINE__); + Vector options(__FILE__, __LINE__); S32 defaultOption = 0; S32 count = StringUnit::getUnitCount(optionsList, DELIM); for (S32 i = 0; i < count; ++i) { + OptionEntry e; const char* option = StringUnit::getUnit(optionsList, i, DELIM); - options.push_back(StringTable->insert(option, true)); + e.mDisplayText = StringTable->insert(option, true); + e.mKeyString = e.mDisplayText; + options.push_back(e); if (String::compare(option, defaultValue) == 0) defaultOption = options.size() - 1; @@ -1075,12 +1078,38 @@ StringTableEntry GuiGameListMenuCtrl::getCurrentOption(S32 rowIndex) const Row* row = (Row*)mRows[rowIndex]; if (row->mSelectedOption != NO_OPTION) { - return row->mOptions[row->mSelectedOption]; + return row->mOptions[row->mSelectedOption].mDisplayText; } } return StringTable->insert("", false); } +StringTableEntry GuiGameListMenuCtrl::getCurrentOptionKey(S32 rowIndex) const +{ + if (isValidRowIndex(rowIndex)) + { + Row* row = (Row*)mRows[rowIndex]; + if (row->mSelectedOption != NO_OPTION) + { + return row->mOptions[row->mSelectedOption].mKeyString; + } + } + return StringTable->insert("", false); +} + +S32 GuiGameListMenuCtrl::getCurrentOptionIndex(S32 rowIndex) const +{ + if (isValidRowIndex(rowIndex)) + { + Row* row = (Row*)mRows[rowIndex]; + if (row->mSelectedOption != NO_OPTION) + { + return row->mSelectedOption; + } + } + return S32(-1); +} + bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption) { if (!isValidRowIndex(rowIndex)) @@ -1090,9 +1119,9 @@ bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption) Row* row = (Row*)mRows[rowIndex]; - for (Vector::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption) + for (Vector::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption) { - if (String::compare(*anOption, theOption) == 0) + if (String::compare((*anOption).mDisplayText, theOption) == 0) { S32 newIndex = anOption - row->mOptions.begin(); row->mSelectedOption = newIndex; @@ -1103,6 +1132,45 @@ bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption) return false; } +bool GuiGameListMenuCtrl::selectOptionByKey(S32 rowIndex, const char* optionKey) +{ + if (!isValidRowIndex(rowIndex)) + { + return false; + } + + Row* row = (Row*)mRows[rowIndex]; + + for (Vector::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption) + { + if (String::compare((*anOption).mKeyString, optionKey) == 0) + { + S32 newIndex = anOption - row->mOptions.begin(); + row->mSelectedOption = newIndex; + return true; + } + } + + return false; +} + +bool GuiGameListMenuCtrl::selectOptionByIndex(S32 rowIndex, S32 optionIndex) +{ + if (!isValidRowIndex(rowIndex) || (optionIndex < 0)) + { + return false; + } + + Row* row = (Row*)mRows[rowIndex]; + if (optionIndex < row->mOptions.size()) + { + row->mSelectedOption = optionIndex; + return true; + } + + return false; +} + void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList) { static StringTableEntry DELIM = StringTable->insert("\t", true); @@ -1119,7 +1187,10 @@ void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList) for (S32 i = 0; i < count; ++i) { const char* option = StringUnit::getUnit(optionsList, i, DELIM); - row->mOptions[i] = StringTable->insert(option, true); + OptionEntry e; + e.mDisplayText = StringTable->insert(option, true); + e.mKeyString = e.mDisplayText; + row->mOptions[i] = e; } if (row->mSelectedOption >= row->mOptions.size()) @@ -1128,6 +1199,21 @@ void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList) } } +void GuiGameListMenuCtrl::addOption(S32 rowIndex, const char* displayText, const char* keyText) +{ + if (!isValidRowIndex(rowIndex)) + { + return; + } + + OptionEntry e; + e.mDisplayText = StringTable->insert(displayText, true); + e.mKeyString = (keyText[0] == '\0') ? e.mDisplayText : StringTable->insert(keyText, true); + + Row* row = (Row*)mRows[rowIndex]; + row->mOptions.push_back(e); +} + void GuiGameListMenuCtrl::clickOption(Row* row, S32 xPos) { GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile; @@ -1566,6 +1652,22 @@ DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOption, const char*, (S32 row) return object->getCurrentOption(row); } +DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOptionKey, const char*, (S32 row), , + "Gets the key string for the currently selected option of the given row.\n\n" + "@param row Index of the row to get the option from.\n" + "@return The key (or id) that was assigned to the selected option on the given row. If there is no selected option then the empty string is returned.") +{ + return object->getCurrentOptionKey(row); +} + +DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOptionIndex, S32, (S32 row), , + "Gets the index into the option list for the currently selected option of the given row.\n\n" + "@param row Index of the row to get the option from.\n" + "@return The index of the selected option on the given row. If there is no selected option then -1 is returned.") +{ + return object->getCurrentOptionIndex(row); +} + DefineEngineMethod(GuiGameListMenuCtrl, selectOption, bool, (S32 row, const char* option), , "Set the row's current option to the one specified\n\n" "@param row Index of the row to set an option on.\n" @@ -1575,6 +1677,24 @@ DefineEngineMethod(GuiGameListMenuCtrl, selectOption, bool, (S32 row, const char return object->selectOption(row, option); } +DefineEngineMethod(GuiGameListMenuCtrl, selectOptionByKey, bool, (S32 row, const char* optionKey), , + "Set the row's current option to the one with the specified key.\n\n" + "@param row Index of the row to set an option on.\n" + "@param optionKey The key string that was assigned to the option to be made active.\n" + "@return True if the row contained the key and the option and was set, false otherwise.") +{ + return object->selectOptionByKey(row, optionKey); +} + +DefineEngineMethod(GuiGameListMenuCtrl, selectOptionByIndex, bool, (S32 row, S32 optionIndex), , + "Set the row's current option to the one at the specified index.\n\n" + "@param row Index of the row to set an option on.\n" + "@param optionIndex The index of the option to be made active.\n" + "@return True if the index was valid and the option and was set, false otherwise.") +{ + return object->selectOptionByIndex(row, optionIndex); +} + DefineEngineMethod(GuiGameListMenuCtrl, setOptions, void, (S32 row, const char* optionsList), , "Sets the list of options on the given row.\n\n" "@param row Index of the row to set options on." @@ -1583,6 +1703,16 @@ DefineEngineMethod(GuiGameListMenuCtrl, setOptions, void, (S32 row, const char* object->setOptions(row, optionsList); } +DefineEngineMethod(GuiGameListMenuCtrl, addOption, void, (S32 row, const char* displayText, const char* keyText), (""), + "Adds an option to the list of options on the given row.\n\n" + "@param row Index of the row to add the option on.\n" + "@param displayText The text to display for this option.\n" + "@param keyText [Optional] The id string to associate with this value. " + "If unset, the id will be the same as the display text.\n") +{ + object->addOption(row, displayText, keyText); +} + DefineEngineMethod(GuiGameListMenuCtrl, getValue, F32, (S32 row), , "Sets the list of options on the given row.\n\n" "@param row Index of the row to set options on." diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.h b/Engine/source/gui/controls/guiGameListMenuCtrl.h index 15bbf49a3..3e6c3c7b0 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.h +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.h @@ -37,6 +37,18 @@ public: typedef GuiGameListMenuProfile Profile; protected: + + /// \struct OptionEntry + /// Display text and ID key for each entry in an option row. + struct OptionEntry + { + StringTableEntry mDisplayText; ///< The text that is displayed for the option + StringTableEntry mKeyString; ///< Key value that is associated with this option + OptionEntry() : mDisplayText(StringTable->EmptyString()), mKeyString(StringTable->EmptyString()) {} + virtual ~OptionEntry() {} + }; + + /// \struct Row /// Internal data representation of a single row in the control. struct Row @@ -60,7 +72,7 @@ protected: Mode mMode; //List options - Vector mOptions; ///< Collection of options available to display + Vector mOptions; ///< Collection of options available to display S32 mSelectedOption; ///< Index into mOptions pointing at the selected option bool mWrapOptions; ///< Determines if options should "wrap around" at the ends @@ -174,13 +186,43 @@ public: /// string is returned. StringTableEntry getCurrentOption(S32 rowIndex) const; + /// Gets the key string for the currently selected option of the given row + /// + /// \param rowIndex Index of the row to get the option from. + /// \return The key (or id) that was assigned to the selected option on the + /// given row. If there is no selected option then the empty string is returned. + StringTableEntry getCurrentOptionKey(S32 rowIndex) const; + + /// Gets the index into the option list for the currently selected option of the given row. + /// + /// \param rowIndex Index of the row to get the option from. + /// \return The index of the selected option on the given row. If there is no + /// selected option then -1 is returned. + S32 getCurrentOptionIndex(S32 rowIndex) const; + /// Attempts to set the given row to the specified selected option. The option /// will only be set if the option exists in the control. /// /// \param rowIndex Index of the row to set an option on. /// \param option The option to be made active. /// \return True if the row contained the option and was set, false otherwise. - bool selectOption(S32 rowIndex, StringTableEntry option); + bool selectOption(S32 rowIndex, const char* option); + + /// Attempts to set the given row to the option with the specified key. The + /// option will only be set if the key exists in the control. + /// + /// \param rowIndex Index of the row to set an option on. + /// \param optionKey The key string that was assigned to the option to be made active. + /// \return True if the row contained the key and the option and was set, false otherwise. + bool selectOptionByKey(S32 rowIndex, const char* optionKey); + + /// Attempts to set the given row to the option at the specified index. The option + /// will only be set if the index is valid. + /// + /// \param rowIndex Index of the row to set an option on. + /// \param optionIndex The index of the option to be made active. + /// \return True if the index was valid and the option and was set, false otherwise. + bool selectOptionByIndex(S32 rowIndex, S32 optionIndex); /// Sets the list of options on the given row. /// @@ -188,6 +230,14 @@ public: /// \param optionsList A tab separated list of options for the control. void setOptions(S32 rowIndex, const char* optionsList); + /// Adds an option to the list of options on the given row. + /// + /// \param rowIndex Index of the row to set options on. + /// \param displayText The text to display for this option. + /// \param keyText The id string to associate with this value. If NULL the + /// id will be the same as the display text. + void addOption(S32 rowIndex, const char* displayText, const char* keyText); + /// Activates the current row. The script callback of the current row will /// be called (if it has one). virtual void activateRow();