;;; uko-buttons.el -- buttons used in UKO-II

;; Copyright (C) 2003 Michael Kuehn, Universität Koblenz-Landau

;; Author: Michael Kuehn <kuehn@uni-koblenz.de>
;; Maintainer: Michael Kuehn <kuehn@uni-koblenz.de>
;; Created: March 2003
;; 
;; $Id: uko-buttons.el,v 1.12 2003/10/30 12:47:52 deee Exp $

;;;; UKO_BUTTONS
;;;; defines and sets up the UKO-II button windows and their displayed labels
;;;; defines the buffers for the windows
;;;; defines the extents in the windows
;;;; defines characteristics of the windows such as window-height, window-width
;;;; and number of letters displayed per line
;;;; defines a mouse-keymap and a function for the inverting faces of button windows
;;;; 
;;;; ------------------------------------------------------------------------

;; defining amount of time (in seconds) showing the pressed button inverted 
(defvar uko-invert-button-time 0.1
  "Time delay for redrawing inverted button.") 

;; defining  number of letters in one line of a button window
(defvar uko-layout-letters-per-line 5
  "Number of letters displayed in one line of a button window.")

;; old
(defvar uko-button-label-move (list "Backward2" "Done" "Forward" "Cancel")
  "Button labels for the move state.")

;; defining the button windows
;; by default set to nil
(defvar uko-button-window-1 nil)
(defvar uko-button-window-2 nil)
(defvar uko-button-window-3 nil)
(defvar uko-button-window-4 nil)
(defvar uko-button-windows)

;; vector for the button-window-buffers
(defvar uko-button-buffer 
  (vector
   (get-buffer-create "UKO Button 1")
   (get-buffer-create "UKO Button 2")
   (get-buffer-create "UKO Button 3")
   (get-buffer-create "UKO Button 4")
   ))


;; defines the height of each of the button windows
;; 8 works for most resolutions
(defvar uko-buttons-height 8
  "Height of each of the button windows.")

;; defines four extents, one for each button window
(defvar uko-button-extent 
  (vector nil nil nil nil)
  "Extents for the UKO button buffers.")

;; define a physical-switch for the left mouse button
(defvar uko-physical-mouse-button [(button1)])


;; creates windows for the buttons and assigns buffers to them
;; evaluates the sizes of the windows
;; labels the modelines
(defun uko-keyboard-init-buttons ()
  "Create and size the windows for the buttons and assign buffers to them."
;  (let ( (wh (* (/ (window-height) 4) 3) ))
  (let ((wh (- (window-height) uko-buttons-height)))
    (setq uko-button-window-1 (split-window (selected-window) wh nil) )
    (setq  uko-button-window-3
	  (split-window  uko-button-window-1
			(/ (window-width  uko-button-window-1) 2) t) )
    (setq  uko-button-window-2
	  (split-window  uko-button-window-1
			(/ (window-width  uko-button-window-1) 2) t) )
    (setq  uko-button-window-4
	  (split-window  uko-button-window-3
			(/ (window-width  uko-button-window-3) 2) t) )
    )
  (setq uko-button-windows 
	(vector uko-button-window-4 uko-button-window-1 uko-button-window-2 uko-button-window-3) )
  (set-window-buffer uko-button-window-1 (aref uko-button-buffer 0))
  (set-window-buffer uko-button-window-2 (aref uko-button-buffer 1))
  (set-window-buffer uko-button-window-3 (aref uko-button-buffer 2))
  (set-window-buffer uko-button-window-4 (aref uko-button-buffer 3))
  (save-current-buffer
    (set-buffer (aref uko-button-buffer 0))
    (setq modeline-format (list " Button 1"))
    (setq fill-column (window-width uko-button-window-1))
    (local-set-key uko-physical-mouse-button 'uko-noop)

    (set-buffer (aref uko-button-buffer 1))
    (setq modeline-format (list " Button 2"))
    (setq fill-column (window-width uko-button-window-2))
    (local-set-key uko-physical-mouse-button 'uko-noop)

    (set-buffer (aref uko-button-buffer 2))
    (setq modeline-format (list " Button 3"))
    (setq fill-column (window-width uko-button-window-3))
    (local-set-key uko-physical-mouse-button 'uko-noop)

    (set-buffer (aref uko-button-buffer 3))
    (setq modeline-format (list " Button 0"))
    (setq fill-column (window-width uko-button-window-4))
    (local-set-key uko-physical-mouse-button 'uko-noop)
    )
  )
 
;Fenster beschreiben ?
(defun uko-display-keyboard-layout (kb &optional text)
  "Display keyboard layout KB in bottom line."
  (message (concat (if text text "")
   (mapconcat (lambda (k) (mapconcat (lambda (x) (string x)) k " ")) kb "    ")
   ) )
  )


;; Changes the current labels of the buttons to those in kb (which is a list of strings) 
(defun uko-display-keyboard-buttons (kb)
  "Change current button captions to those in kb (which is a list of strings)."
  (uko-display-button 0 (nth 0 kb)) ;;nth: Display Nth element from list
  (uko-display-button 1 (nth 1 kb))
  (uko-display-button 2 (nth 2 kb))
  (uko-display-button 3 (nth 3 kb))
  )


;; displays string-list from list d on button b
;; creates an extent in button b from first pixel in window to last pixel in window
;; sets the mouse-face for the extent
;; and assigns the keymap used for the mouse
(defun uko-display-button (b d)
  "Display label D on button B. Create extent for buttons. Create mouse-face for extents. Assign keymap to button b."
  (save-excursion
    (set-buffer (aref uko-button-buffer b))
    (delete-region (point-min) (point-max))
    (if (listp d)
	(uko-display-button-list d)
     (uko-display-button-list (list d))
      )
    (setf (aref uko-button-extent b) 
	  (make-extent (point-min) (point-max)))
    (set-extent-mouse-face (aref uko-button-extent b) uko-button-mouse-face)
    (set-extent-property (aref uko-button-extent b) 'keymap (uko-button-create-mouse-keymap b))
 ) )

;; creates a mouse-keymap
;; defines four possible keys according to the window in which the mouse action takes place
(defun uko-button-create-mouse-keymap (b)
  "Define mouse-keymap on left mouse button and assign action to it.
According to button in which the left mouse button was pressed"
  (let ((keymap (make-sparse-keymap)))
    (define-key keymap uko-physical-mouse-button 
      (cond ((= b 0) 'uko-key-1)
	((= b 1) 'uko-key-2)
	((= b 2) 'uko-key-3)
	((= b 3) 'uko-key-0)
	)
      )
    keymap
    ) 
 )


;; creates a string of blanks with the length of the window-width of the current button window
;; regulating value 2
(defun full-line (b)
  "Create string of blanks to fill an empty line in the button window."
   (cond ((= b 0) (make-string (- (window-width uko-button-window-1) 2) ? ))
	((= b 1) (make-string (- (window-width uko-button-window-2) 2) ? ))
	((= b 2) (make-string (- (window-width uko-button-window-3) 2) ? ))
	((= b 3) (make-string (- (window-width uko-button-window-4) 2) ? ))
	)
   )

;; creates a string of blanks with the length of:
;; length of a full line minus
;; length of the entered string from the button list minus
;; divided by 2
(defun fill-left ()
  "Create string of blanks with the appropriate length to fill the region between the left window margin and the string from the button list 'bl'."
 (make-string (/(- (length (full-line b)) (string-width(car bl))) 2) ? )
  )

;; creates a string of blanks with the length of: 
;; length of a full line minus
;; length of the entered string from the button list minus
;; length of the string of fill-left
(defun fill-right ()
  "Create a string of blanks with the appropriate length to fill the region between the right window margin and the string from the button list 'bl'."
  (make-string (-(- (length (full-line b)) (length (fill-left))) (string-width (car bl))) ? )
  )
 

;; displays the strings from the button list 'bl' in the button windows and fills
;; empty regions around the text with blanks
(defun uko-display-button-list (bl &optional num)
  "Display the strings from the button list 'bl' in the button windows and fillc empty regions with blanks."
  (when (null num) (setq num 1))
  (if bl 
      (progn
	(insert-string (full-line b)) (newline)
	(insert-string (fill-left))
	(insert-string (car bl))
	(insert-string (fill-right))(newline)
	(uko-display-button-list (cdr bl) (+ num 2))
	)
    (while (< num uko-buttons-height)
      (insert-string (full-line b))
      (newline)
      (setq num (1+ num))))
  )


;; creates a layouted list of the list of strings (which are letters) according to number of
;; letters allowed per line defined in variable uko-layout-letters-per-line
(defun uko-keyboard-layout-button (lett)
  "Return a 'layouted' version of the letter-list."
  (if (null lett) '()
    (let ((l '()) (n uko-layout-letters-per-line))
      (while (and lett (> n 0))
	(setq l (append l (list (car lett) ?\ )))
	(setq lett (cdr lett))
	(setq n (1- n))
	)
      (cons (apply 'string l) (uko-keyboard-layout-button lett))
      ) ) )


;; inverts the face of the selected window for the amount of time defined
;; in variable uko-invert-button-time
(defun uko-button-invert (k)
  "Invert face of the button-window k."
  (let ((button (aref uko-button-windows k)))
    (invert-face 'default button)
    (invert-face uko-button-mouse-face)
    (redraw-frame (window-frame) t)
    (sleep-for uko-invert-button-time) 
    (invert-face 'default button)
    (invert-face uko-button-mouse-face)
    (redraw-frame (window-frame) t)
    )
  )
