help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: New balance-windows


From: Stefan Monnier
Subject: Re: New balance-windows
Date: Tue, 09 Aug 2005 20:05:47 -0400
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin)

>     After `balance-windows'           After my new function
>     +-------+-------+-------+        +-------+-------+-------+
>     |  9    |       |       |        |       |       |       |
>     |       |       |  19   |        |  15   |       |  20   |
>     +-------+       |       |        |       |       |       |
>     |       |  29   |       |        +-------+  30   |       |
>     |  19   |       +-------+        |       |       +-------+
>     |       |       |       |        |  15   |       |       |
>     |       |       |       |        |       |       |       |
>     +----+--+-------+  19   |        +----+--+-------+  20   |
>     |    |  |       |       |        |    |  |       |       |
>     | 19 |  |       |       |        | 14 |  |       |       |
>     |    |  |       +-------+        |    |  |       +-------+
>     |    |  |  32   |       |        +----+--+  31   |       |
>     +----+--+       |       |        |       |       |       |
>     |       |       |  22   |        | 15    |       |  20   |
>     | 12    |       |       |        |       |       |       |
>     |       |       |       |        |       |       |       |
>     +-------+-------+-------+        +-------+-------+-------+

For what it's worth, here is another alternative I wrote a few years ago.
Note how it iterates to try and get to a fix point without using the
`preserve-before' argument (which didn't exist at that point).


        Stefan


(defun balance-windows-area ()
  "Make all visible windows use the same area (approximately)."
  (interactive)
  (save-selected-window
    (let* ((change t)
           (resizecount 0)
           (wins (window-list nil 'nomini))
           (count (length wins))
           minresize next (carry 0))
      ;; Resizing a window changes the size of surrounding windows
      ;; in complex ways, so it's difficult to set the sizes in a single pass.
      ;; Instead, we just go through all the windows several times
      ;; until nothing needs to be CHANGEd.
      (while (and change (> count 1))
        (setq change nil count (1- count))
        (dolist (win wins)
          ;; We always have to check liveness because enlarging/shrinking
          ;; always risks deleting windows (although we are very careful
          ;; to avoid most such cases).
          (when (and (window-live-p win) (not (window-fixed-size-p win)))
            (select-window win)
            (setq next nil)
            (while (progn (setq next (next-window next))
                          (window-fixed-size-p next)))
            (let ((diff (- (* (window-height) (window-width))
                           (* (window-height next) (window-width next)))))
              (if (< (car (window-edges)) (car (window-edges next)))
                  ;; The windows are side-by-side
                  (unless (zerop (setq diff (/ diff (window-height) 2)))
                    ;; Change things more smoothly.
                    (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
                    (shrink-window diff)
                    (setq change t))
                (setq diff (/ diff (window-width) 2))
                ;; Change things more smoothly.
                (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
                (cond
                 ((= diff 0))
                 ;; Try to shrink to balance out with a smaller next window.
                 ;; Enlarging risks killing a window, but if the next-window
                 ;; is adjacent, then it should be safe.
                 ((or (and (> diff 0) (window-safely-shrinkable-p))
                      (and (< diff 0)
                           (= (car (window-edges))
                              (car (window-edges next)))
                           (not (eq next (frame-first-window)))))
                  (shrink-window diff)
                  (setq change t))
                 ;; Resizing is also safe if all windows are big enough.
                 ((> (setq minresize
                           (- (apply 'min (mapcar 'window-height wins))
                              window-min-height))
                     0)
                  (shrink-window
                   (if (> diff 0)
                       (min diff minresize) (max diff (- minresize))))
                  (setq change t))
                 ;; Let's try yet something else
                 ((and (< diff 0) (window-safely-shrinkable-p next))
                  (select-window next)
                  (shrink-window (- diff))
                  (setq change t)))))))))))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]