-(defun tree-widget-map (widget fun)
- "For each WIDGET displayed child call function FUN.
-FUN is called with three arguments like this:
-
- (FUN CHILD IS-NODE WIDGET)
-
-where:
-- - CHILD is the child widget.
-- - IS-NODE is non-nil if CHILD is WIDGET node widget."
- (when (widget-get widget :tree-widget--node)
- (funcall fun (widget-get widget :tree-widget--node) t widget)
- (dolist (child (widget-get widget :children))
- (if (tree-widget-p child)
- ;; The child is a tree node.
- (tree-widget-map child fun)
- ;; Another non tree node.
- (funcall fun child nil widget)))))
+(defsubst tree-widget-leaf-node-icon-p (icon)
+ "Return non-nil if ICON is a leaf node icon.
+That is, if its :node property value is a leaf node widget."
+ (widget-get icon :tree-widget--leaf-flag))
+
+(defun tree-widget-icon-action (icon &optional event)
+ "Handle the ICON widget :action.
+If ICON :node is a leaf node it handles the :action. The tree-widget
+parent of ICON handles the :action otherwise.
+Pass the received EVENT to :action."
+ (let ((node (widget-get icon (if (tree-widget-leaf-node-icon-p icon)
+ :node :parent))))
+ (widget-apply node :action event)))
+
+(defun tree-widget-icon-help-echo (icon)
+ "Return the help-echo string of ICON.
+If ICON :node is a leaf node it handles the :help-echo. The tree-widget
+parent of ICON handles the :help-echo otherwise."
+ (let* ((node (widget-get icon (if (tree-widget-leaf-node-icon-p icon)
+ :node :parent)))
+ (help-echo (widget-get node :help-echo)))
+ (if (functionp help-echo)
+ (funcall help-echo node)
+ help-echo)))
+
+(defvar tree-widget-after-toggle-functions nil
+ "Hooks run after toggling a tree-widget expansion.
+Each function is passed a tree-widget. If the value of the :open
+property is non-nil the tree has been expanded, else collapsed.
+This hook should be local in the buffer setup to display widgets.")
+
+(defun tree-widget-action (tree &optional event)
+ "Handle the :action of the TREE tree-widget.
+That is, toggle expansion of the TREE tree-widget.
+Ignore the EVENT argument."
+ (let ((open (not (widget-get tree :open))))
+ (or open
+ ;; Before to collapse the node, save children values so next
+ ;; open can recover them.
+ (tree-widget-children-value-save tree))
+ (widget-put tree :open open)
+ (widget-value-set tree open)
+ (run-hook-with-args 'tree-widget-after-toggle-functions tree)))
+
+(defun tree-widget-help-echo (tree)
+ "Return the help-echo string of the TREE tree-widget."
+ (if (widget-get tree :open)
+ "Collapse node"
+ "Expand node"))