Files
@ fd6bd1140427
Branch filter:
Location: workgroups2/src/workgroups-wtree.el
fd6bd1140427
7.4 KiB
text/x-elisp
Removed rest of filtration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | ;;; workgroups-wtree.el --- window-tree "class"
;;; Commentary:
;;
;; `window-tree' - several opened windows, their sizes and position is
;; what you want to save.
;;
;;; Code:
(require 'workgroups-win)
(defun wg-w-edges (w)
"Return W's edge list."
(cl-etypecase w
(wg-win (wg-win-edges w))
(wg-wtree (wg-wtree-edges w))))
(defun wg-copy-w (w)
"Return a copy of W. W should be a wg-win or a wg-wtree."
(cl-etypecase w
(wg-win (wg-copy-win w))
(wg-wtree (wg-copy-wtree w))))
(defun wg-set-edges (w edges)
"Set W's edge list, and return W."
(cl-etypecase w
(wg-win (setf (wg-win-edges w) edges))
(wg-wtree (setf (wg-wtree-edges w) edges)))
w)
(defun wg-equal-wtrees (w1 w2)
"Return t when W1 and W2 have equal structure."
(cond ((and (wg-win-p w1) (wg-win-p w2))
(equal (wg-w-edges w1) (wg-w-edges w2)))
((and (wg-wtree-p w1) (wg-wtree-p w2))
(and (eq (wg-wtree-dir w1) (wg-wtree-dir w2))
(equal (wg-wtree-edges w1) (wg-wtree-edges w2))
(cl-every #'wg-equal-wtrees
(wg-wtree-wlist w1)
(wg-wtree-wlist w2))))))
(defun wg-normalize-wtree (wtree)
"Clean up and return a new wtree from WTREE.
Recalculate the edge lists of all subwins, and remove subwins
outside of WTREE's bounds. If there's only one element in the
new wlist, return it instead of a new wtree."
(if (wg-win-p wtree) wtree
(wg-with-slots wtree ((dir wg-wtree-dir)
(wlist wg-wtree-wlist))
(wg-with-bounds wtree dir (ls1 hs1 lb1 hb1)
(let* ((min-size (wg-min-size dir))
(max (- hb1 1 min-size))
(lastw (-last-item wlist)))
(cl-labels
((mapwl
(wl)
(wg-dbind (sw . rest) wl
(cons (wg-normalize-wtree
(wg-set-bounds
sw dir ls1 hs1 lb1
(setq lb1 (if (eq sw lastw) hb1
(let ((hb2 (+ lb1 (wg-w-size sw dir))))
(if (>= hb2 max) hb1 hb2))))))
(when (< lb1 max) (mapwl rest))))))
(let ((new (mapwl wlist)))
(if (not (cdr new)) (car new)
(setf (wg-wtree-wlist wtree) new)
wtree))))))))
(defun wg-scale-wtree (wtree wscale hscale)
"Return a copy of WTREE with its dimensions scaled by WSCALE and HSCALE.
All WTREE's subwins are scaled as well."
(let ((scaled (wg-scale-w-size wtree wscale hscale)))
(if (wg-win-p wtree) scaled
(wg-asetf (wg-wtree-wlist scaled)
(wg-docar (sw it) (wg-scale-wtree sw wscale hscale)))
scaled)))
(defun wg-resize-frame-scale-wtree (wconfig)
"Set FRAME's size to WCONFIG's, returning a possibly scaled wtree.
If the frame size was set correctly, return WCONFIG's wtree
unchanged. If it wasn't, return a copy of WCONFIG's wtree scaled
with `wg-scale-wconfigs-wtree' to fit the frame as it exists."
(let ((frame (selected-frame)))
(wg-with-slots wconfig ((wcwidth wg-wconfig-width)
(wcheight wg-wconfig-height))
(when window-system (set-frame-size frame wcwidth wcheight))
(let ((fwidth (frame-parameter frame 'width))
(fheight (frame-parameter frame 'height)))
(if (and (= wcwidth fwidth) (= wcheight fheight))
(wg-wconfig-wtree wconfig)
(wg-scale-wconfigs-wtree wconfig fwidth fheight))))))
(defun wg-wtree-buf-uids (wtree)
"Return a new list of the buf uids of all wins in WTREE."
(if (not wtree)
(error "WTREE is nil in `wg-wtree-buf-uids'!"))
(wg-flatten-wtree wtree 'wg-win-buf-uid))
(defun wg-wtree-unique-buf-uids (wtree)
"Return a list of the unique buf uids of all wins in WTREE."
(cl-remove-duplicates (wg-wtree-buf-uids wtree) :test 'string=))
(defun wg-reset-window-tree ()
"Delete all but one window in `selected-frame', and reset
various parameters of that window in preparation for restoring
a wtree."
(delete-other-windows)
(set-window-dedicated-p nil nil))
(defun wg-restore-window-tree-helper (w)
"Recursion helper for `wg-restore-window-tree'."
(if (wg-wtree-p w)
(cl-loop with dir = (wg-wtree-dir w)
for (win . rest) on (wg-wtree-wlist w)
do (when rest (split-window nil (wg-w-size win dir) (not dir)))
do (wg-restore-window-tree-helper win))
(wg-restore-window w)
(when (wg-win-selected w)
(setq wg-window-tree-selected-window (selected-window)))
(when (wg-win-minibuffer-scroll w)
(setq minibuffer-scroll-window (selected-window)))
(other-window 1)))
(defun wg-restore-window-tree (wtree)
"Restore WTREE in `selected-frame'."
(let ((window-min-width wg-window-min-width)
(window-min-height wg-window-min-height)
(wg-window-tree-selected-window nil))
(wg-reset-window-tree)
(wg-restore-window-tree-helper wtree)
(awhen wg-window-tree-selected-window (select-window it))))
;; (wg-window-tree-to-wtree (window-tree))
(defun wg-window-tree-to-wtree (window-tree)
"Return the serialization (a wg-wtree) of Emacs window tree WINDOW-TREE."
(wg-barf-on-active-minibuffer)
(cl-labels
((inner (w) (if (windowp w) (wg-window-to-win w)
(wg-dbind (dir edges . wins) w
(wg-make-wtree
:dir dir
:edges edges
:wlist (mapcar #'inner wins))))))
(let ((w (car window-tree)))
(when (and (windowp w) (window-minibuffer-p w))
(error "Workgroups can't operate on minibuffer-only frames."))
(inner w))))
(defun wg-flatten-wtree (wtree &optional key)
"Return a new list by flattening WTREE.
KEY non returns returns a list of WTREE's wins.
KEY non-nil returns a list of the results of calling KEY on each win."
(cl-labels
((inner (w) (if (wg-win-p w) (list (if key (funcall key w) w))
(cl-mapcan #'inner (wg-wtree-wlist w)))))
(inner wtree)))
(defun wg-reverse-wlist (w &optional dir)
"Reverse W's wlist and those of all its sub-wtrees in direction DIR.
If DIR is nil, reverse WTREE horizontally.
If DIR is 'both, reverse WTREE both horizontally and vertically.
Otherwise, reverse WTREE vertically."
(cl-labels
((inner (w) (if (wg-win-p w) w
(wg-with-slots w ((d1 wg-wtree-dir))
(wg-make-wtree
:dir d1
:edges (wg-wtree-edges w)
:wlist (let ((wl2 (mapcar #'inner (wg-wtree-wlist w))))
(if (or (eq dir 'both) (eq dir d1))
(nreverse wl2)
wl2)))))))
(wg-normalize-wtree (inner w))))
(defun wg-wtree-move-window (wtree offset)
"Offset `selected-window' OFFSET places in WTREE."
(cl-labels
((inner (w) (if (wg-win-p w) w
(wg-with-slots w ((wlist wg-wtree-wlist))
(wg-make-wtree
:dir (wg-wtree-dir w)
:edges (wg-wtree-edges w)
:wlist (aif (cl-find t wlist :key 'wg-win-selected)
(wg-cyclic-offset-elt it wlist offset)
(mapcar #'inner wlist)))))))
(wg-normalize-wtree (inner wtree))))
(provide 'workgroups-wtree)
;;; workgroups-wtree.el ends here
|