Full modal dialog functionality
This commit is contained in:
parent
25d3019d1a
commit
fc54a6e418
|
@ -1,71 +1,117 @@
|
|||
modalDialog = nil
|
||||
|
||||
function init()
|
||||
g_ui.importStyle('modaldialog')
|
||||
|
||||
connect(g_game, { onModalDialog = onModalDialog,
|
||||
onGameEnd = destroy })
|
||||
onGameEnd = destroyDialog })
|
||||
|
||||
local dialog = rootWidget:recursiveGetChildById('modalDialog')
|
||||
if dialog then
|
||||
modalDialog = dialog
|
||||
end
|
||||
end
|
||||
|
||||
function terminate()
|
||||
disconnect(g_game, { onModalDialog = onModalDialog,
|
||||
onGameEnd = destroy })
|
||||
|
||||
destroy()
|
||||
onGameEnd = destroyDialog })
|
||||
end
|
||||
|
||||
function destroy()
|
||||
function destroyDialog()
|
||||
if modalDialog then
|
||||
modalDialog:destroy()
|
||||
modalDialog = nil
|
||||
end
|
||||
end
|
||||
|
||||
function onModalDialog(id, title, message, enterId, enterText, escapeId, escapeText, choices)
|
||||
if modalDialog then return end
|
||||
function onModalDialog(id, title, message, buttons, enterButton, escapeButton, choices, priority)
|
||||
-- priority parameter is unused, not sure what its use is.
|
||||
if modalDialog then
|
||||
return
|
||||
end
|
||||
|
||||
modalDialog = g_ui.createWidget('ModalDialog', rootWidget)
|
||||
|
||||
local enterButton = modalDialog:getChildById('enterButton')
|
||||
local escapeButton = modalDialog:getChildById('escapeButton')
|
||||
local messageLabel = modalDialog:getChildById('messageLabel')
|
||||
local choiceList = modalDialog:getChildById('choiceList')
|
||||
local choiceScrollbar = modalDialog:getChildById('choiceScrollBar')
|
||||
local buttonList = modalDialog:getChildById('buttonList')
|
||||
|
||||
modalDialog:setText(title)
|
||||
messageLabel:setText(message)
|
||||
enterButton:setText(enterText)
|
||||
escapeButton:setText(escapeText)
|
||||
|
||||
local focusLabel = nil
|
||||
for k, v in pairs(choices) do
|
||||
local choiceId = v[1]
|
||||
local choiceName = v[2]
|
||||
local horizontalPadding = modalDialog:getPaddingLeft() + modalDialog:getPaddingRight()
|
||||
modalDialog:setWidth(math.min(modalDialog.maximumWidth, math.max(messageLabel:getWidth(), modalDialog.minimumWidth)))
|
||||
messageLabel:setWidth(math.min(modalDialog.maximumWidth, math.max(messageLabel:getWidth(), modalDialog.minimumWidth)) - horizontalPadding)
|
||||
|
||||
local labelHeight = nil
|
||||
for i = 1, #choices do
|
||||
local choiceId = choices[i][1]
|
||||
local choiceName = choices[i][2]
|
||||
|
||||
local label = g_ui.createWidget('ChoiceListLabel', choiceList)
|
||||
label.choiceId = choiceId
|
||||
label:setText(choiceName)
|
||||
label:setPhantom(false)
|
||||
if not labelHeight then
|
||||
labelHeight = label:getHeight()
|
||||
end
|
||||
end
|
||||
choiceList:focusNextChild()
|
||||
|
||||
if not focusLabel then
|
||||
focusLabel = label
|
||||
for i = 1, #buttons do
|
||||
local buttonId = buttons[i][1]
|
||||
local buttonText = buttons[i][2]
|
||||
|
||||
local button = g_ui.createWidget('ModalButton', buttonList)
|
||||
button:setText(buttonText)
|
||||
button.onClick = function(self)
|
||||
local focusedChoice = choiceList:getFocusedChild()
|
||||
local choice = 0xFF
|
||||
if focusedChoice then
|
||||
choice = focusedChoice.choiceId
|
||||
end
|
||||
g_game.answerModalDialog(id, buttonId, choice)
|
||||
destroyDialog()
|
||||
end
|
||||
end
|
||||
choiceList:focusChild(focusLabel)
|
||||
|
||||
local additionalHeight = 0
|
||||
if #choices > 0 then
|
||||
choiceList:setVisible(true)
|
||||
choiceScrollbar:setVisible(true)
|
||||
|
||||
additionalHeight = math.min(modalDialog.maximumChoices, math.max(modalDialog.minimumChoices, #choices)) * labelHeight
|
||||
additionalHeight = additionalHeight + choiceList:getPaddingTop() + choiceList:getPaddingBottom()
|
||||
end
|
||||
modalDialog:setHeight(modalDialog:getHeight() + additionalHeight)
|
||||
|
||||
addEvent(function()
|
||||
modalDialog:setHeight(modalDialog:getHeight() + messageLabel:getHeight() - 14)
|
||||
end)
|
||||
|
||||
local enterFunc = function()
|
||||
g_game.answerModalDialog(id, enterId, choiceList:getFocusedChild().choiceId)
|
||||
destroy()
|
||||
local focusedChoice = choiceList:getFocusedChild()
|
||||
local choice = 0xFF
|
||||
if focusedChoice then
|
||||
choice = focusedChoice.choiceId
|
||||
end
|
||||
g_game.answerModalDialog(id, enterButton, choice)
|
||||
destroyDialog()
|
||||
end
|
||||
|
||||
local escapeFunc = function()
|
||||
g_game.answerModalDialog(id, escapeId, choiceList:getFocusedChild().choiceId)
|
||||
destroy()
|
||||
local focusedChoice = choiceList:getFocusedChild()
|
||||
local choice = 0xFF
|
||||
if focusedChoice then
|
||||
choice = focusedChoice.choiceId
|
||||
end
|
||||
g_game.answerModalDialog(id, escapeButton, choice)
|
||||
destroyDialog()
|
||||
end
|
||||
|
||||
choiceList.onDoubleClick = enterFunc
|
||||
|
||||
enterButton.onClick = enterFunc
|
||||
modalDialog.onEnter = enterFunc
|
||||
|
||||
escapeButton.onClick = escapeFunc
|
||||
modalDialog.onEscape = escapeFunc
|
||||
return
|
||||
end
|
|
@ -8,52 +8,61 @@ ChoiceListLabel < Label
|
|||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
ModalDialog < MainWindow
|
||||
id: modalDialog
|
||||
!text: tr('Title')
|
||||
size: 280 230
|
||||
@onEscape: self:destroy()
|
||||
|
||||
Label
|
||||
id: messageLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text-align: left
|
||||
text: Message
|
||||
height: 60
|
||||
|
||||
TextList
|
||||
ChoiceList < TextList
|
||||
id: choiceList
|
||||
vertical-scrollbar: choiceScrollBar
|
||||
anchors.fill: parent
|
||||
anchors.top: prev.bottom
|
||||
anchors.bottom: next.top
|
||||
margin-bottom: 10
|
||||
margin-top: 10
|
||||
padding: 1
|
||||
margin-top: 4
|
||||
margin-bottom: 10
|
||||
focusable: false
|
||||
visible: false
|
||||
|
||||
Button
|
||||
id: enterButton
|
||||
!text: tr('Ok')
|
||||
anchors.top: next.top
|
||||
anchors.right: next.left
|
||||
margin-right: 8
|
||||
width: 60
|
||||
|
||||
Button
|
||||
id: escapeButton
|
||||
!text: tr('Cancel')
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
margin-top: 10
|
||||
width: 60
|
||||
|
||||
VerticalScrollBar
|
||||
ChoiceScrollBar < VerticalScrollBar
|
||||
id: choiceScrollBar
|
||||
anchors.top: choiceList.top
|
||||
anchors.bottom: choiceList.bottom
|
||||
anchors.right: choiceList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
visible: false
|
||||
|
||||
ModalButton < Button
|
||||
width: 60
|
||||
margin: 2
|
||||
|
||||
ModalDialog < MainWindow
|
||||
id: modalDialog
|
||||
size: 280 97
|
||||
&minimumWidth: 200
|
||||
&maximumWidth: 500
|
||||
&minimumChoices: 4
|
||||
&maximumChoices: 10
|
||||
|
||||
Label
|
||||
id: messageLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text-align: left
|
||||
text-auto-resize: true
|
||||
text-wrap: true
|
||||
|
||||
ChoiceList
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: next.top
|
||||
|
||||
Panel
|
||||
id: buttonList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: 24
|
||||
layout: horizontalBox
|
||||
align-right: true
|
||||
|
||||
ChoiceScrollBar
|
||||
|
|
|
@ -61,7 +61,7 @@ end
|
|||
|
||||
function terminate()
|
||||
disconnect(g_game, 'onTextMessage', displayMessage)
|
||||
disconnect(g_game, 'onGameEnd',clearMessages)
|
||||
disconnect(g_game, 'onGameEnd', clearMessages)
|
||||
clearMessages()
|
||||
messagesPanel:destroy()
|
||||
end
|
||||
|
|
|
@ -506,9 +506,9 @@ void Game::processQuestLine(int questId, const std::vector<std::tuple<std::strin
|
|||
g_lua.callGlobalField("g_game", "onQuestLine", questId, questMissions);
|
||||
}
|
||||
|
||||
void Game::processModalDialog(uint32 id, std::string title, std::string message, int enterId, std::string enterText, int escapeId, std::string escapeText, std::vector<std::tuple<int, std::string> > choiceList)
|
||||
void Game::processModalDialog(uint32 id, std::string title, std::string message, std::vector<std::tuple<int, std::string> > buttonList, int enterButton, int escapeButton, std::vector<std::tuple<int, std::string> > choiceList, bool priority)
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onModalDialog", id, title, message, enterId, enterText, escapeId, escapeText, choiceList);
|
||||
g_lua.callGlobalField("g_game", "onModalDialog", id, title, message, buttonList, enterButton, escapeButton, choiceList, priority);
|
||||
}
|
||||
|
||||
void Game::processAttackCancel(uint seq)
|
||||
|
|
|
@ -132,7 +132,7 @@ protected:
|
|||
void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions);
|
||||
|
||||
// modal dialogs >= 970
|
||||
void processModalDialog(uint32 id, std::string title, std::string message, int enterId, std::string enterText, int escapeId, std::string escapeText, std::vector<std::tuple<int, std::string> > choiceList);
|
||||
void processModalDialog(uint32 id, std::string title, std::string message, std::vector<std::tuple<int, std::string> > buttonList, int enterButton, int escapeButton, std::vector<std::tuple<int, std::string> > choiceList, bool priority);
|
||||
|
||||
friend class ProtocolGame;
|
||||
friend class Map;
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace Proto {
|
|||
GameServerMarketLeave = 247, // 944
|
||||
GameServerMarketDetail = 248, // 944
|
||||
GameServerMarketBrowse = 249, // 944
|
||||
GameServerShowModalDialog = 250 // 960
|
||||
GameServerModalDialog = 250 // 960
|
||||
};
|
||||
|
||||
enum ClientOpcodes : uint8
|
||||
|
|
|
@ -212,7 +212,7 @@ private:
|
|||
void parseChannelEvent(const InputMessagePtr& msg);
|
||||
void parseItemInfo(const InputMessagePtr& msg);
|
||||
void parsePlayerInventory(const InputMessagePtr& msg);
|
||||
void parseShowModalDialog(const InputMessagePtr& msg);
|
||||
void parseModalDialog(const InputMessagePtr& msg);
|
||||
void parseExtendedOpcode(const InputMessagePtr& msg);
|
||||
void parseChangeMapAwareRange(const InputMessagePtr& msg);
|
||||
void parseCreaturesMark(const InputMessagePtr& msg);
|
||||
|
|
|
@ -316,8 +316,8 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
|||
parsePlayerInfo(msg);
|
||||
break;
|
||||
// PROTOCOL>=970
|
||||
case Proto::GameServerShowModalDialog:
|
||||
parseShowModalDialog(msg);
|
||||
case Proto::GameServerModalDialog:
|
||||
parseModalDialog(msg);
|
||||
break;
|
||||
// PROTOCOL>=980
|
||||
case Proto::GameServerLoginSuccess:
|
||||
|
@ -1596,18 +1596,18 @@ void ProtocolGame::parsePlayerInventory(const InputMessagePtr& msg)
|
|||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::parseShowModalDialog(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseModalDialog(const InputMessagePtr& msg)
|
||||
{
|
||||
uint32 id = msg->getU32();
|
||||
std::string title = msg->getString();
|
||||
std::string message = msg->getString();
|
||||
|
||||
int sizeButtons = msg->getU8();
|
||||
std::map<int, std::string > buttonList;
|
||||
std::vector<std::tuple<int, std::string> > buttonList;
|
||||
for(int i = 0; i < sizeButtons; ++i) {
|
||||
std::string value = msg->getString();
|
||||
int id = msg->getU8();
|
||||
buttonList[id] = value;
|
||||
buttonList.push_back(std::make_tuple(id, value));
|
||||
}
|
||||
|
||||
int sizeChoices = msg->getU8();
|
||||
|
@ -1628,21 +1628,9 @@ void ProtocolGame::parseShowModalDialog(const InputMessagePtr& msg)
|
|||
escapeButton = msg->getU8();
|
||||
}
|
||||
|
||||
msg->getU8(); // popup value (no clue what it is for)
|
||||
bool priority = msg->getU8() == 0x01;
|
||||
|
||||
std::map<int, std::string>::iterator itEnter = buttonList.find(enterButton);
|
||||
if(itEnter == buttonList.end()) {
|
||||
g_logger.info(stdext::format("Enter button does not exist for dialog id: %d", id));
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<int, std::string >::iterator itEscape = buttonList.find(escapeButton);
|
||||
if(itEscape == buttonList.end()) {
|
||||
g_logger.info(stdext::format("Escape button does not exist for dialog id: %d", id));
|
||||
return;
|
||||
}
|
||||
|
||||
g_game.processModalDialog(id, title, message, itEnter->first, itEnter->second, itEscape->first, itEscape->second, choiceList);
|
||||
g_game.processModalDialog(id, title, message, buttonList, enterButton, escapeButton, choiceList, priority);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseExtendedOpcode(const InputMessagePtr& msg)
|
||||
|
|
Loading…
Reference in New Issue