You can define specialized widgets with define-widget
. It allows
you to create a shorthand for more complex widgets, including specifying
component widgets and new default values for the keyword arguments.
Define a new widget type named name that derives from class.
name and class should both be symbols, and class should be one of the existing widget types.
The third argument doc is a documentation string for the widget.
args should be key-value pairs, overriding keyword values of class, or adding new recognized keywords for name.
Usually, you’ll want to derive from an existing widget type, like the
editable-field
widget, or the default
widget, but it’s
also possible to derive from nothing, by passing a value of nil
as class. Note that if you do this, you’re entirely responsible
for defining a whole new default behavior for your widgets.
After using this function, the following two calls will create identical widgets:
(widget-create name)
(apply widget-create class args)
Using define-widget
just stores the definition of the widget type
in the widget-type
property of name, which is what
widget-create
uses.
If you only want to specify defaults for keywords with no complex
conversions, you can use identity
as your conversion function.
When defining new widgets, the :convert-widget
property might
be useful:
:convert-widget
Function to convert a widget type before creating a widget of that type.
It takes a widget type as an argument, and returns the converted widget type. When a widget is created, this function is called for the widget type and all the widget’s parent types, most derived first.
The predefined functions widget-types-convert-widget
and
widget-value-convert-widget
can be used here.
Example:
(defvar widget-ranged-integer-map (let ((map (copy-keymap widget-keymap))) (define-key map [up] #'widget-ranged-integer-increase) (define-key map [down] #'widget-ranged-integer-decrease) map))
(define-widget 'ranged-integer 'integer "A ranged integer widget." :min-value most-negative-fixnum :max-value most-positive-fixnum :keymap widget-ranged-integer-map)
(defun widget-ranged-integer-change (widget how) "Change the value of the ranged-integer WIDGET, according to HOW." (let* ((value (widget-value widget)) (newval (cond ((eq how 'up) (if (< (1+ value) (widget-get widget :max-value)) (1+ value) (widget-get widget :max-value))) ((eq how 'down) (if (> (1- value) (widget-get widget :min-value)) (1- value) (widget-get widget :min-value))) (t (error "HOW has a bad value")))) (inhibit-read-only t)) (widget-value-set widget newval)))
(defun widget-ranged-integer-increase (widget) "Increase the value of the ranged-integer WIDGET." (interactive (list (widget-at))) (widget-ranged-integer-change widget 'up))
(defun widget-ranged-integer-decrease (widget) "Decrease the value of the ranged-integer WIDGET." (interactive (list (widget-at))) (widget-ranged-integer-change widget 'down))