remi icon indicating copy to clipboard operation
remi copied to clipboard

key events on listview

Open caco3 opened this issue 4 years ago • 10 comments

It would be great to navigate through a listview by keys (up, down).

I think of different ways:

  • support a onkeydown event
  • handle it internally and directly select the next/previous item (but also trigger onselection event)

Bonus:

  • on a long list with scrollbars, if the selection goes out of view, scroll up down so the selected item is in view again.
  • Support scroll to key/value method

caco3 avatar Aug 05 '21 20:08 caco3

@caco3 this is a good idea, but I think that arrow keys should not change the selection. The arrows should allow navigation between elements (list view scroll) and selection should be changed by SPACE or ENTER. This is because sometimes selection is an important activities (think about an industrial machine setup), and requires an additional command. What do you think about this?

dddomodossola avatar Aug 05 '21 21:08 dddomodossola

I understand your point. How ever on most other GUIs one can change the selection in a (focused) list with up/down keys.

What do you think by simply providing a key press event like we have it on a textinput? Then the user would be free to use it in what ever way he wants.

My usecase: I created a photo album editor. A user can set a comment for each photo. There is a listview listing all photos. and a text field which shows the comment of the selected photo. For convenience, the textinput catches the up/down keys and allows switching the selected photo in the listview. This of course how ever only works if the focus is in the textview.

caco3 avatar Aug 05 '21 21:08 caco3

List view should already be able to receive key down and key up events, doesn't it?

dddomodossola avatar Aug 05 '21 21:08 dddomodossola

@caco3 I will look into this tomorrow and provide you an example ;-)

dddomodossola avatar Aug 05 '21 21:08 dddomodossola

List view should already be able to receive key down and key up events, doesn't it?

No, it doesn't work (eg. onkeyup) nor is it documented.

@caco3 I will look into this tomorrow and provide you an example ;-)

Thank you for looking into it. Your framework really is cool!

caco3 avatar Aug 06 '21 05:08 caco3

@caco3 here is an example for you:

import remi.gui as gui
from remi import start, App


class MyApp(App):

    def main(self):
        # creating a container VBox type, vertical (you can use also HBox or Widget)
        main_container = gui.VBox(width=400, height=400, style={'margin': '0px auto'})
        
        self.lbl = gui.Label("output")
        main_container.append(self.lbl)

        items = ('Danny Young','Christine Holand','Lars Gordon','Roberto Robitaille')
        self.listView = gui.ListView.new_from_list(items, width=300, height=120, margin='10px')
        self.listView.onselection.do(self.list_view_on_selected)
        self.listView.onkeyup.do(self.onkeyup_listview)

        #     vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        #>>>> this is fundamental to make the list focusable <<<<
        #     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self.listView.attributes['tabindex'] = '1'

        main_container.append(self.listView)

        # returning the root widget
        return main_container

    def onkeyup_listview(self, emitter, key, keycode, ctrl, shift, alt):
        print("onkeyup: " + keycode)
        self.lbl.set_text("onkeyup: " + keycode) 
        
        index = 0
        #if an item is selected, get its index
        if self.listView.get_key() in self.listView.children.keys():
            index = list(self.listView.children.keys()).index(self.listView.get_key())

        if keycode == '38': #arrow up
            index-=1 

        elif keycode == '40': #arrow down
            index+=1
        
        else:
            return

        #prevent index less than zero
        index = max(index, 0)
        #limit index at list size
        index = index % len(self.listView.children)

        #select the index
        key = list(self.listView.children.keys())[index]
        self.listView.select_by_key( key )
        #trigger the onselection event
        self.listView.onselection( self.listView.children[key] )

    def list_view_on_selected(self, emitter, selected_item_key):
        print("list_view_on_selected")
        self.lbl.set_text('List selection: ' + self.listView.children[selected_item_key].get_text())


if __name__ == "__main__":
    # starts the webserver
    start(MyApp, address='0.0.0.0', port=0, start_browser=True, username=None, password=None)

dddomodossola avatar Aug 06 '21 07:08 dddomodossola

Dear @dddomodossola Thank you very much for your quick and helpful response! Indeed this is what I wanted! Now as you showed the tabindex thingy, I also see it in the documentation (I wasn't carefully enough to also check the parent widgets documentation :(

Now, there is just one thing left: When the list is so long that scrollbars are needed, a key Up/Down will also scroll it. How ever I don't think suppression of this is easily possible!

caco3 avatar Aug 06 '21 20:08 caco3

Unfortunately remi has no documentation and so, no worries to ask me for help.

About scroll bars there should be a solution. However, for your use case maybe a listview is not perfectly suitable. Maybe you can easily construct your own thumbnail preview gallery, by simply using an HBox (or VBox I you need it vertically), and simulate navigation by appending and removing elements by key press. Maybe you can give it a try, and eventually I can create an example.

dddomodossola avatar Aug 06 '21 22:08 dddomodossola

Thanks, it is fine for me as is right now!

As for the documentation: Have you thought about using a wiki for the documentation? An ideal place to host (generated) project documentation is https://readthedocs.org. It free for opensource projects.

How ever I think maybe a wiki form would be better where others can provide explanations by themself. Github provides one automatically: https://github.com/dddomodossola/remi/wiki An example where I contributed before is https://github.com/bit-team/backintime/wiki/FAQ (The pages are too long, its better to have many, short pages).

And if you would want to grow the project and have others actively contributing more, maybe think of moving the project from your space to an organization space: https://docs.github.com/en/get-started/learning-about-github/types-of-github-accounts#organization-accounts.

I would be willing to help you to start something,. because I think this project is really cool!

caco3 avatar Aug 07 '21 17:08 caco3

You are welcome ;-)

The wiki is a good idea.

I already planned to move the project to an organization account. I have already created https://github.com/orgs/rawpython and https://github.com/orgs/the Open Place, I should choose in which one of the two organisations I will move remi.

Have you tried the remi graphical editor? https://github.com/dddomodossola/remi/tree/master/editor

dddomodossola avatar Aug 10 '21 05:08 dddomodossola