diff options
| author | David Ponce | 2005-08-15 13:00:09 +0000 |
|---|---|---|
| committer | David Ponce | 2005-08-15 13:00:09 +0000 |
| commit | 0cfce69f6e359aded65cb59eeab914767435c38e (patch) | |
| tree | 3c5efcd33379845bc63d29bc16a4a8c36a919c9c | |
| parent | 86ae23f8c48916016a2c34ba81ff0f7c2e75bfb1 (diff) | |
| download | emacs-0cfce69f6e359aded65cb59eeab914767435c38e.tar.gz emacs-0cfce69f6e359aded65cb59eeab914767435c38e.zip | |
Update Commentary header.
(tree-widget-theme): Doc fix.
(tree-widget-space-width): New option.
(tree-widget-image-properties): Look up in the default theme too.
(tree-widget--cursors): Only for images with arrow pointer shape.
(tree-widget-lookup-image): Pointer shape is hand by default.
(tree-widget-icon): Generic icon widget renamed from
`tree-widget-control'.
(tree-widget-*-icon): Rename from `tree-widget-*-control' and
derive from `tree-widget-icon'.
(tree-widget-handle): Improve default look and feel of the text
representation.
(tree-widget): Rename :*-control properties to :*-icon properties.
Add :action and :help-echo properties.
(tree-widget-after-toggle-functions): Move.
(tree-widget-close-node, tree-widget-open-node): Remove.
(tree-widget-before-create-icon-functions): New hook.
(tree-widget-value-create): Update to allow customization of icons
and nodes at run-time via that new hook.
(tree-widget-icon-create, tree-widget-leaf-node-icon-p)
(tree-widget-icon-action, tree-widget-icon-help-echo)
(tree-widget-action, tree-widget-help-echo): New functions.
| -rw-r--r-- | lisp/tree-widget.el | 376 |
1 files changed, 235 insertions, 141 deletions
diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el index 407fb65ea49..049999a7b88 100644 --- a/lisp/tree-widget.el +++ b/lisp/tree-widget.el | |||
| @@ -59,37 +59,52 @@ | |||
| 59 | ;; values, it is necessary to set the :args property to nil, then | 59 | ;; values, it is necessary to set the :args property to nil, then |
| 60 | ;; redraw the tree. | 60 | ;; redraw the tree. |
| 61 | ;; | 61 | ;; |
| 62 | ;; :open-control (default `tree-widget-open-control') | 62 | ;; :open-icon (default `tree-widget-open-icon') |
| 63 | ;; :close-control (default `tree-widget-close-control') | 63 | ;; :close-icon (default `tree-widget-close-icon') |
| 64 | ;; :empty-control (default `tree-widget-empty-control') | 64 | ;; :empty-icon (default `tree-widget-empty-icon') |
| 65 | ;; :leaf-control (default `tree-widget-leaf-control') | 65 | ;; :leaf-icon (default `tree-widget-leaf-icon') |
| 66 | ;; :guide (default `tree-widget-guide') | 66 | ;; Those properties define the icon widgets associated to tree |
| 67 | ;; :end-guide (default `tree-widget-end-guide') | 67 | ;; nodes. Icon widgets must derive from the `tree-widget-icon' |
| 68 | ;; :no-guide (default `tree-widget-no-guide') | 68 | ;; widget. The :tag and :glyph-name property values are |
| 69 | ;; :handle (default `tree-widget-handle') | 69 | ;; respectively used when drawing the text and graphic |
| 70 | ;; :no-handle (default `tree-widget-no-handle') | 70 | ;; representation of the tree. The :tag value must be a string |
| 71 | ;; Those properties define the widgets used to draw the tree, and | 71 | ;; that represent a node icon, like "[+]" for example. The |
| 72 | ;; permit to customize its look and feel. For example, using | 72 | ;; :glyph-name value must the name of an image found in the current |
| 73 | ;; `item' widgets with these :tag values: | 73 | ;; theme, like "close" for example (see also the variable |
| 74 | ;; `tree-widget-theme'). | ||
| 74 | ;; | 75 | ;; |
| 75 | ;; open-control "[-] " (OC) | 76 | ;; :guide (default `tree-widget-guide') |
| 76 | ;; close-control "[+] " (CC) | 77 | ;; :end-guide (default `tree-widget-end-guide') |
| 77 | ;; empty-control "[X] " (EC) | 78 | ;; :no-guide (default `tree-widget-no-guide') |
| 78 | ;; leaf-control "[>] " (LC) | 79 | ;; :handle (default `tree-widget-handle') |
| 79 | ;; guide " |" (GU) | 80 | ;; :no-handle (default `tree-widget-no-handle') |
| 80 | ;; noguide " " (NG) | 81 | ;; Those properties define `item'-like widgets used to draw the |
| 81 | ;; end-guide " `" (EG) | 82 | ;; tree guide lines. The :tag property value is used when drawing |
| 82 | ;; handle "-" (HA) | 83 | ;; the text representation of the tree. The graphic look and feel |
| 83 | ;; no-handle " " (NH) | 84 | ;; is given by the images named "guide", "no-guide", "end-guide", |
| 85 | ;; "handle", and "no-handle" found in the current theme (see also | ||
| 86 | ;; the variable `tree-widget-theme'). | ||
| 84 | ;; | 87 | ;; |
| 85 | ;; A tree will look like this: | 88 | ;; These are the default :tag values for icons, and guide lines: |
| 86 | ;; | 89 | ;; |
| 87 | ;; [-] 1 (OC :node) | 90 | ;; open-icon "[-]" |
| 88 | ;; |-[+] 1.0 (GU+HA+CC :node) | 91 | ;; close-icon "[+]" |
| 89 | ;; |-[X] 1.1 (GU+HA+EC :node) | 92 | ;; empty-icon "[X]" |
| 90 | ;; `-[-] 1.2 (EG+HA+OC :node) | 93 | ;; leaf-icon "" |
| 91 | ;; |-[>] 1.2.1 (NG+NH+GU+HA+LC child) | 94 | ;; guide " |" |
| 92 | ;; `-[>] 1.2.2 (NG+NH+EG+HA+LC child) | 95 | ;; no-guide " " |
| 96 | ;; end-guide " `" | ||
| 97 | ;; handle "-" | ||
| 98 | ;; no-handle " " | ||
| 99 | ;; | ||
| 100 | ;; The text representation of a tree looks like this: | ||
| 101 | ;; | ||
| 102 | ;; [-] 1 (open-icon :node) | ||
| 103 | ;; |-[+] 1.0 (guide+handle+close-icon :node) | ||
| 104 | ;; |-[X] 1.1 (guide+handle+empty-icon :node) | ||
| 105 | ;; `-[-] 1.2 (end-guide+handle+open-icon :node) | ||
| 106 | ;; |- 1.2.1 (no-guide+no-handle+guide+handle+leaf-icon leaf) | ||
| 107 | ;; `- 1.2.2 (no-guide+no-handle+end-guide+handle+leaf-icon leaf) | ||
| 93 | ;; | 108 | ;; |
| 94 | ;; By default, images will be used instead of strings to draw a | 109 | ;; By default, images will be used instead of strings to draw a |
| 95 | ;; nice-looking tree. See the `tree-widget-image-enable', | 110 | ;; nice-looking tree. See the `tree-widget-image-enable', |
| @@ -133,19 +148,13 @@ The default is to use the \"tree-widget\" relative name." | |||
| 133 | (defcustom tree-widget-theme nil | 148 | (defcustom tree-widget-theme nil |
| 134 | "*Name of the theme where to look up for images. | 149 | "*Name of the theme where to look up for images. |
| 135 | It must be a sub directory of the directory specified in variable | 150 | It must be a sub directory of the directory specified in variable |
| 136 | `tree-widget-themes-directory'. The default is \"default\". When an | 151 | `tree-widget-themes-directory'. The default theme is \"default\". |
| 137 | image is not found in this theme, the default theme is searched too. | 152 | When an image is not found in a theme, it is searched in the default |
| 138 | A complete theme must contain images with these file names with a | 153 | theme. |
| 139 | supported extension (see also `tree-widget-image-formats'): | 154 | |
| 155 | A complete theme must at least contain images with these file names | ||
| 156 | with a supported extension (see also `tree-widget-image-formats'): | ||
| 140 | 157 | ||
| 141 | \"open\" | ||
| 142 | Represent an expanded node. | ||
| 143 | \"close\" | ||
| 144 | Represent a collapsed node. | ||
| 145 | \"empty\" | ||
| 146 | Represent an expanded node with no child. | ||
| 147 | \"leaf\" | ||
| 148 | Represent a leaf node. | ||
| 149 | \"guide\" | 158 | \"guide\" |
| 150 | A vertical guide line. | 159 | A vertical guide line. |
| 151 | \"no-guide\" | 160 | \"no-guide\" |
| @@ -153,9 +162,21 @@ supported extension (see also `tree-widget-image-formats'): | |||
| 153 | \"end-guide\" | 162 | \"end-guide\" |
| 154 | End of a vertical guide line. | 163 | End of a vertical guide line. |
| 155 | \"handle\" | 164 | \"handle\" |
| 156 | Horizontal guide line that joins the vertical guide line to a node. | 165 | Horizontal guide line that joins the vertical guide line to an icon. |
| 157 | \"no-handle\" | 166 | \"no-handle\" |
| 158 | An invisible handle." | 167 | An invisible handle. |
| 168 | |||
| 169 | Plus images whose name is given by the :glyph-name property of the | ||
| 170 | icon widgets used to draw the tree. By default these images are used: | ||
| 171 | |||
| 172 | \"open\" | ||
| 173 | Icon associated to an expanded tree. | ||
| 174 | \"close\" | ||
| 175 | Icon associated to a collapsed tree. | ||
| 176 | \"empty\" | ||
| 177 | Icon associated to an expanded tree with no child. | ||
| 178 | \"leaf\" | ||
| 179 | Icon associated to a leaf node." | ||
| 159 | :type '(choice (const :tag "Default" nil) | 180 | :type '(choice (const :tag "Default" nil) |
| 160 | (string :tag "Name")) | 181 | (string :tag "Name")) |
| 161 | :group 'tree-widget) | 182 | :group 'tree-widget) |
| @@ -171,6 +192,12 @@ supported extension (see also `tree-widget-image-formats'): | |||
| 171 | "*Default properties of XEmacs images." | 192 | "*Default properties of XEmacs images." |
| 172 | :type 'plist | 193 | :type 'plist |
| 173 | :group 'tree-widget) | 194 | :group 'tree-widget) |
| 195 | |||
| 196 | (defcustom tree-widget-space-width 0.5 | ||
| 197 | "Amount of space between an icon image and a node widget. | ||
| 198 | Must be a valid space :width display property." | ||
| 199 | :group 'tree-widget | ||
| 200 | :type 'sexp) | ||
| 174 | 201 | ||
| 175 | ;;; Image support | 202 | ;;; Image support |
| 176 | ;; | 203 | ;; |
| @@ -297,6 +324,8 @@ properties. Typically it should contain something like this: | |||
| 297 | '(:ascent center :mask (heuristic t)) | 324 | '(:ascent center :mask (heuristic t)) |
| 298 | )) | 325 | )) |
| 299 | 326 | ||
| 327 | When there is no \"tree-widget-theme-setup\" library in the current | ||
| 328 | theme directory, load the one from the default theme, if available. | ||
| 300 | Default global properties are provided for respectively Emacs and | 329 | Default global properties are provided for respectively Emacs and |
| 301 | XEmacs in the variables `tree-widget-image-properties-emacs', and | 330 | XEmacs in the variables `tree-widget-image-properties-emacs', and |
| 302 | `tree-widget-image-properties-xemacs'." | 331 | `tree-widget-image-properties-xemacs'." |
| @@ -308,12 +337,17 @@ XEmacs in the variables `tree-widget-image-properties-emacs', and | |||
| 308 | (file-name-directory file)) t t) | 337 | (file-name-directory file)) t t) |
| 309 | ;; If properties have been setup, use them. | 338 | ;; If properties have been setup, use them. |
| 310 | (unless (setq plist (aref tree-widget--theme 2)) | 339 | (unless (setq plist (aref tree-widget--theme 2)) |
| 311 | ;; By default, use supplied global properties. | 340 | ;; Try from the default theme. |
| 312 | (setq plist (if (featurep 'xemacs) | 341 | (load (expand-file-name "../default/tree-widget-theme-setup" |
| 313 | tree-widget-image-properties-xemacs | 342 | (file-name-directory file)) t t) |
| 314 | tree-widget-image-properties-emacs)) | 343 | ;; If properties have been setup, use them. |
| 315 | ;; Setup the cache. | 344 | (unless (setq plist (aref tree-widget--theme 2)) |
| 316 | (tree-widget-set-image-properties plist))) | 345 | ;; By default, use supplied global properties. |
| 346 | (setq plist (if (featurep 'xemacs) | ||
| 347 | tree-widget-image-properties-xemacs | ||
| 348 | tree-widget-image-properties-emacs)) | ||
| 349 | ;; Setup the cache. | ||
| 350 | (tree-widget-set-image-properties plist)))) | ||
| 317 | plist)) | 351 | plist)) |
| 318 | 352 | ||
| 319 | (defconst tree-widget--cursors | 353 | (defconst tree-widget--cursors |
| @@ -321,10 +355,6 @@ XEmacs in the variables `tree-widget-image-properties-emacs', and | |||
| 321 | ;; This feature works since Emacs 22, and ignored on older versions, | 355 | ;; This feature works since Emacs 22, and ignored on older versions, |
| 322 | ;; and XEmacs. | 356 | ;; and XEmacs. |
| 323 | '( | 357 | '( |
| 324 | ("open" . hand ) | ||
| 325 | ("close" . hand ) | ||
| 326 | ("empty" . arrow) | ||
| 327 | ("leaf" . arrow) | ||
| 328 | ("guide" . arrow) | 358 | ("guide" . arrow) |
| 329 | ("no-guide" . arrow) | 359 | ("no-guide" . arrow) |
| 330 | ("end-guide" . arrow) | 360 | ("end-guide" . arrow) |
| @@ -357,7 +387,8 @@ found." | |||
| 357 | ;; Add the pointer shape | 387 | ;; Add the pointer shape |
| 358 | (cons :pointer | 388 | (cons :pointer |
| 359 | (cons | 389 | (cons |
| 360 | (cdr (assoc name tree-widget--cursors)) | 390 | (or (cdr (assoc name tree-widget--cursors)) |
| 391 | 'hand) | ||
| 361 | (tree-widget-image-properties file))))))))) | 392 | (tree-widget-image-properties file))))))))) |
| 362 | nil))))) | 393 | nil))))) |
| 363 | 394 | ||
| @@ -395,40 +426,39 @@ Return the image found, or nil if not found." | |||
| 395 | "Keymap used inside node buttons. | 426 | "Keymap used inside node buttons. |
| 396 | Handle mouse button 1 click on buttons.") | 427 | Handle mouse button 1 click on buttons.") |
| 397 | 428 | ||
| 398 | (define-widget 'tree-widget-control 'push-button | 429 | (define-widget 'tree-widget-icon 'push-button |
| 399 | "Basic widget other tree-widget node buttons are derived from." | 430 | "Basic widget other tree-widget icons are derived from." |
| 400 | :format "%[%t%]" | 431 | :format "%[%t%]" |
| 401 | :button-keymap tree-widget-button-keymap ; XEmacs | 432 | :button-keymap tree-widget-button-keymap ; XEmacs |
| 402 | :keymap tree-widget-button-keymap ; Emacs | 433 | :keymap tree-widget-button-keymap ; Emacs |
| 434 | :create 'tree-widget-icon-create | ||
| 435 | :action 'tree-widget-icon-action | ||
| 436 | :help-echo 'tree-widget-icon-help-echo | ||
| 403 | ) | 437 | ) |
| 404 | 438 | ||
| 405 | (define-widget 'tree-widget-open-control 'tree-widget-control | 439 | (define-widget 'tree-widget-open-icon 'tree-widget-icon |
| 406 | "Button for an expanded tree-widget node." | 440 | "Icon for an expanded tree-widget node." |
| 407 | :tag "[-] " | 441 | :tag "[-]" |
| 408 | ;;:tag-glyph (tree-widget-find-image "open") | 442 | :glyph-name "open" |
| 409 | :notify 'tree-widget-close-node | ||
| 410 | :help-echo "Collapse node" | ||
| 411 | ) | 443 | ) |
| 412 | 444 | ||
| 413 | (define-widget 'tree-widget-empty-control 'tree-widget-open-control | 445 | (define-widget 'tree-widget-empty-icon 'tree-widget-icon |
| 414 | "Button for an expanded tree-widget node with no child." | 446 | "Icon for an expanded tree-widget node with no child." |
| 415 | :tag "[X] " | 447 | :tag "[X]" |
| 416 | ;;:tag-glyph (tree-widget-find-image "empty") | 448 | :glyph-name "empty" |
| 417 | ) | 449 | ) |
| 418 | 450 | ||
| 419 | (define-widget 'tree-widget-close-control 'tree-widget-control | 451 | (define-widget 'tree-widget-close-icon 'tree-widget-icon |
| 420 | "Button for a collapsed tree-widget node." | 452 | "Icon for a collapsed tree-widget node." |
| 421 | :tag "[+] " | 453 | :tag "[+]" |
| 422 | ;;:tag-glyph (tree-widget-find-image "close") | 454 | :glyph-name "close" |
| 423 | :notify 'tree-widget-open-node | ||
| 424 | :help-echo "Expand node" | ||
| 425 | ) | 455 | ) |
| 426 | 456 | ||
| 427 | (define-widget 'tree-widget-leaf-control 'item | 457 | (define-widget 'tree-widget-leaf-icon 'tree-widget-icon |
| 428 | "Representation of a tree-widget leaf node." | 458 | "Icon for a tree-widget leaf node." |
| 429 | :tag " " ;; Need at least one char to display the image :-( | 459 | :tag "" |
| 430 | ;;:tag-glyph (tree-widget-find-image "leaf") | 460 | :glyph-name "leaf" |
| 431 | :format "%t" | 461 | :button-face 'default |
| 432 | ) | 462 | ) |
| 433 | 463 | ||
| 434 | (define-widget 'tree-widget-guide 'item | 464 | (define-widget 'tree-widget-guide 'item |
| @@ -454,7 +484,7 @@ Handle mouse button 1 click on buttons.") | |||
| 454 | 484 | ||
| 455 | (define-widget 'tree-widget-handle 'item | 485 | (define-widget 'tree-widget-handle 'item |
| 456 | "Horizontal guide line that joins a vertical guide line to a node." | 486 | "Horizontal guide line that joins a vertical guide line to a node." |
| 457 | :tag " " | 487 | :tag "-" |
| 458 | ;;:tag-glyph (tree-widget-find-image "handle") | 488 | ;;:tag-glyph (tree-widget-find-image "handle") |
| 459 | :format "%t" | 489 | :format "%t" |
| 460 | ) | 490 | ) |
| @@ -473,10 +503,12 @@ Handle mouse button 1 click on buttons.") | |||
| 473 | :value-get 'widget-value-value-get | 503 | :value-get 'widget-value-value-get |
| 474 | :value-delete 'widget-children-value-delete | 504 | :value-delete 'widget-children-value-delete |
| 475 | :value-create 'tree-widget-value-create | 505 | :value-create 'tree-widget-value-create |
| 476 | :open-control 'tree-widget-open-control | 506 | :action 'tree-widget-action |
| 477 | :close-control 'tree-widget-close-control | 507 | :help-echo 'tree-widget-help-echo |
| 478 | :empty-control 'tree-widget-empty-control | 508 | :open-icon 'tree-widget-open-icon |
| 479 | :leaf-control 'tree-widget-leaf-control | 509 | :close-icon 'tree-widget-close-icon |
| 510 | :empty-icon 'tree-widget-empty-icon | ||
| 511 | :leaf-icon 'tree-widget-leaf-icon | ||
| 480 | :guide 'tree-widget-guide | 512 | :guide 'tree-widget-guide |
| 481 | :end-guide 'tree-widget-end-guide | 513 | :end-guide 'tree-widget-end-guide |
| 482 | :no-guide 'tree-widget-no-guide | 514 | :no-guide 'tree-widget-no-guide |
| @@ -553,32 +585,35 @@ WIDGET's :node sub-widget." | |||
| 553 | (widget-put arg :value (widget-value child)) | 585 | (widget-put arg :value (widget-value child)) |
| 554 | ;; Save properties specified in :keep. | 586 | ;; Save properties specified in :keep. |
| 555 | (tree-widget-keep arg child))))) | 587 | (tree-widget-keep arg child))))) |
| 556 | 588 | ||
| 557 | (defvar tree-widget-after-toggle-functions nil | 589 | ;;; Widget creation |
| 558 | "Hooks run after toggling a tree-widget expansion. | 590 | ;; |
| 559 | Each function will receive the tree-widget as its unique argument. | 591 | (defvar tree-widget-before-create-icon-functions nil |
| 560 | This hook should be local in the buffer used to display widgets.") | 592 | "Hooks run before to create a tree-widget icon. |
| 561 | 593 | Each function is passed the icon widget not yet created. | |
| 562 | (defun tree-widget-close-node (widget &rest ignore) | 594 | The value of the icon widget :node property is a tree :node widget or |
| 563 | "Collapse the tree-widget, parent of WIDGET. | 595 | a leaf node widget, not yet created. |
| 564 | WIDGET is, or derives from, a tree-widget-open-control widget. | 596 | This hook can be used to dynamically change properties of the icon and |
| 565 | IGNORE other arguments." | 597 | associated node widgets. For example, to dynamically change the look |
| 566 | (let ((tree (widget-get widget :parent))) | 598 | and feel of the tree-widget by changing the values of the :tag |
| 567 | ;; Before to collapse the node, save children values so next open | 599 | and :glyph-name properties of the icon widget. |
| 568 | ;; can recover them. | 600 | This hook should be local in the buffer setup to display widgets.") |
| 569 | (tree-widget-children-value-save tree) | 601 | |
| 570 | (widget-put tree :open nil) | 602 | (defun tree-widget-icon-create (icon) |
| 571 | (widget-value-set tree nil) | 603 | "Create the ICON widget." |
| 572 | (run-hook-with-args 'tree-widget-after-toggle-functions tree))) | 604 | (run-hook-with-args 'tree-widget-before-create-icon-functions icon) |
| 573 | 605 | (widget-put icon :tag-glyph | |
| 574 | (defun tree-widget-open-node (widget &rest ignore) | 606 | (tree-widget-find-image (widget-get icon :glyph-name))) |
| 575 | "Expand the tree-widget, parent of WIDGET. | 607 | ;; Ensure there is at least one char to display the image. |
| 576 | WIDGET is, or derives from, a tree-widget-close-control widget. | 608 | (and (widget-get icon :tag-glyph) |
| 577 | IGNORE other arguments." | 609 | (equal "" (or (widget-get icon :tag) "")) |
| 578 | (let ((tree (widget-get widget :parent))) | 610 | (widget-put icon :tag " ")) |
| 579 | (widget-put tree :open t) | 611 | (widget-default-create icon) |
| 580 | (widget-value-set tree t) | 612 | ;; Insert space between the icon and the node widget. |
| 581 | (run-hook-with-args 'tree-widget-after-toggle-functions tree))) | 613 | (insert-char ? 1) |
| 614 | (put-text-property | ||
| 615 | (1- (point)) (point) | ||
| 616 | 'display (list 'space :width tree-widget-space-width))) | ||
| 582 | 617 | ||
| 583 | (defun tree-widget-value-create (tree) | 618 | (defun tree-widget-value-create (tree) |
| 584 | "Create the TREE tree-widget." | 619 | "Create the TREE tree-widget." |
| @@ -598,37 +633,34 @@ IGNORE other arguments." | |||
| 598 | (let ((args (widget-get tree :args)) | 633 | (let ((args (widget-get tree :args)) |
| 599 | (xpandr (or (widget-get tree :expander) | 634 | (xpandr (or (widget-get tree :expander) |
| 600 | (widget-get tree :dynargs))) | 635 | (widget-get tree :dynargs))) |
| 601 | (leaf (widget-get tree :leaf-control)) | ||
| 602 | (guide (widget-get tree :guide)) | 636 | (guide (widget-get tree :guide)) |
| 603 | (noguide (widget-get tree :no-guide)) | 637 | (noguide (widget-get tree :no-guide)) |
| 604 | (endguide (widget-get tree :end-guide)) | 638 | (endguide (widget-get tree :end-guide)) |
| 605 | (handle (widget-get tree :handle)) | 639 | (handle (widget-get tree :handle)) |
| 606 | (nohandle (widget-get tree :no-handle)) | 640 | (nohandle (widget-get tree :no-handle)) |
| 607 | (leafi (tree-widget-find-image "leaf")) | ||
| 608 | (guidi (tree-widget-find-image "guide")) | 641 | (guidi (tree-widget-find-image "guide")) |
| 609 | (noguidi (tree-widget-find-image "no-guide")) | 642 | (noguidi (tree-widget-find-image "no-guide")) |
| 610 | (endguidi (tree-widget-find-image "end-guide")) | 643 | (endguidi (tree-widget-find-image "end-guide")) |
| 611 | (handli (tree-widget-find-image "handle")) | 644 | (handli (tree-widget-find-image "handle")) |
| 612 | (nohandli (tree-widget-find-image "no-handle")) | 645 | (nohandli (tree-widget-find-image "no-handle"))) |
| 613 | child) | ||
| 614 | ;; Request children at run time, when not already done. | 646 | ;; Request children at run time, when not already done. |
| 615 | (when (and (not args) xpandr) | 647 | (when (and (not args) xpandr) |
| 616 | (setq args (mapcar 'widget-convert (funcall xpandr tree))) | 648 | (setq args (mapcar 'widget-convert (funcall xpandr tree))) |
| 617 | (widget-put tree :args args)) | 649 | (widget-put tree :args args)) |
| 618 | ;; Insert the node "open" button. | 650 | ;; Create the icon widget for the expanded tree. |
| 619 | (push (widget-create-child-and-convert | 651 | (push (widget-create-child-and-convert |
| 620 | tree (widget-get | 652 | tree (widget-get tree (if args :open-icon :empty-icon)) |
| 621 | tree (if args :open-control :empty-control)) | 653 | ;; At this point the node widget isn't yet created. |
| 622 | :tag-glyph (tree-widget-find-image | 654 | :node (setq node (widget-convert node))) |
| 623 | (if args "open" "empty"))) | ||
| 624 | buttons) | 655 | buttons) |
| 625 | ;; Insert the :node element. | 656 | ;; Create the tree node widget. |
| 626 | (push (widget-create-child-and-convert tree node) | 657 | (push (widget-create-child tree node) children) |
| 627 | children) | 658 | ;; Update the icon :node with the created node widget. |
| 628 | ;; Insert children. | 659 | (widget-put (car buttons) :node (car children)) |
| 660 | ;; Create the tree children. | ||
| 629 | (while args | 661 | (while args |
| 630 | (setq child (car args) | 662 | (setq node (car args) |
| 631 | args (cdr args)) | 663 | args (cdr args)) |
| 632 | (and indent (insert-char ?\ indent)) | 664 | (and indent (insert-char ?\ indent)) |
| 633 | ;; Insert guide lines elements from previous levels. | 665 | ;; Insert guide lines elements from previous levels. |
| 634 | (dolist (f (reverse flags)) | 666 | (dolist (f (reverse flags)) |
| @@ -644,30 +676,92 @@ IGNORE other arguments." | |||
| 644 | ;; Insert the node handle line | 676 | ;; Insert the node handle line |
| 645 | (widget-create-child-and-convert | 677 | (widget-create-child-and-convert |
| 646 | tree handle :tag-glyph handli) | 678 | tree handle :tag-glyph handli) |
| 647 | ;; If leaf node, insert a leaf node button. | 679 | (if (tree-widget-p node) |
| 648 | (unless (tree-widget-p child) | 680 | ;; Create a sub-tree node. |
| 681 | (push (widget-create-child-and-convert | ||
| 682 | tree node :tree-widget--guide-flags | ||
| 683 | (cons (if args t) flags)) | ||
| 684 | children) | ||
| 685 | ;; Create the icon widget for a leaf node. | ||
| 649 | (push (widget-create-child-and-convert | 686 | (push (widget-create-child-and-convert |
| 650 | tree leaf :tag-glyph leafi) | 687 | tree (widget-get tree :leaf-icon) |
| 651 | buttons)) | 688 | ;; At this point the node widget isn't yet created. |
| 652 | ;; Finally, insert the child widget. | 689 | :node (setq node (widget-convert |
| 653 | (push (widget-create-child-and-convert | 690 | node :tree-widget--guide-flags |
| 654 | tree child | 691 | (cons (if args t) flags))) |
| 655 | :tree-widget--guide-flags (cons (if args t) flags)) | 692 | :tree-widget--leaf-flag t) |
| 656 | children))) | 693 | buttons) |
| 694 | ;; Create the leaf node widget. | ||
| 695 | (push (widget-create-child tree node) children) | ||
| 696 | ;; Update the icon :node with the created node widget. | ||
| 697 | (widget-put (car buttons) :node (car children))))) | ||
| 657 | ;;;; Collapsed node. | 698 | ;;;; Collapsed node. |
| 658 | ;; Insert the "closed" node button. | 699 | ;; Create the icon widget for the collapsed tree. |
| 659 | (push (widget-create-child-and-convert | 700 | (push (widget-create-child-and-convert |
| 660 | tree (widget-get tree :close-control) | 701 | tree (widget-get tree :close-icon) |
| 661 | :tag-glyph (tree-widget-find-image "close")) | 702 | ;; At this point the node widget isn't yet created. |
| 703 | :node (setq node (widget-convert node))) | ||
| 662 | buttons) | 704 | buttons) |
| 663 | ;; Insert the :node element. | 705 | ;; Create the tree node widget. |
| 664 | (push (widget-create-child-and-convert tree node) | 706 | (push (widget-create-child tree node) children) |
| 665 | children)) | 707 | ;; Update the icon :node with the created node widget. |
| 666 | ;; Save widget children and buttons. The :node child is the first | 708 | (widget-put (car buttons) :node (car children))) |
| 667 | ;; element in children. | 709 | ;; Save widget children and buttons. The tree-widget :node child |
| 710 | ;; is the first element in :children. | ||
| 668 | (widget-put tree :children (nreverse children)) | 711 | (widget-put tree :children (nreverse children)) |
| 669 | (widget-put tree :buttons buttons) | 712 | (widget-put tree :buttons buttons))) |
| 670 | )) | 713 | |
| 714 | ;;; Widget callbacks | ||
| 715 | ;; | ||
| 716 | (defsubst tree-widget-leaf-node-icon-p (icon) | ||
| 717 | "Return non-nil if ICON is a leaf node icon. | ||
| 718 | That is, if its :node property value is a leaf node widget." | ||
| 719 | (widget-get icon :tree-widget--leaf-flag)) | ||
| 720 | |||
| 721 | (defun tree-widget-icon-action (icon &optional event) | ||
| 722 | "Handle the ICON widget :action. | ||
| 723 | If ICON :node is a leaf node it handles the :action. The tree-widget | ||
| 724 | parent of ICON handles the :action otherwise. | ||
| 725 | Pass the received EVENT to :action." | ||
| 726 | (let ((node (widget-get icon (if (tree-widget-leaf-node-icon-p icon) | ||
| 727 | :node :parent)))) | ||
| 728 | (widget-apply node :action event))) | ||
| 729 | |||
| 730 | (defun tree-widget-icon-help-echo (icon) | ||
| 731 | "Return the help-echo string of ICON. | ||
| 732 | If ICON :node is a leaf node it handles the :help-echo. The tree-widget | ||
| 733 | parent of ICON handles the :help-echo otherwise." | ||
| 734 | (let* ((node (widget-get icon (if (tree-widget-leaf-node-icon-p icon) | ||
| 735 | :node :parent))) | ||
| 736 | (help-echo (widget-get node :help-echo))) | ||
| 737 | (if (functionp help-echo) | ||
| 738 | (funcall help-echo node) | ||
| 739 | help-echo))) | ||
| 740 | |||
| 741 | (defvar tree-widget-after-toggle-functions nil | ||
| 742 | "Hooks run after toggling a tree-widget expansion. | ||
| 743 | Each function is passed a tree-widget. If the value of the :open | ||
| 744 | property is non-nil the tree has been expanded, else collapsed. | ||
| 745 | This hook should be local in the buffer setup to display widgets.") | ||
| 746 | |||
| 747 | (defun tree-widget-action (tree &optional event) | ||
| 748 | "Handle the :action of the TREE tree-widget. | ||
| 749 | That is, toggle expansion of the TREE tree-widget. | ||
| 750 | Ignore the EVENT argument." | ||
| 751 | (let ((open (not (widget-get tree :open)))) | ||
| 752 | (or open | ||
| 753 | ;; Before to collapse the node, save children values so next | ||
| 754 | ;; open can recover them. | ||
| 755 | (tree-widget-children-value-save tree)) | ||
| 756 | (widget-put tree :open open) | ||
| 757 | (widget-value-set tree open) | ||
| 758 | (run-hook-with-args 'tree-widget-after-toggle-functions tree))) | ||
| 759 | |||
| 760 | (defun tree-widget-help-echo (tree) | ||
| 761 | "Return the help-echo string of the TREE tree-widget." | ||
| 762 | (if (widget-get tree :open) | ||
| 763 | "Collapse node" | ||
| 764 | "Expand node")) | ||
| 671 | 765 | ||
| 672 | (provide 'tree-widget) | 766 | (provide 'tree-widget) |
| 673 | 767 | ||