Ejemplo n.º 1
0
 def draw(self):
     imgui.begin("Example: popup context view")
     imgui.text("Right-click to set value.")
     if imgui.begin_popup_context_item("Item Context Menu"):
         imgui.selectable("Set to Zero")
         imgui.end_popup()
     imgui.end()
Ejemplo n.º 2
0
    def _show_custom_ui(self):
        preview = "<none>"
        if self.connected_node is not None:
            preview = self.connected_node.name
        if imgui.begin_combo("", preview):
            nodes = self.SetVar.instances[self.graph.parent]

            is_selected = self.connected_node is None
            opened, selected = imgui.selectable("<none>", is_selected)
            if opened:
                self.name = ""
            if is_selected:
                imgui.set_item_default_focus()
            imgui.separator()

            for node in sorted(nodes, key=lambda node: node.name):
                if not node.valid:
                    continue
                is_selected = node == self.connected_node
                opened, selected = imgui.selectable(node.name, is_selected)
                if opened:
                    self.name = node.name
                if is_selected:
                    imgui.set_item_default_focus()
            imgui.end_combo()
Ejemplo n.º 3
0
 def draw(self):
     imgui.begin(self.title)
     _, self.selected[0] = imgui.selectable("1. I am selectable",
                                            self.selected[0])
     _, self.selected[1] = imgui.selectable("2. I am selectable too",
                                            self.selected[1])
     imgui.text("3. I am not selectable")
     imgui.end()
Ejemplo n.º 4
0
def draw_table(data, *selected_row):
    imgui.columns(len(data.columns) + 1, "##table")
    imgui.separator()
    imgui.text("")
    imgui.next_column()
    for c in data.columns:
        imgui.text(c)
        imgui.next_column()
    imgui.separator()
    # fill with data
    i = 0
    for _, row in data.iterrows():
        label = str(i)
        clicked, _ = imgui.selectable(label=label,
                                      selected=selected_row == i,
                                      flags=imgui.SELECTABLE_SPAN_ALL_COLUMNS,
                                      )
        if clicked:
            selected_row = i
        hovered = imgui.is_item_hovered()
        imgui.next_column()
        for c in data.columns:
            imgui.text(row[c])
            imgui.next_column()
        i += 1
Ejemplo n.º 5
0
    def render(self, *args):
        imgui.columns(2, 'fileLlist')
        imgui.separator()

        pathlist = os.listdir(os.curdir)
        pathlist.insert(0, os.pardir)
        pathlist.insert(0, os.curdir)
        length = len(pathlist)
        selected = [False] * length
        for i in range(length):
            _, selected[i] = imgui.selectable(pathlist[i], selected[i])
            imgui.next_column()
            size = os.path.getsize(pathlist[i])
            imgui.text(str(size)+' byte')
            imgui.next_column()
            if(selected[i] is True):
                self.path = os.path.abspath(pathlist[i])
                print('clicked ' + pathlist[i])
                if os.path.isdir(self.path):
                    os.chdir(self.path)
                    break

        imgui.next_column()

        imgui.columns(1)
        return {'path': self.path}
Ejemplo n.º 6
0
 def render_callback(self, time: float, frametime: float):
     if imgui.begin_main_menu_bar():
         if imgui.begin_menu("File", True):
             clicked_quit, selected_quit = imgui.menu_item(
                 "Quit", 'Cmd+Q', False, True
             )
             if clicked_quit:
                 exit(1)
             imgui.end_menu()
         changed, value = imgui.input_text("", self.input_text, 30)
         if changed:
             imgui.set_next_window_position(imgui.get_item_rect_min().x,
                                            imgui.get_item_rect_max().y)
             imgui.set_next_window_size(imgui.get_item_rect_size().x, 0)
             if imgui.begin("##popup", False,
                            imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE):
                 for index, row in symbol_list.iterrows():
                     if value.upper() in row[0]:
                         opened, selected = imgui.selectable(row[0] + " - " + row[2])
                         if imgui.is_item_clicked():
                             input_text = row[0]
                             selected_symbol = row[0]
             imgui.end()
         if imgui.button("download"):
             yfc.download(self.selected_symbol, symbol_data_file())
         imgui.end_main_menu_bar()
     pass
Ejemplo n.º 7
0
 def menu_bar(self):
     if imgui.begin_main_menu_bar():
         if imgui.begin_menu("File", True):
             clicked_quit, selected_quit = imgui.menu_item(
                 "Quit", 'Cmd+Q', False, True)
             if clicked_quit:
                 self.cleanup()
                 exit(0)
             imgui.end_menu()
         changed, value = imgui.input_text("", self.input_text, 30)
         if changed:
             imgui.set_next_window_position(imgui.get_item_rect_min().x,
                                            imgui.get_item_rect_max().y)
             imgui.set_next_window_size(imgui.get_item_rect_size().x, 0)
             if imgui.begin(
                     "##popup", False, imgui.WINDOW_NO_TITLE_BAR
                     | imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE):
                 for index, row in self.symbol_list.iterrows():
                     if value.upper() in row[0]:
                         _, _ = imgui.selectable(row[0] + " - " + row[2])
                         if imgui.is_item_clicked():
                             self.input_text = row[0]
                             self.load_symbol(str(row[0]).lower())
             imgui.end()
         imgui.end_main_menu_bar()
Ejemplo n.º 8
0
    def draw(self):
        imgui.new_frame()

        imgui.set_next_window_position(16, 32, imgui.ONCE)
        imgui.set_next_window_size(512, 512, imgui.ONCE)

        imgui.begin("Example: popup context window")
        if imgui.begin_popup_context_window(mouse_button=0):
            imgui.selectable("Clear")
            imgui.end_popup()
        imgui.end()

        imgui.end_frame()

        imgui.render()

        self.renderer.render(imgui.get_draw_data())
Ejemplo n.º 9
0
    def draw(self):
        imgui.new_frame()

        imgui.set_next_window_position(16, 32, imgui.ONCE)
        imgui.set_next_window_size(512, 512, imgui.ONCE)

        imgui.begin("Example: popup context view")
        imgui.text("Right-click to set value.")
        if imgui.begin_popup_context_item("Item Context Menu", mouse_button=0):
            imgui.selectable("Set to Zero")
            imgui.end_popup()
        imgui.end()

        imgui.end_frame()

        imgui.render()

        self.renderer.render(imgui.get_draw_data())
Ejemplo n.º 10
0
    def draw(self):
        imgui.new_frame()

        imgui.set_next_window_position(16, 32, imgui.ONCE)
        imgui.set_next_window_size(512, 512, imgui.ONCE)

        imgui.begin("Example: simple popup modal")

        if imgui.button("Open Modal popup"):
            imgui.open_popup("select-popup")

        imgui.same_line()

        if imgui.begin_popup_modal("select-popup")[0]:
            imgui.text("Select an option:")
            imgui.separator()
            imgui.selectable("One")
            imgui.selectable("Two")
            imgui.selectable("Three")
            imgui.end_popup()

        imgui.end()

        imgui.end_frame()

        imgui.render()

        self.renderer.render(imgui.get_draw_data())
Ejemplo n.º 11
0
    def _show_custom_ui(self):
        selected_name = self.get("name")
        preview = selected_name if selected_name else "<none>"
        if imgui.begin_combo("", preview):
            is_selected = not selected_name
            opened, selected = imgui.selectable("<none>", is_selected)
            if opened:
                self.get_input("name").value = ""
                self._value = None
            if is_selected:
                imgui.set_item_default_focus()
            imgui.separator()

            for name, value in values_by_dtype.get(self.DTYPE, []):
                is_selected = name == selected_name
                opened, selected = imgui.selectable(name, is_selected)
                if opened:
                    self.get_input("name").value = name
                    self._value = value
                if is_selected:
                    imgui.set_item_default_focus()
            imgui.end_combo()
Ejemplo n.º 12
0
    def displayGameObjectOnHierarchy(self, obj):
        if len(obj.childs) <= 0:
            if imgui.selectable(obj.name)[1]:
                self.curControlObject = obj
        else:
            object_layer = imgui.tree_node(obj.name,
                                           flags=imgui.TREE_NODE_OPEN_ON_ARROW)
            clicked = imgui.is_item_clicked()
            if clicked:
                self.curControlObject = obj

            if object_layer:
                for childObj in obj.childs:
                    self.displayGameObjectOnHierarchy(childObj)
                imgui.tree_pop()
Ejemplo n.º 13
0
    def _show_custom_ui(self):
        current_device_name = "<none>"
        if self._device is not None:
            current_device_name = self._device.name

        imgui.push_item_width(150)
        if imgui.begin_combo("", current_device_name):
            for device_name in mido.get_input_names():
                is_selected = device_name == current_device_name
                opened, selected = imgui.selectable(device_name, is_selected)
                if opened:
                    self.connect(device_name)
                if is_selected:
                    imgui.set_item_default_focus()
            imgui.end_combo()
Ejemplo n.º 14
0
    def draw(self):    
        imgui.begin(self.title)

        if imgui.listbox_header("Custom List", 200, 100):
            for option in OPTIONS:
                clicked, selected = imgui.selectable(option, option == self.selected)
                if clicked:
                    self.selected = option

            imgui.listbox_footer()

        imgui.text("selection: ")
        imgui.same_line()
        imgui.text(self.selected)

        imgui.end()
Ejemplo n.º 15
0
    def do_gui(self):
        imgui.new_frame()

        imgui.set_next_window_position(self.width, 0, pivot_x=1.0)
        imgui.begin("win",
                    closable=False,
                    flags=imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_MOVE
                    | imgui.WINDOW_NO_RESIZE)

        changed, self.time_per_div_selected = imgui.combo(
            "TIME/DIV", self.time_per_div_selected,
            [str(option) for option in TIME_PER_DIV_OPTIONS])
        if changed:
            self.time_per_div = TIME_PER_DIV_OPTIONS[
                self.time_per_div_selected]

        changed, self.y_per_div_selected = imgui.combo(
            "Y/DIV", self.y_per_div_selected,
            [str(option) for option in Y_PER_DIV_OPTIONS])
        if changed:
            self.y_per_div = Y_PER_DIV_OPTIONS[self.y_per_div_selected]

        imgui.text("Values")
        for addr in self.addresses:
            color_changed = False
            if addr in self.lines:
                # Change text color to indicate the color of plot
                r, g, b = self.line_colors[addr]
                imgui.push_style_color(imgui.COLOR_TEXT, r, g, b)
                color_changed = True

            changed, selected = imgui.selectable(addr, addr in self.lines)
            if changed and selected:
                self.lines[addr] = collections.deque(maxlen=MAX_POINTS)
            elif changed and not selected:
                del self.lines[addr]

            if color_changed:
                imgui.pop_style_color()

        self.gui_width = imgui.get_window_width()

        imgui.end()

        # imgui.render() in on_draw caused a "newFrame is not called" error on Windows,
        # therefore we invoke it here
        imgui.render()
Ejemplo n.º 16
0
    def _show_custom_ui(self):
        imgui.dummy(0, 10)
        imgui.text("Sourced %d blocks" % self.blocks)

        sinks = self.pulse.sinks
        current_sink_index = self.pulse.current_sink_index
        current_sink_name = sinks.get(current_sink_index, "<unknown>")
        #print("Unkown sink %s out of %s" % (repr(current_sink_index), sinks))

        imgui.push_item_width(250)
        if imgui.begin_combo("", current_sink_name):
            for index, sink_name in sinks.items():
                is_selected = index == current_sink_index
                opened, selected = imgui.selectable(sink_name, is_selected)
                if opened:
                    self.pulse.current_sink_index = index
                if is_selected:
                    imgui.set_item_default_focus()
            imgui.end_combo()
Ejemplo n.º 17
0
    def draw_navbar(self):
        imgui.set_next_window_position(16, 32, imgui.ONCE)
        imgui.set_next_window_size(256, 732, imgui.ONCE)

        imgui.begin("Examples")

        titles = [page['title'] for page in self.window.pages.values()]
        names = [page['name'] for page in self.window.pages.values()]

        if imgui.listbox_header("Examples", -1, -1):

            for entry in self.window.pages.values():
                opened, selected = imgui.selectable(
                    entry['title'], entry['name'] == self.window.page.name)
                if opened:
                    self.window.show(entry['name'])

            imgui.listbox_footer()

        imgui.end()
Ejemplo n.º 18
0
    def render(self, time: float, frametime: float):
        global selected_symbol
        global input_text
        self.candlestick_chart.render()
        imgui.new_frame()
        if imgui.begin_main_menu_bar():
            if imgui.begin_menu("File", True):
                clicked_quit, selected_quit = imgui.menu_item(
                    "Quit", 'Cmd+Q', False, True
                )
                if clicked_quit:
                    exit(1)
                imgui.end_menu()
            changed, value = imgui.input_text("", input_text, 30)
            if changed:
                imgui.set_next_window_position(imgui.get_item_rect_min().x,
                                               imgui.get_item_rect_max().y)
                imgui.set_next_window_size(imgui.get_item_rect_size().x, 0)
                if imgui.begin("##popup", False,
                               imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE):
                    for index, row in symbol_list.iterrows():
                        if value.upper() in row[0]:
                            opened, selected = imgui.selectable(row[0] + " - " + row[2])
                            if imgui.is_item_clicked():
                                input_text = row[0]
                                selected_symbol = row[0]
                imgui.end()
            if imgui.button("download"):
                yfc.download(selected_symbol, symbol_data_file())
            imgui.end_main_menu_bar()

        if not imgui.get_io().want_capture_mouse:
            self.candlestick_chart.render_gui()
        # if len(df):
        #     graphics.draw_table(df, 0)

        imgui.show_test_window()

        imgui.render()
        self.imgui.render(imgui.get_draw_data())
Ejemplo n.º 19
0
    def draw(self):
        imgui.begin("Example: simple popup")

        if imgui.button("select"):
            imgui.open_popup("select-popup")

        imgui.same_line()

        if imgui.begin_popup("select-popup"):
            imgui.text("Select one")
            imgui.separator()
            imgui.selectable("One")
            imgui.selectable("Two")
            imgui.selectable("Three")
            imgui.end_popup()

        imgui.end()
Ejemplo n.º 20
0
    def draw(self):
        imgui.begin("Example: simple popup modal")

        if imgui.button("Open Modal popup"):
            imgui.open_popup("select-popup")

        imgui.same_line()

        if imgui.begin_popup_modal("select-popup")[0]:
            imgui.text("Select an option:")
            imgui.separator()
            imgui.selectable("One")
            imgui.selectable("Two")
            imgui.selectable("Three")
            imgui.end_popup()

        imgui.end()
Ejemplo n.º 21
0
                        controller_name == controller_type)

                    if clicked:
                        controller_name = controller_type
                        assemble_controller()

                imgui.end_menu()
            imgui.end_main_menu_bar()

        #imgui.show_demo_window()

        imgui.begin("Available GPIO Pins")

        for pin in available_pins:
            if pin[2]:
                imgui.selectable("GPIO #" + str(pin[0]) + ", BCM #" +
                                 str(pin[1]) + " (Hardware PWM)")
            else:
                imgui.selectable("GPIO #" + str(pin[0]) + ", BCM #" +
                                 str(pin[1]))

            if imgui.begin_drag_drop_source():
                imgui.set_drag_drop_payload("pin", str(pin).encode())
                if pin[2]:
                    imgui.text("GPIO #" + str(pin[0]) + ", BCM #" +
                               str(pin[1]) + " (Hardware PWM)")
                else:
                    imgui.text("GPIO #" + str(pin[0]) + ", BCM #" +
                               str(pin[1]))
                imgui.end_drag_drop_source()

        imgui.end()
Ejemplo n.º 22
0
def frame_commands():
    io = imgui.get_io()

    if io.key_ctrl and io.keys_down[glfw.KEY_Q]:
        sys.exit(0)

    with imgui.begin_main_menu_bar() as main_menu_bar:
        if main_menu_bar.opened:
            with imgui.begin_menu("File", True) as file_menu:
                if file_menu.opened:
                    clicked_quit, selected_quit = imgui.menu_item(
                        "Quit", "Ctrl+Q")
                    if clicked_quit:
                        sys.exit(0)

    # turn examples on/off
    with imgui.begin("Active examples"):
        for label, enabled in active.copy().items():
            _, enabled = imgui.checkbox(label, enabled)
            active[label] = enabled

    if active["window"]:
        with imgui.begin("Hello, Imgui!"):
            imgui.text("Hello, World!")

    if active["child"]:
        with imgui.begin("Example: child region"):
            with imgui.begin_child("region", 150, -50, border=True):
                imgui.text("inside region")
            imgui.text("outside region")

    if active["tooltip"]:
        with imgui.begin("Example: tooltip"):
            imgui.button("Click me!")
            if imgui.is_item_hovered():
                with imgui.begin_tooltip():
                    imgui.text("This button is clickable.")

    if active["menu bar"]:
        try:
            flags = imgui.WINDOW_MENU_BAR
            with imgui.begin("Child Window - File Browser", flags=flags):
                with imgui.begin_menu_bar() as menu_bar:
                    if menu_bar.opened:
                        with imgui.begin_menu('File') as file_menu:
                            if file_menu.opened:
                                clicked, state = imgui.menu_item('Close')
                                if clicked:
                                    active["menu bar"] = False
                                    raise Exception
        except Exception:
            print("exception handled")

    if active["popup"]:
        with imgui.begin("Example: simple popup"):
            if imgui.button("select"):
                imgui.open_popup("select-popup")
            imgui.same_line()
            with imgui.begin_popup("select-popup") as popup:
                if popup.opened:
                    imgui.text("Select one")
                    imgui.separator()
                    imgui.selectable("One")
                    imgui.selectable("Two")
                    imgui.selectable("Three")

    if active["popup modal"]:
        with imgui.begin("Example: simple popup modal"):
            if imgui.button("Open Modal popup"):
                imgui.open_popup("select-popup-modal")
            imgui.same_line()
            with imgui.begin_popup_modal("select-popup-modal") as popup:
                if popup.opened:
                    imgui.text("Select an option:")
                    imgui.separator()
                    imgui.selectable("One")
                    imgui.selectable("Two")
                    imgui.selectable("Three")

    if active["popup context item"]:
        with imgui.begin("Example: popup context view"):
            imgui.text("Right-click to set value.")
            with imgui.begin_popup_context_item("Item Context Menu") as popup:
                if popup.opened:
                    imgui.selectable("Set to Zero")

    if active["popup context window"]:
        with imgui.begin("Example: popup context window"):
            with imgui.begin_popup_context_window() as popup:
                if popup.opened:
                    imgui.selectable("Clear")

    if active["popup context void"]:
        with imgui.begin_popup_context_void() as popup:
            if popup.opened:
                imgui.selectable("Clear")

    if active["drag drop"]:
        with imgui.begin("Example: drag and drop"):
            imgui.button('source')
            with imgui.begin_drag_drop_source() as src:
                if src.dragging:
                    imgui.set_drag_drop_payload('itemtype', b'payload')
                    imgui.button('dragged source')
            imgui.button('dest')
            with imgui.begin_drag_drop_target() as dst:
                if dst.hovered:
                    payload = imgui.accept_drag_drop_payload('itemtype')
                    if payload is not None:
                        print('Received:', payload)

    if active["group"]:
        with imgui.begin("Example: item groups"):
            with imgui.begin_group():
                imgui.text("First group (buttons):")
                imgui.button("Button A")
                imgui.button("Button B")
            imgui.same_line(spacing=50)
            with imgui.begin_group():
                imgui.text("Second group (text and bullet texts):")
                imgui.bullet_text("Bullet A")
                imgui.bullet_text("Bullet B")

    if active["tab bar"]:
        with imgui.begin("Example Tab Bar"):
            with imgui.begin_tab_bar("MyTabBar") as tab_bar:
                if tab_bar.opened:
                    with imgui.begin_tab_item("Item 1") as item1:
                        if item1.opened:
                            imgui.text("Here is the tab content!")
                    with imgui.begin_tab_item("Item 2") as item2:
                        if item2.opened:
                            imgui.text("Another content...")
                    global opened_state
                    with imgui.begin_tab_item("Item 3",
                                              opened=opened_state) as item3:
                        opened_state = item3.opened
                        if item3.selected:
                            imgui.text("Hello Saylor!")

    if active["list box"]:
        with imgui.begin("Example: custom listbox"):
            with imgui.begin_list_box("List", 200, 100) as list_box:
                if list_box.opened:
                    imgui.selectable("Selected", True)
                    imgui.selectable("Not Selected", False)

    if active["table"]:
        with imgui.begin("Example: table"):
            with imgui.begin_table("data", 2) as table:
                if table.opened:
                    imgui.table_next_column()
                    imgui.table_header("A")
                    imgui.table_next_column()
                    imgui.table_header("B")

                    imgui.table_next_row()
                    imgui.table_next_column()
                    imgui.text("123")

                    imgui.table_next_column()
                    imgui.text("456")

                    imgui.table_next_row()
                    imgui.table_next_column()
                    imgui.text("789")

                    imgui.table_next_column()
                    imgui.text("111")

                    imgui.table_next_row()
                    imgui.table_next_column()
                    imgui.text("222")

                    imgui.table_next_column()
                    imgui.text("333")
Ejemplo n.º 23
0
 def draw(self):
     imgui.begin("Example: popup context window")
     if imgui.begin_popup_context_window():
         imgui.selectable("Clear")
         imgui.end_popup()
     imgui.end()
Ejemplo n.º 24
0
def double_click_listbox(state: tuple,
                         options: Sequence[str]) -> Tuple[bool, bool, tuple]:
    """
	Good for item-pickers where only one item can be selected, like tool pickers.
	Offers a similar API to imgui.listbox, with important differences:
	- Only one item selected at a time
	- Allows double-clicks on items, and distinguishes them
	  from single clicks

	Takes a tuple representing the selection state (explained further)
	and a sequence of string labels, and returns a triple: 
	```
		state_changed: bool, 	# Anything in the state changed:
								# for example, stopped waiting for second click
								# and switched `('waiting', ix, t) -> ('idle', ix)`
								# Useful to know if you should update the stored state.

		selection_changed: bool # The selected item changed:
								# stays false e.g when the list stops waiting for the
								# second click, that is on changes `('waiting', ix, t) -> ('idle', ix)`
								# Useful to know if the selection changed.
		new selection state: tuple  # Explained below.
	```
	The selection state is a normal tuple of one of the following shapes: 
	```
	('no_selection',   None)
	('idle', 		   int)			# item selected, not waiting for double-click
	('waiting', 	   int, float)	# item selected, but the user might click a second time, creating a double-click
	('double_clicked', int)			# item at index was double-clicked
	#				   ^ state[1]: the index of the selected item in `options`
	#					    ^ state [2]: the time (in seconds) of the click

	```
	prev_state = my_global_state['tool_picker_state']

	opts = ['first', 'second', 'third']
	state_changed, selection_changed, state = double_click_listbox(prev_state, opts)
	if state_changed:
		my_global_state['tool_picker_state'] = state

	if state[0] == 'double_clicked':
		_, ix = state
		... # ix was double-clicked 
	elif selection_changed:
		_, ix = state
		... # ix was selected


	
	The initial state for a `double_click_listbox is usually `('no_selection', None)`,
	or `('idle', ix)` if ix should be selected by default.

	"""
    prev_state = state
    prev_variant = prev_state[0]
    prev_o_selection = prev_state[1]

    changed_option = None
    for ix, option in enumerate(options):
        was_selected = prev_o_selection is not None and prev_o_selection == ix
        changed, selected = im.selectable(option, was_selected)

        if changed:
            changed_option = (ix, selected)

    # Now we know which one (if any) changed and how
    # Time to work those state machines!
    state = None

    if prev_variant == 'no_selection':
        if changed_option is None:
            state = prev_state
        else:
            ix, _ = changed_option
            state = ('waiting', ix, im.get_time())

    elif prev_variant == 'idle':
        if changed_option is None:
            state = prev_state
        else:
            ix, selected = changed_option
            state = ('waiting', ix, im.get_time())

    elif prev_variant == 'waiting':
        _, prev_selection, selected_t = prev_state
        current_t = im.get_time()
        time_is_up = current_t - selected_t >= im.get_io(
        ).mouse_double_click_time
        if changed_option is None:
            if time_is_up:
                state = ('idle', prev_selection)
            else:
                state = prev_state
        else:  # changed_option is not None
            ix, selected = changed_option
            if time_is_up:
                if ix == prev_selection:
                    # start waiting again
                    state = ('waiting', prev_selection, current_t)
                else:  # ix != prev_selection
                    state = ('waiting', ix, current_t)
            else:  # not time_is_up
                if ix == prev_selection:
                    assert not selected
                    state = ('double_clicked', prev_selection)
                else:  # ix != prev_selection
                    state = ('waiting', ix, current_t)

    elif prev_variant == 'double_clicked':
        _, prev_selection = prev_state
        state = ('idle', prev_selection)

    else:
        raise Exception("Invalid state (see this function's help): " +
                        str(prev_state))

    selection_changed = state[1] != prev_state[1]
    state_changed = state != prev_state
    return state_changed, selection_changed, state