Mercurial > hg > xemacs-beta
comparison man/lispref/specifiers.texi @ 2141:6bca5896aab2
[xemacs-hg @ 2004-06-18 07:18:38 by stephent]
neon modeline example <874qp9jpx1.fsf@tleepslib.sk.tsukuba.ac.jp>
author | stephent |
---|---|
date | Fri, 18 Jun 2004 07:18:40 +0000 |
parents | 2ba4f06a264d |
children | c7d4a681eb2c |
comparison
equal
deleted
inserted
replaced
2140:9da6e6c569f7 | 2141:6bca5896aab2 |
---|---|
469 ignored. Specifically, instancing over a frame looks first for frame | 469 ignored. Specifically, instancing over a frame looks first for frame |
470 locales, then device locales, then the @code{global} locale. Instancing | 470 locales, then device locales, then the @code{global} locale. Instancing |
471 over a device domain looks only for device locales and the @code{global} | 471 over a device domain looks only for device locales and the @code{global} |
472 locale. | 472 locale. |
473 | 473 |
474 Note that specifiers are instanced on @emph{every} redisplay. (This is | |
475 the concept; of course the implementation keeps track of changes and | |
476 doesn't reinstance unchanged specifiers.) That means that changes in | |
477 specifiers controlling appearance are reflected immediately in the UI. | |
478 Also, since specifiers are instanced completely, removing a | |
479 specification can be just as effective as adding one. | |
480 | |
481 @emph{E.g.}, Giacomo Boffi wanted a modeline that indicates whether the | |
482 frame containing it is selected or not. The first proposed implementation | |
483 is natural in a world of ``local'' variables. The later implementations | |
484 apply the power of specifiers. | |
485 | |
486 (The copyright notice and permission statement below apply to the code in | |
487 example format, up to the ``@code{;;; end of neon-modeline.el}'' | |
488 comment.) | |
489 | |
490 @example | |
491 ;;; neon-modeline.el | |
492 | |
493 ;; Copyright (c) 2004 Stephen J. Turnbull <stephen@@xemacs.org> | |
494 | |
495 ;; Based on a suggestion by Giacomo Boffi | |
496 | |
497 ;; This code may be used and redistributed under the GNU GPL, v.2 or any | |
498 ;; later version as published by the FSF, or under the license used for | |
499 ;; XEmacs Texinfo manuals, at your option. | |
500 @end example | |
501 | |
502 A few customizations: | |
503 | |
504 @example | |
505 ;; Placate the specifier and Customize gods. | |
506 | |
507 (unless (valid-specifier-tag-p 'modeline-background) | |
508 (define-specifier-tag 'modeline-background)) | |
509 | |
510 (defgroup lisp-demos nil "Demos for Lisp programming techniques.") | |
511 | |
512 (defgroup neon-modeline nil "Neon modeline identifies selected frame." | |
513 :group 'lisp-demos) | |
514 | |
515 (defcustom neon-modeline-selected-background "LemonChiffon" | |
516 "Background color for modeline in selected frames." | |
517 :type 'color | |
518 :group 'neon-modeline) | |
519 | |
520 (defcustom neon-modeline-deselected-background "Wheat" | |
521 "Background color for modeline in unselected frames." | |
522 :type 'color | |
523 :group 'neon-modeline) | |
524 | |
525 @end example | |
526 | |
527 Our first try uses three functions, a setup and two hook functions. | |
528 Separate hooks are defined for entry into a frame and exit from it. | |
529 Since we're using hooks, it's a fairly natural approach: we operate on | |
530 the background on each event corresponding to an appearance change we | |
531 want to make. This doesn't depend on the specifier API, ``frame-local'' | |
532 variables would serve as well. | |
533 | |
534 @example | |
535 (defun select-modeline () | |
536 (set-face-background 'modeline neon-modeline-selected-background | |
537 (selected-frame))) | |
538 | |
539 (defun deselect-modeline () | |
540 (set-face-background 'modeline neon-modeline-deselected-background | |
541 (selected-frame))) | |
542 @end example | |
543 | |
544 Note that the initialization removes no specifications, and therefore is | |
545 not idempotent. Cruft will accumulate in the specifier if the | |
546 @samp{-setup} function is called repeatedly. This shouldn't cause a | |
547 performance problem; specifiers are quite efficient for their purpose. | |
548 But it's ugly, and wastes a small amount of space. | |
549 | |
550 @example | |
551 (defun neon-modeline-setup () | |
552 (interactive) | |
553 (set-face-background 'modeline neon-modeline-deselected-background) | |
554 ;; Add the distinguished background on pointer entry to the frame; | |
555 (add-hook 'select-frame-hook 'select-modeline) | |
556 ;; restore the ordinary background on pointer exit from the frame. | |
557 (add-hook 'deselect-frame-hook 'deselect-modeline) | |
558 @end example | |
559 | |
560 This approach causes a decided flicker on Boffi's platform, because the | |
561 two hook functions are executed in response to separate GUI events. | |
562 | |
563 The following code should be an improvement. First, the hook function. | |
564 | |
565 @example | |
566 (defun neon-modeline-reselect () | |
567 (set-face-background 'modeline neon-modeline-deselected-background | |
568 (selected-frame) '(modeline-background) | |
569 'remove-locale-type)) | |
570 @end example | |
571 | |
572 Only one event triggers the configuration change, which should reduce | |
573 flicker. Because this is implemented as a specifier, we can use the | |
574 specifier API to reset all frame-local specifications (the | |
575 @code{remove-locale-type} argument). This leaves the @code{global} | |
576 specification alone, but removes all existing frame-local | |
577 specifications. Then it adds the selected-frame background | |
578 specification for the newly selected frame. @emph{I.e.}, this | |
579 effectively implements a ``move specification from frame to frame'' | |
580 operation. | |
581 | |
582 Why does it give the desired result? By ensuring that only one frame | |
583 has the selected-frame modeline background. Frame-local specifications | |
584 have precedence over global ones, so when the modeline background is | |
585 instantiated in the selected frame, it matches the specification set up | |
586 for it and gets the right color. On the other hand, in any other frame, | |
587 it does not match the selected frame, so it falls through the | |
588 frame-local specifications and picks up the global specification. Again | |
589 we get the desired color, in this case for unselected frames. | |
590 | |
591 Here the @code{modeline-background} tag is simply good practice | |
592 (identifying an application's specifications allows it to avoid | |
593 interfering with other applications, and other well-behaved applications | |
594 and Customize should not munge specifications with our tag on them). | |
595 However, an alternative implementation of this functionality would be | |
596 | |
597 @example | |
598 (defun neon-modeline-reselect-2 () | |
599 (set-face-background 'modeline neon-modeline-deselected-background | |
600 (selected-frame) '(modeline-background) | |
601 'remove-tag-set-prepend)) | |
602 @end example | |
603 | |
604 @code{neon-modeline-reselect} may be a preferable implementation here, if we | |
605 really want only one frame to have a local specification. The | |
606 @code{neon-modeline-reselect-2} style would be useful if we had groups of | |
607 frames which have @emph{different} modeline backgrounds when deselected. | |
608 | |
609 Here's the initialization function, with different semantics from above. | |
610 Note that it is destructive, unless the user saves off the state of the | |
611 modeline face before invoking the function. This is only a problem if | |
612 you remove specifications and expect the older ones to persist. In this | |
613 example it should not be an issue. We use the customizations defined | |
614 above. | |
615 | |
616 @example | |
617 (defun neon-modeline-modified-setup () | |
618 (interactive) | |
619 (set-face-background 'modeline neon-modeline-selected-background | |
620 'global nil 'remove-all) | |
621 (add-hook 'select-frame-hook 'neon-modeline-reselect) | |
622 | |
623 ;;; end of neon-modeline.el | |
624 @end example | |
625 | |
626 Note the use of @code{'remove-all} to clear out stale specifications. | |
627 Thus it will be idempotent. | |
628 | |
629 | |
474 @node Specifier Types | 630 @node Specifier Types |
475 @section Specifier Types | 631 @section Specifier Types |
476 | 632 |
477 There are various different types of specifiers. The type of a | 633 There are various different types of specifiers. The type of a |
478 specifier controls what sorts of instantiators are valid, how an | 634 specifier controls what sorts of instantiators are valid, how an |