comparison lisp/wid-edit.el @ 1833:eed841acc858

[xemacs-hg @ 2003-12-19 14:28:45 by youngs] 2003-12-15 Steve Youngs <sryoungs@bigpond.net.au> * wid-edit.el (lazy): New. (widget-child-value-get): New. (widget-child-value-inline): New. (widget-child-validate): New. (widget-type-value-create): New. (widget-type-default-get): New. (widget-type-match): New. This adds a "lazy" widget to allow the definition of recursive datatypes for customize. The composite widgets expand their subtypes immediately, which cause obvious problems for recursive datatypes. The "lazy" will only expand them when needed, hense the name. From Per Abrahamsen <abraham@dina.kvl.dk> 2003-12-15 Steve Youngs <sryoungs@bigpond.net.au> * lispref/customize.texi (Defining New Types): New node. From Per Abrahamsen <abraham@dina.kvl.dk>
author youngs
date Fri, 19 Dec 2003 14:29:07 +0000
parents 92dd8587c485
children c0bb56c2da36
comparison
equal deleted inserted replaced
1832:5d8dcaecc32b 1833:eed841acc858
4024 (if (functionp help-echo) 4024 (if (functionp help-echo)
4025 (setq help-echo (funcall help-echo widget))) 4025 (setq help-echo (funcall help-echo widget)))
4026 (if (stringp help-echo) 4026 (if (stringp help-echo)
4027 (display-message 'help-echo help-echo)))) 4027 (display-message 'help-echo help-echo))))
4028 4028
4029 (define-widget 'lazy 'default
4030 "Base widget for recursive datastructures.
4031
4032 The `lazy' widget will, when instantiated, contain a single inferior
4033 widget, of the widget type specified by the :type parameter. The
4034 value of the `lazy' widget is the same as the value of the inferior
4035 widget. When deriving a new widget from the 'lazy' widget, the :type
4036 parameter is allowed to refer to the widget currently being defined,
4037 thus allowing recursive datastructures to be described.
4038
4039 The:type parameter takes the same arguments as the defcustom
4040 parameter with the same name.
4041
4042 Most composite widgets, i.e. widgets containing other widgets, does
4043 not allow recursion. That is, when you define a new widget type, none
4044 of the inferior widgets may be of the same type you are currently
4045 defining.
4046
4047 In Lisp, however, it is custom to define datastructures in terms of
4048 themselves. A list, for example, is defined as either nil, or a cons
4049 cell whose cdr itself is a list. The obvious way to translate this
4050 into a widget type would be
4051
4052 (define-widget 'my-list 'choice
4053 \"A list of sexps.\"
4054 :tag \"Sexp list\"
4055 :args '((const nil) (cons :value (nil) sexp my-list)))
4056
4057 Here we attempt to define my-list as a choice of either the constant
4058 nil, or a cons-cell containing a sexp and my-lisp. This will not work
4059 because the `choice' widget does not allow recursion.
4060
4061 Using the `lazy' widget you can overcome this problem, as in this
4062 example:
4063
4064 (define-widget 'sexp-list 'lazy
4065 \"A list of sexps.\"
4066 :tag \"Sexp list\"
4067 :type '(choice (const nil) (cons :value (nil) sexp sexp-list)))"
4068 :format "%{%t%}: %v"
4069 ;; We don't convert :type because we want to allow recursive
4070 ;; datastructures. This is slow, so we should not create speed
4071 ;; critical widgets by deriving from this.
4072 :convert-widget 'widget-value-convert-widget
4073 :value-create 'widget-type-value-create
4074 :value-delete 'widget-children-value-delete
4075 :value-get 'widget-child-value-get
4076 :value-inline 'widget-child-value-inline
4077 :default-get 'widget-type-default-get
4078 :match 'widget-type-match
4079 :validate 'widget-child-validate)
4080
4081 (defun widget-child-value-get (widget)
4082 "Get the value of the first member of :children in WIDGET."
4083 (widget-value (car (widget-get widget :children))))
4084
4085 (defun widget-child-value-inline (widget)
4086 "Get the inline value of the first member of :children in WIDGET."
4087 (widget-apply (car (widget-get widget :children)) :value-inline))
4088
4089 (defun widget-child-validate (widget)
4090 "The result of validating the first member of :children in WIDGET."
4091 (widget-apply (car (widget-get widget :children)) :validate))
4092
4093 (defun widget-type-value-create (widget)
4094 "Convert and instantiate the value of the :type attribute of WIDGET.
4095 Store the newly created widget in the :children attribute.
4096
4097 The value of the :type attribute should be an unconverted widget type."
4098 (let ((value (widget-get widget :value))
4099 (type (widget-get widget :type)))
4100 (widget-put widget :children
4101 (list (widget-create-child-value widget
4102 (widget-convert type)
4103 value)))))
4104
4105 (defun widget-type-default-get (widget)
4106 "Get default value from the :type attribute of WIDGET.
4107
4108 The value of the :type attribute should be an unconverted widget type."
4109 (widget-default-get (widget-convert (widget-get widget :type))))
4110
4111 (defun widget-type-match (widget value)
4112 "Non-nil if the :type value of WIDGET matches VALUE.
4113
4114 The value of the :type attribute should be an unconverted widget type."
4115 (widget-apply (widget-convert (widget-get widget :type)) :match value))
4116
4029 ;;; The End: 4117 ;;; The End:
4030 4118
4031 (provide 'wid-edit) 4119 (provide 'wid-edit)
4032 4120
4033 ;;; wid-edit.el ends here 4121 ;;; wid-edit.el ends here