comparison lisp/custom/wid-edit.el @ 153:25f70ba0133c r20-3b3

Import from CVS: tag r20-3b3
author cvs
date Mon, 13 Aug 2007 09:38:25 +0200
parents 538048ae2ab8
children 43dd3413c7c7
comparison
equal deleted inserted replaced
152:4c132ee2d62b 153:25f70ba0133c
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.97 7 ;; Version: 1.98
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.
11 11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify 12 ;; GNU Emacs is free software; you can redistribute it and/or modify
29 ;; See `widget.el'. 29 ;; See `widget.el'.
30 30
31 ;;; Code: 31 ;;; Code:
32 32
33 (require 'widget) 33 (require 'widget)
34 34 (require 'cl)
35 (eval-when-compile (require 'cl))
36 35
37 ;;; Compatibility. 36 ;;; Compatibility.
38 37
39 (eval-and-compile 38 (eval-and-compile
40 (autoload 'pp-to-string "pp") 39 (autoload 'pp-to-string "pp")
144 (defface widget-field-face '((((class grayscale color) 143 (defface widget-field-face '((((class grayscale color)
145 (background light)) 144 (background light))
146 (:background "gray85")) 145 (:background "gray85"))
147 (((class grayscale color) 146 (((class grayscale color)
148 (background dark)) 147 (background dark))
149 (:background "dark gray")) 148 (:background "dim gray"))
150 (t 149 (t
151 (:italic t))) 150 (:italic t)))
152 "Face used for editable fields." 151 "Face used for editable fields."
153 :group 'widgets) 152 :group 'widgets)
154 153
540 ;;; Glyphs. 539 ;;; Glyphs.
541 540
542 (defcustom widget-glyph-directory (concat data-directory "custom/") 541 (defcustom widget-glyph-directory (concat data-directory "custom/")
543 "Where widget glyphs are located. 542 "Where widget glyphs are located.
544 If this variable is nil, widget will try to locate the directory 543 If this variable is nil, widget will try to locate the directory
545 automatically. This does not work yet." 544 automatically."
546 :group 'widgets 545 :group 'widgets
547 :type 'directory) 546 :type 'directory)
548 547
549 (defcustom widget-glyph-enable t 548 (defcustom widget-glyph-enable t
550 "If non nil, use glyphs in images when available." 549 "If non nil, use glyphs in images when available."
551 :group 'widgets 550 :group 'widgets
552 :type 'boolean) 551 :type 'boolean)
553 552
553 (defcustom widget-image-conversion
554 '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg")
555 (xbm ".xbm"))
556 "Conversion alist from image formats to file name suffixes."
557 :group 'widgets
558 :type '(repeat (cons :format "%v"
559 (symbol :tag "Image Format" unknown)
560 (repeat :tag "Suffixes"
561 (string :format "%v")))))
562
554 (defun widget-glyph-insert (widget tag image) 563 (defun widget-glyph-insert (widget tag image)
555 "In WIDGET, insert the text TAG or, if supported, IMAGE. 564 "In WIDGET, insert the text TAG or, if supported, IMAGE.
556 IMAGE should either be a glyph, or a name sans extension of an xpm or 565 IMAGE should either be a glyph, an image instantiator, or an image file
557 xbm file located in `widget-glyph-directory'. 566 name sans extension (xpm, xbm, gif, jpg, or png) located in
567 `widget-glyph-directory'.
558 568
559 WARNING: If you call this with a glyph, and you want the user to be 569 WARNING: If you call this with a glyph, and you want the user to be
560 able to activate the glyph, make sure it is unique. If you use the 570 able to activate the glyph, make sure it is unique. If you use the
561 same glyph for multiple widgets, activating any of the glyphs will 571 same glyph for multiple widgets, activating any of the glyphs will
562 cause the last created widget to be activated." 572 cause the last created widget to be activated."
563 (cond ((not (and (string-match "XEmacs" emacs-version) 573 (cond ((not (and (string-match "XEmacs" emacs-version)
564 widget-glyph-enable 574 widget-glyph-enable
565 (fboundp 'make-glyph) 575 (fboundp 'make-glyph)
576 (fboundp 'locate-file)
566 image)) 577 image))
567 ;; We don't want or can't use glyphs. 578 ;; We don't want or can't use glyphs.
568 (insert tag)) 579 (insert tag))
569 ((and (fboundp 'glyphp) 580 ((and (fboundp 'glyphp)
570 (glyphp image)) 581 (glyphp image))
571 ;; Already a glyph. Insert it. 582 ;; Already a glyph. Insert it.
572 (widget-glyph-insert-glyph widget tag image)) 583 (widget-glyph-insert-glyph widget image))
584 ((stringp image)
585 ;; A string. Look it up in relevant directories.
586 (let* ((dirlist (list (or widget-glyph-directory
587 (concat data-directory
588 "custom/"))
589 data-directory))
590 (formats widget-image-conversion)
591 file)
592 (while (and formats (not file))
593 (when (valid-image-instantiator-format-p (car (car formats)))
594 (setq file (locate-file image dirlist
595 (mapconcat 'identity (cdr (car formats))
596 ":"))))
597 (setq formats (cdr formats)))
598 ;; We create a glyph with the file as the default image
599 ;; instantiator, and the TAG fallback
600 (widget-glyph-insert-glyph
601 widget
602 (make-glyph (if file
603 (list (vector (car (car formats)) ':file file)
604 (vector 'string ':data tag))
605 (vector 'string ':data tag))))))
606 ((valid-instantiator-p image 'image)
607 ;; A valid image instantiator (e.g. [gif ':file "somefile"] etc.)
608 (widget-glyph-insert-glyph widget
609 (list image
610 (vector 'string ':data tag))))
573 (t 611 (t
574 ;; A string. Look it up in. 612 ;; Oh well.
575 (let ((file (concat widget-glyph-directory 613 (insert tag))))
576 (if (string-match "/\\'" widget-glyph-directory) 614
577 "" 615 (defun widget-glyph-insert-glyph (widget glyph &optional down inactive)
578 "/")
579 image
580 (if (featurep 'xpm) ".xpm" ".xbm"))))
581 (if (file-readable-p file)
582 (widget-glyph-insert-glyph widget tag (make-glyph file))
583 ;; File not readable, give up.
584 (insert tag))))))
585
586 (defun widget-glyph-insert-glyph (widget tag glyph &optional down inactive)
587 "In WIDGET, with alternative text TAG, insert GLYPH." 616 "In WIDGET, with alternative text TAG, insert GLYPH."
588 (set-glyph-image glyph (cons 'tty tag))
589 (set-glyph-property glyph 'widget widget) 617 (set-glyph-property glyph 'widget widget)
590 (when down 618 (when down
591 (set-glyph-image down (cons 'tty tag))
592 (set-glyph-property down 'widget widget)) 619 (set-glyph-property down 'widget widget))
593 (when inactive 620 (when inactive
594 (set-glyph-image inactive (cons 'tty tag))
595 (set-glyph-property inactive 'widget widget)) 621 (set-glyph-property inactive 'widget widget))
596 (insert "*") 622 (insert "*")
597 (add-text-properties (1- (point)) (point) 623 (add-text-properties (1- (point)) (point)
598 (list 'invisible t 624 (list 'invisible t
599 'end-glyph glyph)) 625 'end-glyph glyph))
607 'balloon-help 633 'balloon-help
608 'help-echo))) 634 'help-echo)))
609 (set-extent-property extent help-property (if (stringp help-echo) 635 (set-extent-property extent help-property (if (stringp help-echo)
610 help-echo 636 help-echo
611 'widget-mouse-help)))))) 637 'widget-mouse-help))))))
638
639 ;;; Buttons.
640
641 (defgroup widget-button nil
642 "The look of various kinds of buttons."
643 :group 'widgets)
644
645 (defcustom widget-button-prefix ""
646 "String used as prefix for buttons."
647 :type 'string
648 :group 'widgets)
649
650 (defcustom widget-button-suffix ""
651 "String used as suffix for buttons."
652 :type 'string
653 :group 'widgets)
654
655 (defun widget-button-insert-indirect (widget key)
656 "Insert value of WIDGET's KEY property."
657 (let ((val (widget-get widget key)))
658 (while (and val (symbolp val))
659 (setq val (symbol-value val)))
660 (when val
661 (insert val))))
612 662
613 ;;; Creating Widgets. 663 ;;; Creating Widgets.
614 664
615 ;;;###autoload 665 ;;;###autoload
616 (defun widget-create (type &rest args) 666 (defun widget-create (type &rest args)
1134 1184
1135 (define-widget 'default nil 1185 (define-widget 'default nil
1136 "Basic widget other widgets are derived from." 1186 "Basic widget other widgets are derived from."
1137 :value-to-internal (lambda (widget value) value) 1187 :value-to-internal (lambda (widget value) value)
1138 :value-to-external (lambda (widget value) value) 1188 :value-to-external (lambda (widget value) value)
1189 :button-prefix 'widget-button-prefix
1190 :button-suffix 'widget-button-suffix
1139 :create 'widget-default-create 1191 :create 'widget-default-create
1140 :indent nil 1192 :indent nil
1141 :offset 0 1193 :offset 0
1142 :format-handler 'widget-default-format-handler 1194 :format-handler 'widget-default-format-handler
1143 :button-face-get 'widget-default-button-face-get 1195 :button-face-get 'widget-default-button-face-get
1157 1209
1158 (defun widget-default-create (widget) 1210 (defun widget-default-create (widget)
1159 "Create WIDGET at point in the current buffer." 1211 "Create WIDGET at point in the current buffer."
1160 (widget-specify-insert 1212 (widget-specify-insert
1161 (let ((from (point)) 1213 (let ((from (point))
1162 (tag (widget-get widget :tag))
1163 (glyph (widget-get widget :tag-glyph))
1164 (doc (widget-get widget :doc))
1165 button-begin button-end 1214 button-begin button-end
1166 sample-begin sample-end 1215 sample-begin sample-end
1167 doc-begin doc-end 1216 doc-begin doc-end
1168 value-pos) 1217 value-pos)
1169 (insert (widget-get widget :format)) 1218 (insert (widget-get widget :format))
1173 (let ((escape (aref (match-string 1) 0))) 1222 (let ((escape (aref (match-string 1) 0)))
1174 (replace-match "" t t) 1223 (replace-match "" t t)
1175 (cond ((eq escape ?%) 1224 (cond ((eq escape ?%)
1176 (insert "%")) 1225 (insert "%"))
1177 ((eq escape ?\[) 1226 ((eq escape ?\[)
1178 (setq button-begin (point))) 1227 (setq button-begin (point))
1228 (widget-button-insert-indirect widget :button-prefix))
1179 ((eq escape ?\]) 1229 ((eq escape ?\])
1230 (widget-button-insert-indirect widget :button-suffix)
1180 (setq button-end (point))) 1231 (setq button-end (point)))
1181 ((eq escape ?\{) 1232 ((eq escape ?\{)
1182 (setq sample-begin (point))) 1233 (setq sample-begin (point)))
1183 ((eq escape ?\}) 1234 ((eq escape ?\})
1184 (setq sample-end (point))) 1235 (setq sample-end (point)))
1185 ((eq escape ?n) 1236 ((eq escape ?n)
1186 (when (widget-get widget :indent) 1237 (when (widget-get widget :indent)
1187 (insert "\n") 1238 (insert "\n")
1188 (insert-char ? (widget-get widget :indent)))) 1239 (insert-char ? (widget-get widget :indent))))
1189 ((eq escape ?t) 1240 ((eq escape ?t)
1190 (cond (glyph 1241 (let ((glyph (widget-get widget :tag-glyph))
1191 (widget-glyph-insert widget (or tag "image") glyph)) 1242 (tag (widget-get widget :tag)))
1192 (tag 1243 (cond (glyph
1193 (insert tag)) 1244 (widget-glyph-insert widget (or tag "image") glyph))
1194 (t 1245 (tag
1195 (let ((standard-output (current-buffer))) 1246 (insert tag))
1196 (princ (widget-get widget :value)))))) 1247 (t
1248 (let ((standard-output (current-buffer)))
1249 (princ (widget-get widget :value)))))))
1197 ((eq escape ?d) 1250 ((eq escape ?d)
1198 (when doc 1251 (let ((doc (widget-get widget :doc)))
1199 (setq doc-begin (point)) 1252 (when doc
1200 (insert doc) 1253 (setq doc-begin (point))
1201 (while (eq (preceding-char) ?\n) 1254 (insert doc)
1202 (delete-backward-char 1)) 1255 (while (eq (preceding-char) ?\n)
1203 (insert "\n") 1256 (delete-backward-char 1))
1204 (setq doc-end (point)))) 1257 (insert "\n")
1258 (setq doc-end (point)))))
1205 ((eq escape ?v) 1259 ((eq escape ?v)
1206 (if (and button-begin (not button-end)) 1260 (if (and button-begin (not button-end))
1207 (widget-apply widget :value-create) 1261 (widget-apply widget :value-create)
1208 (setq value-pos (point)))) 1262 (setq value-pos (point))))
1209 (t 1263 (t
1384 :type 'boolean) 1438 :type 'boolean)
1385 1439
1386 ;; Cache already created GUI objects. 1440 ;; Cache already created GUI objects.
1387 (defvar widget-push-button-cache nil) 1441 (defvar widget-push-button-cache nil)
1388 1442
1443 (defcustom widget-push-button-prefix "["
1444 "String used as prefix for buttons."
1445 :type 'string
1446 :group 'widget-button)
1447
1448 (defcustom widget-push-button-suffix "]"
1449 "String used as suffix for buttons."
1450 :type 'string
1451 :group 'widget-button)
1452
1389 (define-widget 'push-button 'item 1453 (define-widget 'push-button 'item
1390 "A pushable button." 1454 "A pushable button."
1455 :button-prefix ""
1456 :button-suffix ""
1391 :value-create 'widget-push-button-value-create 1457 :value-create 'widget-push-button-value-create
1392 :text-format "[%s]"
1393 :format "%[%v%]") 1458 :format "%[%v%]")
1394 1459
1395 (defun widget-push-button-value-create (widget) 1460 (defun widget-push-button-value-create (widget)
1396 ;; Insert text representing the `on' and `off' states. 1461 ;; Insert text representing the `on' and `off' states.
1397 (let* ((tag (or (widget-get widget :tag) 1462 (let* ((tag (or (widget-get widget :tag)
1398 (widget-get widget :value))) 1463 (widget-get widget :value)))
1399 (text (format (widget-get widget :text-format) tag)) 1464 (text (concat widget-push-button-prefix
1465 tag widget-push-button-suffix))
1400 (gui (cdr (assoc tag widget-push-button-cache)))) 1466 (gui (cdr (assoc tag widget-push-button-cache))))
1401 (if (and (fboundp 'make-gui-button) 1467 (if (and (fboundp 'make-gui-button)
1402 (fboundp 'make-glyph) 1468 (fboundp 'make-glyph)
1403 widget-push-button-gui 1469 widget-push-button-gui
1404 (fboundp 'device-on-window-system-p) 1470 (fboundp 'device-on-window-system-p)
1406 (string-match "XEmacs" emacs-version)) 1472 (string-match "XEmacs" emacs-version))
1407 (progn 1473 (progn
1408 (unless gui 1474 (unless gui
1409 (setq gui (make-gui-button tag 'widget-gui-action widget)) 1475 (setq gui (make-gui-button tag 'widget-gui-action widget))
1410 (push (cons tag gui) widget-push-button-cache)) 1476 (push (cons tag gui) widget-push-button-cache))
1411 (widget-glyph-insert-glyph widget text 1477 (widget-glyph-insert-glyph widget
1412 (make-glyph (nth 0 (aref gui 1))) 1478 (make-glyph
1413 (make-glyph (nth 1 (aref gui 1))) 1479 (list (nth 0 (aref gui 1))
1414 (make-glyph (nth 2 (aref gui 1))))) 1480 (vector 'string ':data text)))
1481 (make-glyph
1482 (list (nth 1 (aref gui 1))
1483 (vector 'string ':data text)))
1484 (make-glyph
1485 (list (nth 2 (aref gui 1))
1486 (vector 'string ':data text)))))
1415 (insert text)))) 1487 (insert text))))
1416 1488
1417 (defun widget-gui-action (widget) 1489 (defun widget-gui-action (widget)
1418 "Apply :action for WIDGET." 1490 "Apply :action for WIDGET."
1419 (widget-apply-action widget (this-command-keys))) 1491 (widget-apply-action widget (this-command-keys)))
1420 1492
1421 ;;; The `link' Widget. 1493 ;;; The `link' Widget.
1422 1494
1495 (defcustom widget-link-prefix "_"
1496 "String used as prefix for links."
1497 :type 'string
1498 :group 'widget-button)
1499
1500 (defcustom widget-link-suffix "_"
1501 "String used as suffix for links."
1502 :type 'string
1503 :group 'widget-button)
1504
1423 (define-widget 'link 'item 1505 (define-widget 'link 'item
1424 "An embedded link." 1506 "An embedded link."
1507 :button-prefix 'widget-link-prefix
1508 :button-suffix 'widget-link-suffix
1425 :help-echo "Follow the link." 1509 :help-echo "Follow the link."
1426 :format "%[_%t_%]") 1510 :format "%[%t%]")
1427 1511
1428 ;;; The `info-link' Widget. 1512 ;;; The `info-link' Widget.
1429 1513
1430 (define-widget 'info-link 'link 1514 (define-widget 'info-link 'link
1431 "A link to an info file." 1515 "A link to an info file."
1754 1838
1755 ;;; The `checkbox' Widget. 1839 ;;; The `checkbox' Widget.
1756 1840
1757 (define-widget 'checkbox 'toggle 1841 (define-widget 'checkbox 'toggle
1758 "A checkbox toggle." 1842 "A checkbox toggle."
1843 :button-suffix ""
1844 :button-prefix ""
1759 :format "%[%v%]" 1845 :format "%[%v%]"
1760 :on "[X]" 1846 :on "[X]"
1761 :on-glyph "check1" 1847 :on-glyph "check1"
1762 :off "[ ]" 1848 :off "[ ]"
1763 :off-glyph "check0" 1849 :off-glyph "check0"
1938 2024
1939 (define-widget 'radio-button 'toggle 2025 (define-widget 'radio-button 'toggle
1940 "A radio button for use in the `radio' widget." 2026 "A radio button for use in the `radio' widget."
1941 :notify 'widget-radio-button-notify 2027 :notify 'widget-radio-button-notify
1942 :format "%[%v%]" 2028 :format "%[%v%]"
2029 :button-suffix ""
2030 :button-prefix ""
1943 :on "(*)" 2031 :on "(*)"
1944 :on-glyph "radio1" 2032 :on-glyph "radio1"
1945 :off "( )" 2033 :off "( )"
1946 :off-glyph "radio0") 2034 :off-glyph "radio0")
1947 2035
2374 2462
2375 ;;; The `widget-help' Widget. 2463 ;;; The `widget-help' Widget.
2376 2464
2377 (define-widget 'widget-help 'push-button 2465 (define-widget 'widget-help 'push-button
2378 "The widget documentation button." 2466 "The widget documentation button."
2379 :format "%[[%t]%] %d" 2467 :format "%[%t%] %d"
2380 :help-echo "Toggle display of documentation." 2468 :help-echo "Toggle display of documentation."
2381 :action 'widget-help-action) 2469 :action 'widget-help-action)
2382 2470
2383 (defun widget-help-action (widget &optional event) 2471 (defun widget-help-action (widget &optional event)
2384 "Toggle documentation for WIDGET." 2472 "Toggle documentation for WIDGET."