diff options
| author | Jonas Bernoulli | 2012-12-06 15:10:36 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2012-12-06 15:10:36 -0500 |
| commit | 24fc9480399b2d018e8d85f34e9c5d8c327ce3bf (patch) | |
| tree | 46246a1e160516229e938fc5b59c266199dd8529 | |
| parent | e86f51344b4bc58f8342b360eaf3d2b2ca0c470a (diff) | |
| download | emacs-24fc9480399b2d018e8d85f34e9c5d8c327ce3bf.tar.gz emacs-24fc9480399b2d018e8d85f34e9c5d8c327ce3bf.zip | |
* lisp/button.el: Make them work in header-lines.
(button-map): Add bindings for header-line and mode-line use.
(button-get, button-put, button-label): `button' may now be a string.
(button-activate): Don't make it a defsubst.
(button--area-button-p, button--area-button-string): New functions.
(make-text-button): Fix the return value when `beg' was a string.
(push-button): Handle the mode-line case.
Fixes: debbugs:12817
| -rw-r--r-- | lisp/ChangeLog | 10 | ||||
| -rw-r--r-- | lisp/button.el | 73 |
2 files changed, 61 insertions, 22 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index d94ffbab67e..58b7e443798 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2012-12-06 Jonas Bernoulli <jonas@bernoul.li> | ||
| 2 | |||
| 3 | * button.el: Make them work in header-lines (bug#12817). | ||
| 4 | (button-map): Add bindings for header-line and mode-line use. | ||
| 5 | (button-get, button-put, button-label): `button' may now be a string. | ||
| 6 | (button-activate): Don't make it a defsubst. | ||
| 7 | (button--area-button-p, button--area-button-string): New functions. | ||
| 8 | (make-text-button): Fix the return value when `beg' was a string. | ||
| 9 | (push-button): Handle the mode-line case. | ||
| 10 | |||
| 1 | 2012-12-06 Stefan Monnier <monnier@iro.umontreal.ca> | 11 | 2012-12-06 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 12 | ||
| 3 | * progmodes/sql.el: Use cl-lib and lexical-binding; various cleanup. | 13 | * progmodes/sql.el: Use cl-lib and lexical-binding; various cleanup. |
diff --git a/lisp/button.el b/lisp/button.el index 3cf38fa64c6..c52dcabed08 100644 --- a/lisp/button.el +++ b/lisp/button.el | |||
| @@ -64,6 +64,11 @@ | |||
| 64 | ;; might get converted to ^M when building loaddefs.el | 64 | ;; might get converted to ^M when building loaddefs.el |
| 65 | (define-key map [(control ?m)] 'push-button) | 65 | (define-key map [(control ?m)] 'push-button) |
| 66 | (define-key map [mouse-2] 'push-button) | 66 | (define-key map [mouse-2] 'push-button) |
| 67 | ;; FIXME: You'd think that for keymaps coming from text-properties on the | ||
| 68 | ;; mode-line or header-line, the `mode-line' or `header-line' prefix | ||
| 69 | ;; shouldn't be necessary! | ||
| 70 | (define-key map [mode-line mouse-2] 'push-button) | ||
| 71 | (define-key map [header-line mouse-2] 'push-button) | ||
| 67 | map) | 72 | map) |
| 68 | "Keymap used by buttons.") | 73 | "Keymap used by buttons.") |
| 69 | 74 | ||
| @@ -184,10 +189,12 @@ changes to a supertype are not reflected in its subtypes)." | |||
| 184 | 189 | ||
| 185 | (defun button-get (button prop) | 190 | (defun button-get (button prop) |
| 186 | "Get the property of button BUTTON named PROP." | 191 | "Get the property of button BUTTON named PROP." |
| 187 | (if (overlayp button) | 192 | (cond ((overlayp button) |
| 188 | (overlay-get button prop) | 193 | (overlay-get button prop)) |
| 189 | ;; Must be a text-property button. | 194 | ((button--area-button-p button) |
| 190 | (get-text-property button prop))) | 195 | (get-text-property 0 prop (button--area-button-string button))) |
| 196 | (t ; Must be a text-property button. | ||
| 197 | (get-text-property button prop)))) | ||
| 191 | 198 | ||
| 192 | (defun button-put (button prop val) | 199 | (defun button-put (button prop val) |
| 193 | "Set BUTTON's PROP property to VAL." | 200 | "Set BUTTON's PROP property to VAL." |
| @@ -202,21 +209,30 @@ changes to a supertype are not reflected in its subtypes)." | |||
| 202 | ;; Disallow updating the `category' property directly. | 209 | ;; Disallow updating the `category' property directly. |
| 203 | (error "Button `category' property may not be set directly"))) | 210 | (error "Button `category' property may not be set directly"))) |
| 204 | ;; Add the property. | 211 | ;; Add the property. |
| 205 | (if (overlayp button) | 212 | (cond ((overlayp button) |
| 206 | (overlay-put button prop val) | 213 | (overlay-put button prop val)) |
| 207 | ;; Must be a text-property button. | 214 | ((button--area-button-p button) |
| 208 | (put-text-property | 215 | (setq button (button--area-button-string button)) |
| 209 | (or (previous-single-property-change (1+ button) 'button) | 216 | (put-text-property 0 (length button) prop val button)) |
| 210 | (point-min)) | 217 | (t ; Must be a text-property button. |
| 211 | (or (next-single-property-change button 'button) | 218 | (put-text-property |
| 212 | (point-max)) | 219 | (or (previous-single-property-change (1+ button) 'button) |
| 213 | prop val))) | 220 | (point-min)) |
| 214 | 221 | (or (next-single-property-change button 'button) | |
| 215 | (defsubst button-activate (button &optional use-mouse-action) | 222 | (point-max)) |
| 223 | prop val)))) | ||
| 224 | |||
| 225 | (defun button-activate (button &optional use-mouse-action) | ||
| 216 | "Call BUTTON's action property. | 226 | "Call BUTTON's action property. |
| 217 | If USE-MOUSE-ACTION is non-nil, invoke the button's mouse-action | 227 | If USE-MOUSE-ACTION is non-nil, invoke the button's mouse-action |
| 218 | instead of its normal action; if the button has no mouse-action, | 228 | instead of its normal action; if the button has no mouse-action, |
| 219 | the normal action is used instead." | 229 | the normal action is used instead. |
| 230 | |||
| 231 | The action can either be a marker or a function. If it's a | ||
| 232 | marker then goto it. Otherwise it it is a function then it is | ||
| 233 | called with BUTTON as only argument. BUTTON is either an | ||
| 234 | overlay, a buffer position, or (for buttons in the mode-line or | ||
| 235 | header-line) a string." | ||
| 220 | (let ((action (or (and use-mouse-action (button-get button 'mouse-action)) | 236 | (let ((action (or (and use-mouse-action (button-get button 'mouse-action)) |
| 221 | (button-get button 'action)))) | 237 | (button-get button 'action)))) |
| 222 | (if (markerp action) | 238 | (if (markerp action) |
| @@ -228,7 +244,10 @@ the normal action is used instead." | |||
| 228 | 244 | ||
| 229 | (defun button-label (button) | 245 | (defun button-label (button) |
| 230 | "Return BUTTON's text label." | 246 | "Return BUTTON's text label." |
| 231 | (buffer-substring-no-properties (button-start button) (button-end button))) | 247 | (if (button--area-button-p button) |
| 248 | (substring-no-properties (button--area-button-string button)) | ||
| 249 | (buffer-substring-no-properties (button-start button) | ||
| 250 | (button-end button)))) | ||
| 232 | 251 | ||
| 233 | (defsubst button-type (button) | 252 | (defsubst button-type (button) |
| 234 | "Return BUTTON's button-type." | 253 | "Return BUTTON's button-type." |
| @@ -238,6 +257,12 @@ the normal action is used instead." | |||
| 238 | "Return t if BUTTON has button-type TYPE, or one of TYPE's subtypes." | 257 | "Return t if BUTTON has button-type TYPE, or one of TYPE's subtypes." |
| 239 | (button-type-subtype-p (button-get button 'type) type)) | 258 | (button-type-subtype-p (button-get button 'type) type)) |
| 240 | 259 | ||
| 260 | (defalias 'button--area-button-p 'stringp | ||
| 261 | "Return non-nil if BUTTON is an area button. | ||
| 262 | Such area buttons are used for buttons in the mode-line and header-line.") | ||
| 263 | |||
| 264 | (defalias 'button--area-button-string 'identity | ||
| 265 | "Return area button BUTTON's button-string.") | ||
| 241 | 266 | ||
| 242 | ;; Creating overlay buttons | 267 | ;; Creating overlay buttons |
| 243 | 268 | ||
| @@ -324,7 +349,7 @@ Also see `insert-text-button'." | |||
| 324 | (cons 'button (cons (list t) properties)) | 349 | (cons 'button (cons (list t) properties)) |
| 325 | object) | 350 | object) |
| 326 | ;; Return something that can be used to get at the button. | 351 | ;; Return something that can be used to get at the button. |
| 327 | beg)) | 352 | (or object beg))) |
| 328 | 353 | ||
| 329 | (defun insert-text-button (label &rest properties) | 354 | (defun insert-text-button (label &rest properties) |
| 330 | "Insert a button with the label LABEL. | 355 | "Insert a button with the label LABEL. |
| @@ -405,7 +430,9 @@ POS may be either a buffer position or a mouse-event. If | |||
| 405 | USE-MOUSE-ACTION is non-nil, invoke the button's mouse-action | 430 | USE-MOUSE-ACTION is non-nil, invoke the button's mouse-action |
| 406 | instead of its normal action; if the button has no mouse-action, | 431 | instead of its normal action; if the button has no mouse-action, |
| 407 | the normal action is used instead. The action may be either a | 432 | the normal action is used instead. The action may be either a |
| 408 | function to call or a marker to display. | 433 | function to call or a marker to display and is invoked using |
| 434 | `button-activate' (which see). | ||
| 435 | |||
| 409 | POS defaults to point, except when `push-button' is invoked | 436 | POS defaults to point, except when `push-button' is invoked |
| 410 | interactively as the result of a mouse-event, in which case, the | 437 | interactively as the result of a mouse-event, in which case, the |
| 411 | mouse event is used. | 438 | mouse event is used. |
| @@ -417,11 +444,13 @@ return t." | |||
| 417 | ;; POS is a mouse event; switch to the proper window/buffer | 444 | ;; POS is a mouse event; switch to the proper window/buffer |
| 418 | (let ((posn (event-start pos))) | 445 | (let ((posn (event-start pos))) |
| 419 | (with-current-buffer (window-buffer (posn-window posn)) | 446 | (with-current-buffer (window-buffer (posn-window posn)) |
| 420 | (push-button (posn-point posn) t))) | 447 | (if (posn-area posn) |
| 448 | ;; mode-line or header-line event | ||
| 449 | (button-activate (car (posn-string posn)) t) | ||
| 450 | (push-button (posn-point posn)) t))) | ||
| 421 | ;; POS is just normal position | 451 | ;; POS is just normal position |
| 422 | (let ((button (button-at (or pos (point))))) | 452 | (let ((button (button-at (or pos (point))))) |
| 423 | (if (not button) | 453 | (when button |
| 424 | nil | ||
| 425 | (button-activate button use-mouse-action) | 454 | (button-activate button use-mouse-action) |
| 426 | t)))) | 455 | t)))) |
| 427 | 456 | ||