aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/cus-edit.el183
-rw-r--r--lisp/wid-edit.el212
-rw-r--r--lisp/widget.el8
3 files changed, 259 insertions, 144 deletions
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index e15a39a015c..c4d6b7f6c2f 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -4,7 +4,7 @@
4;; 4;;
5;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6;; Keywords: help, faces 6;; Keywords: help, faces
7;; Version: 1.9900 7;; Version: 1.9901
8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -517,7 +517,7 @@ if that fails, the doc string with `custom-guess-doc-alist'."
517 "Function used for sorting group members in buffers. 517 "Function used for sorting group members in buffers.
518The value should be useful as a predicate for `sort'. 518The value should be useful as a predicate for `sort'.
519The list to be sorted is the value of the groups `custom-group' property." 519The list to be sorted is the value of the groups `custom-group' property."
520 :type '(radio (function-item 'custom-buffer-sort-alphabetically) 520 :type '(radio (function-item custom-buffer-sort-alphabetically)
521 (function :tag "Other")) 521 (function :tag "Other"))
522 :group 'customize) 522 :group 'customize)
523 523
@@ -539,7 +539,7 @@ sorted after all non-groups."
539 "Function used for sorting group members in menus. 539 "Function used for sorting group members in menus.
540The value should be useful as a predicate for `sort'. 540The value should be useful as a predicate for `sort'.
541The list to be sorted is the value of the groups `custom-group' property." 541The list to be sorted is the value of the groups `custom-group' property."
542 :type '(radio (function-item 'custom-menu-sort-alphabetically) 542 :type '(radio (function-item custom-menu-sort-alphabetically)
543 (function :tag "Other")) 543 (function :tag "Other"))
544 :group 'customize) 544 :group 'customize)
545 545
@@ -1028,8 +1028,8 @@ uninitialized, you should not see this.")
1028 (unknown "?" italic "\ 1028 (unknown "?" italic "\
1029unknown, you should not see this.") 1029unknown, you should not see this.")
1030 (hidden "-" default "\ 1030 (hidden "-" default "\
1031hidden, invoke the state button to show." "\ 1031hidden, invoke the dots above to show." "\
1032group now hidden, invoke the state button to show contents.") 1032group now hidden, invoke the dots above to show contents.")
1033 (invalid "x" custom-invalid-face "\ 1033 (invalid "x" custom-invalid-face "\
1034the value displayed for this item is invalid and cannot be set.") 1034the value displayed for this item is invalid and cannot be set.")
1035 (modified "*" custom-modified-face "\ 1035 (modified "*" custom-modified-face "\
@@ -1088,12 +1088,18 @@ left out, ITEM-DESC will be used.
1088The list should be sorted most significant first.") 1088The list should be sorted most significant first.")
1089 1089
1090(defcustom custom-magic-show 'long 1090(defcustom custom-magic-show 'long
1091 "Show long description of the state of each customization option." 1091 "If non-nil, show textual description of the state.
1092If non-nil and not the symbol `long', only show first word."
1092 :type '(choice (const :tag "no" nil) 1093 :type '(choice (const :tag "no" nil)
1093 (const short) 1094 (const short)
1094 (const long)) 1095 (const long))
1095 :group 'customize) 1096 :group 'customize)
1096 1097
1098(defcustom custom-magic-show-hidden nil
1099 "If non-nil, also show long state description of hidden options."
1100 :type 'boolean
1101 :group 'customize)
1102
1097(defcustom custom-magic-show-button nil 1103(defcustom custom-magic-show-button nil
1098 "Show a magic button indicating the state of each customization option." 1104 "Show a magic button indicating the state of each customization option."
1099 :type 'boolean 1105 :type 'boolean
@@ -1118,6 +1124,7 @@ The list should be sorted most significant first.")
1118 ;; Create compact status report for WIDGET. 1124 ;; Create compact status report for WIDGET.
1119 (let* ((parent (widget-get widget :parent)) 1125 (let* ((parent (widget-get widget :parent))
1120 (state (widget-get parent :custom-state)) 1126 (state (widget-get parent :custom-state))
1127 (hidden (eq state 'hidden))
1121 (entry (assq state custom-magic-alist)) 1128 (entry (assq state custom-magic-alist))
1122 (magic (nth 1 entry)) 1129 (magic (nth 1 entry))
1123 (face (nth 2 entry)) 1130 (face (nth 2 entry))
@@ -1126,13 +1133,14 @@ The list should be sorted most significant first.")
1126 (nth 3 entry))) 1133 (nth 3 entry)))
1127 (lisp (eq (widget-get parent :custom-form) 'lisp)) 1134 (lisp (eq (widget-get parent :custom-form) 'lisp))
1128 children) 1135 children)
1129 (when custom-magic-show 1136 (when (and custom-magic-show
1137 (or custom-magic-show-hidden (not hidden)))
1130 (insert " ") 1138 (insert " ")
1131 (push (widget-create-child-and-convert 1139 (push (widget-create-child-and-convert
1132 widget 'choice-item 1140 widget 'choice-item
1133 :help-echo "\ 1141 :help-echo "\
1134Change the state of this item." 1142Change the state of this item."
1135 :format "%[%t%]" 1143 :format (if hidden "%t" "%[%t%]")
1136 :button-prefix 'widget-push-button-prefix 1144 :button-prefix 'widget-push-button-prefix
1137 :button-suffix 'widget-push-button-suffix 1145 :button-suffix 'widget-push-button-suffix
1138 :mouse-down-action 'widget-magic-mouse-down-action 1146 :mouse-down-action 'widget-magic-mouse-down-action
@@ -1154,8 +1162,10 @@ Change the state of this item."
1154 widget 'choice-item 1162 widget 'choice-item
1155 :mouse-down-action 'widget-magic-mouse-down-action 1163 :mouse-down-action 'widget-magic-mouse-down-action
1156 :button-face face 1164 :button-face face
1165 :button-prefix ""
1166 :button-suffix ""
1157 :help-echo "Change the state." 1167 :help-echo "Change the state."
1158 :format "%[%t%]" 1168 :format (if hidden "%t" "%[%t%]")
1159 :tag (if lisp 1169 :tag (if lisp
1160 (concat "(" magic ")") 1170 (concat "(" magic ")")
1161 (concat "[" magic "]"))) 1171 (concat "[" magic "]")))
@@ -1201,13 +1211,25 @@ Change the state of this item."
1201 (level (widget-get widget :custom-level))) 1211 (level (widget-get widget :custom-level)))
1202 (cond ((eq escape ?l) 1212 (cond ((eq escape ?l)
1203 (when level 1213 (when level
1204 (push (widget-create-child-and-convert 1214 (if (eq state 'hidden)
1205 widget 'item :format "%v " (make-string level ?*)) 1215 (insert-char ?- (* 2 level))
1206 buttons) 1216 (insert "/" (make-string (1- (* 2 level)) ?-)))))
1207 (widget-put widget :buttons buttons))) 1217 ((eq escape ?e)
1218 (when (and level (not (eq state 'hidden)))
1219 (insert "\n\\" (make-string (1- (* 2 level)) ?-) " "
1220 (widget-get widget :tag) " group end ")
1221 (insert (make-string (- 75 (current-column)) ?-) "/\n")))
1222 ((eq escape ?-)
1223 (when level
1224 (if (eq state 'hidden)
1225 (insert-char ?- (- 77 (current-column)))
1226 (insert (make-string (- 76 (current-column)) ?-) "\\"))))
1208 ((eq escape ?L) 1227 ((eq escape ?L)
1209 (when (eq state 'hidden) 1228 (push (widget-create-child-and-convert
1210 (widget-insert " ..."))) 1229 widget 'visibility
1230 :action 'custom-toggle-parent
1231 (not (eq state 'hidden)))
1232 buttons))
1211 ((eq escape ?m) 1233 ((eq escape ?m)
1212 (and (eq (preceding-char) ?\n) 1234 (and (eq (preceding-char) ?\n)
1213 (widget-get widget :indent) 1235 (widget-get widget :indent)
@@ -1218,27 +1240,28 @@ Change the state of this item."
1218 (push magic buttons) 1240 (push magic buttons)
1219 (widget-put widget :buttons buttons))) 1241 (widget-put widget :buttons buttons)))
1220 ((eq escape ?a) 1242 ((eq escape ?a)
1221 (let* ((symbol (widget-get widget :value)) 1243 (unless (eq state 'hidden)
1222 (links (get symbol 'custom-links)) 1244 (let* ((symbol (widget-get widget :value))
1223 (many (> (length links) 2))) 1245 (links (get symbol 'custom-links))
1224 (when links 1246 (many (> (length links) 2)))
1225 (and (eq (preceding-char) ?\n) 1247 (when links
1226 (widget-get widget :indent) 1248 (and (eq (preceding-char) ?\n)
1227 (insert-char ? (widget-get widget :indent))) 1249 (widget-get widget :indent)
1228 (insert "See also ") 1250 (insert-char ? (widget-get widget :indent)))
1229 (while links 1251 (insert "See also ")
1230 (push (widget-create-child-and-convert widget (car links)) 1252 (while links
1231 buttons) 1253 (push (widget-create-child-and-convert widget (car links))
1232 (setq links (cdr links)) 1254 buttons)
1233 (cond ((null links) 1255 (setq links (cdr links))
1234 (insert ".\n")) 1256 (cond ((null links)
1235 ((null (cdr links)) 1257 (insert ".\n"))
1236 (if many 1258 ((null (cdr links))
1237 (insert ", and ") 1259 (if many
1238 (insert " and "))) 1260 (insert ", and ")
1239 (t 1261 (insert " and ")))
1240 (insert ", ")))) 1262 (t
1241 (widget-put widget :buttons buttons)))) 1263 (insert ", "))))
1264 (widget-put widget :buttons buttons)))))
1242 (t 1265 (t
1243 (widget-default-format-handler widget escape))))) 1266 (widget-default-format-handler widget escape)))))
1244 1267
@@ -1329,9 +1352,14 @@ Change the state of this item."
1329 ((eq state 'hidden) 1352 ((eq state 'hidden)
1330 (widget-put widget :custom-state 'unknown)) 1353 (widget-put widget :custom-state 'unknown))
1331 (t 1354 (t
1355 (widget-put widget :documentation-shown nil)
1332 (widget-put widget :custom-state 'hidden))) 1356 (widget-put widget :custom-state 'hidden)))
1333 (custom-redraw widget))) 1357 (custom-redraw widget)))
1334 1358
1359(defun custom-toggle-parent (widget &rest ignore)
1360 "Toggle visibility of parent to WIDGET."
1361 (custom-toggle-hide (widget-get widget :parent)))
1362
1335;;; The `custom-variable' Widget. 1363;;; The `custom-variable' Widget.
1336 1364
1337(defface custom-variable-sample-face '((t (:underline t))) 1365(defface custom-variable-sample-face '((t (:underline t)))
@@ -1405,11 +1433,16 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
1405 ;; Indicate hidden value. 1433 ;; Indicate hidden value.
1406 (push (widget-create-child-and-convert 1434 (push (widget-create-child-and-convert
1407 widget 'item 1435 widget 'item
1408 :format "%{%t%}: ..." 1436 :format "%{%t%}: "
1409 :sample-face 'custom-variable-sample-face 1437 :sample-face 'custom-variable-sample-face
1410 :tag tag 1438 :tag tag
1411 :parent widget) 1439 :parent widget)
1412 children)) 1440 buttons)
1441 (push (widget-create-child-and-convert
1442 widget 'visibility
1443 :action 'custom-toggle-parent
1444 nil)
1445 buttons))
1413 ((eq form 'lisp) 1446 ((eq form 'lisp)
1414 ;; In lisp mode edit the saved value when possible. 1447 ;; In lisp mode edit the saved value when possible.
1415 (let* ((value (cond ((get symbol 'saved-value) 1448 (let* ((value (cond ((get symbol 'saved-value)
@@ -1420,22 +1453,49 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
1420 (custom-quote (funcall get symbol))) 1453 (custom-quote (funcall get symbol)))
1421 (t 1454 (t
1422 (custom-quote (widget-get conv :value)))))) 1455 (custom-quote (widget-get conv :value))))))
1456 (insert (symbol-name symbol) ": ")
1457 (push (widget-create-child-and-convert
1458 widget 'visibility
1459 :action 'custom-toggle-parent
1460 t)
1461 buttons)
1462 (insert " ")
1423 (push (widget-create-child-and-convert 1463 (push (widget-create-child-and-convert
1424 widget 'sexp 1464 widget 'sexp
1425 :button-face 'custom-variable-button-face 1465 :button-face 'custom-variable-button-face
1466 :format "%v"
1426 :tag (symbol-name symbol) 1467 :tag (symbol-name symbol)
1427 :parent widget 1468 :parent widget
1428 :value value) 1469 :value value)
1429 children))) 1470 children)))
1430 (t 1471 (t
1431 ;; Edit mode. 1472 ;; Edit mode.
1432 (push (widget-create-child-and-convert 1473 (let* ((format (widget-get type :format))
1433 widget type 1474 tag-format value-format)
1434 :tag tag 1475 (unless (string-match ":" format)
1435 :button-face 'custom-variable-button-face 1476 (error "Bad format."))
1436 :sample-face 'custom-variable-sample-face 1477 (setq tag-format (substring format 0 (match-end 0)))
1437 :value value) 1478 (setq value-format (substring format (match-end 0)))
1438 children))) 1479 (push (widget-create-child-and-convert
1480 widget 'item
1481 :format tag-format
1482 :action 'custom-tag-action
1483 :mouse-down-action 'custom-tag-mouse-down-action
1484 :button-face 'custom-variable-button-face
1485 :sample-face 'custom-variable-sample-face
1486 tag)
1487 buttons)
1488 (insert " ")
1489 (push (widget-create-child-and-convert
1490 widget 'visibility
1491 :action 'custom-toggle-parent
1492 t)
1493 buttons)
1494 (push (widget-create-child-and-convert
1495 widget type
1496 :format value-format
1497 :value value)
1498 children))))
1439 ;; Now update the state. 1499 ;; Now update the state.
1440 (unless (eq (preceding-char) ?\n) 1500 (unless (eq (preceding-char) ?\n)
1441 (widget-insert "\n")) 1501 (widget-insert "\n"))
@@ -1446,6 +1506,16 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
1446 (widget-put widget :buttons buttons) 1506 (widget-put widget :buttons buttons)
1447 (widget-put widget :children children))) 1507 (widget-put widget :children children)))
1448 1508
1509(defun custom-tag-action (widget &rest args)
1510 "Pass :action to first child of WIDGET's parent."
1511 (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children))
1512 :action args))
1513
1514(defun custom-tag-mouse-down-action (widget &rest args)
1515 "Pass :mouse-down-action to first child of WIDGET's parent."
1516 (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children))
1517 :mouse-down-action args))
1518
1449(defun custom-variable-state-set (widget) 1519(defun custom-variable-state-set (widget)
1450 "Set the state of WIDGET." 1520 "Set the state of WIDGET."
1451 (let* ((symbol (widget-value widget)) 1521 (let* ((symbol (widget-value widget))
@@ -1476,10 +1546,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'."
1476 (widget-put widget :custom-state state))) 1546 (widget-put widget :custom-state state)))
1477 1547
1478(defvar custom-variable-menu 1548(defvar custom-variable-menu
1479 '(("Hide" custom-toggle-hide 1549 '(("Edit" custom-variable-edit
1480 (lambda (widget)
1481 (not (memq (widget-get widget :custom-state) '(modified invalid)))))
1482 ("Edit" custom-variable-edit
1483 (lambda (widget) 1550 (lambda (widget)
1484 (not (eq (widget-get widget :custom-form) 'edit)))) 1551 (not (eq (widget-get widget :custom-form) 'edit))))
1485 ("Edit Lisp" custom-variable-edit-lisp 1552 ("Edit Lisp" custom-variable-edit-lisp
@@ -1712,7 +1779,7 @@ Match frames with dark backgrounds.")
1712 1779
1713(define-widget 'custom-face 'custom 1780(define-widget 'custom-face 'custom
1714 "Customize face." 1781 "Customize face."
1715 :format "%{%t%}: %s%m%h%a%v" 1782 :format "%{%t%}: %s %L\n%m%h%a%v"
1716 :format-handler 'custom-face-format-handler 1783 :format-handler 'custom-face-format-handler
1717 :sample-face 'custom-face-tag-face 1784 :sample-face 'custom-face-tag-face
1718 :help-echo "Set or reset this face." 1785 :help-echo "Set or reset this face."
@@ -1739,7 +1806,7 @@ Match frames with dark backgrounds.")
1739 (copy-face 'custom-face-empty symbol)) 1806 (copy-face 'custom-face-empty symbol))
1740 (setq child (widget-create-child-and-convert 1807 (setq child (widget-create-child-and-convert
1741 widget 'item 1808 widget 'item
1742 :format "(%{%t%})\n" 1809 :format "(%{%t%})"
1743 :sample-face symbol 1810 :sample-face symbol
1744 :tag "sample"))) 1811 :tag "sample")))
1745 (t 1812 (t
@@ -1813,10 +1880,7 @@ Match frames with dark backgrounds.")
1813 (message "Creating face editor...done"))) 1880 (message "Creating face editor...done")))
1814 1881
1815(defvar custom-face-menu 1882(defvar custom-face-menu
1816 '(("Hide" custom-toggle-hide 1883 '(("Edit Selected" custom-face-edit-selected
1817 (lambda (widget)
1818 (not (memq (widget-get widget :custom-state) '(modified invalid)))))
1819 ("Edit Selected" custom-face-edit-selected
1820 (lambda (widget) 1884 (lambda (widget)
1821 (not (eq (widget-get widget :custom-form) 'selected)))) 1885 (not (eq (widget-get widget :custom-form) 'selected))))
1822 ("Edit All" custom-face-edit-all 1886 ("Edit All" custom-face-edit-all
@@ -1955,7 +2019,7 @@ Optional EVENT is the location for the menu."
1955 (let* ((symbol (widget-value widget)) 2019 (let* ((symbol (widget-value widget))
1956 (child (widget-create-child-and-convert 2020 (child (widget-create-child-and-convert
1957 widget 'custom-face 2021 widget 'custom-face
1958 :format "%t %s%m%h%v" 2022 :format "%t %s %L\n%m%h%v"
1959 :custom-level nil 2023 :custom-level nil
1960 :value symbol))) 2024 :value symbol)))
1961 (custom-magic-reset child) 2025 (custom-magic-reset child)
@@ -2039,7 +2103,7 @@ and so forth. The remaining group tags are shown with
2039 2103
2040(define-widget 'custom-group 'custom 2104(define-widget 'custom-group 'custom
2041 "Customize group." 2105 "Customize group."
2042 :format "%l%{%t%}:%L\n%m%h%a%v" 2106 :format "%l %{%t%} group: %L %-\n%m%h%a%v%e"
2043 :sample-face-get 'custom-group-sample-face-get 2107 :sample-face-get 'custom-group-sample-face-get
2044 :documentation-property 'group-documentation 2108 :documentation-property 'group-documentation
2045 :help-echo "Set or reset all members of this group." 2109 :help-echo "Set or reset all members of this group."
@@ -2096,10 +2160,7 @@ and so forth. The remaining group tags are shown with
2096 (message "Creating group... done"))))) 2160 (message "Creating group... done")))))
2097 2161
2098(defvar custom-group-menu 2162(defvar custom-group-menu
2099 '(("Hide" custom-toggle-hide 2163 '(("Set" custom-group-set
2100 (lambda (widget)
2101 (not (memq (widget-get widget :custom-state) '(modified invalid)))))
2102 ("Set" custom-group-set
2103 (lambda (widget) 2164 (lambda (widget)
2104 (eq (widget-get widget :custom-state) 'modified))) 2165 (eq (widget-get widget :custom-state) 'modified)))
2105 ("Save" custom-group-save 2166 ("Save" custom-group-save
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 6de406f4c4c..6749807bb2e 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -4,7 +4,7 @@
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.9900 7;; Version: 1.9901
8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -31,6 +31,7 @@
31;;; Code: 31;;; Code:
32 32
33(require 'widget) 33(require 'widget)
34(eval-when-compile (require 'cl))
34 35
35;;; Compatibility. 36;;; Compatibility.
36 37
@@ -567,27 +568,23 @@ automatically."
567 (repeat :tag "Suffixes" 568 (repeat :tag "Suffixes"
568 (string :format "%v"))))) 569 (string :format "%v")))))
569 570
570(defun widget-glyph-insert (widget tag image) 571(defun widget-glyph-find (image tag)
571 "In WIDGET, insert the text TAG or, if supported, IMAGE. 572 "Create a glyph corresponding to IMAGE with string TAG as fallback.
572IMAGE should either be a glyph, an image instantiator, or an image file 573IMAGE should either already be a glyph, or be a file name sans
573name sans extension (xpm, xbm, gif, jpg, or png) located in 574extension (xpm, xbm, gif, jpg, or png) located in
574`widget-glyph-directory'. 575`widget-glyph-directory'."
575 576 (cond ((not (and image
576WARNING: If you call this with a glyph, and you want the user to be 577 (string-match "XEmacs" emacs-version)
577able to invoke the glyph, make sure it is unique. If you use the
578same glyph for multiple widgets, invoking any of the glyphs will
579cause the last created widget to be invoked."
580 (cond ((not (and (string-match "XEmacs" emacs-version)
581 widget-glyph-enable 578 widget-glyph-enable
582 (fboundp 'make-glyph) 579 (fboundp 'make-glyph)
583 (fboundp 'locate-file) 580 (fboundp 'locate-file)
584 image)) 581 image))
585 ;; We don't want or can't use glyphs. 582 ;; We don't want or can't use glyphs.
586 (insert tag)) 583 nil)
587 ((and (fboundp 'glyphp) 584 ((and (fboundp 'glyphp)
588 (glyphp image)) 585 (glyphp image))
589 ;; Already a glyph. Insert it. 586 ;; Already a glyph. Use it.
590 (widget-glyph-insert-glyph widget image)) 587 image)
591 ((stringp image) 588 ((stringp image)
592 ;; A string. Look it up in relevant directories. 589 ;; A string. Look it up in relevant directories.
593 (let* ((dirlist (list (or widget-glyph-directory 590 (let* ((dirlist (list (or widget-glyph-directory
@@ -599,50 +596,65 @@ cause the last created widget to be invoked."
599 (while (and formats (not file)) 596 (while (and formats (not file))
600 (if (valid-image-instantiator-format-p (car (car formats))) 597 (if (valid-image-instantiator-format-p (car (car formats)))
601 (setq file (locate-file image dirlist 598 (setq file (locate-file image dirlist
602 (mapconcat 'identity (cdr (car formats)) 599 (mapconcat 'identity
600 (cdr (car formats))
603 ":"))) 601 ":")))
604 (setq formats (cdr formats)))) 602 (setq formats (cdr formats))))
605 ;; We create a glyph with the file as the default image 603 ;; We create a glyph with the file as the default image
606 ;; instantiator, and the TAG fallback 604 ;; instantiator, and the TAG fallback
607 (widget-glyph-insert-glyph 605 (make-glyph (if file
608 widget 606 (list (vector (car (car formats)) ':file file)
609 (make-glyph (if file 607 (vector 'string ':data tag))
610 (list (vector (car (car formats)) ':file file) 608 (vector 'string ':data tag)))))
611 (vector 'string ':data tag))
612 (vector 'string ':data tag))))))
613 ((valid-instantiator-p image 'image) 609 ((valid-instantiator-p image 'image)
614 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.) 610 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.)
615 (widget-glyph-insert-glyph 611 (make-glyph (list image
616 widget 612 (vector 'string ':data tag))))
617 (make-glyph (list image
618 (vector 'string ':data tag)))))
619 (t 613 (t
620 ;; Oh well. 614 ;; Oh well.
621 (insert tag)))) 615 nil)))
616
617(defun widget-glyph-insert (widget tag image &optional down inactive)
618 "In WIDGET, insert the text TAG or, if supported, IMAGE.
619IMAGE should either be a glyph, an image instantiator, or an image file
620name sans extension (xpm, xbm, gif, jpg, or png) located in
621`widget-glyph-directory'.
622
623Optional arguments DOWN and INACTIVE is used instead of IMAGE when the
624glyph is pressed or inactive, respectively.
625
626WARNING: If you call this with a glyph, and you want the user to be
627able to invoke the glyph, make sure it is unique. If you use the
628same glyph for multiple widgets, invoking any of the glyphs will
629cause the last created widget to be invoked."
630 (let ((glyph (widget-glyph-find image tag)))
631 (if glyph
632 (widget-glyph-insert-glyph widget
633 glyph
634 (widget-glyph-find down tag)
635 (widget-glyph-find inactive tag))
636 (insert tag))))
622 637
623(defun widget-glyph-insert-glyph (widget glyph &optional down inactive) 638(defun widget-glyph-insert-glyph (widget glyph &optional down inactive)
624 "In WIDGET, with alternative text TAG, insert GLYPH." 639 "In WIDGET, insert GLYPH.
640If optional arguments DOWN and INACTIVE are given, they should be
641glyphs used when the widget is pushed and inactive, respectively."
625 (set-glyph-property glyph 'widget widget) 642 (set-glyph-property glyph 'widget widget)
626 (when down 643 (when down
627 (set-glyph-property down 'widget widget)) 644 (set-glyph-property down 'widget widget))
628 (when inactive 645 (when inactive
629 (set-glyph-property inactive 'widget widget)) 646 (set-glyph-property inactive 'widget widget))
630 (insert "*") 647 (insert "*")
631 (add-text-properties (1- (point)) (point) 648 (let ((ext (make-extent (point) (1- (point))))
632 (list 'invisible t 649 (help-echo (widget-get widget :help-echo)))
633 'end-glyph glyph)) 650 (set-extent-property ext 'invisible t)
651 (set-extent-end-glyph ext glyph)
652 (when help-echo
653 (set-extent-property ext 'balloon-help help-echo)
654 (set-extent-property ext 'help-echo help-echo)))
634 (widget-put widget :glyph-up glyph) 655 (widget-put widget :glyph-up glyph)
635 (when down (widget-put widget :glyph-down down)) 656 (when down (widget-put widget :glyph-down down))
636 (when inactive (widget-put widget :glyph-inactive inactive)) 657 (when inactive (widget-put widget :glyph-inactive inactive)))
637 (let ((help-echo (widget-get widget :help-echo)))
638 (when help-echo
639 (let ((extent (extent-at (1- (point)) nil 'end-glyph))
640 (help-property (if (featurep 'balloon-help)
641 'balloon-help
642 'help-echo)))
643 (set-extent-property extent help-property (if (stringp help-echo)
644 help-echo
645 'widget-mouse-help))))))
646 658
647;;; Buttons. 659;;; Buttons.
648 660
@@ -653,12 +665,12 @@ cause the last created widget to be invoked."
653(defcustom widget-button-prefix "" 665(defcustom widget-button-prefix ""
654 "String used as prefix for buttons." 666 "String used as prefix for buttons."
655 :type 'string 667 :type 'string
656 :group 'widgets) 668 :group 'widget-button)
657 669
658(defcustom widget-button-suffix "" 670(defcustom widget-button-suffix ""
659 "String used as suffix for buttons." 671 "String used as suffix for buttons."
660 :type 'string 672 :type 'string
661 :group 'widgets) 673 :group 'widget-button)
662 674
663(defun widget-button-insert-indirect (widget key) 675(defun widget-button-insert-indirect (widget key)
664 "Insert value of WIDGET's KEY property." 676 "Insert value of WIDGET's KEY property."
@@ -1313,20 +1325,10 @@ Optional EVENT is the event that triggered the action."
1313 ;; Get rid of trailing newlines. 1325 ;; Get rid of trailing newlines.
1314 (when (string-match "\n+\\'" doc-text) 1326 (when (string-match "\n+\\'" doc-text)
1315 (setq doc-text (substring doc-text 0 (match-beginning 0)))) 1327 (setq doc-text (substring doc-text 0 (match-beginning 0))))
1316 (setq buttons 1328 (push (widget-create-child-and-convert
1317 (cons (if (string-match "\n." doc-text) 1329 widget 'documentation-string
1318 ;; Allow multiline doc to be hiden. 1330 doc-text)
1319 (widget-create-child-and-convert 1331 buttons)))
1320 widget 'widget-help
1321 :doc (progn
1322 (string-match "\\`.*" doc-text)
1323 (match-string 0 doc-text))
1324 :widget-doc doc-text
1325 "?")
1326 ;; A single line is just inserted.
1327 (widget-create-child-and-convert
1328 widget 'item :format "%d" :doc doc-text nil))
1329 buttons))))
1330 (t 1332 (t
1331 (error "Unknown escape `%c'" escape))) 1333 (error "Unknown escape `%c'" escape)))
1332 (widget-put widget :buttons buttons))) 1334 (widget-put widget :buttons buttons)))
@@ -1495,8 +1497,7 @@ If END is omitted, it defaults to the length of LIST."
1495 (progn 1497 (progn
1496 (unless gui 1498 (unless gui
1497 (setq gui (make-gui-button tag 'widget-gui-action widget)) 1499 (setq gui (make-gui-button tag 'widget-gui-action widget))
1498 (setq widget-push-button-cache 1500 (push (cons tag gui) widget-push-button-cache))
1499 (cons (cons tag gui) widget-push-button-cache)))
1500 (widget-glyph-insert-glyph widget 1501 (widget-glyph-insert-glyph widget
1501 (make-glyph 1502 (make-glyph
1502 (list (nth 0 (aref gui 1)) 1503 (list (nth 0 (aref gui 1))
@@ -2451,14 +2452,13 @@ when he invoked the menu."
2451 (and (eq (preceding-char) ?\n) 2452 (and (eq (preceding-char) ?\n)
2452 (widget-get widget :indent) 2453 (widget-get widget :indent)
2453 (insert-char ? (widget-get widget :indent))) 2454 (insert-char ? (widget-get widget :indent)))
2454 (setq children 2455 (push (cond ((null answer)
2455 (cons (cond ((null answer) 2456 (widget-create-child widget arg))
2456 (widget-create-child widget arg)) 2457 ((widget-get arg :inline)
2457 ((widget-get arg :inline) 2458 (widget-create-child-value widget arg (car answer)))
2458 (widget-create-child-value widget arg (car answer))) 2459 (t
2459 (t 2460 (widget-create-child-value widget arg (car (car answer)))))
2460 (widget-create-child-value widget arg (car (car answer))))) 2461 children))
2461 children)))
2462 (widget-put widget :children (nreverse children)))) 2462 (widget-put widget :children (nreverse children))))
2463 2463
2464(defun widget-group-match (widget values) 2464(defun widget-group-match (widget values)
@@ -2484,20 +2484,74 @@ when he invoked the menu."
2484 (cons found vals) 2484 (cons found vals)
2485 nil))) 2485 nil)))
2486 2486
2487;;; The `widget-help' Widget. 2487;;; The `visibility' Widget.
2488 2488
2489(define-widget 'widget-help 'push-button 2489(define-widget 'visibility 'item
2490 "The widget documentation button." 2490 "An indicator and manipulator for hidden items."
2491 :format "%[%v%] %d" 2491 :format "%[%v%]"
2492 :help-echo "Toggle display of documentation." 2492 :button-prefix ""
2493 :action 'widget-help-action) 2493 :button-suffix ""
2494 :on "hide"
2495 :off "more"
2496 :value-create 'widget-visibility-value-create
2497 :action 'widget-toggle-action
2498 :match (lambda (widget value) t))
2494 2499
2495(defun widget-help-action (widget &optional event) 2500(defun widget-visibility-value-create (widget)
2496 "Toggle documentation for WIDGET." 2501 ;; Insert text representing the `on' and `off' states.
2497 (let ((old (widget-get widget :doc)) 2502 (let ((on (widget-get widget :on))
2498 (new (widget-get widget :widget-doc))) 2503 (off (widget-get widget :off)))
2499 (widget-put widget :doc new) 2504 (if on
2500 (widget-put widget :widget-doc old)) 2505 (setq on (concat widget-push-button-prefix
2506 on
2507 widget-push-button-suffix))
2508 (setq on ""))
2509 (if off
2510 (setq off (concat widget-push-button-prefix
2511 off
2512 widget-push-button-suffix))
2513 (setq off ""))
2514 (if (widget-value widget)
2515 (widget-glyph-insert widget on "down" "down-pushed")
2516 (widget-glyph-insert widget off "right" "right-pushed")
2517 (insert "..."))))
2518
2519;;; The `documentation-string' Widget.
2520
2521(define-widget 'documentation-string 'item
2522 "A documentation string."
2523 :format "%v"
2524 :action 'widget-documentation-string-action
2525 :value-delete 'widget-children-value-delete
2526 :value-create 'widget-documentation-string-value-create)
2527
2528(defun widget-documentation-string-value-create (widget)
2529 ;; Insert documentation string.
2530 (let ((doc (widget-value widget))
2531 (shown (widget-get (widget-get widget :parent) :documentation-shown)))
2532 (if (string-match "\n" doc)
2533 (let ((before (substring doc 0 (match-beginning 0)))
2534 (after (substring doc (match-beginning 0)))
2535 buttons)
2536 (insert before " ")
2537 (push (widget-create-child-and-convert
2538 widget 'visibility
2539 :off nil
2540 :action 'widget-parent-action
2541 shown)
2542 buttons)
2543 (when shown
2544 (insert after))
2545 (widget-put widget :buttons buttons))
2546 (insert doc)))
2547 (insert "\n"))
2548
2549(defun widget-documentation-string-action (widget &rest ignore)
2550 ;; Toggle documentation.
2551 (let ((parent (widget-get widget :parent)))
2552 (widget-put parent :documentation-shown
2553 (not (widget-get parent :documentation-shown))))
2554 ;; Redraw.
2501 (widget-value-set widget (widget-value widget))) 2555 (widget-value-set widget (widget-value widget)))
2502 2556
2503;;; The Sexp Widgets. 2557;;; The Sexp Widgets.
diff --git a/lisp/widget.el b/lisp/widget.el
index 1be690a6d36..8a550c15f72 100644
--- a/lisp/widget.el
+++ b/lisp/widget.el
@@ -4,7 +4,7 @@
4;; 4;;
5;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6;; Keywords: help, extensions, faces, hypermedia 6;; Keywords: help, extensions, faces, hypermedia
7;; Version: 1.9900 7;; Version: 1.9901
8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -44,14 +44,14 @@
44 (set (car keywords) (car keywords))) 44 (set (car keywords) (car keywords)))
45 (setq keywords (cdr keywords))))))) 45 (setq keywords (cdr keywords)))))))
46 46
47(define-widget-keywords :button-prefix :button-suffix 47(define-widget-keywords :documentation-shown :button-prefix
48 :mouse-down-action :glyph-up :glyph-down :glyph-inactive 48 :button-suffix :mouse-down-action :glyph-up :glyph-down :glyph-inactive
49 :prompt-internal :prompt-history :prompt-match 49 :prompt-internal :prompt-history :prompt-match
50 :prompt-value :deactivate :active 50 :prompt-value :deactivate :active
51 :inactive :activate :sibling-args :delete-button-args 51 :inactive :activate :sibling-args :delete-button-args
52 :insert-button-args :append-button-args :button-args 52 :insert-button-args :append-button-args :button-args
53 :tag-glyph :off-glyph :on-glyph :valid-regexp 53 :tag-glyph :off-glyph :on-glyph :valid-regexp
54 :secret :sample-face :sample-face-get :case-fold :widget-doc 54 :secret :sample-face :sample-face-get :case-fold
55 :create :convert-widget :format :value-create :offset :extra-offset 55 :create :convert-widget :format :value-create :offset :extra-offset
56 :tag :doc :from :to :args :value :value-from :value-to :action 56 :tag :doc :from :to :args :value :value-from :value-to :action
57 :value-set :value-delete :match :parent :delete :menu-tag-get 57 :value-set :value-delete :match :parent :delete :menu-tag-get