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 createdmain
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