Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building "nested" ColumnMenu's #151

Closed
NuSkooler opened this issue Feb 7, 2021 · 12 comments
Closed

Building "nested" ColumnMenu's #151

NuSkooler opened this issue Feb 7, 2021 · 12 comments

Comments

@NuSkooler
Copy link

I'm attempting to build "nested" ColumMenu's. What I mean by this is for example if a user selects a top level menu item "A", the menu is replaced with "B". If they choose "C" from B, they get another menu. This can all be unwound e.g. by pressing ESC.

This seems very similar to #150 - Update A ColumnMenu's Items.

Currently I'm attempting to do this via multiple menus with the same dimensions and coordinates. E.g.:

// submit handler for "A"
menuB.hidden = false; // B and C start out hidden, etc.
menuB.redraw();
document.giveFocusTo(menuB);

This is of course a hack. Some things I think would help is element.show() / element.hide().

Additionally I'm running into a issue with 'blink()'. Since this happens with a timer, "B" is drawn then "A"'s blink loop messes with it. A couple thoughts:

  • For my purposes the ability to disable blink would work, though I do like the effect in general. Probably worth having some control here though.
  • It may be more ideal to have submit blink -> emit 'submit' at the end of the blink cycle?
  • Something else?!

Finally, is a nested menu system like this anywhere on the roadmap? If a single element could allow nesting and perhaps menu ident for nested items (I would use 0 indent in my case)? A x/y indent would allow for "tree" type views perhaps.

Any hints appreciated. I'd like to make myself more useful other than just asking stuff, but will need some hints on where you're taking things in order to do any coding.

@cronvel
Copy link
Owner

cronvel commented Feb 17, 2021

@NuSkooler I ran into a similar issue 2 weeks ago with blink, so I added a blinked event (it's undocumented, but it is stable).

The blinked event passes all the argument of the submit event, so it can be used as a drop-in replacement for that.

EDIT: the name of the event is blinked not blink.

@cronvel
Copy link
Owner

cronvel commented Feb 17, 2021

@NuSkooler Added Element#show() and Element#hide() on v1.47.2.

@cronvel
Copy link
Owner

cronvel commented Feb 17, 2021

@NuSkooler By nested menu, do you mean a sub-menu that pop on the right? Or do you mean a menu that replace the current one?
For instance, I have no plan for this, also it is probably highly similar with the DropDownMenu code, except if you want more depth/sub-levels.

@NuSkooler
Copy link
Author

NuSkooler commented Feb 17, 2021

@cronvel What I'm attempting to build is a menu that has multiple sub levels, but I'm very constrained for space so I'd like to draw them without indentation/etc.

Example, assuming "Item 2" is selected:

  Item 1
> Item 2
  Item 3

The menu becomes:

> Sub Item 1
  Sub Item 2
  Sub Item 3 

Update:
Here is basically what I'm doing via the combination of blinked, and the new show() and hide() to illustrate. Maybe there is a better way (managing a single menu would be great!) but this gets the job done for now:

let mainMenu;
let subMenu;


mainMenu = new TermKit.ColumnMenu({
	// ...
  	items : [
    	{
    		content : 'Menu Item',
    		value : () => {
    			mainMenu.hide();
    			document.giveFocusTo(subMenu);
    			subMenu.show();
    		}
    	}
  	]
});

mainMenu.on('blinked', handler => handler());

subMenu = new TermKit.ColumnMenu({
	// ...
	items : [
		{
			content : 'Sub Menu Item',
			value : () => {
				subMenu.hide();
				document.giveFocusTo(mainMenu);
				mainMenu.show();
			}
		}
	]
});

subMenu.on('blinked', handler=> handler());

cronvel added a commit that referenced this issue Feb 18, 2021
@cronvel
Copy link
Owner

cronvel commented Feb 18, 2021

@NuSkooler I have a very rough support for submenu, look at the file sample/document/column-menu-submenu-test.js.
It's not published yet, it is just on the last github commit.

@cronvel
Copy link
Owner

cronvel commented Feb 18, 2021

@NuSkooler The submenu features is refined and published as v1.49.1.
Left and right arrows and escape can be used to navigate from parent to child menu.
In the file sample/document/column-menu-submenu-test.js, uncomment the part with disposition: 'overwrite' (and comment the part with disposition: 'right').
Disposition right place the submenu on the right, while overwrite place the submenu on top of the current one.

@NuSkooler
Copy link
Author

NuSkooler commented Feb 19, 2021

@cronvel Thank you so much for implementing this - I'm replacing my custom implementation with this now and so far it's working quite well.

One issue: sub menu items do not appear to generate 'focus' events. Seems BaseMenu.prototype.onButtonFocus needs to check if isSubmenu and find it's parent menu type to emit from.

@NuSkooler
Copy link
Author

This almost works, but when leaving a sub, this.parent is null:

BaseMenu.prototype.onButtonFocus = function( focus , type , button ) {
	switch ( button.internalRole ) {
		case 'previousPage' :
		case 'nextPage' :
			break ;
		default :
			if ( focus && this.hasSubmenu && button.def.items && this.submenuOptions.openOn === 'parentFocus' ) {
				this.openSubmenu( button.value , button ) ;
			}

			this.emit( 'itemFocus' , button.value , focus , button ) ;

			if (this.isSubmenu && this.parent) {
				let parent = this.parent;
				while (parent.isSubmenu) {
					parent = parent.parent;
				}
				parent.emit( 'itemFocus' , button.value , focus , button ) ;
			}
	}
} ;

@cronvel
Copy link
Owner

cronvel commented Feb 19, 2021

@NuSkooler You want itemFocus to propagate to the parent menu?

@NuSkooler
Copy link
Author

@cronvel I want to be careful about saying "parent" here, but rather the "owning" menu (since there are in fact N arbitrary parents in nested sub menus).

const menu = new TermKit.ColumnMenu({
  // ...
  items: [
    // ...
    items : [
      // ...
      items : [
        content : "Foo",
        value : 'foo',
      ]
    ]
  ]
});

menu.on('itemFocus', (focus, value) => {
  // focus of "Foo" should fire here.
});

@cronvel
Copy link
Owner

cronvel commented Feb 20, 2021

@NuSkooler Done and published as v2.0.2.

@NuSkooler
Copy link
Author

@cronvel Thank you, this is working wonderfully!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants