diff --git a/clog-gui.lisp b/clog-gui.lisp
index 1908ca1..4019258 100644
--- a/clog-gui.lisp
+++ b/clog-gui.lisp
@@ -19,7 +19,11 @@
(current-win
:accessor current-win
:initform nil
- :documentation "The current window at front.")
+ :documentation "The current window at front")
+ (windows
+ :accessor windows
+ :initform (make-hash-table :test 'equalp)
+ :documentation "Window collection")
(last-z
:accessor last-z
:initform -9999
@@ -31,13 +35,17 @@
(in-drag
:accessor in-drag
:initform nil
- :documentation "Drag window or Size window.")
+ :documentation "Drag window or Size window")
+ (drag-obj
+ :accessor drag-obj
+ :initform nil
+ :documentation "Drag target object")
(drag-x
:accessor drag-x
- :documentation "Location of the left side or width relative to pointer during drag.")
+ :documentation "Location of the left side or width relative to pointer during drag")
(drag-y
:accessor drag-y
- :documentation "Location of the top or height relative to pointer during drag.")))
+ :documentation "Location of the top or height relative to pointer during drag")))
;;;;;;;;;;;;;;;;;;;;;
;; create-clog-gui ;;
@@ -45,7 +53,7 @@
(defun create-clog-gui (clog-body)
"Create a clog-gui object and places it in CLOG-BODY's connection-data as
-\"clog-gui\". (private)"
+\"clog-gui\". (Private)"
(let ((clog-gui (make-instance 'clog-gui)))
(setf (connection-data-item clog-body "clog-gui") clog-gui)
(setf (body clog-gui) clog-body)
@@ -122,7 +130,8 @@ clog-body."))
(on-click nil)
(class "w3-bar-item w3-button")
(html-id nil))
- (let ((span (create-span obj :content content :class class :html-id html-id)))
+ (let ((span
+ (create-span obj :content content :class class :html-id html-id)))
(set-on-click span on-click)
(change-class span 'clog-gui-menu-item)))
@@ -190,35 +199,35 @@ icon ⤢ and full screen mode."))
:accessor sizer
:documentation "Window sizer clog-element")
(on-window-can-close
- :accessor set-on-window-can-close
+ :accessor on-window-can-close
:initform nil
:documentation "Return t to allow close of window")
(on-window-can-move
- :accessor set-on-window-can-move
+ :accessor on-window-can-move
:initform nil
:documentation "Return t to allow move of window")
(on-window-can-size
- :accessor set-on-window-can-size
+ :accessor on-window-can-size
:initform nil
:documentation "Return t to allow close of window")
(on-window-close
- :accessor set-on-window-close
+ :accessor on-window-close
:initform nil
:documentation "Fired on window closed")
(on-window-move
- :accessor set-on-window-move
+ :accessor on-window-move
:initform nil
:documentation "Fired during move of window")
(on-window-size
- :accessor set-on-window-size
+ :accessor on-window-size
:initform nil
:documentation "Fired during size change of window")
(on-window-move-done
- :accessor set-on-window-move-done
+ :accessor on-window-move-done
:initform nil
:documentation "Fired after move of window")
(on-window-size-done
- :accessor set-on-window-size-done
+ :accessor on-window-size-done
:initform nil
:documentation "Fired after size change of window")))
@@ -231,26 +240,35 @@ icon ⤢ and full screen mode."))
(let ((app (connection-data-item obj "clog-gui")))
(unless (in-drag app)
(setf (in-drag app) (attribute obj "data-drag-type"))
- (let* ((id-drag (attribute obj "data-drag-obj"))
- (drag-obj (attach-as-child obj id-drag))
+ (let* ((target (gethash (attribute obj "data-drag-obj") (windows app)))
(pointer-x (getf data ':screen-x))
(pointer-y (getf data ':screen-y))
(obj-top)
- (obj-left))
- (cond ((equalp (in-drag app) "m")
- (setf obj-top (parse-integer (top drag-obj) :junk-allowed t))
- (setf obj-left (parse-integer (left drag-obj) :junk-allowed t)))
- ((equalp (in-drag app) "s")
- (setf obj-top (height drag-obj))
- (setf obj-left (width drag-obj)))
- (t
- (format t "Warning - invalid data-drag-type attribute")))
- (setf (z-index drag-obj) (incf (last-z app)))
- (setf (current-win app) drag-obj)
- (setf (drag-y app) (- pointer-y obj-top))
- (setf (drag-x app) (- pointer-x obj-left))
- (set-on-pointer-move obj 'on-gui-drag-move)
- (set-on-pointer-up obj 'on-gui-drag-stop)))))
+ (obj-left)
+ (perform-drag nil))
+ (when target
+ (setf (drag-obj app) target)
+ (cond ((equalp (in-drag app) "m")
+ (setf obj-top
+ (parse-integer (top (drag-obj app)) :junk-allowed t))
+ (setf obj-left
+ (parse-integer (left (drag-obj app)) :junk-allowed t))
+ (setf perform-drag (fire-on-window-can-move (drag-obj app))))
+ ((equalp (in-drag app) "s")
+ (setf obj-top (height (drag-obj app)))
+ (setf obj-left (width (drag-obj app)))
+ (setf perform-drag (fire-on-window-can-size (drag-obj app))))
+ (t
+ (format t "Warning - invalid data-drag-type attribute")))
+ (setf (z-index (drag-obj app)) (incf (last-z app)))
+ (setf (current-win app) (drag-obj app))
+ (setf (drag-y app) (- pointer-y obj-top))
+ (setf (drag-x app) (- pointer-x obj-left)))
+ (cond (perform-drag
+ (set-on-pointer-move obj 'on-gui-drag-move)
+ (set-on-pointer-up obj 'on-gui-drag-stop))
+ (t
+ (setf (in-drag app) nil)))))))
;;;;;;;;;;;;;;;;;;;;;;
;; on-gui-drag-move ;;
@@ -259,20 +277,19 @@ icon ⤢ and full screen mode."))
(defun on-gui-drag-move (obj data)
"Handle mouse tracking on drag object"
(let* ((app (connection-data-item obj "clog-gui"))
- (drag-obj (attach-as-child obj (attribute obj "data-drag-obj")))
(x (getf data ':screen-x))
(y (getf data ':screen-y))
(adj-y (- y (drag-y app)))
(adj-x (- x (drag-x app))))
(when (and (> adj-x 0) (> adj-y 30))
(cond ((equalp (in-drag app) "m")
- ;; send on-window-move
- (setf (top drag-obj) (unit :px adj-y))
- (setf (left drag-obj) (unit :px adj-x)))
+ (fire-on-window-move (drag-obj app))
+ (setf (top (drag-obj app)) (unit :px adj-y))
+ (setf (left (drag-obj app)) (unit :px adj-x)))
((equalp (in-drag app) "s")
- ;; send on-window-resize
- (setf (height drag-obj) (unit :px adj-y))
- (setf (width drag-obj) (unit :px adj-x)))))))
+ (fire-on-window-size (drag-obj app))
+ (setf (height (drag-obj app)) (unit :px adj-y))
+ (setf (width (drag-obj app)) (unit :px adj-x)))))))
;;;;;;;;;;;;;;;;;;;;;;
;; on-gui-drag-stop ;;
@@ -280,18 +297,16 @@ icon ⤢ and full screen mode."))
(defun on-gui-drag-stop (obj data)
"Handle end of drag object"
- (let ((app (connection-data-item obj "clog-gui"))
- (drag-obj (attach-as-child obj (attribute obj "data-drag-obj"))))
+ (let ((app (connection-data-item obj "clog-gui")))
(on-gui-drag-move obj data)
- (setf (in-drag app) nil)
(set-on-pointer-move obj nil)
(set-on-pointer-up obj nil)
(cond ((equalp (in-drag app) "m")
- (when (set-on-window-move-done app)
- (funcall (set-on-window-move-done app) drag-obj)))
+ (fire-on-window-move-done (drag-obj app)))
((equalp (in-drag app) "s")
- (when (set-on-window-size-done app)
- (funcall (set-on-window-size-done app) drag-obj))))))
+ (fire-on-window-size-done (drag-obj app))))
+ (setf (in-drag app) nil)
+ (setf (drag-obj app) nil)))
;;;;;;;;;;;;;;;;;;;;;;;
;; create-gui-window ;;
@@ -326,7 +341,7 @@ icon ⤢ and full screen mode."))
X
-
~A
+ ~A
+
@@ -348,9 +363,25 @@ icon ⤢ and full screen mode."))
(set-on-pointer-down (win-title win) 'on-gui-drag-down :capture-pointer t)
(set-on-pointer-down (sizer win) 'on-gui-drag-down :capture-pointer t)
(set-on-click (closer win) (lambda (obj)
- (remove-from-dom win)))
+ (when (fire-on-window-can-close win)
+ (remhash (format nil "~A" html-id) (windows app))
+ (remove-from-dom win)
+ (fire-on-window-close win))))
+ (setf (gethash (format nil "~A" html-id) (windows app)) win)
+ (setf (current-win app) win)
win))
+;;;;;;;;;;;;;;;;;;;;
+;; current-window ;;
+;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric current-window (clog-obj)
+ (:documentation "Get the current selected clog-gui-window"))
+
+(defmethod current-window ((obj clog-obj))
+ (let ((app (connection-data-item obj "clog-gui")))
+ (current-win app)))
+
;;;;;;;;;;;;;;;;;;
;; window-title ;;
;;;;;;;;;;;;;;;;;;
@@ -367,3 +398,146 @@ icon ⤢ and full screen mode."))
(defmethod set-window-title ((obj clog-gui-window) value)
(setf (inner-html (win-title obj)) value))
(defsetf window-title set-window-title)
+
+;;;;;;;;;;;;;;;;;;;;
+;; window-content ;;
+;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric window-content (clog-gui-window)
+ (:documentation "Get window content element."))
+
+(defmethod window-content ((obj clog-gui-window))
+ (content obj))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-can-close ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-can-close (clog-gui-window handler)
+ (:documentation "Set the on-window-can-close HANDLER"))
+
+(defmethod set-on-window-can-close ((obj clog-gui-window) handler)
+ (setf (on-window-can-close obj) handler))
+
+(defgeneric fire-on-window-can-close (clog-gui-window)
+ (:documentation "Fire handler if set. (Private)"))
+
+(defmethod fire-on-window-can-close ((obj clog-gui-window))
+ (if (on-window-can-close obj)
+ (funcall (on-window-can-close obj) obj)
+ t))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-close ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-close (clog-gui-window handler)
+ (:documentation "Set the on-window-close HANDLER"))
+
+(defmethod set-on-window-close ((obj clog-gui-window) handler)
+ (setf (on-window-close obj) handler))
+
+(defgeneric fire-on-window-close (clog-gui-window)
+ (:documentation "Fire handler if set. (Private)"))
+
+(defmethod fire-on-window-close ((obj clog-gui-window))
+ (when (on-window-close obj)
+ (funcall (on-window-close obj) obj)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-can-size ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-can-size (clog-gui-window handler)
+ (:documentation "Set the on-window-can-size HANDLER"))
+
+(defmethod set-on-window-can-size ((obj clog-gui-window) handler)
+ (setf (on-window-can-size obj) handler))
+
+(defgeneric fire-on-window-can-size (clog-gui-window)
+ (:documentation "Fire handler if set. (Private)"))
+
+(defmethod fire-on-window-can-size ((obj clog-gui-window))
+ (if (on-window-can-size obj)
+ (funcall (on-window-can-size obj) obj)
+ t))
+
+;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-size ;;
+;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-size (clog-gui-window handler)
+ (:documentation "Set the on-window-size HANDLER"))
+
+(defmethod set-on-window-size ((obj clog-gui-window) handler)
+ (setf (on-window-size obj) handler))
+
+(defgeneric fire-on-window-size (clog-gui-window)
+ (:documentation "Fire handler if set. (Private)"))
+
+(defmethod fire-on-window-size ((obj clog-gui-window))
+ (when (on-window-size obj)
+ (funcall (on-window-size obj) obj)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-size-done ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-size-done (clog-gui-window handler)
+ (:documentation "Set the on-window-size-done HANDLER"))
+
+(defmethod set-on-window-size-done ((obj clog-gui-window) handler)
+ (setf (on-window-size-done obj) handler))
+
+(defmethod fire-on-window-size-done ((obj clog-gui-window))
+ (when (on-window-size-done obj)
+ (funcall (on-window-size-done obj) obj)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-can-move ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-can-move (clog-gui-window handler)
+ (:documentation "Set the on-window-can-move HANDLER"))
+
+(defmethod set-on-window-can-move ((obj clog-gui-window) handler)
+ (setf (on-window-can-move obj) handler))
+
+(defgeneric fire-on-window-can-move (clog-gui-window)
+ (:documentation "Fire handler if set. (Private)"))
+
+(defmethod fire-on-window-can-move ((obj clog-gui-window))
+ (if (on-window-can-move obj)
+ (funcall (on-window-can-move obj) obj)
+ t))
+
+;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-move ;;
+;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-move (clog-gui-window handler)
+ (:documentation "Set the on-window-move HANDLER"))
+
+(defmethod set-on-window-move ((obj clog-gui-window) handler)
+ (setf (on-window-move obj) handler))
+
+(defgeneric fire-on-window-move (clog-gui-window)
+ (:documentation "Fire handler if set. (Private)"))
+
+(defmethod fire-on-window-move ((obj clog-gui-window))
+ (when (on-window-move obj)
+ (funcall (on-window-move obj) obj)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; set-on-window-move-done ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgeneric set-on-window-move-done (clog-gui-window handler)
+ (:documentation "Set the on-window-move-done HANDLER"))
+
+(defmethod set-on-window-move-done ((obj clog-gui-window) handler)
+ (setf (on-window-move-done obj) handler))
+
+(defmethod fire-on-window-move-done ((obj clog-gui-window))
+ (when (on-window-move-done obj)
+ (funcall (on-window-move-done obj) obj)))
diff --git a/clog.lisp b/clog.lisp
index c9588bd..6855f00 100644
--- a/clog.lisp
+++ b/clog.lisp
@@ -666,8 +666,17 @@ embedded in a native template application.)"
(create-gui-menu-icon generic-function)
"CLOG-GUI - Windows"
+ (current-window generic-function)
+ (clog-gui-window class)
(create-gui-window generic-function)
(window-title generic-function)
+ (window-content generic-function)
+ (set-on-window-can-close generic-function)
+ (set-on-window-close generic-function)
+ (set-on-window-can-move generic-function)
+ (set-on-window-can-size generic-function)
+ (set-on-window-move generic-function)
+ (set-on-window-size generic-function)
(set-on-window-move-done generic-function)
(set-on-window-size-done generic-function))
diff --git a/demos/03-demo.lisp b/demos/03-demo.lisp
index c5e6569..66eeac5 100644
--- a/demos/03-demo.lisp
+++ b/demos/03-demo.lisp
@@ -10,129 +10,10 @@
((body
:accessor body
:documentation "Top level access to browser window")
- (current-win
- :accessor current-win
- :initform nil
- :documentation "The current window at front.")
- (last-z
- :accessor last-z
- :initform -9999
- :documentation "Top z-order for windows")
(copy-buf
:accessor copy-buf
:initform ""
- :documentation "Copy buffer")
- (in-drag
- :accessor in-drag
- :initform nil
- :documentation "Drag window or Size window.")
- (drag-x
- :accessor drag-x
- :documentation "Location of the left side or width relative to pointer during drag.")
- (drag-y
- :accessor drag-y
- :documentation "Location of the top or height relative to pointer during drag.")))
-
-(defun on-ide-drag-down (obj data)
- (let ((app (connection-data-item obj "app-data")))
- (unless (in-drag app)
- (setf (in-drag app) (attribute obj "data-drag-type"))
- (let* ((id-drag (attribute obj "data-drag-obj"))
- (drag-obj (attach-as-child obj id-drag))
- (pointer-x (getf data ':screen-x))
- (pointer-y (getf data ':screen-y))
- (obj-top)
- (obj-left))
- (if (equalp (in-drag app) "m")
- (progn
- (setf (current-win app) drag-obj)
- (setf obj-top (parse-integer (top drag-obj) :junk-allowed t))
- (setf obj-left (parse-integer (left drag-obj) :junk-allowed t)))
- (progn
- (setf obj-top (height drag-obj))
- (setf obj-left (width drag-obj))))
- (setf (z-index drag-obj) (incf (last-z app)))
- (setf (drag-y app) (- pointer-y obj-top))
- (setf (drag-x app) (- pointer-x obj-left))
- (set-on-pointer-move obj 'on-ide-drag-move)
- (set-on-pointer-up obj 'on-ide-drag-stop)))))
-
-(defun on-ide-drag-move (obj data)
- (let* ((app (connection-data-item obj "app-data"))
- (drag-obj (attach-as-child obj (attribute obj "data-drag-obj")))
- (x (getf data ':screen-x))
- (y (getf data ':screen-y))
- (adj-y (- y (drag-y app)))
- (adj-x (- x (drag-x app))))
- (when (and (> adj-x 0) (> adj-y 30))
- (cond ((equalp (in-drag app) "m")
- (setf (top drag-obj) (format nil "~Apx" adj-y))
- (setf (left drag-obj) (format nil "~Apx" adj-x)))
- ((equalp (in-drag app) "s")
- (js-execute drag-obj (format nil "editor_~A.resize()" (html-id drag-obj)))
- (setf (height drag-obj) (format nil "~Apx" adj-y))
- (setf (width drag-obj) (format nil "~Apx" adj-x)))))))
-
-(defun on-ide-drag-stop (obj data)
- (let ((app (connection-data-item obj "app-data")))
- (on-ide-drag-move obj data)
- (setf (in-drag app) nil)
- (set-on-pointer-move obj nil)
- (set-on-pointer-up obj nil)))
-
-
-(defgeneric create-window (clog-obj title
- &key html-id content left top width height)
- (:documentation "Create an mdi window"))
-
-(defmethod create-window ((obj clog-obj) title &key
- (html-id nil)
- (content "")
- (left 60)
- (top 60)
- (width 400)
- (height 300))
- (unless html-id
- (setf html-id (clog-connection:generate-id)))
-
- (let* ((app (connection-data-item obj "app-data"))
- (win (create-child (body app)
- (format nil
- ""
- top left width height (incf (last-z app)) ; outer div
- html-id html-id html-id ; title bar
- title html-id ; title
- html-id content ; body
- html-id html-id) ; size
- :html-id html-id))
- (title (attach-as-child win (format nil "~A-title" html-id)))
- (close-x (attach-as-child win (format nil "~A-close" html-id)))
- (sizer (attach-as-child win (format nil "~A-size" html-id))))
- (set-on-pointer-down title 'on-ide-drag-down :capture-pointer t)
- (set-on-pointer-down sizer 'on-ide-drag-down :capture-pointer t)
- (set-on-click close-x (lambda (obj)
- (remove-from-dom win)))
- win))
-
-(defun set-title (obj title)
- (setf (inner-html (attach-as-child obj (format nil "~A-title" (html-id obj)))) title))
-
-(defun get-title (obj)
- (inner-html (attach-as-child obj (format nil "~A-title" (html-id obj)))))
+ :documentation "Copy buffer")))
(defun read-file (infile)
(with-open-file (instream infile :direction :input :if-does-not-exist nil)
@@ -149,12 +30,12 @@
(defun get-file-name (obj title on-file-name)
(let* ((app (connection-data-item obj "app-data"))
- (win (create-window obj title
- :left (- (/ (width (body app)) 2) 200)
- :width 400
- :height 60))
- (body (attach-as-child win (format nil "~A-body" (html-id win))))
- (form (create-form body))
+ (win (create-gui-window obj
+ :title title
+ :left (- (/ (width (body app)) 2) 200)
+ :width 400
+ :height 60))
+ (form (create-form (window-content win)))
(input (create-form-element form :input :label
(create-label form :content "File Name:")))
(ok (create-button form :content "OK")))
@@ -173,11 +54,14 @@
(format nil "~A~%=>~A~%" result eval-result)))
(defun do-ide-file-new (obj)
- (let ((app (connection-data-item obj "app-data"))
- (win (create-window obj "New window"
- :left (random 600)
- :top (+ 40 (random 400)))))
- (create-child obj
+ (let ((win (create-gui-window obj
+ :title "New window"
+ :left (random 600)
+ :top (+ 40 (random 400)))))
+ (set-on-window-size win (lambda (obj)
+ (js-execute obj
+ (format nil "editor_~A.resize()" (html-id win)))))
+ (create-child win
(format nil
"