*** empty log message ***
[bpt/emacs.git] / lisp / wid-edit.el
index 34d9fb7..a3821dc 100644 (file)
@@ -1,6 +1,6 @@
 ;;; wid-edit.el --- Functions for creating and using widgets -*-byte-compile-dynamic: t;-*-
 ;;
-;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
@@ -851,47 +851,65 @@ Recommended as a parent keymap for modes using widgets.")
   "Invoke the button that the mouse is pointing at."
   (interactive "@e")
   (if (widget-event-point event)
-      (save-excursion
-       (mouse-set-point event)
-       (let* ((pos (widget-event-point event))
-              (button (get-char-property pos 'button)))
-         (if button
-             (let* ((overlay (widget-get button :button-overlay))
-                    (face (overlay-get overlay 'face))
-                    (mouse-face (overlay-get overlay 'mouse-face)))
-               (unwind-protect
-                   (let ((track-mouse t))
-                     (save-excursion
-                       (when face      ; avoid changing around image
-                         (overlay-put overlay
-                                      'face widget-button-pressed-face)
-                         (overlay-put overlay
-                                      'mouse-face widget-button-pressed-face))
-                       (unless (widget-apply button :mouse-down-action event)
-                         (while (not (widget-button-release-event-p event))
-                           (setq event (read-event)
-                                 pos (widget-event-point event))
-                           (if (and pos
-                                    (eq (get-char-property pos 'button)
-                                        button))
-                               (when face
-                                 (overlay-put overlay
-                                              'face
-                                              widget-button-pressed-face)
-                                 (overlay-put overlay
-                                              'mouse-face
-                                              widget-button-pressed-face))
-                             (overlay-put overlay 'face face)
-                             (overlay-put overlay 'mouse-face mouse-face))))
-                       (when (and pos
-                                  (eq (get-char-property pos 'button) button))
-                         (widget-apply-action button event))))
-                 (overlay-put overlay 'face face)
-                 (overlay-put overlay 'mouse-face mouse-face)))
-           (let ((up t)
-                 command)
-             ;; Find the global command to run, and check whether it
-             ;; is bound to an up event.
+      (let* ((pos (widget-event-point event))
+            (button (get-char-property pos 'button)))
+       (if button
+           ;; Mouse click on a widget button.  Do the following
+           ;; in a save-excursion so that the click on the button
+           ;; doesn't change point.
+           (save-selected-window
+             (save-excursion
+               (mouse-set-point event)
+               (let* ((overlay (widget-get button :button-overlay))
+                      (face (overlay-get overlay 'face))
+                      (mouse-face (overlay-get overlay 'mouse-face)))
+                 (unwind-protect
+                     ;; Read events, including mouse-movement events
+                     ;; until we receive a release event.  Highlight/
+                     ;; unhighlight the button the mouse was initially
+                     ;; on when we move over it.
+                     (let ((track-mouse t))
+                       (save-excursion
+                         (when face    ; avoid changing around image
+                           (overlay-put overlay
+                                        'face widget-button-pressed-face)
+                           (overlay-put overlay
+                                        'mouse-face widget-button-pressed-face))
+                         (unless (widget-apply button :mouse-down-action event)
+                           (while (not (widget-button-release-event-p event))
+                             (setq event (read-event)
+                                   pos (widget-event-point event))
+                             (if (and pos
+                                      (eq (get-char-property pos 'button)
+                                          button))
+                                 (when face
+                                   (overlay-put overlay
+                                                'face
+                                                widget-button-pressed-face)
+                                   (overlay-put overlay
+                                                'mouse-face
+                                                widget-button-pressed-face))
+                               (overlay-put overlay 'face face)
+                               (overlay-put overlay 'mouse-face mouse-face))))
+
+                         ;; When mouse is released over the button, run
+                         ;; its action function.
+                         (when (and pos
+                                    (eq (get-char-property pos 'button) button))
+                           (widget-apply-action button event))))
+                   (overlay-put overlay 'face face)
+                   (overlay-put overlay 'mouse-face mouse-face))))
+
+               (unless (pos-visible-in-window-p (widget-event-point event))
+                 (mouse-set-point event)
+                 (beginning-of-line)
+                 (recenter)))
+
+           (let ((up t) command)
+             ;; Mouse click not on a widget button.  Find the global
+             ;; command to run, and check whether it is bound to an
+             ;; up event.
+             (mouse-set-point event)
              (if (memq (event-basic-type event) '(mouse-1 down-mouse-1))
                  (cond ((setq command  ;down event
                               (lookup-key widget-global-map [down-mouse-1]))
@@ -909,10 +927,6 @@ Recommended as a parent keymap for modes using widgets.")
                  (setq event (read-event))))
              (when command
                (call-interactively command)))))
-         (unless (pos-visible-in-window-p (widget-event-point event))
-           (mouse-set-point event)
-           (beginning-of-line)
-           (recenter)))
     (message "You clicked somewhere weird.")))
 
 (defun widget-button-press (pos &optional event)
@@ -2910,6 +2924,7 @@ It will read a file name from the minibuffer when invoked."
 ;;;    (widget-setup)
 ;;;    (widget-apply widget :notify widget event)))
 
+;; Fixme: use file-name-as-directory.
 (define-widget 'directory 'file
   "A directory widget.
 It will read a directory name from the minibuffer when invoked."
@@ -2960,6 +2975,7 @@ It will read a directory name from the minibuffer when invoked."
   :prompt-match 'fboundp
   :prompt-history 'widget-function-prompt-value-history
   :action 'widget-field-action
+  :match-alternatives '(functionp)
   :validate (lambda (widget)
              (unless (functionp (widget-value widget))
                (widget-put widget :error (format "Invalid function: %S"
@@ -2972,7 +2988,6 @@ It will read a directory name from the minibuffer when invoked."
   "History of input to `widget-variable-prompt-value'.")
 
 (define-widget 'variable 'symbol
-  ;; Should complete on variables.
   "A Lisp variable."
   :prompt-match 'boundp
   :prompt-history 'widget-variable-prompt-value-history
@@ -3193,10 +3208,11 @@ To use this type, you must define :match or :match-alternatives."
 (defun widget-plist-convert-widget (widget)
   ;; Handle `:options'.
   (let* ((options (widget-get widget :options))
+        (widget-plist-value-type (widget-get widget :value-type))
         (other `(editable-list :inline t
                                (group :inline t
                                       ,(widget-get widget :key-type)
-                                      ,(widget-get widget :value-type))))
+                                      ,widget-plist-value-type)))
         (args (if options
                   (list `(checklist :inline t
                                     :greedy t
@@ -3237,10 +3253,11 @@ To use this type, you must define :match or :match-alternatives."
 (defun widget-alist-convert-widget (widget)
   ;; Handle `:options'.
   (let* ((options (widget-get widget :options))
+        (widget-alist-value-type (widget-get widget :value-type))
         (other `(editable-list :inline t
                                (cons :format "%v"
                                      ,(widget-get widget :key-type)
-                                     ,(widget-get widget :value-type))))
+                                     ,widget-alist-value-type)))
         (args (if options
                   (list `(checklist :inline t
                                     :greedy t
@@ -3346,6 +3363,7 @@ To use this type, you must define :match or :match-alternatives."
 \f
 ;;; The `color' Widget.
 
+;; Fixme: match 
 (define-widget 'color 'editable-field
   "Choose a color name (with sample)."
   :format "%t: %v (%{sample%})\n"
@@ -3380,14 +3398,16 @@ To use this type, you must define :match or :match-alternatives."
 (defun widget-color-sample-face-get (widget)
   (let* ((value (condition-case nil
                    (widget-value widget)
-                 (error (widget-get widget :value))))
-        (symbol (intern (concat "fg:" value))))
-    (condition-case nil
-       (facemenu-get-face symbol)
-      (error 'default))))
+                 (error (widget-get widget :value)))))
+    (if (color-defined-p value)
+       (let ((symbol (intern (concat "fg:" value))))
+         (condition-case nil
+             (facemenu-get-face symbol)
+           (error 'default)))
+      'default)))
 
 (defun widget-color-action (widget &optional event)
-  ;; Prompt for a color.
+  "Prompt for a color."
   (let* ((tag (widget-apply widget :menu-tag-get))
         (prompt (concat tag ": "))
         (value (widget-value widget))