(local { : Gtk : Gdk : WebKit2 : cairo } (require :lgi)) (local Webview (require :just.webview)) (local Listeners (require :just.listeners)) (local thumbnail-width 300) (local thumbnail-height 200) (fn on-fake-swipe [widget fun] ;; this is here for testing on desktop systems that don't ;; have touch support (Gtk.GestureLongPress { :widget widget :on_pressed fun })) (fn on-swipe [widget fun] (if (os.getenv "JUST_HACKING") (on-fake-swipe widget fun)) (Gtk.GestureSwipe { :widget widget :on_update (fn [self] (self:set_state Gtk.EventSequenceState.CLAIMED)) :on_swipe (fn [self x y] (if (and (< 700 x) (< y 700)) (fun) (self:set_state Gtk.EventSequenceState.DENIED)) true) })) (fn refresh-overview [self scrolledwindow views] (let [box (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })] (each [_ w (ipairs (scrolledwindow:get_children))] (scrolledwindow:remove w)) (each [i w (pairs views)] (box:pack_start (let [b (Gtk.Button { :label w.properties.title :width thumbnail-width :height thumbnail-height :image-position Gtk.PositionType.TOP :on_clicked #(self:focus-view w) })] (on-swipe b #(self:remove-view w)) (w:thumbnail-image thumbnail-width thumbnail-height #(b:set_image $1)) b) false false 5)) (box:pack_start (Gtk.Button { :label " + " :width 300 :height 200 :on_clicked (fn [] (self:add-view (doto (Webview.new {:content-filter-store self.content-filter-store}) (: :visit "about:blank")))) }) false false 5) (scrolledwindow:add box) (scrolledwindow:show_all) )) { :new (fn [{: content-filter-store}] (var foreground-view nil) (let [listeners (Listeners.new) relay-events [] widget (Gtk.Notebook { :show_tabs false }) overview (Gtk.ScrolledWindow) overview-page-num (widget:append_page overview) relay-event (fn [source event-name] (source:listen event-name #(if (= source foreground-view) (listeners:notify event-name $1)))) views {}] { :content-filter-store content-filter-store :listen (fn [_ name fun] (if (not (. relay-events name)) (each [_ v (pairs views)] (relay-event v name))) (table.insert relay-events name) (listeners:add name fun)) :widget widget :add-view (fn [self webview] (webview.widget:show) (each [_ event-name (ipairs relay-events)] (relay-event webview event-name)) (let [page (widget:append_page webview.widget)] (tset views page webview) (self:focus-view webview) page)) :remove-view (fn [self view] (let [page (widget:page_num view.widget)] (tset views page nil) (widget:remove_page page) (self:show-overview) )) :focus-view (fn [self view] (when view (set foreground-view view) (each [_ prop (ipairs relay-events)] (listeners:notify prop (. view.properties prop))) (tset self :properties view.properties) (set widget.page (widget:page_num view.widget)))) :show-overview (fn [self] (set foreground-view nil) (set widget.page overview-page-num) (refresh-overview self overview views)) :visit #(and foreground-view (foreground-view:visit $2)) :stop-loading #(and foreground-view (foreground-view:stop-loading)) :refresh #(and foreground-view (foreground-view:refresh)) :go-back #(and foreground-view (foreground-view:go-back)) } ))}