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 }]
|
(fn completion [{: widget : text : value }]
|
||||||
(let [value (or value (assert text "must have text"))]
|
(let [value (or value (assert text "must have text"))]
|
||||||
{
|
{
|
||||||
:widget (or widget (Gtk.Button { :label text }))
|
:widget (or widget (Gtk.Label { :label text }))
|
||||||
: text
|
: text
|
||||||
: value
|
: value
|
||||||
}))
|
}))
|
||||||
@ -52,7 +52,7 @@
|
|||||||
(icollect [v (_G.history:find-distinct term)]
|
(icollect [v (_G.history:find-distinct term)]
|
||||||
(let [label (.. v.url " " (or v.title ""))]
|
(let [label (.. v.url " " (or v.title ""))]
|
||||||
(completion { :text v.url
|
(completion { :text v.url
|
||||||
:widget (Gtk.Button { : label })
|
:widget (Gtk.Label { : label })
|
||||||
:value v.url
|
:value v.url
|
||||||
})))
|
})))
|
||||||
[])]
|
[])]
|
||||||
@ -147,6 +147,8 @@
|
|||||||
(if (not result.active)
|
(if (not result.active)
|
||||||
(completions-widget:hide))
|
(completions-widget:hide))
|
||||||
(set entry.text (or result.default result.error ""))
|
(set entry.text (or result.default result.error ""))
|
||||||
|
(if result.active (entry:grab_focus))
|
||||||
|
|
||||||
(when widget.parent
|
(when widget.parent
|
||||||
(widget.parent:set_visible_child_name
|
(widget.parent:set_visible_child_name
|
||||||
(if result.active "commander" "echo-area"))))
|
(if result.active "commander" "echo-area"))))
|
||||||
@ -155,14 +157,29 @@
|
|||||||
(let [parent self.completions-widget
|
(let [parent self.completions-widget
|
||||||
set-completions
|
set-completions
|
||||||
(fn [completions]
|
(fn [completions]
|
||||||
(parent:foreach #(parent:remove $1))
|
(let [flowbox (Gtk.FlowBox {
|
||||||
(each [_ c (pairs completions)]
|
:activate_on_single_click true
|
||||||
(parent:add
|
:selection_mode Gtk.SelectionMode.SINGLE
|
||||||
(doto c.widget
|
})
|
||||||
(tset :on_clicked
|
;; I don't know why, but the flowboxchild activate signal
|
||||||
#(update-widget-state
|
;; is working only for keyboard activation not for
|
||||||
self
|
;; clicking. So instead of using it we connect to
|
||||||
(self:on-input-finished c.text))))))
|
;; 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))]
|
(parent:show_all))]
|
||||||
(match self.state
|
(match self.state
|
||||||
{:command c :this-param param-name}
|
{:command c :this-param param-name}
|
||||||
@ -210,7 +227,7 @@
|
|||||||
prompt (Gtk.Label { :label ""})
|
prompt (Gtk.Label { :label ""})
|
||||||
box (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })
|
box (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })
|
||||||
hbox (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL })
|
hbox (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL })
|
||||||
completions (Gtk.FlowBox)
|
completions (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })
|
||||||
self {
|
self {
|
||||||
:state default-state
|
:state default-state
|
||||||
: activate
|
: activate
|
||||||
|
@ -66,18 +66,20 @@ focus from entry to step through the completions then RET activates
|
|||||||
* [done] back binding
|
* [done] back binding
|
||||||
* [done] save url history, use it in completions
|
* [done] save url history, use it in completions
|
||||||
* [done] autocomplete command name
|
* [done] autocomplete command name
|
||||||
|
* [done] keyboard navigation of completions
|
||||||
|
|
||||||
* custom rendering for completions (e.g. buffer thumbnails)
|
* custom rendering for completions (e.g. buffer thumbnails)
|
||||||
* less ugly default completions rendering
|
* less ugly default completions rendering
|
||||||
* buffer name is often going to be useless. find buffers by url/title
|
* buffer name is often going to be useless. find buffers by url/title
|
||||||
still need some 1:1 mapping between the buffer object and
|
still need some 1:1 mapping between the buffer object and
|
||||||
a text-representable form of same
|
a text-representable form of same
|
||||||
* bind event to echo-area click, ideally dependent on what's being shown
|
* bind event to echo-area click, ideally dependent on what's being shown in there
|
||||||
in there
|
|
||||||
* in general, can we bind commands to widget events?
|
* in general, can we bind commands to widget events?
|
||||||
* command to create new buffer
|
* command to create new buffer
|
||||||
* keyboard navigation of completions
|
|
||||||
|
|
||||||
* suppress "Return is undefined" message after a command executes
|
* 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 {
|
(completion {
|
||||||
:text keyword
|
:text keyword
|
||||||
:value keyword
|
:value keyword
|
||||||
:widget (Gtk.Button { :label name })
|
:widget (Gtk.Label { :label name })
|
||||||
}))))
|
}))))
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user