comparison lisp/custom/wid-edit.el @ 116:9f59509498e1 r20-1b10

Import from CVS: tag r20-1b10
author cvs
date Mon, 13 Aug 2007 09:23:06 +0200
parents c53a95d3c46d
children 7d55a9ba150c
comparison
equal deleted inserted replaced
115:f109f7dabbe2 116:9f59509498e1
2 ;; 2 ;;
3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 ;; 4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Keywords: extensions 6 ;; Keywords: extensions
7 ;; Version: 1.65 7 ;; Version: 1.68
8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10 ;;; Commentary: 10 ;;; Commentary:
11 ;; 11 ;;
12 ;; See `widget.el'. 12 ;; See `widget.el'.
22 22
23 (eval-and-compile 23 (eval-and-compile
24 (autoload 'pp-to-string "pp") 24 (autoload 'pp-to-string "pp")
25 (autoload 'Info-goto-node "info") 25 (autoload 'Info-goto-node "info")
26 26
27 (when (string-match "XEmacs" emacs-version)
28 (require 'overlay))
29
27 (if (string-match "XEmacs" emacs-version) 30 (if (string-match "XEmacs" emacs-version)
28 ;; XEmacs spell `intangible' as `atomic'. 31 ;; XEmacs spell `intangible' as `atomic'.
29 (defun widget-make-intangible (from to side) 32 (defun widget-make-intangible (from to side)
30 "Make text between FROM and TO atomic with regard to movement. 33 "Make text between FROM and TO atomic with regard to movement.
31 Third argument should be `start-open' if it should be sticky to the rear, 34 Third argument should be `start-open' if it should be sticky to the rear,
378 (delete-region (point-min) (1+ (point-min))) 381 (delete-region (point-min) (1+ (point-min)))
379 (delete-region (1- (point-max)) (point-max)) 382 (delete-region (1- (point-max)) (point-max))
380 (goto-char (point-max)) 383 (goto-char (point-max))
381 result))) 384 result)))
382 385
386 (defface widget-inactive-face '((((class grayscale color)
387 (background dark))
388 (:foreground "light gray"))
389 (((class grayscale color)
390 (background light))
391 (:foreground "dark gray"))
392 (t
393 (:italic t)))
394 "Face used for inactive widgets."
395 :group 'widgets)
396
397 (defun widget-specify-inactive (widget from to)
398 "Make WIDGET inactive for user modifications."
399 (unless (widget-get widget :inactive)
400 (let ((overlay (make-overlay from to nil t nil)))
401 (overlay-put overlay 'face 'widget-inactive-face)
402 (overlay-put overlay 'evaporate 't)
403 (overlay-put overlay (if (string-match "XEmacs" emacs-version)
404 'read-only
405 'modification-hooks) '(widget-overlay-inactive))
406 (widget-put widget :inactive overlay))))
407
408 (defun widget-overlay-inactive (&rest junk)
409 "Ignoring the arguments, signal an error."
410 (unless inhibit-read-only
411 (error "Attempt to modify inactive widget")))
412
413
414 (defun widget-specify-active (widget)
415 "Make WIDGET active for user modifications."
416 (let ((inactive (widget-get widget :inactive)))
417 (when inactive
418 (delete-overlay inactive)
419 (widget-put widget :inactive nil))))
420
383 ;;; Widget Properties. 421 ;;; Widget Properties.
384 422
385 (defsubst widget-type (widget) 423 (defsubst widget-type (widget)
386 "Return the type of WIDGET, a symbol." 424 "Return the type of WIDGET, a symbol."
387 (car widget)) 425 (car widget))
438 ((and vals 476 ((and vals
439 (widget-apply widget :match (car vals))) 477 (widget-apply widget :match (car vals)))
440 (cons (list (car vals)) (cdr vals))) 478 (cons (list (car vals)) (cdr vals)))
441 (t nil))) 479 (t nil)))
442 480
481 (defun widget-apply-action (widget &optional event)
482 "Apply :action in WIDGET in response to EVENT."
483 (if (widget-apply widget :active)
484 (widget-apply widget :action event)
485 (error "Attempt to perform action on inactive widget")))
486
443 ;;; Glyphs. 487 ;;; Glyphs.
444 488
445 (defcustom widget-glyph-directory (concat data-directory "custom/") 489 (defcustom widget-glyph-directory (concat data-directory "custom/")
446 "Where widget glyphs are located. 490 "Where widget glyphs are located.
447 If this variable is nil, widget will try to locate the directory 491 If this variable is nil, widget will try to locate the directory
657 (defun widget-field-activate (pos &optional event) 701 (defun widget-field-activate (pos &optional event)
658 "Activate the ediable field at point." 702 "Activate the ediable field at point."
659 (interactive "@d") 703 (interactive "@d")
660 (let ((field (get-text-property pos 'field))) 704 (let ((field (get-text-property pos 'field)))
661 (if field 705 (if field
662 (widget-apply field :action event) 706 (widget-apply-action field event)
663 (call-interactively 707 (call-interactively
664 (lookup-key widget-global-map (this-command-keys)))))) 708 (lookup-key widget-global-map (this-command-keys))))))
665 709
666 (defun widget-button-click (event) 710 (defun widget-button-click (event)
667 "Activate button below mouse pointer." 711 "Activate button below mouse pointer."
668 (interactive "@e") 712 (interactive "@e")
669 (cond ((and (fboundp 'event-glyph) 713 (cond ((and (fboundp 'event-glyph)
670 (event-glyph event)) 714 (event-glyph event))
671 (let ((widget (glyph-property (event-glyph event) 'widget))) 715 (let ((widget (glyph-property (event-glyph event) 'widget)))
672 (if widget 716 (if widget
673 (widget-apply widget :action event) 717 (widget-apply-action widget event)
674 (message "You clicked on a glyph.")))) 718 (message "You clicked on a glyph."))))
675 ((event-point event) 719 ((event-point event)
676 (let ((button (get-text-property (event-point event) 'button))) 720 (let ((button (get-text-property (event-point event) 'button)))
677 (if button 721 (if button
678 (widget-apply button :action event) 722 (widget-apply-action button event)
679 (call-interactively 723 (call-interactively
680 (or (lookup-key widget-global-map [ button2 ]) 724 (or (lookup-key widget-global-map [ button2 ])
681 (lookup-key widget-global-map [ down-mouse-2 ]) 725 (lookup-key widget-global-map [ down-mouse-2 ])
682 (lookup-key widget-global-map [ mouse-2])))))) 726 (lookup-key widget-global-map [ mouse-2]))))))
683 (t 727 (t
688 (interactive "@e") 732 (interactive "@e")
689 (if (and (fboundp 'event-glyph) 733 (if (and (fboundp 'event-glyph)
690 (event-glyph event)) 734 (event-glyph event))
691 (let ((widget (glyph-property (event-glyph event) 'widget))) 735 (let ((widget (glyph-property (event-glyph event) 'widget)))
692 (if widget 736 (if widget
693 (widget-apply widget :action event) 737 (widget-apply-action widget event)
694 (message "You clicked on a glyph."))) 738 (message "You clicked on a glyph.")))
695 (call-interactively (lookup-key widget-global-map (this-command-keys))))) 739 (call-interactively (lookup-key widget-global-map (this-command-keys)))))
696 740
697 (defun widget-button-press (pos &optional event) 741 (defun widget-button-press (pos &optional event)
698 "Activate button at POS." 742 "Activate button at POS."
699 (interactive "@d") 743 (interactive "@d")
700 (let ((button (get-text-property pos 'button))) 744 (let ((button (get-text-property pos 'button)))
701 (if button 745 (if button
702 (widget-apply button :action event) 746 (widget-apply-action button event)
703 (let ((command (lookup-key widget-global-map (this-command-keys)))) 747 (let ((command (lookup-key widget-global-map (this-command-keys))))
704 (when (commandp command) 748 (when (commandp command)
705 (call-interactively command)))))) 749 (call-interactively command))))))
706 750
707 (defun widget-move (arg) 751 (defun widget-move (arg)
945 :delete 'widget-default-delete 989 :delete 'widget-default-delete
946 :value-set 'widget-default-value-set 990 :value-set 'widget-default-value-set
947 :value-inline 'widget-default-value-inline 991 :value-inline 'widget-default-value-inline
948 :menu-tag-get 'widget-default-menu-tag-get 992 :menu-tag-get 'widget-default-menu-tag-get
949 :validate (lambda (widget) nil) 993 :validate (lambda (widget) nil)
994 :active 'widget-default-active
995 :activate 'widget-specify-active
996 :deactivate 'widget-default-deactivate
950 :action 'widget-default-action 997 :action 'widget-default-action
951 :notify 'widget-default-notify) 998 :notify 'widget-default-notify)
952 999
953 (defun widget-default-create (widget) 1000 (defun widget-default-create (widget)
954 "Create WIDGET at point in the current buffer." 1001 "Create WIDGET at point in the current buffer."
1075 (let ((from (widget-get widget :from)) 1122 (let ((from (widget-get widget :from))
1076 (to (widget-get widget :to)) 1123 (to (widget-get widget :to))
1077 (inhibit-read-only t) 1124 (inhibit-read-only t)
1078 after-change-functions) 1125 after-change-functions)
1079 (widget-apply widget :value-delete) 1126 (widget-apply widget :value-delete)
1080 (delete-region from to) 1127 (when (< from to)
1128 ;; Kludge: this doesn't need to be true for empty formats.
1129 (delete-region from to))
1081 (set-marker from nil) 1130 (set-marker from nil)
1082 (set-marker to nil))) 1131 (set-marker to nil)))
1083 1132
1084 (defun widget-default-value-set (widget value) 1133 (defun widget-default-value-set (widget value)
1085 ;; Recreate widget with new value. 1134 ;; Recreate widget with new value.
1098 (defun widget-default-menu-tag-get (widget) 1147 (defun widget-default-menu-tag-get (widget)
1099 ;; Use tag or value for menus. 1148 ;; Use tag or value for menus.
1100 (or (widget-get widget :menu-tag) 1149 (or (widget-get widget :menu-tag)
1101 (widget-get widget :tag) 1150 (widget-get widget :tag)
1102 (widget-princ-to-string (widget-get widget :value)))) 1151 (widget-princ-to-string (widget-get widget :value))))
1152
1153 (defun widget-default-active (widget)
1154 "Return t iff this widget active (user modifiable)."
1155 (and (not (widget-get widget :inactive))
1156 (let ((parent (widget-get widget :parent)))
1157 (or (null parent)
1158 (widget-apply parent :active)))))
1159
1160 (defun widget-default-deactivate (widget)
1161 "Make WIDGET inactive for user modifications."
1162 (widget-specify-inactive widget
1163 (widget-get widget :from)
1164 (widget-get widget :to)))
1103 1165
1104 (defun widget-default-action (widget &optional event) 1166 (defun widget-default-action (widget &optional event)
1105 ;; Notify the parent when a widget change 1167 ;; Notify the parent when a widget change
1106 (let ((parent (widget-get widget :parent))) 1168 (let ((parent (widget-get widget :parent)))
1107 (when parent 1169 (when parent
1194 (make-glyph (car (aref gui 1))))) 1256 (make-glyph (car (aref gui 1)))))
1195 (insert text)))) 1257 (insert text))))
1196 1258
1197 (defun widget-gui-action (widget) 1259 (defun widget-gui-action (widget)
1198 "Apply :action for WIDGET." 1260 "Apply :action for WIDGET."
1199 (widget-apply widget :action (this-command-keys))) 1261 (widget-apply-action widget (this-command-keys)))
1200 1262
1201 ;;; The `link' Widget. 1263 ;;; The `link' Widget.
1202 1264
1203 (define-widget 'link 'item 1265 (define-widget 'link 'item
1204 "An embedded link." 1266 "An embedded link."
1490 "A checkbox toggle." 1552 "A checkbox toggle."
1491 :format "%[%v%]" 1553 :format "%[%v%]"
1492 :on "[X]" 1554 :on "[X]"
1493 :on-glyph "check1" 1555 :on-glyph "check1"
1494 :off "[ ]" 1556 :off "[ ]"
1495 :off-glyph "check0") 1557 :off-glyph "check0"
1558 :action 'widget-checkbox-action)
1559
1560 (defun widget-checkbox-action (widget &optional event)
1561 "Toggle checkbox, notify parent, and set active state of sibling."
1562 (widget-toggle-action widget event)
1563 (let ((sibling (widget-get-sibling widget)))
1564 (when sibling
1565 (if (widget-value widget)
1566 (widget-apply sibling :activate)
1567 (widget-apply sibling :deactivate)))))
1496 1568
1497 ;;; The `checklist' Widget. 1569 ;;; The `checklist' Widget.
1498 1570
1499 (define-widget 'checklist 'default 1571 (define-widget 'checklist 'default
1500 "A multiple choice widget." 1572 "A multiple choice widget."
1547 :value (not (null chosen)) 1619 :value (not (null chosen))
1548 button-args))) 1620 button-args)))
1549 ((eq escape ?v) 1621 ((eq escape ?v)
1550 (setq child 1622 (setq child
1551 (cond ((not chosen) 1623 (cond ((not chosen)
1552 (widget-create-child widget type)) 1624 (let ((child (widget-create-child widget type)))
1625 (widget-apply child :deactivate)
1626 child))
1553 ((widget-get type :inline) 1627 ((widget-get type :inline)
1554 (widget-create-child-value 1628 (widget-create-child-value
1555 widget type (cdr chosen))) 1629 widget type (cdr chosen)))
1556 (t 1630 (t
1557 (widget-create-child-value 1631 (widget-create-child-value
1733 button-args))) 1807 button-args)))
1734 ((eq escape ?v) 1808 ((eq escape ?v)
1735 (setq child (if chosen 1809 (setq child (if chosen
1736 (widget-create-child-value 1810 (widget-create-child-value
1737 widget type value) 1811 widget type value)
1738 (widget-create-child widget type)))) 1812 (widget-create-child widget type)))
1813 (unless chosen
1814 (widget-apply child :deactivate)))
1739 (t 1815 (t
1740 (error "Unknown escape `%c'" escape))))) 1816 (error "Unknown escape `%c'" escape)))))
1741 ;; Update properties. 1817 ;; Update properties.
1742 (when chosen 1818 (when chosen
1743 (widget-put widget :choice type)) 1819 (widget-put widget :choice type))
1793 (let* ((button (widget-get current :button)) 1869 (let* ((button (widget-get current :button))
1794 (match (and (not found) 1870 (match (and (not found)
1795 (widget-apply current :match value)))) 1871 (widget-apply current :match value))))
1796 (widget-value-set button match) 1872 (widget-value-set button match)
1797 (if match 1873 (if match
1798 (widget-value-set current value)) 1874 (progn
1875 (widget-value-set current value)
1876 (widget-apply current :activate))
1877 (widget-apply current :deactivate))
1799 (setq found (or found match)))))) 1878 (setq found (or found match))))))
1800 1879
1801 (defun widget-radio-validate (widget) 1880 (defun widget-radio-validate (widget)
1802 ;; Valid if we have made a valid choice. 1881 ;; Valid if we have made a valid choice.
1803 (let ((children (widget-get widget :children)) 1882 (let ((children (widget-get widget :children))
1820 (while children 1899 (while children
1821 (setq current (car children) 1900 (setq current (car children)
1822 children (cdr children)) 1901 children (cdr children))
1823 (let* ((button (widget-get current :button))) 1902 (let* ((button (widget-get current :button)))
1824 (cond ((eq child button) 1903 (cond ((eq child button)
1825 (widget-value-set button t)) 1904 (widget-value-set button t)
1905 (widget-apply current :activate))
1826 ((widget-value button) 1906 ((widget-value button)
1827 (widget-value-set button nil))))))) 1907 (widget-value-set button nil)
1908 (widget-apply current :deactivate)))))))
1828 ;; Pass notification to parent. 1909 ;; Pass notification to parent.
1829 (widget-apply widget :notify child event)) 1910 (widget-apply widget :notify child event))
1830 1911
1831 ;;; The `insert-button' Widget. 1912 ;;; The `insert-button' Widget.
1832 1913
1965 (widget-put widget :children (cons child children)) 2046 (widget-put widget :children (cons child children))
1966 (while (not (eq (car (cdr children)) before)) 2047 (while (not (eq (car (cdr children)) before))
1967 (setq children (cdr children))) 2048 (setq children (cdr children)))
1968 (setcdr children (cons child (cdr children))))))) 2049 (setcdr children (cons child (cdr children)))))))
1969 (widget-setup) 2050 (widget-setup)
1970 (widget-apply widget :notify widget)) 2051 widget (widget-apply widget :notify widget))
1971 2052
1972 (defun widget-editable-list-delete-at (widget child) 2053 (defun widget-editable-list-delete-at (widget child)
1973 ;; Delete child from list of children. 2054 ;; Delete child from list of children.
1974 (save-excursion 2055 (save-excursion
1975 (let ((buttons (copy-list (widget-get widget :buttons))) 2056 (let ((buttons (copy-list (widget-get widget :buttons)))