make keyboard completions work
1. When adding a button to flowbox, the flowbox widget interposes a flowboxchild between the two, which can receive events and so becomes part of the tab order. this is why our buttons weren't getting activated - they weren't focused even though they looked focused. So, use labels instead of buttons for completions 2. For some reason I don't understand, flowboxchild widgets receive :activate *only* on keyboard activation. So instead of using it, we connect to :child-activated on the flowbox. 3. Setting widget:on_foo *adds* a handler to the widget instead of replacing what was previously there. There is no nice way to remove handlers from a widget either. Because we need a new on_child_activated handler every time the completions change, the only way I can see to achieve this is to create the flowbox afresh on each keystroke instead of creating it once when the frame is created
This commit is contained in:
parent
d76769752b
commit
a5a65006ca
39
command.fnl
39
command.fnl
|
@ -20,7 +20,7 @@
|
|||
(fn completion [{: widget : text : value }]
|
||||
(let [value (or value (assert text "must have text"))]
|
||||
{
|
||||
:widget (or widget (Gtk.Button { :label text }))
|
||||
:widget (or widget (Gtk.Label { :label text }))
|
||||
: text
|
||||
: value
|
||||
}))
|
||||
|
@ -52,7 +52,7 @@
|
|||
(icollect [v (_G.history:find-distinct term)]
|
||||
(let [label (.. v.url " " (or v.title ""))]
|
||||
(completion { :text v.url
|
||||
:widget (Gtk.Button { : label })
|
||||
:widget (Gtk.Label { : label })
|
||||
:value v.url
|
||||
})))
|
||||
[])]
|
||||
|
@ -147,6 +147,8 @@
|
|||
(if (not result.active)
|
||||
(completions-widget:hide))
|
||||
(set entry.text (or result.default result.error ""))
|
||||
(if result.active (entry:grab_focus))
|
||||
|
||||
(when widget.parent
|
||||
(widget.parent:set_visible_child_name
|
||||
(if result.active "commander" "echo-area"))))
|
||||
|
@ -155,14 +157,29 @@
|
|||
(let [parent self.completions-widget
|
||||
set-completions
|
||||
(fn [completions]
|
||||
(parent:foreach #(parent:remove $1))
|
||||
(each [_ c (pairs completions)]
|
||||
(parent:add
|
||||
(doto c.widget
|
||||
(tset :on_clicked
|
||||
#(update-widget-state
|
||||
self
|
||||
(self:on-input-finished c.text))))))
|
||||
(let [flowbox (Gtk.FlowBox {
|
||||
:activate_on_single_click true
|
||||
:selection_mode Gtk.SelectionMode.SINGLE
|
||||
})
|
||||
;; I don't know why, but the flowboxchild activate signal
|
||||
;; is working only for keyboard activation not for
|
||||
;; clicking. So instead of using it we connect to
|
||||
;; child_activated, and use kids-map to find out which
|
||||
;; child it was
|
||||
kids-map {}]
|
||||
(parent:foreach #(parent:remove $1)) ; expect only 1 direct child
|
||||
(each [_ c (pairs completions)]
|
||||
(let [fbc (Gtk.FlowBoxChild)]
|
||||
(tset kids-map fbc c.text)
|
||||
(fbc:add c.widget)
|
||||
(flowbox:add fbc)))
|
||||
(tset flowbox :on_child_activated
|
||||
(fn [_self child]
|
||||
(match (. kids-map child)
|
||||
text (update-widget-state
|
||||
self
|
||||
(self:on-input-finished text)))))
|
||||
(parent:add flowbox))
|
||||
(parent:show_all))]
|
||||
(match self.state
|
||||
{:command c :this-param param-name}
|
||||
|
@ -210,7 +227,7 @@
|
|||
prompt (Gtk.Label { :label ""})
|
||||
box (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })
|
||||
hbox (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL })
|
||||
completions (Gtk.FlowBox)
|
||||
completions (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })
|
||||
self {
|
||||
:state default-state
|
||||
: activate
|
||||
|
|
|
@ -66,18 +66,20 @@ focus from entry to step through the completions then RET activates
|
|||
* [done] back binding
|
||||
* [done] save url history, use it in completions
|
||||
* [done] autocomplete command name
|
||||
* [done] keyboard navigation of completions
|
||||
|
||||
* custom rendering for completions (e.g. buffer thumbnails)
|
||||
* less ugly default completions rendering
|
||||
* buffer name is often going to be useless. find buffers by url/title
|
||||
still need some 1:1 mapping between the buffer object and
|
||||
a text-representable form of same
|
||||
* bind event to echo-area click, ideally dependent on what's being shown
|
||||
in there
|
||||
* bind event to echo-area click, ideally dependent on what's being shown in there
|
||||
* in general, can we bind commands to widget events?
|
||||
* command to create new buffer
|
||||
* keyboard navigation of completions
|
||||
|
||||
* suppress "Return is undefined" message after a command executes
|
||||
|
||||
----
|
||||
|
||||
can we increase the testability? e.g. for command processing,
|
||||
define a command, feed in some keystrokes,
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
(completion {
|
||||
:text keyword
|
||||
:value keyword
|
||||
:widget (Gtk.Button { :label name })
|
||||
:widget (Gtk.Label { :label name })
|
||||
}))))
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue