comparison lisp/gutter-items.el @ 406:b8cc9ab3f761 r21-2-33

Import from CVS: tag r21-2-33
author cvs
date Mon, 13 Aug 2007 11:17:09 +0200
parents 2f8bb876ab1d
children 501cfd01ee6d
comparison
equal deleted inserted replaced
405:0e08f63c74d2 406:b8cc9ab3f761
22 ;; along with Xmacs; see the file COPYING. If not, write to the 22 ;; along with Xmacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, 59 Temple Place - Suite 330, 23 ;; Free Software Foundation, 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA. 24 ;; Boston, MA 02111-1307, USA.
25 25
26 ;; Some of this is taken from the buffer-menu stuff in menubar-items.el 26 ;; Some of this is taken from the buffer-menu stuff in menubar-items.el
27 ;; and the custom specs in toolbar.el.
28
29 (defgroup gutter nil
30 "Input from the gutters."
31 :group 'environment)
32
33 ;; Although these customizations appear bogus, they are neccessary in
34 ;; order to be able to save options through the options menu.
35 (defcustom default-gutter-position
36 (default-gutter-position)
37 "The location of the default gutter. It can be 'top, 'bottom, 'left or
38 'right. This option should be customized through the options menu.
39 To set the gutter position explicitly use `set-default-gutter-position'"
40 :group 'gutter
41 :type '(choice (const :tag "top" top)
42 (const :tag "bottom" bottom)
43 (const :tag "left" left)
44 (const :tag "right" right))
45 :set #'(lambda (var val)
46 (set-default-gutter-position val)
47 (setq default-gutter-position val)))
48
49 ;;; Gutter helper functions
50
51 ;; called by Fset_default_gutter_position()
52 (defvar default-gutter-position-changed-hook nil
53 "Function or functions to be called when the gutter position is changed.
54 The value of this variable may be buffer-local.")
55
56 ;; called by set-gutter-element-visible-p
57 (defvar gutter-element-visibility-changed-hook nil
58 "Function or functions to be called when the visibility of an
59 element in the gutter changes. The value of this variable may be
60 buffer-local. The gutter element symbol is passed as an argument to
61 the hook, as is the visibility flag.")
62
63 (defun set-gutter-element (gutter-specifier prop val &optional locale tag-set)
64 "Set GUTTER-SPECIFIER gutter element PROP to VAL in optional LOCALE.
65 This is a convenience function for setting gutter elements."
66 (map-extents #'(lambda (extent arg)
67 (set-extent-property extent 'duplicable t)) val)
68 (modify-specifier-instances gutter-specifier #'plist-put (list prop val)
69 'force nil locale tag-set))
70
71 (defun remove-gutter-element (gutter-specifier prop &optional locale tag-set)
72 "Remove gutter element PROP from GUTTER-SPECIFIER in optional LOCALE.
73 This is a convenience function for removing gutter elements."
74 (modify-specifier-instances gutter-specifier #'plist-remprop (list prop)
75 'force nil locale tag-set))
76
77 (defun set-gutter-element-visible-p (gutter-visible-specifier-p
78 prop &optional visible-p
79 locale tag-set)
80 "Change the visibility of gutter elements.
81 Set the visibility of element PROP to VISIBLE-P for
82 GUTTER-SPECIFIER-VISIBLE-P in optional LOCALE.
83 This is a convenience function for hiding and showing gutter elements."
84 (modify-specifier-instances
85 gutter-visible-specifier-p #'(lambda (spec prop visible-p)
86 (if (consp spec)
87 (if visible-p
88 (if (memq prop spec) spec
89 (cons prop spec))
90 (delq prop spec))
91 (if visible-p (list prop))))
92 (list prop visible-p)
93 'force nil locale tag-set)
94 (run-hook-with-args 'gutter-element-visibility-changed-hook prop visible-p))
95
96 (defun gutter-element-visible-p (gutter-visible-specifier-p
97 prop &optional domain)
98 "Determine whether a gutter element is visible.
99 Given GUTTER-VISIBLE-SPECIFIER-P and gutter element PROP, return
100 non-nil if it is visible in optional DOMAIN."
101 (let ((spec (specifier-instance gutter-visible-specifier-p domain)))
102 (or (and (listp spec) (memq 'buffers-tab spec))
103 spec)))
104
105 (defun init-gutter ()
106 "Initialize the gutter."
107 ;; do nothing as yet.
108 )
109 27
110 ;;; The Buffers tab 28 ;;; The Buffers tab
111 29
112 (defgroup buffers-tab nil 30 (defgroup buffers-tab nil
113 "Customization of `Buffers' tab." 31 "Customization of `Buffers' tab."
123 "Whether the buffers tab is globally visible. 41 "Whether the buffers tab is globally visible.
124 This option should be set through the options menu." 42 This option should be set through the options menu."
125 :group 'buffers-tab 43 :group 'buffers-tab
126 :type 'boolean 44 :type 'boolean
127 :set #'(lambda (var val) 45 :set #'(lambda (var val)
128 (set-gutter-element-visible-p default-gutter-visible-p 'buffers-tab val) 46 (set-gutter-element-visible-p default-gutter-visible-p
47 'buffers-tab val)
129 (setq gutter-buffers-tab-visible-p val))) 48 (setq gutter-buffers-tab-visible-p val)))
130 49
131 (defvar gutter-buffers-tab-orientation 'top 50 (defvar gutter-buffers-tab-orientation 'top
132 "Where the buffers tab currently is. Do not set this.") 51 "Where the buffers tab currently is. Do not set this.")
133 52
229 (setq buffers-tab-max-buffer-line-length val))) 148 (setq buffers-tab-max-buffer-line-length val)))
230 149
231 (defun buffers-tab-switch-to-buffer (buffer) 150 (defun buffers-tab-switch-to-buffer (buffer)
232 "For use as a value for `buffers-tab-switch-to-buffer-function'." 151 "For use as a value for `buffers-tab-switch-to-buffer-function'."
233 (unless (eq (window-buffer) buffer) 152 (unless (eq (window-buffer) buffer)
153 ;; this used to add the norecord flag to both calls below.
154 ;; this is bogus because it is a pervasive assumption in XEmacs
155 ;; that the current buffer is at the front of the buffers list.
156 ;; for example, select an item and then do M-C-l
157 ;; (switch-to-other-buffer). Things get way confused.
158 ;;
159 ;; Andy, if you want to maintain the current look, you must
160 ;; *uncouple* the gutter order and buffers order.
234 (if (> (length (windows-of-buffer buffer)) 0) 161 (if (> (length (windows-of-buffer buffer)) 0)
235 (select-window (car (windows-of-buffer buffer)) t) 162 (select-window (car (windows-of-buffer buffer)))
236 (switch-to-buffer buffer t)))) 163 (switch-to-buffer buffer))))
237 164
238 (defun select-buffers-tab-buffers-by-mode (buf1 buf2) 165 (defun select-buffers-tab-buffers-by-mode (buf1 buf2)
239 "For use as a value of `buffers-tab-selection-function'. 166 "For use as a value of `buffers-tab-selection-function'.
240 This selects buffers by major mode `buffers-tab-grouping-regexp'." 167 This selects buffers by major mode `buffers-tab-grouping-regexp'."
241 (let ((mode1 (symbol-name (symbol-value-in-buffer 'major-mode buf1))) 168 (let ((mode1 (symbol-name (symbol-value-in-buffer 'major-mode buf1)))
343 buffers))) 270 buffers)))
344 271
345 (defun add-tab-to-gutter () 272 (defun add-tab-to-gutter ()
346 "Put a tab control in the gutter area to hold the most recent buffers." 273 "Put a tab control in the gutter area to hold the most recent buffers."
347 (setq gutter-buffers-tab-orientation (default-gutter-position)) 274 (setq gutter-buffers-tab-orientation (default-gutter-position))
348 (let ((gutter-string "\n")) 275 (let ((gutter-string (copy-sequence "\n")))
349 (unless gutter-buffers-tab-extent 276 (unless gutter-buffers-tab-extent
350 (setq gutter-buffers-tab-extent (make-extent 0 1 gutter-string))) 277 (setq gutter-buffers-tab-extent (make-extent 0 1 gutter-string)))
351 (set-extent-begin-glyph 278 (set-extent-begin-glyph
352 gutter-buffers-tab-extent 279 gutter-buffers-tab-extent
353 (setq gutter-buffers-tab 280 (setq gutter-buffers-tab
432 ;; A myriad of different update hooks all doing slightly different things 359 ;; A myriad of different update hooks all doing slightly different things
433 (add-hook 'kill-buffer-hook 'remove-buffer-from-gutter-tab) 360 (add-hook 'kill-buffer-hook 'remove-buffer-from-gutter-tab)
434 (add-hook 'create-frame-hook 361 (add-hook 'create-frame-hook
435 #'(lambda (frame) 362 #'(lambda (frame)
436 (when gutter-buffers-tab (update-tab-in-gutter frame t)))) 363 (when gutter-buffers-tab (update-tab-in-gutter frame t))))
437 (add-hook 'record-buffer-hook 'update-tab-in-gutter) 364 (add-hook 'buffer-list-changed-hook 'update-tab-in-gutter)
438 (add-hook 'default-gutter-position-changed 365 (add-hook 'default-gutter-position-changed-hook
439 #'(lambda (arg) 366 #'(lambda ()
440 (when gutter-buffers-tab (update-tab-in-gutter arg)))) 367 (when gutter-buffers-tab (update-tab-in-gutter))))
441 (add-hook 'gutter-element-visibility-changed-hook 368 (add-hook 'gutter-element-visibility-changed-hook
442 #'(lambda (prop visible-p) 369 #'(lambda (prop visible-p)
443 (when (and (eq prop 'buffers-tab) visible-p) 370 (when (and (eq prop 'buffers-tab) visible-p)
444 (update-tab-in-gutter)))) 371 (update-tab-in-gutter))))
445 372
453 are available on the current console. If non-NIL then progress display will be 380 are available on the current console. If non-NIL then progress display will be
454 textual and displayed in the echo area." 381 textual and displayed in the echo area."
455 :type 'boolean 382 :type 'boolean
456 :group 'gutter) 383 :group 'gutter)
457 384
385 (defvar progress-glyph-height 32
386 "Height of the gutter area for progress messages.")
387
388 (defvar progress-display-popup-period 0.5
389 "The time that the progress gauge should remain up after completion")
390
391 ;; private variables
392 (defvar progress-text-glyph
393 (make-glyph [string :data ""]))
394
395 (defvar progress-layout-glyph nil)
396 (defvar progress-gauge-glyph
397 (make-glyph
398 `[progress-gauge
399 :pixel-height (- progress-glyph-height 8)
400 :pixel-width 250
401 :descriptor "Progress"]))
402
403 (defun set-progress-display-style (style)
404 "Control the appearance of the progress gauge.
405 If STYLE is 'large, the default, then the progress-display text is
406 displayed above the gauge itself. If STYLE is 'small then the gauge
407 and text are arranged side-by-side."
408 (cond
409 ((eq style 'small)
410 (setq progress-glyph-height 24)
411 (setq progress-layout-glyph
412 (make-glyph
413 `[layout
414 :orientation horizontal
415 :items (,progress-gauge-glyph
416 [button
417 :pixel-height (- progress-glyph-height 8)
418 ;; 'quit is special and acts "asynchronously".
419 :descriptor "Stop" :callback 'quit]
420 ,progress-text-glyph)])))
421 (t
422 (setq progress-glyph-height 32)
423 (setq progress-layout-glyph
424 (make-glyph
425 `[layout
426 :orientation vertical :justify left
427 :items (,progress-text-glyph
428 [layout
429 :pixel-height (eval progress-glyph-height)
430 :orientation horizontal
431 :items (,progress-gauge-glyph
432 [button
433 :pixel-height (- progress-glyph-height 8)
434 :descriptor " Stop "
435 ;; 'quit is special and acts "asynchronously".
436 :callback 'quit])])])))))
437
438 (defcustom progress-display-style 'large
439 "*Control the appearance of the progress gauge.
440 If 'large, the default, then the progress-display text is displayed
441 above the gauge itself. If 'small then the gauge and text are arranged
442 side-by-side."
443 :group 'gutter
444 :type '(choice (const :tag "large" large)
445 (const :tag "small" small))
446 :set #'(lambda (var val)
447 (set-progress-display-style val)))
448
458 (defvar progress-stack nil 449 (defvar progress-stack nil
459 "An alist of label/string pairs representing active progress gauges. 450 "An alist of label/string pairs representing active progress gauges.
460 The first element in the list is currently displayed in the gutter area. 451 The first element in the list is currently displayed in the gutter area.
461 Do not modify this directly--use the `progress-display' or 452 Do not modify this directly--use the `progress-display' or
462 `display-progress-display'/`clear-progress-display' functions.") 453 `display-progress-display'/`clear-progress-display' functions.")
463 454
464 (defvar progress-glyph-height 32
465 "Height of the gutter area for progress messages.")
466
467 (defvar progress-display-stop-callback 'progress-display-quit-function
468 "Function to call to stop the progress operation.")
469
470 (defvar progress-display-popup-period 0.5
471 "The time that the progress gauge should remain up after completion")
472
473 (defun progress-display-quit-function ()
474 "Default function to call for the stop button in a progress gauge.
475 This just removes the progress gauge and calls quit."
476 (interactive)
477 (clear-progress-display)
478 (keyboard-quit))
479
480 ;; private variables
481 (defvar progress-gauge-glyph
482 (make-glyph
483 (vector 'progress-gauge
484 :pixel-height (- progress-glyph-height 8)
485 :pixel-width 250
486 :descriptor "Progress")))
487
488 (defvar progress-text-glyph
489 (make-glyph [string :data ""]))
490
491 (defvar progress-layout-glyph
492 (make-glyph
493 (vector
494 'layout :orientation 'vertical :justify 'left
495 :items (list
496 progress-text-glyph
497 (make-glyph
498 (vector
499 'layout :pixel-height progress-glyph-height
500 :orientation 'horizontal
501 :items (list
502 progress-gauge-glyph
503 (vector
504 'button :pixel-height (- progress-glyph-height 8)
505 :descriptor " Stop "
506 :callback '(funcall progress-display-stop-callback)))))))))
507
508 (defvar progress-abort-glyph 455 (defvar progress-abort-glyph
509 (make-glyph 456 (make-glyph
510 (vector 'layout :orientation 'vertical :justify 'left 457 `[layout :orientation vertical :justify left
511 :items (list progress-text-glyph 458 :items (,progress-text-glyph
512 (make-glyph 459 [layout
513 (vector 'layout 460 :pixel-height progress-glyph-height
514 :pixel-height progress-glyph-height 461 :orientation horizontal])]))
515 :orientation 'horizontal))))))
516
517 (defvar progress-extent-text "\n")
518 (defvar progress-extent nil)
519 462
520 (defun progress-displayed-p (&optional return-string frame) 463 (defun progress-displayed-p (&optional return-string frame)
521 "Return a non-nil value if a progress gauge is presently displayed in the 464 "Return a non-nil value if a progress gauge is presently displayed in the
522 gutter area. If optional argument RETURN-STRING is non-nil, 465 gutter area. If optional argument RETURN-STRING is non-nil,
523 return a string containing the message, otherwise just return t." 466 return a string containing the message, otherwise just return t."
549 (erase-buffer (get-buffer-create " *Gutter Area*"))) 492 (erase-buffer (get-buffer-create " *Gutter Area*")))
550 (if no-restore 493 (if no-restore
551 nil ; just preparing to put another msg up 494 nil ; just preparing to put another msg up
552 (if progress-stack 495 (if progress-stack
553 (let ((oldmsg (cdr (car progress-stack)))) 496 (let ((oldmsg (cdr (car progress-stack))))
554 (raw-append-progress-display oldmsg frame) 497 (raw-append-progress-display oldmsg nil frame)
555 oldmsg) 498 oldmsg)
556 ;; nothing to display so get rid of the gauge 499 ;; nothing to display so get rid of the gauge
557 (set-specifier bottom-gutter-border-width 0 frame) 500 (set-specifier bottom-gutter-border-width 0 frame)
558 (set-gutter-element-visible-p bottom-gutter-visible-p 501 (set-gutter-element-visible-p bottom-gutter-visible-p
559 'progress nil frame))))) 502 'progress nil frame)))))
560 503
561 (defun progress-display-clear-when-idle (&optional label) 504 (defun progress-display-clear-when-idle (&optional label)
562 (add-hook 'pre-idle-hook 505 (add-one-shot-hook 'pre-idle-hook
563 (defun progress-display-clear-pre-idle-hook () 506 `(lambda ()
564 (clear-progress-display label) 507 (clear-progress-display ',label))))
565 (remove-hook 'pre-idle-hook
566 'progress-display-clear-pre-idle-hook))))
567 508
568 (defun remove-progress-display (&optional label frame) 509 (defun remove-progress-display (&optional label frame)
569 ;; If label is nil, we want to remove all matching progress gauges. 510 ;; If label is nil, we want to remove all matching progress gauges.
570 (while (and progress-stack 511 (while (and progress-stack
571 (or (null label) ; null label means clear whole stack 512 (or (null label) ; null label means clear whole stack
577 (if (eq label (car msg)) 518 (if (eq label (car msg))
578 (progn 519 (progn
579 (setcdr s (cdr (cdr s)))) 520 (setcdr s (cdr (cdr s))))
580 (setq s (cdr s))))))) 521 (setq s (cdr s)))))))
581 522
523 (defun progress-display-dispatch-non-command-events ()
524 ;; don't allow errors to hose things
525 (condition-case t
526 ;; (sit-for 0) is too agressive and cause more display than we
527 ;; want.
528 (dispatch-non-command-events)
529 nil))
530
582 (defun append-progress-display (label message &optional value frame) 531 (defun append-progress-display (label message &optional value frame)
583 (or frame (setq frame (selected-frame))) 532 (or frame (setq frame (selected-frame)))
584 ;; Add a new entry to the message-stack, or modify an existing one 533 ;; Add a new entry to the message-stack, or modify an existing one
585 (let* ((top (car progress-stack)) 534 (let* ((top (car progress-stack))
586 (tmsg (cdr top))) 535 (tmsg (cdr top)))
587 (if (eq label (car top)) 536 (if (eq label (car top))
588 (progn 537 (progn
589 (setcdr top message) 538 (setcdr top message)
590 (if (equal tmsg message) 539 (if (equal tmsg message)
591 (set-image-instance-property 540 (set-image-instance-property
592 (glyph-image-instance progress-gauge-glyph) 541 (glyph-image-instance progress-gauge-glyph
593 :percent value) 542 (frame-selected-window frame))
543 :value value)
594 (raw-append-progress-display message value frame)) 544 (raw-append-progress-display message value frame))
595 (redisplay-gutter-area)) 545 (redisplay-gutter-area))
596 (push (cons label message) progress-stack) 546 (push (cons label message) progress-stack)
597 (raw-append-progress-display message value frame)) 547 (raw-append-progress-display message value frame))
598 (dispatch-non-command-events) 548 (progress-display-dispatch-non-command-events)
599 ;; either get command events or sit waiting for them 549 ;; either get command events or sit waiting for them
600 (if (not (eq value 100)) 550 (when (eq value 100)
601 (when (input-pending-p) 551 ; (sit-for progress-display-popup-period nil)
602 (dispatch-event (next-command-event)))
603 (sit-for progress-display-popup-period nil)
604 (clear-progress-display label)))) 552 (clear-progress-display label))))
605 553
606 (defun abort-progress-display (label message &optional frame) 554 (defun abort-progress-display (label message &optional frame)
607 (if (or (not (valid-image-instantiator-format-p 'progress-gauge frame)) 555 (if (or (not (valid-image-instantiator-format-p 'progress-gauge frame))
608 progress-display-use-echo-area) 556 progress-display-use-echo-area)
615 (if (eq label (car top)) 563 (if (eq label (car top))
616 (setcdr top message) 564 (setcdr top message)
617 (push (cons label message) progress-stack)) 565 (push (cons label message) progress-stack))
618 (unless (equal message "") 566 (unless (equal message "")
619 (insert-string message (get-buffer-create " *Gutter Area*")) 567 (insert-string message (get-buffer-create " *Gutter Area*"))
620 ;; Do what the device is able to cope with. 568 (let* ((gutter-string (copy-sequence "\n"))
621 ;; do some funky display here. 569 (ext (make-extent 0 1 gutter-string)))
622 (unless progress-extent 570 ;; do some funky display here.
623 (setq progress-extent (make-extent 0 1 progress-extent-text))) 571 (set-extent-begin-glyph ext progress-abort-glyph)
624 (let ((bglyph (extent-begin-glyph progress-extent)))
625 (set-extent-begin-glyph progress-extent progress-abort-glyph)
626 ;; fixup the gutter specifiers 572 ;; fixup the gutter specifiers
627 (set-gutter-element bottom-gutter 573 (set-gutter-element bottom-gutter 'progress gutter-string frame)
628 'progress progress-extent-text frame)
629 (set-specifier bottom-gutter-border-width 2 frame) 574 (set-specifier bottom-gutter-border-width 2 frame)
630 (set-image-instance-property 575 (set-image-instance-property
631 (glyph-image-instance progress-text-glyph) :data message) 576 (glyph-image-instance progress-text-glyph
577 (frame-selected-window frame)) :data message)
632 (set-specifier bottom-gutter-height 'autodetect frame) 578 (set-specifier bottom-gutter-height 'autodetect frame)
633 (set-gutter-element-visible-p bottom-gutter-visible-p 579 (set-gutter-element-visible-p bottom-gutter-visible-p
634 'progress t frame) 580 'progress t frame)
635 ;; we have to do this so redisplay is up-to-date and so 581 ;; we have to do this so redisplay is up-to-date and so
636 ;; redisplay-gutter-area performs optimally. 582 ;; redisplay-gutter-area performs optimally.
637 (redisplay-gutter-area) 583 (redisplay-gutter-area)
638 (sit-for progress-display-popup-period nil) 584 (sit-for progress-display-popup-period nil)
639 (clear-progress-display label) 585 (clear-progress-display label frame)
640 (set-extent-begin-glyph progress-extent bglyph) 586 (set-extent-begin-glyph ext progress-layout-glyph)
587 (set-gutter-element bottom-gutter 'progress gutter-string frame)
641 ))))) 588 )))))
642 589
643 (defun raw-append-progress-display (message &optional value frame) 590 (defun raw-append-progress-display (message &optional value frame)
644 (unless (equal message "") 591 (unless (equal message "")
645 (let ((inhibit-read-only t) 592 (let* ((inhibit-read-only t)
646 (zmacs-region-stays zmacs-region-stays) 593 (zmacs-region-stays zmacs-region-stays)
647 (val (or value 0))) 594 (val (or value 0))
595 (gutter-string (copy-sequence "\n"))
596 (ext (make-extent 0 1 gutter-string)))
648 (insert-string message (get-buffer-create " *Gutter Area*")) 597 (insert-string message (get-buffer-create " *Gutter Area*"))
649 ;; do some funky display here. 598 ;; do some funky display here.
650 (unless progress-extent 599 (set-extent-begin-glyph ext progress-layout-glyph)
651 (setq progress-extent (make-extent 0 1 progress-extent-text))
652 (set-extent-begin-glyph progress-extent progress-layout-glyph))
653 ;; fixup the gutter specifiers 600 ;; fixup the gutter specifiers
654 (set-gutter-element bottom-gutter 'progress progress-extent-text frame) 601 (set-gutter-element bottom-gutter 'progress gutter-string frame)
655 (set-specifier bottom-gutter-border-width 2 frame) 602 (set-specifier bottom-gutter-border-width 2 frame)
656 (set-image-instance-property 603 (set-image-instance-property
657 (glyph-image-instance progress-gauge-glyph) :percent val) 604 (glyph-image-instance progress-gauge-glyph
605 (frame-selected-window frame))
606 :value val)
658 (set-image-instance-property 607 (set-image-instance-property
659 (glyph-image-instance progress-text-glyph) :data message) 608 (glyph-image-instance progress-text-glyph (frame-selected-window frame))
609 :data message)
660 (if (and (eq (specifier-instance bottom-gutter-height frame) 610 (if (and (eq (specifier-instance bottom-gutter-height frame)
661 'autodetect) 611 'autodetect)
662 (gutter-element-visible-p bottom-gutter-visible-p 612 (gutter-element-visible-p bottom-gutter-visible-p
663 'progress frame)) 613 'progress frame))
614 ;; if the gauge is already visible then just draw the gutter
615 ;; checking for user events
664 (progn 616 (progn
665 ;; if the gauge is already visible then just draw the gutter
666 ;; checking for user events
667 (redisplay-gutter-area) 617 (redisplay-gutter-area)
668 (dispatch-non-command-events) 618 (progress-display-dispatch-non-command-events))
669 (when (input-pending-p)
670 (dispatch-event (next-command-event))))
671 ;; otherwise make the gutter visible and redraw the frame 619 ;; otherwise make the gutter visible and redraw the frame
672 (set-specifier bottom-gutter-height 'autodetect frame) 620 (set-specifier bottom-gutter-height 'autodetect frame)
673 (set-gutter-element-visible-p bottom-gutter-visible-p 621 (set-gutter-element-visible-p bottom-gutter-visible-p
674 'progress t frame) 622 'progress t frame)
675 ;; we have to do this so redisplay is up-to-date and so 623 ;; we have to do this so redisplay is up-to-date and so
676 ;; redisplay-gutter-area performs optimally. This may also 624 ;; redisplay-gutter-area performs optimally. This may also
677 ;; make sure the frame geometry looks ok. 625 ;; make sure the frame geometry looks ok.
678 (dispatch-non-command-events) 626 (progress-display-dispatch-non-command-events)
679 (redisplay-frame) 627 (redisplay-frame frame)
680 )))) 628 ))))
681 629
682 (defun display-progress-display (label message &optional value frame) 630 (defun display-progress-display (label message &optional value frame)
683 "Display a progress gauge and message in the bottom gutter area. 631 "Display a progress gauge and message in the bottom gutter area.
684 First argument LABEL is an identifier for this message. MESSAGE is 632 First argument LABEL is an identifier for this message. MESSAGE is
729 (clear-progress-display label nil)) 677 (clear-progress-display label nil))
730 (let ((str (apply 'format fmt args))) 678 (let ((str (apply 'format fmt args)))
731 (display-progress-display label str value) 679 (display-progress-display label str value)
732 str)))) 680 str))))
733 681
682 ;;
683 ;; Simple search dialog
684 ;;
685 (defvar search-dialog-direction t)
686 (defvar search-dialog-text
687 (make-glyph
688 [edit-field :width 15 :descriptor "" :active t :face default]))
689
690 (defun search-dialog-callback (parent image-instance event)
691 (save-selected-frame
692 (select-frame parent)
693 (funcall (if search-dialog-direction
694 'search-forward 'search-backward)
695 (image-instance-property
696 (glyph-image-instance search-dialog-text
697 (frame-selected-window
698 (event-channel event))) :text))
699 (isearch-highlight (match-beginning 0) (match-end 0))))
700
701 (defun make-search-dialog ()
702 "Popup a search dialog box."
703 (interactive)
704 (let* ((parent (selected-frame)))
705 (set-buffer-dedicated-frame
706 (get-buffer-create "Dialog")
707 (make-dialog-box
708 (make-glyph
709 `[layout
710 :orientation horizontal :justify left
711 :height 10 :width 40
712 :border [string :data "Search"]
713 :items
714 ([layout :orientation vertical :justify left
715 :items
716 ([string :data "Search for:"]
717 [button :descriptor "Match case"
718 :style toggle
719 :selected (not case-fold-search)
720 :callback (setq case-fold-search
721 (not case-fold-search))]
722 [button :descriptor "Forwards"
723 :style radio
724 :selected search-dialog-direction
725 :callback (setq search-dialog-direction t)]
726 [button :descriptor "Backwards"
727 :style radio
728 :selected (not search-dialog-direction)
729 :callback (setq search-dialog-direction nil)]
730 )]
731 [layout :orientation vertical :justify left
732 :items
733 (search-dialog-text
734 [button :width 10 :descriptor "Find Next"
735 :callback-ex
736 (lambda (image-instance event)
737 (search-dialog-callback ,parent
738 image-instance event))]
739 [button :width 10 :descriptor "Cancel"
740 :callback-ex
741 (lambda (image-instance event)
742 (isearch-dehighlight)
743 (delete-frame
744 (event-channel event)))])])])
745 '(height 10 width 40)))))
746
734 (provide 'gutter-items) 747 (provide 'gutter-items)
735 ;;; gutter-items.el ends here. 748 ;;; gutter-items.el ends here.