Forum Discussion

JohnBasedow's avatar
12 years ago

Dev Issue - Multiple roMessageDialog with back button

I'm trying to implement a quick way for the user to change search filter settings, and to accomplish this, I am using an roSearchScreen, and two roMessageDialog windows.

If the user presses the info button (*) on the roSearchScreen, I open the first roMessageDialog, and call EnableBackButton(false) before it is shown. I add two buttons to the first roMessageDialog, one to configure one option, and the other for another option. This window also has EnableBackButton(false) set.

If I open the first roMessageDialog and hit the 'Back' button, nothing happens, like I expect. If instead, I choose the option value I want, then return to the first roMessageDialog and hit 'Back', the channel returns to my Channel's home screen, instead of the Search screen, which is unexpected, since I thought I had disabled the Back button.

At this point, my code is still in the first roMessageDialog's event loop waiting for any kind of message, of course none come, so it is essentially locked. To work around this, I added a timeout to the wait call in the first dialog, and that un-locks my channel's home screen. Of course this is a dirty workaround, and I can't leave it that way.

Flow:

Issue:
Home
-- Search (roSearchScreen)
-- Options (roMessageDialog)
-- Hit 'Back' button here = does nothing
-- Option 1 (roMessageDialog)
-- Option 1 dialog closes
-- Options
-- Hit 'Back' button here
Home


Okay case (as long as I don't hit the back button after the 2nd roMessageDialog closes, it works fine):
Home
-- Search (roSearchScreen)
-- Options (roMessageDialog)
-- Option 1 (roMessageDialog)
-- Option 1 dialog closes
-- Option 2 (roMessageDialog)
-- Option 2 dialog closes
-- Hit 'Done'
-- Options dialog closes
-- Search
Home


It looks like either I'm doing something incorrectly, or that the platform places roMessageDialogs in a special position atop the screen stack.

Any help would be appreciated!

Edit: Formatted the flows a little better

6 Replies

  • if you have some code that demonstrates the issue, perhaps you can post it here. In most cases the back button is a firmware action that will close whatever screen is open, so you always need to have a handler for isscreenclosed() events that includes a return statement, and of course, the calling function needs to be able to handle whatever is returned from the called function or sub.

    - Joel
  • Here's a stripped-down version of the code that exhibits the issue:

    Sub doSearchWindow()
    port = CreateObject("roMessagePort")
    searchScreen = CreateObject("roSearchScreen")
    searchScreen.SetMessagePort(port)

    history = CreateObject("roSearchHistory")
    searchScreen.SetSearchTerms(history.GetAsArray())
    searchScreen.Show()

    while (true)
    msg = wait(0, port)

    if (type(msg) = "roSearchScreenEvent") then
    if (msg.isScreenClosed()) then
    return
    else if (msg.isPartialResult()) then
    ' Unnecessary
    else if (msg.isFullResult()) then
    ' Unnecessary
    else if (msg.isCleared()) then
    ' Unnecessary
    else if ((msg.isRemoteKeyPressed() AND msg.GetIndex() = 10) OR msg.isButtonInfo()) then
    ' Shows the first roMessageDialog for search filters
    SearchOptionsDialog()
    end if
    end if
    end while
    End Sub

    Function SearchOptionsDialog() as Integer
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Search Options")
    dialog.SetText("Some text")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "Change Filter One")
    dialog.addButton(2, "Change Filter Two")
    dialog.addButton(3, "Done")
    dialog.Show()
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    ret = FilterOneClicked()
    if (ret = "") then
    ' Do other stuff
    end if
    else if (dlgMsg.GetIndex() = 2) then
    ret = FilterTwoClicked()
    if (ret = "") then
    ' do other stuff
    end if
    else if (dlgMsg.GetIndex() = 3) then
    dialog.Close()
    exit while
    end if
    else if (dlgMsg.isScreenClosed()) then
    dialog.Close()
    exit while
    else
    exit while
    end if
    else
    exit while
    end if
    end while
    return 0
    End Function

    Function FilterOneClicked() as String
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Filter One")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "None")
    dialog.Show()
    toReturn = ""
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    toReturn = ""
    end if
    exit while
    else if (dlgMsg.isScreenClosed()) then
    exit while
    end if
    end if
    end while
    dialog.Close()
    return toReturn
    End Function

    Function FilterTwoClicked() as String
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Filter Two")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "None")
    dialog.Show()
    toReturn = ""
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    toReturn = ""
    end if
    exit while
    else if (dlgMsg.isScreenClosed()) then
    exit while
    end if
    end if
    end while
    dialog.Close()
    return toReturn
    End Function
  • I modified your code so that it doesn't call a second dialog.close() on the isScreenClosed() event - (the dialog is already closed, but then you are calling dialog.close() again any time there is an exit while. )

        Sub doSearchWindow()

    port = CreateObject("roMessagePort")
    searchScreen = CreateObject("roSearchScreen")
    searchScreen.SetMessagePort(port)

    history = CreateObject("roSearchHistory")
    searchScreen.SetSearchTerms(["test","west","best","lest","vest"] )
    searchScreen.Show()

    while (true)
    msg = wait(0, port)

    if (type(msg) = "roSearchScreenEvent") then
    if (msg.isScreenClosed()) then

    return
    else if (msg.isPartialResult()) then
    ' Unnecessary
    else if (msg.isFullResult()) then
    ' Unnecessary
    else if (msg.isCleared()) then
    ' Unnecessary
    else if ((msg.isRemoteKeyPressed() AND msg.GetIndex() = 10) OR msg.isButtonInfo()) then
    ' Shows the first roMessageDialog for search filters
    SearchOptionsDialog()
    end if
    end if
    end while
    End Sub

    Function SearchOptionsDialog() as Integer
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Search Options")
    dialog.SetText("Some text")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "Change Filter One")
    dialog.addButton(2, "Change Filter Two")
    dialog.addButton(3, "Done")
    dialog.Show()
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    ret = FilterOneClicked()
    if (ret = "") then
    ' Do other stuff
    end if
    else if (dlgMsg.GetIndex() = 2) then
    ret = FilterTwoClicked()
    if (ret = "") then
    ' do other stuff
    end if
    else if (dlgMsg.GetIndex() = 3) then
    'dialog.Close()
    return 0
    end if
    else if (dlgMsg.isScreenClosed()) then
    return 0
    exit while
    else
    exit while
    end if
    else
    exit while
    end if
    end while
    return 0
    End Function

    Function FilterOneClicked() as String
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Filter One")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "None")
    dialog.Show()
    toReturn = ""
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    toReturn = ""
    end if
    return toreturn
    else if (dlgMsg.isScreenClosed()) then
    return toreturn
    end if
    end if
    end while
    dialog.Close()
    return toReturn
    End Function

    Function FilterTwoClicked() as String
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Filter Two")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "None")
    dialog.Show()
    toReturn = ""
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    ?"button pressed:";dlgmsg.getindex()
    if (dlgMsg.GetIndex() = 1) then
    toReturn = ""
    end if
    return toreturn
    else if (dlgMsg.isScreenClosed()) then
    ?"screen closed"
    return toreturn
    end if
    end if
    end while
    End Function
  • Honestly, I added those after I saw this issue happening. Removing/moving them changes nothing, the first roMessageDialog does not get any events when I hit the back button after opening, then closing the second roMessageDialog.

    If I add debug prints, I can see when the associated functions are returning and when I get events, everything is returning/exiting as I would expect, except when I hit the back button.

    You can see in the code I explicitly disable the back button, so why is it still firing after the 2nd roMessageDialog closes? The first roMessageDialog shouldn't allow the back button either, and it doesn't unless I open/close the 2nd.
  • Generally, stacking multiple dialogs is not a great idea. Best practice is to close one before opening the other.

    I was also able to make it work the way I think you intended by opening a blank roImageCanvas between the two dialogs.
  • I decided to take your advice RokuChris, and have modified the code to be similar to this (of course I don't like the delay after closing the 2nd dialog for the window to reappear, but whatever):
            Sub doSearchWindow()

    port = CreateObject("roMessagePort")
    searchScreen = CreateObject("roSearchScreen")
    searchScreen.SetMessagePort(port)

    history = CreateObject("roSearchHistory")
    searchScreen.SetSearchTerms(["test","west","best","lest","vest"] )
    searchScreen.Show()

    while (true)
    msg = wait(0, port)

    if (type(msg) = "roSearchScreenEvent") then
    if (msg.isScreenClosed()) then

    return
    else if (msg.isPartialResult()) then
    ' Unnecessary
    else if (msg.isFullResult()) then
    ' Unnecessary
    else if (msg.isCleared()) then
    ' Unnecessary
    else if ((msg.isRemoteKeyPressed() AND msg.GetIndex() = 10) OR msg.isButtonInfo()) then
    ' Shows the first roMessageDialog for search filters
    while (SearchOptionsDialog() = 2)
    end while
    end if
    end if
    end while
    End Sub

    Function SearchOptionsDialog() as Integer
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Search Options")
    dialog.SetText("Some text")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "Change Filter One")
    dialog.addButton(2, "Change Filter Two")
    dialog.addButton(3, "Done")
    dialog.Show()
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    dialog.Close()
    ret = FilterOneClicked()
    if (ret = "") then
    ' Do other stuff
    end if
    return 2
    else if (dlgMsg.GetIndex() = 2) then
    dialog.Close()
    ret = FilterTwoClicked()
    if (ret = "") then
    ' do other stuff
    end if
    return 2
    else if (dlgMsg.GetIndex() = 3) then
    'dialog.Close()
    return 0
    end if
    else if (dlgMsg.isScreenClosed()) then
    return 0
    exit while
    else
    exit while
    end if
    else
    exit while
    end if
    end while
    return 0
    End Function

    Function FilterOneClicked() as String
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Filter One")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "None")
    dialog.Show()
    toReturn = ""
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    if (dlgMsg.GetIndex() = 1) then
    toReturn = ""
    end if
    return toreturn
    else if (dlgMsg.isScreenClosed()) then
    return toreturn
    end if
    end if
    end while
    dialog.Close()
    return toReturn
    End Function

    Function FilterTwoClicked() as String
    dialog = CreateObject("roMessageDialog")
    port = CreateObject("roMessagePort")
    dialog.SetMessagePort(port)
    dialog.SetTitle("Filter Two")
    dialog.EnableBackButton(false)
    dialog.addButton(1, "None")
    dialog.Show()
    toReturn = ""
    while true
    dlgMsg = wait(0, dialog.GetMessagePort())
    if (type(dlgMsg) = "roMessageDialogEvent") then
    if (dlgMsg.isButtonPressed()) then
    ?"button pressed:";dlgmsg.getindex()
    if (dlgMsg.GetIndex() = 1) then
    toReturn = ""
    end if
    return toreturn
    else if (dlgMsg.isScreenClosed()) then
    ?"screen closed"
    return toreturn
    end if
    end if
    end while
    End Function