add ability to extend desktop to popups/tabs

This commit is contained in:
David Botton 2024-04-09 23:48:34 -04:00
parent a5544de767
commit d3842c8e0d
4 changed files with 104 additions and 54 deletions

View file

@ -55,6 +55,7 @@
(window-content generic-function) (window-content generic-function)
(window-focus generic-function) (window-focus generic-function)
(window-close generic-function) (window-close generic-function)
(window-valid-p function)
(window-maximized-p generic-function) (window-maximized-p generic-function)
(window-maximize generic-function) (window-maximize generic-function)
(window-normalize generic-function) (window-normalize generic-function)
@ -130,12 +131,8 @@
;; Implementation - clog-gui - Desktop GUI abstraction ;; Implementation - clog-gui - Desktop GUI abstraction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defclass clog-gui () (defclass clog-gui ()
((body ((current-win
:accessor body
:documentation "Top level access to browser window")
(current-win
:accessor current-win :accessor current-win
:initform nil :initform nil
:documentation "The current window at front") :documentation "The current window at front")
@ -207,7 +204,6 @@
\"clog-gui\". (Private)" \"clog-gui\". (Private)"
(let ((clog-gui (make-instance 'clog-gui))) (let ((clog-gui (make-instance 'clog-gui)))
(setf (connection-data-item clog-body "clog-gui") clog-gui) (setf (connection-data-item clog-body "clog-gui") clog-gui)
(setf (body clog-gui) clog-body)
clog-gui)) clog-gui))
;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;
@ -242,6 +238,7 @@
(body-left-offset 0) (body-left-offset 0)
(body-right-offset 0) (body-right-offset 0)
(use-clog-debugger nil) (use-clog-debugger nil)
(parent-desktop-obj nil)
(w3-css-url "/css/w3.css") (w3-css-url "/css/w3.css")
(jquery-ui-css "/css/jquery-ui.css") (jquery-ui-css "/css/jquery-ui.css")
(jquery-ui "/js/jquery-ui.js")) (jquery-ui "/js/jquery-ui.js"))
@ -249,11 +246,16 @@
If W3-CSS-URL has not been loaded before is installed unless is nil. If W3-CSS-URL has not been loaded before is installed unless is nil.
BODY-LEFT-OFFSET and BODY-RIGHT-OFFSET limit width on maximize. If BODY-LEFT-OFFSET and BODY-RIGHT-OFFSET limit width on maximize. If
use-clog-debugger then a graphical debugger is set for all events. use-clog-debugger then a graphical debugger is set for all events.
parent-desktop-obj is used if this window is a popup or otherwise a
slave of another clog-gui page.
NOTE: use-clog-debugger should not be set for security issues NOTE: use-clog-debugger should not be set for security issues
on non-secure environments." on non-secure environments."
(if parent-desktop-obj
(let ((app (connection-data-item parent-desktop-obj "clog-gui")))
(setf (connection-data-item clog-body "clog-gui") app))
(let ((app (create-clog-gui clog-body))) (let ((app (create-clog-gui clog-body)))
(setf (body-left-offset app) body-left-offset) (setf (body-left-offset app) body-left-offset)
(setf (body-right-offset app) body-right-offset)) (setf (body-right-offset app) body-right-offset)))
(set-on-full-screen-change (html-document clog-body) 'reorient-all-windows) (set-on-full-screen-change (html-document clog-body) 'reorient-all-windows)
(set-on-orientation-change (window clog-body) 'reorient-all-windows) (set-on-orientation-change (window clog-body) 'reorient-all-windows)
(set-on-resize (window clog-body) 'reorient-all-windows) (set-on-resize (window clog-body) 'reorient-all-windows)
@ -302,7 +304,7 @@ create-gui-menu-bar."))
(defmethod menu-bar-height ((obj clog-obj)) (defmethod menu-bar-height ((obj clog-obj))
(let ((app (connection-data-item obj "clog-gui"))) (let ((app (connection-data-item obj "clog-gui")))
(if (menu app) (if (and app (menu app))
(height (menu app)) (height (menu app))
0))) 0)))
@ -326,15 +328,16 @@ create-gui-menu-bar."))
window or nil if not found")) window or nil if not found"))
(defmethod window-to-top-by-title ((obj clog-obj) title) (defmethod window-to-top-by-title ((obj clog-obj) title)
(when title
(let ((app (connection-data-item obj "clog-gui")) (let ((app (connection-data-item obj "clog-gui"))
(r nil)) (r nil))
(maphash (lambda (key value) (maphash (lambda (key value)
(declare (ignore key)) (declare (ignore key))
(when (equalp (window-title value) title) (when (and (equalp (window-title value) title)
(window-focus value) (window-focus value)
(setf r value))) (setf r value))))
(windows app)) (windows app))
r)) r)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; window-to-top-by-param ;; ;; window-to-top-by-param ;;
@ -557,10 +560,12 @@ Only one instance allowed."))
(setf (window-select app) window-select) (setf (window-select app) window-select)
(set-on-change window-select (lambda (obj) (set-on-change window-select (lambda (obj)
(let ((win (gethash (value obj) (windows app)))) (let ((win (gethash (value obj) (windows app))))
(when win (if (window-valid-p win)
(unless (keep-on-top win) (unless (keep-on-top win)
(setf (hiddenp win) nil) (setf (hiddenp win) nil)
(window-focus win)))))) (window-focus win))
(execute window-select (format nil "remove(~A.selectedIndex)"
(script-id window-select)))))))
(when content (when content
(create-option window-select :content content)) (create-option window-select :content content))
window-select)) window-select))
@ -897,9 +902,10 @@ window-to-top-by-param or window-by-param."))
(border-class *default-border-class*) (border-class *default-border-class*)
(title-class *default-title-class*) (title-class *default-title-class*)
(html-id nil)) (html-id nil))
(let ((app (connection-data-item obj "clog-gui"))) (let ((app (connection-data-item obj "clog-gui"))
(body (connection-body obj)))
(unless html-id (unless html-id
(setf html-id (generate-id))) (setf html-id (format nil "~A" (generate-id))))
(when (eql (hash-table-count (windows app)) 0) (when (eql (hash-table-count (windows app)) 0)
;; If previously no open windows reset default position ;; If previously no open windows reset default position
(setf (last-x app) 0) (setf (last-x app) 0)
@ -914,9 +920,9 @@ window-to-top-by-param or window-by-param."))
(setf (last-y app) (menu-bar-height obj))) (setf (last-y app) (menu-bar-height obj)))
(setf top (last-y app)) (setf top (last-y app))
(incf (last-y app) *top-bar-height*) (incf (last-y app) *top-bar-height*)
(when (> top (- (inner-height (window (body app))) (last-y app))) (when (> top (- (inner-height (window body)) (last-y app)))
(setf (last-y app) (menu-bar-height obj)))) (setf (last-y app) (menu-bar-height obj))))
(let ((win (create-child (body app) (let ((win (create-child body
(format nil (format nil
"<div style='position:fixed;top:~Apx;left:~Apx;width:~Apx;height:~Apx; "<div style='position:fixed;top:~Apx;left:~Apx;width:~Apx;height:~Apx;
z-index:~A;visibility:hidden' z-index:~A;visibility:hidden'
@ -959,7 +965,7 @@ window-to-top-by-param or window-by-param."))
(setf (closer win) (attach-as-child win (format nil "~A-closer" html-id))) (setf (closer win) (attach-as-child win (format nil "~A-closer" html-id)))
(setf (sizer win) (attach-as-child win (format nil "~A-sizer" html-id))) (setf (sizer win) (attach-as-child win (format nil "~A-sizer" html-id)))
(setf (content win) (attach-as-child win (format nil "~A-body" html-id))) (setf (content win) (attach-as-child win (format nil "~A-body" html-id)))
(setf (gethash (format nil "~A" html-id) (windows app)) win) (setf (gethash html-id (windows app)) win)
(set-on-click win (lambda (obj) (set-on-click win (lambda (obj)
(declare (ignore obj)) (declare (ignore obj))
(unless (> (modal-count app) 0) (unless (> (modal-count app) 0)
@ -1076,13 +1082,17 @@ window-to-top-by-param or window-by-param."))
(:documentation "Set CLOG-GUI-WINDOW as focused window.")) (:documentation "Set CLOG-GUI-WINDOW as focused window."))
(defmethod window-focus ((obj clog-gui-window)) (defmethod window-focus ((obj clog-gui-window))
(let ((app (connection-data-item obj "clog-gui"))) (let ((app (connection-data-item obj "clog-gui"))
(pop (connection-data-item obj "clog-popup")))
(when app
(unless (keep-on-top obj) (unless (keep-on-top obj)
(when (last-z app) (when (last-z app)
(setf (z-index obj) (incf (last-z app))))) (setf (z-index obj) (incf (last-z app)))))
(when (window-select app) (when (window-select app)
(setf (selectedp (window-select-item obj)) t)) (setf (selectedp (window-select-item obj)) t))
(fire-on-window-change obj app)) (when pop
(focus pop))
(fire-on-window-change obj app)))
obj) obj)
;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;
@ -1105,6 +1115,24 @@ the browser."))
(fire-on-window-close obj))) (fire-on-window-close obj)))
nil) nil)
;;;;;;;;;;;;;;;;;;;;
;; window-valid-p ;;
;;;;;;;;;;;;;;;;;;;;
(defun window-valid-p (obj)
"Returns t if is a valid clog-gui-window. An invalid state
can occur when a popup slave desktop is closed by the OS or the window has
been previously closed. If the obj exists in the internal hash of windows
it is removed."
(when obj
(when (typep obj 'clog-gui-window)
(let* ((app (connection-data-item obj "clog-gui"))
(win (when app
(gethash (html-id obj) (windows app)))))
(when win
(when (connection-data-item win "clog-gui")
obj))))))
;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;
;; window-maximized-p ;; ;; window-maximized-p ;;
;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;
@ -1135,15 +1163,19 @@ the browser."))
(setf (last-y obj) (top obj)) (setf (last-y obj) (top obj))
(setf (last-height obj) (height obj)) (setf (last-height obj) (height obj))
(setf (last-width obj) (width obj))) (setf (last-width obj) (width obj)))
(cond ((connection-data-item obj "clog-popup")
(setf (top obj) (unit :px 0))
(setf (height obj) (inner-height (window (connection-body obj)))))
(t
(setf (top obj) (unit :px (menu-bar-height obj))) (setf (top obj) (unit :px (menu-bar-height obj)))
(setf (height obj)
(- (inner-height (window (connection-body obj))) (menu-bar-height obj)))))
(setf (left obj) (unit :px 0)) (setf (left obj) (unit :px 0))
(setf (width obj) (unit :vw 100)) (setf (width obj) (unit :vw 100))
(setf (left obj) (unit :px (body-left-offset app))) (setf (left obj) (unit :px (body-left-offset app)))
(setf (width obj) (- (width obj) (setf (width obj) (- (width obj)
(body-left-offset app) (body-left-offset app)
(body-right-offset app))) (body-right-offset app)))
(setf (height obj)
(- (inner-height (window (body app))) (menu-bar-height obj)))
(fire-on-window-size-done obj))))) (fire-on-window-size-done obj)))))
;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;
@ -1247,7 +1279,7 @@ interactions. Use window-end-modal to undo."))
(let ((app (connection-data-item obj "clog-gui"))) (let ((app (connection-data-item obj "clog-gui")))
(when (and app (when (and app
(<= (modal-count app) 0)) (<= (modal-count app) 0))
(setf (modal-background app) (create-div (body app) :class "w3-overlay")) (setf (modal-background app) (create-div (connection-body obj) :class "w3-overlay"))
(setf (display (modal-background app)) :block)) (setf (display (modal-background app)) :block))
(incf (modal-count app)) (incf (modal-count app))
(setf (keep-on-top obj) t) (setf (keep-on-top obj) t)

View file

@ -32,15 +32,27 @@
(defun on-open-file-ext (obj &key open-file popup) (defun on-open-file-ext (obj &key open-file popup)
(if (and *open-external-with-emacs* open-file) (if (and *open-external-with-emacs* open-file)
(swank:ed-in-emacs open-file) (swank:ed-in-emacs open-file)
(if *open-external-using-clog-popups*
(let ((pop (open-clog-popup obj
:specs (if (or popup *open-external-source-in-popup*)
"width=640,height=480"
"")
:name "_blank")))
(if pop
(let ((app (connection-data-item obj "builder-app-data")))
(setf (connection-data-item pop "builder-app-data") app)
(clog-gui-initialize pop :parent-desktop-obj obj)
(on-open-file pop :open-file open-file :maximized t))
(on-open-file obj :open-file open-file)))
(open-window (window (connection-body obj)) (open-window (window (connection-body obj))
(if open-file (if open-file
(format nil "/source-editor?open-file=~A" (format nil "/source-editor?open-file=~A"
open-file) open-file)
"/source-editor?open-file=%20") "/source-editor?open-file=%20")
:specs (if (or popup *open-external-in-popup*) :specs (if (or popup *open-external-source-in-popup*)
"width=800,height=600" "width=800,height=600"
"") "")
:name "_blank"))) :name "_blank"))))
(defun on-open-file (obj &key open-file (defun on-open-file (obj &key open-file
(title "New Source Editor") (title "New Source Editor")
@ -299,8 +311,8 @@
(set-on-click m-ntab (lambda (obj) (set-on-click m-ntab (lambda (obj)
(when is-dirty (when is-dirty
(save obj nil)) (save obj nil))
(on-open-file-ext obj :open-file file-name) (window-close win)
(window-close win))) (on-open-file-ext obj :open-file file-name)))
(set-on-window-can-close win (set-on-window-can-close win
(lambda (obj) (lambda (obj)
(cond (is-dirty (cond (is-dirty

View file

@ -12,8 +12,10 @@
;; Open panels and files in new browser tabs by default ;; Open panels and files in new browser tabs by default
(defparameter *open-external* nil) (defparameter *open-external* nil)
;; Use clog-popup and extend desktop to popups
(defparameter *open-external-using-clog-popups* nil)
;; Open files in browser popups instead of tabs if browser allows ;; Open files in browser popups instead of tabs if browser allows
(defparameter *open-external-in-popup* nil) (defparameter *open-external-source-in-popup* nil)
;; Open panel editors in browser popus instead of tabs if browser allows ;; Open panel editors in browser popus instead of tabs if browser allows
(defparameter *open-external-panels-in-popup* nil) (defparameter *open-external-panels-in-popup* nil)
;; Open panels as popups by default ;; Open panels as popups by default

View file

@ -5,10 +5,12 @@
;; Preferences loaded on next call to clog-tools:clog-builder or [Eval All] ;; Preferences loaded on next call to clog-tools:clog-builder or [Eval All]
;; Builder Desktop
;; Open panels and files in new browser tabs by default ;; Open panels and files in new browser tabs by default
(setf *open-external* nil) (setf *open-external* nil)
;; Open files in browser popups instead of tabs if browser allows ;; Use clog-popup and extend desktop to popups
(setf *open-external-in-popup* nil) (setf *open-external-using-clog-popups* nil)
;; CLOG Panels ;; CLOG Panels
@ -19,6 +21,8 @@
;; CLOG Source Editor ;; CLOG Source Editor
;; Open files in browser popups instead of tabs if browser allows
(setf *open-external-source-in-popup* nil)
;; Use console for evals instead of capture ;; Use console for evals instead of capture
(setf *editor-use-console-for-evals* nil) (setf *editor-use-console-for-evals* nil)
;; Use emacs instead of the source-editor when opening external ;; Use emacs instead of the source-editor when opening external