viewplex.fnl (4889B)
1 (local { : Gtk : Gdk : WebKit2 : cairo } (require :lgi)) 2 3 (local Webview (require :just.webview)) 4 (local Listeners (require :just.listeners)) 5 6 (local thumbnail-width 300) 7 (local thumbnail-height 200) 8 9 (fn on-fake-swipe [widget fun] 10 ;; this is here for testing on desktop systems that don't 11 ;; have touch support 12 (Gtk.GestureLongPress { 13 :widget widget 14 :on_pressed fun 15 })) 16 17 (fn on-swipe [widget fun] 18 (if (os.getenv "JUST_HACKING") (on-fake-swipe widget fun)) 19 20 (Gtk.GestureSwipe { 21 :widget widget 22 :on_update 23 (fn [self] 24 (self:set_state Gtk.EventSequenceState.CLAIMED)) 25 :on_swipe 26 (fn [self x y] 27 (if (and (< 700 x) (< y 700)) 28 (fun) 29 (self:set_state Gtk.EventSequenceState.DENIED)) 30 true) 31 })) 32 33 (fn refresh-overview [self scrolledwindow views] 34 (let [box (Gtk.Box { 35 :orientation Gtk.Orientation.VERTICAL 36 })] 37 38 (each [_ w (ipairs (scrolledwindow:get_children))] 39 (scrolledwindow:remove w)) 40 41 (each [i w (pairs views)] 42 (box:pack_start 43 (let [b (Gtk.Button { 44 :label w.properties.title 45 :width thumbnail-width 46 :height thumbnail-height 47 :image-position Gtk.PositionType.TOP 48 :on_clicked #(self:focus-view w) 49 })] 50 (on-swipe b #(self:remove-view w)) 51 (w:thumbnail-image thumbnail-width thumbnail-height #(b:set_image $1)) 52 b) 53 false false 5)) 54 55 (box:pack_start (Gtk.Button 56 { 57 :label " + " 58 :width 300 59 :height 200 60 :on_clicked (fn [] 61 (self:add-view 62 (doto (Webview.new 63 {:content-filter-store self.content-filter-store}) 64 (: :visit "about:blank")))) 65 }) 66 false false 5) 67 68 (scrolledwindow:add box) 69 (scrolledwindow:show_all) 70 )) 71 72 73 { 74 :new 75 (fn [{: content-filter-store}] 76 (var foreground-view nil) 77 (let [listeners (Listeners.new) 78 relay-events [] 79 widget (Gtk.Notebook { 80 :show_tabs false 81 }) 82 overview (Gtk.ScrolledWindow) 83 overview-page-num (widget:append_page overview) 84 relay-event (fn [source event-name] 85 (source:listen 86 event-name 87 #(if (= source foreground-view) 88 (listeners:notify event-name $1)))) 89 views {}] 90 { 91 :content-filter-store content-filter-store 92 :listen (fn [_ name fun] 93 (if (not (. relay-events name)) 94 (each [_ v (pairs views)] 95 (relay-event v name))) 96 (table.insert relay-events name) 97 (listeners:add name fun)) 98 99 :widget widget 100 101 :add-view (fn [self webview] 102 (webview.widget:show) 103 (each [_ event-name (ipairs relay-events)] 104 (relay-event webview event-name)) 105 (let [page (widget:append_page webview.widget)] 106 (tset views page webview) 107 (self:focus-view webview) 108 page)) 109 110 :remove-view (fn [self view] 111 (let [page (widget:page_num view.widget)] 112 (tset views page nil) 113 (widget:remove_page page) 114 (self:show-overview) 115 )) 116 117 :focus-view (fn [self view] 118 (when view 119 (set foreground-view view) 120 (each [_ prop (ipairs relay-events)] 121 (listeners:notify prop (. view.properties prop))) 122 (tset self :properties view.properties) 123 (set widget.page (widget:page_num view.widget)))) 124 125 :show-overview (fn [self] 126 (set foreground-view nil) 127 (set widget.page overview-page-num) 128 (refresh-overview self overview views)) 129 130 :visit #(and foreground-view (foreground-view:visit $2)) 131 :stop-loading #(and foreground-view 132 (foreground-view:stop-loading)) 133 :refresh #(and foreground-view (foreground-view:refresh)) 134 :go-back #(and foreground-view (foreground-view:go-back)) 135 } 136 ))}