[CIQBUG] Menu not behaving correctly after Ui.popView()

I'm running into an interesting problem with nested menus. The below test case illustrates the problem.

To reproduce...

  • Start the app.
  • Press (or tap) Menu to get to the Options menu.
  • Press enter (or tap screen) to select Menu 0.
  • Press enter (or tap screen) to select Sub 0x0.
  • Press enter (or tap screen) to select Item 0x0x0.
  • You will find yourself back at the Options menu with Menu 0 selected. So far everything is normal.
  • Press Up/Down (or swipe) to hilight Menu 1.
  • Press enter (or tap screen) to select Menu 1.
  • Note that the current menu is Sub 0x1 and the available menu options are Item 0x1x0 and Item 0x1x1. This is unexpected. If I select Menu 1, I'd be looking at Menu 1 and the options would be Sub 1x0 and Sub 1x1.


I'm able to reproduce the problem on both the vivoactive w/ 2.80 firmware and the fr920xt w/ 3.30 firmware. I do not see the problem in the simulator. If I remove the Ui.popView() from SubMenu.onMenuItem, I do not see the problem.

using Toybox.Application as App;
using Toybox.Graphics as Gfx;
using Toybox.System as Sys;
using Toybox.WatchUi as Ui;

// allows me to do dynamic menus
const _mSymbols = [
:symbol0,
:symbol1,
:symbol2,
:symbol3,
:symbol4,
:symbol5,
:symbol6,
:symbol7,
:symbol8
];

// allows me to put all rendering and input handling code into a single class
class MyMenuDelegate extends Ui.MenuInputDelegate {
hidden var _mMenu;

function initialize(menu) {
_mMenu = menu;
}

function onMenuItem(item) {
return _mMenu.onMenuItem(item);
}
}

class MySubMenu extends Ui.Menu {
hidden var _mMenu;
hidden var _mSubMenu;

function initialize(menu, sub) {
_mMenu = menu;
_mSubMenu = sub;

setTitle(Lang.format("Sub $1$x$2$", [ _mMenu, _mSubMenu ]));

for (var i = 0; i < 2; ++i) {
addItem(Lang.format("Item $1$x$2$x$3$", [ _mMenu, _mSubMenu, i ]), _mSymbols);
}
}

function onMenuItem(item) {
var symbol;
for (symbol = 0; symbol < _mSymbols.size(); ++symbol) {

if (_mSymbols[symbol] == item) {
break;
}
}

if (_mSymbols.size() != symbol) {

// go back to the Options menu
Ui.popView(Ui.SLIDE_IMMEDIATE);
}

return true;
}
}

class MyMenu extends Ui.Menu {
hidden var _mMenu;

function initialize(menu) {
_mMenu = menu;

setTitle(Lang.format("Menu $1$", [ _mMenu ]));

for (var i = 0; i < 3; ++i) {
addItem(Lang.format("Sub $1$x$2$", [ _mMenu, i ]), _mSymbols);
}
}

function onMenuItem(item) {

var symbol;
for (symbol = 0; symbol < _mSymbols.size(); ++symbol) {

if (_mSymbols[symbol] == item) {
break;
}
}

if (_mSymbols.size() != symbol) {
var menu = new MySubMenu(_mMenu, symbol);
Ui.pushView(menu, new MyMenuDelegate(menu), Ui.SLIDE_LEFT);
}

return true;
}
}

class OptionsMenu extends Ui.Menu {
function initialize() {
setTitle("Options");

for (var i = 0; i < 2; ++i) {
addItem(Lang.format("Menu $1$", [ i ]), _mSymbols);
}
}

function onMenuItem(item) {

var symbol;
for (symbol = 0; symbol < _mSymbols.size(); ++symbol) {

if (_mSymbols[symbol] == item) {
break;
}
}

if (_mSymbols.size() != symbol) {
var menu = new MyMenu(symbol);
Ui.pushView(menu, new MyMenuDelegate(menu), Ui.SLIDE_LEFT);
}

return true;
}
}

class MyDelegate extends Ui.InputDelegate {

function onKey(evt) {
var key = evt.getKey();
if (key == Ui.KEY_ESC) {
Ui.popView(Ui.SLIDE_IMMEDIATE);
}
else if (key == Ui.KEY_MENU) {
var menu = new OptionsMenu();
Ui.pushView(menu, new MyMenuDelegate(menu), Ui.SLIDE_LEFT);
}
else {
return false;
}

return true;
}
}

class MyView extends Ui.View {
function onUpdate(dc) {
dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_BLACK);
dc.clear();

var cx = dc.getWidth() / 2;
var cy = dc.getHeight() / 2;

dc.drawText(cx, cy, Gfx.FONT_LARGE, "Press Menu", Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
}
}

class MyApp extends App.AppBase {

function getInitialView() {
var view = new MyView();
var delegate = new MyDelegate();

return [ view, delegate ];
}
}
[/code]