;;; xwem-framei.el --- Frame indicator.

;; Copyright (C) 2004 by Free Software Foundation, Inc.

;; Author: Zajcev Evgeny <zevlg@yandex.ru>
;; Created: Tue Jan 27 08:01:43 MSK 2004
;; Keywords: xwem
;; X-CVS: $Id: xwem-framei.el,v 1.3 2004/05/05 22:43:07 lg Exp $

;; This file is part of XWEM.

;; XWEM is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; XWEM is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
;; License for more details.

;; You should have received a copy of the GNU General Public License
;; along with XEmacs; see the file COPYING.  If not, write to the Free
;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.

;;; Synched up with: Not in FSF

;;; Commentary:

;; When switching frames indicate frame number using xwem-osd.
;;
;; Add something like this to your xwemrc.el to start using frame
;; indicator:
;;
;;   (autoload 'xwem-framei-init "xwem-framei")
;;   (add-hook 'xwem-after-init-hook 'xwem-framei-init)
;;

;;; Code:

(require 'xwem-osd)

(defgroup xwem-framei nil
  "*Group to customize xwem frame indicator."
  :prefix "xwem-framei-"
  :group 'xwem-frame)

(defcustom xwem-framei-showtime 1
  "Period of time in second while xwem framei is shown."
  :type 'number
  :group 'xwem-framei)

(defcustom xwem-framei-xoffset 20
  "*X Offset from top left frame corner in pixels, where to show framei."
  :type 'number
  :group 'xwem-framei)

(defcustom xwem-framei-yoffset 20
  "*Y Offset from top left frame corner in pixels, where to show framei."
  :type 'number
  :group 'xwem-framei)

(defcustom xwem-framei-show-frame-name t
  "*Non-nil mean show frame name aswell as frame number."
  :type 'boolean
  :group 'xwem-framei)

(defface xwem-framei-face
  `((t (:foreground "green2" :size 128 :family "helvetica")))
  "*Face used to draw frame number."
  :group 'xwem-framei)

(defcustom xwem-framei-select-face-function 'xwem-framei-default-sff
  "*Function called with one arg - frame and should return face, which
will be used.  Function can look like this:

(cond ((string= \"Devel\" (xwem-frame-name frame))
       (get-face 'my-xwem-fi-devel-face))
      ((string= \"Inet\" (xwem-frame-name frame))
       (get-face 'my-xwem-fi-inet-face))
      )

To use different faces for different frames."
  :type 'function
  :group 'xwem-framei)


;;; Internal variables
(defvar xwem-framei-osd nil
  "OSD for frame indicator.")

(defvar xwem-framei-itimer nil
  "itimer for frame indicator.")

(defun xwem-framei-hidder ()
  (xwem-osd-hide xwem-framei-osd)
  (setq xwem-framei-itimer nil)
  )


(defun xwem-framei-default-sff (frame)
  "Default `xwem-framei-select-face-function'."
  (get-face 'xwem-framei-face))

;;; Functions
(defun xwem-framei-handle-switch (ofr nfr)
  "Handle frame switching."
  (let ((frgeom (xwem-frame-xgeom nfr)))

    (xwem-osd-move xwem-framei-osd (+ xwem-framei-xoffset (X-Geom-x frgeom))
		   (+ xwem-framei-yoffset (X-Geom-y frgeom)))

    ;; Change
    (let ((fface (funcall xwem-framei-select-face-function nfr)))
      (unless (facep fface)
        (setq fface 'xwem-framei-face))
      (xwem-osd-set-color xwem-framei-osd (face-foreground-name fface))
      (xwem-osd-set-font xwem-framei-osd (face-font-name fface)))

    ;; XXX Format is hard coded
    (xwem-osd-text xwem-framei-osd
                   (if xwem-framei-show-frame-name
                       (format "[%d] %s" (xwem-frame-num nfr) (xwem-frame-name nfr))
                     (format "%d" (xwem-frame-num nfr))))
    (xwem-osd-show xwem-framei-osd)

    (when (itimerp xwem-framei-itimer)
      (delete-itimer xwem-framei-itimer)
      (setq xwem-framei-itimer nil))
    (setq xwem-framei-itimer
          (start-itimer "xwem-framei-timer" 'xwem-framei-hidder xwem-framei-showtime))
    ))

;;;###autoload
(defun xwem-framei-init (&optional xdpy)
  "Initialize xwem frame indicator on display XDPY."
  (unless xdpy
    (setq xdpy (xwem-dpy)))

  (let ((xwem-osd-always-ontop nil)
        (rgeom (XGetGeometry xdpy (XDefaultRootWindow xdpy))))
    (setq xwem-framei-osd (xwem-osd-create xdpy 0 0 (X-Geom-width rgeom) (X-Geom-height rgeom))))

  (xwem-osd-set-color xwem-framei-osd (face-foreground-name 'xwem-framei-face))
  (xwem-osd-set-font xwem-framei-osd (face-font-name 'xwem-framei-face))
  
  (add-hook 'xwem-frame-switch-hook 'xwem-framei-handle-switch))

(defun xwem-framei-stop ()
  "Stop xwem-framei."
  (remove-hook 'xwem-frame-switch-hook 'xwem-framei-handle-switch)
  (when xwem-framei-itimer
    (delete-itimer xwem-framei-itimer))

  (when (xwem-osd-p xwem-framei-osd)
    (xwem-osd-destroy xwem-framei-osd)))

;;;; Frame indicator dockapp
(defvar xwem-framei-dockapp-keymap
  (let ((map (make-sparse-keymap)))
    (set-keymap-default-binding map (lambda () (interactive))) ; ignorance
    (define-key map [button3] 'xwem-framei-dockapp-frames-menu)
    map)
  "Keymap used for framei osd.")

(defface xwem-framei-dockapp-face
  `((t (:foreground "magenta4" :background "black" :bold t)))
  "Face used to draw in framei dockapp."
  :group 'xwem-faces)

;;;###autoload
(defcustom xwem-framei-dockapp-format-function 'xwem-framei-dockapp-default-format
  "Function passed with one arg - frame, should return string to display."
  :type 'funtion
  :group 'xwem-framei)

(defun xwem-framei-dockapp-default-format (frame)
  "Default function used in `xwem-framei-dockapp-format-function'.
Return string in form \"NUM: NAME\""
  (format "%d:%s" (xwem-frame-num frame) (xwem-frame-name frame)))

(defvar xwem-framei-dockapp-osd nil
  "Framei's dockapp osd.")

(defun xwem-framei-dockapp-on-frame-switch (orf nfr)
  "To be used in `xwem-frame-switch-hook'."
  (if (not (xwem-osd-p xwem-framei-dockapp-osd))
      ;; Hmm
      (remove-hook 'xwem-frame-switch-hook 'xwem-framei-dockapp-on-frame-switch)

    (if (not (xwem-frame-p nfr))
        (xwem-osd-clear xwem-framei-dockapp-osd)

      (xwem-osd-text xwem-framei-dockapp-osd
                     (funcall xwem-framei-dockapp-format-function nfr)))))

;;;###autoload
(defun xwem-framei-start-dockapp (&optional xdpy width height)
  "Start frameindicator as dockapp.
XDPY   - display where run dockapp (default is `xwem-dpy').
WIDTH  - Dockapp width (default is 24).
HEIGHT - Dockapp height (default is 24)."
  (unless xdpy
    (setq xdpy (xwem-dpy)))
  (unless width
    (setq width (* (face-width 'xwem-framei-dockapp-face) 8)))
  (unless height
    (setq height (face-height 'xwem-framei-dockapp-face)))

  (setq xwem-framei-dockapp-osd
        (xwem-osd-create-dock xdpy width height
                              (list 'keymap xwem-framei-dockapp-keymap)))
  (xwem-osd-set-font xwem-framei-dockapp-osd
                     (face-font-name 'xwem-framei-dockapp-face))
  (xwem-osd-set-color xwem-framei-dockapp-osd
                      (face-foreground-name 'xwem-framei-dockapp-face))

  ;; Try to display current frame
  (xwem-framei-dockapp-on-frame-switch nil (xwem-frame-selected))

  ;; Add frame switching hook
  (add-hook 'xwem-frame-switch-hook 'xwem-framei-dockapp-on-frame-switch)
  )

(defun xwem-framei-stop-dockapp ()
  "Stop framei dockapp, if any."
  (when (xwem-osd-p xwem-framei-dockapp-osd)
    (xwem-osd-destroy xwem-framei-dockapp-osd))
  )

;; commands
(define-xwem-command xwem-framei-dockapp-frames-menu ()
  "Popup frames menu."
  (xwem-interactive)

  (xwem-popup-menu (list "XWEM Frames" :filter 
                         (lambda (not-used)
                           (mapcar (lambda (el)
                                     (let ((fn (xwem-frame-num el)))
                                       (vector
                                        (concat "Frame " (int-to-string fn) ": " (xwem-frame-name el))
                                        `(xwem-frame-switch-nth ,fn))))
                                   xwem-frames-list))))
  )


(provide 'xwem-framei)

;;; xwem-framei.el ends here
