

;;
;; Stack to keep track of dumped windows
(defvar dv-dump-stack nil)
(setq dv-dump-stack nil)

(show-message (prin1-to-string dv-dump-stack))

;;
;; push a window onto the stack with the given id
(defun dv-push-window-onto-dump-stack ( window stackid )
  "Pushes the given window onto the stack with the given id"
  (let ((window-info (cons window (cons (window-position window)
                                        (window-dimensions window)))))
    (window-put window 'dv-dumped t)
    (window-put window 'dv-dump-stackid stackid)
    (setq dv-dump-stack (cons window-info dv-dump-stack))))


;;
;; pop the first window on the given workspace and stackid
;; off the dump stack
(defun dv-pop-window-off-dump-stack ( space stackid )
  "Pops the a window on the given space with the given stackid off the stack"
  (catch 'return
    (let ((dump-stack-curr dv-dump-stack))
      (while (and (consp dump-stack-curr)
                  (car dump-stack-curr))
        (let* ((window-info (car dump-stack-curr))
               (window (car window-info)))
          (when (and (eq stackid (window-get window 'dv-dump-stackid))
                     (eq space (window-get window 'workspace)))
            (rplaca dump-stack-curr (car (cdr dump-stack-curr)))
            (rplacd dump-stack-curr (cdr (cdr dump-stack-curr)))
            (window-put window 'dv-dumped nil)
            (window-put window 'dv-dump-stackid nil)
            (throw 'return window-info)))
        (setq dump-stack-curr (cdr dump-stack-curr)))
      (throw 'return nil))))
          
;;
;; Search the dump stack and remove the given window
(defun dv-remove-window-from-dump-stack ( window )
  "Removes the given window object from the stack"
  (let ((dump-stack-curr dv-dump-stack))
    (while (consp dump-stack-curr)
      (let ((window-curr (car (car dump-stack-curr))))
        (when (eq window window-curr)
          (window-put 'dv-dumped nil)
          (window-put 'dv-dump-stackid nil)
          (rplaca dump-stack-curr (car (cdr dump-stack-curr)))
          (rplacd dump-stack-curr (cdr (cdr dump-stack-curr)))))
      (setq dump-stack-curr (cdr dump-stack-curr)))))
                  
;;
;; Remove a window from the dump stack if it's state changes
(add-hook 'window-state-change-hook
          #'(lambda ( window )
              (dv-remove-window-from-dump-stack window)))

;;
;; Slide a window to a new position and size
(defun dv-slide-window-to ( window x y &optional width height )
  "Slides a window to the to a position of the screen"
  (let* ((pos (window-position window))
         (xpos (car pos))
         (ypos (cdr pos))
         (xdelta (/ (- x xpos) 25))
         (ydelta (/ (- y ypos) 25))
         (dim (window-dimensions window))
         (width (if width width (car dim)))
         (height (if height height (cdr dim)))
         (wdim (car dim))
         (hdim (cdr dim))
         (wdelta (/ (- width wdim) 25))
         (hdelta (/ (- height hdim) 25))
         (count 0))
    (hide-window window)
    (draw-window-outline 'box xpos ypos wdim hdim)
    (while (< count 25)
      (erase-window-outline 'box xpos ypos wdim hdim)
      (if (not (eq xdelta 0))
          (setq xpos (+ xpos xdelta)))
      (if (not (eq ydelta 0))
          (setq ypos (+ ypos ydelta)))
      (if (not (eq wdelta 0))
          (setq wdim (+ wdim wdelta)))
      (if (not (eq hdelta 0))
          (setq hdim (+ hdim hdelta)))
      (draw-window-outline 'box xpos ypos wdim hdim)
      (setq count (+ count 1))
      (sleep-for 0 5))
    (erase-window-outline 'box xpos ypos wdim hdim)
    (move-window-to window x y)
    (resize-window-to window width height)
    (show-window window)))

;;
;; undumps a window from any side of the screen
(defun dv-undump-window ( stackid )
  "Undumps the next window from the given stackid"
  (let ((window-info (dv-pop-window-off-dump-stack current-workspace stackid)))
    (when window-info
      (let ((window (car window-info))
            (pos (car (cdr window-info)))
            (dim (cdr (cdr window-info))))
        (dv-slide-window-to window (car pos) (cdr pos) (car dim) (cdr dim))))))
  
;;
;; dumps a window to left side of the screen
(defun dv-dump-window-left ( window )
  "Dumps a window to the left region"
  (interactive "%W")
  (when (not (window-get window 'dv-dumped))
    (dv-push-window-onto-dump-stack window 'left)
    (dv-slide-window-to window
                     0 (cdr (window-position window))
                     150 (cdr (window-dimensions window)))))


;;
;; undumps a window from the left
(defun dv-undump-window-left ()
  "Undumps a window from the left region"
  (interactive)
  (dv-undump-window 'left))

;;
;; dumps a window to right side of the screen
(defun dv-dump-window-right ( window )
  "Dumps a window to the right region"
  (interactive "%W")
  (when (not (window-get window 'dv-dumped))
    (dv-push-window-onto-dump-stack window 'right)
    (dv-slide-window-to window
                     (- (screen-width) 150) (cdr (window-position window))
                     150 (cdr (window-dimensions window)))))


;;
;; undumps a window from the right
(defun dv-undump-window-right ()
  "Undumps a window from the right region"
  (interactive)
  (dv-undump-window 'right))


;;
;; dumps a window to top side of the screen
(defun dv-dump-window-top ( window )
  "Dumps a window to the top region"
  (interactive "%W")
  (when (not (window-get window 'dv-dumped))
    (dv-push-window-onto-dump-stack window 'top)
    (dv-slide-window-to window
                     (car (window-position window)) 0
                     (car (window-dimensions window)) 150)))

;;
;; undumps a window from the top
(defun dv-undump-window-top ()
  "Undumps a window from the top region"
  (interactive)
  (dv-undump-window 'top))

;;
;; dumps a window to bottom side of the screen
(defun dv-dump-window-bottom ( window )
  "Dumps a window to the bottom region"
  (interactive "%W")
  (when (not (window-get window 'dv-dumped))
    (dv-push-window-onto-dump-stack window 'bottom)
    (dv-slide-window-to window
                     (car (window-position window)) (- (screen-height) 150)
                     (car (window-dimensions window)) 150)))

;;
;; undumps a window from the bottom
(defun dv-undump-window-bottom ()
  "Undumps a window from the bottom region"
  (interactive)
  (dv-undump-window 'bottom))

