From d98845400c510f6f4da19eaaaa348e4e9a11dc6c Mon Sep 17 00:00:00 2001 From: cer <cer> Date: Fri, 19 Mar 1993 09:47:39 +0000 Subject: [PATCH] Bugs fixed ---------- clim2bug448 colin 13 [spr7638] Problem with layout pane option :min-width '(50 :chara clim2bug449 colin 13 [spr7639] Problem with layout pane option :min-width "MMMMMMMMM" clim2bug440 [spr7645] Layout problem clim2bug441 box-pane ignores :width,:height, :spacing etc etc. clim2bug447 Alternative space requirements only looked at when layout change clim2bug427 Accepting-values commands are echoed in the interactor clim2bug303 bogus characters in input buffer... clim2bug437 Command activated from menu bar in activity cannot access applicationo clim/accept-values.lisp Made :align-prompts work for own-window dialogs Accept-values-command-buttons calback function now use process-command-event. clim/activities.lisp Added frame-top-level-process method for activity-frame. Added destroy-activity function. clim/basic-translators.lisp Call-presentation-menu takes a :gesture argument that it passes to menu-choose clim/command-processor.lisp clim2bug303, added (values (complete-input)) to accept-method for command name clim/command.lisp clim2bug437 clim/db-stream.lisp Method for update-region added open-window-steam changed clim/default-frame.lisp :panes clim/drag-and-drop.lisp Drag and drop now supports aborting clim2bug340 clim/frames.lisp adjust-layout-requirements is called by generate-panes after method Allow neither :panes or :pane to be specified. Renamed iconify-frame to shrink-frame Added frame-top-level-process accessor clim/graph-formatting.lisp match-output-record method checks for duplicate-key and test. clim/incremental-redisplay.lisp Redraws because of erases now generate clipping-region clim/input-defs.lisp clim/input-protocol.lisp Modified handling of asynchronus aborts. clim/menus.lisp Menu-choose now uses frame-manager of associated-window clim/noting-progress.lisp supports frame-manager-specific progress notes clim/recording-protocol.lisp compute-output-record-offsets now behaves like convert-from-relative-to-absolute-coordinates. clim/standard-types.lisp Methods moved from textual-dialog-view to dialog-view-mixin clim/tracking-pointer.lisp Modified tracking-pointer to support timeout clause climtoys/ccc.lisp Added show-class-methods and generic functions commands climtoys/ib.lisp Made attempt to make dialog work. climtoys/sysdcl.lisp Moved files to test directory demo/browser.lisp pakage presentation-typep method works for allegro demo/peek-frame.lisp Added :gesture argument demo/plot.lisp Added more incremental redisplay support to plot-demo misc/compile-1.lisp Compile test-files misc/dev-load-1.lisp Load test files misc/train.lisp (setq *global-gc-behavior* nil) misc/undefinedsymbols Added XIconifyWindow postscript/postscript-port.lisp Added force-output to close text-output-record silica/db-box.lisp Added spacing argument silica/db-layout.lisp Removed junk and simplified silica/db-scroll.lisp Made update-region do nothing by default silica/db-table.lisp Removed fudges. silica/framem.lisp Fixed find-frame-manager silica/gadgets.lisp Fixed viewport to handle case when child is not a stream-pane silica/scroll-pane.lisp scroll-pane now inherits from client-overridability-mixin specs/*.tex swm changes test/postscript-tests.lisp Fixed stipple definition test/test.lisp Replace ncolumns,nlines by :width (30 :character) specification tk/convenience.lisp Added working dialog support tk-silica/ol-frames.lisp progress notification now sets the busy property of the frame tk-silica/ol-gadgets.lisp text-fields support :width (30 :character) tk-silica/xm-dialogs.lisp align-prompts in own-window dialog tk-silica/xm-frames.lisp Progress notification to use working dialog tk-silica/xm-gadgets.lisp text-fields support :width (30 :character) tk-silica/xt-frames.lisp Window (de)iconification and application-frame-marker tk-silica/xt-silica.lisp Fix coordinates for port-move-frame utils/lisp-utilities.lisp replaced |kdjfkdf djfkdjf| symbol utils/p --- clim/accept-values.lisp | 82 ++--- clim/command.lisp | 3 +- clim/db-stream.lisp | 37 +- clim/frames.lisp | 56 +-- clim/graph-formatting.lisp | 10 +- clim/incremental-redisplay.lisp | 88 ++++- clim/menus.lisp | 7 +- clim/recording-protocol.lisp | 20 +- demo/browser.lisp | 9 +- demo/plot.lisp | 75 ++-- misc/compile-1.lisp | 16 +- misc/dev-load-1.lisp | 8 +- misc/train.lisp | 3 +- postscript/postscript-port.lisp | 5 +- silica/db-box.lisp | 64 ++-- silica/db-layout.lisp | 315 ++--------------- silica/gadgets.lisp | 38 +- specs/acknowledgments.tex | 7 +- specs/bboxes.tex | 2 +- specs/bordered-output.tex | 6 +- specs/changes.tex | 65 ++-- specs/clim-sys.tex | 59 +++- specs/clim.tex | 18 +- specs/colors.tex | 126 ++++--- specs/commands.tex | 90 +++-- specs/conventions.tex | 21 +- specs/designs.tex | 30 +- specs/dialogs.tex | 65 ++-- specs/drawing-options.tex | 12 +- specs/encapsulating-streams.tex | 5 +- specs/extended-input.tex | 138 ++++---- specs/extended-output.tex | 114 +++--- specs/frames.tex | 340 ++++++++++++------ specs/gadgets.tex | 512 +++++++++++++++++++-------- specs/glossary.tex | 8 +- specs/graph-formatting.tex | 31 +- specs/graphics.tex | 578 ++++++++++++++---------------- specs/input-editing.tex | 85 +++-- specs/menus.tex | 70 +++- specs/output-recording.tex | 185 ++++++---- specs/overview.tex | 21 -- specs/panes.tex | 499 ++++++++++++++++++-------- specs/presentation-types.tex | 149 +++++--- specs/psfig+.tex | 2 +- specs/redisplay.tex | 59 ++-- specs/regions.tex | 70 ++-- specs/silica.tex | 607 +++++++++++++++++++++++--------- specs/spec-macros.tex | 13 +- specs/table-formatting.tex | 45 ++- specs/text-formatting.tex | 15 +- specs/text-styles.tex | 33 +- specs/transforms.tex | 21 +- test/postscript-tests.lisp | 4 +- test/test-clim.lisp | 432 +++++++++++++++++++++++ test/test-driver.lisp | 497 ++++++++++++++++++++++++++ test/test.lisp | 51 ++- tk-silica/ol-frames.lisp | 22 +- tk-silica/ol-gadgets.lisp | 98 +++++- tk-silica/xm-frames.lisp | 63 +++- tk-silica/xm-gadgets.lisp | 142 +++++++- tk-silica/xt-frames.lisp | 13 +- tk-silica/xt-graphics.lisp | 6 +- tk-silica/xt-silica.lisp | 3 +- utils/lisp-utilities.lisp | 4 +- utils/packages.lisp | 3 +- utils/region-arithmetic.lisp | 46 ++- xlib/xlib-funs.lisp | 8 +- 67 files changed, 4266 insertions(+), 2063 deletions(-) create mode 100644 test/test-clim.lisp create mode 100644 test/test-driver.lisp diff --git a/clim/accept-values.lisp b/clim/accept-values.lisp index 430e9308..1ff40a43 100644 --- a/clim/accept-values.lisp +++ b/clim/accept-values.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: accept-values.lisp,v 1.54 93/03/04 18:59:38 colin Exp $ +;; $fiHeader: accept-values.lisp,v 1.55 93/03/18 14:36:07 colin Exp $ (in-package :clim-internals) @@ -267,13 +267,15 @@ ;;--- These frames should be resourced (define-application-frame accept-values-own-window (accept-values) ((help-window :initform nil) - (scroll-bars :initform nil :initarg :scroll-bars)) + (scroll-bars :initform nil :initarg :scroll-bars) + (align-prompts :initform nil :initarg :align-prompts)) (:pane - (with-slots (stream own-window exit-button-stream scroll-bars) *application-frame* + (with-slots (stream own-window exit-button-stream scroll-bars align-prompts) *application-frame* (vertically () (outlining () (progn (setq stream (make-instance 'accept-values-stream + :align-prompts align-prompts :stream (setq own-window (make-pane 'clim-stream-pane :initial-cursor-visibility :off @@ -321,6 +323,7 @@ ((t :right) :right) ((:left) :left) ((nil) nil))) + (let ((frame-manager (frame-manager stream)) (*current-accept-values-tick* *accept-values-tick*) (the-own-window nil)) @@ -345,7 +348,8 @@ :resynchronize-every-pass resynchronize-every-pass :check-overlapping check-overlapping :resize-frame resize-frame - :scroll-bars scroll-bars))) + :scroll-bars scroll-bars + :align-prompts align-prompts))) (when command-table (setf (frame-command-table frame) command-table)) (unwind-protect @@ -450,7 +454,8 @@ ;; means we should run the continuation an extra time to see ;; that all visible stuff is up to date. That's all! (with-output-recording-options (stream :draw nil) - (redisplay avv stream :check-overlapping check-overlapping))) + (redisplay avv stream :check-overlapping + check-overlapping))) (setf (slot-value avv-record 'resynchronize) nil) (when exit-button-record (redisplay exit-button-record exit-button-stream)) @@ -1330,41 +1335,38 @@ ;; This is how we associate an output-record with the button (defmethod invoke-accept-values-command-button - (stream continuation (view gadget-dialog-view) prompt - &key (documentation (if (stringp prompt) - prompt - (with-output-to-string (stream) - (funcall prompt stream)))) - (query-identifier (list ':button documentation)) - (cache-value t) (cache-test #'eql) - resynchronize) + (stream continuation (view gadget-dialog-view) prompt + &key (documentation (if (stringp prompt) + prompt + (with-output-to-string (stream) + (funcall prompt stream)))) + (query-identifier (list ':button documentation)) + (cache-value t) (cache-test #'eql) + resynchronize) (declare (dynamic-extent prompt)) (updating-output (stream :unique-id query-identifier :id-test #'equal :cache-value cache-value :cache-test cache-test) - (with-output-as-gadget (stream) - (let ((record (stream-current-output-record (encapsulating-stream-stream stream))) - (client (make-instance 'accept-values-command-button - :continuation continuation - :documentation documentation - :resynchronize resynchronize))) - (make-pane 'push-button - :label (if (stringp prompt) - prompt - ;;--- Perhaps we should create a pixmap - (with-output-to-string (stream) - (funcall prompt stream))) - :id record :client client - :activate-callback - #'(lambda (button) - (when (accept-values-query-valid-p nil record) ;---can't be right - (throw-highlighted-presentation - (make-instance 'standard-presentation - :object `(com-avv-command-button ,client ,record) - :type 'command) - *input-context* - ;;--- It would be nice if we had the real event... - (allocate-event 'pointer-button-press-event - :sheet (sheet-parent button) - :x 0 :y 0 - :modifier-state 0 - :button +pointer-left-button+))))))))) + (with-output-as-gadget (stream) + (let ((record (stream-current-output-record (encapsulating-stream-stream stream))) + (client (make-instance 'accept-values-command-button + :continuation continuation + :documentation documentation + :resynchronize resynchronize))) + (make-pane 'push-button + :label (if (stringp prompt) + prompt + ;;--- Perhaps we should create a pixmap + (with-output-to-string (stream) + (funcall prompt stream))) + :id record :client client + :activate-callback + #'(lambda (button) + (when (accept-values-query-valid-p nil record) ;---can't be right + (let ((sheet (sheet-parent button))) + (process-command-event + sheet + (allocate-event 'presentation-event + :sheet sheet + :presentation-type 'command + :value `(com-avv-command-button ,client ,record) + :frame *application-frame*)))))))))) diff --git a/clim/command.lisp b/clim/command.lisp index 5609b389..63201cb0 100644 --- a/clim/command.lisp +++ b/clim/command.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: command.lisp,v 1.19 92/12/14 15:02:00 cer Exp $ +;; $fiHeader: command.lisp,v 1.20 93/02/08 15:56:39 cer Exp $ (in-package :clim-internals) @@ -14,6 +14,7 @@ (defvar *unsupplied-argument-marker* '#:unsupplied-argument) (defvar *numeric-argument-marker* '#:numeric-argument) +(defvar *application-frame-marker* '#:application-frame) (defun unsupplied-argument-p (arg) (eq arg *unsupplied-argument-marker*)) diff --git a/clim/db-stream.lisp b/clim/db-stream.lisp index 42c282e2..2ae757eb 100644 --- a/clim/db-stream.lisp +++ b/clim/db-stream.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: db-stream.lisp,v 1.45 93/02/08 15:56:42 cer Exp $ +;; $fiHeader: db-stream.lisp,v 1.46 93/03/18 14:36:24 colin Exp $ (in-package :clim-internals) @@ -51,6 +51,22 @@ (setf (stream-default-text-margin pane) (bounding-rectangle-width (sheet-region viewport)))) +(defmethod update-region ((sheet clim-stream-sheet) nleft ntop nright nbottom &key no-repaint) + (declare (ignore no-repaint)) + (with-bounding-rectangle* (left top right bottom) sheet + (when (or (< nleft left) + (< ntop top) + (> nright right) + (> nbottom bottom)) + ;; It should be safe to modify the sheet's region + (let ((region (sheet-region sheet))) + (setf (slot-value region 'left) (min nleft left) + (slot-value region 'top) (min ntop top) + (slot-value region 'right) (max nright right) + (slot-value region 'bottom) (max nbottom bottom)) + (note-sheet-region-changed sheet))))) + + (defmethod invoke-with-drawing-options ((sheet clim-stream-sheet) continuation &rest options &key ink &allow-other-keys) @@ -640,7 +656,7 @@ ;;; This is too useful to simply omit -(defun open-window-stream (&key port left top right bottom width height +(defun open-window-stream (&key left top right bottom width height (foreground +black+) (background +white+) text-style default-text-style (vertical-spacing 2) @@ -651,6 +667,7 @@ text-margin default-text-margin save-under input-buffer (scroll-bars :vertical) borders label) + (declare (ignore label borders scroll-bars input-buffer)) (when (or width height) (assert (and (null right) (null bottom)))) (when (null left) (setq left 0)) @@ -661,21 +678,15 @@ height 100) (setq width (- right left) height (- bottom top)))) - (when (null port) - (setq port (find-port))) - (when (null text-style) - (setq text-style (port-default-text-style port))) - (when (null default-text-style) - (setq default-text-style (port-default-text-style port))) - (let ((stream + (let* ((stream (let ((frame (make-application-frame 'menu-frame - :parent (or port (find-port)) :save-under save-under))) - (slot-value frame 'menu)))) + (slot-value frame 'menu))) + (port (port stream))) (setf (medium-foreground stream) foreground (medium-background stream) background - (medium-default-text-style stream) default-text-style - (medium-text-style stream) text-style + (medium-default-text-style stream) (or default-text-style (port-default-text-style port)) + (medium-text-style stream) (or text-style (port-default-text-style port)) (stream-vertical-spacing stream) vertical-spacing (stream-end-of-line-action stream) end-of-line-action (stream-end-of-page-action stream) end-of-page-action diff --git a/clim/frames.lisp b/clim/frames.lisp index 285e52d0..a1c8d69a 100644 --- a/clim/frames.lisp +++ b/clim/frames.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: frames.lisp,v 1.59 93/02/08 15:56:45 cer Exp $ +;; $fiHeader: frames.lisp,v 1.60 93/03/18 14:36:38 colin Exp $ (in-package :clim-internals) @@ -53,7 +53,7 @@ (resizable :initarg :resize-frame :reader frame-resizable) (layout :initarg :layouts :reader frame-layouts) - (top-level-process :initform nil) + (top-level-process :initform nil :reader frame-top-level-process) (command-queue :initform (make-locking-queue) :reader frame-command-queue) (input-buffer :initform nil :initarg :input-buffer :reader frame-input-buffer) (pane-to-avv-stream-table :initform nil :accessor frame-pane-to-avv-stream-table)) @@ -103,6 +103,10 @@ (frame standard-application-frame)) (setf (frame-panes frame) nil)) +(defmethod generate-panes :after ((framem standard-frame-manager) + (frame standard-application-frame)) + (adjust-layout-requirements frame (frame-current-layout frame))) + (eval-when (compile load eval) (defun define-application-frame-1 (name state-variables pane-descriptions &key top-level layouts @@ -156,9 +160,9 @@ (check-type top-level list) (check-type disabled-commands list) (when (and pane panes) - (error "The ~S and ~S options cannot be used together" :pane :panes)) - (when (and layouts (null panes)) - (error "You must use ~S with ~S" :panes :layouts)) + (error "You must use either ~S or ~S options" :pane :panes)) + (when (and panes (null layouts)) + (error "You must use ~S and ~S together" :panes :layouts)) (when (null superclasses) (setq superclasses '(standard-application-frame))) (when (eq command-definer 't) @@ -181,11 +185,13 @@ `(list ,@(mapcar #'(lambda (layout) (destructuring-bind (name panes &rest sizes) layout + (check-type sizes list) (if sizes `(list ',name ',panes ,@(mapcar #'(lambda (pane-and-size) - `(list ',(car pane-and-size) - ,@(cdr pane-and-size))) + (destructuring-bind (pane &rest sizes) pane-and-size + `(list ',pane + ,@sizes))) sizes)) `',layout))) layouts)))) @@ -537,20 +543,23 @@ (sheet-adopt-child (frame-top-level-sheet frame) (frame-panes frame)) (multiple-value-call #'layout-frame frame (bounding-rectangle-size (frame-top-level-sheet frame))) + ;;--- Don't throw, just recompute stream bindings in a principled way + (handler-case + (throw 'layout-changed nil) + (error () nil)))) + +(defun adjust-layout-requirements (frame layout) + (when (frame-panes frame) (let ((layout-space-requirements - (cddr (assoc layout (frame-layouts frame))))) + (cddr (assoc layout (frame-layouts frame))))) (changing-space-requirements (:layout nil) (flet ((adjust-layout (sheet) - (change-space-requirements-to-default sheet) (let ((x (and (panep sheet) (assoc (pane-name sheet) layout-space-requirements)))) - (when x (apply #'change-space-requirements sheet (cdr x)))))) + (if x (apply #'change-space-requirements sheet (cdr x)) + (change-space-requirements-to-default sheet))))) (declare (dynamic-extent #'adjust-layout)) - (map-over-sheets #'adjust-layout (frame-top-level-sheet frame))))) - ;;--- Don't throw, just recompute stream bindings in a principled way - (handler-case - (throw 'layout-changed nil) - (error () nil)))) + (map-over-sheets #'adjust-layout (frame-panes frame))))))) (defmethod frame-all-layouts ((frame standard-application-frame)) (mapcar #'first (frame-layouts frame))) @@ -682,7 +691,7 @@ (:shrunk (note-frame-deiconified (frame-manager frame) frame))))) -(defmethod iconify-frame ((frame standard-application-frame)) +(defmethod shrink-frame ((frame standard-application-frame)) (note-frame-iconified (frame-manager frame) frame)) (defmethod destroy-frame ((frame standard-application-frame)) @@ -1145,15 +1154,20 @@ ) (read-command (frame-command-table frame) :stream stream)) -#+++ignore ;--- install this? + (defmethod execute-frame-command :around ((frame standard-application-frame) command) - (let ((top-level-process (slot-value frame 'top-level-process))) - (if (and top-level-process - (eq top-level-process (current-process))) + (let ((top-level-process (slot-value frame 'top-level-process)) + activity) + (if (or (and top-level-process + (eq top-level-process (current-process))) + (and (typep frame 'activity-frame) + (setq activity (frame-activity frame)) + (eq (slot-value activity 'top-level-process) (current-process)))) ;; If we're in the process for the frame, just execute the command + ;; Or the process for the frames activity (call-next-method) ;; Otherwise arrange to run the command in the frame's process - (execute-command-in-frame frame command)))) + (execute-command-in-frame frame command :queuep t)))) (defmethod execute-frame-command ((frame standard-application-frame) command) (apply (command-name command) (command-arguments command))) diff --git a/clim/graph-formatting.lisp b/clim/graph-formatting.lisp index 540fc0da..deb49d31 100644 --- a/clim/graph-formatting.lisp +++ b/clim/graph-formatting.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: graph-formatting.lisp,v 1.23 93/01/18 13:54:36 cer Exp $ +;; $fiHeader: graph-formatting.lisp,v 1.24 93/01/21 14:57:59 cer Exp $ (in-package :clim-internals) @@ -152,8 +152,10 @@ &key object duplicate-key duplicate-test &allow-other-keys) (when (or (and (null object) (null (graph-node-object record))) - (funcall duplicate-test (funcall duplicate-key object) - (funcall duplicate-key (graph-node-object record)))) + (and duplicate-key + duplicate-test + (funcall duplicate-test (funcall duplicate-key object) + (funcall duplicate-key (graph-node-object record))))) (setf (graph-node-parents record) nil (graph-node-children record) nil) t)) @@ -677,7 +679,7 @@ circular graphs without accounting for this case. (dolist (root root-nodes) (traverse root 0))))) ->(defmethod add-graph-filler-output-records ((graph directed-graph-output-record) stream) +(defmethod add-graph-filler-output-records ((graph directed-graph-output-record) stream) (with-slots (root-nodes) graph (labels ((traverse (node) (let* ((gen (graph-node-generation node)) diff --git a/clim/incremental-redisplay.lisp b/clim/incremental-redisplay.lisp index 8ce9bb5c..e023b6a3 100644 --- a/clim/incremental-redisplay.lisp +++ b/clim/incremental-redisplay.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: incremental-redisplay.lisp,v 1.14 92/10/02 15:19:34 cer Exp $ +;; $fiHeader: incremental-redisplay.lisp,v 1.15 92/12/16 16:46:32 cer Exp $ (in-package :clim-internals) @@ -64,7 +64,7 @@ ;; Don't cons a rectangle to hold the old bounding-rect until we need one (if (null old-bounding-rectangle) (setf old-bounding-rectangle (bounding-rectangle record)) ;cons a new rectangle - (bounding-rectangle record old-bounding-rectangle)) + (bounding-rectangle record old-bounding-rectangle)) (output-record-set-old-start-cursor-position record start-x start-y) (setf contents-ok (not (null old-is-ok))) (unless old-is-ok @@ -528,17 +528,22 @@ (declare (values erases moves draws erase-overlapping move-overlapping)) (let ((new-draws nil)) (labels ((augment-draws (record x-offset y-offset old-x-offset old-y-offset) - (when (and (displayed-output-record-p record) - (not (children-never-overlap-p (output-record-parent record))) - (not (member record draws :key #'first)) - (not (member record erases :key #'first)) - (dolist (erase erases nil) - (when (region-intersects-region-p record (first erase)) - (return t)))) - (push (list record - (bounding-rectangle-shift-position - record x-offset y-offset)) - new-draws)) + (let ((erases-that-overlap nil)) + (when (and (displayed-output-record-p record) + (not (children-never-overlap-p (output-record-parent record))) + (not (member record draws :key #'first)) + (not (member record erases :key #'first)) + (do ((erases erases (cdr erases))) + ((null erases) nil) + (when (region-intersects-region-p record (first (first erases))) + (setq erases-that-overlap erases) + (return t)))) + (push (list record + (bounding-rectangle-shift-position record x-offset y-offset) + (compute-region-that-overlaps-with-erases + record x-offset y-offset + erases-that-overlap)) + new-draws))) (when (output-record-p record) (multiple-value-bind (start-x start-y) (output-record-start-cursor-position record) @@ -558,6 +563,53 @@ (values erases moves (nconc (nreverse new-draws) draws) erase-overlapping move-overlapping))) +#+ignore +(defun compute-region-that-overlaps-with-erases (record x-offset y-offset erases-that-overlap) + +everywhere+) + +(defun compute-region-that-overlaps-with-erases (record x-offset y-offset erases-that-overlap) + (with-bounding-rectangle* (left top right bottom) record + (translate-coordinates x-offset y-offset left top right bottom) + + (with-bounding-rectangle* (eleft etop eright ebottom) (caar erases-that-overlap) + (multiple-value-bind (xoff1 yoff1) (compute-output-record-offsets (caar erases-that-overlap)) + (translate-coordinates xoff1 yoff1 eleft etop eright ebottom) + (let (union) + (multiple-value-bind (intersectsp rleft rtop rright rbottom) + (ltrb-overlaps-ltrb-p left top right bottom eleft etop eright ebottom) + (assert intersectsp) + + (dolist (erase (cdr erases-that-overlap)) + + (with-bounding-rectangle* (eleft etop eright ebottom) (car erase) + (multiple-value-bind (xoff1 yoff1) (compute-output-record-offsets (car erase)) + (translate-coordinates xoff1 yoff1 eleft etop eright ebottom) + (multiple-value-setq (intersectsp eleft etop eright ebottom) + (ltrb-overlaps-ltrb-p left top right bottom eleft etop eright ebottom)) + (when intersectsp + (cond (union + (setq union + (region-union + union (make-bounding-rectangle eleft etop eright ebottom)))) + ((ltrb-contains-ltrb-p + eleft etop eright ebottom + rleft rtop rright rbottom) + (setf rleft eleft rtop etop rright eright rbottom ebottom)) + + ((ltrb-contains-ltrb-p + rleft rtop rright rbottom + eleft etop eright ebottom)) + + (t + (let ((a (make-bounding-rectangle rleft + rtop rright rbottom)) + (b (make-bounding-rectangle + eleft etop eright ebottom))) + (setq union (region-union a b))))))))) + + (or union (make-bounding-rectangle rleft rtop rright rbottom)))))))) + + ;; This has nothing to do with output-recording. You can call this on any ;; stream that can set the cursor position, replace existing output, and ;; can do bitblt's, although I suppose we could make the last part generic. @@ -585,7 +637,7 @@ (with-bounding-rectangle* (left top right bottom) rectangle (translate-coordinates xoff yoff left top right bottom) (draw-rectangle* stream left top right bottom - :ink +background-ink+ :filled t))) + :ink +background-ink+ :filled t))) (replay-record (record stream region) ;; REGION is the bounding rectangle (multiple-value-bind (x y) (bounding-rectangle-position record) @@ -604,8 +656,12 @@ (replay-record record stream region))) (dolist (draw draws) (let ((record (first draw)) - (region (second draw))) - (replay-record record stream region))) + (region (second draw)) + (clipping (third draw))) + (if clipping + (with-drawing-options (stream :clipping-region clipping) + (replay-record record stream region)) + (replay-record record stream region)))) (dolist (erase erase-overlapping) (erase-rectangle stream erase)) (dolist (move move-overlapping) diff --git a/clim/menus.lisp b/clim/menus.lisp index d9b09366..1765df81 100644 --- a/clim/menus.lisp +++ b/clim/menus.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: menus.lisp,v 1.39 93/02/08 15:56:52 cer Exp $ +;; $fiHeader: menus.lisp,v 1.40 93/03/18 14:36:48 colin Exp $ (in-package :clim-internals) @@ -246,8 +246,7 @@ (cell-align-x ':left) (cell-align-y ':top) pointer-documentation menu-type gesture) (declare (values value chosen-item gesture)) - (declare (ignore associated-window - text-style default-item + (declare (ignore text-style default-item label scroll-bars printer presentation-type cache unique-id id-test cache-value cache-test max-width max-height n-rows n-columns @@ -255,7 +254,7 @@ pointer-documentation menu-type gesture)) (declare (dynamic-extent keys)) (unless (zerop (length items)) - (apply #'frame-manager-menu-choose (frame-manager *application-frame*) items keys))) + (apply #'frame-manager-menu-choose (frame-manager associated-window) items keys))) ;; Specific ports can put :AROUND methods on this in order to use their own ;; kinds of menus. diff --git a/clim/recording-protocol.lisp b/clim/recording-protocol.lisp index 0fb20b75..9fe5ca00 100644 --- a/clim/recording-protocol.lisp +++ b/clim/recording-protocol.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-INTERNALS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: recording-protocol.lisp,v 1.28 92/12/03 10:27:46 cer Exp $ +;; $fiHeader: recording-protocol.lisp,v 1.29 92/12/16 16:46:52 cer Exp $ (in-package :clim-internals) @@ -195,6 +195,8 @@ (declare (ignore x y)) t) + +#+ignore (defun compute-output-record-offsets (record) (let ((parent (output-record-parent record))) (if (null parent) @@ -206,6 +208,22 @@ (declare (type coordinate our-x our-y)) (values (+ our-x x) (+ our-y y))))))) + +(defun compute-output-record-offsets (record) + (compute-output-record-offsets-1 (output-record-parent record))) + + +(defun compute-output-record-offsets-1 (record) + (if (null record) + (values 0 0) + (let ((parent (output-record-parent record))) + (multiple-value-bind (x y) + (compute-output-record-offsets-1 parent) + (declare (type coordinate x y)) + (multiple-value-bind (our-x our-y) (output-record-position record) + (declare (type coordinate our-x our-y)) + (values (+ our-x x) (+ our-y y))))))) + (defmethod region-equal ((record1 output-record-element-mixin) (record2 output-record-element-mixin)) (with-bounding-rectangle* (left1 top1 right1 bottom1) record1 diff --git a/demo/browser.lisp b/demo/browser.lisp index 0fc2b7cc..c48be0a6 100644 --- a/demo/browser.lisp +++ b/demo/browser.lisp @@ -3,7 +3,7 @@ ;;; Simple extensible browser ;;; Scott McKay -;; $fiHeader: browser.lisp,v 1.17 92/12/03 10:28:28 cer Exp $ +;; $fiHeader: browser.lisp,v 1.18 93/01/18 13:55:04 cer Exp $ (in-package :clim-browser) @@ -477,7 +477,10 @@ :inherit-from t :history t) -#+genera +(define-presentation-method presentation-typep (object (type package)) + (typep object 'common-lisp:package)) + +#+(or allegro genera) (define-presentation-method accept ((type package) stream (view textual-view) &key) (completing-from-suggestions (stream :partial-completers '(#\-)) (map nil #'(lambda (package) @@ -510,7 +513,7 @@ (defun package-browser-make-root (object) (typecase object - (package + (common-lisp:package (make-package-call-node object)) ((or string symbol) (let ((package (find-package object))) diff --git a/demo/plot.lisp b/demo/plot.lisp index 096cb5eb..3df5db3e 100644 --- a/demo/plot.lisp +++ b/demo/plot.lisp @@ -21,7 +21,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: plot.lisp,v 1.20 92/12/03 10:28:48 cer Exp $ +;; $fiHeader: plot.lisp,v 1.21 92/12/14 15:02:44 cer Exp $ (in-package :clim-demo) @@ -110,6 +110,7 @@ (setq nx x ny y) (return (make-rectangle* ox oy nx ny))))))))) + ;; Define a presentation translator from a graph-plot to a graph-region. ;; In that way we trivially write a command that will zoom into a ;; particular region of the graph. @@ -156,8 +157,8 @@ (etypecase points ((array t (* *)) nil) (list - (setq points (make-array (list (length points) (length (car points))) - :initial-contents (nreverse points))))) + (setq points (make-array (list (length points) (length (car points))) + :initial-contents (nreverse points))))) (multiple-value-setq (width height) (default-width-and-height stream type points width height)) @@ -166,31 +167,33 @@ (default-graph-axis type points x-min y-min x-max y-max y-labelling)) (let ((transform - (and (not (eq type :pie)) - (let ((scaling-transform - (make-scaling-transformation - (/ width (- x-max x-min)) - (/ height (- y-max y-min))))) - (multiple-value-bind (ox oy) - (transform-position scaling-transform x-min y-min) - (compose-transformations - (make-translation-transformation (- ox) (- oy)) - scaling-transform)))))) + (and (not (eq type :pie)) + (let ((scaling-transform + (make-scaling-transformation + (/ width (- x-max x-min)) + (/ height (- y-max y-min))))) + (multiple-value-bind (ox oy) + (transform-position scaling-transform x-min y-min) + (compose-transformations + (make-translation-transformation (- ox) (- oy)) + scaling-transform)))))) (with-output-as-presentation (stream nil 'graph-plot :single-box :position) - (formatting-item-list (stream :n-columns 2) - (formatting-cell (stream) - (with-room-for-graphics (stream) - (draw-axis stream type - width height - x-min y-min x-max y-max - x-labels y-labels - points transform - y-labelling) - (draw-data stream type - width height x-min y-min x-max - y-max points transform))) + (formatting-item-list (stream :n-columns 2) + (updating-output (stream :unique-id :data-and-axis) + (formatting-cell (stream) + (with-room-for-graphics (stream) + (draw-axis stream type + width height + x-min y-min x-max y-max + x-labels y-labels + points transform + y-labelling) + (draw-data stream type + width height x-min y-min x-max + y-max points transform)))) + (updating-output (stream :unique-id :caption) (formatting-cell (stream) - (draw-caption stream type y-labels))))))) + (draw-caption stream type y-labels)))))))) (defun draw-caption (stream type y-labels) (updating-output (stream :unique-id 'captions @@ -277,6 +280,7 @@ (dotimes (j (1- columns)) (updating-output (stream :unique-id `(pie ,j) :id-test #'equal + :cache-test #'equal :cache-value (let ((r nil)) (dotimes (i rows (nreverse r)) (push (aref points i (1+ j)) r)))) @@ -299,6 +303,7 @@ (dotimes (i n-lines) (updating-output (stream :unique-id `(bar ,i) :id-test #'equal + :cache-test #'equal :cache-value (list x-min y-min x-max y-max width height (let ((r nil)) (dotimes (j rows @@ -327,6 +332,7 @@ (dotimes (i n-lines) (updating-output (stream :unique-id `(plot-line ,i) :id-test #'equal + :cache-test #'equal :cache-value (list x-min y-min x-max y-max width height (let ((r nil)) (dotimes (j rows @@ -700,15 +706,14 @@ (frame-exit *application-frame*)) (defmethod display-graph ((frame plot-demo) stream &key &allow-other-keys) - (updating-output (stream) - (with-slots (y-labelling graph-type plot-data x-labels y-labels - x-min y-min x-max y-max) frame - (plotting-data (stream :y-labelling y-labelling - :x-labels x-labels :y-labels y-labels - :x-min x-min :y-min y-min - :x-max x-max :y-max y-max - :type graph-type) - (plot-data plot-data))))) + (with-slots (y-labelling graph-type plot-data x-labels y-labels + x-min y-min x-max y-max) frame + (plotting-data (stream :y-labelling y-labelling + :x-labels x-labels :y-labels y-labels + :x-min x-min :y-min y-min + :x-max x-max :y-max y-max + :type graph-type) + (plot-data plot-data)))) (define-plot-demo-command com-describe-graph-line ((line 'graph-line :gesture :describe)) diff --git a/misc/compile-1.lisp b/misc/compile-1.lisp index 1bb39110..297c7267 100644 --- a/misc/compile-1.lisp +++ b/misc/compile-1.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: compile-1.lisp,v 1.17 92/12/07 12:15:00 cer Exp $ +;; $fiHeader: compile-1.lisp,v 1.18 93/03/18 14:37:23 colin Exp $ (in-package :user) @@ -74,11 +74,13 @@ (load "demo/sysdcl") (clim-defsys::compile-system 'clim-demo :propagate t) (clim-defsys::load-system 'clim-demo) - - (load "climtoys/sysdcl.lisp") - (clim-defsys::compile-system 'clim-toys) - (clim-defsys::load-system 'clim-toys) - + (when (probe-file "climtoys/sysdcl.lisp") + (load "climtoys/sysdcl.lisp") + (clim-defsys::compile-system 'clim-toys)) + (dolist (file '("test/test-driver" + "test/test-clim" + "test/test-demos")) + (compile-file file) + (load file)) #+ignore (load "compatibility/sysdcl.lisp") #+ignore (clim-defsys::compile-system 'clim-compatibility :propagate t)) - diff --git a/misc/dev-load-1.lisp b/misc/dev-load-1.lisp index 419af2aa..8079d7a2 100644 --- a/misc/dev-load-1.lisp +++ b/misc/dev-load-1.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: dev-load-1.lisp,v 1.21 92/11/19 14:24:37 cer Exp $ +;; $fiHeader: dev-load-1.lisp,v 1.22 93/01/21 14:58:40 cer Exp $ ;;;; This should not matter ;;;; (setq *ignore-package-name-case* t) @@ -70,6 +70,12 @@ (when (probe-file "climtoys/sysdcl.lisp") (load "climtoys/sysdcl.lisp") (tenuring (clim-defsys::load-system 'clim-toys))) + + (dolist (file '("test/test-driver.lisp" + "test/test-clim" + "test/test-demos.lisp")) + (load file)) + (ignore-errors (require :composer)) (ignore-errors diff --git a/misc/train.lisp b/misc/train.lisp index 89220d9b..acad6367 100644 --- a/misc/train.lisp +++ b/misc/train.lisp @@ -20,9 +20,10 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: train.lisp,v 1.2 92/12/07 12:15:06 cer Exp $ +;; $fiHeader: train.lisp,v 1.3 92/12/14 15:02:56 cer Exp $ (defun train-clim (&key (train-times 2) (psview nil) (frame-tests t) (errorp t)) + (setq *global-gc-behavior* nil) (load "test/test.lisp") (when frame-tests (clim-user::train-clim-2 train-times) diff --git a/postscript/postscript-port.lisp b/postscript/postscript-port.lisp index 422953fa..a174f48f 100644 --- a/postscript/postscript-port.lisp +++ b/postscript/postscript-port.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: POSTSCRIPT-CLIM; Base: 10; Lowercase: Yes -*- -;; $fiHeader: postscript-port.lisp,v 1.14 92/12/17 15:33:11 cer Exp $ +;; $fiHeader: postscript-port.lisp,v 1.15 93/02/08 15:57:19 cer Exp $ (in-package :postscript-clim) @@ -252,7 +252,7 @@ (defclass postscript-medium (basic-medium) ((printer-stream :initarg :stream) - (current-color :initform nil) ;for decoding stippled inks + (current-color :initform nil) ;for decoding stippled inks (features-sent :initform nil) (curfont :initform nil) ;a psfck structure (ch1buf :initform (make-array 1 :element-type #+ANSI-90 'character @@ -818,6 +818,7 @@ x y translate xra yra scale 0 0 1 sa ea arcp setmatrix end} def (unwind-protect (multiple-value-prog1 (funcall continuation stream) + (force-output stream) (multiple-value-bind (width height) (bounding-rectangle-size (stream-output-history stream)) (let* ((page-width diff --git a/silica/db-box.lisp b/silica/db-box.lisp index 22b5fb37..307e7619 100644 --- a/silica/db-box.lisp +++ b/silica/db-box.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: SILICA; Base: 10; Lowercase: Yes -*- -;; $fiHeader: db-box.lisp,v 1.22 92/09/24 09:37:28 cer Exp $ +;; $fiHeader: db-box.lisp,v 1.23 93/02/08 15:57:26 cer Exp $ (in-package :silica) @@ -15,7 +15,7 @@ (defclass box-pane (layout-pane) - ((space :initform 1 :initarg :spacing) + ((spacing :initform 0 :initarg :spacing) contents)) (defmethod initialize-instance :after @@ -37,10 +37,10 @@ (deallocate-event event)) (defmethod compose-box - ((box-pane box-pane) - fn-major fn-major+ fn-major- fn-minor fn-minor+ fn-minor- width-or-height - keys) - (with-slots (contents space) box-pane + ((box-pane box-pane) + fn-major fn-major+ fn-major- fn-minor fn-minor+ fn-minor- width-or-height + keys) + (with-slots (contents spacing) box-pane (if (null contents) (make-space-requirement) (let ((major 0) @@ -60,7 +60,7 @@ (psetf entry (second entry) scale (let ((n (first entry))) (if (numberp n) (float n) n))) - (setf scale 1.0)) + (setf scale 1.0)) (let ((space-req (apply #'compose-space entry width-or-height))) (flet ((scale (x) (if (and (numberp scale) (< x +fill+)) (/ x scale) x))) @@ -68,26 +68,27 @@ (cond ((eq scale :fill) (incf major+ +fill+)) (t - (incf major (+ (scale (funcall fn-major space-req)) space)) + (incf major (scale (funcall fn-major space-req))) (incf major+ (scale (funcall fn-major+ space-req))))) (incf major- (scale (funcall fn-major- space-req))) (setq minor (max minor (funcall fn-minor space-req))) (maxf minor-min (funcall fn-minor- space-req)) (minf minor-max (funcall fn-minor+ space-req))))))) - (decf major space) ;;--- These calcs lead to weirdness when fills are involved. ;;--- This looks like a leftover from the time when +/- were relative ;;(setq minor- (max 0 (- minor minor-min))) ;;(setq minor+ (max 0 (- minor-max minor))) (setq minor- minor-min) (setq minor+ minor-max) - (apply #'make-space-requirement - (mapcan #'list - keys - (list major major+ major- minor minor+ minor-))))))) + (let ((extra (* (1- (length (sheet-children box-pane))) spacing))) + (apply #'make-space-requirement + (mapcan #'list + keys + (list (+ extra major) (+ extra major+) (+ extra major-) minor minor+ minor-)))))))) -(defclass hbox-pane (box-pane) ()) +(defclass hbox-pane (box-pane) + ((spacing :initarg :x-spacing))) (defmethod compose-space ((box-pane hbox-pane) &key width height) (declare (ignore width)) @@ -102,7 +103,7 @@ '(:width :max-width :min-width :height :max-height :min-height))) (defmethod allocate-space ((box-pane hbox-pane) width height) - (with-slots (contents space) box-pane + (with-slots (contents spacing) box-pane (let ((space-requirement (compose-space box-pane :width width :height height))) (flet ((compose (x) @@ -110,10 +111,11 @@ ((eq (car x) :fill) :fill) (t (make-space-requirement :height 0 :width (* (car x) width)))))) (declare (dynamic-extent #'compose)) - (let ((sizes + (let* ((adjust (* spacing (1- (length (sheet-children box-pane))))) + (sizes (allocate-space-to-items - width - space-requirement + (- width adjust) + (space-requirement+* space-requirement :height (- adjust)) contents #'space-requirement-min-width #'space-requirement-width @@ -125,13 +127,14 @@ (and (consp sheet) (panep (second sheet)) (setq sheet (second sheet)))) - (move-and-resize-sheet - sheet x 0 (frob-size size width x) height)) + (move-and-resize-sheet sheet x 0 size height) + (incf x spacing)) (incf x size)) contents sizes)))))) -(defclass vbox-pane (box-pane) ()) +(defclass vbox-pane (box-pane) + ((spacing :initarg :y-spacing))) (defmethod compose-space ((box-pane vbox-pane) &key width height) (declare (ignore height)) @@ -146,7 +149,7 @@ `(:height :max-height :min-height :width :max-width :min-width))) (defmethod allocate-space ((box-pane vbox-pane) width height) - (with-slots (contents space) box-pane + (with-slots (contents spacing) box-pane (let ((space-requirement (compose-space box-pane :width width :height height))) (flet ((compose (x) @@ -154,10 +157,11 @@ ((eq (car x) :fill) :fill) (t (make-space-requirement :width 0 :height (* (car x) height)))))) (declare (dynamic-extent #'compose)) - (let ((sizes + (let* ((adjust (* spacing (1- (length (sheet-children box-pane))))) + (sizes (allocate-space-to-items - height - space-requirement + (- height adjust) + (space-requirement+* space-requirement :height (- adjust)) contents #'space-requirement-min-height #'space-requirement-height @@ -169,17 +173,11 @@ (and (consp sheet) (panep (second sheet)) (setq sheet (second sheet)))) - (move-and-resize-sheet - sheet 0 y width (frob-size size height y))) + (move-and-resize-sheet sheet 0 y width size) + (incf y spacing)) (incf y size)) contents sizes)))))) -;;--- In theory this should work OK. -(defun frob-size (wanted-size available where-we-are-now) - #---ignore (declare (ignore available where-we-are-now)) - #---ignore wanted-size - #+++ignore (min wanted-size (1- (- available where-we-are-now)))) - ;;; Bulletin board ;;; Is there any value in this??? ;;; What do we want it to do? diff --git a/silica/db-layout.lisp b/silica/db-layout.lisp index 8439e8ac..26104993 100644 --- a/silica/db-layout.lisp +++ b/silica/db-layout.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: SILICA; Base: 10; Lowercase: Yes -*- -;; $fiHeader: db-layout.lisp,v 1.28 93/01/21 14:58:53 cer Exp $ +;; $fiHeader: db-layout.lisp,v 1.29 93/03/18 14:37:46 colin Exp $ (in-package :silica) @@ -97,7 +97,7 @@ (cons nil *inside-changing-space-requirements*))) (multiple-value-prog1 (funcall continuation) - (unless (or (not layout) old-inside-changing-space-requirements) + (when (and layout (not old-inside-changing-space-requirements)) ;; Layout that frames that need to be laid out and ;; re-layout the minimal subtrees that need to be laid out (let* ((frames (remove-duplicates @@ -189,11 +189,11 @@ ;;; Space Req Mixin ;;; -(defclass space-requirement-mixin (layout-mixin) +(defclass basic-space-requirement-mixin (layout-mixin) ((initial-space-requirement :reader pane-initial-space-requirements) (space-requirement :reader pane-space-requirements))) -(defmethod initialize-instance :after ((pane space-requirement-mixin) +(defmethod initialize-instance :after ((pane basic-space-requirement-mixin) &rest args &key width max-width min-width height max-height min-height) @@ -211,11 +211,11 @@ (setf space-requirement sr initial-space-requirement sr))))) -(defmethod change-space-requirements-to-default ((pane space-requirement-mixin)) +(defmethod change-space-requirements-to-default ((pane basic-space-requirement-mixin)) (when (pane-initial-space-requirements pane) (change-space-requirements-to pane (pane-initial-space-requirements pane)))) -(defmethod default-space-requirements ((pane space-requirement-mixin) +(defmethod default-space-requirements ((pane basic-space-requirement-mixin) &key (width 0) (min-width width) (max-width width) @@ -225,12 +225,7 @@ (values width min-width max-width height min-height max-height)) -(defmethod compose-space ((pane space-requirement-mixin) &key width height) - (declare (ignore width height)) - (or (slot-value pane 'space-requirement) - (slot-value pane 'initial-space-requirement))) - -(defmethod change-space-requirements ((pane space-requirement-mixin) +(defmethod change-space-requirements ((pane basic-space-requirement-mixin) &key width min-width max-width height min-height max-height resize-frame) @@ -247,169 +242,34 @@ :min-height (or min-height srmin-height) :max-height (or max-height srmax-height)))))) - -;;; -;;; Client Space-req Mixin (read Client Space-req) + ;;; +(defclass space-requirement-mixin (basic-space-requirement-mixin) ()) -(defclass basic-client-space-requirement-mixin (layout-mixin) - ((client-space-requirement :initform nil)) - (:documentation "User can specify a value for the client-space-requirement slot that defaults to NIL")) - -(defmethod change-space-requirements ((pane basic-client-space-requirement-mixin) - &key width min-width max-width - height min-height max-height - resize-frame) - (declare (ignore resize-frame)) - (with-slots (client-space-requirement) pane - ;;--- This doesn't look very convincing! - (let ((srwidth 100) (srmin-width 0) (srmax-width +fill+) - (srheight 100) (srmin-height 0) (srmax-height +fill+)) - (when client-space-requirement - (multiple-value-setq (srwidth srmin-width srmax-width - srheight srmin-height srmax-height) - (space-requirement-components client-space-requirement))) - (setq client-space-requirement (make-space-requirement - :width (or width srwidth) - :min-width (or min-width srmin-width) - :max-width (or max-width srmax-width) - :height (or height srheight) - :min-height (or min-height srmin-height) - :max-height (or max-height srmax-height)))))) - -(defmethod initialize-instance :after ((pane basic-client-space-requirement-mixin) - &rest args - &key width max-width min-width - height max-height min-height) - (declare (dynamic-extent args)) - (when (or width max-width min-width height max-height min-height) - (multiple-value-bind (width min-width max-width - height min-height max-height) - (apply #'default-space-requirements pane :allow-other-keys t args) - (setf (slot-value pane 'client-space-requirement) - (make-space-requirement - :width width :min-width min-width :max-width max-width - :height height :min-height min-height :max-height max-height))))) - -;;--- This duplicates the method on SPACE-REQUIREMENT-MIXIN. Can we share? -(defmethod default-space-requirements ((pane basic-client-space-requirement-mixin) - &key (width 0) - (min-width width) - (max-width width) - (height 0) - (min-height height) - (max-height height)) - (values width min-width max-width - height min-height max-height)) - -;;;; - -;;--- The only subclass of BASIC-CLIENT-SPACE-REQUIREMENT-MIXIN. Merge them? -(defclass client-space-requirement-mixin (basic-client-space-requirement-mixin) - () - (:documentation "If the user specifies some space requirements then use it otherwise use other value")) -(defmethod compose-space :around ((pane client-space-requirement-mixin) &key width height) +(defmethod compose-space ((pane space-requirement-mixin) &key width height) (declare (ignore width height)) - (or (slot-value pane 'client-space-requirement) - (call-next-method))) - - - -;;; -;;; Client space space-requirement (read Client Space Space-requirement) -;;; Just like the above but used by panes that are using the client-specified -;;; space-requirement to determine how much free space is requested (spacer, filler). -;;; - -;(defclass client-space-space-requirement-mixin (client-space-requirement-mixin) -; ()) -; -;(defmethod initialize-instance :around -; ((pane client-space-space-requirement-mixin) &rest rest -; &key space) -; (if space -; (apply #'call-next-method pane :width space :height space rest) -; (call-next-method))) -;;; -;;; Client Stretchability -;;; - -;(defclass client-stretchability-mixin (layout-mixin) -; ((max-width :initform nil :initarg :max-width) -; (max-height :initform nil :initarg :max-height))) -; - -;(defmethod compose-space :around ((pane client-stretchability-mixin) &key width height) -; (with-slots (max-width max-height) pane -; (let ((sr (call-next-method))) -; (when (or max-width max-height) -; (multiple-value-bind (srwidth srmin-width srmax-width -; srheight srmin-height srmax-height) -; (space-requirement-components sr) -; (setq sr (make-space-requirement :width srwidth -; :min-width srmin-width -; :max-width (or max-width srmax-width) -; :height srheight -; :min-height srmin-height -; :max-height (or max-height srmax-height))))) -; sr))) + (or (slot-value pane 'space-requirement) + (slot-value pane 'initial-space-requirement))) + ;;; ;;; Client Overridability ;;; -(defclass client-overridability-mixin (layout-mixin) - ((width :initform nil :initarg :width) - (min-width :initform nil :initarg :min-width) - (max-width :initform nil :initarg :max-width) - (height :initform nil :initarg :height) - (min-height :initform nil :initarg :min-height) - (max-height :initform nil :initarg :max-height)) - (:documentation "Client can specify values that override those provided elsewhere")) +(defclass client-overridability-mixin (basic-space-requirement-mixin) + ()) + +(defmethod default-space-requirements ((pane client-overridability-mixin) + &key width min-width max-width height min-height max-height) + (values width min-width max-width + height min-height max-height)) (defmethod compose-space :around ((pane client-overridability-mixin) &key width height) (declare (ignore width height)) - (with-slots (width height max-width max-height min-width min-height) pane - (let ((sr (call-next-method))) - (if (or width min-width max-width height min-height max-height) - (multiple-value-bind (srwidth srmin-width srmax-width - srheight srmin-height srmax-height) - (space-requirement-components sr) - (make-space-requirement - :width (or width srwidth) - :min-width (or min-width srmin-width) - :max-width (or max-width srmax-width) - :height (or height srheight) - :min-height (or min-height srmin-height) - :max-height (or max-height srmax-height))) - sr)))) - - -;;; -;;; Client Demandability -;;; -;;; Used by db-scroll -;(defclass client-demandability-mixin (client-space-requirement-mixin -; space-requirement-cache-mixin) -; ((space-demand-p :initform t :initarg :space-demand-p))) -; -;(defmethod compose-space ((pane client-demandability-mixin) &key width height) -; (with-slots (client-space-requirement space-demand-p) pane -; (if space-demand-p -; (or client-space-requirement (compose-space (sheet-child pane))) -; (let ((child-req (compose-space (sheet-child pane)))) -; (if client-space-requirement -; (make-space-requirement -; :width (min (space-requirement-width client-space-req) -; (space-requirement-width child-req)) -; :max-width (max (space-requirement-max-width client-space-req) -; (space-requirement-max-width child-req)) -; :height (min (space-requirement-height client-space-req) -; (space-requirement-height child-req)) -; :max-height (max (space-requirement-max-height client-space-req) -; (space-requirement-max-height child-req))) -; child-req))))) + (with-slots (space-requirement) pane + (space-requirement-combine + #'(lambda (x y) (or x y)) space-requirement (call-next-method)))) ;;; ;;; Space Req Cache @@ -457,8 +317,7 @@ ;;; (defclass wrapping-space-mixin (layout-mixin) - () - (:documentation "Supports echoing allocations down and compositions up.")) + ()) (defmethod allocate-space ((pane wrapping-space-mixin) width height) (resize-sheet (sheet-child pane) width height)) @@ -468,130 +327,10 @@ (compose-space child :width width :height height))) -;;; -;;; Transforming Wrapping Space Mixin -;;; - -;(defclass simple-transforming-wrapping-space-mixin (space-requirement-cache-mixin) -; () -; (:documentation "Supports echoing allocations down and compositions up.~%~ -; Transforming the echos for translations and reflection.")) -; -;(defmethod allocate-space ((pane simple-transforming-wrapping-space-mixin) -; width height) -; (let ((child (sheet-child pane))) -; (multiple-value-bind (width height) -; (untransform-dimensions (sheet-transformation child) width height) -; (resize-sheet child width height)))) -; -;(defmethod compose-space ((pane simple-transforming-wrapping-space-mixin) &key width height) -; (declare (ignore width height)) -; (let* ((child (sheet-child pane)) -; (xform (sheet-transformation child)) -; (req (compose-space child))) -; (multiple-value-bind (width min-width max-width -; height min-height max-height) -; (space-requirement-components req) -; (multiple-value-setq (width height) -; (untransform-dimensions xform width height)) -; (multiple-value-setq (max-width max-height) -; (untransform-dimensions xform max-width max-height)) -; (multiple-value-setq (min-width min-height) -; (untransform-dimensions xform min-width min-height)) -; (make-space-requirement :width width :min-width min-width :max-width max-width -; :height height :min-height min-height :max-height max-height)))) - - -;;; -;;; Restrainer-pane -;;; -;;; Use this wrapping composite to not allow note-space-requirements-changed to propagate up. - -(defclass restrainer-pane (simple-wrapper-mixin - wrapping-space-mixin - sheet-mute-input-mixin - composite-pane) - ()) - -(defmethod note-space-requirements-changed ((pane restrainer-pane) inner) - (declare (ignore inner)) - (allocate-space - pane - (bounding-rectangle-width pane) (bounding-rectangle-height pane))) - - - -;;; Generally useful layout function -;;; Used all over to satisfy constraints - -;;--- I think that since coordinates are ultimately integers we loose -;;--- along the way, calling FIX-COORDINATE on alloc helps a little but we -;;--- still end up with a gap along the bottom-right edges. -#+++ignore -(defun allocate-space-to-items (given wanted items min-size - desired-size max-size item-size) - (macrolet ((desired-size (x) `(funcall desired-size ,x)) - (min-size (x) `(funcall min-size ,x)) - (max-size (x) `(funcall max-size ,x)) - (item-size (x) `(funcall item-size ,x))) - (let ((stretch-p (>= given (desired-size wanted))) - extra give used sizes) - (if stretch-p - (setq give (- (max-size wanted) (desired-size wanted)) - extra (min (- given (desired-size wanted)) give)) - (setq give (- (desired-size wanted) (min-size wanted)) - extra (min (- (desired-size wanted) given) give))) - (dolist (item items) - (let (alloc) - (typecase item - ((member :fill) - (if stretch-p - (progn - (setq alloc (/ (* +fill+ extra) give)) - (setq alloc (ceiling alloc)) - (fix-coordinates alloc) - (decf give +fill+)) - (setq alloc 0))) - (t - (let* ((item-size (item-size item))) - (if (eq item-size :fill) - (if stretch-p - (progn - (setq alloc (/ (* +fill+ extra) give)) - (setq alloc (ceiling alloc)) - (fix-coordinates alloc) - (decf give +fill+)) - (setq alloc 0)) - (progn - (setq alloc (desired-size item-size)) - (when (> give 0) - (if stretch-p - (progn - (setq used (/ (* (- (max-size item-size) - (desired-size item-size)) - extra) - give)) - (incf alloc used) - (fix-coordinates alloc) - (decf give (- (max-size item-size) - (desired-size item-size)))) - (progn - (setq used (/ (* (- (desired-size item-size) - (min-size item-size)) - extra) - give)) - (decf alloc used) - (fix-coordinates alloc) - (decf give (- (desired-size item-size) - (min-size item-size))))) - (decf extra used))))))) - (push alloc sizes))) - (nreverse sizes)))) - ;; This new supa dupa version saves up all the fills to the end and ;; then divides up any leftover space equally amongst them and it ;; seems to work! -#---ignore + (defun allocate-space-to-items (given wanted items min-size desired-size max-size item-size) (macrolet ((desired-size (x) `(funcall desired-size ,x)) @@ -654,10 +393,11 @@ ;; Most of the layout panes should inherit from this ;;--- It would be nice if this and COMPOSITE-PANE had single- and multiple-child ;;--- versions so that users could get better error diagnostics + (defclass layout-pane (sheet-mute-input-mixin sheet-with-resources-mixin - space-requirement-mixin space-requirement-cache-mixin + client-overridability-mixin sheet-permanently-enabled-mixin composite-pane) ()) @@ -666,6 +406,7 @@ ;;--- Does this need to be more complicated? ;;--- What is the correct behavior. Should it take a space requirement? ;;--- and just call ALLOCATE-SPACE? + (defclass bboard-pane (space-requirement-mixin layout-pane) ()) (defmethod handle-event :after ((pane bboard-pane) (event pointer-motion-event)) diff --git a/silica/gadgets.lisp b/silica/gadgets.lisp index 7ec318f4..98238c26 100644 --- a/silica/gadgets.lisp +++ b/silica/gadgets.lisp @@ -1,6 +1,6 @@ ;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: SILICA; Base: 10; Lowercase: Yes -*- -;; $fiHeader: gadgets.lisp,v 1.45 93/02/08 15:57:32 cer Exp $ +;; $fiHeader: gadgets.lisp,v 1.46 93/03/18 14:38:01 colin Exp $ "Copyright (c) 1991, 1992 by Franz, Inc. All rights reserved. Portions copyright (c) 1992 by Symbolics, Inc. All rights reserved." @@ -450,7 +450,7 @@ :accessor gadget-lines) (word-wrap :initarg :word-wrap :accessor gadget-word-wrap)) - (:default-initargs :ncolumns 1 :nlines 1 :editable-p t :word-wrap nil)) + (:default-initargs :ncolumns 30 :nlines 1 :editable-p t :word-wrap nil)) ;;; Viewport @@ -486,16 +486,22 @@ :width width :min-width 0 :max-width max-width :height height :min-height 0 :max-height max-height)))) + (defmethod allocate-space ((viewport viewport) width height) ;; Make sure the child is at least as big as the viewport ;; (VIEWPORT-REGION-CHANGED actually does this also) (let* ((child (sheet-child viewport))) - (multiple-value-bind (cwidth cheight) - (bounding-rectangle-size child) - (when (or (< cwidth width) - (< cheight height)) - (resize-sheet - child (max width cwidth) (max height cheight)))))) + (if (typep child 'clim-stream-pane) + (multiple-value-bind (cwidth cheight) + (bounding-rectangle-size child) + (when (or (< cwidth width) + (< cheight height)) + (resize-sheet + child (max width cwidth) (max height cheight)))) + (progn + (let ((sr (compose-space child :width width :height height))) + (resize-sheet child (space-requirement-width sr) + (space-requirement-height sr))))))) (defmethod allocate-space :after ((viewport viewport) width height) (let ((vr (viewport-viewport-region viewport))) @@ -519,6 +525,22 @@ (update-scroll-bars viewport) (viewport-region-changed (sheet-child viewport) viewport)))))))))) +;;-- This method seems applicable to a whole bunch of panes. +;;-- The problem we have is that a whole bunch of panes dont get the +;;-- right background so it looks crap. + +#+ignore +(defmethod repaint-sheet ((sheet viewport) region) + (let ((region (region-intersection (sheet-region sheet) region))) + (dolist (child (sheet-children sheet)) + (setq region (region-difference region (transform-region (sheet-transformation child) (sheet-region child))))) + (with-sheet-medium (medium sheet) + (with-drawing-options (medium :ink +background-ink+) + (dolist (rect (region-set-regions region)) + (unless (eq +nowhere+ rect) + (with-bounding-rectangle* (left top right bottom) rect + (draw-rectangle* medium left top right bottom)))))))) + (defmethod note-space-requirements-changed ((pane viewport) inner) (declare (ignore inner)) (allocate-space diff --git a/specs/acknowledgments.tex b/specs/acknowledgments.tex index 7deea2c7..715100c6 100644 --- a/specs/acknowledgments.tex +++ b/specs/acknowledgments.tex @@ -15,9 +15,10 @@ interests through the whole process. The attendees of the CLIM coalition meetings and those who contributed to CLIM along the way include all of those listed on the title page, but also include -Bob Kerns, Chris Richardson and John Irwin, Paul Weineke and JonL White, and -Kevin Males. Other contributors include Mike McMahon, Paul Robertson, John -Hotchkiss, Dave Lowry, Mike Greenwald, Dave Schatsky, and Glenn Adams. +Bob Kerns, John Irwin, Paul Weineke and JonL White, and Kevin Males. Other +contributors include Mike McMahon, Paul Robertson, John Hotchkiss, Dave Lowry, +Mike Greenwald, Dave Schatsky, and Glenn Adams. Barry Margolin and Richard +Billington, acting for the ALU, contributed useful comments as well. Sonya Keene, Ann Hathaway, and Ellen Golden all deserve credit for improving the quality of this specification (in part by authoring the original CLIM diff --git a/specs/bboxes.tex b/specs/bboxes.tex index 6b8d08c8..d2c0323c 100644 --- a/specs/bboxes.tex +++ b/specs/bboxes.tex @@ -68,7 +68,7 @@ mutable objects as sheets and output records, bounding rectangles are volatile. Therefore, programmers must not depend on the bounding rectangle associated with a mutable object remaining constant. -\Defun {bounding-rectangle-p} {object} +\Defpredicate {bounding-rectangle-p} {object} Returns \term{true} if \arg{object} is a \term{bounding rectangle} (that is, supports the bounding rectangle protocol), otherwise returns \term{false}. diff --git a/specs/bordered-output.tex b/specs/bordered-output.tex index 636a285b..63a17acb 100644 --- a/specs/bordered-output.tex +++ b/specs/bordered-output.tex @@ -31,6 +31,7 @@ rectangular, highlighted with a dropshadow, and underlined, respectively. \Defmacro {surrounding-output-with-border} {(\optional stream + \rest drawing-options \key shape (move-cursor \cl{t})) \body body} @@ -42,7 +43,8 @@ rectangle of the output. \cl{:oval} draws an oval around the bounding rectangle of the output. \cl{:drop-shadow} draws a ``drop shadow'' around the lower right edge of the bounding rectangle of the output. \cl{:underline} draws a thin line along the baseline of all of the text in the output, but does not draw anything -underneath non-textual output. +underneath non-textual output. \arg{drawing-options} is a list of drawing +options that are passed to the function that draws the border. If the boolean \arg{move-cursor} is \term{true} (the default), then the text cursor will be moved so that it immediately follows the lower right corner of @@ -70,6 +72,8 @@ comparison): \arg{(\key stream record left top right bottom)} \\ +\arg{arglist} may include other keyword arguments that serve as the drawing options. + \arg{body} is the code that actually draws the border. It has lexical access to \cl{stream}, \cl{record}, \cl{left}, \cl{top}, \cl{right}, and \cl{bottom}, which are respectively, the stream being drawn on, the output record being diff --git a/specs/changes.tex b/specs/changes.tex index 4c74b240..4c9e7839 100644 --- a/specs/changes.tex +++ b/specs/changes.tex @@ -4,8 +4,8 @@ \label {changes} This appendix lists the incompatible changes from CLIM 1.0 (and CLIM 0.9 for the -API related to the windowing substrate), and the rationale for those changes. -They are listed on a chapter-by-chapter basis. +API related to the windowing substrate and gadgets), and the rationale for those +changes. They are listed on a chapter-by-chapter basis. When the items say that a compatibility stub will be provided, this does not mean that this compatibility needs to be part of CLIM itself. It could be @@ -218,9 +218,9 @@ provided. \cl{stream-add-string-output} and \cl{stream-add-character-output}. Compatibility functions will be provided. -\item \cl{with-output-recording-options} has had its \arg{draw-p} and -\arg{record-p} keyword arguments changed to \arg{draw} and \arg{record} to -conform to Common Lisp naming conventions. Compability code will be provided. +\item \cl{with-output-recording-options} has had its \cl{:draw-p} and +\cl{:record-p} keyword arguments changed to \cl{:draw} and \cl{:record} to +conform to Common Lisp naming conventions. Compatibility code will be provided. \end{itemize} @@ -234,8 +234,8 @@ have been renamed to \cl{:x-spacing}, \cl{:y-spacing}, and options. Compatibility options will be provided. \item The \cl{:minimum-width} and \cl{:minimum-height} options to -\cl{formatting-cell} have been renamed to \cl{:min-width} and {:min-height} in -order to be consistent with the pane options. Compatibility options will be +\cl{formatting-cell} have been renamed to \cl{:min-width} and \cl{:min-height} +in order to be consistent with the pane options. Compatibility options will be provided. \item The \cl{:inter-column-spacing} and \cl{:inter-row-spacing} options to @@ -243,7 +243,7 @@ provided. \cl{:x-spacing} and \cl{:y-spacing} in order to be consistent with the pane options. Compatibility options will be provided. -\item The \cl{:no-initial-spacing} option to {formatting-item-list} and +\item The \cl{:no-initial-spacing} option to \cl{formatting-item-list} and \cl{format-items} has been renamed to \cl{:initial-spacing}, because inverted-sense flags are too hard to keep straight. The default for \cl{:no-initial-spacing} was \term{true}, therefore the default for @@ -280,9 +280,10 @@ remain as a compatibility function that takes a single root object. conventions. A compatibility function will be provided. \item All of the clause arglists for \cl{tracking-pointer} are specified with -\key, that is, they are named arguments rather than positional ones. This -should not cause any problems, except for the one case that the \arg{character} -argument to the \cl{:keyboard} clause has been renamed to \arg{gesture}. +{\tt\&key\}, that is, they are named arguments rather than positional ones. +This should not cause any problems, except for the one case that the +\arg{character} argument to the \cl{:keyboard} clause has been renamed to +\arg{gesture}. \item The function \cl{dragging-output-record} has been renamed to \cl{drag-output-record} to be consistent with our naming conventions. A @@ -296,18 +297,18 @@ compatibility function will be provided. \item The argument list for \cl{with-output-as-presentation} has been changed to make \arg{stream}, \arg{object}, and \arg{type} be required arguments instead of keyword arguments. This is because it is always necessary to supply those -arguments in order for \cl{with-output-as-presentation} to work. Compability +arguments in order for \cl{with-output-as-presentation} to work. Compatibility code will be provided to support the old syntax. -\item The \arg{activation-characters}, \arg{additional-activation-characters}, -\arg{blip-characters}, and \arg{additional-blip-characters} keyword arguments to -the \cl{accept} functions have been renamed to \arg{activation-gestures}, -\arg{additional-activation-gestures}, \arg{delimiter-gestures}, and -\arg{additional-delimiter-gestures}. Compability code will be provided to +\item The \cl{:activation-characters}, \cl{:additional-activation-characters}, +\cl{:blip-characters}, and \cl{:additional-blip-characters} keyword arguments to +the \cl{accept} functions have been renamed to \cl{:activation-gestures}, +\cl{:additional-activation-gestures}, \cl{:delimiter-gestures}, and +\cl{:additional-delimiter-gestures}. Compatibility code will be provided to support the old keyword arguments. \item The arglists for presentation translators and their documentation and -tester components have been changed to take a single position \arg{object} +tester components have been changed to take a single positional \arg{object} argument and a list of named (keyword) arguments. Except for translators that omit the \arg{object} argument or have it in other than the initial position of the arglist, this will not pose a problem. This change can be detected. @@ -317,15 +318,15 @@ been changed to be a \arg{command-table} argument. A check at run-time can detect when a frame is supplied to \cl{find-presentation-translators} instead of a command table. -\item The \arg{shift-mask} keyword argument to \cl{test-presentation-translator}, +\item The \cl{:shift-mask} keyword argument to \cl{test-presentation-translator}, \cl{find-applicable-translators}, \cl{presentation-matches-context-type}, and \cl{find-innermost-applicable-presentation} has been renamed to -\arg{modifier-state} in order to be consistent with the device event terminology. -Compability code will be provided to support the old keyword. +\cl{:modifier-state} in order to be consistent with the device event terminology. +Compatibility code will be provided to support the old keyword. -\item The \arg{shifts} keyword argument to \cl{define-gesture-name} has been -renamed to \arg{modifiers} in order to be consistent with the device event -terminology. Compability code will be provided to support the old keyword. +\item \cl{define-gesture-name} is completely different from CLIM 1.1. There +will be no compatibility code provided to support the old version of +\cl{define-gesture-name}. \item \cl{dialog-view} and \cl{+dialog-view+} have been renamed to \cl{textual-dialog-view} and \cl{+textual-dialog-view+} in order to accurately @@ -395,18 +396,20 @@ be retained, but its use is deprecated. options will be provided. \item The \cl{:test} argument to the following functions has been removed, since -the use of gesture names makes it unnecessary: \cl{add-command-to-command-table}, -\cl{add-keystroke-to-command-table}, \cl{remove-keystroke-from-command-table}, -\cl{find-keystroke-item}, \cl{lookup-keystroke-item}, and -\cl{lookup-keystroke-command-item}. The \cl{:keystroke-test} argument has been -removed from \cl{read-command} and \cl{read-command-using-keystrokes} for the -same reason. +the use of gesture names makes it unnecessary: +\cl{add-command-to-command-table}, \cl{(add-keystroke-to-command-table}, and +\cl{remove-keystroke-from-command-table}. The \cl{:keystroke-test} argument has +been removed from \cl{read-command} and \cl{read-command-using-keystrokes} for +the same reason. \end{itemize} \paragraph {Application Frames} \begin{itemize} +\item The \cl{:root} argument has been removed from \cl{open-window-stream} and +\cl{make-application-frame}. + \item The \cl{:layout} option has been removed, and is replaced by the more general \cl{:layouts} option. A compatibility hook will be provided that handles the old \cl{:layout} option. @@ -434,7 +437,7 @@ Compatibility functions will be provided. \begin{itemize} \item \cl{realize-pane} and \cl{realize-pane-1} have been renamed to -\cl{make-pane} and \cl{make-pane-1}. A compability function will be provided +\cl{make-pane} and \cl{make-pane-1}. A compatibility function will be provided for \cl{realize-pane}. \item The pane options \cl{:hs}, \cl{:hs+}, \cl{:hs-}, \cl{:vs}, \cl{:vs+}, and diff --git a/specs/clim-sys.tex b/specs/clim-sys.tex index 828817ca..fb1ea666 100644 --- a/specs/clim-sys.tex +++ b/specs/clim-sys.tex @@ -106,6 +106,11 @@ Most Lisp implementations provide some form of multi-processing. CLIM provides a set of functions that implement a uniform interface to the multi-processing functionality. +\Defvar {*multiprocessing-p*} + +The value of \cl{*multiprocessing-p*} is \cl{t} if the current Lisp +environment supports multi-processing, otherwise it is \cl{nil}. + \Defun {make-process} {function \key name} Creates a process named \arg{name}. The new process will evaluate the function @@ -126,6 +131,17 @@ would be returned by \cl{make-process}. Returns a sequence of all of the processes. +\Defpredicate {processp} {object} + +Returns \cl{t} if \arg{object} is a process, otherwise returns \arg{nil}. + +\defun {process-name} {process} +\defun {process-state} {process} +\Defun {process-whostate} {process} + +These functions return, respectively, the name, state, and ``whostate'' of the +process. These format of these quantities will vary depending on the platform. + \Defun {process-wait} {reason predicate} Causes the current process to wait until \arg{predicate} returns \term{true}. @@ -152,15 +168,41 @@ Interrupts the process \arg{process} and causes it to evaluate the function \arg{function}. On systems that do not support multi-processing, this is equivalent to \cl{funcall}'ing \arg{function}. +\Defun {disable-process} {process} + +Disables the process \arg{process} from becoming runnable until it is enabled +again. + +\Defun {enable-process} {process} + +Allows the process \arg{process} to become runnable again after it has been +disabled. + +\Defun {restart-process} {process} + +Restarts the process \arg{process} by ``unwinding'' it to its initial state, and +reinvoking its top-level function. + \Defmacro {without-scheduling} {\body body} Evaluates \arg{body} in a context that is guaranteed to be free from interruption by other processes. On systems that do not support multi-processing, \cl{without-scheduling} is equivalent to \cl{progn}. +\defun {atomic-incf} {reference} +\Defun {atomic-decf} {reference} + +Increments (or decrements) the fixnum value referred to by \arg{reference} as a +single, atomic operation. + \section {Locks} +\Defun {make-lock} {\optional name} + +Creates a lock whose name is \arg{name}. On systems that do not support +locking, this will return a new list of one element, \cl{nil}. + \Defmacro {with-lock-held} {(place \optional state) \body body} Evaluates \arg{body} with the lock named by \arg{place}. \arg{place} is a @@ -169,10 +211,13 @@ reference to a lock created by \cl{make-lock}. On systems that do not support locking, \cl{with-lock-held} is equivalent to \cl{progn}. -\Defun {make-lock} {\optional name} +\Defun {make-recursive-lock} {\optional name} -Creates a lock whose name is \arg{name}. On systems that do not support -locking, this will return a new list of one element, \cl{nil}. +Creates a recursive lock whose name is \arg{name}. On systems that do not +support locking, this will return a new list of one element, \cl{nil}. A +recursive lock differs from an ordinary lock in that a process that already +holds the recursive lock can call \cl{with-recursive-lock-held} on the same lock +without blocking. \Defmacro {with-recursive-lock-held} {(place \optional state) \body body} @@ -182,14 +227,6 @@ is a reference to a recursive lock created by \cl{make-recursive-lock}. On systems that do not support locking, \cl{with-recursive-lock-held} is equivalent to \cl{progn}. -\Defun {make-recursive-lock} {\optional name} - -Creates a recursive lock whose name is \arg{name}. On systems that do not -support locking, this will return a new list of one element, \cl{nil}. A -recursive lock differs from an ordinary lock in that a process that already -holds the recursive lock can call \cl{with-recursive-lock-held} on the same lock -without blocking. - %% Use \tt instead of \cl, such the hairy \cl macro will blow chow \section {Multiple Value {\tt setf}} diff --git a/specs/clim.tex b/specs/clim.tex index 0c042565..4796b5fd 100644 --- a/specs/clim.tex +++ b/specs/clim.tex @@ -4,21 +4,22 @@ \pagestyle{headings} \title{Common Lisp Interface Manager \\ - Release 2.0 Specification} + CLIM II Specification} -\author{Scott McKay ({\tentt SWM@Riverside.SCRC.Symbolics.COM}) \\ - William York ({\tentt York@Fuji.ILA.COM}) \\ +\author{Scott McKay ({\tentt SWM@Symbolics.COM}) \\ + William York ({\tentt York@Lucid.COM}) \\ {\tenit with contributions by} \\ - {\tenrm John Aspinall ({\tentt JGA@Riverside.SCRC.Symbolics.COM})} \\ + {\tenrm John Aspinall ({\tentt JGA@Symbolics.COM})} \\ {\tenrm Dennis Doughty ({\tentt Doughty@ILeaf.COM})} \\ - {\tenrm Charles Hornig ({\tentt Hornig@Riverside.SCRC.Symbolics.COM})} \\ + {\tenrm Charles Hornig ({\tentt Hornig@ODI.COM})} \\ {\tenrm Richard Lamson ({\tentt RLamson\%UMAB.BitNet@MITVMA.MIT.EDU})} \\ {\tenrm David Linden ({\tentt Linden@CRL.DEC.COM})} \\ {\tenrm David Moon ({\tentt Moon@Cambridge.Apple.COM})} \\ - {\tenrm Ramana Rao ({\tentt rao@PARC.Xerox.COM})}} + {\tenrm Ramana Rao ({\tentt rao@PARC.Xerox.COM})} \\ + {\tenrm Chris Richardson ({\tentt cer@Franz.COM})}} \date{\today} -\markright{CLIM 2.0 Specification} +\markright{CLIM II Specification} \makeindex @@ -100,8 +101,9 @@ \appendix \input{glossary.tex} \input{clim-sys.tex} -\input{gray-streams.tex} \input{encapsulating-streams.tex} +\input{gray-streams.tex} +\input{extensions.tex} \input{changes.tex} \end{document} diff --git a/specs/colors.tex b/specs/colors.tex index caea8852..4fac6bf7 100644 --- a/specs/colors.tex +++ b/specs/colors.tex @@ -25,7 +25,7 @@ Chapter~\ref{graphics}, can take as its value: \begin{itemize} \item a color, -\item an opacity, +\item an opacity or the constant \cl{+transparent-ink+}, \item the constant \cl{+foreground-ink+}, @@ -48,7 +48,7 @@ The \cl{:ink} drawing option is a design that specifies a new arrangement of colors (and opacities) in this region of the medium's drawing plane. Any viewports or dataports attached to this drawing plane are updated accordingly. The \cl{:ink} drawing option is never affected by the \cl{:transformation} -drawing option nor by the sheet transformation; this ensures that stipple +drawing option nor by the medium's transformation; this ensures that stipple patterns on adjacent sheets join seamlessly. \issue {DCPL} {The description of how the clipping region and transformations @@ -115,7 +115,7 @@ design. This is done by drawing with \cl{(compose-in} \cl{+foreground-ink+} the-colorless-design\cl{)}. See Chapter~\ref{designs} for the details of \cl{compose-in}. -\Defun {designp} {object} +\Defpredicate {designp} {object} Returns \term{true} if \arg{object} is a \term{design}, otherwise returns \term{false}. @@ -141,7 +141,7 @@ mean white. The intensity-hue-saturation color model is also supported, but the red-green-blue color model is the primary model we will use in the specification. -\Defun {colorp} {object} +\Defpredicate {colorp} {object} Returns \term{true} if \arg{object} is a \term{color}, otherwise returns \term{false}. @@ -197,12 +197,13 @@ between 0 andn $\sqrt{3}$ (inclusive). The second and third values are real numbers between 0 and 1 (inclusive). -\subsection {Standard Color Names} +\subsection {Standard Color Names and Constants} -Table~\ref{color-names} lists all the provided color constants. Application -programs can define other colors; these are provided because they are commonly -used in the X Windows community, not because there is anything special about -these particular colors. This table is a subset of the color listed in the file +Table~\ref{color-names} lists the commonly provided color names that can be +looked up with \cl{find-named-color}. Application programs can define other +colors; these are provided because they are commonly used in the X Windows +community, not because there is anything special about these particular colors. +This table is a subset of the color listed in the file \cl{/X11/R4/mit/rgb/rgb.txt}, from the X11 R4 distribution. \begin{table} @@ -210,55 +211,69 @@ these particular colors. This table is a subset of the color listed in the file \vspace{1pc} \cl{ \begin{tabular}{lllll} -+alice-blue+ & +antique-white+ & +aquamarine+ \\ -+azure+ & +beige+ & +bisque+ \\ -+black+ & +blanched-almond+ & +blue+ \\ -+blue-violet+ & +brown+ & +burlywood+ \\ -+cadet-blue+ & +chartreuse+ & +chocolate+ \\ -+coral+ & +cornflower-blue+ & +cornsilk+ \\ -+cyan+ & +dark-goldenrod+ & +dark-green+ \\ -+dark-khaki+ & +dark-olive-green+ & +dark-orange+ \\ -+dark-orchid+ & +dark-salmon+ & +dark-sea-green+ \\ -+dark-slate-blue+ & +dark-slate-gray+ & +dark-turquoise+ \\ -+dark-violet+ & +deep-pink+ & +deep-sky-blue+ \\ -+dim-gray+ & +dodger-blue+ & +firebrick+ \\ -+floral-white+ & +forest-green+ & +gainsboro+ \\ -+ghost-white+ & +gold+ & +goldenrod+ \\ -+gray+ & +green+ & +green-yellow+ \\ -+honeydew+ & +hot-pink+ & +indian-red+ \\ -+ivory+ & +khaki+ & +lavender+ \\ -+lavender-blush+ & +lawn-green+ & +lemon-chiffon+ \\ -+light-blue+ & +light-coral+ & +light-cyan+ \\ -+light-goldenrod+ & +light-goldenrod-yellow+ & +light-gray+ \\ -+light-pink+ & +light-salmon+ & +light-sea-green+ \\ -+light-sky-blue+ & +light-slate-blue+ & +light-slate-gray+ \\ -+light-steel-blue+ & +light-yellow+ & +lime-green+ \\ -+linen+ & +magenta+ & +maroon+ \\ -+medium-aquamarine+ & +medium-blue+ & +medium-orchid+ \\ -+medium-purple+ & +medium-sea-green+ & +medium-slate-blue+ \\ -+medium-spring-green+ & +medium-turquoise+ & +medium-violet-red+ \\ -+midnight-blue+ & +mint-cream+ & +misty-rose+ \\ -+moccasin+ & +navajo-white+ & +navy-blue+ \\ -+old-lace+ & +olive-drab+ & +orange+ \\ -+orange-red+ & +orchid+ & +pale-goldenrod+ \\ -+pale-green+ & +pale-turquoise+ & +pale-violet-red+ \\ -+papaya-whip+ & +peach-puff+ & +peru+ \\ -+pink+ & +plum+ & +powder-blue+ \\ -+purple+ & +red+ & +rosy-brown+ \\ -+royal-blue+ & +saddle-brown+ & +salmon+ \\ -+sandy-brown+ & +sea-green+ & +seashell+ \\ -+sienna+ & +sky-blue+ & +slate-blue+ \\ -+slate-gray+ & +snow+ & +spring-green+ \\ -+steel-blue+ & +tan+ & +thistle+ \\ -+tomato+ & +turquoise+ & +violet+ \\ -+violet-red+ & +wheat+ & +white+ \\ -+white-smoke+ & +yellow+ & +yellow-green+ \\ +alice-blue & antique-white & aquamarine \\ +azure & beige & bisque \\ +black & blanched-almond & blue \\ +blue-violet & brown & burlywood \\ +cadet-blue & chartreuse & chocolate \\ +coral & cornflower-blue & cornsilk \\ +cyan & dark-goldenrod & dark-green \\ +dark-khaki & dark-olive-green & dark-orange \\ +dark-orchid & dark-salmon & dark-sea-green \\ +dark-slate-blue & dark-slate-gray & dark-turquoise \\ +dark-violet & deep-pink & deep-sky-blue \\ +dim-gray & dodger-blue & firebrick \\ +floral-white & forest-green & gainsboro \\ +ghost-white & gold & goldenrod \\ +gray & green & green-yellow \\ +honeydew & hot-pink & indian-red \\ +ivory & khaki & lavender \\ +lavender-blush & lawn-green & lemon-chiffon \\ +light-blue & light-coral & light-cyan \\ +light-goldenrod & light-goldenrod-yellow & light-gray \\ +light-pink & light-salmon & light-sea-green \\ +light-sky-blue & light-slate-blue & light-slate-gray \\ +light-steel-blue & light-yellow & lime-green \\ +linen & magenta & maroon \\ +medium-aquamarine & medium-blue & medium-orchid \\ +medium-purple & medium-sea-green & medium-slate-blue \\ +medium-spring-green & medium-turquoise & medium-violet-red \\ +midnight-blue & mint-cream & misty-rose \\ +moccasin & navajo-white & navy-blue \\ +old-lace & olive-drab & orange \\ +orange-red & orchid & pale-goldenrod \\ +pale-green & pale-turquoise & pale-violet-red \\ +papaya-whip & peach-puff & peru \\ +pink & plum & powder-blue \\ +purple & red & rosy-brown \\ +royal-blue & saddle-brown & salmon \\ +sandy-brown & sea-green & seashell \\ +sienna & sky-blue & slate-blue \\ +slate-gray & snow & spring-green \\ +steel-blue & tan & thistle \\ +tomato & turquoise & violet \\ +violet-red & wheat & white \\ +white-smoke & yellow & yellow-green \\ \end{tabular}} \caption{\label{color-names} Standard color names.} \vspace{1pc} \hrule \end{table} +In addition, the following color constants are provided. + +\defconst {+red+} +\defconst {+green+} +\defconst {+blue+} +\defconst {+cyan+} +\defconst {+magenta+} +\defconst {+yellow+} +\defconst {+black+} +\Defconst {+white+} + +Constants corresponding to the usual definitions of red, green, blue, cyan, +magenta, yellow, black, and white. + \subsection {Contrasting Colors} @@ -321,7 +336,7 @@ implementation might implement color blending and unsaturated colors by stippling, although it is preferred, when possible, for a viewport to display a uniform color as a uniform color rather than as a perceptible stipple. -\Defun {opacityp} {object} +\Defpredicate {opacityp} {object} Returns \term{true} if \arg{object} is an \term{opacity}, otherwise returns \term{false}. @@ -335,6 +350,11 @@ Returns a member of class \cl{opacity} whose opacity is \arg{value}, which is a real number in the range from 0 to 1 (inclusive), where 0 is fully transparent and 1 is fully opaque. +\Defconst {+transparent-ink+} + +An fully transparent ink, that is, an opacity whose value is 0. This is +typically used as the ``background'' ink in a call to \cl{make-pattern}. + The following function returns the sole component of an opacity. This is the only function in the opacity protocol. All subclasses of \cl{opacity} must diff --git a/specs/commands.tex b/specs/commands.tex index 94adb171..6b10dce8 100644 --- a/specs/commands.tex +++ b/specs/commands.tex @@ -188,8 +188,9 @@ does not contain any items inherited from superior command tables. \item A menu that associates menu names to command menu items (used to support interaction via command menus). The command menu items can invoke commands or -sub-menus. The menu does not contain any command menu items inherited from -superior command tables. +sub-menus. By default, the menu does not contain any command menu items +inherited from superior command tables, although this can be overridden by the +\cl{:inherit-menu} option to \cl{define-command-table}. \end{itemize} We say that a command is \concept{present} in a command table when it has been @@ -204,7 +205,7 @@ The protocol class that corresponds to command tables. \IfYouWantClass {a} {command table} {command-table} \Mutable -\Defun {command-table-p} {object} +\Defpredicate {command-table-p} {object} Returns \term{true} if \arg{object} is a \term{command table}, otherwise returns \term{false}. @@ -231,7 +232,7 @@ Returns a list of the command tables from which the \term{command table} \ReadOnly -\Defmacro {define-command-table} {name \key inherit-from menu} +\Defmacro {define-command-table} {name \key inherit-from menu inherit-menu} Defines a command table whose name is the symbol \arg{name}. The new command table inherits from all of the command tables specified by \arg{inherit-from}, @@ -242,6 +243,11 @@ to inherit from CLIM's global command table. (This command table contains such things as the ``menu'' translator that is associated with the right-hand button on pointers.) +If \arg{inherit-menu} is \term{true}, the new command table will inherit the +menu items and keystroke accelerators from all of the inherited command tables. +If it is \term{false} (the default), no menu items or keystroke accelerators +will be inherited. + \arg{menu} can be used to specify a menu for the command table. The value of \arg{menu} is a list of clauses. Each clause is a list with the syntax \cl{(\arg{string} \arg{type} \arg{value} \key \arg{keystroke} @@ -257,15 +263,16 @@ the existing command table alone. None of \cl{define-command-table}'s arguments are evaluated. -\Defun {make-command-table} {name \key inherit-from menu (errorp t)} +\Defun {make-command-table} {name \key inherit-from menu inherit-menu (errorp t)} -Creates a command table named \arg{name}. \arg{inherit-from} and \arg{menu} are -the same as for \cl{define-command-table}. \cl{make-command-table} does not -implicitly include CLIM's global command table in the inheritance list for the -new command table. If the command table already exists and \arg{errorp} is -\term{true}, the \cl{command-table-already-exists} error will be signalled. If -the command table already exists and \arg{errorp} is \term{false}, then the old -command table will be discarded. The returned value is the command table. +Creates a command table named \arg{name}. \arg{inherit-from}, \arg{menu}, and +\arg{inherit-menu} are the same as for \cl{define-command-table}. +\cl{make-command-table} does not implicitly include CLIM's global command table +in the inheritance list for the new command table. If the command table already +exists and \arg{errorp} is \term{true}, the \cl{command-table-already-exists} +error will be signalled. If the command table already exists and \arg{errorp} +is \term{false}, then the old command table will be discarded. The returned +value is the command table. \Defun {find-command-table} {name \key (errorp t)} @@ -281,6 +288,10 @@ signalled. The class that is the superclass of the following four conditions. This class is a subclass of \cl{error}. +\cl{command-table-error} and its subclasses must handle the \cl{:format-string} +and \cl{:format-arguments} initargs, which are used to specify a control string +and arguments for a call to \cl{format}. + \Deferror {command-table-not-found} The error that is signalled by such functions as \cl{find-command-table} when a @@ -315,12 +326,9 @@ the \term{command table designator} \arg{command-table}. \cl{t}, or a string. When it is \cl{nil}, the command will not be available via command-line interactions. When it is a string, that string is the command-line name for the command. When it is \cl{t}, the command-line name is generated -automatically. (The automatically generated name consists of the command's name -with the hyphens replaced by spaces, and the words capitalized; furthermore, if -there is a prefix of ``COM-'', the prefix is removed. For example, if the -command name is \cl{com-show-file}, the command-line name will be ``Show -File''.) For the purposes of command-line name lookup, the character case of -\arg{name} is ignored. +automatically by calling \cl{command-name-from-symbol} on \arg{command-name}. +For the purposes of command-line name lookup, the character case of \arg{name} +is ignored. \arg{menu} is a menu item for the command, and can be \cl{nil}, \cl{t}, a string, or a cons. When it is \cl{nil}, the command will not be available via @@ -352,6 +360,14 @@ by the \term{command table designator} \arg{command-table}. If the command is not present in the command table and \arg{errorp} is \term{true}, the \cl{command-not-present} error will be signalled. +\Defun {command-name-from-symbol} {symbol} + +Generates a string suitable for use as a command-line name from the symbol +\arg{symbol}. The string consists the symbol name with the hyphens replaced by +spaces, and the words capitalized. If the symbol name is prefixed by ``COM-'', +the prefix is removed. For example, if the symbol is \cl{com-show-file}, the +result string will be ``Show File''. + \Defmacro {do-command-table-inheritance} {(command-table-var command-table) \body body} @@ -609,7 +625,7 @@ Returns a list of the options for the command menu item \arg{menu-item}. If \Defgeneric {display-command-table-menu} {command-table stream \key max-width max-height n-rows n-columns - x-spacing y-spacing initial-spacing + x-spacing y-spacing initial-spacing row-wise (cell-align-x \cl{:left}) (cell-align-y \cl{:top}) (move-cursor \cl{t})} @@ -619,8 +635,9 @@ platform dependent manner, such as using the menu bar on a Macintosh. \arg{command-table} is a \term{command table designator}. \arg{max-width}, \arg{max-height}, \arg{n-rows}, \arg{n-columns}, -\arg{x-spacing}, \arg{y-spacing}, \arg{initial-spacing}, \arg{cell-align-x}, -\arg{cell-align-y}, and \arg{move-cursor} are as for \cl{formatting-item-list}. +\arg{x-spacing}, \arg{y-spacing}, \arg{row-wise}, \arg{initial-spacing}, +\arg{cell-align-x}, \arg{cell-align-y}, and \arg{move-cursor} are as for +\cl{formatting-item-list}. \Defun {menu-choose-command-from-command-table} {command-table \key associated-window default-style label @@ -703,7 +720,7 @@ programmer requires this behavior, he should examine the type of the command menu item to see if it is \cl{:menu}. -\Defun {find-keystroke-item} {gesture command-table \key (errorp t)} +\Defun {find-keystroke-item} {gesture command-table \key test (errorp t)} Given a keyboard gesture \arg{gesture} and a command table, returns two values, the command menu item associated with the gesture and the command table in which @@ -712,17 +729,15 @@ returned value will always be \arg{command-table}.) \ReadOnly -Note that \arg{gesture} may be either a keyboard gesture name of a gesture -object. When it is a gesture name, \cl{eql} will be used to compare the -supplied gesture to the gesture names stored in the command table's menu. When -it is a gesture object, \cl{event-matches-gesture-name-p} will be used to do the -comparison. +\arg{test} is the test used to compare the supplied gesture to the gesture name +in the command table. The supplied gesture will generally be an event object, +so the default for \arg{test} is \cl{event-matches-gesture-name-p}. If the keystroke accelerator is not present in \arg{command-table} and \arg{errorp} is \term{true}, then the \cl{command-not-present} error will be signalled. \arg{command-table} is a \term{command table designator}. -\Defun {lookup-keystroke-item} {gesture command-table} +\Defun {lookup-keystroke-item} {gesture command-table \key test} Given a keyboard gesture \arg{gesture} and a command table, returns two values, the command menu item associated with the gesture and the command table in which @@ -736,7 +751,11 @@ cannot be found in the command table or any of the command tables from which it inherits, \cl{lookup-keystroke-item} will return \cl{nil}. \arg{command-table} is a \term{command table designator}. -\Defun {lookup-keystroke-command-item} {gesture command-table \key numeric-arg} +\arg{test} is the test used to compare the supplied gesture to the gesture name +in the command table. The supplied gesture will generally be an event object, +so the default for \arg{test} is \cl{event-matches-gesture-name-p}. + +\Defun {lookup-keystroke-command-item} {gesture command-table \key test numeric-arg} Given a keyboard gesture \arg{gesture} and a command table, returns the command associated with the keystroke, or \arg{gesture} if no command is found. Note @@ -748,6 +767,10 @@ This is like \cl{find-keystroke-item}, except that only keystrokes that map to an enabled application command will be matched. \arg{command-table} is a \term{command table designator}. +\arg{test} is the test used to compare the supplied gesture to the gesture name +in the command table. The supplied gesture will generally be an event object, +so the default for \arg{test} is \cl{event-matches-gesture-name-p}. + \arg{numeric-arg} (which defaults to 1) is substituted into the resulting command for any occurrence of \cl{*numeric-argument-marker*} in the command. This is intended to allow programmers to define keystroke accelerators that take @@ -827,7 +850,7 @@ read a command. These are all mediated by the Command Processor. \Defun {read-command} {command-table - \key (stream *query-io*) + \key (stream *standard-input*) command-parser command-unparser partial-command-parser use-keystrokes} @@ -836,8 +859,9 @@ read a command. These are all mediated by the Command Processor. \term{command table designator}. \arg{command-parser} must be a function of two arguments, a command table and a -stream. It reads a command from the user and returns a command object. The -default value for \arg{command-parser} is the value of \cl{*command-parser*}. +stream. It reads a command from the user and returns a command object, or +\cl{nil} if an empty command line was read. The default value for +\arg{command-parser} is the value of \cl{*command-parser*}. \arg{command-unparser} must be a function of three arguments, a command table, a stream, and a command to ``unparse''. It prints a textual description of the @@ -876,7 +900,7 @@ context. \arg{command-table} is a \term{command table designator}. \arg{body} may have zero or more declarations as its first forms. \Defun {read-command-using-keystrokes} {command-table keystrokes - \key (stream *query-io*) + \key (stream *standard-input*) command-parser command-unparser partial-command-parser} diff --git a/specs/conventions.tex b/specs/conventions.tex index 2291dab9..d5daa5a1 100644 --- a/specs/conventions.tex +++ b/specs/conventions.tex @@ -237,7 +237,9 @@ programmer would like to invoke \cl{(setf~output-record-position)}. Normally however, \cl{setf} only takes a single value with which to modify the specified place. CLIM provides a ``multiple value'' version of \cl{setf} that allows an expression that returns multiple values to be used in updating the specified -place. In this specification, this facility will be referred to as \cl{setf*}. +place. In this specification, this facility will be referred to as \cl{setf*} +in the guise of function names such as \cl{(setf* output-record-position)}, even +though \cl{setf*} is not actually a defined form. For example, the modifying function for \cl{output-record-position} might be called in either of the following two ways: @@ -251,6 +253,11 @@ called in either of the following two ways: The second form works because \cl{output-record-position} itself returns two values. +Some CLIM implementations may not support \cl{setf*} due to restrictions imposed +by the underlying Lisp implementation. In this case, programmers may use +special ``setter'' function instead. In the above example, +\cl{output-record-set-position} is the ``setter'' function. + \section {Sheet, Stream, or Medium Arguments to Macros} @@ -260,12 +267,12 @@ In CLIM, this argument must be a variable bound to a sheet, stream, or medium; it may not be an arbitrary form that evaluates to a sheet, stream, or medium. \cl{t} and sometimes \cl{nil} are usually allowed as special cases; this causes the variable to be interpreted as a reference to another stream variable -(usually \cl{*standard-output*} for output macros, or \cl{*query-io*} for input -macros). Note that, while the variable outside the macro form and the variable -inside the body share the same name, they cannot be assumed to be the same -reference. That is, the macro is free to create a new binding for the variable. -Thus, the following code fragment will not necessarily affect the value of -\arg{stream} outside the \cl{formatting-table} form: +(usually \cl{*standard-output*} for output macros, or \cl{*standard-input*} for +input macros). Note that, while the variable outside the macro form and the +variable inside the body share the same name, they cannot be assumed to be the +same reference. That is, the macro is free to create a new binding for the +variable. Thus, the following code fragment will not necessarily affect the +value of \arg{stream} outside the \cl{formatting-table} form: \begin{verbatim} (formatting-table (stream) diff --git a/specs/designs.tex b/specs/designs.tex index 9f10e8b7..4eb02791 100644 --- a/specs/designs.tex +++ b/specs/designs.tex @@ -165,6 +165,12 @@ different portion of each of those designs shows through in each tile. \MayCaptureInputs +\defgeneric {pattern-width} {pattern} +\Defgeneric {pattern-height} {pattern} + +These functions return the width and height, respectively, of the \term{pattern} +\arg{pattern}. + \Defun {make-stencil} {array} @@ -228,9 +234,9 @@ described in the sections on those designs. \section {Arbitrary Designs} -\Defgeneric {draw-design} {sheet design \key \DrawingOptions \LineJointCapOptions\ \TextOptions} +\Defgeneric {draw-design} {medium design \key \DrawingOptions \LineJointCapOptions\ \TextOptions} -Draws the \term{design} \arg{design} onto the \term{sheet} \arg{sheet}. This is +Draws the \term{design} \arg{design} onto the \term{medium} \arg{medium}. This is defined to work for all types of regions and designs, although in practice some implementations may be more restrictive. \arg{ink}, \arg{transformation}, and \arg{clipping-region} are used to modify the medium. The other drawing @@ -239,13 +245,13 @@ being drawn. For instance, if \arg{design} is a path, then line style options may be supplied. If \arg{design} is an area, \cl{draw-design} paints the specified region of the -drawing plane with current ink of the sheet's medium. If \arg{design} is a +drawing plane with medium's current ink. If \arg{design} is a path, \cl{draw-design} strokes the path with medium's current ink under control of the line-style. If \arg{design} is a point, \cl{draw-design} is the same as \cl{draw-point}. If \arg{design} is a color or an opacity, \cl{draw-design} paints the entire -drawing plane (subject to the clipping region of the sheet's medium). +drawing plane (subject to the clipping region of the medium). If \arg{design} is \cl{+nowhere+}, \cl{draw-design} has no effect. @@ -269,9 +275,9 @@ created by a geometric object constructor. \end{itemize} -\Defun {draw-pattern*} {sheet pattern x y \key clipping-region transformation} +\Defun {draw-pattern*} {medium pattern x y \key clipping-region transformation} -Draws the pattern \arg{pattern} on the \term{sheet} \arg{sheet} at the +Draws the pattern \arg{pattern} on the \term{medium} \arg{medium} at the position $(x,y)$. \arg{pattern} is any design created by \cl{make-pattern}. \arg{clipping-region} and \arg{transformation} are as for \cl{with-drawing-options} or any of the drawing functions. @@ -294,16 +300,16 @@ and scaled pattern constructed from the raster array and raster color map. pattern. \begin{verbatim} -(defun draw-pattern* (sheet pattern x y &key clipping-region transformation) +(defun draw-pattern* (medium pattern x y &key clipping-region transformation) (check-type pattern pattern) (let ((width (pattern-width pattern)) (height (pattern-height pattern))) (if (or clipping-region transformation) - (with-drawing-options (sheet :clipping-region clipping-region - :transformation transformation) - (draw-rectangle* sheet x y (+ x width) (+ y height) + (with-drawing-options (medium :clipping-region clipping-region + :transformation transformation) + (draw-rectangle* medium x y (+ x width) (+ y height) :filled t :ink pattern)) - (draw-rectangle* sheet x y (+ x width) (+ y height) + (draw-rectangle* medium x y (+ x width) (+ y height) :filled t :ink pattern)))) \end{verbatim} @@ -330,7 +336,7 @@ Specify \cl{:ink (make-rectangular-tile (make-pattern \arg{array} \arg{colors})) \paragraph {Drawing a ``bitmap''.} -Use \cl{(draw-design \arg{sheet} (make-pattern \arg{bit-array} (list +Use \cl{(draw-design \arg{medium} (make-pattern \arg{bit-array} (list +background-ink+ +foreground-ink+)) :transformation (make-translation-transformation \arg{x} \arg{y}))}. diff --git a/specs/dialogs.tex b/specs/dialogs.tex index 89f5515a..fe355710 100644 --- a/specs/dialogs.tex +++ b/specs/dialogs.tex @@ -10,9 +10,12 @@ by the host?} \Defmacro {accepting-values} {(\optional stream - \key own-window exit-boxes initially-select-query-identifier - resynchronize-every-pass - label x-position y-position frame-class) + \key own-window exit-boxes + initially-select-query-identifier modify-initial-query + resynchronize-every-pass resize-frame + align-prompts label scroll-bars + x-position y-position width height + command-table frame-class) \body body} Builds a dialog for user interaction based on calls to \cl{accept} within @@ -25,25 +28,32 @@ whatever values the body returns. If ``abort'' is selected, \arg{stream} is an interactive stream that \cl{accepting-values} will use to build up the dialog. The \arg{stream} argument is not evaluated, and must be a symbol that is bound to a stream. If \arg{stream} is \cl{t} (the default), -\cl{*query-io*} is used. +\cl{*standard-input*} is used. \arg{body} is the body of the dialog, which contains calls to \cl{accept} that will be intercepted by \cl{accepting-values} and used to build up the dialog. \arg{body} may have zero or more declarations as its first forms. -An \cl{accepting-values} dialog is implemented as a looping structure. First, -\arg{body} is evaluated in order to collect the output. While the body is being -evaluated, all calls to \cl{accept} call the \cl{accept-present-default} -presentation methods instead of calling the \cl{accept} presentation methods. -The output is then displayed (preferably using incremental redisplay in order to -avoid unnecessary redisplay of unchanged output). Then \cl{accepting-values} -awaits a user gesture, such as clicking on one of the fields of the dialog. -When the user clicks on a field, \cl{accepting-values} reads a new value for -that field using \cl{accept} and replaces the old value with the new value. -Then the loop is started again, until the user either exits or aborts from the -dialog. - -Because of this looping structure, \cl{accepting-values} needs to be able to +An \cl{accepting-values} dialog is implemented as an application frame with a +looping structure. First, \arg{body} is evaluated in order to collect the +output. While the body is being evaluated, all calls to \cl{accept} call the +\cl{accept-present-default} presentation methods instead of calling the +\cl{accept} presentation methods. The output is then displayed, preferably +using incremental redisplay in order to avoid unnecessary redisplay of unchanged +output. If \arg{align-prompts} is \term{true} (the default is \cl{nil}), then +the fields of the dialog will be displayed within a call to +\cl{formatting-table} so that the prompts are aligned vertically on their +right-hand sides and the input fields are aligned on their left-hand sides. +This option is intended to support toolkits where users expect dialogs to have +this sort of layout. + +After \cl{accepting-values} has displayed all of the fields, it awaits a user +gesture, such as clicking on one of the fields of the dialog. When the user +clicks on a field, \cl{accepting-values} reads a new value for that field using +\cl{accept} and replaces the old value with the new value. Then the loop is +started again, until the user either exits or aborts from the dialog. + +Because of its looping structure, \cl{accepting-values} needs to be able to uniquely identify each call to \cl{accept} in the body of the dialog. The \concept{query identifier} is used to identify the calls to \cl{accept}. The query identifier for a call to \cl{accept} is computed on each loop through the @@ -68,6 +78,13 @@ record for each field in the dialog will probably need a mapping back to the query identifier. A mediating object (a ``query object'') is also useful, for instance, as a place to store the ``changed-p'' flag. +The class of the application frame created by \cl{accepting-values} will be +\cl{accept-values} or a subclass of \cl{accept-values}. Programmers can use a +class of their own by supplying the name of a class via the \arg{frame-class} +argument. CLIM will use the command table \cl{accept-values} as the command +table for \cl{accepting-values}. Programmers can supply a command table of their +own by supplying the \arg{command-table} argument. + When \arg{own-window} is non-\cl{nil}, the dialog will appear in its own ``popped-up'' window. In this case the initial value of \arg{stream} is a window with which the dialog is associated. (This is similar to the @@ -112,7 +129,9 @@ dialog should be pre-selected when the user interaction begins. The field to be selected is tagged by the \cl{:query-identifier} option to \cl{accept}. When the initial display is output, the input editor cursor appears after the prompt of the tagged field, just as if the user had selected that field by clicking on -it. The default value, if any, for the selected field is not displayed. +it. The default value, if any, for the selected field is not displayed. When +\arg{modify-initial-query} is \term{true}, the initially selected field is +selected for modification rather than for replacement; the default is \cl{nil}. \arg{resynchronize-every-pass} is a boolean option specifying whether earlier queries depend on later values; the default is \term{false}. When it is @@ -121,8 +140,12 @@ each user interaction. This has the effect of ensuring that, when the value of some field of a dialog depends on the value of another field, all of the displayed fields will be up to date. +When \arg{resize-frame} is \term{true}, own-window dialogs will be resized after +each pass through the redisplay loop. The default is \cl{nil}. + \arg{label} is as for \cl{menu-choose}. \arg{x-position} and \arg{y-position} -are as for \cl{menu-choose-from-drawer}. +are as for \cl{menu-choose-from-drawer}. \arg{width} and \arg{height} are real +numbers that specify the initial width and height of own-window dialogs. \Defframe {accept-values} @@ -163,8 +186,8 @@ to \cl{invoke-accept-values-command-button}, supplying a function that executes \arg{body} as the \arg{continuation} argument to \cl{accept-values-command-button}. The \arg{stream} argument is not evaluated, and must be a symbol that is bound -to a stream. If \arg{stream} is \cl{t} (the default), \cl{*query-io*} is used. -\arg{body} may have zero or more declarations as its first forms. +to a stream. If \arg{stream} is \cl{t} (the default), \cl{*standard-input*} is +used. \arg{body} may have zero or more declarations as its first forms. \Defmethod {invoke-accept-values-command-button} {stream continuation view prompt diff --git a/specs/drawing-options.tex b/specs/drawing-options.tex index 2e701f53..52e638ff 100644 --- a/specs/drawing-options.tex +++ b/specs/drawing-options.tex @@ -361,6 +361,16 @@ The \arg{medium} argument is not evaluated, and must be a symbol that is bound to a sheet or medium. If \arg{medium} is \cl{t}, \cl{*standard-output*} is used. \arg{body} may have zero or more declarations as its first forms. +\Defmacro {with-identity-transformation} {(medium) \body body} + +Establishes the identity transformation on the \term{medium} designated +by \arg{medium}. + +The \arg{medium} argument is not evaluated, and must be a symbol that is bound +to a sheet or medium. If \arg{medium} is \cl{t}, \cl{*standard-output*} is +used. \arg{body} may have zero or more declarations as its first forms. + + \subsection {Establishing Local Coordinate Systems} @@ -401,7 +411,7 @@ substrate on how to perform the rendering. The protocol class for line styles. \IfYouWantClass {a} {line style} {line-style} -\Defun {line-style-p} {object} +\Defpredicate {line-style-p} {object} Returns \term{true} if \arg{object} is a \term{line style}, otherwise returns \term{false}. diff --git a/specs/encapsulating-streams.tex b/specs/encapsulating-streams.tex index 09eb6d78..49ccdccc 100644 --- a/specs/encapsulating-streams.tex +++ b/specs/encapsulating-streams.tex @@ -30,7 +30,7 @@ The protocol class that corresponds to an encapsulating stream. \IfYouWantClass {an} {encapsulating stream} {encapsulating-stream} \Mutable -\Defun {encapsulating-stream-p} {object} +\Defpredicate {encapsulating-stream-p} {object} Returns \term{true} if \arg{object} is an \term{encapsulating stream}, otherwise returns \term{false}. @@ -42,7 +42,8 @@ specify the stream to be encapsulated. \Defclass {standard-encapsulating-stream} -This class provides a standard implementation of an encapsulating stream. +This instantiable class provides a standard implementation of an encapsulating +stream. \subsection {Encapsulating Stream Protocol} diff --git a/specs/extended-input.tex b/specs/extended-input.tex index 0740bde4..fb8867f6 100644 --- a/specs/extended-input.tex +++ b/specs/extended-input.tex @@ -29,6 +29,11 @@ Returns the next character available in the \term{input stream} \arg{stream}, or \cl{:eof} if the stream is at end-of-file. If no character is available this function will wait until one becomes available. +\Defgeneric {stream-read-char-no-hang} {stream} + +Like \cl{stream-read-char}, except that if no character is available the +function returns \term{false}. + \Defgeneric {stream-unread-char} {stream character} Places the character \arg{character} back into the \term{input stream} @@ -36,11 +41,6 @@ Places the character \arg{character} back into the \term{input stream} will return the unread character. The character supplied must be the most recent character read from the stream. -\Defgeneric {stream-read-char-no-hang} {stream} - -Like \cl{stream-read-char}, except that if no character is available the -function returns \term{false}. - \Defgeneric {stream-peek-char} {stream} Returns the next character available in the \term{input stream} \arg{stream}. @@ -78,7 +78,7 @@ The protocol class for CLIM extended input streams. This is a subclass of \cl{input-stream}. \IfYouWantClass {an} {extended input stream} {extended-input-stream} -\Defun {extended-input-stream-p} {object} +\Defpredicate {extended-input-stream-p} {object} Returns \term{true} if \arg{object} is a CLIM \term{extended input stream}, otherwise returns \term{false}. @@ -118,29 +118,12 @@ on one of them is available to an input call on any of the streams. The input buffer must be vector with a fill pointer capable of holding general input gesture objects (such as characters and event objects). -\Defgeneric {stream-pointers} {stream} - -Returns the list of pointer objects corresponding to the pointing devices of the -port associated with \arg{stream}. -\ReadOnly - -\Defgeneric {stream-primary-pointer} {stream} -\Defgeneric {(setf stream-primary-pointer)} {pointer stream} - -Returns (or sets) the pointer object corresponding to the primary pointing -device of the console. - -{\bf Note:} CLIM currently supports only a single pointer for any port. -Therefore, the length of the list returned by \cl{stream-pointers} will always -be one, and \cl{stream-primary-pointer} will always return an object that is the -only element of that list. - \Defgeneric {stream-pointer-position} {stream \key pointer} Returns the current position of the pointing device \arg{pointer} for the \term{extended input stream} \arg{stream} as two values, the $x$ and $y$ positions in the stream's drawing surface coordinate system. If \arg{pointer} -is not supplied, it defaults to the \cl{stream-primary-pointer} of the stream. +is not supplied, it defaults to \cl{port-pointer} of the stream's port. \Defgeneric {(setf* stream-pointer-position)} {x y stream \key pointer} @@ -148,16 +131,14 @@ Sets the position of the pointing device for the \term{extended input stream} \arg{stream} to \arg{x} and \arg{y}, which are integers. \arg{pointer} is as for \cl{stream-pointer-position}. +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{stream-set-pointer-position}. \Defgeneric {stream-set-input-focus} {stream} -Sets the ``input focus'' to the \term{extended input stream} \arg{stream} and -returns the old input focus as its value. - -\Defgeneric {stream-restore-input-focus} {stream old-focus} - -Restores the ``input focus'' of the \term{extended input stream} \arg{stream} to -\arg{old-focus}. +Sets the ``input focus'' to the \term{extended input stream} \arg{stream} by +changing the value of \cl{port-keyboard-input-focus} and returns the old input +focus as its value. \Defmacro {with-input-focus} {(stream) \body body} @@ -209,9 +190,9 @@ condition will be signalled. \cl{stream-read-gesture} works by invoking \cl{stream-input-wait} on \arg{stream}, \arg{input-wait-test}, and \arg{timeout}, and then processing the -input, if there is any. \cl{:around} methods on this generic function invoke a -gesture preprocessing mechanism on every gesture. For a discussion of this -facility, see the Section~\ref{gesture-preproc}. +input, if there is any. \cl{:around} methods on this generic function can be +used to implement some sort of a gesture preprocessing mechanism on every +gesture; CLIM's input editor will typically be implemented this way. \arg{timeout} is either \cl{nil} or an integer that specifies the number of seconds that \cl{stream-read-gesture} will wait for input to become available. @@ -275,7 +256,9 @@ the \cl{:abort} gesture name. \Defcondition {abort-gesture} This condition is signalled by \cl{read-gesture} whenever an abort gesture (one -of the gestures in \cl{*abort-gestures*} is read from the user. +of the gestures in \cl{*abort-gestures*} is read from the user. This condition +will handle the \cl{:event} initarg, which is used to supply the event +corresponding to the abort gesture. \Defgeneric {abort-gesture-event} {condition} @@ -290,12 +273,15 @@ The global value for this is \cl{nil}. \Defcondition {accelerator-gesture} This condition is signalled by \cl{read-gesture} whenever an keystroke -accelerator gesture (one of the gestures in \cl{*accelerator-gestures*} is -read from the user. +accelerator gesture (one of the gestures in \cl{*accelerator-gestures*} is read +from the user. This condition will handle the \cl{:event} and the +\cl{:numeric-argument} initargs, which are used to supply the event +corresponding to the abort gesture and the accumulated numeric argument (which +defaults to 1). \Defgeneric {accelerator-gesture-event} {condition} -Returns the event that cause the accelerator gesture condition to be signalled. +Returns the event that caused the accelerator gesture condition to be signalled. \cl{condition} is an object of type \cl{accelerator-gesture}. \Defgeneric {accelerator-gesture-numeric-argument} {condition} @@ -345,7 +331,7 @@ gesture that corresponds to a standard printing character, it may be enough to represent the gesture object as a character. -\Defmacro {define-gesture-name} {name type gesture-spec} +\Defmacro {define-gesture-name} {name type gesture-spec \key (unique \cl{t})} Defines a new gesture named by the symbol \arg{name}. \arg{type} is the type of gesture being created, and must be one of the symbols described below. @@ -353,6 +339,9 @@ gesture being created, and must be one of the symbols described below. gesture; its syntax depends on the value of \arg{type}. \cl{define-gesture-name} must expand into a call to \cl{add-gesture-name}. +If \arg{unique} is \term{true}, all old gestures named by \arg{name} are first +removed. \arg{unique} defaults to \cl{t}. + None of the arguments to \cl{define-gesture-name} is evaluated. \Defun {add-gesture-name} {name type gesture-spec \key unique} @@ -378,7 +367,7 @@ naming the character (\cl{:newline}, \cl{:linefeed}, \cl{:return}, \cl{:tab}, \cl{:backspace}, \cl{:page}, and \cl{:rubout}). CLIM implementations may extend the set of key names on a per-port basic, but should choose a port-specific package. For example, the Genera port might such gestures as include -\cl{clim-genera:help} and \cl{clim-genera:complete}. +\cl{genera-clim:help} and \cl{genera-clim:complete}. The names of the modifier keys have been chosen to be uniform across all platforms, even though not all platforms will have keys on the keyboard with @@ -436,6 +425,12 @@ the same on every port, and only the mappings differ from port to port. Some ports may define additional gesture names, but they will simply not be mapped on other ports. Is this a reasonable assumption?} +\Defun {make-modifier-state} {\rest modifiers} + +Given a list of modifier state names, this creates an integer that serves as a +modifier key state. The legal modifier state names are \cl{:shift}, +\cl{:control}, \cl{:meta}, \cl{:super}, and \cl{:hyper}. + \subsection {Standard Gesture Names} @@ -506,7 +501,7 @@ The protocol class that corresponds to a pointing device. \IfYouWantClass {a} {pointer} {pointer} \Mutable -\Defun {pointerp} {object} +\Defpredicate {pointerp} {object} Returns \term{true} if \arg{object} is a \term{pointer}, otherwise returns \term{false}. @@ -520,19 +515,17 @@ associated. The instantiable class that implements a pointer. -\Defgeneric {pointer-port} {pointer} - -Returns the port with which the \term{pointer} \arg{pointer} is associated. - \defgeneric {pointer-sheet} {pointer} \Defgeneric {(setf pointer-sheet)} {sheet pointer} Returns (or sets) the sheet over which the \term{pointer} \arg{pointer} is located. -\Defgeneric {pointer-buttons} {pointer} +\Defgeneric {pointer-button-state} {pointer} -Returns the state of the buttons of the \term{pointer} \arg{pointer}. This is -represented in the same as \cl{pointer-event-button}. +Returns the current state of the buttons of the \term{pointer} \arg{pointer} as +an integer. This will be a mask consisting of the \cl{logior} of +\cl{+pointer-left-button+}, \cl{+pointer-middle-button+}, and +\cl{+pointer-right-button+}. \Defgeneric {pointer-position} {pointer} @@ -544,6 +537,9 @@ values. Sets the $x$ and $y$ position of the \term{pointer} \arg{pointer} to the specified position. +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{pointer-set-position}. + \defgeneric {pointer-cursor} {pointer} \Defgeneric {(setf pointer-cursor)} {cursor pointer} @@ -551,10 +547,14 @@ A pointer object usually has a visible cursor associated with it. These functions return (or set) the cursor associated with the \term{pointer} \arg{pointer}. +\Defmethod {port} {(pointer \cl{standard-pointer})} + +Returns the port with which \arg{pointer} is associated. + \section {Pointer Tracking} -\Defmacro {tracking-pointer} {(sheet \key pointer multiple-windows +\Defmacro {tracking-pointer} {(sheet \key pointer multiple-window transformp context-type highlight) \body body} @@ -580,7 +580,7 @@ an input sheet or stream. If \arg{sheet} is \cl{t}, \cl{*standard-output*} is used. \arg{body} may have zero or more declarations as its first forms. The \arg{pointer} argument specifies a pointer to track. It defaults to -the primary pointer for the sheet, \cl{(stream-primary-pointer \arg{sheet})}. +the primary pointer for the sheet, \cl{(port-pointer (port \arg{sheet}))}. When the boolean \arg{multiple-windows} is \term{true}, then the pointer will be tracked across multiple windows, otherwise is will be tracked only in the window @@ -602,7 +602,8 @@ When \arg{highlight} is \term{true}, \cl{tracking-pointer} will highlight applicable presentations as the pointer is positioned over them. {highlight} defaults to \term{true} when any of the \cl{:presentation}, \cl{:presentation-button-press}, or \cl{:presentation-button-release} clauses is -supplied, otherwise it defaults to \term{false}. +supplied, otherwise it defaults to \term{false}. See +Chapter~\ref{output-recording} for a complete discussion of presentations. The body of \cl{tracking-pointer} consists of a list of clauses. Each clause is of the form @@ -691,7 +692,8 @@ character typed. \Defgeneric {drag-output-record} {stream output-record - \key repaint erase feedback finish-on-release} + \key repaint erase feedback finish-on-release + multiple-window} Enters an interaction mode in which the user moves the pointer and \arg{output-record} ``follows'' the pointer by being dragged on the \term{output @@ -728,7 +730,11 @@ If the boolean \arg{finish-on-release} is \term{false} (the default), it is \term{true}, \cl{drag-output-record} is exited when the user releases the pointer button currently being held down. -\Defmacro {dragging-output} {(\optional stream \key repaint finish-on-release) +\arg{multiple-window} is as for \cl{tracking-pointer}. + + +\Defmacro {dragging-output} {(\optional stream + \key repaint finish-on-release multiple-window) \body body} Evaluates \arg{body} inside of \cl{with-output-to-output-record} to produce an @@ -743,28 +749,6 @@ to an \term{output recording stream} stream. If \arg{stream} is \cl{t} (the default), \cl{*standard-output*} is used. \arg{body} may have zero or more declarations as its first forms. -\arg{repaint} and \arg{finish-on-release} are as for \cl{drag-output-record}. - - -\section {Gesture Preprocessing\label{gesture-preproc}} - -Every gesture that goes through \cl{stream-read-gesture} gets processed before -it is returned. This allows applications to intercept gestures and alter the -flow of control. Gesture processing is done via a gesture table that associates -each gesture with a function of two arguments, \arg{stream} and \arg{gesture}, -which is applied when the gesture is read. - -\issue {SWM} {What function is ``gesture preprocessing'' meant to fulfill? -At the very least, it needs to specialize on the application frame, or frame -manager, or port, or something.} - -\defun {gesture-processing-handler} {gesture} -\Defun {(setf gesture-processing-handler)} {gesture} +\arg{repaint}, \arg{finish-on-release}, and \arg{multiple-window} are as for +\cl{drag-output-record}. -Manipulate the gesture processing handler for a particular gesture. All pointer -button presses are considered equivalent at this layer; to modify the handler -for pointer button presses, specify \cl{:pointer-button-press} as the -\arg{gesture}. The default values for the handlers for all gestures is -\cl{nil}, meaning there is no handler. The presentation subsystem could be -implemented by installing \cl{input-context-button-press-handler} as the handler -for pointer button presses. diff --git a/specs/extended-output.tex b/specs/extended-output.tex index 7e262d4a..2c5b8233 100644 --- a/specs/extended-output.tex +++ b/specs/extended-output.tex @@ -26,17 +26,6 @@ based on the CLIM output kernel. Writes the character \arg{character} to the \term{output stream} \arg{stream}, and returns \arg{character} as its value. -\Defgeneric {stream-line-column} {stream} - -This function returns the column number where the next character will be written -on the \term{output stream} \arg{stream}. The first column on a line is -numbered 0. - -\Defgeneric {stream-start-line-p} {stream} - -Returns \term{true} if the \term{output stream} \arg{stream} is positioned at -the beginning of a line (that is, column 0), otherwise returns \term{false}. - \Defgeneric {stream-write-string} {stream string \optional (start \cl{0}) end} Writes the string \arg{string} to the \term{output stream} \arg{stream}. If @@ -68,6 +57,17 @@ Like \cl{stream-finish-output}, except that it may immediately return Aborts any outstanding output operation in progress on the \term{output stream} \arg{stream}, and returns \term{false}. +\Defgeneric {stream-line-column} {stream} + +This function returns the column number where the next character will be written +on the \term{output stream} \arg{stream}. The first column on a line is +numbered 0. + +\Defgeneric {stream-start-line-p} {stream} + +Returns \term{true} if the \term{output stream} \arg{stream} is positioned at +the beginning of a line (that is, column 0), otherwise returns \term{false}. + \Defgeneric {stream-advance-to-column} {stream column} Writes enough blank space on the \term{output stream} \arg{stream} so that the @@ -87,14 +87,14 @@ The protocol class for CLIM extended output streams. This is a subclass of \cl{output-stream}. \IfYouWantClass {an} {extended output stream} {extended-output-stream} -\Defun {extended-output-stream-p} {object} +\Defpredicate {extended-output-stream-p} {object} Returns \term{true} if \arg{object} is a CLIM \term{extended output stream}, otherwise returns \term{false}. \definitarg {:foreground} \definitarg {:background} -\definitarg {:default-text-style} +\definitarg {:text-style} \definitarg {:vertical-spacing} \definitarg {:text-margin} \definitarg {:end-of-line-action} @@ -106,6 +106,9 @@ are used to specify, respectively, the medium foreground and background, default text style, vertical spacing, default text margin, end of line and end of page actions, and the default view for the stream. +\cl{:foreground}, \cl{:background}, and \cl{:text-style} are handled via the +usual pane initialize options (see Section~\ref{pane-init}). + \Defclass {standard-extended-output-stream} This class provides an implementation of the CLIM extended output stream @@ -259,13 +262,18 @@ Many streams that maintain a text cursor display some visible indication of the text cursor. The object that represents this display is (somewhat confusingly) also called a cursor. +An \concept{active} cursor is one that is being actively maintained by its +owning sheet. A active cursor has a \concept{state} that is either on or off. +An active cursor can also has a state that indicates the the owning sheet has +the input focus. + \Defprotoclass {cursor} The protocol class that corresponds to cursors. \IfYouWantClass {a} {cursor} {cursor} \Mutable -\Defun {cursorp} {object} +\Defpredicate {cursorp} {object} Returns \term{true} if \arg{object} is a \term{cursor}, otherwise returns \term{false}. @@ -287,27 +295,41 @@ Returns the sheet with which the \term{cursor} \arg{cursor} is associated. \Defgeneric {cursor-position} {cursor} Returns the $x$ and $y$ position of the \term{cursor} \arg{cursor} as two -values. +values. $x$ and $y$ are in the coordinate system of the cursor's sheet. \Defgeneric {(setf* cursor-position)} {x y cursor} Sets the $x$ and $y$ position of the \term{cursor} \arg{cursor} to the specified -position. +position. $x$ and $y$ are in the coordinate system of the cursor's sheet. -\defgeneric {cursor-visibility} {cursor} -\Defgeneric {(setf cursor-visibility)} {visibility cursor} +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{cursor-set-position}. + +\defgeneric {cursor-active} {cursor} +\Defgeneric {(setf cursor-active)} {value cursor} + +Returns (or sets) the ``active'' attribute of the cursor. When \term{true}, the +cursor is active. + +\defgeneric {cursor-state} {cursor} +\Defgeneric {(setf cursor-state)} {value cursor} + +Returns (or sets) the ``state'' attribute of the cursor. When \term{true}, the +cursor is visible. When \term{false}, the cursor is not visible. -Returns (or sets) the visibility of the \term{cursor} \arg{cursor}. The -visibility can be either \cl{:on} (meaning that the cursor will be visible at -its current position), \cl{:off} (meaning that the cursor is active, but not -visible at its current position), or \cl{nil} (meaning that the cursor is to -be deactivated). +\Defgeneric {cursor-focus} {cursor} -\Defgeneric {display-cursor} {cursor state} +Returns the ``focus'' attribute of the cursor. When \term{true}, the sheet +owning the cursor has the input focus. -This is responsible for drawing or erasing the \term{cursor} \arg{cursor}. -If \arg{state} is \cl{:draw}, the cursor will be drawn. Otherwise, if the -\arg{state} is \cl{:erase}, the cursor will be erased. +\defgeneric {cursor-visibility} {cursor} +\Defgeneric {(setf cursor-visibility)} {visibility cursor} + +These are convenience functions that combine the functionality of +\cl{cursor-active} and \cl{cursor-state}. The visibility can be either \cl{:on} +(meaning that the cursor is active and visible at its current position), +\cl{:off} (meaning that the cursor is active, but not visible at its current +position), or \cl{nil} (meaning that the cursor is not activate). \subsection {Stream Text Cursor Protocol} @@ -332,6 +354,9 @@ Sets the text cursor position of the \term{extended output stream} \arg{stream} to \arg{x} and \arg{y}. \arg{x} and \arg{y} are in device units, and must be integers. +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{stream-set-cursor-position}. + \Defgeneric {stream-increment-cursor-position} {stream dx dy} Moves the text cursor position of the \term{extended output stream} \arg{stream} @@ -389,8 +414,9 @@ change, too. Returns what the line height of a line on the \term{extended output stream} \arg{stream} containing text in the \term{text style} \arg{text-style} would be, -as a rational number. \arg{text-style} defaults to the current text style for -the stream. +as a rational number. The height of the line is measured from the baseline of +the text style to its ascent. \arg{text-style} defaults to the current text +style for the stream. \Defgeneric {stream-vertical-spacing} {stream} @@ -410,18 +436,20 @@ The following macro provides a convenient way to mix text and graphics on the same output stream. \Defmacro {with-room-for-graphics} {(\optional stream - \key (move-cursor \cl{t}) height record-type) + \key (first-quadrant \cl{t}) height (move-cursor \cl{t}) + record-type) \body body} -Binds the dynamic environment to establish a local Cartesian coordinate system -for doing graphics output onto the \term{extended output stream} designated by -\arg{stream}. The origin $(0,0)$ of the local coordinate system is placed at -the current cursor position, and is in the lower left corner of the area -created. If the boolean \arg{move-cursor} is \term{true} (the default), then -after the graphic output is completed, the cursor is positioned past -(immediately below) this origin. The bottom of the vertical block allocated is -at this location (that is, just below point $(0,0)$, not necessarily at the -bottom of the output done). +Binds the dynamic environment to establish a local coordinate system for doing +graphics output onto the \term{extended output stream} designated by +\arg{stream}. If \arg{first-quadrant} is \term{true} (the default), a local +Cartesian coordinate system is established with the origin $(0,0)$ of the local +coordinate system placed at the current cursor position; $(0,0)$ is in the lower +left corner of the area created. If the boolean \arg{move-cursor} is +\term{true} (the default), then after the graphic output is completed, the +cursor is positioned past (immediately below) this origin. The bottom of the +vertical block allocated is at this location (that is, just below point $(0,0)$, +not necessarily at the bottom of the output done). The \arg{stream} argument is not evaluated, and must be a symbol that is bound to a stream. If \arg{stream} is \cl{t} (the default), \cl{*standard-output*} is @@ -488,14 +516,14 @@ vertically out of the viewport. The end-of-page action is one of: \begin{itemize} -\item \cl{:wrap}---when doing text output, wrap the text around (that is, go back -to the top of the viewport). - \item \cl{:scroll}---scroll the window vertically to keep the cursor position inside the viewport, then keep doing output. This is the default. \item \cl{:allow}---ignore the viewport and do the output on the drawing plane beyond the visible part of the viewport. + +\item \cl{:wrap}---when doing text output, wrap the text around (that is, go back +to the top of the viewport). \end{itemize} \Defmacro {with-end-of-page-action} {(stream action) \body body} @@ -511,7 +539,7 @@ to a stream. If \arg{stream} is \cl{t}, \cl{*standard-output*} is used. \section {Attracting the User's Attention} -\Defgeneric {beep} {\optional sheet} +\Defgeneric {beep} {\optional medium} Attracts the user's attention, usually with an audible sound. diff --git a/specs/frames.tex b/specs/frames.tex index 8b879306..540e8686 100644 --- a/specs/frames.tex +++ b/specs/frames.tex @@ -15,15 +15,16 @@ other applications. In addition to controlling the screen real estate managed by an application, a frame keeps track of the Lisp state variables that contain the state of the application. -The contents of frame is established by defining a hierarchy of \concept{panes}. -CLIM panes are interactive objects that are analogous to the windows, gadgets, -or widgets of other toolkits. Application builders can compose their -application's user interface from a library of standard panes or by defining and -using their own pane types. Application frames can use a number of different -types of panes including \concept{layout panes} for spatially organizing panes, -\concept{user panes} for presenting application specific information, and -\concept{gadget panes} for displaying data and obtaining user input. Panes are -describe in greater detail in Chapter~\ref{panes} and Chapter~\ref{gadgets}. +The visual aspect of an application frame is established by defining a hierarchy +of \concept{panes}. CLIM panes are interactive objects that are analogous to +the windows, gadgets, or widgets of other toolkits. Application builders can +compose their application's user interface from a library of standard panes or +by defining and using their own pane types. Application frames can use a number +of different types of panes including \concept{layout panes} for spatially +organizing panes, \concept{user panes} for presenting application specific +information, and \concept{gadget panes} for displaying data and obtaining user +input. Panes are describe in greater detail in Chapter~\ref{panes} and +Chapter~\ref{gadgets}. Frames are managed by special applications called \concept{frame managers}. Frame managers control the realization of the look and feel of a frame. The @@ -108,7 +109,7 @@ The protocol class that corresponds to an application frame. All application frame classes are mutable. -\Defun {application-frame-p} {object} +\Defpredicate {application-frame-p} {object} Returns \term{true} if \arg{object} is an \term{application frame}, otherwise returns \term{false}. @@ -130,9 +131,9 @@ properties for the frame. \Defclass {standard-application-frame} -The standard class that implements application frames. By default, most -application frame classes will inherit from this class, unless a non-\cl{nil} -value for \arg{superclasses} is supplied to \cl{define-application-frame}. +The instantiable standard class that implements application frames. By default, +most application frame classes will inherit from this class, unless a +non-\cl{nil} value for \arg{superclasses} is supplied to \cl{define-application-frame}. \Defmacro {define-application-frame} {name superclasses slots \rest options} @@ -154,8 +155,8 @@ usual \cl{defclass} options, plus any of the following: \item \cl{:pane} \arg{form}, where \arg{form} specifies the single pane in the application. The default is \cl{nil}, meaning that there is no single pane. This is the simplest way to define a pane hierarchy. The \cl{:pane} option is -mutually exclusive with the \cl{:panes} and \cl{:layouts} options. See -Section~\ref{frame-panes} for a complete description of the \cl{:pane} option. +mutually exclusive with the \cl{:panes} options. See Section~\ref{frame-panes} +for a complete description of the \cl{:pane} option. \item \cl{:panes} \arg{form}, where \arg{form} is an alist that specifies names and panes of the application. The default is \cl{nil}, meaning that there are @@ -164,8 +165,7 @@ See Section~\ref{frame-panes} for a complete description of the \cl{:panes} option. \item \cl{:layouts} \arg{form}, where \arg{form} specifies the layout. The -default layout is to lay out all of the named panes in horizontal strips. The -\cl{:layouts} and \cl{:pane} options are mutually exclusive. See +default layout is to lay out all of the named panes in horizontal strips. See Section~\ref{frame-panes} for a complete description of the \cl{:layouts} option. @@ -175,6 +175,12 @@ followed by some keyword-value pairs. The keywords can be \cl{:inherit-from} or \cl{:menu} (which are as in \cl{define-command-table}). The default is to create a command table with the same name as the application frame. +\item \cl{:command-definer} \arg{value}, where \arg{value} either \cl{nil}, +\cl{t}, or another symbol. When it is \cl{nil}, no command-defining macro is +defined. When it is \cl{t}, a command-defining macro is defined, whose name is +of the form \cl{define-{\it name}-command}. When it is another symbol, the +symbol names the command-defining macro. The default is \cl{t}. + \item \cl{:menu-bar} \arg{form} is used to specify what commands will appear in a ``menu bar''. It typically specifies the top-level commands of the application. \arg{form} is either \cl{nil}, meaning there is no menu bar; @@ -184,20 +190,23 @@ meaning that that command table's menu should be used; or a list, which is interpreted the same way the \cl{:menu} option to \cl{define-command-table} is interpreted. The default is \cl{t}. -\item \cl{:disabled-commands} \arg{commands}, where \arg{commands} is a list -of command names that are initially disabled in the application frame. - -\item \cl{:command-definer} \arg{value}, where \arg{value} either \cl{nil}, -\cl{t}, or another symbol. When it is \cl{nil}, no command-defining macro is -defined. When it is \cl{t}, a command-defining macro is defined, whose name is -of the form \cl{define-{\it name}-command}. When it is another symbol, the -symbol names the command-defining macro. The default is \cl{t}. +\item \cl{:disabled-commands} \arg{commands}, where \arg{commands} is a list of +command names that are initially disabled in the application frame. The set of +enabled and disabled commands can be modified via \cl{(setf~command-enabled)}. \item \cl{:top-level} \arg{form}, where \arg{form} is a list whose first element is the name of a function to be called to execute the top-level loop. The function must take at least one argument, the frame. The rest of the list consists of additional arguments to be passed to the function. The default function is \cl{default-frame-top-level}. + +\item \cl{:icon} \arg{pixmap} specifies a pixmap to be displayed by the host's +window manager when the frame is iconified. + +\item \cl{:geometry} \arg{plist}, where \arg{plist} is a property list +containing the default values for the \cl{:left}, \cl{:top}, \cl{:right}, +\cl{:bottom}, \cl{:width}, and \cl{:height} options to +\cl{make-application-frame}. \end{itemize} The \arg{name}, \arg{superclasses}, and \arg{slots} arguments are not evaluated. @@ -215,7 +224,9 @@ Makes an instance of the application frame of type \arg{frame-class}. If \arg{frame-class} is not supplied, it defaults to \arg{frame-name}. The size options \arg{left}, \arg{top}, \arg{right}, \arg{bottom}, \arg{width}, -and \arg{height} can be used to specify the size of the frame. +and \arg{height} can be used to specify the initial size of the frame. If they +are unsupplied and \cl{:geometry} was supplied to \cl{define-application-frame}, +then these arguments default from the specified geometry. \arg{options} are passed as additional arguments to \cl{make-instance}, after the \arg{pretty-name}, \arg{frame-manager}, \arg{enable}, \arg{state}, @@ -242,13 +253,39 @@ conjunction with \cl{with-slots} or \cl{slot-value}. \Defmacro {with-application-frame} {(frame) \body body} -This macro provides lexical access to the ``current'' frame for use with the -\cl{:pane}, \cl{:panes}, and \cl{:layouts} options. \arg{frame} is bound to the -current frame within the context of one of those options. +This macro provides lexical access to the ``current'' frame for use with +commands and the \cl{:pane}, \cl{:panes}, and \cl{:layouts} options. +\arg{frame} is bound to the current frame within the context of one of those +options. \arg{frame} is a symbol; it is not evaluated. \arg{body} may have zero or more declarations as its first forms. +\Defun {map-over-frames} {function \key port frame-manager} + +Applies the function \arg{function} to all of the application frames that +``match'' \arg{port} and \arg{frame-manager}. If neither \arg{port} nor +\arg{frame-manager} is supplied, all frames are considered to match. If +\arg{frame-manager} is supplied, only those frames that use that frame manager +match. If \arg{port} is supplied, only those frames that use that port match. + +\arg{function} is a function of one argument, the frame. It has dynamic extent. + + +\Defgeneric {destroy-frame} {frame} + +Destroys the application frame \arg{frame}. + +\Defgeneric {raise-frame} {frame} + +Raises the application frame \arg{frame} to be on top of all of the other host +windows by invoking \cl{raise-sheet} on the frame's top-level sheet. + +\Defgeneric {bury-frame} {frame} + +Buries the application frame \arg{frame} to be underneath all of the other host +windows by invoking \cl{bury-sheet} on the frame's top-level sheet. + \subsection {Specifying the Panes of a Frame\label{frame-panes}} @@ -260,6 +297,9 @@ option is mutually exclusive with \cl{:panes} and \cl{:layouts}. It is meaningful to define frames that have no panes at all; the frame will simply serve as a repository for state and commands. +Panes and gadgets are discussed in detail in Chapter~\ref{panes} and +Chapter~\ref{gadgets}. + The value of the \cl{:pane} option is a form that is used to create a single (albeit arbitrarily complex) pane. For example: @@ -284,7 +324,7 @@ If the \cl{:pane} option is not used, a set of named panes can be specified with the \cl{:panes} option. Optionally, \cl{:layouts} can also be used to describe different layouts of the set of panes. -The value of the \cl{:panes} option is an alist, each entry of which is of the +The value of the \cl{:panes} option is a list, each entry of which is of the form \arg{(name . body)}. \arg{name} is a symbol that names the pane, and \arg{body} specifies how to create the pane. \arg{body} is either a list containing a single element that is itself a list, or a list consisting of a @@ -297,14 +337,14 @@ example, \cl{slider} or \cl{push-button}). For CLIM stream panes, the following abbreviations are defined: \begin{itemize} -\item \cl{:interactor}---a pane of type \cl{interactor-pane} +\item \cl{:interactor}---a pane of type \cl{interactor-pane}. -\item \cl{:application}---a pane of type \cl{application-pane} +\item \cl{:application}---a pane of type \cl{application-pane}. -\item \cl{:command-menu}---a pane of type \cl{command-menu-pane} +\item \cl{:command-menu}---a pane of type \cl{command-menu-pane}. \item \cl{:pointer-documentation}---a pane suitable for displaying pointer -documentation, if the host window system does not provide this +documentation, if the host window system does not provide this. \item \cl{:title}---a pane suitable for displaying the title of the application, if the host window system does not provide this. @@ -332,13 +372,14 @@ An example of the use of \cl{:panes} is: :incremental-redisplay t)) \end{verbatim} -The value of the \cl{:layouts} option is an alist, each entry of which is of the +The value of the \cl{:layouts} option is a list, each entry of which is of the form \arg{(name layout)}. \arg{name} is a symbol that names the layout, and \arg{layout} specifies the layout. \arg{layout} is a form like the form used in the \cl{:pane} option, with the extension to the syntax such that the name of a -named pane can be used wherever a pane may appear. For example, assuming a -frame that uses the \cl{:panes} example above, the following layouts could be -specified: +named pane can be used wherever a pane may appear. (This will typically be +implemented by using \cl{symbol-macrolet} for each of the named panes.) For +example, assuming a frame that uses the \cl{:panes} example above, the following +layouts could be specified: \begin{verbatim} (:layouts @@ -355,6 +396,32 @@ specified: button toggle)))) \end{verbatim} +The syntax for \cl{:layouts} can be concisely expressed as: + +\begin{description} +\item \cl{:layouts (\arg{layout-name layout-panes})} + +\item \arg{layout-name} is a symbol. + +\item \arg{layout-panes} is \arg{layout-panes1} or \cl{(\arg{size-spec layout-panes1})}. + +\item \arg{layout-panes1} is a \arg{pane-name}, or a \arg{layout-macro-form}, or +\arg{layout-code}. + +\item \arg{layout-code} is lisp code that generates a pane, which may include +the name of a named pane. + +\item \arg{size-spec} is a rational number less than 1, or \cl{:fill}, or +\cl{:compute}. + +\item \arg{layout-macro-form} is \cl{(\arg{layout-macro-name} (\arg{options}) . +\arg{body})}. + +\item \arg{layout-macro-name} is one of the layout macros, such as +\cl{outlining}, \cl{spacing}, \cl{labelling}, \cl{vertically}, \cl{horizontally}, +or \cl{tabling}. +\end{description} + \section {Application Frame Functions} @@ -374,7 +441,9 @@ Returns the ``pretty name'' of the \term{frame} \arg{frame}, which is a string. \Defgeneric {(setf frame-pretty-name)} {name frame} Sets the pretty name of the \term{frame} \arg{frame} to \arg{name}, which must -be a string. +be a string. Changing the pretty name of a frame notifies its frame manager, +which in turn may change some aspects of the appearance of the frame, such as +its title bar. \Defgeneric {frame-command-table} {frame} @@ -393,7 +462,7 @@ bar) as needed. \arg{command-table} is a \term{command table designator}. Returns the stream that will be used for \cl{*standard-output*} for the \term{frame} \arg{frame}. The default method (on \cl{standard-application-frame}) returns the first named pane of type -\cl{application-pane} that is exposed in the current layout; if there is no such +\cl{application-pane} that is visible in the current layout; if there is no such pane, it returns the first pane of type \cl{interactor-pane} that is exposed in the current layout. @@ -402,7 +471,7 @@ the current layout. Returns the stream that will be used for \cl{*standard-input*} for the \term{frame} \arg{frame}. The default method (on \cl{standard-application-frame}) returns the first named pane of type -\cl{interactor-pane} that is exposed in the current layout; if there is no such +\cl{interactor-pane} that is visible in the current layout; if there is no such pane, the value returned by {frame-standard-output} is used. \Defgeneric {frame-query-io} {frame} @@ -445,16 +514,22 @@ This often, but not always, returns the same value as \cl{frame-manager}. \Defgeneric {frame-panes} {frame} -Returns a list of all of the \term{frame} \arg{frame}'s named panes. This -includes panes in the current layout, and panes in other layouts as well. If -there are no named panes (that is, the \cl{:pane} option was used), only the -single, top level pane is returned. -\ReadOnly +Returns the pane that is the top-level pane in the current layout of the +\term{frame} \arg{frame}'s named panes. This will typically be some sort of a +layout pane. + +\Defgeneric {frame-top-level-sheet} {frame} + +Returns the sheet that is the top-level sheet for the \term{frame} \arg{frame}. +This is the sheet that has as its descendents all of the panes of \arg{frame}. + +The value returned by \cl{frame-panes} will be a descendents of the value of +\cl{frame-top-level-sheet}. \Defgeneric {frame-current-panes} {frame} Returns a list of those named panes in the \term{frame} \arg{frame}'s current -layout. If there are no named panes (that is, the \cl{:pane} option was used), +layout. If there are no named panes (for example, the \cl{:pane} option was used), only the single, top level pane is returned. \ReadOnly @@ -469,15 +544,6 @@ Returns the pane in the \term{frame} \arg{frame} whose name is \arg{pane-name}. This can return any type of pane, not just CLIM stream panes. -\Defgeneric {frame-top-level-sheet} {frame} - -Returns the sheet that is the top-level sheet for the \term{frame} \arg{frame}. -This is the sheet that has as its descendents all of the panes of \arg{frame}. - -\Defgeneric {frame-pane} {frame} - -Returns the pane that is the top level pane of the current layout of the frame. - \Defgeneric {frame-current-layout} {frame} Returns the current layout for the \term{frame} \arg{frame}. The layout is @@ -496,6 +562,10 @@ to \cl{run-frame-top-level} in order to do this. After the new layout has been computed, the contents of each of the panes must be displayed to the degree necessary to ensure that all output is visible. +\Defgeneric {frame-all-layouts} {frame} + +Returns a list of the names of all of the possible layouts for the frame. + \Defgeneric {layout-frame} {frame \optional width height} Resizes the frame and lays out the current pane hierarchy using the layout @@ -515,24 +585,42 @@ In either case, after the frame is resized, the space allocation pass of the layout protocol is invoked on the top-level pane. -\Defrestart {frame-exit} +\Defcondition {frame-exit} + +The condition that is signalled when \cl{frame-exit} is called. This condition +will handle the \cl{:frame} initarg, which is used to supply the frame that is +being exited from. -The restart that is invoked when \cl{frame-exit} is called. +\Defgeneric {frame-exit-frame} {condition} + +Returns the frame that is being exited from associated with the \cl{frame-exit} +condition. \Defgeneric {frame-exit} {frame} Exits from the \term{frame} \arg{frame}. The default method (on -\cl{standard-application-frame}) invokes the \cl{frame-exit} restart. +\cl{standard-application-frame}) signals a \cl{frame-exit} condition, supplying +\arg{frame} as the \cl{:frame} initarg. + +\Defgeneric {pane-needs-redisplay} {pane} -\defgeneric {panes-need-redisplay} {frame} -\Defgeneric {pane-needs-redisplay} {frame pane} +Returns two values, the first indicating whether the \term{pane} \arg{pane} +needs to be redisplayed, and the second indicating whether the pane needs to be +cleared before being redisplayed. The first value is \term{true} when the pane +is to be redisplayed. The second value is \term{true} when the pane is to be +cleared. -\cl{panes-need-redisplay} indicates that all of the panes in the \term{frame} -\arg{frame} should be redisplayed the next time around the command loop. -\cl{pane-needs-redisplay} causes only the pane \arg{pane} within \arg{frame} to -be redisplayed the next time around the command loop; in this case, \arg{pane} -is either a pane or the name of a named pane. +\Defgeneric {(setf pane-needs-redisplay)} {value pane} + +Indicates that the \term{pane} \arg{pane} should (or should not) be redisplayed +the next time the owning frame executes the redisplay part of its command loop. + +When \arg{value} is \cl{nil}, the pane will not require redisplay. When +\arg{value} is \cl{t}, the pane will be cleared and redisplayed exactly once. +When \arg{value} is \cl{:command-loop}, the pane will be cleared and redisplayed +in each successive pass through the command loop. When \arg{value} is +\cl{:no-clear}, the pane will be redisplayed exactly once without clearing it. \Defgeneric {redisplay-frame-pane} {frame pane \key force-p} @@ -556,16 +644,21 @@ region specified by the region \arg{region}, which defaults to viewport of \arg{stream}. -\Defgeneric {notify-user} {frame format-string \rest format-args} +\Defgeneric {notify-user} {frame message + \key associated-window title documentation + exit-boxes name style text-style Notifies the user of some event on behalf of the \term{frame} \arg{frame}. -\arg{format-string} and \arg{format-args} are arguments allowable by -\cl{format}. +\arg{message} is a message string. This function provides a look and feel +independent way for applications to communicate messages to the user. -This function is intended to provide a look and feel independent way for -applications to communicate messages to the user. For example, a frame manager -might provide a top-level message window or a message window for each frame, or -might pop up an alert box. +\arg{associated-window} is the window with which the notification will be +associated, as it is for \cl{menu-choose}. \arg{title} is a title string to +include in the notification. \arg{text-style} is the text style in which to +display the notification. \arg{exit-boxes} is as for \arg{accepting-values}; it +indicates what sort of exit boxes should appear in the notification. +\arg{style} is the style in which to display the notification, and is +implementation-dependent. \defgeneric {frame-properties} {frame property} @@ -700,13 +793,13 @@ All classes that inherit from \cl{application-frame} must inherit or implement methods for all of the following functions. -\Defgeneric {run-frame-top-level} {frame} +\Defgeneric {run-frame-top-level} {frame \key \allow} Runs the top-level function for the \term{frame} \arg{frame}. The default method on \cl{application-frame} simply invokes the top-level function for the frame (which defaults to \cl{default-frame-top-level}). -\Defaroundmethod {run-frame-top-level} {(frame \cl{application-frame})} +\Defaroundmethod {run-frame-top-level} {(frame \cl{application-frame}) \key} The \cl{:around} method of \cl{run-frame-top-level} on the \cl{application-frame} class is responsible for establish the initial dynamic @@ -751,7 +844,7 @@ interactor, otherwise it defaults to \arg{command-parser}, \arg{command-unparser}, and \arg{partial-command-parser}. -\Defgeneric {read-frame-command} {frame stream} +\Defgeneric {read-frame-command} {frame \key (stream \cl{*standard-input*})} Reads a command from the stream \arg{stream} on behalf of the \term{frame} \arg{frame}. The returned value is a command object. @@ -770,6 +863,12 @@ The default method (on \cl{standard-application-frame}) for \cl{execute-frame-command} simply applies the \cl{command-name} of \arg{command} to \cl{command-arguments} of \arg{command}. +If process that \cl{execute-frame-command} is invoked in is not the same process +the one \arg{frame} is running in, CLIM may need to make special provisions in +order for the command to be correctly executed, since as queueing up a special +``command event'' in \arg{frame}'s event queue. The exact details of how this +should work is left unspecified. + \Defgeneric {command-enabled} {command-name frame} @@ -788,15 +887,16 @@ If \arg{enabled} is \term{false}, this disables the use of the command named by \arg{command-name} while in the \term{frame} \arg{frame}. Otherwise if \arg{enabled} is \term{true}, the use of the command is enabled. After the command has been enabled (or disabled), \cl{note-command-enabled} (or -\cl{note-command-disabled}) is invoked on the frame manager in order to update -the appearance of the interface. +\cl{note-command-disabled}) is invoked on the frame manager and the frame in +order to update the appearance of the interface, for example, ``graying out'' a +disabled command. If \arg{command-name} is not accessible to the command table being used by \arg{frame}, using \cl{setf} on \cl{command-enabled} does nothing. \Defgeneric {display-command-menu} {frame stream - \key command-table initial-spacing + \key command-table initial-spacing row-wise max-width max-height n-rows n-columns (cell-align-x \cl{:left}) (cell-align-y \cl{:top})} @@ -805,8 +905,9 @@ calling \cl{display-command-table-menu}. If \arg{command-table} is not supplied, it defaults to \cl{(frame-command-table \arg{stream})}. This function is generally used as the display function for panes that contain command menus. -\arg{initial-spacing}, \arg{max-width}, \arg{max-height}, \arg{n-rows}, \arg{n-columns}, -\arg{cell-align-x}, and \arg{cell-align-y} are as for \cl{formatting-item-list}. +\arg{initial-spacing}, \arg{max-width}, \arg{max-height}, \arg{n-rows}, +\arg{n-columns}, \arg{row-wise}, \arg{cell-align-x}, and \arg{cell-align-y} are +as for \cl{formatting-item-list}. \section {Frame Managers} @@ -839,7 +940,7 @@ There are no advertised standard frame manager classes. Each port will implement one or more frame managers that correspond to the look and feel for the port. -\Defun {frame-mananger-p} {object} +\Defpredicate {frame-mananger-p} {object} Returns \term{true} if \arg{object} is a \term{frame manager}, otherwise returns \term{false}. @@ -952,6 +1053,14 @@ with a frame. For example, removing a frame from a frame manager that is talking to a remote server allows it to release all remote resources used by the frame. +\Defmethod {port} {(frame \cl{standard-application-frame})} + +If \arg{frame} has been adopted by a frame manager, this returns the port with +which \arg{frame} is associated. Otherwise it returns \cl{nil}. + +\Defmethod {port} {(frame-manager \cl{standard-frame-manager})} + +Returns the port with which \arg{frame-manager} is associated. \Defgeneric {frame-state} {frame} @@ -962,30 +1071,55 @@ indicating the current state of frame. \defgeneric {disable-frame} {frame} \Defgeneric {shrink-frame} {frame} -These functions force a frame into the enabled, disabled, or shrunken states. A -frame in the enabled state may be visible if it is not occluded or placed out of -the user's focus of attention. A disabled frame is never visible. A shrunk -frame is accessible to the user for re-enabling, but may be represented in some -abbreviated form, such as an icon or a menu item. +These functions force a frame into the enabled, disabled, or shrunken +(iconified) states. A frame in the enabled state may be visible if it is not +occluded or placed out of the user's focus of attention. A disabled frame is +never visible. A shrunk frame is accessible to the user for re-enabling, but +may be represented in some abbreviated form, such as an icon or a menu item. -These functions call \cl{note-frame-state-changed} to notify the frame manager -that the state of the frame changed. +These functions call the notification functions describe below to notify the +frame manager that the state of the frame changed. -\Defgeneric {note-frame-state-changed} {frame-manager frame new-state} +\defgeneric {note-frame-enabled} {frame-manager frame} +\defgeneric {note-frame-disabled} {frame-manager frame} +\defgeneric {note-frame-iconified} {frame-manager frame} +\Defgeneric {note-frame-deiconified} {frame-manager frame} -Notifies the frame manager \arg{frame-manager} that the frame \arg{frame} -has changed its state to \arg{state}. +Notifies the frame manager \arg{frame-manager} that the frame \arg{frame} has +changed its state to the enabled, disabled, iconified, or deiconified state, +respectively. + + +\defgeneric {note-command-enabled} {frame-manager frame command-name} +\Defgeneric {note-command-disabled} {frame-manager frame command-name} + +Notifies the frame manager \arg{frame-manager} that the command named by +\arg{command-name} has been enabled or disabled (respectively) in the frame +\arg{frame}. The frame manager can update the appearance of the user interface +as appropriate, for instance, by ``graying out'' a newly disabled command from a +command menu or menu bar. + + +\Defgeneric {frame-manager-notify-user} {framem message-string + \key frame associated-window title documentation + exit-boxes name style text-style} + +This is the generic function used by \cl{notify-user}. The arguments are as for +\cl{notify-user}. The default method on \cl{standard-frame-manager} will +display a dialog or an alert box that contains the message and has exit boxes +that allow the user to dismiss the notification. \Defgeneric {generate-panes} {frame-manager frame} -This function is invoked by a standard method of \cl{adopt-frame}. It is the -responsibility of the frame implementor to provide a method that invokes -\cl{setf} of \cl{frame-pane} on the frame with a value of type \cl{pane}. +This function is invoked by a standard method of \cl{adopt-frame}. \cl{define-application-frame} automatically supplies a \cl{generate-panes} method if either the \cl{:pane} or \cl{:panes} option is used in the \cl{define-application-frame}. +It is the responsibility of this method to call \cl{setf} on \cl{frame-panes} on +the frame in order to set the current + \Defgeneric {find-pane-for-frame} {frame-manager frame} This function is invoked by a standard method of \cl{adopt-frame}. It must @@ -996,16 +1130,6 @@ function if either the \cl{:pane} or \cl{:panes} option is used in the \cl{define-application-frame}. -\defgeneric {note-command-enabled} {frame-manager frame command-name} -\Defgeneric {note-command-disabled} {frame-manager frame command-name} - -Notifies the frame manager \arg{frame-manager} that the command named by -\arg{command-name} has been enabled or disabled (respectively) in the frame -\arg{frame}. The frame manager can update the appearance of the user interface -as appropriate, for instance, by ``graying out'' a newly disabled command from a -command menu or menu bar. - - \subsection {Frame Manager Settings} CLIM provides frame manager settings in order to allow a frame to communicate @@ -1015,7 +1139,7 @@ information to its frame manager. Sets the setting \arg{setting} to \arg{value} for the frame \arg{frame}. -\Defgeneric {reset-frame} {frame \rest new-client-settings} +\Defgeneric {reset-frame} {frame \rest client-settings} Resets the settings of frame. \cl{reset-frame} invokes a protocol that forces the frame manager to notice that the settings have changed, where the setf @@ -1041,7 +1165,7 @@ The following is an example that outlines a simple 4-by-4 sliding piece puzzle: :height :compute :incremental-redisplay T :display-function 'draw-puzzle)))) - (:layout + (:layouts (:default display))) (defmethod run-frame-top-level :before ((puzzle puzzle)) @@ -1092,7 +1216,7 @@ The following is an application frame with two layouts: (e :interactor-pane :width 300 :max-width +fill+ :height 300 :max-height +fill+)) - (:layout + (:layouts (default (vertically () a b c (scrolling () e))) diff --git a/specs/gadgets.tex b/specs/gadgets.tex index c384f98b..737a9d05 100644 --- a/specs/gadgets.tex +++ b/specs/gadgets.tex @@ -11,7 +11,7 @@ For example, a push button has an ``activate'' callback function that is invoked when its button is ``pressed''; a scroll bar has a ``value changed'' callback that is invoked after its indicator has been moved. -The gadget definitions specified by CLIM are abstract, that is, the gadget +The gadget definitions specified by CLIM are abstract, in that the gadget definition does not specify the exact user interface of the gadget, but only specifies the semantics that the gadget should provide. For instance, it is not defined whether the user clicks on a push button with the mouse or moves the @@ -93,11 +93,11 @@ We could then refine the above as: ;; Create the start and stop push buttons (make-pane 'push-button - :label "Start" - :client frame :id 'start) + :label "Start" + :client frame :id 'start) (make-pane 'push-button - :label "Stop" - :client frame :id 'stop) + :label "Stop" + :client frame :id 'stop) \end{verbatim} Another way to distinguish between gadgets is to explicitly specify what @@ -108,17 +108,17 @@ could then be written as follows: \begin{verbatim} ;; No callback methods needed, just create the push buttons (make-pane 'push-button - :label "Start" - :client frame :id 'start - :activate-callback - #'(lambda (gadget) - (start-test (gadget-client gadget)))) + :label "Start" + :client frame :id 'start + :activate-callback + #'(lambda (gadget) + (start-test (gadget-client gadget)))) (make-pane 'push-button - :label "Stop" - :client frame :id 'stop - :activate-callback - #'(lambda (gadget) - (stop-test (gadget-client gadget)))) + :label "Stop" + :client frame :id 'stop + :activate-callback + #'(lambda (gadget) + (stop-test (gadget-client gadget)))) \end{verbatim} @@ -127,11 +127,7 @@ could then be written as follows: The following shows how a push button gadget might be implemented. \begin{verbatim} -;; A PUSH-BUTTON uses the ACTIVATE-CALLBACK, and has a label. -;; This is the abstract class -(defclass push-button (action-gadget labelled-gadget) ()) - -;; Here is a concrete implementation of a PUSH-BUTTON. +;; Here is a concrete implementation of a CLIM PUSH-BUTTON. ;; The "null" frame manager create a pane of type PUSH-BUTTON-PANE when ;; asked to create a PUSH-BUTTON. (defclass push-button-pane @@ -142,20 +138,24 @@ The following shows how a push button gadget might be implemented. :accessor push-button-show-as-default) (armed :initform nil))) -;; General highlight-by-inverting method +;; General highlight-by-inverting method. (defmethod highlight-button ((pane push-button-pane) medium) (with-bounding-rectangle* (left top right bottom) (sheet-region pane) (draw-rectangle* medium left top right bottom - :ink +flipping-ink+ :filled t))) + :ink +flipping-ink+ :filled t) + (medium-force-output medium))) -;; Compute the amount of space required by a PUSH-BUTTON-PANE +;; Compute the amount of space required by a PUSH-BUTTON-PANE. (defmethod compose-space ((pane push-button-pane) &key width height) + (let ((x-margin 4) + (y-margin 2)) (multiple-value-bind (width height) (compute-gadget-label-size pane) - (make-space-requirement :width width :height height))) + (make-space-requirement :width (+ width (* x-margin 2)) + :height (+ height (* y-margin 2)))) ;; This gets invoked to draw the push button. -(defmethod repaint-sheet ((pane push-button-pane) region) +(defmethod handle-repaint ((pane push-button-pane) region) (declare (ignore region)) (with-sheet-medium (medium pane) (let ((text (gadget-label pane)) @@ -165,35 +165,45 @@ The following shows how a push button gadget might be implemented. (multiple-value-call #'draw-rectangle* medium (bounding-rectangle* (sheet-region pane)) :filled nil) - (draw-text medium text (clim-utils::bounding-rectangle-center region) + (draw-text medium text (bounding-rectangle-center region) :text-style text-style - :align-x ':center :align-y ':top) + :align-x ':center :align-y ':center) (when (eql armed ':button-press) (highlight-button pane medium))))) -;; When we enter the push button's region, arm it. +(defmethod handle-event :around ((pane push-button-pane) (event pointer-event)) + (when (gadget-active-p pane) + (call-next-method))) + +;; When we enter the push button's region, arm it. If there is a pointer +;; button down, make the button active as well. (defmethod handle-event ((pane push-button-pane) (event pointer-enter-event)) (with-slots (armed) pane (unless armed - (setf armed t) + (cond ((let ((pointer (pointer-event-pointer event))) + (and (pointer-button-state pointer) + (not (zerop (pointer-button-state pointer))))) + (setf armed :active) + (with-sheet-medium (medium pane) + (highlight-button pane medium))) + (t (setf armed t))) (armed-callback pane (gadget-client pane) (gadget-id pane))))) ;; When we leave the push button's region, disarm it. (defmethod handle-event ((pane push-button-pane) (event pointer-exit-event)) (with-slots (armed) pane (when armed - (when (eql armed ':button-press) - (highlight-button pane medium)) - (setf armed nil) + (when (prog1 (eq armed :active) (setf armed nil)) + (with-sheet-medium (medium pane) + (highlight-button pane medium))) (disarmed-callback pane (gadget-client pane) (gadget-id pane))))) ;; When the user presses a pointer button, ensure that the button ;; is armed, and highlight it. (defmethod handle-event ((pane push-button-pane) (event pointer-button-press-event)) (with-slots (armed) pane - (unless armed - (setf armed ':button-press) - (armed-callback pane (gadget-client pane) (gadget-id pane)) + (when armed + (setf armed :active) (with-sheet-medium (medium pane) (highlight-button pane medium))))) @@ -201,18 +211,17 @@ The following shows how a push button gadget might be implemented. ;; call the activate callback. (defmethod handle-event ((pane push-button-pane) (event pointer-button-release-event)) (with-slots (armed) pane - (when (eql armed ':button-press) - (activate-callback pane (gadget-client pane) (gadget-id pane)) + (when (eq armed :active) (setf armed t) (with-sheet-medium (medium pane) - (highlight-button pane medium))))) + (highlight-button pane medium)) + (activate-callback pane (gadget-client pane) (gadget-id pane))))) \end{verbatim} \section {Basic Gadget Classes} -The following are the basic gadget classes upon which all abstract gadgets are -built. +The following are the basic gadget classes upon which all gadgets are built. \Defprotoclass {gadget} @@ -221,14 +230,15 @@ The protocol class that corresponds to a gadget, a subclass of \cl{pane}. All of the subclasses of \cl{gadget} are mutable. -\Defun {gadgetp} {object} +\Defpredicate {gadgetp} {object} Returns \term{true} if \arg{object} is a \term{gadget}, otherwise returns \term{false}. -\Defclass {standard-gadget} +\Defclass {basic-gadget} -The standard class on which all CLIM gadgets are built. +The basic class on which all CLIM gadgets are built, a subclass of \cl{gadget}. +\AbstractClass \definitarg {:id} \definitarg {:client} @@ -248,9 +258,10 @@ a simple Lisp object that uniquely identifies the gadgets. \defgeneric {gadget-client} {gadget} \Defgeneric {(setf gadget-client)} {client gadget} -Returns the client of the gadget \arg{gadget}. The client is usually an +Returns the client of the gadget \arg{gadget}. The client is often an application frame, but it could be another gadget (for example, in the case of a -push button that is contained in a radio box). +push button that is contained in a radio box, the client of the button could be +the radio box). \defgeneric {gadget-armed-callback} {gadget} \Defgeneric {gadget-disarmed-callback} {gadget} @@ -266,11 +277,14 @@ disarmed) callback for the gadget. \Callback {disarmed-callback} {gadget client gadget-id} These callbacks are invoked when the gadget \arg{gadget} is, respectively, armed -or disarmed. The exact definition of arming and disarming varies from gadget to -gadget, but typically a gadget becomes armed when the pointer is moved into its -region, and disarmed when the pointer moves out of its region. +or disarmed. -The default methods (on \cl{standard-gadget}) call the function stored in +The exact definition of arming and disarming varies from gadget to gadget, but +typically a gadget becomes armed when the pointer is moved into its region, and +disarmed when the pointer moves out of its region. A gadget will not call the +activate or value-changed callback unless it is armed. + +The default methods (on \cl{basic-gadget}) call the function stored in \cl{gadget-armed-callback} or \cl{gadget-disarmed-callback} with one argument, the gadget. @@ -284,18 +298,28 @@ Causes the host gadget to become inactive, that is, unavailable for input. In some environments this may cause the gadget to become grayed over; in others, no visual effect may be detected. +\Defgeneric {gadget-active-p} {gadget} + +Returns \cl{t} if the gadget \arg{gadget} is active (that is, has been activated +with \cl{activate-gadget}), otherwise returns \cl{nil}. + \Defgeneric {note-gadget-activated} {client gadget} -This function is invoked after a gadget is made active. +This function is invoked after a gadget is made active. It is intended to allow +the client of the gadget to notice when the gadget has been activated. \Defgeneric {note-gadget-deactivated} {client gadget} -This function is invoked after a gadget is made inactive. +This function is invoked after a gadget is made inactive. It is intended to +allow the client of the gadget to notice when the gadget has been activated. +For instance, when the client is an application frame, the frame may invoke the +frame manager to ``gray out'' deactivated gadgets. \Defclass {value-gadget} -The class used by gadgets that have a value; a subclass of \cl{standard-gadget}. +The class used by gadgets that have a value; a subclass of \cl{basic-gadget}. +\AbstractClass \definitarg {:value} \Definitarg {:value-changed-callback} @@ -314,8 +338,9 @@ interpret the value.) \Defgeneric {(setf gadget-value)} {value value-gadget \key invoke-callback} -Sets the gadget's value to the specified value. In addition, if -\arg{invoke-callback} is \term{true}, the value changed callback for the +Sets the gadget's value to the specified value. + +If \arg{invoke-callback} is \term{true}, the value changed callback for the gadget is invoked. The default is \term{false}. The syntax for using \cl{(setf~gadget-value)} in conjunction with \arg{invoke-callback} is: @@ -349,7 +374,8 @@ CLIM implementations must implement or inherit a method for \Defclass {action-gadget} The class used by gadgets that perform some kind of action, such as a push -button; a subclass of \cl{standard-gadget}. +button; a subclass of \cl{basic-gadget}. +\AbstractClass \Definitarg {:activate-callback} @@ -376,15 +402,15 @@ CLIM implementations must implement or inherit a method for \cl{action-gadget}. -\Defclass {oriented-gadget} +\Defclass {oriented-gadget-mixin} The class that is mixed in to a gadget that has an orientation associated with -it, for example, a slider. +it, for example, a slider. This class is not intended to be instantiated. \Definitarg {:orientation} -All subclasses of \cl{oriented-gadget} must handle this initarg, which is used -to specify the orientation of the gadget. +All subclasses of \cl{oriented-gadget-mixin} must handle this initarg, +which is used to specify the orientation of the gadget. \Defgeneric {gadget-orientation} {oriented-gadget} @@ -392,19 +418,19 @@ Returns the orientation of the gadget \arg{oriented-gadget}. Typically, this will be a keyword such as \cl{:horizontal} or \cl{:vertical}. -\Defclass {labelled-gadget} +\Defclass {labelled-gadget-mixin} The class that is mixed in to a gadget that has a label, for example, a push -button. +button. This class is not intended to be instantiated. \definitarg {:label} \definitarg {:align-x} -\definitarg {:align-y} -\Definitarg {:label-text-style} +\Definitarg {:align-y} -All subclasses of \cl{labelled-gadget} must handle these initargs, which are -used to specify the label, its $x$ and $y$ alignment, and its text style for the -gadget. +All subclasses of \cl{labelled-gadget-mixin} must handle these initargs, which +are used to specify the label, and its $x$ and $y$ alignment. Labelled gadgets +will also have a text style for the label, but this is managed by the usual text +style mechanism for panes. \defgeneric {gadget-label} {labelled-gadget} \Defgeneric {(setf gadget-label)} {label labelled-gadget} @@ -422,18 +448,11 @@ Returns (or sets) the alignment of the label of the gadget \arg{labelled-gadget}. Changing the alignment a gadget may result in invoking the layout protocol on the gadget and its ancestor sheets. -\defgeneric {gadget-label-text-style} {labelled-gadget} -\Defgeneric {(setf gadget-label-text-style)} {text-style labelled-gadget} - -Returns (or sets) the text style of the label of the gadget -\arg{labelled-gadget}. This must be a CLIM text style object. Changing the -label text style of a gadget may result in invoking the layout protocol on the -gadget and its ancestor sheets. - \Defclass {range-gadget-mixin} The class that is mixed in to a gadget that has a range, for example, a slider. +This class is not intended to be instantiated. \definitarg {:min-value} \Definitarg {:max-value} @@ -453,19 +472,29 @@ number. Returns (or sets) the maximum value of the gadget \arg{range-gadget}. It will be a real number. +\Defgeneric {gadget-range} {range-gadget} + +Returns the range of \arg{range-gadget}, that is, the difference of the maximum value +and the minimum value. + +\Defgeneric {gadget-range*} {range-gadget} + +Returns the minimum and maximum values of \arg{range-gadget} as two values. + \section {Abstract Gadget Classes} -CLIM supplies a set of gadgets that have been designed to be compatible with -with a variety of user interface toolkits, including Xt widget-based toolkits -(such as Motif), OpenLook, and MacApp and MicroSoft Windows. +CLIM supplies a set of abstract gadgets that have been designed to be compatible +with with a variety of user interface toolkits, including Xt widget-based +toolkits (such as Motif), OpenLook, and MacApp and MicroSoft Windows. -Each gadget maps to an implementation-specific object that is managed by the -underlying toolkit. For example, while a CLIM program manipulates an object of -class \cl{scroll-bar}, the underlying implementation-specific object might be an -Xt widget of type \cl{Xm\_Scroll\_Bar}. As events are processed on the -underlying object the corresponding generic operations are applied to the Lisp -gadget. +CLIM's ``concrete'' gadget classes will all be subclasses of these abstract +gadget classes. Each concrete gadget maps to an implementation-specific object +that is managed by the underlying toolkit. For example, while a CLIM program +manipulates an object of class \cl{scroll-bar}, the underlying +implementation-specific object might be an Xt widget of type +\cl{Xm\_Scroll\_Bar}. As events are processed on the underlying object the +corresponding generic operations are applied to the Lisp gadget. \issue {ILA} {Do we want to define something like \cl{gadget-handle} that is a documented way to get ahold of the underlying toolkit object?} @@ -492,15 +521,15 @@ the button. \Defclass {push-button} -The class that implements an abstract push button. It is a subclass of -\cl{active-gadget} and \cl{labelled-gadget}. +The instantiable class that implements an abstract push button. It is a +subclass of \cl{action-gadget} and \cl{labelled-gadget-mixin}. -\Definitarg {:show-as-default-p} +\Definitarg {:show-as-default} This is used to initialize the ``show as default'' property for the gadget, described below. -\Defgeneric {push-button-show-as-default-p} {push-button} +\Defgeneric {push-button-show-as-default} {push-button} Returns the ``show as default'' property for the push button gadget. When \term{true}, the push button will be drawn with a heavy border, which indicates @@ -508,7 +537,8 @@ that this button is the ``default operation''. \Defclass {push-button-pane} -The class that implements a portable push button; a subclass of \cl{push-button}. +The instantiable class that implements a portable push button; a subclass of +\cl{push-button}. \Gadget {toggle-button} @@ -527,8 +557,8 @@ outside of the toggle button. \Defclass {toggle-button} -The class that implements an abstract toggle button. It is a subclass of -\cl{value-gadget} and \cl{labelled-gadget}. +The instantiable class that implements an abstract toggle button. It is a +subclass of \cl{value-gadget} and \cl{labelled-gadget-mixin}. \Definitarg {:indicator-type} @@ -548,7 +578,8 @@ Returns \term{true} if the button is selected, otherwise returns \term{false}. \Defclass {toggle-button-pane} -The class that implements a portable toggle button; a subclass of \cl{toggle-button}. +The instantiable class that implements a portable toggle button; a subclass of +\cl{toggle-button}. \Gadget {menu-button} @@ -566,12 +597,13 @@ outside of the menu button. \Defclass {menu-button} -The class that implements an abstract menu button. It is a subclass of -\cl{value-gadget} and \cl{labelled-gadget}. +The instantiable class that implements an abstract menu button. It is a +subclass of \cl{value-gadget} and \cl{labelled-gadget-mixin}. \Defclass {menu-button-pane} -The class that implements a portable menu button; a subclass of \cl{menu-button}. +The instantiable class that implements a portable menu button; a subclass of +\cl{menu-button}. \Gadget {scroll-bar} @@ -580,18 +612,19 @@ The \cl{scroll-bar} gadget corresponds to a scroll bar. \Defclass {scroll-bar} -The class that implements a scroll bar. This is a subclass of -\cl{value-gadget}, \cl{oriented-gadget}, and \cl{range-gadget-mixin}. +The instantiable class that implements an abstract scroll bar. This is a +subclass of \cl{value-gadget}, \cl{oriented-gadget-mixin}, and +\cl{range-gadget-mixin}. \definitarg {:drag-callback} \definitarg {:scroll-to-bottom-callback} \definitarg {:scroll-to-top-callback} -\definitarg {:drag-down-line-callback} -\definitarg {:drag-up-line-callback} -\definitarg {:drag-down-page-callback} -\Definitarg {:drag-up-page-callback} +\definitarg {:scroll-down-line-callback} +\definitarg {:scroll-up-line-callback} +\definitarg {:scroll-down-page-callback} +\Definitarg {:scroll-up-page-callback} -Specifies the drag and other callbacks for the scroll bar. +Specifies the drag and other scrolling callbacks for the scroll bar. \Defgeneric {scroll-bar-drag-callback} {scroll-bar} @@ -601,10 +634,10 @@ the new value. \defgeneric {scroll-bar-scroll-to-bottom-callback} {scroll-bar} \defgeneric {scroll-bar-scroll-to-top-callback} {scroll-bar} -\defgeneric {scroll-bar-drag-down-line-callback} {scroll-bar} -\defgeneric {scroll-bar-drag-up-line-callback} {scroll-bar} -\defgeneric {scroll-bar-drag-down-page-callback} {scroll-bar} -\Defgeneric {scroll-bar-drag-up-page-callback} {scroll-bar} +\defgeneric {scroll-bar-scroll-down-line-callback} {scroll-bar} +\defgeneric {scroll-bar-scroll-up-line-callback} {scroll-bar} +\defgeneric {scroll-bar-scroll-down-page-callback} {scroll-bar} +\Defgeneric {scroll-bar-scroll-up-page-callback} {scroll-bar} Returns the functions that will be used as callbacks when various parts of the scroll bar are clicked on. These are all functions of a single argument, the @@ -640,7 +673,8 @@ Returns a real number within the specified range. \Defclass {scroll-bar-pane} -The class that implements a portable scroll bar; a subclass of \cl{scroll-bar}. +The instantiable class that implements a portable scroll bar; a subclass of +\cl{scroll-bar}. \Gadget {slider} @@ -649,14 +683,31 @@ The \cl{slider} gadget corresponds to a slider. \Defclass {slider} -The class that implements a slider. This is a subclass of \cl{value-gadget}, -\cl{oriented-gadget}, \cl{range-gadget-mixin}, and \cl{labelled-gadget}. +The instantiable class that implements an abstract slider. This is a subclass +of \cl{value-gadget}, \cl{oriented-gadget-mixin}, \cl{range-gadget-mixin}, and +\cl{labelled-gadget-mixin}. \definitarg {:drag-callback} -\Definitarg {:show-value-p} +\definitarg {:show-value-p} +\Definitarg {:decimal-places} -Specifies the drag callback for the slider, and whether the slider should show -its current value. +Specifies the drag callback for the slider, whether the slider should show its +current value, and how many decimal places to the right of the decimal point +should be displayed when the slider is showing its current value. + +\definitarg {:min-label} +\definitarg {:max-label} +\Definitarg {:range-label-text-style} + +Specifies a label to be used at the low end and high end of the sldier, and what +the text style of those labels should be. + +\definitarg {:number-of-tick-marks} +\Definitarg {:number-of-quanta} + +Specifies the number of tick marks that should be drawn on the scroll bar, and +the number of quanta in the scroll bar. If the scroll bar is quantized, the +scroll bar will consist of discrete values rather than continuous values. \Defgeneric {gadget-show-value-p} {slider} @@ -686,26 +737,29 @@ Returns a real number within the specified range. \Defclass {slider-pane} -The class that implements a portable slider; a subclass of \cl{slider}. +The instantiable class that implements a portable slider; a subclass of +\cl{slider}. -\Gadget {radio-box} +\subsection {The {\tt radio-box} and {\tt check-box} Gadgets} -A radio box is a special kind of gadget that constrains one or more toggle -buttons. At any one time, only one of the buttons managed by the radio box may -be ``on''. The contents of a radio box are its buttons, and as such a radio box -is responsible for laying out the buttons that it contains. A radio box is a -client of each of its buttons so that the value of the radio box can be properly -computed. +Radio boxes and check boxes are special kinds of gadgets that constrain one or +more toggle buttons. At any one time, only one of the buttons managed by the +radio box, or zero or more of the buttons managed by a check box, may be ``on''. +The contents of a radio box or a check box are its buttons, and as such a radio +box or check bnox is responsible for laying out the buttons that it contains. A +radio box or check box is a client of each of its buttons so that the value of +the radio or check box can be properly computed. As the current selection changes, the previously selected button and the newly selected button both have their \cl{value-changed-callback} handlers invoked. - \Defclass {radio-box} -The class that implements a radio box. It is a subclass of \cl{value-gadget} -and \cl{oriented-gadget}. +The instantiable class that implements an abstract radio box, that is, a gadget +that constrains a number of toggle buttons, only one of which may be selected at +any one time. It is a subclass of \cl{value-gadget} and +\cl{oriented-gadget-mixin}. \Definitarg {:current-selection} @@ -717,20 +771,64 @@ This is used to specify which button, if any, should be initially selected. Returns (or sets) the current selection for the radio box. The current selection will be one of the toggle buttons in the box. +\Defgeneric {radio-box-selections} {radio-box} + +Returns a sequence of all of the selections in the radio box. The elements of +the sequence will be toggle buttons. + \Defmethod {gadget-value} {(button \cl{radio-box})} -Returns the selected button. +Returns the selected button. This will return the same value as +\cl{radio-box-current-selection} \Defclass {radio-box-pane} -The class that implements a portable radio box; a subclass of \cl{radio-box}. +The instantiable class that implements a portable radio box; a subclass of +\cl{radio-box}. + + +\Defclass {check-box} + +The instantiable class that implements an abstract check box, that is, a gadget +that constrains a number of toggle buttons, zero or more of which may be +selected at any one time. It is a subclass of \cl{value-gadget} and +\cl{oriented-gadget-mixin}. + +\Definitarg {:current-selection} + +This is used to specify which buttons, if any, should be initially selected. + +\defgeneric {check-box-current-selection} {check-box} +\Defgeneric {(setf check-box-current-selection)} {button check-box} + +Returns (or sets) the current selection for the check box. The current +selection will be a list of zero or more of the toggle buttons in the box. + +\Defgeneric {check-box-selections} {check-box} + +Returns a sequence of all of the selections in the check box. The elements of +the sequence will be toggle buttons. + +\Defmethod {gadget-value} {(button \cl{check-box})} + +Returns the selected buttons as a list. This will return the same value as +\cl{check-box-current-selection} + +\Defclass {check-box-pane} + +The instantiable class that implements a portable check box; a subclass of +\cl{check-box}. -\Defmacro {with-radio-box} {(\rest options) \body body} + +\Defmacro {with-radio-box} {(\rest options \key (type \cl{:one-of}) \allow) \body body} Creates a radio box whose buttons are created by the forms in \arg{body}. The macro \cl{radio-box-current-selection} can be wrapped around one of forms in \arg{body} in order to indicate that that button is the current selection. +If \arg{type} is \cl{:one-of}, a \cl{radio-box} will be created. If \arg{type} +is \cl{:some-of}, a \cl{check-box} will be created. + For example, the following creates a radio box with three buttons in it, the second of which is initially selected. @@ -742,6 +840,110 @@ second of which is initially selected. (make-pane 'toggle-button :label "Quad")) \end{verbatim} +The following simpler form can also be used when the programmer does not need to +control the appearance of each button closely. + +\begin{verbatim} +(with-radio-box () + "Mono" "Stereo" "Quad") +\end{verbatim} + + +\subsection {The {\tt list-pane} and {\tt option-pane} Gadgets} + +\Defclass {list-pane} + +The instantiable class that implements an abstract list pane, that is, a gadget +whose semantics are similar to a radio box or check box, but whose visual +appearance is a list of buttons. It is a subclass of \cl{value-gadget}. + +\Definitarg {:mode} + +Either \cl{:nonexclusive} or \cl{:exclusive}. When it is \cl{:exclusive}, the +list pane acts like a radio box, that is, only a single item can be selected. +Otherwise, the list pane acts like a check box, in that zero or more items can +be selected. The default is \cl{:exclusive}. + +\definitarg {:items} +\definitarg {:name-key} +\definitarg {:value-key} +\Definitarg {:test} + +The \cl{:items} initarg specifies a sequence of items to use as the items of the +list pane. The name of the item is extracted by the function that is the value +of the \cl{:name-key} initarg, which defaults to \cl{princ-to-string}. The +value of the item is extracted by the function that is the value of the +\cl{:value-key} initarg, which defaults to \cl{identity}. The \cl{:test} +initarg specifies a function of two arguments that is used to compare items; it +defaults to \cl{eql}. + +For example, + +\begin{verbatim} +D,#TD1PsT[Begin using 006 escapes](1 0 (NIL 0) (SAGE:SANS-SERIF-BODY SAGE::TYPEWRITER :NORMAL) "CPTFONT")(make-pane 'list-pane +0 1:value '("Lisp" "C++") +0 1:mode :nonexclusive +0 1:items '("Lisp" "Fortran" "C" "C++" "Cobol" "Ada") +0 1:test 'string=) +0\end{varbatim} + +\Defmethod {gadget-value} {(button \cl{list-pane})} + +Returns the single selected item when the mode is \cl{:exclusive}, or a sequence +of selected items when the mode is \cl{:nonexclusive}. + +\Defclass {generic-list-pane} + +The instantiable class that implements a portable list pane; a subclass of +\cl{list-pane}. + +\Defclass {option-pane} + +The instantiable class that implements an abstract option pane, that is, a +gadget whose semantics are identical to a list pane, but whose visual appearance +is a single push button which, when pressed, pops up a menu of selections.. It +is a subclass of \cl{value-gadget}. + +\Definitarg {:mode} + +Either \cl{:nonexclusive} or \cl{:exclusive}. When it is \cl{:exclusive}, the +option pane acts like a radio box, that is, only a single item can be selected. +Otherwise, the option pane acts like a check box, in that zero or more items can +be selected. The default is \cl{:exclusive}. + +\definitarg {:items} +\definitarg {:name-key} +\definitarg {:value-key} +\Definitarg {:test} + +The \cl{:items} initarg specifies a sequence of items to use as the items of the +option pane. The name of the item is extracted by the function that is the value +of the \cl{:name-key} initarg, which defaults to \cl{princ-to-string}. The +value of the item is extracted by the function that is the value of the +\cl{:value-key} initarg, which defaults to \cl{identity}. The \cl{:test} +initarg specifies a function of two arguments that is used to compare items; it +defaults to \cl{eql}. + +For example, + +\begin{verbatim} +1(make-pane 'option-pane +0 1:value '("Lisp" "C++") +0 1:mode :nonexclusive +0 1:items '("Lisp" "Fortran" "C" "C++" "Cobol" "Ada") +0 1:test 'string=) +0\end{varbatim} + +\Defmethod {gadget-value} {(button \cl{option-pane})} + +Returns the single selected item when the mode is \cl{:exclusive}, or a sequence +of selected items when the mode is \cl{:nonexclusive}. + +\Defclass {generic-option-pane} + +The instantiable class that implements a portable option pane; a subclass of +\cl{option-pane}. + \Gadget {text-field} @@ -749,42 +951,50 @@ The \cl{text-field} gadget corresponds to a small field containing text. \Defclass {text-field} -The class that implements a text field. This is a subclass of \cl{value-gadget} -and \cl{action-gadget}. +The instantiable class that implements an abstract text field. This is a subclass of +\cl{value-gadget} and \cl{action-gadget}. The value of a text field is the text string. +\Definitarg {:editable-p} + +This is used to specify whether or not the text field may be edited. + \Defmethod {gadget-value} {(button \cl{text-field})} Returns the resulting string. \Defclass {text-field-pane} -The class that implements a portable text field; a subclass of \cl{text-field}. +The instantiable class that implements a portable text field; a subclass of +\cl{text-field}. \Gadget {text-editor} -The \cl{text-editor} gadget corresponds to a large field containing text. - -\definitarg {:width} -\Definitarg {:height} - -Specifies the width and height of the text editor. +The \cl{text-editor} gadget corresponds to a large field containing multiple +lines of text. \Defclass {text-editor} -The class that implements a large text field. This is a subclass of \cl{text-field}. +The instantiable class that implements an abstract large text field. This is a +subclass of \cl{text-field}. The value of a text editor is the text string. +\definitarg {:ncolumns} +\Definitarg {:nlines} + +Specifies the width and height of the text editor in columns and number of lines. + \Defmethod {gadget-value} {(button \cl{text-editor})} Returns the resulting string. \Defclass {text-editor-pane} -The class that implements a portable text editor; a subclass of \cl{text-editor}. +The instantiable class that implements a portable text editor; a subclass of +\cl{text-editor}. \section {Integrating Gadgets and Output Records} @@ -801,16 +1011,20 @@ system that the toolkit object representing the gadget has moved, \Defclass {gadget-output-record} -The class the represents an output record class that contains a gadget. This is -a subclass of \cl{output-record}. +The instantiable class the represents an output record class that contains a +gadget. This is a subclass of \cl{output-record}. -\Defmacro {with-output-as-gadget} {(stream) \body body} +\Defmacro {with-output-as-gadget} {(stream \rest options) \body body} Invokes \arg{body} to create a gadget, and then creates a gadget output record that contains the gadget and install's it into the output history of the output recording stream \arg{stream}. The returned value of \arg{body} must be the gadget. +The options in \arg{options} are passed as initargs to the call to +\cl{invoke-with-new-output-record} that is used to create the gadget output +record. + The \arg{stream} argument is not evaluated, and must be a symbol that is bound to an output recording stream. If \arg{stream} is \cl{t}, \cl{*standard-output*} is used. \arg{body} may have zero or more declarations as its first forms. @@ -822,12 +1036,12 @@ radio box that itself contains several toggle buttons: (with-output-as-gadget (stream) (let* ((radio-box (make-pane 'radio-box - :client stream :id 'radio-box))) + :client stream :id 'radio-box))) (dolist (item sequence) (make-pane 'toggle-button - :label (princ-to-string (item-name item)) - :value (item-value item) - :id item :parent radio-box)) + :label (princ-to-string (item-name item)) + :value (item-value item) + :id item :parent radio-box)) radio-box)) \end{verbatim} @@ -843,12 +1057,12 @@ into the presentation type system to execute a command might be as follows: (declare (ignore button)) (throw-highlighted-presentation (make-instance 'standard-presentation - :object `(com-exit ,*application-frame*) - :type 'command) + :object `(com-exit ,*application-frame*) + :type 'command) *input-context* (make-instance 'pointer-button-press-event - :sheet (sheet-parent button) - :x 0 :y 0 - :modifiers 0 - :button +pointer-left-button+))))) + :sheet (sheet-parent button) + :x 0 :y 0 + :modifiers 0 + :button +pointer-left-button+))))) \end{verbatim} diff --git a/specs/glossary.tex b/specs/glossary.tex index 58d71acf..97a615c1 100644 --- a/specs/glossary.tex +++ b/specs/glossary.tex @@ -212,7 +212,7 @@ to modify typed-in input.} \term{input editing}.} \GlossaryEntry {input stream designator} {n.} {A Lisp object that is either an -input stream, or the symbol \cl{t}, which is taken to mean \cl{*query-io*}.} +input stream, or the symbol \cl{t}, which is taken to mean \cl{*standard-input*}.} \GlossaryEntry {interactive stream} {n.} {A stream that supports both input from and output to the user in an interactive fashion.} @@ -292,8 +292,8 @@ that is responsible for managing host display server resources and for processing input events received from the host display server.} \GlossaryEntry {position} {n.} {1.~A position on a plane, such as CLIM's -abstract drawing plane. 2.~Two real number values $x$ and $y$ that represent a -\term{position}.} +abstract drawing plane. 2.~A pair of real number values $x$ and $y$ that +represent a \term{position}.} \GlossaryEntry {presentation} {n.} {1.~An association between an object and a \term{presentation type} with some output on a \term{output recording stream}. @@ -429,7 +429,7 @@ represents a \term{view}.} \GlossaryEntry {viewport} {n.} {The portion of the drawing plane of a sheet's medium that is visible on a display device.} -\GlossaryEntry {volatile} {adj.} {1.~(of an immutable object) Having components +\GlossaryEntry {volatile} {adj.} {(of an immutable object) Having components that cannot be modified by the programmer at the protocol level, but which may be modified internally by CLIM. \term{Volatile} objects reflect internal state of CLIM.} diff --git a/specs/graph-formatting.tex b/specs/graph-formatting.tex index 5f5009c6..fdde403c 100644 --- a/specs/graph-formatting.tex +++ b/specs/graph-formatting.tex @@ -89,23 +89,26 @@ the default is \cl{eql}. \arg{duplicate-key} and \arg{duplicate-test} have dynamic extent. \arg{generation-separation} is the amount of space to leave between successive -generations of the graph; the default is 20. \arg{within-generation-separation} -is the amount of space to leave between nodes in the same generation of the -graph; the default is 10. \arg{generation-separation} and -\arg{within-generation-separation} are specified in the same way as the -\arg{inter-row-spacing} argument to \cl{formatting-table}. +generations of the graph; the default should be chosen so that the resulting +graph is visually pleasing. \arg{within-generation-separation} is the amount of +space to leave between nodes in the same generation of the graph; the default +should be chosen so that the resulting graph is visually pleasing. +\arg{generation-separation} and \arg{within-generation-separation} are specified +in the same way as the \arg{inter-row-spacing} argument to +\cl{formatting-table}. When \arg{center-nodes} is \term{true}, each node of the graph is centered with respect to the widest node in the same generation. The default is \term{false}. \arg{arc-drawer} is a function of seven positional and some unspecified keyword arguments that is responsible for drawing the arcs from one node to another; it -has dynamic extent. The positional arguments are the stream, the ``from'' node, -the ``to'' node, the ``from'' $x$ and $y$ position, and the ``to'' $x$ and $y$ -position. The keyword arguments gotten from \arg{arc-drawing-options} are -typically line drawing options, such as for \cl{draw-line*}. If \arg{arc-drawer} -is unsupplied, the default behavior is to draw a thin line from the ``from'' node -to the ``to'' node using \cl{draw-line*}. +has dynamic extent. The positional arguments are the stream, the ``from'' +node's object, the ``to'' node's object, the ``from'' $x$ and $y$ position, and +the ``to'' $x$ and $y$ position. The keyword arguments gotten from +\arg{arc-drawing-options} are typically line drawing options, such as for +\cl{draw-line*}. If \arg{arc-drawer} is unsupplied, the default behavior is to +draw a thin line from the ``from'' node to the ``to'' node using +\cl{draw-line*}. \arg{graph-type} is a keyword that specifies the type of graph to draw. All CLIM implementations must support graphs of type \cl{:tree}, @@ -139,7 +142,7 @@ the graph output record. The protocol class that represents a graph; a subclass of \cl{output-record}. \IfYouWantClass {a} {graph output record} {graph-output-record} -\Defun {graph-output-record-p} {object} +\Defpredicate {graph-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{graph output record}, otherwise returns \term{false}. @@ -201,7 +204,7 @@ those graph node output records that correspond to the root objects. \arg{duplicate-key}, and \arg{duplicate-test} are as for \cl{format-graph-from-roots}. -\Defgeneric {layout-graph-nodes} {graph-record stream} +\Defgeneric {layout-graph-nodes} {graph-record stream arc-drawer arc-drawing-options} This function is responsible for laying out the nodes in the graph contained in the output record \arg{graph-record}. It is called after the graph output has @@ -224,7 +227,7 @@ The protocol class that represents a node in graph; a subclass of \cl{output-record}. \IfYouWantClass {a} {graph node output record} {graph-node-output-record} -\Defun {graph-node-output-record-p} {object} +\Defpredicate {graph-node-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{graph node output record}, otherwise returns \term{false}. diff --git a/specs/graphics.tex b/specs/graphics.tex index 179cb30d..c1a2fe74 100644 --- a/specs/graphics.tex +++ b/specs/graphics.tex @@ -56,19 +56,21 @@ identify a point in the drawing plane. \paragraph {Sheets and Mediums.} -In this chapter, we use a sheet as a destination for output. Associated with a -sheet is a medium, which has a drawing plane, two designs called the medium's -foreground and background, a transformation, a clipping region, a line style, -and a text style. There are per-medium, dynamically scoped, default drawing -options. Different medium classes are provided to allow programmers to draw on -different sorts of devices, such as displays, printers, and virtual devices such -as bitmaps. - -Note that a stream is a special kind of sheet that implements the stream -protocol; streams include additional state such as the current text cursor -(which is some point in the drawing plane). While the functions defined here -are specified to be called on sheets, they can also be called on streams and -mediums. +In this chapter, we use a medium as a destination for output. The medium has a +drawing plane, two designs called the medium's foreground and background, a +transformation, a clipping region, a line style, and a text style. There are +per-medium, dynamically scoped, default drawing options. Different medium +classes are provided to allow programmers to draw on different sorts of devices, +such as displays, printers, and virtual devices such as bitmaps. + +Many sheets can be used for doing output, so the drawing functions can also take +a sheet as the output argument. In this case, drawing function ``trampolines'' +to the sheet's medium. So, while the functions defined here are specified to be +called on sheets, they can also be called on sheets. + +A stream is a special kind of sheet that implements the stream protocol; streams +include additional state such as the current text cursor (which is some point in +the drawing plane). By default, the ``fundamental'' coordinate system of a CLIM stream (not a general sheet or medium, whose fundamental coordinate system is not defined) is @@ -256,9 +258,9 @@ seen clearly in Figure~\ref{inscribed-circle} if we attempt to draw a rectangle and circle overlaid with the following code: \begin{verbatim} -(defun draw-test (sheet radius) - (draw-circle* sheet 0 0 radius :ink +foreground-ink+) - (draw-rectangle* sheet (- radius) (- radius) (+ radius) (+ radius) +(defun draw-test (medium radius) + (draw-circle* medium 0 0 radius :ink +foreground-ink+) + (draw-rectangle* medium (- radius) (- radius) (+ radius) (+ radius) :ink +flipping-ink+)) \end{verbatim} @@ -347,8 +349,10 @@ signalled. See Chapter~\ref{drawing-options} for a more complete discussion of the drawing options. An error will be signalled if any drawing function is called on a sheet that is mute for output. -While the functions in this section are specified to be called on sheets, they -can also be called on streams and mediums. +While the functions in this section are specified to be called on mediums, they +can also be called on sheets and streams. CLIM implementations will typically +implement the method on a medium, and write a ``trampoline'' on the various +sheet and stream classes that trampolines to the medium. {\bf Implementation note:} The drawing functions are all specified as ordinary functions, not as generic functions. This is intended to ease the task of @@ -375,11 +379,11 @@ extensions to CLIM. \subsection {Basic Drawing Functions} -\defun {draw-point} {sheet point \key \DrawingOptions \PointOptions} -\Defun {draw-point*} {sheet x y \key \DrawingOptions \PointOptions} +\defun {draw-point} {medium point \key \DrawingOptions \PointOptions} +\Defun {draw-point*} {medium x y \key \DrawingOptions \PointOptions} These functions (structured and spread arguments, respectively) draw a single -point on the \term{sheet} \arg{sheet} at the \term{point} \arg{point} (or the +point on the \term{medium} \arg{medium} at the \term{point} \arg{point} (or the position $(x,y)$). The unit and thickness components of the current line style (see @@ -387,33 +391,33 @@ Chapter~\ref{drawing-options}) affect the drawing of the point by controlling the size on the display device of the ``blob'' that is used to render the point. -\defun {draw-points} {sheet point-seq \key \DrawingOptions \PointOptions} -\Defun {draw-points*} {sheet coord-seq \key \DrawingOptions \PointOptions} +\defun {draw-points} {medium points \key \DrawingOptions \PointOptions} +\Defun {draw-points*} {medium position-seq \key \DrawingOptions \PointOptions} These functions (structured and spread arguments, respectively) draw a set of -points on the \term{sheet} \arg{sheet}. \arg{point-seq} is a sequence of -point objects; \arg{coord-seq} is a sequence of coordinate pairs, which are real -numbers. It is an error if \arg{coord-seq} does not contain an even number of -elements. +points on the \term{medium} \arg{medium}. \arg{points} is a sequence of point +objects; \arg{position-seq} is a sequence of coordinate pairs, which are real +numbers. It is an error if \arg{position-seq} does not contain an even number +of elements. -These functions exist as equivalents to +Ignoring the drawing options, these functions exist as equivalents to \begin{verbatim} -(map nil #`(lambda (point) (draw-point sheet point)) point-seq) +(map nil #`(lambda (point) (draw-point medium point)) points) \end{verbatim} and \begin{verbatim} (do ((i 0 (+ i 2))) - ((= i (length coord-seq))) - (draw-point* sheet (elt coord-seq i) (elt coord-seq (+ i 1)))) + ((= i (length position-seq))) + (draw-point* medium (elt position-seq i) (elt position-seq (+ i 1)))) \end{verbatim} for convenience and efficiency. -\defun {draw-line} {sheet point1 point2 \key \DrawingOptions \LineCapOptions} -\Defun {draw-line*} {sheet x1 y1 x2 y2 \key \DrawingOptions \LineCapOptions} +\defun {draw-line} {medium point1 point2 \key \DrawingOptions \LineCapOptions} +\Defun {draw-line*} {medium x1 y1 x2 y2 \key \DrawingOptions \LineCapOptions} These functions (structured and spread arguments, respectively) draw a line -segment on the \term{sheet} \arg{sheet} from the \term{point} \arg{point1} to +segment on the \term{medium} \arg{medium} from the \term{point} \arg{point1} to \arg{point2} (or from the position (\arg{x1},\arg{y1}) to (\arg{x2},\arg{y2})). The current line style (see Chapter~\ref{drawing-options}) affects the drawing @@ -421,35 +425,35 @@ of the line in the obvious way, except that the joint shape has no effect. Dashed lines start dashing at \arg{point1}. -\defun {draw-lines} {sheet point-seq \key \DrawingOptions \LineCapOptions} -\Defun {draw-lines*} {sheet coord-seq \key \DrawingOptions \LineCapOptions} +\defun {draw-lines} {medium points \key \DrawingOptions \LineCapOptions} +\Defun {draw-lines*} {medium position-seq \key \DrawingOptions \LineCapOptions} These functions (structured and spread arguments, respectively) draw a set of -disconnected line segments. \arg{point-seq} is a sequence of point objects; -\arg{coord-seq} is a sequence of coordinate pairs. It is an error if -\arg{coord-seq} does not contain an even number of elements. +disconnected line segments. \arg{points} is a sequence of point objects; +\arg{position-seq} is a sequence of coordinate pairs. It is an error if +\arg{position-seq} does not contain an even number of elements. -These functions are equivalent to +Ignoring the drawing options, these functions are equivalent to \begin{verbatim} (do ((i 0 (+ i 2))) - ((= i (length point-seq))) - (draw-line sheet (elt point-seq i) (elt point-seq (1+ i)))) + ((= i (length points))) + (draw-line medium (elt points i) (elt points (1+ i)))) \end{verbatim} and \begin{verbatim} (do ((i 0 (+ i 4))) - ((= i (length coord-seq))) - (draw-line* sheet (elt coord-seq i) (elt coord-seq (+ i 1)) - (elt coord-seq (+ i 2)) (elt coord-seq (+ i 3)))) + ((= i (length position-seq))) + (draw-line* medium (elt position-seq i) (elt position-seq (+ i 1)) + (elt position-seq (+ i 2)) (elt position-seq (+ i 3)))) \end{verbatim} -\defun {draw-polygon} {sheet point-seq \key (filled \cl{t}) (closed \cl{t}) +\defun {draw-polygon} {medium point-seq \key (filled \cl{t}) (closed \cl{t}) \DrawingOptions \LineJointCapOptions} -\Defun {draw-polygon*} {sheet coord-seq \key (filled \cl{t}) (closed \cl{t}) +\Defun {draw-polygon*} {medium coord-seq \key (filled \cl{t}) (closed \cl{t}) \DrawingOptions \LineJointCapOptions} -Draws a polygon or polyline on the \term{sheet} \arg{sheet}. When +Draws a polygon or polyline on the \term{medium} \arg{medium}. When \arg{filled} is \term{false}, this draws a set of connected lines, otherwise it draws a filled polygon. If \arg{closed} is \term{true} (the default) and \arg{filled} is \term{false}, it ensures that a segment is drawn that connects @@ -468,10 +472,12 @@ If \arg{filled} is \term{true}, a closed polygon is drawn and filled in. In this case, \arg{closed} is assumed to be \term{true} as well. -\Defun {draw-rectangle*} {sheet x1 y1 x2 y2 \key (filled \cl{t}) +\Defun {draw-rectangle} {medium point1 point2 \key (filled \cl{t}) + \DrawingOptions \LineJointOptions} +\Defun {draw-rectangle*} {medium x1 y1 x2 y2 \key (filled \cl{t}) \DrawingOptions \LineJointOptions} -Draws either a filled or unfilled rectangle on the \term{sheet} \arg{sheet} that +Draws either a filled or unfilled rectangle on the \term{medium} \arg{medium} that has its sides aligned with the coordinate axes of the native coordinate system. One corner of the rectangle is at the position (\arg{x1},\arg{y1}) and the opposite corner is at (\arg{x2},\arg{y2}). The arguments \arg{x1}, \arg{y1}, @@ -483,16 +489,39 @@ of unfilled rectangles in the obvious way, except that the cap shape has no effect. -\defun {draw-ellipse} {sheet center-pt radius-1-dx radius-1-dy radius-2-dx radius-2-dy +\defun {draw-rectangles} {medium points \key \DrawingOptions \LineJointOptions} +\Defun {draw-rectangles*} {medium position-seq \key \DrawingOptions \LineJointOptions} + +These functions (structured and spread arguments, respectively) draw a set of +rectangles. \arg{points} is a sequence of point objects; \arg{position-seq} is +a sequence of coordinate pairs. It is an error if \arg{position-seq} does not +contain an even number of elements. + +Ignoring the drawing options, these functions are equivalent to +\begin{verbatim} +(do ((i 0 (+ i 2))) + ((= i (length points))) + (draw-rectangle medium (elt points i) (elt points (1+ i)))) +\end{verbatim} +and +\begin{verbatim} +(do ((i 0 (+ i 4))) + ((= i (length position-seq))) + (draw-rectangle* medium (elt position-seq i) (elt position-seq (+ i 1)) + (elt position-seq (+ i 2)) (elt position-seq (+ i 3)))) +\end{verbatim} + + +\defun {draw-ellipse} {medium center-pt radius-1-dx radius-1-dy radius-2-dx radius-2-dy \key (filled \cl{t}) start-angle end-angle \DrawingOptions \LineCapOptions} -\Defun {draw-ellipse*} {sheet center-x center-y radius-1-dx radius-1-dy radius-2-dx radius-2-dy +\Defun {draw-ellipse*} {medium center-x center-y radius-1-dx radius-1-dy radius-2-dx radius-2-dy \key (filled \cl{t}) start-angle end-angle \DrawingOptions \LineCapOptions} These functions (structured and spread arguments, respectively) draw an ellipse (when \arg{filled} is \term{true}, the default) or an elliptical arc (when -\arg{filled} is \term{false}) on the \term{sheet} \arg{sheet}. The center of +\arg{filled} is \term{false}) on the \term{medium} \arg{medium}. The center of the ellipse is the \term{point} \arg{center-pt} (or the position (\arg{center-x},\arg{center-y})). @@ -522,14 +551,14 @@ that the joint shape has no effect. Dashed elliptical arcs start ``dashing'' at \arg{start-angle}. -\defun {draw-circle} {sheet center-pt radius \key (filled \cl{t}) start-angle end-angle +\defun {draw-circle} {medium center-pt radius \key (filled \cl{t}) start-angle end-angle \DrawingOptions \LineCapOptions} -\Defun {draw-circle*} {sheet center-x center-y radius \key (filled \cl{t}) start-angle end-angle +\Defun {draw-circle*} {medium center-x center-y radius \key (filled \cl{t}) start-angle end-angle \DrawingOptions \LineCapOptions} These functions (structured and spread arguments, respectively) draw a circle (when \arg{filled} is \term{true}, the default) or a circular arc (when -\arg{filled} is \term{false}) on the \term{sheet} \arg{sheet}. The center of +\arg{filled} is \term{false}) on the \term{medium} \arg{medium}. The center of the circle is \arg{center-pt} or (\arg{center-x},\arg{center-y}) and the radius is \arg{radius}. These are just special cases of \cl{draw-ellipse} and \cl{draw-ellipse*}. \arg{filled} is as for \cl{draw-ellipse*}. @@ -541,19 +570,19 @@ above. The ``filled arc'' behavior is the same as that of an ellipse, above. -\defun {draw-text} {sheet string-or-char point +\defun {draw-text} {medium string-or-char point \key text-style (start \cl{0}) end (align-x \cl{:left}) (align-y \cl{:baseline}) toward-point transform-glyphs \DrawingOptions \TextOptions} -\Defun {draw-text*} {sheet string-or-char x y +\Defun {draw-text*} {medium string-or-char x y \key text-style (start \cl{0}) end (align-x \cl{:left}) (align-y \cl{:baseline}) toward-x toward-y transform-glyphs \DrawingOptions \TextOptions} -The text specified by \arg{string-or-char} is drawn on the \term{sheet} -\arg{sheet} starting at the position specified by the \term{point} \arg{point} +The text specified by \arg{string-or-char} is drawn on the \term{medium} +\arg{medium} starting at the position specified by the \term{point} \arg{point} (or the position $(x,y)$). The exact definition of ``starting at'' is dependent on \arg{align-x} and \arg{align-y}. \arg{align-x} is one of \cl{:left}, \cl{:center}, or \cl{:right}. \arg{align-y} is one of \cl{:baseline}, @@ -562,7 +591,7 @@ and \arg{align-y} defaults to \cl{:baseline}; with these defaults, the first glyph is drawn with its left edge and its baseline at \arg{point}. \arg{text-style} defaults to \cl{nil}, meaning that the text will be drawn using -the current text style of the sheet's medium. +the current text style of the medium. \arg{start} and \arg{end} specify the start and end of the string, in the case where \arg{string-or-char} is a string. If \arg{start} is supplied, it must be @@ -595,15 +624,13 @@ CLIM also provides a few compound drawing functions. The compound drawing functions could be composed by a programmer from the basic drawing functions, but are provided by CLIM because they are commonly used. -\defun {draw-arrow} {sheet point-1 point-2 \key \DrawingOptions \LineCapOptions - to-head from-head - head-length head-width} -\Defun {draw-arrow*} {sheet x1 y1 x2 y2 \key \DrawingOptions \LineCapOptions - from-head to-head - head-length head-width} +\defun {draw-arrow} {medium point-1 point-2 \key \DrawingOptions \LineCapOptions + to-head from-head head-length head-width} +\Defun {draw-arrow*} {medium x1 y1 x2 y2 \key \DrawingOptions \LineCapOptions + from-head to-head head-length head-width} These functions (structured and spread arguments, respectively) draw a line -segment on the \term{sheet} \arg{sheet} from the \term{point} \arg{point1} to +segment on the \term{medium} \arg{medium} from the \term{point} \arg{point1} to \arg{point2} (or from the position (\arg{x1},\arg{y1}) to (\arg{x2},\arg{y2})). If \arg{to-head} is \term{true} (the default), then the ``to'' end of the line is capped by an arrowhead. If \arg{from-head} is \term{true} (the default is @@ -616,13 +643,13 @@ of the line portion of the arrow in the obvious way, except that the joint shape has no effect. Dashed arrows start dashing at \arg{point1}. -\defun {draw-oval} {sheet center-pt x-radius y-radius \key (filled \cl{t}) - \DrawingOptions \LineCapOptions} -\Defun {draw-oval*} {sheet center-x center-y x-radius y-radius \key (filled \cl{t}) - \DrawingOptions \LineCapOptions} +\defun {draw-oval} {medium center-pt x-radius y-radius \key (filled \cl{t}) + \DrawingOptions \LineCapOptions} +\Defun {draw-oval*} {medium center-x center-y x-radius y-radius \key (filled \cl{t}) + \DrawingOptions \LineCapOptions} These functions (structured and spread arguments, respectively) draw a filled or -unfilled oval (that is, a ``race-track'' shape) on the \term{sheet} \arg{sheet}. +unfilled oval (that is, a ``race-track'' shape) on the \term{medium} \arg{medium}. The oval is centered on \arg{center-pt} (or (\arg{center-x},\arg{center-y})). If \arg{x-radius} or \arg{y-radius} is $0$, then a circle is drawn with the specified non-zero radius. Other, a figure is drawn that results from drawing a @@ -633,30 +660,31 @@ short sides with a semicircular arc of the appropriate size. \section {Pixmaps} A \concept{pixmap} can be thought of as an ``off-screen window'', that is, a -sheet that can be used for graphical output, but is not visible on any display +medium that can be used for graphical output, but is not visible on any display device. Pixmaps are provided to allow a programmer to generate a piece of output associated with some display device that can then be rapidly drawn on a real display device. For example, an electrical CAD system might generate a pixmap that corresponds to a complex, frequently used part in a VLSI schematic, and then use \cl{copy-from-pixmap} to draw the part as needed. -The exact representation of a pixmap is explicitly unspecified. There is no -interaction between the pixmap operations and output recording, that is, -displaying a pixmap on a sheet is a pure drawing operation that affects only the -display, not the output history. Some sheets may not support pixmaps; in this -case, an error will be signalled. +The exact representation of a pixmap is explicitly unspecified. There +is no interaction between the pixmap operations and output recording, +that is, displaying a pixmap on a sheet or medium is a pure drawing +operation that affects only the display, not the output history. Some +mediums may not support pixmaps; in this case, an error will be +signalled. -\Defgeneric {allocate-pixmap} {sheet width height} +\Defgeneric {allocate-pixmap} {medium width height} -Allocates and returns a pixmap object that can be used on any sheet that shares -the same characteristics as \arg{sheet}. (The exact definition of ``shared -characteristics'' will vary from host to host.) \arg{sheet} can be a sheet, a -medium, or a stream. +Allocates and returns a pixmap object that can be used on any medium that shares +the same characteristics as \arg{medium}. (The exact definition of ``shared +characteristics'' will vary from host to host.) \arg{medium} can be a medium, a +sheet, or a stream. -The resulting pixmap will be \arg{width} units wide, \arg{height} units high, -and as deep as is necessary to store the information for the sheet. The exact -representation of pixmaps is explicitly unspecified. +The resulting pixmap will be at least \arg{width} units wide, \arg{height} units +high, and as deep as is necessary to store the information for the medium. The +exact representation of pixmaps is explicitly unspecified. The returned value is the pixmap. @@ -669,62 +697,76 @@ Deallocates the pixmap \arg{pixmap}. \defgeneric {pixmap-height} {pixmap} \Defgeneric {pixmap-depth} {pixmap} -These functions return, respectively, the programmer-specified width and height, -and the depth of the pixmap \arg{pixmap}. +These functions return, respectively, the width, height, and depth of the pixmap +\arg{pixmap}. These values may be different from the programmer-specified +values, since some window systems need to allocate pixmaps only of particular +sizes. -\Defgeneric {copy-to-pixmap} {sheet sheet-x sheet-y width height - \optional pixmap (pixmap-x \cl{0}) (pixmap-y \cl{0})} +\Defun {copy-to-pixmap} {medium medium-x medium-y width height + \optional pixmap (pixmap-x \cl{0}) (pixmap-y \cl{0})} -Copies the pixels from the sheet \arg{sheet} starting at the position specified -by (\arg{sheet-x},\arg{sheet-y}) into the pixmap \arg{pixmap} at the position +Copies the pixels from the medium \arg{medium} starting at the position specified +by (\arg{medium-x},\arg{medium-y}) into the pixmap \arg{pixmap} at the position specified by (\arg{pixmap-x},\arg{pixmap-y}). A rectangle whose width and -height is specified by \arg{width} and \arg{height} is copied. \arg{sheet-x} -and \arg{sheet-y} are specified in user coordinates. (If \arg{sheet} is a -medium or a stream, then \arg{sheet-x} and \arg{sheet-y} are transformed by the -user transformation.) +height is specified by \arg{width} and \arg{height} is copied. \arg{medium-x} +and \arg{medium-y} are specified in user coordinates. (If \arg{medium} is a +medium or a stream, then \arg{medium-x} and \arg{medium-y} are transformed by the +user transformation.) The copying must be done by \cl{medium-copy-copy}. If \arg{pixmap} is not supplied, a new pixmap will be allocated. Otherwise, \arg{pixmap} must be an object returned by \cl{allocate-pixmap} that has the -appropriate characteristics for \arg{sheet}. +appropriate characteristics for \arg{medium}. The returned value is the pixmap. -\Defgeneric {copy-from-pixmap} {pixmap pixmap-x pixmap-y width height - sheet window-x window-y} +\Defun {copy-from-pixmap} {pixmap pixmap-x pixmap-y width height + medium medium-x medium-y} Copies the pixels from the pixmap \arg{pixmap} starting at the position -specified by (\arg{pixmap-x},\arg{pixmap-y}) into the sheet \arg{sheet} at the -position (\arg{sheet-x},\arg{sheet-y}). A rectangle whose width and height is -specified by \arg{width} and \arg{height} is copied. \arg{sheet-x} and -\arg{sheet-y} are specified in user coordinates. (If \arg{sheet} is a medium or -a stream, then \arg{sheet-x} and \arg{sheet-y} are transformed by the user -transformation.) +specified by (\arg{pixmap-x},\arg{pixmap-y}) into the medium \arg{medium} at the +position (\arg{medium-x},\arg{medium-y}). A rectangle whose width and height is +specified by \arg{width} and \arg{height} is copied. \arg{medium-x} and +\arg{medium-y} are specified in user coordinates. (If \arg{medium} is a medium or +a stream, then \arg{medium-x} and \arg{medium-y} are transformed by the user +transformation.) The copying must be done by \cl{medium-copy-copy}. \arg{pixmap} must be an object returned by \cl{allocate-pixmap} that has the -appropriate characteristics for \arg{sheet}. +appropriate characteristics for \arg{medium}. The returned value is the pixmap. -This is intended to specialize on both the \arg{pixmap} and \arg{sheet} -arguments. +\Defgeneric {copy-area} {medium from-x from-y width height to-x to-y} + +Copies the pixels from the medium \arg{medium} starting at the position +specified by (\arg{from-x},\arg{from-y}) to the position (\arg{to-x},\arg{to-y}) +on the same medium. A rectangle whose width and height is specified by +\arg{width} and \arg{height} is copied. \arg{from-x}, \arg{from-y}, \arg{to-x}, +and \arg{to-y} are specified in user coordinates. (If \arg{medium} is a medium +or a stream, then the $x$ and $y$ values are transformed by the user +transformation.) The copying must be done by \cl{medium-copy-copy}. -\Defgeneric {copy-area} {sheet from-x from-y width height to-x to-y} -Copies the pixels from the sheet \arg{sheet} starting at the position specified -by (\arg{from-x},\arg{from-y}) to the position (\arg{to-x},\arg{to-y}) on the -same sheet. A rectangle whose width and height is specified by \arg{width} and -\arg{height} is copied. \arg{from-x}, \arg{from-y}, \arg{to-x}, and \arg{to-y} -are specified in user coordinates. (If \arg{sheet} is a medium or a stream, -then \arg{sheet-x} and \arg{sheet-y} are transformed by the user -transformation.) +\Defgeneric {medium-copy-area} {from-drawable from-x from-y width height + to-drawable to-x to-y} +Copies the pixels from the source drawable \arg{from-drawable} at the position +(\arg{from-x},\arg{from-y}) to the destination drawable \arg{to-drawable} at the +position (\arg{to-x},\arg{to-y}). A rectangle whose width and height is +specified by \arg{width} and \arg{height} is copied. \arg{from-x}, +\arg{from-y}, \arg{to-x}, and \arg{to-y} are specified in user coordinates. +The $x$ and $y$ are transformed by the user transformation. -\Defmacro {with-output-to-pixmap} {(medium-var sheet \key width height) \body body} +This is intended to specialize on both the \arg{from-drawable} and +\arg{to-drawable} arguments. \arg{from-drawable} and \arg{to-drawable} may be +either mediums or pixmaps. + + +\Defmacro {with-output-to-pixmap} {(medium-var medium \key width height) \body body} Binds \arg{medium-var} to a ``pixmap medium'', that is, a medium that does -output to a pixmap with the characteristics appropriate to the sheet -\arg{sheet}, and then evaluates \arg{body} in that context. All the output done +output to a pixmap with the characteristics appropriate to the medium +\arg{medium}, and then evaluates \arg{body} in that context. All the output done to the medium designated by \arg{medium-var} inside of \arg{body} is drawn on the pixmap stream. The pixmap medium must support the medium output protocol, including all of the graphics function. CLIM implementations are permitted, but @@ -737,7 +779,7 @@ contain all of the output done by \arg{body}. \arg{medium-var} must be a symbol; it is not evaluated. -The returned value is a pixmap that can be drawn onto \arg{sheet} using +The returned value is a pixmap that can be drawn onto \arg{medium} using \cl{copy-from-pixmap}. @@ -751,35 +793,27 @@ same arguments as the non-generic spread function equivalents, except the arguments that are keyword arguments in the non-generic functions are positional arguments in the generic functions. -Every port must implement methods for the various graphical drawing generic +Every medium must implement methods for the various graphical drawing generic functions. All of these generic functions take as (specialized) arguments the -port and medium, followed by the drawing function-specific arguments, followed -by the ink, line style (or text style), and clipping region. +medium, followed by the drawing function-specific arguments, followed by the +ink, line style (or text style), and clipping region. -The drawing function-specific arguments will either be $x$ and $y$ positions, or -a sequence of $x$ and $y$ positions. These positions will be in medium +The drawing function-specific arguments will either be $x$ and $y$ positions, +or a sequence of $x$ and $y$ positions. These positions will be in medium coordinates, and must be transformed by applying the medium's device transformation in order to produce device coordinates. Note that the user transformation will have already been applied to the positions when the -port-specific drawing function is called. - -The ink, line style (or text style), and clipping regions arguments are -optional, and default from the medium (\cl{medium-ink}, \cl{medium-line-style} -(or \cl{medium-current-text-style}), and \cl{medium-clipping-region}, -respectively). Each port method will decode the ink, line (or text) style, and -clipping region in a port-specific way and communicate it to the underlying +medium-specific drawing function is called. However, the medium-specific +drawing function will still need to apply the device transformation to the +positions in order to draw the graphics in the appopriate place on the host +window. + +The ink, line style, text style, and clipping regions arguments are not part of +the medium-specific drawing functions. They must be extracted from the medium +object. Each medium-specific method will decode the ink, line (or text) style, +and clipping region in a port-specific way and communicate it to the underlying port. -\issue {SWM} {Do we need to specify \cl{define-graphics-generic} and -\cl{define-graphics-method}, or whatever, so that the graphics protocol is -easier to extend? Such things should also help define the hooks into output -recording.} - -\Issue {SWM, York} {The medium and port layers should be merged. There is no -gain in performance to be had by separating them, since transformations need to -be applied to the coordinates at both layers anyway, and if the two layers are -coalesced, there is better opportunity for caching transformations.} - \subsection {General Behavior of Drawing Functions} @@ -787,22 +821,27 @@ Using \cl{draw-line*} as an example, calling any of the drawing functions specified above results in the following series of function calls on a non-output recording sheet: -\begin{itemize} -\item A program calls \cl{draw-line*} on arguments \arg{sheet}, \arg{x1}, +\begin{itemize} +\item A program calls \cl{draw-line*} on either a sheet or a medium, \arg{x1}, \arg{y1}, \arg{x2}, and \arg{y2}, and perhaps some drawing options. -\item \cl{draw-line*} merges the supplied drawing options into the sheet's -medium, and then calls \cl{medium-draw-line*} on the sheet. (Note that a -compiler macro could detect the case where there are no drawing options or -constant drawing options, and do this at compile time.) +\item \cl{draw-line*} merges the supplied drawing options into the medium, and +then calls \cl{medium-draw-line*} on the sheet or medium. (Note that a compiler +macro could detect the case where there are no drawing options or constant +drawing options, and do this at compile time.) + +\item If \cl{draw-line*} was called on a sheet, the \cl{medium-draw-line*} on +the sheet trampolines to the medium's \cl{medium-draw-line*} method. -\item \cl{medium-draw-line*} on the sheet trampolines to the medium's -\cl{medium-draw-line*} method. +\item An \cl{:around} method for \cl{medium-draw-line*} performs the necessary +user transformations by applying the medium transformation to \arg{x1}, +\arg{y1}, \arg{x2}, and \arg{y2}, and to the clipping region, and then calls the +medium-specific method. -\item \cl{medium-draw-line*} performs the necessary user transformations by -applying the medium transformation to \arg{x1}, \arg{y1}, \arg{x2}, and -\arg{y2}, and to the clipping region. Then \cl{medium-draw-line*} calls -\cl{port-draw-line*} to do the actual drawing. +\item The ``real'' \cl{medium-draw-line*} transforms the start and end +coordinates of the line by the sheet's device transformation, decodes the ink +and line style into port-specific objects, and finally invokes a port-specific +function (such as \cl{xlib:draw-line}) to do the actual drawing. \end{itemize} @@ -811,75 +850,78 @@ applying the medium transformation to \arg{x1}, \arg{y1}, \arg{x2}, and All mediums and all sheets that support the standard output protocol must implement methods for the following generic functions. -{\bf: Note:} CLIM implementations should provide ``trampoline'' methods on -sheets that support the standard output protocol that simply call the same -generic function on the medium. Sheets that support output recording will +The method for each of these drawing functions on the most specific, +implementation-dependent medium class will transform the coordinates by the +device transformation of the medium's sheet, extract the medium's port-specific +``drawable'', and then invoke a port-specific drawing function (such as +\cl{xlib:draw-line}) to do the actual drawing. + +An \cl{:around} on \cl{basic-medium} for each of the drawing functions will have +already transformed the user coordinates to medium coordinates before the most +specific, implementation-dependent method is called. + +{\bf Implementation note:} CLIM implementations should provide ``trampoline'' +methods on sheets that support the standard output protocol that simply call the +same generic function on the medium. Sheets that support output recording will require extra mechanism before delegating to the medium in order to implement such functionality as creating output records and handling scrolling. \Defgeneric {medium-draw-point*} {medium x y} -Draws a point on the \term{medium} \arg{medium}. The point is drawn at -$(x,y)$, transformed by the medium's current transformation. -\cl{medium-draw-point*} will call \cl{port-draw-point*} in order to draw the -point. +Draws a point on the \term{medium} \arg{medium}. \Defgeneric {medium-draw-points*} {medium coord-seq} Draws a set of points on the \term{medium} \arg{medium}. \arg{coord-seq} is a sequence of coordinate pairs, which are real numbers. It is an error if -\arg{coord-seq} does not contain an even number of elements. The coordinates in -\arg{coord-seq} are transformed by the medium's current transformation. -\cl{medium-draw-points*} will call \cl{port-draw-points*} in order to draw the -points. +\arg{coord-seq} does not contain an even number of elements. \Defgeneric {medium-draw-line*} {medium x1 y1 x2 y2} Draws a line on the \term{medium} \arg{medium}. The line is drawn from -$(x1,y1)$ to $(x2,y2)$, with the start and end positions transformed by the -medium's current transformation. \cl{medium-draw-line*} will call -\cl{port-draw-line*} in order to draw the line. +$(x1,y1)$ to $(x2,y2)$. -\Defgeneric {medium-draw-lines*} {medium coord-seq} +\Defgeneric {medium-draw-lines*} {stream position-seq} Draws a set of disconnected lines on the \term{medium} \arg{medium}. -\arg{coord-seq} is a sequence of coordinate pairs, which are real numbers. -It is an error if \arg{coord-seq} does not contain an even number of -elements. The coordinates in \arg{coord-seq} are transformed by the medium's -current transformation. \cl{medium-draw-lines*} will call -\cl{port-draw-lines*} in order to draw the line. +\arg{coord-seq} is a sequence of coordinate pairs, which are real numbers. Each +successive pair of coordinate pairs is taken as the start and end position of +each line. It is an error if \arg{coord-seq} does not contain an even number of +elements. \Defgeneric {medium-draw-polygon*} {medium coord-seq closed} Draws a polygon or polyline on the \term{medium} \arg{medium}. \arg{coord-seq} is a sequence of coordinate pairs, which are real numbers. It is an error if -\arg{coord-seq} does not contain an even number of elements. The coordinates in -\arg{coord-seq} are transformed by the medium's current transformation. -\cl{medium-draw-polygon*} will call \cl{port-draw-polygon*} in order to draw the -polygon. +\arg{coord-seq} does not contain an even number of elements. Each successive +coordinate pair is taken as the position of one vertex of the polygon. \Defgeneric {medium-draw-rectangle*} {medium x1 y1 x2 y2} Draws a rectangle on the \term{medium} \arg{medium}. The corners of the -rectangle are at $(x1,y1)$ and $(x2,y2)$, with the corner positions transformed -by the medium's current transformation. \cl{medium-draw-rectangle*} will call -\cl{port-draw-rectangle*} in order to draw the rectangle. +rectangle are at $(x1,y1)$ and $(x2,y2)$. + +\Defgeneric {medium-draw-rectangles*} {medium coord-seq} + +Draws a set of rectangles on the \term{medium} \arg{medium}. \arg{coord-seq} is +a sequence of coordinate pairs, which are real numbers. It is an error if +\arg{coord-seq} does not contain an even number of elements. Each successive +pair of coordinate pairs is taken as the upper-left and lower-right corner of +the rectangle. \Defgeneric {medium-draw-ellipse*} {medium center-x center-y radius-1-dx radius-1-dy radius-2-dx radius-2-dy start-angle end-angle} -Draws an rectangle on the \term{medium} \arg{medium}. The center of the -rectangle is at $(x,y)$, and the radii are specified by the two vectors -(\arg{radius-1-dx},\arg{radius-1-dy}) and (\arg{radius-2-dx},\arg{radius-2-dy}). -The center point and radii are transformed by the medium's current -transformation. \cl{medium-draw-ellipse*} will call \cl{port-draw-ellipse*} in -order to draw the ellipse. +Draws an ellipse or elliptical arc on the \term{medium} \arg{medium}. The +center of the ellipse is at $(x,y)$, and the radii are specified by the two +vectors (\arg{radius-1-dx},\arg{radius-1-dy}) and +(\arg{radius-2-dx},\arg{radius-2-dy}). \arg{start-angle} and \arg{end-angle} are real numbers that specify an arc -rather than a complete ellipse. The medium transformation must be applied to -the angles as well. +rather than a complete ellipse. Note that the medium and device transformations +must be applied to the angles as well. \Defgeneric {medium-draw-text*} {medium text x y (start \cl{0}) end @@ -887,134 +929,36 @@ the angles as well. toward-x toward-y transform-glyphs} Draws a character or a string on the \term{medium} \arg{medium}. The text is -drawn starting at $(x,y)$, and towards (\arg{toward-x},\arg{toward-y}); these -positions are transformed by the medium's current transformation. -\cl{medium-draw-text*} will call either \cl{port-draw-string*} or -\cl{port-draw-character*} in order to draw the text. - - -\subsection {Port-specific Drawing Functions} - -The following port-specific functions are required by the drawing functions in -the API. If the optional arguments to these functions are not supplied, they -are defaulted from the medium. - -\Defgeneric {port-draw-point*} {port medium x y - \optional ink line-style clipping-region} - -Draws a point on the \term{medium} \arg{medium} on the \term{port} \arg{port}. -The point is drawn at the position that results from applying the device -transformation to $(x,y)$. - -\Defgeneric {port-draw-points*} {port medium coord-seq - \optional ink line-style clipping-region} - -Draws a set of points on the \term{medium} \arg{medium} on the \term{port} -\arg{port}. \arg{coord-seq} is a sequence of coordinate pairs, which are real -numbers. It is an error if \arg{coord-seq} does not contain an even number of -elements. \cl{port-draw-points*} could be implemented by repeatedly calling -{port-draw-point*}, but some ports may support faster primitives to do this. - -\Defgeneric {port-draw-line*} {port medium x1 y1 x2 y2 - \optional ink line-style clipping-region} - -Draws a line on the \term{medium} \arg{medium} on the \term{port} \arg{port}. -The device transformation is applied to $(x1,y1)$ to $(x2,y2)$, and the line is -drawn from one transformed endpoint to the other. - -\Defgeneric {port-draw-lines*} {port medium coord-seq - \optional ink line-style clipping-region} - -Draws a set of disconnected lines on the \term{medium} \arg{medium} on the -\term{port} \arg{port}. \arg{coord-seq} is a sequence of coordinate pairs, -which are real numbers. It is an error if \arg{coord-seq} does not contain an -even number of elements. \cl{port-draw-lines*} could be implemented by -repeatedly calling {port-draw-line*}, but some ports may support faster -primitives to do this. - -\Defgeneric {port-draw-polygon*} {port medium coord-seq closed - \optional ink line-style clipping-region} - -Draws a polygon or polyline on the \term{medium} \arg{medium} on the \term{port} -\arg{port}. When \arg{line-style} is \cl{nil}, this draws a filled polygon; -otherwise, \arg{line-style} is the line style to use when drawing a set of -connected lines. \arg{coord-seq} is a sequence of coordinate pairs, which are -real numbers. It is an error if \arg{coord-seq} does not contain an even number -of elements. The coordinate sequence specifies the corners of the polygon; the -device transformation is applied to each of the coordinates to produce the -corners of the rendered polygon. - -When \cl{port-draw-polygon*} is drawing a set of connected lines, then if -\arg{closed} is \term{true}, a closed polygon is drawn. If \arg{closed} is -\term{false}, the polygon will not be closed. - -\Defgeneric {port-draw-rectangle*} {port medium x1 y1 x2 y2 - \optional ink line-style clipping-region} - -Draws a rectangle on the \term{medium} \arg{medium} on the \term{port} -\arg{port}. When \arg{line-style} is \cl{nil}, this draws a filled rectangle; -otherwise, \arg{line-style} is the line style to use when drawing an unfilled -rectangle. The device transformation is applied to $(x1,y1)$ and $(x2,y2)$ to -produce the corners of the rectangle. - -\Defgeneric {port-draw-ellipse*} {port medium - center-x center-y - radius-1-dx radius-1-dy radius-2-dx radius-2-dy - start-angle end-angle - \optional ink line-style clipping-region} - -Draws an ellipse rectangle on the \term{medium} \arg{medium} on the \term{port} -\arg{port}. When \arg{line-style} is \cl{nil}, this draws a filled ellipse; -otherwise, \arg{line-style} is the line style to use when drawing an unfilled -ellipse. - -The center of the ellipse is produced by applying the device transformation to -(\arg{center-x},\arg{center-y}). Two vectors, -(\arg{radius-1-dx},\arg{radius-1-dy}) and (\arg{radius-2-dx},\arg{radius-2-dy}) -specify the bounding parallelogram of the ellipse as explained in -Chapter~\ref{regions}. When the ellipse vectors have the same length, the -ellipse is circle. The device transformation must is applied to the vectors as -well. +drawn starting at $(x,y)$, and towards (\arg{toward-x},\arg{toward-y}). In Some +implementations of CLIM, \cl{medium-draw-text*} may call either +\cl{medium-draw-string*} or \cl{medium-draw-character*} in order to draw the +text. -\arg{start-angle} and \arg{end-angle} are real numbers that specify an arc -rather than a complete ellipse. The device transformation must be applied to -the angles as well. - -\Defgeneric {port-draw-string*} {port medium text x y - (start \cl{0}) end - (align-x \cl{:left}) (align-y \cl{:baseline}) - toward-x toward-y transform-glyphs - \optional ink text-style clipping-region} - -Draws a string on the \term{medium} \arg{medium} on the \term{port} \arg{port}. -The string is drawn starting at the position that results from applying the -device transformation to $(x,y)$, and towards (\arg{toward-x},\arg{toward-y}). -\arg{align-x} is one of \cl{:left}, \cl{:center}, or \cl{:right}. \arg{align-y} -is one of \cl{:baseline}, \cl{:top}, \cl{:center}, or \cl{:bottom}. - -\arg{start} and \arg{end} specify the start and end of the string. \arg{start} -is an integer that is less than the length of the string. \arg{end} is an -integer that is less than the length of the string, but greater than or equal to -\arg{start}. - -Normally, glyphs are drawn from left to right, but \arg{toward-x} and -\arg{toward-y} can be used to change the direction from one glyph to the next -one. The reference point in each glyph lies on a line from $(x,y)$ to -(\arg{toward-x},\arg{toward-y}) and the spacing of each glyph is determined by -packing rectangles along that line, where each rectangle is ``char-width'' wide -and ``char-height'' high. Of course, some ports may not be able to fully -support this. +\subsection {Other Medium-specific Output Functions} -If \arg{transform-glyphs} is \term{true}, then each glyph is transformed as an -image before it is drawn. It is permissible for CLIM implementations to ignore -\arg{transform-glyphs} if it is too expensive to implement. +\Defgeneric {medium-finish-output} {medium} + +Ensures that all the output sent to \arg{medium} has reached its destination, +and only then return \term{false}. This is used by \cl{finish-output}. + +\Defgeneric {medium-force-output} {medium} + +Like \cl{medium-finish-output}, except that it may return \term{false} without +waiting for the output to complete. This is used by \cl{force-output}. + +\Defgeneric {medium-clear-area} {medium left top right bottom} + +Clears an area on the {medium} \arg{medium} by filling the rectangle whose edges +are at \arg{left}, \arg{top}, \arg{right}, and \arg{bottom} with the medium's +background ink. \arg{left}, \arg{top}, \arg{right}, and \arg{bottom} are in +thed medium's coordinate system. + +The default method on \cl{basic-medium} simply uses \cl{draw-rectangle*} to +clear the area. Some host window systems has special functions that are faster +than \cl{draw-rectangle*}. + +\Defgeneric {medium-beep} {medium} -\Defgeneric {port-draw-character*} {port medium character x y - (align-x \cl{:left}) (align-y \cl{:baseline}) - \optional ink text-style clipping-region} +Causes an audible sound to be played on the medium. The default method +does nothing. -Draws a single character on the \term{medium} \arg{medium} on the \term{port} -\arg{port} at the position that results from applying the device transformation -to $(x,y)$. \arg{align-x} is one of \cl{:left}, \cl{:center}, or \cl{:right}. -\arg{align-y} is one of \cl{:baseline}, \cl{:top}, \cl{:center}, or -\cl{:bottom}. diff --git a/specs/input-editing.tex b/specs/input-editing.tex index 1a85c41f..faeb3887 100644 --- a/specs/input-editing.tex +++ b/specs/input-editing.tex @@ -113,8 +113,9 @@ operation. When the user requests an input editor deletion command, the sequence of gesture objects at $IP$ are removed, and $IP$ and $FP$ must be modified to reflect the new state of the input buffer. Deletion commands (and other commands that -modify the input buffer) must call \cl{immediate-rescan} when they are done -modifying the buffer. +modify the input buffer) must arrange for a rescan to occur when they are done +modifying the buffer, either by calling \cl{queue-rescan} or +\cl{immediate-rescan}. CLIM implementations are free to put special objects in the input editor buffer, such as ``noise strings'' and ``accept results''. A ``noise string'' is used to @@ -128,7 +129,7 @@ skipped over by input editing commands, and accept results are treated as a single gesture. -\Defgeneric {interactive-stream-p} {object} +\Defpredicate {interactive-stream-p} {object} Returns \term{true} if \arg{object} is an interactive stream, that is, a bidrectional stream intended for user interactions. Otherwise it returns @@ -142,7 +143,7 @@ The input editor need only be fully implemented for interactive streams. The protocol class that corresponds to an input editing stream. \IfYouWantClass {an} {input editing stream} {input-editing-stream} -\Defun {input-editing-stream-p} {object} +\Defpredicate {input-editing-stream-p} {object} Returns \term{true} if \arg{object} is an \term{input editing stream} (that is, a stream of the sort created by a call to \cl{with-input-editing}), otherwise @@ -150,14 +151,14 @@ returns \term{false}. \Defclass {standard-input-editing-stream} -The class that implements CLIM's standard input editor. This is the class of -stream created by calling \cl{with-input-editing}. +The instantiable class that implements CLIM's standard input editor. This is +the class of stream created by calling \cl{with-input-editing}. \Mutable \Defmacro {with-input-editing} {(\optional stream - \key input-sensitizer initial-contents) + \key input-sensitizer initial-contents class) \body body} Establishes a context in which the user can edit the input typed in on the @@ -167,9 +168,9 @@ and the values returned by \arg{body} are returned as the values of first forms. The \arg{stream} argument is not evaluated, and must be a symbol that is bound -to an input stream. If \arg{stream} is \cl{t} (the default), \cl{*query-io*} is -used. If \arg{stream} is a stream that is not an interactive stream, then -\cl{with-input-editing} is equivalent to \cl{progn}. +to an input stream. If \arg{stream} is \cl{t} (the default), +\cl{*standard-input*} is used. If \arg{stream} is a stream that is not an +interactive stream, then \cl{with-input-editing} is equivalent to \cl{progn}. \arg{input-sensitizer}, if supplied, is a function of two arguments, a stream and a continuation function; the function has dynamic extent. The continuation, @@ -185,20 +186,31 @@ list, the printed representation of the object will be inserted into the input buffer using \cl{presentation-replace-input}. -\Defmacro {with-input-editor-typeout} {(\optional stream) \body body} +\Defmacro {with-input-editor-typeout} {(\optional stream \key erase) \body body} Establishes a context inside of \cl{with-input-editing} in which output can be -done by \arg{body} to the input editing stream \arg{stream}. -\cl{with-input-editor-typeout} should call \cl{fresh-line} before and after -evaluating the body. \arg{body} may have zero or more declarations as its first -forms. +done by \arg{body} to the input editing stream \arg{stream}. If \arg{erase} is +\term{true}, the area underneath the typeout will be erased before the typeout +is done. \cl{with-input-editor-typeout} should call \cl{fresh-line} before and +after evaluating the body. \arg{body} may have zero or more declarations as its +first forms. The \arg{stream} argument is not evaluated, and must be a symbol that is bound -to a stream. If \arg{stream} is \cl{t} (the default), \cl{*query-io*} is used. -If \arg{stream} is a stream that is not an input editing stream, then +to a stream. If \arg{stream} is \cl{t} (the default), \cl{*standard-input*} is +used. If \arg{stream} is a stream that is not an input editing stream, then \cl{with-input-editor-typeout} is equivalent to calling \cl{fresh-line}, evaluating the body, and then calling \cl{fresh-line} again. +\Defgeneric {input-editor-format} {stream format-string \rest format-args} + +This function is like \cl{format}, except that it is intended to be called on +input editing streams. It arranges to insert ``noise strings'' in the input +editor's input buffer. Programmers can use this to display in-line prompts in +\cl{accept} methods. + +If \arg{stream} is a stream that is not an input editing stream, then +\cl{input-editor-format} is equivalent to \cl{format}. + \subsection {The Input Editing Stream Protocol} @@ -282,13 +294,15 @@ Indicates that a rescan operation on the \term{input editing stream} \arg{stream} should take place after the next non-input editing gesture is read by setting the ``rescan queued'' flag to \term{true}. -\Defgeneric {rescan-if-necessary} {stream} +\Defgeneric {rescan-if-necessary} {stream \optional inhibit-activation} Invokes a rescan operation on the \term{input editing stream} \arg{stream} if \cl{queue-rescan} was called on the same stream and no intervening rescan operation has taken place. Resets the state of the ``rescan queued'' flag to \term{false}. +If \arg{inhibit-activation} is \term{false}, the input line will not be +activated even if there is an activation character in it. \Defgeneric {erase-input-buffer} {stream \optional (start-position \cl{0})} @@ -333,8 +347,8 @@ maintaining the scan pointer. An implementation of the input editor should provide a set of generally useful input editing commands. The exact set of these commands is unspecified, and the key bindings for these commands may vary from platform to platform. The -following is a suggested set of input editing commands and key bindings, taken -roughly from EMACS. +following is a suggested minimum set of input editing commands and key bindings, +taken roughly from EMACS. \begin{tabular}{|l|l|} \hline @@ -377,6 +391,15 @@ processor in such a way that \cl{substitute-numeric-argument-marker} can be used to insert the numeric argument into a command that was read via a keystroke accelerator. +\Defun {add-input-editor-command} {gestures function} + +Adds an input editing command that causes \arg{function} to be executed when the +specified gesture(s) are typed by the user. \arg{gestures} is either a single +gesture name, or a list of gesture names. When \arg{gestures} is a sequence of +gesture names, the function is executed only after all of the gestures are typed +in order with no intervening gestures. (This is used to implement ``prefixed'' +commands, such as the {\tt control-X control-F} command one might fix in EMACS.) + \section {Activation and Delimiter Gestures} @@ -457,7 +480,11 @@ otherwise returns \term{false}. \Deferror {simple-parse-error} The error that is signalled by \cl{simple-parse-error}. This is a subclass of -\cl{parse-error}. +\cl{parse-error}. + +This condition handles two initargs, \cl{:format-string} and +\cl{:format-arguments}, which are used to specify a control string and arguments +for a call to \cl{format}. \Defun {simple-parse-error} {format-string \rest format-arguments} @@ -469,6 +496,9 @@ return. \arg{format-string} and \arg{format-args} are as for \cl{format}. The error that is signalled by \cl{input-not-of-required-type}. This is a subclass of \cl{parse-error}. +This condition handles two initargs, \cl{:string} and \cl{:type}, which specify +a string to be used in an error message and the expected presentation type. + \Defun {input-not-of-required-type} {object type} Reports that input does not satisfy the specified type by signalling an @@ -660,8 +690,16 @@ issues a possibility gesture (a gesture that matches one of the gesture names in \cl{*possibilities-gestures*}). +\Defcondition {simple-completion-error} + +The error that is signalled by \cl{complete-input} when no completion is found. +This is a subclass of \cl{simple-parse-error}. + + \Defmacro {completing-from-suggestions} {(stream - \key partial-completers allow-any-input possibility-printer) + \key partial-completers allow-any-input + possibility-printer + (help-displays-possibilities \cl{t})) \body body} Reads input from the \term{input editing stream} \arg{stream}, completing over a @@ -672,7 +710,8 @@ set of possibilities generated by calls to \cl{suggest} within \arg{body}. \arg{success}, and \arg{string} The \arg{stream} argument is not evaluated, and must be a symbol that is bound -to a stream. If \arg{stream} is \cl{t} (the default), \cl{*query-io*} is used. +to a stream. If \arg{stream} is \cl{t} (the default), \cl{*standard-input*} is +used. \arg{partial-completers}, \arg{allow-any-input}, and \arg{possibility-printer} are as for \cl{complete-input}. diff --git a/specs/menus.tex b/specs/menus.tex index 0f9a0012..d7b9e21f 100644 --- a/specs/menus.tex +++ b/specs/menus.tex @@ -11,12 +11,12 @@ facility provided by OpenLook?} \Defgeneric {menu-choose} {items \key associated-window printer presentation-type - default-item default-style label + default-item text-style label cache unique-id id-test cache-value cache-test max-width max-height n-rows n-columns - x-spacing y-spacing + x-spacing y-spacing row-wise cell-align-x cell-align-y - pointer-documentation} + scroll-bars pointer-documentation} Displays a menu whose choices are given by the elements of the sequence \arg{items}. It returns three values: the value of the chosen item, the item @@ -24,6 +24,34 @@ itself, and the pointer button event corresponding to the gesture that the user used to select it. If the user aborts out of the menu, a single value is returned, \cl{nil}. +\cl{menu-choose} will call \cl{frame-manager-menu-choose} on the frame manager +being used by \arg{associated-window} (or the frame manager of the current +application frame). All of the arguments to \cl{menu-choose} will be passed on +to \cl{frame-manager-menu-choose}. + +\Defgeneric {frame-manager-menu-choose} {frame-manager items + \key associated-window printer presentation-type + default-item text-style label + cache unique-id id-test cache-value cache-test + max-width max-height n-rows n-columns + x-spacing y-spacing row-wise + cell-align-x cell-align-y + scroll-bars pointer-documentation} + +Displays a menu whose choices are given by the elements of the sequence +\arg{items}. It returns three values: the value of the chosen item, the item +itself, and the pointer button event corresponding to the gesture that the user +used to select it. If the user aborts out of the menu, a single value is +returned, \cl{nil}. + +{\bf Implementation note:} the default method on \cl{standard-frame-manager} +will generally be implemented in terms of CLIM's own window stream and +formatting facilities, such as using \cl{menu-choose-from-drawer} on a stream +allocated by \cl{with-menu}. However, some frame managers may be able to use a +native menu facility to handle most (if not all) menus. If the native menu +facility cannot handle some cases, it can simply use \cl{call-next-method} to +invoke the default method. + \arg{items} is a sequence of menu items. Each menu item has a visual representation derived from a display object, an internal representation that is a value object, and a set of menu item options. The form of a menu item is one @@ -50,8 +78,8 @@ The menu item options are: \item \cl{:style}---specifies the text style used to \cl{princ} the display object when neither \arg{presentation-type} nor \arg{printer} is supplied. -\item \cl{:items}---specifies a sequence of menu items for a sub-menu used if -this item is selected. +\item \cl{:items}---specifies a sequence of menu items for a sub-menu to be used +if this item is selected. \item \cl{:documentation}---associates some documentation with the menu item. When \arg{:pointer-documentation} is not \cl{nil}, this will be used as pointer @@ -65,8 +93,8 @@ over'' the item. \item \cl{:type}---specifies the type of the item. \cl{:item} (the default) indicates that the item is a normal menu item. \cl{:label} indicates that the item is simply an inactive label; labels will not be ``grayed over''. -\cl{:separator} indicates that the item serves as a separator between groups of -other items; separator items will usually be drawn as a horizontal line. +\cl{:divider} indicates that the item serves as a divider between groups of +other items; divider items will usually be drawn as a horizontal line. \end{itemize} The visual representation of an item depends on the \arg{printer} and @@ -89,7 +117,7 @@ This defaults to the top-level window of the current application frame. \arg{default-item} is the menu item where the mouse will appear. -\arg{default-style} is a text style that defines how the menu items are +\arg{text-style} is a text style that defines how the menu items are presented. \arg{label} is a string to which the menu title will be set. @@ -139,12 +167,18 @@ Can be one of \cl{:top}, \cl{:bottom}, or \cl{:center}. The default is \cl{:top}. The semantics are the same as for the \cl{:align-y} option to \cl{formatting-cell}. +\arg{row-wise} is as for \cl{formatting-item-list}. It defaults to \cl{t}. + +\arg{scroll-bars} specifies whether the menu should have scroll bars. It acts +the same way as the \cl{:scroll-bars} option to \cl{make-clim-stream-pane}. It +defaults to \cl{:vertical}. + \arg{pointer-documentation} is either \cl{nil} (the default), meaning that no pointer documentation should be computed, or a stream on which pointer documentation should be displayed. -\Defgeneric {menu-choose-from-drawer} {menu type drawer +\Defgeneric {menu-choose-from-drawer} {menu presentation-type drawer \key x-position y-position cache unique-id id-test cache-value cache-test default-presentation pointer-documentation} @@ -158,8 +192,9 @@ closure that closes over the menu items. \cl{menu-choose-from-drawer} draws the menu items into that window using the drawing function. The drawing function gets called with two arguments, -\arg{stream} and \arg{type}. It can use \arg{type} for its own purposes, such -as using it as the type argument in a call to \cl{present}. +\arg{stream} and \arg{presentation-type}. It can use \arg{presentation-type} +for its own purposes, such as using it as the presentation type argument in a +call to \cl{present}. \cl{menu-choose-from-drawer} returns two values: the object the user clicked on, and the pointer button event. If the user aborts out of the menu, a single @@ -169,13 +204,13 @@ value is returned, \cl{nil}. specialized to provide a different look-and-feel for different host window systems. -\arg{type} is a presentation type specifier for each of the mouse-sensitive +\arg{presentation-type} is a presentation type specifier for each of the mouse-sensitive items in the menu. This is the input context that will be established once the menu is displayed. For programmers who don't need to define their own types, a useful presentation type is \cl{menu-item}. \arg{drawer} is a function that takes two arguments, \arg{stream} and -\arg{type}, draws the contents of the menu. It has dynamic extent. +\arg{presentation-type}, draws the contents of the menu. It has dynamic extent. \arg{x-position} and \arg{y-position} are the requested $x$ and $y$ positions of the menu. They may be \cl{nil}, meaning that the position is unspecified. @@ -193,7 +228,7 @@ is pointing to when the menu comes up. \Defun {draw-standard-menu} {stream presentation-type items default-item \key item-printer max-width max-height n-rows n-columns - inter-column-spacing inter-row-spacing + x-spacing y-spacing row-wise cell-align-x cell-align-y} \cl{draw-standard-menu} is the function used by CLIM to draw the contents of a @@ -204,11 +239,10 @@ the menu items (usually \cl{menu-item}), and \arg{item-printer} is a function used to draw each item. \arg{item-printer} defaults to \cl{print-menu-item}. \arg{items}, \arg{default-item}, \arg{max-width}, \arg{max-height}, -\arg{n-rows}, \arg{n-columns}, \arg{inter-column-spacing}, -\arg{inter-row-spacing}, \arg{cell-align-x}, and \arg{cell-align-y} are as for -\cl{menu-choose} +\arg{n-rows}, \arg{n-columns}, \arg{x-spacing}, \arg{y-spacing}, \arg{row-wise}, +\arg{cell-align-x}, and \arg{cell-align-y} are as for \cl{menu-choose} -\Defun {print-menu-item} {menu-item \optional stream} +\Defun {print-menu-item} {menu-item \optional (stream \cl{*standard-output*})} Given a menu item \arg{menu-item}, displays it on the stream \arg{stream}. This is the function that \cl{menu-choose} uses to display menu items if no printer diff --git a/specs/output-recording.tex b/specs/output-recording.tex index 8fc8d61e..505b8147 100644 --- a/specs/output-recording.tex +++ b/specs/output-recording.tex @@ -84,7 +84,7 @@ protocol. All output records are mutable. -\Defun {output-record-p} {object} +\Defpredicate {output-record-p} {object} Returns \term{true} if \arg{object} is an \term{output record}, otherwise returns \term{false}. @@ -98,7 +98,7 @@ some output stream. This is a subclass of \cl{bounding-rectangle}. All displayed output records are mutable. -\Defun {displayed-output-record-p} {object} +\Defpredicate {displayed-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{displayed output record}, otherwise returns \term{false}. @@ -150,6 +150,9 @@ updated to be large enough to contain \arg{record}. This does not replay the output record, but the next time the output record is replayed it will appear at the new position. +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{output-record-set-position}. + \Defgeneric {output-record-start-cursor-position} {record} Returns the $x$ and $y$ starting cursor position of the \term{output record} @@ -168,6 +171,9 @@ affect the bounding rectangle of \arg{record}, nor does it replay the output record. For those output records that do not require or affect the cursor position, the method for this function is a no-op. +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{output-record-set-start-cursor-position}. + \Defgeneric {output-record-end-cursor-position} {record} Returns the $x$ and $y$ ending cursor position of the \term{output record} @@ -188,6 +194,8 @@ affect the bounding rectangle of \arg{record}, nor does it replay the output record. For those output records that do not require or affect the cursor position, the method for this function is a no-op. +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{output-record-set-end-cursor-position}. \Defgeneric {output-record-parent} {record} @@ -233,14 +241,6 @@ maintains the cursor position) affect the cursor position of the stream? It is probably that case that \cl{replay} should not affect the cursor position.} -\Defgeneric {erase-output-record} {record stream} - -Erases the \term{output record} \arg{record} from the \term{output recording -stream} \arg{stream}, removes \arg{record} from \arg{stream}'s output history, -and ensures that all other output records that were covered by \arg{record} are -visible. In effect, this draws background ink over the record, and then redraws -all the records that overlap \arg{record}. - \Defgeneric {output-record-hit-detection-rectangle*} {record} This method is used to establish the usual ``effective size'' of \arg{record} @@ -250,7 +250,7 @@ method (on CLIM's standard output record class) is equivalent to calling calling \cl{bounding-rectangle*} on \arg{record}, but this method can be specialized to return a larger bounding rectangle in order to implement a form of hysteresis. -\Defgeneric {output-record-refined-sensitivity-test} {record x y} +\Defgeneric {output-record-refined-position-test} {record x y} This is used to definitively answer hit detection queries, that is, determining that the point $(x,y)$ is contained within the output record \arg{record}. Once @@ -270,6 +270,11 @@ highlighting) or \cl{:unhighlight} (meaning to erase the highlighting). The default method (on CLIM's standard output record class) will simply draw a rectangle that corresponds the the bounding rectangle of \arg{record}. +\Defgeneric {displayed-output-record-ink} {displayed-output-record} + +Returns the ink used by the \term{displayed output record} +\arg{displayed-output-record}. + \subsection {The Output Record ``Database'' Protocol} @@ -316,12 +321,13 @@ Returns the number of children contained within the \term{output record} \Defgeneric {map-over-output-records-containing-position} - {function record x y \optional x-offset y-offset} + {function record x y \optional x-offset y-offset \rest function-args} Maps over all of the children of the \term{output record} \arg{record} that contain the point at $(x,y)$, calling \arg{function} on each one. -\arg{function} is a function of one argument, the record containing the point; -it has dynamic extent. +\arg{function} is a function of one or more arguments, the first argument being +the record containing the point; it has dynamic extent. \arg{function} is also +called with all of \arg{function-args} as ``apply'' arguments. If there are multiple records that contain the point and that overlap each other, \cl{map-over-output-records-containing-position} must hit the uppermost @@ -330,12 +336,13 @@ inserted) record last. Otherwise, the order in which the records are traversed is unspecified. \Defgeneric {map-over-output-records-overlapping-region} - {function record region \optional x-offset y-offset} + {function record region \optional x-offset y-offset \rest function-args} Maps over all of the children of the \term{output record} \arg{record} that overlap the \term{region} \arg{region}, calling \arg{function} on each one. -\arg{function} is a function of one argument, the record overlapping the region; -it has dynamic extent. +\arg{function} is a function of one or more arguments, the first argument being +the record overlapping the region; it has dynamic extent. \arg{function} is +also called with all of \arg{function-args} as ``apply'' arguments. If there are multiple records that overlap the region and that overlap each other, \cl{map-over-output-records-overlapping-region} must hit the bottommost @@ -393,19 +400,19 @@ classes of output records and the displayed output record protocol. \Defclass {standard-sequence-output-record} -The standard class provided by CLIM to store a relatively short sequence of -output records; a subclass of \cl{output-record}. The insertion and retrieval -complexity of this class is O(n). Most of the formatted output facilities (such -as \cl{formatting-table}) create output records that are a subclass of -\cl{standard-sequence-output-record}. +The standard instantiable class provided by CLIM to store a relatively short +sequence of output records; a subclass of \cl{output-record}. The insertion and +retrieval complexity of this class is O(n). Most of the formatted output +facilities (such as \cl{formatting-table}) create output records that are a +subclass of \cl{standard-sequence-output-record}. \Defclass {standard-tree-output-record} -The standard class provided by CLIM to store longer sequences of output records. -Typically, the child records of a tree output record will be maintained in some -sort of sorted order, such as a lexicographic ordering on the $x$ and $y$ -coordinates of the children. The insertion and retrieval complexity of this -class is O(log~n). +The standard instantiable class provided by CLIM to store longer sequences of +output records. Typically, the child records of a tree output record will be +maintained in some sort of sorted order, such as a lexicographic ordering on the +$x$ and $y$ coordinates of the children. The insertion and retrieval complexity +of this class is O(log~n). \subsection {Graphics Displayed Output Records} @@ -447,7 +454,7 @@ functions, such as \cl{draw-line*}. This is a subclass of \cl{displayed-output-record}. \IfYouWantClass {a} {graphics displayed output record} {graphics-displayed-output-record} -\Defun {graphics-displayed-output-record-p} {object} +\Defpredicate {graphics-displayed-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{graphics displayed output record}, otherwise returns \term{false}. @@ -492,7 +499,7 @@ The protocol class that corresponds to text displayed output records. This is a subclass of \cl{displayed-output-record}. \IfYouWantClass {a} {text displayed output record} {text-displayed-output-record} -\Defun {text-displayed-output-record-p} {object} +\Defpredicate {text-displayed-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{text displayed output record}, otherwise returns \term{false}. @@ -536,7 +543,8 @@ scroll bars. \Defclass {stream-output-history-mixin} This class is mixed into some other output record class to produce a new class -that is suitable for use as a a top-level output history. +that is suitable for use as a a top-level output history. This class is not +intended to be instantiated. When the bounding rectangle of an member of this class is updated, CLIM implementations must update any window decorations (such as scroll bars) @@ -545,9 +553,15 @@ associated. \Defclass {standard-tree-output-history} -The standard class provided by CLIM to use as the top-level output history. -This will typically be a subclass of both \cl{standard-tree-output-record} and -\cl{stream-output-history-mixin}. +The standard instantiable class provided by CLIM to use as the top-level output +history. This will typically be a subclass of both +\cl{standard-tree-output-record} and \cl{stream-output-history-mixin}. + +\Defclass {standard-sequence-output-history} + +Another instantiable class provided by CLIM to use for top-level output records +that have only a small number of children. This will typically be a subclass of +both \cl{standard-sequence-output-record} and \cl{stream-output-history-mixin}. \section {Output Recording Streams} @@ -566,7 +580,7 @@ lots of things.} The protocol class that indicates that a stream is an output recording stream. \IfYouWantClass {an} {output recording stream} {output-recording-stream} -\Defun {output-recording-stream-p} {object} +\Defpredicate {output-recording-stream-p} {object} Returns \term{true} if \arg{object} is an \term{output recording stream}, otherwise returns \term{false}. @@ -634,41 +648,69 @@ Directs the \term{output recording stream} \arg{stream} to invoke \cl{replay} on its output history. Only those records that overlap the \term{region} \arg{region} (which defaults to the viewport of the stream) are replayed. +\Defgeneric {erase-output-record} {record stream \optional (errorp \cl{t})} + +Erases the \term{output record} \arg{record} from the \term{output recording +stream} \arg{stream}, removes \arg{record} from \arg{stream}'s output history, +and ensures that all other output records that were covered by \arg{record} are +visible. In effect, this draws background ink over the record, and then redraws +all the records that overlap \arg{record}. + +If \arg{record} is not in the stream's output history, then an error is +signalled, unless \arg{errorp} is \term{false}. + +\Defun {copy-textual-output-history} {window stream \optional region record} + +Given an \term{output recording stream} \arg{window} and a character output +stream \arg{stream}, \cl{copy-textual-output-history} maps over all of the +textual output records in the region \arg{region} and writes them to +\arg{stream}, in order from the top of the output to the bottom of the output. + +If \arg{record} is supplied, it is the top-level record to map over. It +defaults to \cl{stream-output-history} of \arg{window}. + \subsection {Graphics Output Recording} Using \cl{draw-line*} as an example, calling any of the drawing functions specified in Section~\ref{drawing-functions} and -Section~\ref{graphics-protocols} results in the following series of function -calls on an output recording stream: +Section~\ref{graphics-protocols} on an output recording stream results in the +following series of function calls: \begin{itemize} -\item A program calls \cl{draw-line*} on arguments \arg{sheet}, \arg{x1}, -\arg{y1}, \arg{x2}, and \arg{y2}, and perhaps some drawing options. +\item A program calls \cl{draw-line*} on arguments \arg{stream} (and output +recording stream), \arg{x1}, \arg{y1}, \arg{x2}, and \arg{y2}, and perhaps some +drawing options. -\item \cl{draw-line*} merges the supplied drawing options into the sheet's -medium, and then calls \cl{medium-draw-line*} on the sheet. (Note that a +\item \cl{draw-line*} merges the supplied drawing options into the stream's +medium, and then calls \cl{medium-draw-line*} on the stream. (Note that a compiler macro could detect the case where there are no drawing options or constant drawing options, and do this at compile time.) \item The \cl{:around} method for \cl{medium-draw-line*} on the output recording -stream is called. This creates an output record with all of the information -necessary to replay the output record, if \cl{stream-recording-p} is -\term{true}. If \cl{stream-drawing-p} is \term{true}, this then does a -\cl{call-next-method}. (Note that the \cl{call-next-method} could be replaced -by a call to the \cl{medium-draw-line*} method on the sheet's medium, avoiding -the need for a trampolining function call.) - -\item \cl{medium-draw-line*} performs the necessary user transformations by -applying the medium transformation to \arg{x1}, \arg{y1}, \arg{x2}, and -\arg{y2}, and to the clipping region. Then \cl{medium-draw-line*} calls -\cl{port-draw-line*} to do the actual drawing. +stream is called. If \cl{stream-recording-p} is \term{true}, this creates an +output record with all of the information necessary to replay the output record. +If \cl{stream-drawing-p} is \term{true}, this then does a \cl{call-next-method}. +(Note that the \cl{call-next-method} could be replaced by a call to the +\cl{medium-draw-line*} method on the stream's medium, avoiding the need for a +trampolining function call.) + +\item An \cl{:around} method for \cl{medium-draw-line*} performs the necessary +user transformations by applying the medium transformation to \arg{x1}, +\arg{y1}, \arg{x2}, and \arg{y2}, and to the clipping region, and then calls the +medium-specific method. + +\item The ``real'' \cl{medium-draw-line*} transforms the start and end +coordinates of the line by the stream's device transformation, decodes the ink +and line style into port-specific objects, and finally invokes a port-specific +function (such as \cl{xlib:draw-line}) to do the actual drawing. \end{itemize} -\cl{replay-output-record} for a graphics displayed output record simply calls +\cl{replay-output-record} for a graphics displayed output record simply binds +the state of the medium to the state captured in the output record, and calls the medium drawing function (such as \cl{medium-draw-line*}) directly on the -sheet ({\sl not} on the medium) with \cl{stream-recording-p} set to \term{false} -and \cl{stream-drawing-p} set to \term{true}. +medium, with \cl{stream-recording-p} of the stream set to \term{false} and +\cl{stream-drawing-p} set to \term{true}. \subsection {Text Output Recording} @@ -772,7 +814,7 @@ All output recording streams must implement a method for \Defmacro {with-new-output-record} {(stream \optional record-type record - \rest init-args) + \rest initargs) \body body} Creates a new output record of type \arg{record-type} (which defaults to @@ -783,9 +825,8 @@ output record associated with the \term{output recording stream} designated by for \arg{stream} will be bound to the new output record. If \arg{record} is supplied, it is the name of a variable that will be lexically -bound to the new output record inside of body. \arg{init-args} are CLOS -initialization arguments that are passed to \cl{make-instance} when the new output -record is created. +bound to the new output record inside of body. \arg{initargs} are CLOS initargs +that are passed to \cl{make-instance} when the new output record is created. \cl{with-new-output-record} returns the output record it creates. @@ -799,7 +840,7 @@ as the \arg{continuation} argument to \cl{invoke-with-new-output-record}. The e behavior of this macro is described under \cl{invoke-with-new-output-record}. \Defgeneric {invoke-with-new-output-record} {stream continuation record-type - \rest init-args \key} + \rest initargs \key parent \allow} Creates a new output record of type \arg{record-type}. The function \arg{continuation} is then called, and any output it does to the \term{output @@ -809,9 +850,14 @@ record is then inserted into the current ``open'' output record associated with one). While \arg{continuation} is being executed, the current output record for \arg{stream} will be bound to the new output record. -\arg{continuation} is a function of two arguments, the stream and the output record; -it has dynamic extent. \arg{init-args} are CLOS initialization arguments that -are passed to \cl{make-instance} when the new output record is created. +\arg{continuation} is a function of two arguments, the stream and the output +record; it has dynamic extent. + +\arg{initargs} are CLOS initargs that are passed to \cl{make-instance} when the +new output record is created. The \arg{parent} initarg is handled specially, +and specifies what output record should serve as the parent for the newly +created record. If unspecified, \cl{stream-current-output-record} of +\arg{stream} will be used as the parent. \cl{invoke-with-new-output-record} returns the output record it creates. @@ -820,7 +866,7 @@ All output recording streams must implement a method for \Defmacro {with-output-to-output-record} {(stream \optional record-type record - \rest init-args)) + \rest initargs)) \body body} This is identical to \cl{with-new-output-record} except that the new output record @@ -828,9 +874,8 @@ is not inserted into the output record hierarchy, and the text cursor position of \arg{stream} is initially bound to $(0,0)$. \arg{record-type} is the type of output record to create, which defaults to -\cl{standard-sequence-output-record}. \arg{init-args} are CLOS initialization -arguments that are passed to \cl{make-instance} when the new output record is -created. +\cl{standard-sequence-output-record}. \arg{initargs} are CLOS initargs that are +passed to \cl{make-instance} when the new output record is created. If \arg{record} is supplied, it is a variable that will be bound to the new output record while body is evaluated. @@ -850,7 +895,7 @@ to \cl{invoke-with-output-to-output-record} supplying a function that executes described under \cl{invoke-with-output-to-output-record}. \Defgeneric {invoke-with-output-to-output-record} {stream continuation record-type - \rest init-args \key} + \rest initargs \key} This is similar to \cl{invoke-with-new-output-record} except that the new output record is not inserted into the output record hierarchy, and the text cursor @@ -860,9 +905,9 @@ occurs and nothing is put into the stream's normal output history. The function \arg{continuation} is called, and any output it does to \arg{stream} is captured in the output record. -\arg{continuation} is a function of two arguments, the stream and the output record; -it has dynamic extent. \arg{record-type} is the type of output record to -create. \arg{init-args} are CLOS initialization arguments that are passed to +\arg{continuation} is a function of two arguments, the stream and the output +record; it has dynamic extent. \arg{record-type} is the type of output record +to create. \arg{initargs} are CLOS initargs that are passed to \cl{make-instance} when the new output record is created. \cl{invoke-with-output-to-output-record} returns the output record it creates. diff --git a/specs/overview.tex b/specs/overview.tex index 5f734524..9629a7a7 100644 --- a/specs/overview.tex +++ b/specs/overview.tex @@ -109,25 +109,4 @@ easily construct applications that will automatically conform to a variety of user interface standards. In addition, a portable Lisp-based implementation of the abstract panes is provided. -\comment{ -CLIM provides an architecture for building and incorporating panes that can be -used by application users. This includes a mechanism for selecting -implementations of abstract panes based on the frame manager that controls the -frame. (It's look and feel is to be determined, but probably the right answer -is Motif-like). - -CLIM applications can be written without building in knowledge of particular -frame managers. They can later be tailored by the user and/or by the -application developer for a particular frame manager. The CLIM interface -provide facilities that allow developing applications that are good citizens -under various existing and emerging desktop manager. - -\item [Wires and Triggers] {\sl to be defined, but roughly...} Wires -provide a mechanism for hooking elements of the user interface to the -applications functionality. - -\item [Settings] {\sl to be defined, but roughly...} Settings are a -mechanism for merging the look and feel preferences and defaults of users, -frames, and frame managers. -} \end{description} diff --git a/specs/panes.tex b/specs/panes.tex index 3d70129c..cd59ae24 100644 --- a/specs/panes.tex +++ b/specs/panes.tex @@ -30,17 +30,16 @@ application specific information. CLIM provides a number of these graphics and extended stream facilities. \concept{Abstract panes} are panes that are defined only in terms of their -programmer interface, or behavior. The protocol for an abstract pane (that -is, the specified set of initialization options, accessors, and callbacks) is -designed to specify the pane in terms of its overall purpose, rather then in -terms of its specific appearance or particular interactive details. The -purpose of this abstract definition is to allow multiple implementations of -the abstract pane, each defining its own specific look and feel. CLIM can -then select the appropriate pane implementation based on factors outside the -control of the application, such as user preferences or the look and feel of -the host operating environment. A subset of the abstract panes, the -\term{adaptive panes}, have been defined to integrate well across all CLIM -operating platforms. +programmer interface, or behavior. The protocol for an abstract pane (that is, +the specified set of initargs, accessors, and callbacks) is designed to specify +the pane in terms of its overall purpose, rather then in terms of its specific +appearance or particular interactive details. The purpose of this abstract +definition is to allow multiple implementations of the abstract pane, each +defining its own specific look and feel. CLIM can then select the appropriate +pane implementation based on factors outside the control of the application, +such as user preferences or the look and feel of the host operating environment. +A subset of the abstract panes, the \term{adaptive panes}, have been defined to +integrate well across all CLIM operating platforms. CLIM provides a general mechanism for automatically selecting the particular implementation of an abstract pane selected by an application based on the @@ -49,7 +48,7 @@ mechanism by using the name of a specific pane implementation in place of the abstract pane name when specifying the application frame's layout. By convention, the name of the basic, portable implementation of an abstract pane class can be determined by adding the suffix ``\cl{-pane}'' to the name of the -abstract class. +abstract pane class. \section {Basic Pane Construction} @@ -92,20 +91,30 @@ layout protocols. All of the subclasses of \cl{pane} are mutable. -\Defun {panep} {object} +\Defpredicate {panep} {object} Returns \term{true} if \arg{object} is a \term{pane}, otherwise returns \term{false}. +\Defclass {basic-pane} + +The basic class on which all CLIM panes are built, a subclass of \cl{pane}. +\AbstractClass + + \Defun {make-pane} {abstract-class-name \rest initargs} Selects a class that implements the behavior of the abstract pane \arg{abstract-class-name} and constructs a pane of that class. \cl{make-pane} -must be used either within the dynamic scope of a call to +must be used either within the scope of a call to \cl{with-look-and-feel-realization}, or within the \cl{:pane} or \cl{:panes} options of a \cl{define-application-frame} (which implicitly invokes \cl{with-look-and-feel-realization}). +It is permitted for this function to have lexical scope, and be defined only +within the body of \cl{with-look-and-feel-realization}. + + \Defgeneric {make-pane-1} {realizer frame abstract-class-name \rest initargs} The generic function that is invoked by a call to \cl{make-pane}. The object @@ -129,7 +138,7 @@ is uses its own subpanes to achieve its functionality, this form might be used with \arg{realizer} being the pane itself. -\subsection {Pane Initialization Options} +\subsection {Pane Initialization Options \label{pane-init}} The following options must be accepted by all pane classes. @@ -137,17 +146,22 @@ The following options must be accepted by all pane classes. \Defoption {:background} These options specify the default foreground and background inks for a pane. +These will normally default from window manager resources. If there are no such +resources, the defaults are black and white, respectively. + Client code should be cautious about passing values for these two options, since -the desktop's look and feel or the user's preferences should usually determine -these values. +the window manager's look and feel or the user's preferences should usually +determine these values. \Defoption {:text-style} This option specifies the default text style that should be used for any sort of pane that supports text output. Panes that do not support text output ignore -this option. Client code should be cautious about passing values for this -option, since the desktop's look and feel or the user's preferences should -usually determine this value. +this option. + +Client code should be cautious about passing values for this option, since the +window manager's look and feel or the user's preferences should usually +determine this value. \Defoption {:name} @@ -168,12 +182,13 @@ hierarchy. Returns the name of the pane. \defgeneric {pane-foreground} {pane} -\Defgeneric {pane-background} {pane} +\defgeneric {pane-background} {pane} +\Defgeneric {pane-text-style} {pane} -Return the current foreground and background inks of the pane, respectively. - -\issue {SWM} {Why aren't these \cl{medium-foreground} and -\cl{medium-background}, since panes obey the medium protocol to this extent?} +Return the default foreground and background inks and the default text style, +respectively, for the pane \arg{pane}. These will be used as the default value +for \cl{medium-foreground} and \cl{medium-background} when a medium is grafted +to the pane. \section {Composite and Layout Panes} @@ -272,11 +287,14 @@ both the $x$ and $y$ spacing simultaneously. \subsection {Layout Pane Classes} \deflpane {hbox-pane} -\Defmacro {horizontally} {(\rest options) \body contents} +\Defmacro {horizontally} {(\rest options \key spacing \allow) \body contents} The \cl{hbox-pane} class lays out all of its child panes horizontally, from left -to right. The \cl{horizontally} macro serves as a convenient interface for -creating an \cl{hbox-pane}. +to right. The child panes are separated by the amount of space specified by +\arg{spacing}. + +The \cl{horizontally} macro serves as a convenient interface for creating an +\cl{hbox-pane}. \arg{contents} is one or more forms that are the child panes. Each form in \arg{contents} is of the form: @@ -309,11 +327,14 @@ one-third of the space, then second takes two-thirds of the space. \deflpane {vbox-pane} -\Defmacro {vertically} {(\rest options) \body contents} +\Defmacro {vertically} {(\rest options \key spacing \allow) \body contents} The \cl{vbox-pane} class lays out all of its child panes vertically, from top to -bottom. The \cl{vertically} macro serves as a convenient interface for creating -an \cl{vbox-pane}. +bottom. The child panes are separated by the amount of space specified by +\arg{spacing}. + +The \cl{vertically} macro serves as a convenient interface for creating an +\cl{vbox-pane}. \arg{contents} is as for \cl{horizontally}. @@ -356,18 +377,19 @@ A \cl{grid-pane} is like a \cl{table-pane}, except that each cell is the same size in each of the two dimensions. -\deflpane {spacer-pane} -\Defmacro {spacing} {(\rest options) \body contents} +\deflpane {spacing-pane} +\Defmacro {spacing} {(\rest options \key thickness \allow) \body contents} -This pane reserves some margin space around a single child pane. The space -requirement keys that are passed in indicate the requirements for the -surrounding space, not including the requirements of the child. +This pane reserves some margin space of thickness \arg{thickness} around a +single child pane. The space requirement keys that are passed in indicate the +requirements for the surrounding space, not including the requirements of the +child. -\deflpane {border-pane} -\Defmacro {bordering} {(\rest options) \body contents} +\deflpane {outlined-pane} +\Defmacro {outlining} {(\rest options \key thickness \allow) \body contents} -This layout pane puts a border around its contents. +This layout pane puts a outline of thickness \arg{thickness} around its contents. The \cl{:background} option can be used to control the ink used to draw the background. @@ -388,7 +410,17 @@ A pane that allows its children to be any size and lays them out wherever they want to be (for example, a desktop manager). -\subsection {Other Composite Pane Classes} +\defspane {label-pane} +\Defmacro {labelling} {(\rest options \key label label-alignment \allow) + \body contents} + +Creates a pane that consists of the specified label \arg{label}, which is a +string. \arg{label-alignment} may be either \cl{:bottom} or \cl{:top}, which +specifies whether the label should appear at the top or the bottom of the +labelled pane. The default for \arg{label-alignment} is left unspecified. + + +\subsection {Scroller Pane Classes} CLIM defines the following additional pane classes, each having at least one implementation. @@ -409,21 +441,28 @@ has as children the scroll bars and a \concept{viewport}. The viewport of a pane is the area of the window's drawing plane that is currently visible to the user. The viewport has as its child the specified contents. -\issue {SWM} {Supply the following four definitions.} - \Defgeneric {pane-viewport} {pane} +If the pane \arg{pane} is part of a scroller pane, this returns the viewport +pane for \arg{pane}. Otherwise it returns \cl{nil}. + \Defgeneric {pane-viewport-region} {pane} +If the pane \arg{pane} is part of a scroller pane, this returns the region of +the pane's viewport. Otherwise it returns \cl{nil}. + \Defgeneric {pane-scroller} {pane} -\Defgeneric {scroll-extent} {pane x y} +If the pane \arg{pane} is part of a scroller pane, this returns the scroller +pane itself. Otherwise it returns \cl{nil}. +\Defgeneric {scroll-extent} {pane x y} -\defspane {label-pane} -\Defmacro {labelled} {(\rest options) \body contents} +If the pane \arg{pane} is part of a scroller pane, this scrolls the pane in its +viewport so that the position $(x,y)$ of \arg{pane} is at the upper-left corner +of the viewport. Otherwise, it does nothing. -Creates a pane that consists of the specified label, which is a string. +\arg{x} and \arg{y} are coordinates. \subsection {The Layout Protocol\label{layout-protocol}} @@ -477,6 +516,94 @@ above which the pane cannot be grown. (The minimum and maximum sizes can also be specified as relative amounts.) All sizes are specified as a real number indicating the number of device units (such as pixels). + +\Defclass {space-requirement} + +The protocol class of all space requirement objects. There are one or more +subclasses of \cl{space-requirement} with implementation-dependent names that +implement space requirements. The exact names of these classes is explicitly +unspecified. +\IfYouWantClass {a} {space requirement} {space-requirement} + +All of the instantiable space requirement classes provided by CLIM are +immutable. + + +\Defun {make-space-requirement} {\key (width \cl{0}) (max-width \cl{0}) (min-width \cl{0}) + (height \cl{0}) (max-height \cl{0}) (min-height \cl{0})} + +Constructs a space requirement object with the given characteristics, \cl{:width}, +\cl{:height}, and so on. + +\defgeneric {space-requirement-width} {space-req} +\defgeneric {space-requirement-min-width} {space-req} +\defgeneric {space-requirement-max-width} {space-req} +\defgeneric {space-requirement-height} {space-req} +\defgeneric {space-requirement-min-height} {space-req} +\Defgeneric {space-requirement-max-height} {space-req} + +These functions read the components of the space requirement \arg{space-req}. + +\Defgeneric {space-requirement-components} {space-req} + +Returns the components of the space requirement \arg{space-req} as six values, +the width, minimum width, maximum width, height, minimum height, and maximum +height. + +\Defun {space-requirement-combine} {function sr1 sr2} + +Returns a new space requirement each of whose components is the result of +applying the function \arg{function} to each the components of the two space +requirements \arg{sr1} and \arg{sr2}. + +\arg{function} is a function of two arguments, both of which are real numbers. +It has dynamic extent. + +\Defun {space-requirement+} {sr1 sr2} + +Returns a new space whose components are the sum of each of the components of +\arg{sr1} and \arg{sr2}. This could be implemented as follows: + +\begin{verbatim} +(defun space-requirement+ (sr1 sr2) + (space-requirement-combine #'+ sr1 sr2)) +\end{verbatim} + +\Defun {space-requirement+*} {space-req \key width min-width max-width + height min-height max-height} + +Returns a new space requirement whose components are the sum of each of the +components of \arg{space-req} added to the appropriate keyword argument (for +example, the width component of \arg{space-req} is added to \arg{width}). + +This is intended to be a more efficient, ``spread'' version of +\cl{space-requirement+}. + + +\Defgeneric {compose-space} {pane \key width height} + +During the space composition pass, a composite pane will typically ask each of +its children how much space it requires by calling \cl{compose-space}. They +answer by returning \cl{space-requirement} objects. The composite will then +form its own space requirement by composing the space requirements of its +children according to its own rules for laying out its children. + +The value returned by \cl{compose-space} is a space requirement object that +represents how much space the pane \arg{pane} requires. + +\arg{width} and \arg{height} are real numbers that the \cl{compose-space} method +for a pane may use as ``recommended'' values for the width and height of the +pane. These are used to drive top-down layout. + +\Defgeneric {allocate-space} {pane width height} + +During the space allocation pass, a composite pane will arrange its children +within the available space and allocate space to them according to their space +requirements and its own composition rules by calling \cl{allocate-space} on +each of the child panes. \arg{width} and \arg{height} are the width and height +of \arg{pane} in device units. + + \Defgeneric {change-space-requirements} {pane \key resize-frame \rest space-req-keys} This function can be invoked to indicate that the space requirements for @@ -503,7 +630,7 @@ cases that \cl{layout-frame} isn't invoked. In the case that \cl{layout-frame} is invoked, it isn't necessary to call \cl{note-space-requirements-changed} since a complete re-layout of the frame will be executed. -\Defmacro {changing-space-requirements} {(\key resize-frame) \body body} +\Defmacro {changing-space-requirements} {(\key resize-frame layout) \body body} This macro supports batching the invocation of the layout protocol by calls to \cl{change-space-requirements}. Within the body, all calls to @@ -513,62 +640,22 @@ appropriately. \arg{body} may have zero or more declarations as its first forms. -\Defgeneric {compose-space} {pane} - -During the space composition pass, a composite pane will typically ask each of -its children how much space it requires by calling \cl{compose-space}. They -answer by returning \cl{space-requirement} objects. The composite will then -form its own space requirement by composing the space requirements of its -children according to its own rules for laying out its children. - -\Defgeneric {allocate-space} {pane width height} - -During the space allocation pass, a composite pane will arrange its children -within the available space and allocate space to them according to their space -requirements and its own composition rules by calling \cl{allocate-space} on -each of the child panes. \arg{width} and \arg{height} are the width and height -of \arg{pane} in device units. - - -\Defun {make-space-requirement} {\key (width \cl{0}) (max-width \cl{0}) (min-width \cl{0}) - (height \cl{0}) (max-height \cl{0}) (min-height \cl{0})} - -Constructs a space requirement object with the given characteristics, \cl{:width}, -\cl{:height}, and so on. - -\defun {space-requirement-width} {space-req} -\defun {(setf space-requirement-width)} {size space-req} -\defun {space-requirement-max-width} {space-req} -\defun {(setf space-requirement-max-width)} {size space-req} -\defun {space-requirement-min-width} {space-req} -\defun {(setf space-requirement-min-width)} {size space-req} -\defun {space-requirement-height} {space-req} -\defun {(setf space-requirement-height)} {size space-req} -\defun {space-requirement-max-height} {space-req} -\defun {(setf space-requirement-max-height)} {size space-req} -\defun {space-requirement-min-height} {space-req} -\Defun {(setf space-requirement-min-height)} {size space-req} - -These functions read or modify the components of the space requirement -\arg{space-req}. - - -\section {Application Panes\label{clim-panes}} +\section {CLIM Stream Panes\label{clim-panes}} In addition to the various layout panes and gadgets, an application usually needs some space to display application-specific output and receive application-specific input from the user. For example, a paint program needs a ``canvas'' pane on which to display the picture and handle the ``mouse strokes''. An application frame can use the basic CLIM input and output -services in an application-specific way through use of an \concept{application +services in an application-specific way through use of a \concept{CLIM stream pane}. -This section describes the basic CLIM application pane types. Programmers are +This section describes the basic CLIM stream pane types. Programmers are free to customize pane behavior by defining subclasses of these pane classes writing methods to change the repaint or event-handling behavior. -\subsection {Application Pane Options} +\subsection {CLIM Stream Pane Options\label{clim-pane-options}} CLIM application frames accept the \cl{:foreground}, \cl{:background}, \cl{:text-style}, and layout pane options. The space requirement options @@ -576,7 +663,7 @@ CLIM application frames accept the \cl{:foreground}, \cl{:background}, \cl{:compute}, which causes CLIM to run the display function for the pane, and make the pane large enough to hold the output of the display function. -In addition to the above, CLIM application frames accept the following options: +In addition to the above, CLIM stream panes accept the following options: \Defoption {:display-function} @@ -592,12 +679,13 @@ arguments, if any. The default for this option is \cl{nil}. \Defoption {:display-time} This is used to indicate to CLIM when the pane's display function should be run. -If it is \cl{:command-loop}, CLIM will erase the pane's contents and run the -display function after each time a frame command is executed. If it is \cl{t}, -the pane will be displayed once and not again until \cl{pane-needs-redisplay} is +If it is \cl{:command-loop}, CLIM will clear the pane and run the display +function after each time a frame command is executed. If it is \cl{t}, the pane +will be displayed once and not again until \cl{(setf~pane-needs-redisplay)} is called on the pane. If it is \cl{nil}, CLIM will never run the display function until it is explicitly requested, either via \cl{pane-needs-redisplay} or -\cl{redisplay-frame-pane}. The default for this option varies. +\cl{redisplay-frame-pane}. The default for this option varies depending on the +type of the pane. \Defoption {:incremental-redisplay} @@ -622,18 +710,24 @@ These options specify the end-of-line and end-of-page actions to be used for the pane. The default for these options are \cl{:wrap} and \cl{:scroll}, respectively. -\Defoption {:output-history} +\Defoption {:output-record} + +This option names the output record class to be used for the output history of +the pane. The default is \cl{standard-tree-output-history}. + +\defoption {:draw} +\Defoption {:record} -This option names the class to be used for the output history for the pane. The -default is \cl{standard-tree-output-history}. +These options specify whether the pane should initially allow drawing and output +recording. The default for both options is \cl{t}. -\subsection {Application Pane Classes} +\subsection {CLIM Stream Pane Classes} \Defspane {clim-stream-pane} This class implements a pane that supports the CLIM graphics, extended input and -output, and output recording protocols. Most application panes will be +output, and output recording protocols. Most CLIM stream panes will be subclasses of this class. \Defspane {interactor-pane} @@ -678,23 +772,35 @@ For \cl{pointer-documentation-pane}, the default for \cl{:display-time} is \cl{nil} and the default for \cl{:scroll-bars} is \cl{nil}. -\subsection {Making CLIM Application Panes} +\subsection {Making CLIM Stream Panes} -Most CLIM application panes will contain more information than can be displayed +Most CLIM stream panes will contain more information than can be displayed in the allocated space, so scroll bars are nearly always desirable. CLIM therefore provides a convenient form for creating composite panes that include the CLIM stream pane, scroll bars, labels, and so forth. -\Defun {make-clim-stream-pane} {\rest options \key type label scroll-bars \allow} +\Defun {make-clim-stream-pane} {\rest options + \key type label label-alignment scroll-bars borders + display-after-commands \allow} + +Creates a pane of type \arg{type}, which defaults to \cl{clim-stream-pane}. + +If \arg{label} is supplied, it is a string used to label the pane. +\arg{label-alignment} is as for the \cl{labelling} macro. -Creates a pane of type \arg{type}, which defaults to \cl{clim-stream-pane}. If -\arg{label} is supplied, it is a string used to label the pane. \arg{scroll-bars} may be \cl{t} to indicate that both vertical and horizontal scroll bars should be included, \cl{:vertical} (the default) to indicate that vertical scroll bars should be included, or \cl{:horizontal} to indicate that horizontal scroll bars should be included. -The other options may include all of the valid CLIM application pane options. +If \arg{borders} is \term{true}, the default, a border is drawn around the pane. + +\arg{display-after-commands} is used to initialize the \cl{:display-time} +property of the pane. It may be \cl{t} (for \cl{:display-time :command-loop}), +\cl{:no-clear} (for \cl{:display-time :no-clear}), or \cl{nil} (for +\cl{:display-time nil}). + +The other options may include all of the valid CLIM stream pane options. \Defun {make-clim-interactor-pane} {\rest options} @@ -707,7 +813,7 @@ Like \cl{make-clim-stream-pane}, except that the type is forced to be \cl{application-pane}. -\subsection {CLIM Application Pane Functions} +\subsection {CLIM Stream Pane Functions} The following functions can be called on any pane that is a subclass of \cl{clim-stream-pane}. (Such a pane is often simply referred to as a @@ -728,8 +834,11 @@ output records in the visible part of the window are replayed. \Defgeneric {window-viewport} {window} -Returns the viewport region of the CLIM stream pane \arg{window}. The returned -region will usually be a \cl{standard-bounding-rectangle}. +Returns the viewport region of the CLIM stream pane \arg{window}. If the window +is not scrollable, and hence has no viewport, this will region \cl{sheet-region} +of \arg{window}. + +The returned region will generally be a \cl{standard-bounding-rectangle}. \Defgeneric {window-erase-viewport} {window} @@ -739,19 +848,75 @@ Clears the visible part of the drawing plane of the CLIM stream pane \Defgeneric {window-viewport-position} {window} Returns two values, the $x$ and $y$ position of the top-left corner of the CLIM -stream pane \arg{window}'s viewport. +stream pane \arg{window}'s viewport. If the window is not scrollable, this will +return the two values 0 and 0. \Defgeneric {(setf* window-viewport-position)} {x y window} Sets the position of the CLIM stream pane \arg{window}'s viewport to \arg{x} and -\arg{y}. +\arg{y}. If the window is not scrollable, this will do nothing. + +For CLIM implementations that do not support \cl{setf*}, the ``setter'' function +for this is \cl{window-set-viewport-position}. + + +\subsection {Creating a Standalone CLIM Window} + +The following function can be used to create a standalone window that obeys +CLIM's extended input and output stream and output recording protocols. + +\Defun {open-window-stream} {\key port left top right bottom width height + foreground background text-style + (vertical-spacing \cl{2}) + end-of-line-action end-of-page-action + output-record (draw \cl{t}) (record \cl{t}) + (initial-cursor-visibility \cl{:off}) + text-margin save-under input-buffer + (scroll-bars \cl{:vertical}) borders label} + +Creates and returns a sheet that can be used as a standalone window that obeys +CLIM's extended input and output stream and output recording protocols. + +The window will be created on the port \arg{port} at the position specified by +\arg{left} and \arg{top}, which default to 0. \arg{right}, \arg{bottom}, +\arg{width}, and \arg{height} default in such a way that the default width will +be 100 and the default height will be 100. + +\arg{foreground}, \arg{background}, and \arg{text-style} are used to specify the +window's default foreground and background inks, and text style. +\arg{vertical-spacing}, \arg{text-margin}, \arg{end-of-line-action}, +\arg{end-of-page-action}, \arg{output-record}, \arg{draw}, and \arg{record} are +described in Section~\ref{clim-pane-options}. + +\arg{scroll-bars} specifies whether scroll bars should be included in the +resulting window. It may be one of \arg{nil}, \cl{:vertical} (the default), +\cl{:horizontal}, or \cl{:both}. + +\arg{borders} is a booleans that specifies whether or not the resulting window +should have a border drawn around it. The default is \cl{t}. \arg{label} is +either \cl{nil} or a string to use as a label for the window. + +\arg{initial-cursor-visibility} is used to specify whether the window should +have a text cursor. \cl{:off} (the default) means to make the cursor visible if +the window is waiting for input. \cl{:on} means to make the cursor visible +immediately. \cl{nil} means the cursor will not be visible at all. + +When \arg{save-under} is \term{true}, the result window will be given a ``bit +save array''. The default is \cl{nil}. + +If \cl{input-buffer} is supplied, it is an input buffer or event queue to use +for the resulting window. Programmers will generally supply this when they want +the new window to share its input buffer with an existing application. The +default is to create a new input buffer. \section {Defining New Pane Types} -This section describes how to define new pane classes. +This section describes how to define new pane classes. The first section shows +a new kind of leaf pane (an odd kind of push-button). The second section shows +a new composite pane that draws a dashed border around its contents. -\subsection {Defining Leaf Panes} +\subsection {Defining a New Leaf Pane} To define a gadget pane implementation, first define the appearance and layout behavior of the gadget, then define the callbacks, then define the specific user @@ -761,26 +926,31 @@ For example, to define an odd new kind of button that displays itself as a circle, and activates whenever the mouse is moved over it, proceed as follows: \begin{verbatim} -;; A new kind of button -(defclass sample-button-pane (gadget-pane) ()) - -;; An arbitrary size parameter +;; A new kind of button. +(defclass sample-button-pane + (action-gadget + space-requirement-mixin + leaf-pane) + ()) + +;; An arbitrary size parameter. (defparameter *sample-button-radius* 10) ;; Define the sheet's repaint method to draw the button. -(defmethod handle-repaint ((button sample-button-pane) region - &key medium &allow-other-keys) - (let ((radius *sample-button-radius*) - (half (round *sample-button-radius* 2))) - ;; Larger circle with small one in the center. - (draw-circle* medium radius radius radius - :filled nil) - (draw-circle* medium radius radius half - :filled t))) - -;;; Define the pane's compose-space method to always request the -;;; fixed size of the pane. -(defmethod compose-space ((pane sample-button-pane)) +(defmethod handle-repaint ((button sample-button-pane) region) + (with-sheet-medium (medium button) + (let ((radius *sample-button-radius*) + (half (round *sample-button-radius* 2))) + ;; Larger circle with small one in the center + (draw-circle* medium radius radius radius + :filled nil) + (draw-circle* medium radius radius half + :filled t))) + +;; Define the pane's compose-space method to always request the +;; fixed size of the pane. +(defmethod compose-space ((pane sample-button-pane) &key width height) + (declare (ignore width height)) (make-space-requirement :width (* 2 *sample-button-radius*) :height (* 2 *sample-button-radius*))) \end{verbatim} @@ -794,20 +964,71 @@ interaction that triggers them. \begin{verbatim} ;; This default method is defined so that the callback can be invoked -;; on an arbitrary client value without error. -(defmethod value-change-callback - ((button sample-button-pane) client id value) +;; on an arbitrary client without error. +(defmethod activate-callback + ((button sample-button-pane) client id) (declare (ignore client id value))) ;; This event processing method defines the rather odd interaction -;; style of this button, to whit: it triggers the activate callback +;; style of this button, to wit, it triggers the activate callback ;; whenever the mouse moves into it. -(defmethod enter-region ((pane sample-button-pane) &key &allow-other-keys) - (value-change-callback pane (gadget-client pane) (gadget-id pane) nil)) +(defmethod handle-event ((pane sample-button-pane) (event pointer-enter-event)) + (activate-callback pane (gadget-client pane) (gadget-id pane))) \end{verbatim} -\subsection {Defining Composite Panes} +\subsection {Defining a New Composite Pane} -\issue {ILA} {To be supplied.} +To define a new layout pane implementation, the programmer must define how the +much space the pane takes, where its children go, and what the pane looks like. +For example, to define a new kind of border pane that draws a dashed border +around its child pane, proceed as follows: + +\begin{verbatim} +;; The new layout pane class. +(defclass dashed-border-pane (layout-pane) + ((thickness :initform 1 :initarg :thickness)) + (:default-initargs :background +black+)) + +;; The specified contents are the sole child of the pane. +(defmethod initialize-instance :after ((pane dashed-border-pane) &key contents) + (sheet-adopt-child pane contents)) + +;; The composite pane takes up all of the space of the child, plus +;; the space required for the border. +(defmethod compose-space ((pane dashed-border-pane) &key width height) + (let ((thickness (slot-value pane 'thickness)) + (child (sheet-child pane))) + (space-requirement+ + (compose-space child :width width :height height) + (make-space-requirement + :width (* 2 thickness) + :height (* 2 thickness))))) + +;; The child pane is positioned just inside the borders. +(defmethod allocate-space ((pane dashed-border-pane) width height) + (let ((thickness (slot-value pane 'thickness))) + (move-and-resize-sheet + (sheet-child pane) + thickness thickness + (- width (* 2 thickness)) (- height (* 2 thickness))))) + +(defmethod handle-repaint ((pane dashed-border-pane) region) + (declare (ignore region)) ;not worth checking + (with-sheet-medium (medium pane) + (with-bounding-rectangle* (left top right bottom) (sheet-region pane) + (let ((thickness (slot-value pane 'thickness))) + (decf right (ceiling thickness 2)) + (decf bottom (ceiling thickness 2)) + (draw-rectangle* medium left top right bottom + :line-thickness thickness :filled nil + :ink (pane-background pane)))))) + +(defmacro dashed-border ((&rest options &key thickness &allow-other-keys) + &body contents) + (declare (ignore thickness)) + `(make-pane 'dashed-border-pane + :contents ,@contents + ,@options)) +\end{verbatim} diff --git a/specs/presentation-types.tex b/specs/presentation-types.tex index 913c0c3c..4213f991 100644 --- a/specs/presentation-types.tex +++ b/specs/presentation-types.tex @@ -62,19 +62,18 @@ presentations to be nested?} \Defprotoclass {presentation} -The protocol class that corresponds to a presentation. A subclass of -\cl{output-record}. +The protocol class that corresponds to a presentation. \IfYouWantClass {a} {presentation} {presentation} -\Defun {presentationp} {object} +\Defpredicate {presentationp} {object} Returns \term{true} if \arg{object} is a \term{presentation}, otherwise returns \term{false}. \Defclass {standard-presentation} -The output record class that represents presentations. \cl{present} normally -creates output records of this class. +The instantiable output record class that represents presentations. +\cl{present} normally creates output records of this class. \Mutable \definitarg {:object} @@ -359,7 +358,7 @@ this expands the type abbreviation once, and returns two values, the expansion and \cl{t}. If \arg{type} is not a presentation type abbreviation, then the values \arg{type} and \cl{nil} are returned. -\arg{env} is a macro-expansion environment, as in \cl{macroexpand}. +\arg{env} is a macro-expansion environment, as for \cl{macroexpand}. \Defun {expand-presentation-type-abbreviation} {type \optional env} @@ -702,9 +701,18 @@ at least as specific as \arg{type}. \arg{(type-key parameters default type \key default-type)} -\Defpresmeth {presentation-refined-position-test} {} +\Defpresmeth {presentation-refined-position-test} {type record x y} -\issue {SWM} {To be supplied.} +This method used to definitively answer hit detection queries for a +presentation, that is, determining that the point $(x,y)$ is contained within +the output record \arg{record}. Its contract is exactly the same as for +\cl{output-record-refined-position-test}, except that it is intended to +specialize on the presentation type \arg{type}. + +{\bf Implementation note:} the actual argument list to the +\cl{presentation-refined-position-test} method is +\\ +\arg{(type-key parameters options type record x y)} \Defpresmeth {highlight-presentation} {type record stream state} @@ -826,7 +834,7 @@ This is analogous to the Common Lisp \cl{typep} function. Returns a presentation type of which \arg{object} is a member. \cl{presentation-type-of} returns the most specific presentation type that can be conveniently computed and is likely to be useful to the programmer. This is -often the class name of the clas of the object. +often the class name of the class of the object. If \cl{presentation-type-of} cannot determine the presentation type of the object, it may return either \cl{expression} or \cl{t}. @@ -918,8 +926,8 @@ time. The object can be any Lisp object. \Defmacro {with-output-as-presentation} {(stream object type - \key modifier single-box - allow-sensitive-inferiors record-type) + \key modifier single-box allow-sensitive-inferiors + parent record-type \allow) \body body} The output of \arg{body} to the \term{extended output recording} \arg{stream} is @@ -952,6 +960,10 @@ When the boolean \arg{allow-sensitive-inferiors} is \term{false}, nested calls to \cl{present} or \cl{with-output-as-presentation} inside this one will not generate presentations. The default is \term{true}. +\arg{parent} specifies what output record should serve as the parent for the +newly created presentation. If unspecified, \cl{stream-current-output-record} +of \arg{stream} will be used as the parent. + \arg{record-type} specifies the class of the presentation output record to be created. It defaults to \cl{standard-presentation}. This argument should only be supplied by a programmer if there is a new class of output record that @@ -1054,15 +1066,20 @@ be nested?} The current input context. This will be a list, each element of which corresponds to a single call to \cl{with-input-context}. The first element of -the list is the context established by the most recent call to -\cl{with-input-context}, and the last element is the least recent call to -\cl{with-input-context}. +the list represents the context established by the most recent call to +\cl{with-input-context}, and the last element represents the context established +by the least recent call to \cl{with-input-context}. The exact format of the elements in the list is unspecified, but will typically be a list of a presentation type and a tag that corresponds to the point in the control structure of CLIM at which the input context was establish. \cl{*input-context*} and the elements in it may have dynamic extent. +\Defun {input-context-type} {context-entry} + +Given one element from \cl{*input-context*}, \arg{context-entry}, returns the +presentation type of the context entry. + \Defmacro {with-input-context} {(type \key override) (\optional object-var type-var event-var options-var) form @@ -1113,13 +1130,13 @@ For example, \Defun {accept} {type \key stream view default default-type provide-default - insert-default replace-input history + insert-default replace-input history active-p prompt prompt-mode display-default query-identifier activation-gestures additional-activation-gestures delimiter-gestures additional-delimiter-gestures} Requests input of type \arg{type} from the \term{stream} \arg{stream}, which -defaults to \cl{*query-io*}. \cl{accept} returns two values, the object +defaults to \cl{*standard-input*}. \cl{accept} returns two values, the object representing the input and its presentation type. \arg{type} is a presentation type specifier, and can be an abbreviation. The other arguments and overall behavior of \cl{accept} are as for \cl{accept-1}. @@ -1134,7 +1151,7 @@ arguments. \Defgeneric {stream-accept} {stream type \key view default default-type provide-default - insert-default replace-input history + insert-default replace-input history active-p prompt prompt-mode display-default query-identifier activation-gestures additional-activation-gestures delimiter-gestures additional-delimiter-gestures} @@ -1159,7 +1176,7 @@ the default behavior. \Defun {accept-1} {stream type \key view default default-type provide-default - insert-default replace-input history + insert-default replace-input history active-p prompt prompt-mode display-default query-identifier activation-gestures additional-activation-gestures delimiter-gestures additional-delimiter-gestures} @@ -1223,7 +1240,11 @@ suppresses putting a colon after the prompt and/or default in a top-level in a nested \cl{accept}. \arg{query-identifier} is used within \cl{accepting-values} to identify the -field within the dialog. +field within the dialog. The \cl{active-p} argument (which defaults to \cl{t}) +can be used to control whether a field within an \cl{accepting-values} is +active; when \term{false}, the field will not be active, that is, it will not be +available for input. Some CLIM implementations will provide a visual cue that +the field is inactive, for instance, by ``graying out'' the field. \arg{activation-gestures} is a list of gesture names that will override the current activation gestures (which are stored in \cl{*activation-gestures*}). @@ -1300,49 +1321,49 @@ The protocol class for view objects. All of the view classes are immutable. -\Defun {viewp} {object} +\Defpredicate {viewp} {object} Returns \term{true} if \arg{object} is a \term{view}, otherwise returns \term{false}. \Defclass {textual-view} -The class representing all textual views, a subclass of \cl{view}. Presentation -methods that apply to a textual view must only do textual input and output (such -as \cl{read-char} and \cl{write-string}). +The instantiable class representing all textual views, a subclass of \cl{view}. +Presentation methods that apply to a textual view must only do textual input and +output (such as \cl{read-char} and \cl{write-string}). \Defclass {textual-menu-view} -The class that represents the default view that is used inside \cl{menu-choose} -for frame managers that are not using a gadget-oriented look and feel. It is a -subclass of \cl{textual-view}. +The instantiable class that represents the default view that is used inside +\cl{menu-choose} for frame managers that are not using a gadget-oriented look +and feel. It is a subclass of \cl{textual-view}. \Defclass {textual-dialog-view} -The class that represents the default view that is used inside +The instantiable class that represents the default view that is used inside \cl{accepting-values} dialogs for frame managers that are not using a gadget-oriented look and feel. It is a subclass of \cl{textual-view}. \Defclass {gadget-view} -The class representing all gadget views, a subclass of \cl{view}. +The instantiable class representing all gadget views, a subclass of \cl{view}. \Defclass {gadget-menu-view} -The class that represents the default view that is used inside \cl{menu-choose} -for frame managers that are using a gadget-oriented look and feel. It is a -subclass of \cl{gadget-view}. +The instantiable class that represents the default view that is used inside +\cl{menu-choose} for frame managers that are using a gadget-oriented look and +feel. It is a subclass of \cl{gadget-view}. \Defclass {gadget-dialog-view} -The class that represents the default view that is used inside +The instantiable class that represents the default view that is used inside \cl{accepting-values} dialogs for frame managers that are using a gadget-oriented look and feel. It is a subclass of \cl{gadget-view}. \Defclass {pointer-documentation-view} -The class that represents the default view that is used when computing pointer -documentation. It is a subclass of \cl{textual-view}. +The instantiable class that represents the default view that is used when +computing pointer documentation. It is a subclass of \cl{textual-view}. \defconst {+textual-view+} \defconst {+textual-menu-view+} @@ -1562,13 +1583,13 @@ None of \cl{define-presentation-action}'s arguments is evaluated. \Defmacro {define-drag-and-drop-translator} {name - from-type to-type destination-type command-table - \key gesture tester - documentation pointer-documentation - menu priority - feedback highlighting} + (from-type to-type destination-type command-table + \key gesture tester + documentation pointer-documentation + menu priority + feedback highlighting) arglist - \body body) + \body body} Defines a ``drag and drop'' (or ``direct manipulation'') translator named \arg{name} that translates from objects of type \arg{from-type} to objects of @@ -1636,6 +1657,10 @@ pointer around in any CLIM pane), it should cache its result in order to avoid consing. Therefore, the resulting list of translators should not be modified; the consequences of doing so are unspecified. +{\bf Implementation note:} The ordering of the list of translators is left +unspecified, but implementations may find it convenient to return the list using +the ordering specified for \cl{find-applicable-translators}. + \Defun {test-presentation-translator} {translator presentation context-type frame window x y \key event modifier-state for-menu} @@ -1669,19 +1694,19 @@ ensure that its value matches \arg{to-type}. \Defun {find-applicable-translators} {presentation input-context frame window x y \key event modifier-state for-menu fastp} -Returns an object that describes the translators that definitely apply to the +Returns a list that describes the translators that definitely apply to the \term{presentation} \arg{presentation} in the input context \arg{input-context}. -The result is a list whose elements are each of the form +Each element in the returned list is of the form \\ -\arg{(translator the-presentation context-type tag)} +\arg{(translator the-presentation context-type . rest)} \\ where \arg{translator} is a presentation translator, \arg{the-presentation} is the presentation that the translator applies to (and can be different from \arg{presentation} due to nesting of presentations), \arg{context-type} is the -context type that in which the translator applies, and \arg{tag} is a tag used -internally by CLIM. \arg{translator}, \arg{the-presentation}, and -\arg{context-type} can be passed to such functions as -\cl{call-presentation-translator} and \cl{document-presentation-translator}. +context type in which the translator applies, and \arg{rest} is other +unspecified data reserved for internal use by CLIM. \arg{translator}, +\arg{the-presentation}, and \arg{context-type} can be passed to such functions +as \cl{call-presentation-translator} and \cl{document-presentation-translator}. Since input contexts can be nested, \cl{find-applicable-translators} must iterate over all the contexts in \arg{input-context}. \arg{window}, \arg{x}, @@ -1691,6 +1716,11 @@ for \arg{window}, respectively) are used to further restrict the set of applicable translators. (Only one of \arg{event} or \arg{modifier-state} may be supplied; it is unspecified what will happen if both are supplied.) +Presentations can also be nested. The ordering of the translators returned by +\cl{find-applicable-translators} is that translators matching inner contexts +should precede translators matching outer contexts, and, in the same input +context, inner presentations precede outer presentations. + When \arg{for-menu} is non-\cl{nil}, this matches the value of \arg{for-menu} against the presentation's menu specification, and returns only those translators that match. \arg{event} and \arg{modifier-state} are disregarded in @@ -1813,8 +1843,8 @@ it is unspecified what will happen if both are supplied. \arg{frame} defaults to the current frame, \cl{*application-frame*}. -The default method for {frame-find-innermost-applicable-presentation} will call -this function. +The default method for \cl{frame-find-innermost-applicable-presentation} will +call this function. \Defun {throw-highlighted-presentation} {presentation input-context button-press-event} @@ -1846,6 +1876,10 @@ entry to \cl{highlight-applicable-presentation}, \arg{input-context} will be the value of \cl{*input-context*} and \arg{frame} will be the value of \cl{*application-frame*}. +If \arg{prefer-pointer-window} is \term{true} (the default), CLIM will highlight +the applicable presentation on the same window that the pointer is located over. +Otherwise, CLIM will highlight an applicable presentation on \arg{stream}. + {\bf Implementation note:} This will probably use \cl{frame-find-innermost-applicable-presentation-at-position} to locate the innermost presentation, and \cl{unhighlight-highlighted-presentation} and @@ -1857,11 +1891,15 @@ innermost presentation, and \cl{unhighlight-highlighted-presentation} and Highlights the \term{presentation} \arg{presentation} on \arg{stream}. This must call \cl{highlight-presentation} methods if that is appropriate. +\arg{prefer-pointer-window} is as for \cl{highlight-applicable-presentation}. + \Defun {unhighlight-highlighted-presentation} {stream \optional prefer-pointer-window} Unhighlights any highlighted presentations on \arg{stream}. +\arg{prefer-pointer-window} is as for \cl{highlight-applicable-presentation}. + \subsection {Translator Applicability} @@ -1999,10 +2037,13 @@ no applicable presentations. This will have a presentation type of \cl{blank-ar The type that represents a general number. It is the supertype of all the number types. -\Defptype {complex} {} +\Defptype {complex} {\optional type} The type that represents a complex number. It is a subtype of \cl{number}. +The components of the complex number are of type \arg{type}, which must be +\cl{real} or a subtype of \cl{real}. + \Defptype {real} {\optional low high} The type that represents either a ratio, an integer, or a floating point number @@ -2208,6 +2249,14 @@ The type that is used to specify one of several types, for example, \cl{(or type abbreviations. \cl{accept} returns one of the possible types as its second value, not the original \cl{or} presentation type specifier. +The \cl{accept} method for \cl{or} could be implemented by iteratively calling +\cl{accept} on each of the presentation types in \arg{types}. It would +establish a condition handler for \cl{parse-error}, call \cl{accept} on one of +the types and return the result if no condition was signalled. If a +\cl{parse-error} is signalled, the \cl{accept} method for \cl{or} would call +\cl{accept} on the next type. When there are no more types, the \cl{accept} +method for \cl{or} would itself signal a \cl{parse-error}. + \Defptype {and} {\rest types} diff --git a/specs/psfig+.tex b/specs/psfig+.tex index df372343..eb72a102 100644 --- a/specs/psfig+.tex +++ b/specs/psfig+.tex @@ -9,7 +9,7 @@ % distribute any portion of psfig/tex for profit or as part of any commercial % product is specifically reserved for the author. % -% $Header: /repo/cvs.copy/clim2/specs/psfig+.tex,v 1.1 1993/01/18 13:57:12 cer Exp $ +% $Header: /repo/cvs.copy/clim2/specs/psfig+.tex,v 1.2 1993/03/19 09:45:58 cer Exp $ % $Source: /repo/cvs.copy/clim2/specs/psfig+.tex,v $ % % Thanks to Greg Hager (GDH) and Ned Batchelder for their contributions diff --git a/specs/redisplay.tex b/specs/redisplay.tex index e283861c..6f61b738 100644 --- a/specs/redisplay.tex +++ b/specs/redisplay.tex @@ -8,15 +8,14 @@ CLIM's incremental redisplay facility to allows the programmer to change the output in an output history (and hence, on the screen or other output device) in an incremental fashion. It allows the programmer to redisplay individual pieces -of the existing output differently, under program control. - -It is ``incremental'' in the sense that CLIM will try to minimize the changes to -the existing output on a display device when displaying new output. +of the existing output differently, under program control. It is +``incremental'' in the sense that CLIM will try to minimize the changes to the +existing output on a display device when displaying new output. There are two different ways to do incremental redisplay. -The first is to call \cl{redisplay} on an output record. This essentially tells -the system to recompute the output of that output record over from scratch. It +The first is to call \cl{redisplay} on an output record. In essence, this tells +CLIM to recompute the output of that output record over from scratch. CLIM compares the new results with the existing output and tries to do minimal redisplay. The \cl{updating-output} form allows the programmer to assist CLIM by informing it that entire branches of the output history are known not to have @@ -25,10 +24,11 @@ fact that a piece of the output record hierarchy has moved, either by having an output record change its parent, or by having an output record change its position. -The second way to do incremental redisplay is to manually do the updates to the -output history, and then call \cl{note-output-record-child-changed} on an output -record. This causes CLIM to propagate the changes up the output record tree and -allows parent output records to readjust themselves to account for the changes. +The second way to do incremental redisplay is for the programmer to manually do the +updates to the output history, and then call \cl{note-output-record-child-changed} +on an output record. This causes CLIM to propagate the changes up the output +record tree and allows parent output records to readjust themselves to account for +the changes. Each style is appropriate under different circumstances. \cl{redisplay} is often easier to use, especially when there might are large numbers of changes @@ -56,23 +56,23 @@ just hints to incremental redisplay that can reduce the amount of work done by CLIM. The outermost call to \cl{updating-output} executes its body, producing the -initial version of the output, and returns an incremental redisplay record that +initial version of the output, and returns an \cl{updating-output-record} that captures the body in a closure. Each nested call to \cl{updating-output} stores its \cl{:unique-id} and \cl{:cache-value} arguments and the portion of the output produced by its body. -\cl{redisplay} takes an incremental redisplay record and executes the captured +\cl{redisplay} takes an \cl{updating-output-record} and executes the captured body of \cl{updating-output} over again. When a nested call to \cl{updating-output} is executed during redisplay, \cl{updating-output} decides whether the cached output can be reused or the output needs to be redrawn. This is controlled by the \cl{:cache-value} argument to \cl{updating-output}. If its value matches its previous value, the body would produce output identical to the -previous output and thus is unnecessary. In this case the cached output is -reused and \cl{updating-output} does not execute its body. If the cache value -does not match, the output needs to be redrawn, so \cl{updating-output} executes -its body and the new output drawn on the stream replaces the previous output. -The \cl{:cache-value} argument is only meaningful for nested calls to -\cl{updating-output}. +previous output and thus it is unnecessary for CLIM to execute the body again. +In this case the cached output is reused and \cl{updating-output} does not +execute its body. If the cache value does not match, the output needs to be +recomputed, so \cl{updating-output} executes its body and the new output drawn +on the stream replaces the previous output. The \cl{:cache-value} argument is +only meaningful for nested calls to \cl{updating-output}. In order to compare the cache to the output record, two pieces of information are necessary: @@ -164,7 +164,7 @@ CLIM takes care of ensuring that only the third line gets erased and redisplayed. In the case where items moved around (try the example substituting \begin{verbatim} -(setf list (sort list #'(lambda (x y) +(setq list (sort list #'(lambda (x y) (declare (ignore x y)) (zerop (random 2))))) \end{verbatim} @@ -183,8 +183,7 @@ redisplay automatically within the panes of an application frame. \rest args \key unique-id (id-test \#'\cl{eql}) cache-value (cache-test \#'\cl{eql}) - copy-cache-value fixed-position - all-new parent-cache + fixed-position all-new parent-cache record-type) \body body} @@ -206,7 +205,7 @@ behavior of this macro is described under \cl{invoke-updating-output}. \Defgeneric {invoke-updating-output} {stream continuation record-type unique-id id-test - cache-value cache-test copy-cache-value + cache-value cache-test \key all-new parent-cache} Introduces a caching point for incremental redisplay. Calls the function @@ -233,9 +232,7 @@ that is used for comparing unique ids; it has indefinite extent. produced by body does not need to be recomputed. If the cache value is not supplied, CLIM will not use a cache for this piece of output. \arg{cache-test} is a function of two arguments that is used for comparing cache values; it has -indefinite extent. If \arg{copy-cache-value} is \term{true}, then the supplied -cache value will be copied using \cl{copy-seq} before it is stored in the output -record. The default for \arg{copy-cache-value} is \term{false}. +indefinite extent. If \arg{fixed-position} is \term{true}, then the location of this output is fixed relative to its parent output record. When CLIM redisplays an output @@ -286,8 +283,9 @@ history of the \term{output recording stream} \arg{stream}, although it can be anywhere inside the hierarchy. When \arg{check-overlapping} is \term{false}, this means that CLIM can assume -that no sibling output records overlap each other at any level. Supplying a -\term{false} value for this argument can improve performance of redisplay. +that no sibling output records overlap each other at any level in the output +record tree. Supplying a \term{false} value for this argument can improve +performance of redisplay. {\bf Implementation note:} \cl{redisplay-output-record} is implemented by first binding \cl{stream-redisplaying-p} of the stream to \term{true}, then creating @@ -327,7 +325,7 @@ The protocol class corresponding to records that support incremental redisplay; a subclass of \cl{output-record}. \IfYouWantClass {an} {updating output record} {updating-output-record} -\Defun {updating-output-record-p} {object} +\Defpredicate {updating-output-record-p} {object} Returns \term{true} if \arg{object} is an \term{updating output record}, otherwise returns \term{false}. @@ -419,7 +417,8 @@ that no sibling output records overlap each other at any level. Supplying a \item \arg{move-overlapping} is a list of \cl{(\arg{record} \arg{old-box} \arg{new-position})} \end{itemize} -\Defgeneric {augment-draw-set} {record erases moves draws erase-overlapping move-overlapping} +\Defgeneric {augment-draw-set} {record erases moves draws erase-overlapping move-overlapping + \optional x-offset y-offset old-x-offset old-y-offset} \issue {SWM} {To be supplied.} @@ -514,7 +513,7 @@ contents of the record. \section {Incremental Redisplay Stream Protocol} -\Defgeneric {stream-redisplayable-p} {stream} +\Defgeneric {redisplayable-stream-p} {stream} Returns \term{true} for any stream that maintains an output history and supports the incremental redisplay protocol, otherwise returns \term{false}. diff --git a/specs/regions.tex b/specs/regions.tex index 4469df47..bbfe65a0 100644 --- a/specs/regions.tex +++ b/specs/regions.tex @@ -64,7 +64,7 @@ Chapter~\ref{color}). There is no general constructor called \cl{make-region} because of the impossibility of a uniform way to specify the arguments to such a function. -\Defun {regionp} {object} +\Defpredicate {regionp} {object} Returns \term{true} if \arg{object} is a \term{region}, otherwise returns \term{false}. @@ -77,19 +77,19 @@ The protocol class \cl{path} denotes bounded regions that have \IfYouWantClass {a} {path} {path} Constructing a \cl{path} object with no length (via \cl{make-line*}, for -example) canonicalizes it to \cl{+nowhere+}. +example) may canonicalize it to \cl{+nowhere+}. Some rendering models support the constructing of areas by filling a closed path. In this case, the path needs a direction associated with it. Since CLIM does not currently support the path-filling model, paths are directionless. -\Defun {pathp} {object} +\Defpredicate {pathp} {object} Returns \term{true} if \arg{object} is a \term{path}, otherwise returns \term{false}. Note that constructing a \cl{path} object with no length (such as calling -\cl{make-line} with two coincident points), for example) canonicalizes it to +\cl{make-line} with two coincident points), for example) may canonicalize it to \cl{+nowhere+}. \Defprotoclass {area} @@ -99,25 +99,30 @@ The protocol class \cl{area} denotes bounded regions that have dimensionality 2 \IfYouWantClass {an} {area} {area} Note that constructing an \cl{area} object with no area (such as calling -\cl{make-rectangle} with two coincident points), for example) canonicalizes it -to \cl{+nowhere+}. +\cl{make-rectangle} with two coincident points), for example) may canonicalize +it to \cl{+nowhere+}. -\Defun {areap} {object} +\Defpredicate {areap} {object} Returns \term{true} if \arg{object} is an \term{area}, otherwise returns \term{false}. \Deftype {coordinate} -The type that represents a coordinate. This must be a subtype of \cl{real}, but -CLIM implementations may use a more specific subtype (such as \cl{single-float}) -for reasons of efficiency. +The type that represents a coordinate. This must either be \cl{t}, or a +subtype of \cl{real}. CLIM implementations may use a more specific subtype of +\cl{real}, such as \cl{single-float}, for reasons of efficiency. All of the specific region classes and subclasses of \cl{bounding-rectangle} will use this type to store their coordinates. However, the constructor functions for the region classes and for bounding rectangles must accept numbers of any type and coerce them to \cl{coordinate}. +\Defun {coordinate} {n} + +Coerces the number \arg{n} to be a coordinate. + + \defconst {+everywhere+} \Defconst {+nowhere+} @@ -204,7 +209,7 @@ the union of several axis-aligned rectangles. \Immutable -\Defun {region-set-p} {object} +\Defpredicate {region-set-p} {object} Returns \term{true} if \arg{object} is a \term{region set}, otherwise returns \term{false}. @@ -276,8 +281,8 @@ always has dimensionality that is the maximum dimensionality of \arg{region1} and \arg{region2}. For example, the union of a path and an area produces an area; the union of two paths is a path. -\cl{region-union} will return either a simple region or a member of the class -\cl{standard-region-union}. +\cl{region-union} will return either a simple region, a region set, or a member +of the class \cl{standard-region-union}. \MayCaptureInputs @@ -307,8 +312,8 @@ boundary points to make the result closed). The result of same area; the difference of a path and an area produces the path clipped to stay outside of the area. -\cl{region-difference} will return either a simple region or a member of the -class \cl{standard-region-difference}. +\cl{region-difference} will return either a simple region, a region set, or a +member of the class \cl{standard-region-difference}. \MayCaptureInputs @@ -324,16 +329,17 @@ class \cl{standard-region-difference}. The other types of regions are points, polylines, polygons, elliptical arcs, and ellipses. All of these region types are closed under affine transformations. -\Issue {SWM, York} {There is a proposal to remove the \cl{polygon}, \cl{polyline}, -\cl{line}, \cl{ellipse}, and {elliptical-arc} classes, since they are only of -limited utility, and CLIM itself doesn't use the classes at all. The advantage -of removing these classes is that both the spec and CLIM itself become a little -simpler, and there are fewer cases of the region protocol to implement. -However, removing these classes results in a geometric model that is no longer -closed (in the mathematical sense). Furthermore, these are intuitive objects -that are used by a small, but important, class of applications, and some people -feel that CLIM should relieve programmers from having to implement these classes -for himself or herself. +\Issue {SWM, York} {There is a proposal to remove the \cl{polygon}, +\cl{polyline}, \cl{line}, \cl{ellipse}, and \cl{elliptical-arc} classes, since +they are only of limited utility, and CLIM itself doesn't use the classes at +all. The advantage of removing these classes is that both the spec and CLIM +itself become a little simpler, and there are fewer cases of the region protocol +to implement. However, removing these classes results in a geometric model that +is no longer closed (in the mathematical sense). This lack of closure makes it +difficult to specify the design-based drawing model. Furthermore, these are +intuitive objects that are used by a small, but important, class of +applications, and some people feel that CLIM should relieve programmers from +having to implement these classes for himself or herself. The advocates of of removing these classes also propose removing the design-based drawing model. In this case, a more consistent proposal is to @@ -368,7 +374,7 @@ The protocol class that corresponds to a mathematical point. This is a subclass of \cl{region} and \cl{bounding-rectangle}. \IfYouWantClass {a} {point} {point} -\Defun {pointp} {object} +\Defpredicate {pointp} {object} Returns \term{true} if \arg{object} is a \term{point}, otherwise returns \term{false}. @@ -425,7 +431,7 @@ The protocol class that corresponds to a polyline. This is a subclass of \cl{path}. \IfYouWantClass {a} {polyline} {polyline} -\Defun {polylinep} {object} +\Defpredicate {polylinep} {object} Returns \term{true} if \arg{object} is a \term{polyline}, otherwise returns \term{false}. @@ -460,7 +466,7 @@ The protocol class that corresponds to a mathematical polygon. This is a subclass of \cl{area}. \IfYouWantClass {a} {polygon} {polygon} -\Defun {polygonp} {object} +\Defpredicate {polygonp} {object} Returns \term{true} if \arg{object} is a \term{polygon}, otherwise returns \term{false}. @@ -530,7 +536,7 @@ The protocol class that corresponds to a mathematical line segment, that is, a polyline with only a single segment. This is a subclass of \cl{polyline}. \IfYouWantClass {a} {line} {line} -\Defun {linep} {object} +\Defpredicate {linep} {object} Returns \term{true} if \arg{object} is a \term{line}, otherwise returns \term{false}. @@ -593,7 +599,7 @@ rectangular polygons whose sides are parallel to the coordinate axes. This is a subclass of \cl{polygon}. \IfYouWantClass {a} {rectangle} {rectangle} -\Defun {rectanglep} {object} +\Defpredicate {rectanglep} {object} Returns \term{true} if \arg{object} is a \term{rectangle}, otherwise returns \term{false}. @@ -729,7 +735,7 @@ The protocol class that corresponds to a mathematical ellipse. This is a subclass of \cl{area}. \IfYouWantClass {an} {ellipse} {ellipse} -\Defun {ellipsep} {object} +\Defpredicate {ellipsep} {object} Returns \term{true} if \arg{object} is an \term{ellipse}, otherwise returns \term{false}. @@ -778,7 +784,7 @@ The protocol class that corresponds to a mathematical elliptical arc. This is a subclass of \cl{path}. \IfYouWantClass {an} {elliptical arc} {elliptical-arc} -\Defun {elliptical-arc-p} {object} +\Defpredicate {elliptical-arc-p} {object} Returns \term{true} if \arg{object} is an \term{elliptical arc}, otherwise returns \term{false}. diff --git a/specs/silica.tex b/specs/silica.tex index b9e5621b..04b174af 100644 --- a/specs/silica.tex +++ b/specs/silica.tex @@ -129,18 +129,23 @@ calling \cl{make-pane} is how application programmers will make sheets. \Defprotoclass {sheet} -The protocol class that corresponds to a sheet, a subclass of -\cl{bounding-rectangle}. This and the next chapter describe all of the sheet -protocols. +The protocol class that corresponds to a sheet. This and the next chapter +describe all of the sheet protocols. \IfYouWantClass {a} {sheet} {sheet} All of the subclasses of \cl{sheet} are mutable. -\Defun {sheetp} {object} +\Defpredicate {sheetp} {object} Returns \term{true} if \arg{object} is a \term{sheet}, otherwise returns \term{false}. +\Defclass {basic-sheet} + +The basic class on which all CLIM sheets are built, a subclass of \cl{sheet}. +\AbstractClass + + \section {Relationships Between Sheets} @@ -279,10 +284,19 @@ are enabled and appear earlier in the \term{sheet} \arg{sheet}'s children. If \FreshOutputs +\Defgeneric {map-over-sheets} {function sheet} + +Applies the function \arg{function} to the sheet \arg{sheet}, and then applies +\arg{function} to all of the descendents (the children, the children's children, +and so forth) of \arg{sheet}. + +Function is a function of one argument, the sheet; it has dynamic extent. + \subsection {Sheet Genealogy Classes} -Different ``mixin'' classes are provided that implement the relationship protocol. +Different ``mixin'' classes are provided that implement the relationship +protocol. None of the four following classes is instantiable. \Defclass {sheet-parent-mixin} @@ -319,8 +333,9 @@ Returns a transformation that converts coordinates in the \term{sheet} system. Using \cl{setf} on this accessor will modify the sheet's coordinate system, including moving its region in its parent's coordinate system. -When the sheet's transformation is changed, \cl{note-sheet-region-changed} is -called to notify the sheet of the change. +When the sheet's transformation is changed, +\cl{note-sheet-transformation-changed} is called on the to notify the sheet of +the change. \defgeneric {sheet-region} {sheet} \Defgeneric {(setf sheet-region)} {region sheet} @@ -329,8 +344,8 @@ Returns a region object that represents the set of points to which the \term{sheet} \arg{sheet} refers. The region is in the sheet's coordinate system. Using \cl{setf} on this accessor modifies the sheet's region. -When the sheet's region is changed, \cl{note-sheet-region-region} is called - to notify the sheet of the change. +When the sheet's region is changed, \cl{note-sheet-region-region} is called on +\arg{sheet} to notify the sheet of the change. \issue {RSL} {To reshape and move a region, you generally have to manipulate both of the above. Maybe there should be a single function that takes either @@ -346,6 +361,55 @@ return the old value until the notification comes in from the display server that says that the mirror has been moved.} +\Defgeneric {move-sheet} {sheet x y} + +Moves the \term{sheet} \arg{sheet} to the new position $(x,y)$. \arg{x} and +\arg{y} are expressed in the coordinate system of \arg{sheet}'s parent. + +\cl{move-sheet} simply modifies \arg{sheet}'s transformation, and could be +implemented as follows: + +\begin{verbatim} +(defmethod move-sheet ((sheet basic-sheet) x y) + (let ((transform (sheet-transformation sheet))) + (multiple-value-bind (old-x old-y) + (transform-position transform 0 0) + (setf (sheet-transformation sheet) + (compose-translation-with-transformation + transform (- x old-x) (- y old-y)))))) +\end{verbatim} + +\Defgeneric {resize-sheet} {sheet width height} + +Resizes the \term{sheet} \arg{sheet} to have a new width \arg{width} and a new +height \arg{height}. \arg{width} and \arg{height} are real numbers. + +\cl{resize-sheet} simply modifies \arg{sheet}'s region, and could be implemented +as follows: + +\begin{verbatim} +(defmethod resize-sheet ((sheet basic-sheet) width height) + (setf (sheet-region sheet) + (make-bounding-rectangle 0 0 width height))) +\end{verbatim} + + +\Defgeneric {move-and-resize-sheet} {sheet x y width height} + +Moves the \term{sheet} \arg{sheet} to the new position $(x,y)$, and changes its +size to the new width \arg{width} and the new height \arg{height}. \arg{x} and +\arg{y} are expressed in the coordinate system of \arg{sheet}'s parent. +\arg{width} and \arg{height} are real numbers. + +\cl{move-and-resize-sheet} could be implemented as follows: + +\begin{verbatim} +(defmethod move-and-resize-sheet ((sheet basic-sheet) x y width height) + (move-sheet sheet x y) + (resize-sheet sheet width height)) +\end{verbatim} + + \Defgeneric {map-sheet-position-to-parent} {sheet x y} Applies the \term{sheet} \arg{sheet}'s transformation to the point $(x,y)$, @@ -379,6 +443,23 @@ bounding rectangle of the transformed region as four values, \arg{min-x}, \issue {SWM} {I now think that \cl{map-} in these names is misleading; maybe \cl{convert-} is better?} +\Defgeneric {map-over-sheets-containing-position} {function sheet x y} + +Applies the function \arg{function} to all of the children of the sheet +\arg{sheet} that contain the position $(x,y)$. \arg{x} and \arg{y} are +expressed in \arg{sheet}'s coordinate system. + +Function is a function of one argument, the sheet; it has dynamic extent. + +\Defgeneric {map-over-sheets-overlapping-region} {function sheet region} + +Applies the function \arg{function} to all of the children of the sheet +\arg{sheet} that overlap the region \arg{region}. \arg{region} is expressed in +\arg{sheet}'s coordinate system. + +Function is a function of one argument, the sheet; it has dynamic extent. + + \Defgeneric {child-containing-position} {sheet x y} Returns the topmost enabled direct child of the \term{sheet} \arg{sheet} whose @@ -396,9 +477,6 @@ whose corner points are $(x1,y1)$ and $(x2,y2)$. The region is expressed in \arg{sheet}'s coordinate system. \FreshOutputs -\issue {SWM} {The above three functions should really be \cl{map-over-...} -functions to both avoid consing and be consistent with that convention -throughout the rest of CLIM.} \Defgeneric {sheet-delta-transformation} {sheet ancestor} @@ -421,7 +499,8 @@ from \arg{child}'s actual region. \subsection {Sheet Geometry Classes} Each of the following implements the sheet geometry protocol in a different -manner, according to the sheet's requirements. +manner, according to the sheet's requirements. None of the four following +classes is instantiable. \Defclass {sheet-identity-transformation-mixin} @@ -442,7 +521,8 @@ translating by some amount in $x$ and $y$. \Defclass {sheet-transformation-mixin} This class is mixed into sheet classes whose coordinate system is related to -that of its parent by an arbitrary affine transformation. +that of its parent by an arbitrary affine transformation. CLIM implementations +are allowed to restrict these transformations to just rectilinear ones. \chapter {Sheet Protocols} @@ -493,9 +573,11 @@ In the functions below, the \arg{client} argument is typically a sheet, but it may be another object that supports event distribution, dispatching, and handling. -\issue {SWM} {Do we want to advertise \cl{sheet-event-queue}? It is analogous -to the input buffer for a stream. (In fact, sometimes the stream's input buffer -and the event queue for the shet are the exact same object.)} +\Defgeneric {sheet-event-queue} {sheet} + +Any sheet that can process events will have an event queue from which the events +are gotten. \cl{sheet-event-queue} returns the object that acts as the event +queue. The exact representation of an event queue is explicitly unspecified. \Defgeneric {process-next-event} {port \key wait-function timeout} @@ -557,7 +639,8 @@ that the pointer has entered its territory, there would be a method to carry out the policy that specializes the appropriate sheet and event classes. In addition to \cl{queue-event}, the queued input protocol handles the following -generic functions: +generic functions. The \arg{client} argument to these functions is typically a +sheet. \Defgeneric {event-read} {client} @@ -595,38 +678,45 @@ delegate all other events to some other input client. Such a sheet should have \cl{delegate-sheet-input-mixin} as a superclass, and have a more specific method for \cl{dispatch-event} on its class and \cl{pointer-button-click-event}. +None of the five following classes is instantiable. + \Defclass {standard-sheet-input-mixin} This class of sheet provides a method for \cl{dispatch-event} that calls \cl{queue-event} on each device event. Note that configuration events invoke \cl{handle-event} immediately. +The \cl{standard-sheet-input-mixin} class will also provide a +\cl{sheet-event-queue} method, describe above. + \Defclass {immediate-sheet-input-mixin} This class of sheet provides a method for \cl{dispatch-event} that calls \cl{handle-event} immediately for all events. -\Defclass {mute-sheet-input-mixin} +The \cl{immediate-sheet-input-mixin} class will also provide a +\cl{sheet-event-queue} method, describe above. + +\Defclass {sheet-mute-input-mixin} This is mixed in to any sheet class the does not handle any input events. \Defclass {delegate-sheet-input-mixin} This class of sheet provides a method for \cl{dispatch-event} that calls -\cl{dispatch-event} on a designated substitute and the event. The -initialization argument \cl{:delegate} or the accessor {delegate-sheet-delegate} -may be used to set the recipient of dispatched events. - -\issue {SWM} {What is a ``substitute'' and how do you ``designate'' it? Is the -substitute what \cl{delegate-sheet-delegate} returns? Does't this want an -initarg for the substitute?} +\cl{dispatch-event} on a designated substitute recipient and the event. The +initarg \cl{:delegate} or the accessor {delegate-sheet-delegate} may be used to +set the recipient of dispatched events. \defgeneric {delegate-sheet-delegate} {sheet} \Defgeneric {(setf delegate-sheet-delegate)} {delegate sheet} This may be set to another recipient of events dispatched to a sheet of class -\cl{delegate-sheet-input-mixin}. If the delegate is \cl{nil}, events are -discarded. +\cl{delegate-sheet-input-mixin}. \arg{delegate} is the object to which events +will be dispatched, and is usually another sheet. If the delegate is \cl{nil}, +events are discarded. + + \section {Standard Device Events} @@ -655,11 +745,14 @@ XX\=XX\=XX\=XX\=XX\=XX\= \kill \>\>\>\>\cl{pointer-button-release-event} \\ \>\>\>\>\cl{pointer-button-hold-event} \\ \>\>\>\cl{pointer-motion-event} \\ -\>\>\>\>\cl{pointer-enter-event} \\ -\>\>\>\>\cl{pointer-exit-event} \\ +\>\>\>\>\cl{pointer-boundary-event} \\ +\>\>\>\>\>\cl{pointer-enter-event} \\ +\>\>\>\>\>\cl{pointer-exit-event} \\ \>\cl{window-event} \\ \>\>\cl{window-configuration-event} \\ \>\>\cl{window-repaint-event} \\ +\>\cl{window-manager-event} \\ +\>\>\cl{window-manager-delete--event} \\ \>\cl{timer-event} \\ \end{tabbing} \caption{\label{event-hier} CLIM event classes. All classes that appear @@ -674,9 +767,12 @@ lesser indentation.} The protocol class that corresponds to any sort of ``event''. \IfYouWantClass {an} {event} {event} -All of the event classes are immutable. +All of the event classes are immutable. CLIM implementations may choose to keep +a resource of the device event classes, but this must be invisible at the API +level. That is, any event visible at the level of the API must act as though it +is immutable. -\Defun {eventp} {object} +\Defpredicate {eventp} {object} Returns \term{true} if \arg{object} is an \term{event}, otherwise returns \term{false}. @@ -707,8 +803,8 @@ All event classes must implement methods for \cl{event-type} and \definitarg {:sheet} \Definitarg {:modifier-state} -The class that corresponds to any sort of device event. This is a subclass of -\cl{event}. +The instantiable class that corresponds to any sort of device event. This is a +subclass of \cl{event}. All subclasses of \cl{device-event} must take the \cl{:sheet} and \cl{:modifier-state} initargs, which are used to specify the sheet and modifier @@ -720,9 +816,10 @@ Returns the sheet associated with the event \arg{device-event}. \Defgeneric {event-modifier-state} {device-event} -Returns a value that encodes the state of all the modifier keys on the keyboard. -This will be a mask consisting of the \cl{logior} of \cl{+shift-key+}, -\cl{+control-key+}, \cl{+meta-key+}, \cl{+super-key+}, and \cl{+hyper-key+}. +Returns an integer value that encodes the state of all the modifier keys on the +keyboard. This will be a mask consisting of the \cl{logior} of +\cl{+shift-key+}, \cl{+control-key+}, \cl{+meta-key+}, \cl{+super-key+}, and +\cl{+hyper-key+}. All device event classes must implement methods for \cl{event-sheet} and \cl{event-modifier-state}. @@ -731,8 +828,8 @@ All device event classes must implement methods for \cl{event-sheet} and \defclass {keyboard-event} \Definitarg {:key-name} -The class that corresponds to any sort of keyboard event. This is a subclass of -\cl{device-event}. +The instantiable class that corresponds to any sort of keyboard event. This is +a subclass of \cl{device-event}. All subclasses of \cl{keyboard-event} must take the \cl{:key-name} initarg, which is used to specify the key name component for the event. @@ -755,8 +852,8 @@ All keyboard event classes must implement methods for \defclass {key-press-event} \Defclass {key-release-event} -The classes that correspond to a key press or release event. This is a subclass -of \cl{keyboard-event}. +The instantiable classes that correspond to a key press or release event. This +is a subclass of \cl{keyboard-event}. \defclass {pointer-event} @@ -765,8 +862,8 @@ of \cl{keyboard-event}. \definitarg {:x} \Definitarg {:y} -The class that corresponds to any sort of pointer event. This is a subclass of -\cl{device-event}. +The instantiable class that corresponds to any sort of pointer event. This is a +subclass of \cl{device-event}. All subclasses of \cl{pointer-event} must take the \cl{:pointer}, \cl{:button}, \cl{:x}, and \cl{:y} initargs, which are used to specify the pointer object, @@ -792,54 +889,67 @@ method for these generic functions. Returns the pointer object to which this event refers. -\Defgeneric {pointer-event-button} {pointer-event} - -Returns the number of the pointer button that was pressed, which will be -one of \cl{+pointer-left-button+}, \cl{+pointer-middle-button+}, or -\cl{+pointer-right-button+}. - All pointer event classes must implement methods for \cl{pointer-event-x}, \cl{pointer-event-y}, \cl{pointer-event-native-x}, \cl{pointer-event-native-y}, -\cl{pointer-event-pointer}, and \cl{pointer-event-button}. +and \cl{pointer-event-pointer}. \Defclass {pointer-button-event} -The class that corresponds to any sort of pointer button event. This is a -subclass of \cl{pointer-event}. +The instantiable class that corresponds to any sort of pointer button event. +This is a subclass of \cl{pointer-event}. + +\Defgeneric {pointer-event-button} {pointer-button-event} + +Returns the an integer corresponding to the pointer button that was pressed or +released, which will be one of \cl{+pointer-left-button+}, +\cl{+pointer-middle-button+}, or \cl{+pointer-right-button+}. \defclass {pointer-button-press-event} \defclass {pointer-button-release-event} \Defclass {pointer-button-hold-event} -The classes that correspond to a pointer button press, button release, and -click-and-hold events. These are subclasses of \cl{pointer-button-event}. +The instantiable classes that correspond to a pointer button press, button +release, and click-and-hold events. These are subclasses of +\cl{pointer-button-event}. -\defclass {pointer-button-click-event} -\defclass {pointer-button-double-click-event} -\Defclass {pointer-button-click-and-hold-event} +\defclass {pointer-click-event} +\defclass {pointer-double-click-event} +\Defclass {pointer-click-and-hold-event} -The classes that correspond to a pointer button press, followed immediately by -(respectively) a button release, another button press, or pointer motion. These -are subclasses of \cl{pointer-button-event}. Ports are not required to generate -these events. +The instantiable classes that correspond to a pointer button press, followed +immediately by (respectively) a button release, another button press, or pointer +motion. These are subclasses of \cl{pointer-button-event}. Ports are not +required to generate these events. \Defclass {pointer-motion-event} -The class that corresponds to any sort of pointer motion event. This is a -subclass of \cl{pointer-event}. +The instantiable class that corresponds to any sort of pointer motion event. +This is a subclass of \cl{pointer-event}. + +\Defclass {pointer-boundary-event} + +The instantiable class that corresponds to a pointer motion event that crosses +some sort of sheet boundary. This is a subclass of \cl{pointer-motion-event}. + +\Defgeneric {pointer-boundary-event-kind} {pointer-boundary-event} + +Returns the ``kind'' of boundary event, which will be one of \cl{:ancestor}, +\cl{:virtual}, \cl{:inferior}, \cl{:nonlinear}, \cl{:nonlinear-virtual}, or +\cl{nil}. These event kinds correspond to the detail members for X11 enter and +exit events. \defclass {pointer-enter-event} \Defclass {pointer-exit-event} -The classes that correspond to a pointer enter or exit event. This is a -subclass of \cl{pointer-motion-event}. +The instantiable classes that correspond to a pointer enter or exit event. +These are subclasses of \cl{pointer-boundary-event}. \defclass {window-event} \Definitarg {:region} -The class that corresponds to any sort of windowing event. This is a subclass -of \cl{device-event}. +The instantiable class that corresponds to any sort of windowing event. This is +a subclass of \cl{event}. All subclasses of \cl{window-event} must take a \cl{:region} initarg, which is used to specify the damage region associated with the event. @@ -862,19 +972,34 @@ All window event classes must implement methods for \cl{window-event-region}, \Defclass {window-configuration-event} -The class that corresponds to a window changing its size or position. This is -a subclass of \cl{window-event}. +The instantiable class that corresponds to a window changing its size or +position. This is a subclass of \cl{window-event}. \Defclass {window-repaint-event} -The class that corresponds to a request to repaint the window. This is a -subclass of \cl{window-event}. +The instantiable class that corresponds to a request to repaint the window. +This is a subclass of \cl{window-event}. + + +\defclass {window-manager-event} +\Definitarg {:sheet} + +The instantiable class that corresponds to any sort of window manager event. +This is a subclass of \cl{event}. + +All subclasses of \cl{window-manager-event} must take a \cl{:sheet} initarg, +which is used to specify the sheet on which the window manager acted. + +\Defclass {window-manager-delete-event} + +The instantiable class that corresponds to window manager event that causes a +host window to be deleted. This is a subclass of \cl{window-manager-event}. \Defclass {timer-event} -The class that corresponds to a timeout event. This is a subclass of -\cl{event}. +The instantiable class that corresponds to a timeout event. This is a subclass +of \cl{event}. \defconst {+pointer-left-button+} @@ -884,6 +1009,9 @@ The class that corresponds to a timeout event. This is a subclass of Constants that correspond to the left, middle, and right button on a pointing device. \cl{pointer-event-button} will returns one of these three values. +These constants are powers of 2 so that they can be combined with \cl{logior} +and tested with \cl{logtest}. + \defconst {+shift-key+} \defconst {+control-key+} \defconst {+meta-key+} @@ -891,37 +1019,16 @@ device. \cl{pointer-event-button} will returns one of these three values. \Defconst {+hyper-key+} Constants that correspond to the shift, control, meta, super, and hyper modifier -keys being held down on the keyboard. These constants must be powers of 2 so -that they can be combined with \cl{logior} and tested with \cl{logtest}. +keys being held down on the keyboard. These constants are powers of 2 that are +disjoint from the pointer button constants, so that they can be combined with +\cl{logior} and tested with \cl{logtest}. + \cl{event-modifier-state} will return some combination of these values. Implementations must support at least shift, control, and meta modifiers. Control and meta might correspond to the control and option or command shift keys on a Macintosh keyboard, for example. -\Defmacro {key-modifier-state-match-p} {button modifier-state \body clauses} - -This macro generates code that will check whether the modifier state -\arg{modifier-state} and the pointer button \arg{button} match all of the -clauses. \arg{clauses} are implicitly grouped by \cl{and}. Matching a button -or a modifier means that that the modifier state indicates that the button or -modifier is pressed. - -A clause may be one of: - -\begin{itemize} -\item A pointer button. One of \cl{:left}, \cl{:middle} or \cl{:right}. - -\item A modifier key. One of \cl{:shift}, \cl{:control}, \cl{:meta}, -\cl{:super} or \cl{:hyper}. - -\item \cl{(and [\arg{clause}]+)} - -\item \cl{(or [\arg{clause}]+)} - -\item \cl{(not \arg{clause})} -\end{itemize} - \section {Output Protocol} @@ -952,11 +1059,17 @@ The protocol class that corresponds to the output state for some kind of sheet. There is no single advertised standard medium class. \IfYouWantClass {a} {medium} {medium} -\Defun {mediump} {object} +\Defpredicate {mediump} {object} Returns \term{true} if \arg{object} is a \term{medium}, otherwise returns \term{false}. +\Defclass {basic-medium} + +The basic class on which all CLIM mediums are built, a subclass of \cl{medium}. +\AbstractClass + + The following generic functions comprise the basic medium protocol. All mediums must implement methods for these generic functions. Often, a sheet class that supports the output protocol will implement a ``trampoline'' method that passes @@ -1076,25 +1189,33 @@ Section~\ref{graphics-protocols}. \subsection {Output Protocol Classes} -The following classes implement the standard output protocols. +The following classes implement the standard output protocols. None of the five +following classes is instantiable. \Defclass {standard-sheet-output-mixin} This class is mixed in to any sheet that provides the standard output protocol, such as repainting and graphics. -\Defclass {mute-sheet-output-mixin} +\Defclass {sheet-mute-output-mixin} This class is mixed in to any sheet that provides none of the output protocol. +\Defclass {sheet-with-medium-mixin} + +This class is used for any sheet that has either a permanent or a temporary +medium. + \Defclass {permanent-medium-sheet-output-mixin} This class is mixed in to any sheet that always has a medium associated with it. +It is a subclass of \cl{sheet-with-medium-mixin}. \Defclass {temporary-medium-sheet-output-mixin} This class is mixed in to any sheet that may have a medium associated with it, -but does not necessarily have a medium at any given instant. +but does not necessarily have a medium at any given instant. It is a subclass +of \cl{sheet-with-medium-mixin}. \subsection {Associating a Medium with a Sheet} @@ -1112,14 +1233,21 @@ purpose of displaying a border for another sheet, the border sheet receives output only when the window's shape is changed. To associate a sheet with a medium, the macro \cl{with-sheet-medium} is used. +Only sheets that are subclasses of \cl{sheet-with-medium-mixin} may have a +medium associated with them. + \Defmacro {with-sheet-medium} {(medium sheet) \body body} Within the body, the variable \arg{medium} is bound to the sheet's medium. If -the sheet does not have a medium permanently allocated, one will be allocated, -associated with the sheet for the duration of the body, and deallocated as the -when the body has been exited. The values of the last form of the body are -returned as the values of \cl{with-sheet-medium}. +the sheet does not have a medium permanently allocated, one will be allocated +and associated with the sheet for the duration of the body (by calling +\cl{engraft-medium}), and then degrafted from the sheet and deallocated when the +body has been exited. The values of the last form of the body are returned as +the values of \cl{with-sheet-medium}. + +This macro will signal a runtime error if sheet is not a subclass of +\cl{sheet-with-medium-mixin}. The \arg{medium} argument is not evaluated, and must be a symbol that is bound to a medium. \arg{body} may have zero or more declarations as its first forms. @@ -1132,10 +1260,13 @@ Typically, a single medium will be allocated an passed to several different sheets that can use the same medium. If the sheet already has a medium allocated to it, the new medium will not be -given to the sheet. If the value of \arg{medium} is \cl{nil}, -\cl{with-sheet-medium-bound} is exactly equivalent to \cl{with-sheet-medium}. -The values of the last form of the body are returned as the values of -\cl{with-sheet-medium-bound}. +grafted to the sheet, and \cl{with-sheet-medium-bound} will simple evaluate the +body. If the value of \arg{medium} is \cl{nil}, \cl{with-sheet-medium-bound} is +exactly equivalent to \cl{with-sheet-medium}. The values of the last form of +the body are returned as the values of \cl{with-sheet-medium-bound}. + +This macro will signal a runtime error if sheet is not a subclass of +\cl{sheet-with-medium-mixin}. \arg{body} may have zero or more declarations as its first forms. @@ -1144,6 +1275,73 @@ The values of the last form of the body are returned as the values of Returns the medium associated with the \term{sheet} \arg{sheet}. If \arg{sheet} does not have a medium allocated to it, \cl{sheet-medium} returns \cl{nil}. +This function will signal an error if sheet is not a subclass of +\cl{sheet-with-medium-mixin}. + +\Defgeneric {medium-sheet} {medium} + +Returns the sheet associated with the \term{medium} \arg{medium}. If +\arg{medium} is not grafted to a sheet, \cl{medium-sheet} returns \cl{nil}. + +\Defgeneric {medium-drawable} {medium} + +Returns an implementation-dependent object that corresponds to the actual host +window that will be drawn on when the \term{medium} \arg{medium} is drawn on. +If \arg{medium} is not grafted to a sheet or the medium's sheet is not currently +mirrored on a display server, \cl{medium-drawable} returns \cl{nil}. + +Programmers can use this function to get a host window system object that can be +manipulated using the functions of the host window system. This might be done +in order to explicitly trade of performance against portability. + +\Defmethod {port} {(medium \cl{basic-medium})} + +If \arg{medium} is both grafted to a sheet and the sheet is currently mirrored +on a display server, this returns the port with which \arg{medium} is +associated. Otherwise it returns \cl{nil}. + +\subsubsection {Grafting and Degrafting of Mediums} + +The following generic functions are the protocol-level functions responsible for +the allocating, deallocating, grafting, and degrafting of mediums. They are not +intended for general use by programmers. + +\Defgeneric {allocate-medium} {port sheet} + +Allocates a medium from the \term{port} \arg{port}'s medium resource, or calls +\cl{make-medium} on the port to create a new medium if the resource is empty or +the port does not maintain a resource of mediums. The resulting medium will +have its default characteristics determined by \arg{sheet}. + +\Defgeneric {deallocate-medium} {port medium} + +Returns the \term{medium} \arg{medium} to \arg{port}'s medium resource. + +\Defgeneric {make-medium} {port sheet} + +Creates a new medium for the \term{port} \arg{port}. The new medium will have +its default characteristics determined by \arg{sheet}. + +\Defgeneric {engraft-medium} {medium port sheet} + +Grafts the \term{medium} \arg{medium} to the \term{sheet} \arg{sheet} on the +\term{port} \arg{port}. + +The default method on \cl{basic-medium} will set \cl{medium-sheet} on +\arg{medium} to point to the sheet, and will set up the medium state (foreground +ink, background ink, and so forth) from the defaults gotten from {sheet}. Each +implementation may specialize this generic function in order to set up such +things as per-medium ink caches, and so forth. + +\Defgeneric {degraft-medium} {medium port sheet} + +Degrafts the \term{medium} \arg{medium} from the \term{sheet} \arg{sheet} on the +\term{port} \arg{port}. + +The default method on \cl{basic-medium} will set \cl{medium-sheet} back to +\cl{nil}. Each implementation may specialize this generic function in order to +clear any caches it has set up, and so forth. + \section {Repaint Protocol} @@ -1159,42 +1357,32 @@ cause a repaint to be executed for the newly-exposed region. \subsection {Repaint Protocol Functions} -\Defgeneric {dispatch-repaint} {sheet region} +\Defgeneric {queue-repaint} {sheet repaint-event} -Requests a repaint of the \term{region} \arg{region} within the \term{sheet} -\arg{sheet}. The region is given in sheet coordinates. Depending on the class -of the sheet, this may cause \cl{queue-repaint} or \cl{handle-repaint} to be -invoked. - -All CLIM implementations must support repainting for regions that are rectangles -or region sets composed entirely of rectangles. +Requests that the repaint event \arg{repaint-event} be placed in the input queue +of the \term{sheet} \arg{sheet}. A program that reads events out of the queue +will be expected to call \cl{handle-event} for the sheet using the repaint +region gotten from \arg{repaint-event}. -\Defgeneric {queue-repaint} {sheet region} +\Defgeneric {handle-repaint} {sheet region} -Requests that a repaint event for the \term{region} \arg{region} be placed in -the input queue of the \term{sheet} \arg{sheet}. A program that reads events -out of the queue will be expected to call \cl{handle-event} for the repaint -region; the method for that generic function on repaint events will generally -call \cl{repaint-sheet}. +Implements repainting for a given sheet class. \term{sheet} is the sheet to +repaint and \arg{region} is the region to repaint. -\Defgeneric {handle-repaint} {sheet medium region} +\Defgeneric {repaint-sheet} {sheet region} Recursively causes repainting of the \term{sheet} \arg{sheet} and any of its -children that overlap the \term{region} \arg{region}. \arg{medium} is the -medium to use for the repainting; if it is \cl{nil}, \cl{handle-repaint} will -allocate a medium and associate it with the sheet. \cl{handle-repaint} will -call \cl{repaint-sheet} on \arg{sheet}, and then call \cl{handle-repaint} on all -of the children of \arg{sheet}. - -\Defgeneric {repaint-sheet} {sheet region} +descendants that overlap the \term{region} \arg{region}. -Implements repainting for a given sheet class. It may only be called on a sheet -that has an associated medium. \term{sheet} and \arg{region} are as for -\cl{dispatch-repaint}. +All CLIM implementations must support repainting for regions that are rectangles +or region sets composed entirely of rectangles. \subsection {Repaint Protocol Classes} +The following classes implement the standard repaint protocols. None of the +three following classes is instantiable. + \Defclass {standard-repainting-mixin} Defines a \cl{dispatch-repaint} method that calls \cl{queue-repaint}. @@ -1203,7 +1391,7 @@ Defines a \cl{dispatch-repaint} method that calls \cl{queue-repaint}. Defines a \cl{dispatch-repaint} method that calls \cl{handle-repaint}. -\Defclass {mute-repainting-mixin} +\Defclass {sheet-mute-repainting-mixin} Defines a \cl{dispatch-repaint} method that calls \cl{queue-repaint}, and a method on \cl{repaint-sheet} that does nothing. This means that its children @@ -1264,17 +1452,50 @@ first element is a keyword that selects the kind of port. The remainder of the server path is a list of alternating keywords and values whose interpretation is port type-specific. -\Defun {find-port} {\key (server-path \cl{*default-server-path*})} +\Defprotoclass {port} + +The protocol class that corresponds to a port. +\IfYouWantClass {a} {port} {port} + +All of the subclasses of \cl{port} are mutable. + +\Defpredicate {portp} {object} + +Returns \term{true} if \arg{object} is a \term{port}, otherwise returns +\term{false}. + +\Defclass {basic-port} + +The basic class on which all CLIM ports are built, a subclass of \cl{port}. +\AbstractClass + + +\Defun {find-port} {\rest initargs \key (server-path \cl{*default-server-path*}) \allow} Finds a port that provides a connection to the window server addressed by \arg{server-path}. If no such connection exists, a new connection will be -constructed and returned. +constructed and returned. The initargs in \arg{initargs} will be passed to the +function that constructed the new port. -The following server paths are currently supported: +\Defvar {*default-server-path*} + +This special variable is used by \cl{find-port} and its callers to default the +choice of a display service to locate. Binding this variable in a dynamic +context will affect the defaulting of this argument to these functions. This +variable will be defaulted according to the environment. In the Unix +environment, for example, CLIM will attempt to set this variable based on the +value of the \cl{DISPLAY} environment variable. + +The value of \cl{*default-server-path*} is a cons of a port type followed by a +list of initargs. + +The following are the recommendations for port types and their initargs. This +list is not intended to be comprehensive, nor is it required that a CLIM +implementation support any of these port types. \def\Defdp #1 #2 {\Dodocf {#1} {#2} {Server~Path}} -\Defdp {:x11} {\key host display-id screen-id} +\Defdp {:clx} {\key host display-id screen-id} Given this server path, \cl{find-port} finds a port for the X server on the given \arg{host}, using the \arg{display-id} and \arg{screen-id}. @@ -1283,20 +1504,28 @@ On a Unix host, if these values are not supplied, the defaults come from the \cl{DISPLAY} environment variable. Each CLIM implementation must describe how it uses such environment variables. -\Defdp {:genera} {\key screen} +\Defdp {:motif} {\key host display-id screen-id} + +Given this server path, \cl{find-port} finds a port for a Motif X server on the +given \arg{host}, using the \arg{display-id} and \arg{screen-id}. -\issue {SWM} {RSL claims that this is old and obsolete. What is the proposed -replacement for it?} +On a Unix host, if these values are not supplied, the defaults come from the +\cl{DISPLAY} environment variable. +\Defdp {:openlook} {\key host display-id screen-id} -\Defvar {*default-server-path*} +Given this server path, \cl{find-port} finds a port for an OpenLook X server on +the given \arg{host}, using the \arg{display-id} and \arg{screen-id}. + +On a Unix host, if these values are not supplied, the defaults come from the +\cl{DISPLAY} environment variable. + +\Defdp {:genera} {\key screen} + +Given this server path, \cl{find-port} finds a port for local Genera platform on +the screen object \arg{screen}. \arg{screen} defaults to \arg{tv:main-screen}, +but could also be an object return from \cl{color:find-color-screen}. -This special variable is used by \cl{find-port} and its callers to default the -choice of a display service to locate. Binding this variable in a dynamic -context will affect the defaulting of this argument to these functions. This -variable will be defaulted according to the environment. In the Unix -environment, for example, CLIM will attempt to set this variable based on the -value of the \cl{DISPLAY} environment variable. \Defgeneric {port} {object} @@ -1306,7 +1535,7 @@ protocol), mediums, and application frames. For degrafted sheets or other objects that aren't currently associated with particular ports, \cl{port} will return \cl{nil}. -\Defmacro {with-port-locked} {port \body body} +\Defmacro {with-port-locked} {(port) \body body} Executes \arg{body} after grabbing a lock associated with the \term{port} \arg{port}, which may be a port or any object on which the function \cl{port} @@ -1316,10 +1545,26 @@ without locking. \arg{body} may have zero or more declarations as its first forms. +\Defun {map-over-ports} {function} + +Invokes \arg{function} on each existing port. Function is a function of one +argument, the port; it has dynamic extent. + \Defgeneric {port-server-path} {port} Returns the server path associated with the \term{port} \arg{port}. +\Defgeneric {port-name} {port} + +Returns an implementation-dependent string that is the name of the port. For +example, a \cl{:clx} port might have a name of \cl{"summer:0.0"}. + +\Defgeneric {port-type} {port} + +Returns the type of the port, that is, the first element of the server path +spec. + + \defgeneric {port-properties} {port indicator} \Defgeneric {(setf port-properties)} {property port indicator} @@ -1328,11 +1573,6 @@ to support users of CLIM that may need to associate certain information with ports. For example, the implementor of a special graphics package may need to maintain resource tables for each port on which it is used. -\Defun {map-over-ports} {function} - -Invokes \arg{function} on each existing port. Function is a function of one -argument, the port; it has dynamic extent. - \Defgeneric {restart-port} {port} In a multi-process Lisp, \cl{restart-port} restarts the global input processing @@ -1349,19 +1589,6 @@ forcibly degrafted by disowning the children of grafts on \arg{port} using by any graphics objects on \arg{port} are released as part of the connection shutdown. -\defgeneric {add-watcher} {port watcher} -\defgeneric {delete-watcher} {port watcher} -\Defgeneric {reset-watcher} {watcher how} - -Watchers are a mechanism for clients to be notified when the port is destroyed -or restarted. \cl{add-watcher} and \cl{delete-watcher} provide an interface for -adding and removing \arg{watcher} to the list of watchers that the \term{port} -\arg{port} maintains. \cl{destroy-port} and \cl{restart-port} invoke -\cl{reset-watcher} on each of these watchers with \cl{:destroy} and -\cl{:restart} being passed in as \arg{how}, respectively. - -\issue {SWM} {What exactly is a watcher? The above is not specific enough.} - \section {Grafts} @@ -1381,8 +1608,9 @@ Returns \term{true} if any of the sheet's ancestors is a graft, otherwise returns \term{false}. -\Defun {find-graft} {\key (port \cl{(find-port)}) (server-path \cl{*default-server-path*}) - (orientation \cl{:default}) (units \cl{:device})} +\Defun {find-graft} {\key (server-path \cl{*default-server-path*}) + (port \cl{(find-port :server-path server-path)}) + (orientation \cl{:default}) (units \cl{:device})} Finds a graft that represents the display device on the port \arg{port} that also matches the other supplied parameters. If no such graft exists, a new @@ -1430,7 +1658,7 @@ Invokes \arg{function} on each existing graft associated with the \term{port} \arg{port}. \arg{function} is a function of one argument, the graft; it has dynamic extent. -\Defmacro {with-graft-locked} {graft \body body} +\Defmacro {with-graft-locked} {(graft) \body body} Executes \arg{body} after grabbing a lock associated with the \term{graft} \arg{graft}, which may be a graft or any object on which the function @@ -1506,6 +1734,10 @@ In both of these cases, we must have a coordinate transformation that converts coordinates in the mirror (so-called ``native'' coordinates) into coordinates in the sheet and vice-versa. +\Defclass {mirrored-sheet-mixin} + +This class is mixed in to sheet classes that can be directly mirrored. + \subsection {Mirror Functions} @@ -1514,9 +1746,10 @@ the handle to the actual toolkit window or gadget?} \Defgeneric {sheet-direct-mirror} {sheet} -Returns the mirror of the \term{sheet} \arg{sheet}. If the sheet is not -mirrored (or does not currently have a mirror), \cl{sheet-mirror} returns -\cl{nil}. +Returns the mirror of the \term{sheet} \arg{sheet}. If the sheet is not a +subclass of \cl{mirrored-sheet-mixin}, this will return \cl{nil}. If the sheet +is a subclass of \cl{mirrored-sheet-mixin} and does not currently have a mirror, +\cl{sheet-mirror} will return \cl{nil}. \Defgeneric {sheet-mirrored-ancestor} {sheet} @@ -1537,7 +1770,29 @@ ancestor. \cl{sheet-mirror} could be implemented as: Creates a mirror for the \term{sheet} \arg{mirrored-sheet} on the \term{port} \arg{port}, if it does not already have one. The returned value is the sheet's -mirror. +mirror; the type of this object is implementation dependent. + +\Defgeneric {destroy-mirror} {port mirrored-sheet} + +Destroys the mirror for the \term{sheet} \arg{mirrored-sheet} on the \term{port} +\arg{port}. + +\Defgeneric {raise-mirror} {port sheet} + +Raises the \term{sheet} \arg{sheet}'s mirror to the top of all of the host +windows on the \term{port} \arg{port}. \arg{sheet} need not be a directly +mirrored sheet. + +\Defgeneric {bury-mirror} {port sheet} + +Buries the \term{sheet} \arg{sheet}'s mirror at the bottom of all of the host +windows on the \term{port} \arg{port}. \arg{sheet} need not be a directly +mirrored sheet. + +\Defmethod {port} {(sheet \cl{basic-sheet})} + +If \arg{sheet} is currently mirrored on a display server, this returns the port +with which \arg{sheet} is associated. Otherwise it returns \cl{nil}. \subsection {Internal Interfaces for Native Coordinates} diff --git a/specs/spec-macros.tex b/specs/spec-macros.tex index 57173a38..917b17be 100644 --- a/specs/spec-macros.tex +++ b/specs/spec-macros.tex @@ -96,8 +96,9 @@ \def\Defvar #1 {\Dodocv {#1} {Variable}} \def\Defconst #1 {\Dodocv {#1} {Constant}} \def\Defprotoclass #1 {\Dodocv {#1} {Protocol~Class}} +\def\Defpredicate #1 #2 {\Dodocf {#1} {#2} {Protocol~Predicate}} \def\Defclass #1 {\Dodocv {#1} {Class}} -\def\Definitarg #1 {\Dodocv {#1} {Init~Arg}} +\def\Definitarg #1 {\Dodocv {#1} {Initarg}} \def\Deftype #1 {\Dodocv {#1} {Type}} \def\Defoption #1 {\Dodocv {#1} {Option}} \def\Defptype #1 #2 {\Dodocf {#1} {#2} {Presentation~Type}} @@ -121,8 +122,9 @@ \def\defvar #1 {\dodocv {#1} {Variable}} \def\defconst #1 {\dodocv {#1} {Constant}} \def\defprotoclass #1 {\dodocv {#1} {Protocol~Class}} +\def\defpredicate #1 #2 {\dodocf {#1} {#2} {Protocol~Predicate}} \def\defclass #1 {\dodocv {#1} {Class}} -\def\definitarg #1 {\dodocv {#1} {Init~Arg}} +\def\definitarg #1 {\dodocv {#1} {Initarg}} \def\defoption #1 {\dodocv {#1} {Option}} \def\Defcommandtable #1 {\Dodocv {#1} {Command~Table}} @@ -144,8 +146,11 @@ %% \def\IfYouWantClass #1 #2 #3 {If you want to create a new class that behaves -like #1 #2, it should be a subclass of \cl{#3}. Subclasses of \cl{#3} must obey -the #2 protocol.\ } +like #1 #2, it should be a subclass of \cl{#3}. All instantiable subclasses of +\cl{#3} must obey the #2 protocol.\ } + +\def\AbstractClass{This class is an abstract class, intended only to be +subclassed, not instantiated.\ } \def\Mutable{Members of this class are mutable.\ } diff --git a/specs/table-formatting.tex b/specs/table-formatting.tex index 120dd566..4f1cf001 100644 --- a/specs/table-formatting.tex +++ b/specs/table-formatting.tex @@ -118,7 +118,7 @@ direction, and how to constrain them in the vertical direction. \key x-spacing y-spacing multiple-columns multiple-columns-x-spacing equalize-column-widths - (move-cursor \cl{t}) record-type) + (move-cursor \cl{t}) record-type \allow) \body body} Binds the local environment in such a way the output of \arg{body} will be done @@ -175,7 +175,7 @@ a programmer if there is a new class of output record that supports the table formatting protocol. -\Defmacro {formatting-row} {(\optional stream \key record-type) +\Defmacro {formatting-row} {(\optional stream \key record-type \allow) \body body} Binds the local environment in such a way the output of \arg{body} will be @@ -197,7 +197,7 @@ programmer if there is a new class of output record that supports the row formatting protocol. -\Defmacro {formatting-column} {(\optional stream \key record-type) +\Defmacro {formatting-column} {(\optional stream \key record-type \allow) \body body} Binds the local environment in such a way the output of \arg{body} will be @@ -221,7 +221,7 @@ column formatting protocol. \Defmacro {formatting-cell} {(\optional stream \key (align-x \cl{':left}) (align-y \cl{':baseline}) - min-width min-height record-type) + min-width min-height record-type \allow) \body body} Controls the output of a single cell inside a table row or column, or of a @@ -262,8 +262,8 @@ formatting protocol. \key x-spacing y-spacing n-columns n-rows stream-width stream-height max-width max-height - initial-spacing - (move-cursor \cl{t}) record-type) + initial-spacing (row-wise \cl{t}) + (move-cursor \cl{t}) record-type \allow) \body body} Binds the local environment in such a way that the output of \arg{body} will be @@ -281,6 +281,12 @@ specified \arg{y-spacing}). Multiple rows and columns are constructed after laying the item list out in a single column. Item list output takes place in a normalized +$y$-downward coordinate system. +If \arg{row-wise} is \term{true} (the default) and the item list requires +multiple columns, each successive element in the item list is layed out from +left to right. If \arg{row-wise} is \term{false} and the item list requires +multiple columns, each successive element in the item list is layed out below +its predecessor, like in a telephone book. + The returned value is the output record corresponding to the table. \arg{stream} is an output recording stream to which output will be done. The @@ -328,7 +334,7 @@ the item list formatting protocol. n-columns n-rows max-width max-height cell-align-x cell-align-y - initial-spacing + initial-spacing (row-wise \cl{t}) (move-cursor \cl{t}) record-type} This is a function interface to the item list formatter. The elements of the @@ -351,8 +357,8 @@ When \arg{printer} is supplied, each item will be enclosed in a presentation whose type is \arg{presentation-type}. \arg{x-spacing}, \arg{y-spacing}, \arg{n-columns}, \arg{n-rows}, -\arg{max-width}, \arg{max-height}, \arg{initial-spacing}, and \arg{move-cursor} -are as for \cl{formatting-item-list}. +\arg{max-width}, \arg{max-height}, \arg{initial-spacing}, \arg{row-wise}, and +\arg{move-cursor} are as for \cl{formatting-item-list}. \arg{cell-align-x} and \arg{cell-align-y} are used to supply \cl{:align-x} and \cl{:align-y} to an implicitly used \cl{formatting-cell}. @@ -402,7 +408,7 @@ The protocol class that represents tabular output records; a subclass of \cl{output-record}. \IfYouWantClass {a} {table output record} {table-output-record} -\Defun {table-output-record-p} {object} +\Defpredicate {table-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{table output record}, otherwise returns \term{false}. @@ -458,7 +464,7 @@ The protocol class that represents one row in a table; a subclass of \cl{output-record}. \IfYouWantClass {a} {row output record} {row-output-record} -\Defun {row-output-record-p} {object} +\Defpredicate {row-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{row output record}, otherwise returns \term{false}. @@ -484,7 +490,7 @@ The protocol class that represents one column in a table; a subclass of \cl{output-record}. \IfYouWantClass {a} {column output record} {column-output-record} -\Defun {column-output-record-p} {object} +\Defpredicate {column-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{column output record}, otherwise returns \term{false}. @@ -516,7 +522,7 @@ The protocol class that represents one cell in a table or an item list; a subclass of \cl{output-record}. \IfYouWantClass {a} {cell output record} {cell-output-record} -\Defun {cell-output-record-p} {object} +\Defpredicate {cell-output-record-p} {object} Returns \term{true} if \arg{object} is a \term{cell output record}, otherwise returns \term{false}. @@ -554,7 +560,7 @@ The protocol class that represents an item list; a subclass of \cl{output-record}. \IfYouWantClass {an} {item list output record} {item-list-output-record} -\Defun {item-list-output-record-p} {object} +\Defpredicate {item-list-output-record-p} {object} Returns \term{true} if \arg{object} is an \term{item list output record}, otherwise returns \term{false}. @@ -562,6 +568,7 @@ otherwise returns \term{false}. \definitarg {:x-spacing} \definitarg {:y-spacing} \definitarg {:initial-spacing} +\definitarg {:row-wise} \definitarg {:n-rows} \definitarg {:n-columns} \definitarg {:max-width} @@ -569,14 +576,14 @@ otherwise returns \term{false}. All subclasses of \cl{item-list-output-record} must handle these initargs, which are used to specify, respectively, the $x$ and $y$ spacing, the initial spacing, -the desired number of rows and columns, and maximum width and height attributes -of the item list. +row-wise, the desired number of rows and columns, and maximum width and height +attributes of the item list. \Defclass {standard-item-list-output-record} -The output record that represents item list output. Its children will be a -sequence of cells, with presentations possibly intervening. This is a subclass -of \cl{item-list-output-record}. +The instantiable output record that represents item list output. Its children +will be a sequence of cells, with presentations possibly intervening. This is a +subclass of \cl{item-list-output-record}. \Defgeneric {map-over-item-list-cells} {function item-list-record} diff --git a/specs/text-formatting.tex b/specs/text-formatting.tex index 4d56fa1c..dabc5355 100644 --- a/specs/text-formatting.tex +++ b/specs/text-formatting.tex @@ -51,12 +51,15 @@ If the boolean \arg{move-cursor} is \term{true} (the default), CLIM moves the cursor to the end of the table. Programmers using \cl{indenting-output} should begin the body with a call to -\arg{fresh-line} (or some equivalent) to position the stream to the indentation -initially. There is a restriction on interactions between \cl{indenting-output} -and \cl{filling-output} such that a call to \cl{indenting-output} should appear -outside of a call to \cl{filling-output}. Implementations are permitted to -relax this restriction, but uses of \cl{indenting-output} inside of -\cl{filling-output} may not be portable. +\arg{fresh-line} (or some equivalent) to position the stream to the initial +indentation. + +{\bf Implementation note:} Some CLIM implementations restrict the use of +\cl{indenting-output} and \cl{filling-output} such that a call to +\cl{indenting-output} should appear outside of a call to \cl{filling-output}. +Implementations are encouraged to relax this restriction if the behavior is +well-defined, but uses of \cl{indenting-output} inside of \cl{filling-output} +may not be portable. \section {Filled Output} diff --git a/specs/text-styles.tex b/specs/text-styles.tex index c83534c5..1cfc6354 100644 --- a/specs/text-styles.tex +++ b/specs/text-styles.tex @@ -31,7 +31,7 @@ size component is not a relative size (that is, is neither \cl{:smaller} nor The protocol class for text styles. \IfYouWantClass {a} {text style} {text-style} -\Defun {text-style-p} {object} +\Defpredicate {text-style-p} {object} Returns \term{true} if \arg{object} is a \term{text style}, otherwise returns \term{false}. @@ -64,7 +64,8 @@ Implementations are permitted to extend legal values for \arg{family}, \issue {York, SWM} {Need to describe what family, face, size mean in terms of visual appearance. This should also be reconciled with the ISO description of -the attributes of a ``text style''.} +the attributes of a ``text style'', including such things as underlining, +subscripts, superscripts, etc.} \Defconst {*default-text-style*} @@ -137,15 +138,15 @@ largest, is \cl{:tiny}, \cl{:very-small}, \cl{:small}, \cl{:normal}, bold face with an italic one can result in a bold-italic face.} -\defgeneric {text-style-ascent} {text-style port} -\defgeneric {text-style-descent} {text-style port} -\defgeneric {text-style-height} {text-style port} -\Defgeneric {text-style-width} {text-style port} +\defgeneric {text-style-ascent} {text-style medium} +\defgeneric {text-style-descent} {text-style medium} +\defgeneric {text-style-height} {text-style medium} +\Defgeneric {text-style-width} {text-style medium} Returns the ascent, descent, height, and width (respectively) of the font corresponding to the \term{text style} \arg{text-style} as it would be rendered -on any medium on the \term{port} \arg{port}. \arg{text-style} must be a fully -specified text style. +on the \term{medium} \arg{medium}. \arg{text-style} must be a fully specified +text style. The ascent of a font is the distance between the top of the tallest character in that font and the font's baseline. The descent of a font is the distance @@ -155,21 +156,21 @@ and the descent of the font. The width of a font is the width of some representative character in the font. The methods for these generic functions will typically specialize both the -\arg{text-style} and \arg{port} arguments. Implementations should also provide -``trampoline'' for these generic function for mediums and output sheets; the -trampolines will simply call the method for the port. +\arg{text-style} and \arg{medium} arguments. Implementations should also +provide ``trampoline'' for these generic functions on output sheets; the +trampolines will simply call the method for the medium. -\Defgeneric {text-style-fixed-width-p} {text-style port} +\Defgeneric {text-style-fixed-width-p} {text-style medium} Returns \term{true} if the \term{text styles} \arg{text-style} will map to a -fixed-width font on any medium on the \term{port} \arg{port}, otherwise returns +fixed-width font on the \term{medium} \arg{medium}, otherwise returns \term{false}. \arg{text-style} must be a fully specified text style. The methods for this generic function will typically specialize both the -\arg{text-style} and \arg{port} arguments. Implementations should also provide -a ``trampoline'' for this generic function for mediums and output sheets; the -trampoline will simply call the method for the port. +\arg{text-style} and \arg{medium} arguments. Implementations should also +provide a ``trampoline'' for this generic function for output sheets; the +trampoline will simply call the method for the medium. \issue {SWM} {Discuss baselines? Kerning?} diff --git a/specs/transforms.tex b/specs/transforms.tex index f1f416de..b5aceaff 100644 --- a/specs/transforms.tex +++ b/specs/transforms.tex @@ -23,7 +23,7 @@ transformations. The exact names of these classes is explicitly unspecified. All of the instantiable transformation classes provided by CLIM are immutable. -\Defun {transformationp} {object} +\Defpredicate {transformationp} {object} Returns \term{true} if \arg{object} is a \term{transformation}, otherwise returns \term{false}. @@ -44,17 +44,21 @@ is a subclass of \cl{error}. \Deferror {transformation-underspecified} The error that is signalled when \cl{make-3-point-transformation} is given three -collinear image points. +collinear image points. This condition will handle the \cl{:points} initarg, +which is used to supply the points that are in error. \Deferror {reflection-underspecified} The error that is signalled when \cl{make-reflection-transformation} is given -two coincident points. +two coincident points. This condition will handle the \cl{:points} initarg, +which is used to supply the points that are in error. \Deferror {singular-transformation} The error that is signalled when \cl{invert-transformation} is called on a -singular transformation, that is, a transformation that has no inverse. +singular transformation, that is, a transformation that has no inverse. This +condition will handle the \cl{:transformation} initarg, which is used to supply +the transformation that is singular. \section {Transformation Constructors} @@ -84,7 +88,7 @@ all entities from that point. points by \arg{angle} (which is a real number indicating an angle in radians) around the point \arg{origin}. If \arg{origin} is supplied it must be a point; if not supplied it defaults to $(0,0)$. \arg{origin-x} and \arg{origin-y} must -be real numbers. +be real numbers, and default to $0$. \defun {make-scaling-transformation} {scale-x scale-y \optional origin} \Defun {make-scaling-transformation*} {scale-x scale-y \optional origin-x origin-y} @@ -100,7 +104,7 @@ $x$-coordinate distance of every point from \arg{origin} by \arg{scale-x} and the $y$-coordinate distance of every point from \arg{origin} by \arg{scale-y}. \arg{scale-x} and \arg{scale-y} must be real numbers. If \arg{origin} is supplied it must be a point; if not supplied it defaults to $(0,0)$. -\arg{origin-x} and \arg{origin-y} must be real numbers. +\arg{origin-x} and \arg{origin-y} must be real numbers, and default to $0$. \defun {make-reflection-transformation} {point1 point2} @@ -345,6 +349,11 @@ methods for \cl{transform-region} and \cl{untransform-region}. That is, methods for the following generic functions will typically specialize both the \arg{transformation} and \term{region} arguments. +Note that, if the extended region classes are not implemented, the following +functions are not closed, that is, they may return results that are not CLIM +regions. + + \Defgeneric {transform-region} {transformation region} Applies \arg{transformation} to the \term{region} \arg{region}, and returns the diff --git a/test/postscript-tests.lisp b/test/postscript-tests.lisp index f5ca7842..08d52d9c 100644 --- a/test/postscript-tests.lisp +++ b/test/postscript-tests.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: LISP; Syntax: Common-lisp; Package: CLIM-USER; Base: 10; Lowercase: Yes -*- -;; $fiHeader: postscript-tests.lisp,v 1.4 92/12/16 16:50:10 cer Exp $ +;; $fiHeader: postscript-tests.lisp,v 1.5 93/03/04 19:01:26 colin Exp $ (in-package :clim-user) @@ -248,7 +248,7 @@ (0 0 0 1 0 0 0 0) (0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0)) - (list +foreground-ink+ +background-ink+)) + (list +background-ink+ +foreground-ink+)) 8 8)) ;(defun pat-ps (&optional file) diff --git a/test/test-clim.lisp b/test/test-clim.lisp new file mode 100644 index 00000000..2babace8 --- /dev/null +++ b/test/test-clim.lisp @@ -0,0 +1,432 @@ +;; -*- mode: common-lisp; package: clim-user -*- +;; +;; -[]- +;; +;; copyright (c) 1985, 1986 Franz Inc, Alameda, CA All rights reserved. +;; copyright (c) 1986-1992 Franz Inc, Berkeley, CA All rights reserved. +;; +;; The software, data and information contained herein are proprietary +;; to, and comprise valuable trade secrets of, Franz, Inc. They are +;; given in confidence by Franz, Inc. pursuant to a written license +;; agreement, and may be stored and used only in accordance with the terms +;; of such license. +;; +;; Restricted Rights Legend +;; ------------------------ +;; Use, duplication, and disclosure of the software, data and information +;; contained herein by any agency, department or entity of the U.S. +;; Government are subject to restrictions of Restricted Rights for +;; Commercial Software developed at private expense as specified in FAR +;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as +;; applicable. +;; +;; $fiHeader: test-clim.lisp,v 1.20 93/02/08 15:57:09 cer Exp $ + + +(in-package :clim-user) + +;;; Testing stuff + +(define-frame-test run-clim-tests (clim-tests :width 600 :height 600) + ( + (:commands clim-tests-commands) + ) + (exit-clim-tests)) + +(define-frame-test run-clim-tests-with-r-tree (clim-tests + :width 600 :height 600 + :history-class r-tree-output-history) + ( + (:commands clim-tests-commands) + ) + (exit-clim-tests)) + +(defun do-avv-test (inv) + (execute-one-command inv '(com-graphics-dialog)) + (wait-for-clim-input-state inv) + (clim-utils:letf-globally (((slot-value inv 'avv-frame) (get-avv-frame inv))) + (dotimes (i 10) + (dolist (cmd '(("Draw / diagonal" nil) + ("Draw / diagonal" t) + ("Color" :red) + ("Color" :green))) + (apply 'change-query-value inv cmd) + (wait-for-clim-input-state inv))) + (execute-one-command inv :abort) + )) + +(define-command-sequence clim-tests-commands + (com-draw-some-bezier-curves) + (:commands do-avv-test) + (com-input-editor-tests) + "This is (sexp) and a string" + :ie-backward-character + :ie-backward-character + :ie-backward-word + :ie-backward-word + :ie-backward-word + :ie-forward-word + :ie-backward-word + :ie-backward-sexp + :ie-forward-sexp + :ie-end-of-line + :ie-beginning-of-line + :ie-delete-word + :ie-delete-character + :ie-forward-word + :ie-forward-character + :ie-rubout-character + :ie-rubout-character + " love lisp" + :ie-beginning-of-line + :ie-upcase-word + :ie-beginning-of-line + :ie-downcase-word + :ie-beginning-of-line + :ie-kill-line + :ie-make-|()| + "cons (car x) (cdr x)" + :help + :abort + + ;;--- phew. write some more + + (com-drag-and-drop-tests) + (:presentation-click display-pane drag-source) + (:presentation-click display-pane drop-target) + (:presentation-click display-pane drag-source) + (:presentation-click display-pane drop-target) + (:presentation-click display-pane drag-source) + (:presentation-click display-pane drop-target) + (:presentation-click display-pane drag-source) + (:presentation-click display-pane drop-target) + (:presentation-click display-pane drag-source) + (:presentation-click display-pane drop-target) + :abort + + (com-simple-redisplay) + (:presentation-click display-pane integer) + (:presentation-click display-pane integer) + (:presentation-click display-pane integer) + (:presentation-click display-pane integer) + :abort + + (com-read-image-test) + + (com-filled-output) + + ;; This would be nice but moving to the top right of the + ;; presentation does not work when they are circular! + ;; (com-ordering-test-1) + ;; (:presentation-click display-pane integer) + + + (:presentation-click display-pane string) + + (com-ordering-test-2a) + (:presentation-click display-pane integer) + (com-ordering-test-2b) + (:presentation-click display-pane integer) + + (com-text-formatting) + + (com-negative-extent) + (com-more-simple-menus) + (com-readonly-gadget-dialog) + :abort + (com-ozone-dialog) + :abort + (com-gadgets-dialog) + :abort + (com-graphics-dialog) + :abort + (com-simple-spreadsheet) + :abort + (com-highlighting-tests) + "123" + #\return + "56565" + #\return + :abort + ;; (com-graphics-dialog) + ;; (com-choose-compass-direction) + ;; (com-graphical-menu) + ;; (com-simple-menu) + (com-string-stream-accept) + (com-string-accept) + (com-redisplay-graph) + (com-redisplay-border) + (com-redisplay-overlapping) + (com-graphics-redisplay-2) + (com-graphics-redisplay-1) + ;; (com-simple-redisplay) + ;; (com-comprehensive-table-tests) + ;; (com-text-formatting) + ;; (com-filled-output) + (com-offset-graph) + (com-clos-metaobjects-graph) + (com-offset-table) + (com-simple-graph) + (com-hairy-graph-formatting) + (com-simple-borders) + (com-mixed-table) + (com-checkerboard) + (com-cell-coordinates) + (com-nested-table) + (com-equalized-multiple-columns-table) + (com-multiple-columns-table) + (com-equal-width-table) + (com-column-table) + (com-row-table) + (com-cursorpos-table) + ;; (com-ordering-test-2b) + ;; (com-ordering-test-2a) + ;; (com-ordering-test-1) + (com-draw-bullseye) + (com-basic-line-styles) + (com-patterned-graphics-shapes) + (com-colored-inks) + (com-rotated-text) + (com-pixmap-test) + (com-points-and-lines) + (com-basic-graphics-inks) + (com-transformed-graphics-shapes) + (com-basic-graphics-shapes) + (com-region-intersects-region-tests) + (com-region-contains-region-tests) + (com-region-contains-point-tests) + (com-region-equal-tests) + (com-draw-enstyled-text) + (com-blue-gettysburg) + (com-styled-gettysburg) + (com-gettysburg) + (com-draw-some-arcs) + (com-draw-some-points) + (com-scaled-rotated-circles) + (com-rotated-scaled-circles) + (com-draw-some-circles) + (com-scaled-rotated-rectangles) + (com-rotated-scaled-rectangles) + (com-draw-some-rectangles)) + +(define-frame-test test-test-frame (test-frame :width 600 :height 600) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-test-frame0 (test-frame0) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-test-frame5 (test-frame5) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button)) + (com-switch) + (com-switch)) + (com-quit)) + +(define-frame-test test-tf99 (tf99) + () + (com-quit)) + +(define-frame-test test-tf98 (tf98 :width 600 :height 600) + () + (com-quit)) + +(define-frame-test test-tf96 (tf96) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-tf96-2 (tf96) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button)) + (com-frob-sizes) + (com-frob-sizes) + (com-frob-sizes) + (com-frob-sizes)) + (com-quit)) + +(define-frame-test test-tf95 (tf95) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-tf94 (tf94) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-tf93 (tf93) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-tf91 (tf91) + ((com-clear) + (com-make-table) + (com-make-table) + (com-square-it 5) + (com-make-one (:push-button))) + (com-quit)) + +(define-frame-test test-tf92 (tf92) + () + (com-quit)) + + +(define-frame-test test-tf101 (tf101) + ((com-make-table) + (com-switch) + (com-switch) + (com-switch)) + (com-quit)) + +(define-frame-test test-tf100 (tf100) + () + (com-quit)) + +(define-frame-test test-tf107 (tf107) + () + (com-quit)) + +(define-frame-test test-tf107 (tf108) + () + (com-quit)) + +(defun run-postscript-tests (&key (output :view)) + (exercise-frame 'clim-postscript-tests + '(:width 600 :height 600) + (mapcar #'(lambda (command) + (append command `(:output ,output))) + '((pcom-test-set-1) + (pcom-partial-circle 0 255) + (pcom-show-dash-patterns-some-more) + (pcom-show-dash-patterns) + (pcom-test-with-room-for-graphics) + (pcom-test-record-and-replay) + (pcom-test-transformations) + (pcom-test-text-alignment "Ignatz") + (pcom-test-text-baselines) + (pcom-test-text-sizes) + (pcom-test-text-size) + (pcom-test-table) + (pcom-test-text-vertical-alignment) + (pcom-test-character-positioning) + (pcom-write-multiple-strings) + (pcom-test-alignment) + (pcom-test-graphics) + (pcom-test-ellipse) + (pcom-draw-line-test) + (pcom-pattern-test))) + '(com-exit-clim-postscript-tests))) +;;; + +(define-application-frame frame-test () + () + (:panes + (display :interactor)) + (:layouts + (default display))) + +(define-frame-test-command com-frame-test-hello + () + (with-text-size (t :huge) + (write-line "Hello"))) + +(define-frame-test-command com-frame-test-change-name + () + (setf (frame-pretty-name *application-frame*) "Sonic Rules")) + +(define-frame-test-command com-frame-test-display-dialogs + () + (mp::with-timeout (3) (select-file *application-frame*)) + (dolist (style '(:inform :error :question :warning)) + (mp::with-timeout (3) + (notify-user *application-frame* + "Just say no to sega games" + :title (format nil "The style is ~A" style) + :style style)))) + +(define-frame-test-command com-frame-test-bye + () + (with-text-size (t :huge) + (write-line "Bye"))) + +(define-frame-test-command com-frame-test-quit + () + (frame-exit *application-frame*)) + +(define-frame-test-command com-frame-test-raise + () + (raise-frame *application-frame*)) + +(define-frame-test-command com-frame-test-bury + () + (bury-frame *application-frame*)) + +(define-frame-test-command com-frame-test-iconify + () + (shrink-frame *application-frame*)) + +(define-frame-test-command com-frame-test-deiconify + () + (enable-frame *application-frame*)) + +(define-frame-test test-frame-test (frame-test :width 400 :height 400) + ((com-frame-test-hello) + (:sleep 2) + (com-frame-test-change-name) + (:sleep 2) + (com-frame-test-display-dialogs) + (:sleep 2) + (com-frame-test-bury) + (:sleep 3) + (com-frame-test-raise) + (:sleep 3) + (com-frame-test-iconify) + (:sleep 2) + (com-frame-test-deiconify) + (:sleep 2) + (com-frame-test-bye) + ) + (com-frame-test-quit)) + +;;; make the training selective. + +(locally + (declare (special si::*clos-preload-packages*)) + (setq si::*clos-preload-packages* + (mapcar #'find-package '(:clim :clim-internals :silica :tk :xm-silica)))) + +;; This stops warnings happening asynchronously and causing confusion. + +(setq excl:*global-gc-behavior* nil) + + + diff --git a/test/test-driver.lisp b/test/test-driver.lisp new file mode 100644 index 00000000..35d4bfb3 --- /dev/null +++ b/test/test-driver.lisp @@ -0,0 +1,497 @@ +(in-package :clim-user) + +(defclass invocation () + ((process :initform nil :accessor invocation-process) + (frame :initform nil :accessor invocation-frame) + (condition :initform nil :accessor invocation-condition) + (state :initform nil :accessor invocation-state) + (avv-frame :initform nil :accessor invocation-avv-frame) + )) + +(defun invocation-active-p (invocation) + (not (eq (invocation-state invocation) :dead))) + +(defmethod initialize-instance :after ((inv invocation) &key class initargs) + (flet ((run-frame-top-level-almost (frame) + ;; Maybe this should be a handler bind so there is the + ;; option of trying again as well as aborting the process + (handler-case + (unwind-protect + (loop + (let ((again (catch 'try-again + (setf (invocation-state inv) :running) + (run-frame-top-level frame) + nil))) + (unless again (return nil)))) + (setf (invocation-state inv) :dead)) + (error (condition) + (handler-invocation-debugger-hook inv condition))))) + (let* ((frame (apply #'make-application-frame class initargs)) + (process (mp:process-run-function + (format nil "~A Test process for" class) + #'run-frame-top-level-almost + frame))) + (setf (invocation-process inv) process + (invocation-frame inv) frame) + (wait-for-clim-input-state inv)))) + +(defun handler-invocation-debugger-hook (invocation condition) + (format excl:*initial-terminal-io* "The following error occurred: ~A~%" condition)) + +(defun wait-for-clim-input-state (invocation &optional (timeout 300)) + (let ((process (invocation-process invocation))) + (mp:process-allow-schedule) + (if timeout + (let ((done nil)) + (mp:process-wait-with-timeout + "Waiting for process to sleep" + timeout + #'(lambda () + (setq done + (or (not (mp::process-stack-group process)) + (string-equal (mp::process-whostate process) "CLIM Input"))))) + (unless done + (error "Timed out after ~D seconds" timeout))) + (mp:process-wait + "Waiting for process to sleep" + #'(lambda () + (or (not (mp::process-stack-group process)) + (string-equal (mp::process-whostate process) "CLIM Input"))))))) + +(defvar *death-timeout* 30) + +(defun terminate-invocation (invocation exit-command) + (with-slots (frame process) invocation + (write-line "Terminating frame") + (execute-one-command invocation exit-command) + (unless (mp::process-stack-group process) (error "Frame terminated abnormally")) + (unless (wait-for-death process) + (warn "Process did not terminate")))) + +(defun wait-for-death (process) + (let (done) + (mp:process-wait-with-timeout + "Waiting for death" + *death-timeout* + #'(lambda () (setq done (not (mp::process-stack-group process))))) + done)) + + +(defun execute-commands-in-invocation (invocation commands) + (do ((commands commands (cdr commands))) + ((or (not (invocation-active-p invocation)) + (null commands))) + (execute-one-command invocation (car commands)) + (wait-for-clim-input-state invocation))) + +(defvar *command-sequence-table* (make-hash-table)) + +(defun execute-one-command (invocation command) + (with-slots (frame process avv-frame) invocation + (let ((sheet (frame-top-level-sheet (or avv-frame frame)))) + (unless (characterp command) + (format t "Executing command ~S~%" command)) + (etypecase command + (character + (let ((x (clim-internals::port-canonicalize-gesture-spec (port frame) command))) + (when x + (distribute-event (port frame) + (make-instance 'key-press-event + :sheet sheet + :character command + :key-name (car x) + :modifier-state (cdr x)))))) + (string + (dotimes (i (length command)) + (execute-one-command invocation (char command i)))) + (keyword + (distribute-event (port frame) + (multiple-value-bind (keysym modifiers) + (clim-internals::gesture-name-keysym-and-modifiers command) + (make-instance 'key-press-event + :sheet sheet + :character nil + :key-name keysym + :modifier-state modifiers)))) + + (list + (case (car command) + (:sleep + (sleep (cadr command))) + (:presentation-click + (apply #'click-on-presentation invocation (cdr command))) + (:presentation-press + (apply #'click-on-presentation invocation + (second command) (third command) :release nil (cdddr command))) + (:click + (apply #'click-on-window invocation (cdr command))) + (:press + (apply #'press-on-window invocation (cdr command))) + (:release + (apply #'release-on-window invocation (cdr command))) + (:command + (apply #'test-a-command invocation (cdr command))) + (:commands + (funcall (cadr command) invocation)) + (:edit-avv + (destructuring-bind (pane prompt new-value) (cdr command) + (change-query-value invocation prompt new-value pane))) + (t + (if (and (consp command) (consp (car command))) + (destructuring-bind (command &key timeout) command + (execute-command-in-frame (or avv-frame frame) command) + (when timeout + (wait-for-clim-input-state invocation timeout))) + (execute-command-in-frame (or avv-frame frame) command))))))))) + +(defvar *catch-errors-in-tests* t) + +(defun exercise-frame (class initargs commands exit-command &optional (error *catch-errors-in-tests*)) + (flet ((doit () + (let ((invocation (make-instance 'invocation :class class :initargs initargs))) + (unwind-protect + (if commands + (execute-commands-in-invocation invocation commands) + (sleep 5)) + (terminate-invocation invocation exit-command) + (mp::process-kill (invocation-process invocation)) + (unless (wait-for-death (invocation-process invocation)) + (warn "Process would not die when killed")) + (destroy-frame (invocation-frame invocation)))))) + (if error + (handler-case (doit) + (error (condition) + (warn "The following error occurred: ~A" condition))) + (doit)))) + + +(defun walk-over-presentations (function output-record) + (labels ((find-object-1 (record x-offset y-offset) + (with-bounding-rectangle* (left top right bottom) record + (incf left x-offset) + (incf right x-offset) + (incf top y-offset) + (incf bottom y-offset) + (when (typep record 'standard-presentation) + (funcall function record left top right bottom)) + (multiple-value-bind (xoff yoff) (output-record-start-cursor-position record) + (map-over-output-records + #'find-object-1 record + (- x-offset) (- y-offset) + (+ x-offset xoff) (+ y-offset yoff)))))) + (find-object-1 output-record 0 0))) + +(setq *random-state* (make-random-state t)) + + +(defun click-on-presentation (invocation pane-name + presentation-type + &key gesture + (release t) + (modifier 0) (button +pointer-left-button+)) + (with-slots (frame process) invocation + (when gesture + (multiple-value-setq (button modifier) + (clim-internals::gesture-name-button-and-modifiers gesture)) + (assert button () "Not a valid gesture")) + (let ((pane (get-frame-pane frame pane-name)) + (presentations nil) + (expanded-presentation-type + (expand-presentation-type-abbreviation presentation-type))) + (flet ((doit (record left top right bottom) + (when (presentation-subtypep + (presentation-type record) + expanded-presentation-type) + (stream-set-pointer-position pane left top) + ;; At this point it would be nice to specify that a + ;; modifier key was pressed. + (wait-for-clim-input-state invocation) + (when (eq (clim-internals::stream-highlighted-presentation + pane) record) + (push (list record left top right bottom) + presentations))))) + (walk-over-presentations #'doit (stream-output-history pane))) + #+ignore + (format excl:*initial-terminal-io* "~d presentations~%" (length presentations)) + (assert presentations () + "Did not find presentations to click on!") + (when presentations + (prog1 t + (let* ((len (length presentations)) + (i (random len))) + (destructuring-bind + (record left top right bottom) (nth i presentations) + (declare (ignore record right bottom)) + #+ignore + (format excl:*initial-terminal-io* + "selecting ~d of ~d = ~s @ ~d,~d~%" + i len record left top) + (stream-set-pointer-position pane left top) + (wait-for-clim-input-state invocation) + (assert (clim-internals::stream-highlighted-presentation pane)) + ;;-- this is bypassing the distribution mechanism + ;;-- Perhaps we should have a send-event that interfaces to + ;;-- the Xlib code. But can we send fill in all the detail + ;;-- fields of the event + ;;-- In order to get the modifiers to work I think we need + ;;-- to send Keypress/release events + (multiple-value-bind + (x y) (untransform-position (sheet-device-transformation pane) left top) + (let ((ma (sheet-mirrored-ancestor pane)) + (port (port pane))) + (distribute-event port + (make-instance 'pointer-button-press-event + :sheet ma + :pointer (port-pointer port) + :button button + :native-x x + :native-y y + :x :?? :y :?? + :modifier-state + modifier)) + (when release + (distribute-event port + (make-instance 'pointer-button-release-event + :sheet ma + :pointer (port-pointer port) + :button button + :native-x x + :native-y y + :x :?? :y :?? + :modifier-state modifier)))))))))))) + + +(defun click-on-window (invocation pane-name left top &rest args) + (apply #'button-event-on-window invocation pane-name left top + :up t :down t args)) + +(defun press-on-window (invocation pane-name left top &rest args) + (apply #'button-event-on-window invocation pane-name left top + :up nil :down t args)) + +(defun release-on-window (invocation pane-name left top &rest args) + (apply #'button-event-on-window invocation pane-name left top + :up t :down nil args)) + + + +(defun button-event-on-window (invocation pane-name left top + &key gesture (modifier 0) (button +pointer-left-button+) + up down) + (with-slots (frame process) invocation + (when gesture + (multiple-value-setq (button modifier) + (clim-internals::gesture-name-button-and-modifiers gesture)) + (assert button () "Not a valid gesture")) + (let ((pane (get-frame-pane frame pane-name))) + (stream-set-pointer-position pane left top) + (wait-for-clim-input-state invocation) + (multiple-value-bind + (x y) (untransform-position (sheet-device-transformation pane) left top) + (let ((ma (sheet-mirrored-ancestor pane)) + (port (port pane))) + (when down + (distribute-event port + (make-instance 'pointer-button-press-event + :sheet ma + :pointer (port-pointer port) + :button button + :native-x x + :native-y y + ;;-- normally the distributor + ;;-- fills these in + :x :?? :y :?? + :modifier-state modifier))) + (when up + (distribute-event port + (make-instance 'pointer-button-release-event + :sheet ma + :pointer (port-pointer port) + :button button + :native-x x + :native-y y + ;;-- normally the distributor + ;;-- fills these in + :x :?? :y :?? + :modifier-state modifier)))))))) + + + +(defun simulate-accept (invocation pane-name presentation-type &key + stream + default provide-default &allow-other-keys) + ;; We a choice. + ;; 1. Send the characters or + ;; 2. Click on a presentation + (assert (click-on-presentation invocation pane-name presentation-type) + () "Clicking failed")) + +(defun send-it (invocation x &key (delim t)) + (execute-one-command invocation (string x)) + (when delim + (execute-one-command invocation " "))) + +(defun test-a-command (invocation pane-name command &key colon-prefix) + (with-slots (process frame) invocation + (let ((stream (get-frame-pane frame pane-name))) + (flet ((accept-function (stream presentation-type &rest args) + (apply #'simulate-accept invocation pane-name stream + presentation-type args)) + (send-it-function (x) + (send-it invocation x))) + (when colon-prefix + (send-it invocation ":" :delim nil)) + (fill-in-partial-command-1 + (if (atom command) command (car command)) + (frame-command-table frame) + stream + command + #'accept-function + #'send-it-function) + ;;--- Need to send a newline now + ;;--- It looks like some clim code tries to eat following + ;;--- delimiters if they are there. Which code is this? + (sleep 2) + (send-it invocation #\newline :delim nil) + )))) + + + +(defvar *frame-tests* nil) + +(defmacro define-frame-test (name (class &rest initargs) commands exit-command) + `(progn + (pushnew ',name *frame-tests*) + (defun ,name () + (exercise-frame ',class ',initargs ',commands ',exit-command)))) + +(defmacro define-command-sequence (name &rest commands) + `(defun ,name (invocation) + (execute-commands-in-invocation invocation ',commands))) + +(defun do-frame-tests (&optional (errorp *catch-errors-in-tests*)) + (dolist (test *frame-tests*) + (format t "Doing test ~A~%" test) + (if errorp + (handler-case (funcall test) + (error (c) + (format t "~&The following error occurred in ~S: ~A~%" test + c))) + (funcall test)))) + + +;;; Training stuff + +(defun train-clim-2 (&optional (n 2)) + (dotimes (i n) + (format t "Test ~D out of ~D~%" (1+ i) n) + (test-it))) + +(defun benchmark-clim (filename) + (test-it (or filename + (multiple-value-bind (second minute hour date month year) + (get-decoded-time) + (declare (ignore second minute hour)) + (format nil "notes/times/~D.~D.~D.n" month date year))))) + +(defun test-it (&optional filename (errorp *catch-errors-in-tests*)) + (let* ((file (pathname (or filename (format nil "/tmp/foofile~A" (gensym)))))) + (exercise-frame 'clim-tests + '(:width 600 :height 400 :left 0 :top 0) + `(((run-benchmarks-to-dummy-file :file ,file) :timeout 1800)) + `(exit-clim-tests) + errorp) + (unless filename (delete-file file)))) + +(defun fill-in-partial-command-1 (command-name command-table stream + partial-command accept-function send-it) + (let ((*original-stream* nil) + (copy-partial-command (if (atom partial-command) + (list partial-command) + partial-command))) + (labels ((arg-parser (stream presentation-type &rest args) + (declare (dynamic-extent args)) + ;; This code is to handle the case where a partial command has been + ;; passed in. PARSE-NORMAL-ARG needs to be called with a :DEFAULT of + ;; the appropriate element of the partial command structure. + (let* ((default (if copy-partial-command + (pop copy-partial-command) + *unsupplied-argument-marker*))) + (with-presentation-type-decoded (type-name parameters) presentation-type + (when (eq type-name 'command-name) + (send-it (string-downcase(command-line-name-for-command + command-name + command-table))) + (return-from arg-parser (values command-name presentation-type))) + (cond ((not (clim-internals::unsupplied-argument-p default)) + (cond ((eq type-name 'keyword-argument-name) + default) + (t (apply #'parse-normal-arg + stream presentation-type + :default default args)))) + ((eq type-name 'keyword-argument-name) + (let ((name (intern (symbol-name (caar parameters)) clim-internals::*keyword-package*))) + (send-it name) + name)) + (t + (apply #'parse-normal-arg + stream presentation-type + :provide-default nil args)))))) + (send-it (it) + (funcall send-it it)) + (parse-normal-arg (stream arg-type &rest options) + (declare (dynamic-extent options)) + (with-delimiter-gestures (*command-argument-delimiters*) + (apply accept-function arg-type :stream stream options))) + (separate-args (stream args-to-go) + (declare (ignore stream args-to-go)) + #+ignore + (when (only-keyword-args-remain args-to-go) + (throw 'stop-reading-command-arguments nil)))) + (declare (dynamic-extent #'arg-parser #'parse-normal-arg #'separate-args)) + (clim-internals::invoke-command-parser-and-collect + command-table #'arg-parser #'separate-args stream)))) + +;;; Need +;;; 1. Access to avv fields +;;; 2. Send mouse events clicks that are independent of presentations +;;; (eg tracking-pointer stuff). + +;;; Testing avv + +(defun get-avv-frame (invocation) + (with-slots (process frame) invocation + (let ((avv-frame nil)) + (loop + (setf avv-frame nil) + (mp::process-interrupt process #'(lambda () (setq avv-frame (list *application-frame*)))) + (mp:process-wait "Waiting for frame" #'(lambda () avv-frame)) + (unless (eq (car avv-frame) frame) + (return-from get-avv-frame (car avv-frame))) + (sleep 1))))) + +(defun find-avv-query (avv-stream prompt) + (maphash #'(lambda (query-id query) + (when (and (consp query-id) + (eq (car query-id) :query-identifier) + (consp (cdr query-id)) + (equal (cadr query-id) prompt)) + (return-from find-avv-query query))) + (slot-value (slot-value avv-stream 'clim-internals::avv-record) 'clim-internals::query-table))) + +(defun change-query-value (invocation prompt new-value &optional pane-name) + (with-slots (process frame avv-frame) invocation + (let ((query (find-avv-query (if pane-name + (car (gethash (get-frame-pane frame pane-name) + (clim-internals::frame-pane-to-avv-stream-table frame))) + (slot-value avv-frame 'stream)) + prompt))) + (assert query () "Could not find the query") + (execute-one-command invocation `(clim-internals::com-change-query ,query ,new-value))))) + +;; How to invoke command-buttons +;; It would be nice if we could change gadget values directly. +;; Lets say we want to run the bitmap-editor-add-color frame, change +;; some values and then exit from the frame +;; How can we wait for a frame to be created. Grab hold of it and then +;; run some commands on it. diff --git a/test/test.lisp b/test/test.lisp index 50d63732..4e21ac4c 100644 --- a/test/test.lisp +++ b/test/test.lisp @@ -19,7 +19,7 @@ ;; 52.227-19 or DOD FAR Suppplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: test.lisp,v 1.43 92/12/03 10:29:53 cer Exp $ +;; $fiHeader: test.lisp,v 1.44 93/02/08 15:57:48 cer Exp $ (in-package :clim-user) @@ -380,13 +380,15 @@ (make-pane 'text-editor :word-wrap nil :value "c sucks" - :ncolumns 30 :nlines 10))) + :width '(30 :character) + :height '(10 :line)))) (outlining () (scrolling () (make-pane 'text-editor :word-wrap t :value "unix sucks more" - :ncolumns 30 :nlines 10)))))) + :width '(30 :character) + :height '(10 :line))))))) (define-application-frame tf99 () () (:command-table test-frame) @@ -421,13 +423,15 @@ (make-pane 'text-editor :value "c sucks" :value-changed-callback 'text-field-changed - :ncolumns 30 :nlines 10))) + :width '(30 :character) + :height '(10 :line)))) (outlining () (scrolling () (make-pane 'text-editor :value "unix sucks more" :value-changed-callback 'text-field-changed - :ncolumns 30 :nlines 10)))) + :width '(30 :character) + :height '(10 :line))))) (outlining () (spacing () (make-pane 'slider @@ -464,13 +468,15 @@ (make-pane 'text-editor :value "c sucks" :value-changed-callback 'text-field-changed - :ncolumns 30 :nlines 10))) + :width '(30 :character) + :height '(10 :line)))) (outlining () (scrolling () (make-pane 'text-editor :value "unix sucks more" :value-changed-callback 'text-field-changed - :ncolumns 30 :nlines 10))))) + :width '(30 :character) + :height '(10 :line)))))) (outlining () (spacing () (make-pane 'slider @@ -490,14 +496,14 @@ (make-pane 'text-editor :value "lucid " :value-changed-callback 'text-field-changed - :ncolumns 30 - :nlines 10))) + :width '(30 :character) + :height '(10 :line)))) (scrolling () (make-pane 'text-editor :value "harlqn more" :value-changed-callback 'text-field-changed - :ncolumns 30 - :nlines 10))))))) + :width '(30 :character) + :height '(10 :line)))))))) (define-application-frame tf97 () () (:command-table test-frame) @@ -530,8 +536,8 @@ (make-pane 'text-editor :value "lucid are nice guys " :value-changed-callback 'text-field-changed - :ncolumns 30 - :nlines 10)))) + :width '(30 :character) + :height '(10 :line))))) (make-clim-interactor-pane :scroll-bars :vertical)))) (define-application-frame tf96 () () @@ -950,8 +956,8 @@ (setq r (accept 'string :stream stream :prompt "foo" :view '(text-editor-view - :ncolumns 30 - :nlines 5) + :width (30 :character) + :height (5 :line)) :default r)) (terpri stream) (setq u (accept '(member :xxx :yyy :zyy) @@ -1010,3 +1016,18 @@ :foreground +cyan+ :text-style (make-text-style :serif :roman 20)))))) + +(define-application-frame tf108 () + () + (:command-table test-frame) + (:panes + (z push-button :label "fart") + (a text-field) + (b label-pane :label "hello") + (c text-field :width '(50 :character)) + (d text-editor :height '(10 :line)) + (e label-pane :label "goodbye" :width '(50 :character)) + (f push-button :label "goodbye" :width '(50 :character))) + (:layouts + (default (scrolling (:max-height +fill+) + (vertically (:y-spacing 20) z a b c d e f))))) diff --git a/tk-silica/ol-frames.lisp b/tk-silica/ol-frames.lisp index a9342609..aa693a54 100644 --- a/tk-silica/ol-frames.lisp +++ b/tk-silica/ol-frames.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: ol-frames.lisp,v 1.19 92/12/03 10:30:10 cer Exp $ +;; $fiHeader: ol-frames.lisp,v 1.20 92/12/07 12:15:50 cer Exp $ (in-package :xm-silica) @@ -58,7 +58,9 @@ presentation-type associated-window text-style - label) + label + gesture) + (declare (ignore gesture)) (let* (value-returned return-value (simplep (and (null printer) @@ -190,3 +192,19 @@ (declare (ignore menu)) t) + +(defmethod clim-internals::frame-manager-invoke-with-noting-progress ((framem openlook-frame-manager) + note + continuation) + (let ((shell (let ((stream (slot-value note 'stream))) + (if stream + (frame-shell (pane-frame stream)) + (frame-shell *application-frame*))))) + (if (typep shell 'xt::vendor-shell) + (let ((old-busy (tk::get-values shell :busy))) + (unwind-protect + (progn + (tk::set-values shell :busy t) + (call-next-method)) + (tk::set-values shell :busy old-busy))) + (call-next-method)))) diff --git a/tk-silica/ol-gadgets.lisp b/tk-silica/ol-gadgets.lisp index 4a2b1cb4..68ca499b 100644 --- a/tk-silica/ol-gadgets.lisp +++ b/tk-silica/ol-gadgets.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: ol-gadgets.lisp,v 1.38 93/02/08 15:58:04 cer Exp $ +;; $fiHeader: ol-gadgets.lisp,v 1.39 93/03/04 19:01:52 colin Exp $ (in-package :xm-silica) @@ -873,6 +873,82 @@ (when (sheet-direct-mirror sheet) (tk::set-values (sheet-direct-mirror sheet) :title-string (or nv "")))) + +;;; New definitions to support specifying width and height in terms of +;;; lines and characters. +;;;;---------------- This needs to be done for Openlook +;;;;---------------- Code currently is just a copy of the motif stuff + +;;;--- Implement caching +;;;--- Flush ncolumns, nrows but perhaps keep them of compatibility +;;;--- We are not supporting (pixels :relative) + +(defmethod compose-space :around ((sheet openlook-text-field) &key width height) + (declare (ignore width height)) + (compose-space-for-text-field-or-label + sheet (call-next-method))) + +;;-- For label pane there are margin-{left,top,right,bottom} resources also +;;-- but they default to 0. + +(defmethod compose-space :around ((sheet openlook-label-pane) &key width height) + (declare (ignore width height)) + (compose-space-for-text-field-or-label + sheet (call-next-method))) + +(defmethod compose-space :around ((sheet openlook-push-button) &key width height) + (declare (ignore width height)) + (compose-space-for-text-field-or-label + sheet (call-next-method))) + +(defun compose-space-for-text-field-or-label (sheet sr) + (multiple-value-bind (width min-width max-width height min-height max-height) + (space-requirement-components sr) + (if (and (numberp width) + (numberp min-width) + (numberp max-width)) + sr + (make-space-requirement + :width (process-width-specification sheet width) + :min-width (process-width-specification sheet min-width) + :max-width (process-width-specification sheet max-width) + :height height + :min-height min-height + :max-height max-height)))) + +(defun process-width-specification (sheet width) + (break "Make me work") + (when (numberp width) (return-from process-width-specification width)) + (let ((chars (etypecase width + (list + (assert (eq (second width) :character)) + (first width)) + (string (length width))))) + (multiple-value-bind (font left-margin right-margin) + (tk::get-values (sheet-direct-mirror sheet) + :font :left-margin :right-margin) + (let ((font-width (font-list-max-width-and-height font))) + (+ (* 2 (+ left-margin right-margin)) (* font-width chars)))))) + +(defun font-list-max-width-and-height (font) + (values (tk::font-width font) (tk::font-height font))) + +;;-- What should this do really? + +(defun process-height-specification (sheet width) + (when (numberp width) (return-from process-height-specification width)) + (let ((chars (etypecase width + (list + (assert (eq (second width) :line)) + (first width)) + (string (length width))))) + (multiple-value-bind (font top-margin bottom-margin) + (tk::get-values (sheet-direct-mirror sheet) + :font :top-margin :bottom-margin) + (let ((font-height (nth-value 1 (font-list-max-width-and-height font-list)))) + (+ top-margin bottom-margin (* font-height chars)))))) + + ;;; (defclass openlook-text-editor (text-editor xt-leaf-pane) @@ -941,6 +1017,26 @@ :width width :min-width min-width :max-width +fill+ :height height :min-height min-height :max-height +fill+)))) +(defmethod compose-space :around ((sheet openlook-text-editor) &key width height) + (declare (ignore width height)) + (let ((sr (call-next-method))) + (multiple-value-bind (width min-width max-width height min-height max-height) + (space-requirement-components (call-next-method)) + (if (and (numberp width) + (numberp min-width) + (numberp max-width) + (numberp height) + (numberp min-height) + (numberp max-height)) + sr + (make-space-requirement + :width (process-width-specification sheet width) + :min-width (process-width-specification sheet min-width) + :max-width (process-width-specification sheet max-width) + :height (process-height-specification sheet height) + :min-height (process-height-specification sheet min-height) + :max-height (process-height-specification sheet max-height)))))) + (defmethod gadget-value ((gadget openlook-text-editor)) (if (sheet-direct-mirror gadget) (text-editor-text gadget) diff --git a/tk-silica/xm-frames.lisp b/tk-silica/xm-frames.lisp index af59868c..19de85a0 100644 --- a/tk-silica/xm-frames.lisp +++ b/tk-silica/xm-frames.lisp @@ -18,7 +18,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: xm-frames.lisp,v 1.48 93/02/10 10:04:22 cer Exp $ +;; $fiHeader: xm-frames.lisp,v 1.49 93/03/18 14:39:04 colin Exp $ (in-package :xm-silica) @@ -464,16 +464,51 @@ (tk::is-managed-p menu)) -;;;; - -#| - -(defmethod frame-manager-clear-progress-note - ((framem motif-frame-manager) (note progress-note)) - ) - -(defmethod frame-manager-display-progress-note - ((framem motif-frame-manager) (note progress-note)) - ) - -|# +;;; Progress notification code. + +(defvar *working-dialog* nil) + +(defmethod clim-internals::frame-manager-invoke-with-noting-progress ((framem motif-frame-manager) + note + continuation) + (if *working-dialog* + (let ((old-string (tk::get-values *working-dialog* :message-string))) + (unwind-protect + (progn + (tk::set-values *working-dialog* :message-string (string (progress-note-name note))) + (funcall continuation note)) + (tk::set-values *working-dialog* :message-string old-string))) + (let ((dialog (make-instance 'xt::xm-working-dialog + :dialog-style :primary-application-modal + :managed nil + :parent (let ((stream (slot-value note 'stream))) + (if stream + (frame-shell (pane-frame stream)) + (frame-shell *application-frame*))) + :name "Working" + :dialog-title "Progress Note" + :resize-policy :grow + :message-string + (format nil "~A "(progress-note-name note))))) + (multiple-value-bind + (ok-button cancel-button help-button separator) + (get-message-box-child dialog :ok :cancel :help :separator) + (tk::unmanage-child help-button) + (xt::unmanage-child cancel-button) + (tk::unmanage-child ok-button) + (tk::unmanage-child separator)) + (unwind-protect + (progn + (tk::manage-child dialog) + (let ((*working-dialog* dialog)) + (funcall continuation note))) + (tk::destroy-widget dialog))))) + +(defmethod clim-internals::frame-manager-display-progress-note + ((framem motif-frame-manager) note) + (with-slots ((name clim-internals::name) + (stream clim-internals::stream) + (numerator clim-internals::numerator) + (denominator clim-internals::denominator)) note + (tk::set-values *working-dialog* + :message-string (format nil "~A: ~3D%" name (round (* 100 numerator) denominator))))) diff --git a/tk-silica/xm-gadgets.lisp b/tk-silica/xm-gadgets.lisp index ffc21f69..de637407 100644 --- a/tk-silica/xm-gadgets.lisp +++ b/tk-silica/xm-gadgets.lisp @@ -18,7 +18,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: xm-gadgets.lisp,v 1.65 93/03/04 19:02:03 colin Exp $ +;; $fiHeader: xm-gadgets.lisp,v 1.66 93/03/18 14:39:13 colin Exp $ (in-package :xm-silica) @@ -158,6 +158,13 @@ (sheet motif-label-pane)) (values 'tk::xm-label nil)) + +(defmethod compose-space ((sheet motif-label-pane) &key width height) + (declare (ignore width height)) + (make-space-requirement + :width (process-width-specification sheet `(,(max 1 (length (gadget-label sheet))) :character)) + :height (process-height-specification sheet `(1 :line)))) + ;;; Push button (defclass motif-push-button (push-button @@ -199,6 +206,14 @@ 'sheet-mirror-event-handler sheet)) +;;-- This is identical to the method for label + +(defmethod compose-space ((sheet motif-push-button) &key width height) + (declare (ignore width height)) + (make-space-requirement + :width (process-width-specification sheet `(,(max 1 (length (gadget-label sheet))) :character)) + :height (process-height-specification sheet `(1 :line)))) + ;;; range pane mixin (defclass motif-range-pane (motif-value-changed-callback-pane) @@ -453,6 +468,7 @@ ;; its drawing area children :accelerators nil ;; Prevents buttons from deactivating dialog + :dialog-style :primary-application-modal :auto-unmanage nil :resize-policy :none :name (if (pane-frame sheet) @@ -514,6 +530,88 @@ `(:editable ,editable) (and value `(:value ,value)))))) + + +;;; New definitions to support specifying width and height in terms of +;;; lines and characters. + +;;;--- Implement caching +;;;--- Flush ncolumns, nrows but perhaps keep them of compatibility +;;;--- We are not supporting (pixels :relative) + +(defmethod compose-space :around ((sheet motif-text-field) &key width height) + (declare (ignore width height)) + (compose-space-for-text-field-or-label + sheet (call-next-method))) + +;;-- For label pane there are margin-{left,top,right,bottom} resources also +;;-- but they default to 0. + +(defmethod compose-space :around ((sheet motif-label-pane) &key width height) + (declare (ignore width height)) + (compose-space-for-text-field-or-label + sheet (call-next-method))) + +(defmethod compose-space :around ((sheet motif-push-button) &key width height) + (declare (ignore width height)) + (compose-space-for-text-field-or-label + sheet (call-next-method))) + +(defun compose-space-for-text-field-or-label (sheet sr) + (multiple-value-bind (width min-width max-width height min-height max-height) + (space-requirement-components sr) + (if (and (numberp width) + (numberp min-width) + (numberp max-width)) + sr + (make-space-requirement + :width (process-width-specification sheet width) + :min-width (process-width-specification sheet min-width) + :max-width (process-width-specification sheet max-width) + :height height + :min-height min-height + :max-height max-height)))) + +(defun process-width-specification (sheet width) + (when (numberp width) (return-from process-width-specification width)) + (let ((chars (etypecase width + (list + (assert (eq (second width) :character)) + (first width)) + (string (length width))))) + (multiple-value-bind (font-list margin highlight shadow) + (tk::get-values (sheet-direct-mirror sheet) + :font-list :margin-width :highlight-thickness :shadow-thickness) + (let ((font-width (font-list-max-width-and-height font-list))) + (+ (* 2 (+ margin highlight shadow)) (* font-width chars)))))) + +(defun font-list-max-width-and-height (font-list) + (let* ((max-width most-negative-fixnum) + (max-ascent most-negative-fixnum) + (max-descent most-negative-fixnum)) + (assert font-list) + (dolist (font font-list (values max-width (+ max-ascent max-descent))) + (let ((font (second font))) + (maxf max-ascent (tk::font-ascent font)) + (maxf max-descent (tk::font-descent font)) + (maxf max-width (tk::font-width font)))))) + +;;-- What should this do really? + +(defun process-height-specification (sheet width) + (when (numberp width) (return-from process-height-specification width)) + (let ((chars (etypecase width + (list + (assert (eq (second width) :line)) + (first width)) + (string (length width))))) + (multiple-value-bind (font-list margin highlight shadow) + (tk::get-values (sheet-direct-mirror sheet) + :font-list :margin-height :highlight-thickness :shadow-thickness) + (let ((font-height (nth-value 1 (font-list-max-width-and-height font-list)))) + (+ (* 2 (+ margin highlight shadow)) (* font-height chars)))))) + + #+ignore (defmethod add-sheet-callbacks :after ((port motif-port) (sheet motif-text-field) (widget t)) @@ -562,6 +660,31 @@ (and value `(:value ,value)) (and word-wrap `(:word-wrap t))))))) +(defmethod compose-space ((te motif-text-editor) &key width height) + (declare (ignore width height)) + (make-space-requirement :width (process-width-specification te`(,(gadget-columns te) :character)) + :height (process-height-specification te `(,(gadget-lines te) :line)))) + +(defmethod compose-space :around ((sheet motif-text-editor) &key width height) + (declare (ignore width height)) + (let ((sr (call-next-method))) + (multiple-value-bind (width min-width max-width height min-height max-height) + (space-requirement-components (call-next-method)) + (if (and (numberp width) + (numberp min-width) + (numberp max-width) + (numberp height) + (numberp min-height) + (numberp max-height)) + sr + (make-space-requirement + :width (process-width-specification sheet width) + :min-width (process-width-specification sheet min-width) + :max-width (process-width-specification sheet max-width) + :height (process-height-specification sheet height) + :min-height (process-height-specification sheet min-height) + :max-height (process-height-specification sheet max-height)))))) + (defmethod (setf gadget-word-wrap) :after (nv (gadget motif-text-editor)) (tk::set-values (sheet-direct-mirror gadget) :word-wrap (and nv t))) @@ -596,20 +719,7 @@ :width width :min-width min-width :max-width +fill+ :height height :min-height min-height :max-height +fill+)))) -(defmethod compose-space ((te motif-text-editor) &key width height) - (declare (ignore width height)) - (multiple-value-bind (font-list margin-height margin-width) - (tk::get-values (sheet-direct-mirror te) :font-list - :margin-height :margin-width) - (let* ((max-width most-negative-fixnum) - (max-height most-negative-fixnum)) - (assert font-list) - (dolist (font font-list) - (let ((font (second font))) - (maxf max-height (tk::font-height font)) - (maxf max-width (tk::font-width font)))) - (make-space-requirement :width (+ (* 2 margin-width) (* max-width (gadget-columns te))) - :height (+ (* 2 margin-height) (* max-height (gadget-lines te))))))) + ;;; Toggle button @@ -934,7 +1044,7 @@ :scroll-bar-display-policy ,(case scroll-mode ((:vertical :both) :static) - (t :dynamic)) + (t :as-needed)) ,@(and selected-items `(:selected-item-count ,(length selected-items) :selected-items ,selected-items)) diff --git a/tk-silica/xt-frames.lisp b/tk-silica/xt-frames.lisp index e6670136..9f089eff 100644 --- a/tk-silica/xt-frames.lisp +++ b/tk-silica/xt-frames.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: xt-frames.lisp,v 1.27 93/01/21 14:59:28 cer Exp $ +;; $fiHeader: xt-frames.lisp,v 1.28 93/02/08 15:58:13 cer Exp $ (in-package :xm-silica) @@ -73,7 +73,7 @@ (defun command-button-callback (button dunno frame command-table item) (declare (ignore dunno button)) (execute-command-in-frame - frame (second item) + frame (substitute clim-internals::*application-frame-marker* frame (second item)) :presentation-type `(command :command-table ,command-table))) @@ -104,7 +104,7 @@ (id-test 'equal) (cache-value items) (cache-test #'equal) - gesture) + (gesture :select)) (declare (ignore keys)) (declare (values value chosen-item gesture)) (let ((port (port framem)) @@ -188,10 +188,13 @@ '((:exit) (:abort))) (defmethod note-frame-iconified ((framem xt-frame-manager) frame) - (tk::set-values (frame-shell frame) :iconic t)) + (let ((display (port-display (port framem)))) + (x11:xiconifywindow display (tk::widget-window (frame-shell frame)) + (xt::display-screen-number display)))) (defmethod note-frame-deiconified ((framem xt-frame-manager) frame) - (tk::set-values (frame-shell frame) :iconic nil)) + (x11:xmapwindow (port-display (port framem)) + (tk::widget-window (frame-shell frame)))) ;;; diff --git a/tk-silica/xt-graphics.lisp b/tk-silica/xt-graphics.lisp index 365a48a0..935571e8 100644 --- a/tk-silica/xt-graphics.lisp +++ b/tk-silica/xt-graphics.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: xt-graphics.lisp,v 1.64 93/03/04 19:02:14 colin Exp $ +;; $fiHeader: xt-graphics.lisp,v 1.65 93/03/18 14:39:33 colin Exp $ (in-package :tk-silica) @@ -271,6 +271,10 @@ :none) ((eq dr +nowhere+) :nowhere) + #+ignore + ((typep dr 'clim-utils:standard-rectangle-set) + ;;-- Do something more complicated + ) (t (with-bounding-rectangle* (left top right bottom) dr (list (fix-coordinate left) (fix-coordinate top) diff --git a/tk-silica/xt-silica.lisp b/tk-silica/xt-silica.lisp index b85c2323..22618480 100644 --- a/tk-silica/xt-silica.lisp +++ b/tk-silica/xt-silica.lisp @@ -20,7 +20,7 @@ ;; 52.227-19 or DOD FAR Supplement 252.227-7013 (c) (1) (ii), as ;; applicable. ;; -;; $fiHeader: xt-silica.lisp,v 1.70 93/03/04 19:02:28 colin Exp $ +;; $fiHeader: xt-silica.lisp,v 1.71 93/03/18 14:39:45 colin Exp $ (in-package :xm-silica) @@ -1613,6 +1613,7 @@ the geometry of the children. Instead the parent has control. ")) ))) (defmethod port-move-frame ((port xt-port) frame x y) + (fix-coordinates x y) (check-type x (signed-byte 16)) (check-type y (signed-byte 16)) (tk::set-values (frame-shell frame) :x x :y y)) diff --git a/utils/lisp-utilities.lisp b/utils/lisp-utilities.lisp index 72318a36..6f8a44ec 100644 --- a/utils/lisp-utilities.lisp +++ b/utils/lisp-utilities.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-UTILS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: lisp-utilities.lisp,v 1.27 92/12/14 15:04:58 cer Exp $ +;; $fiHeader: lisp-utilities.lisp,v 1.28 92/12/16 16:51:08 cer Exp $ (in-package :clim-utils) @@ -400,7 +400,7 @@ (cons evaled-item evaled-reference))))) (defmacro catch-if (condition tag &body body) - `(catch (if ,condition ,tag '|tag for CATCH-IF false condition|) + `(catch (if ,condition ,tag '#:tag-for-catch-if) ,@body)) ;#+Genera diff --git a/utils/packages.lisp b/utils/packages.lisp index e813a21c..7df12373 100644 --- a/utils/packages.lisp +++ b/utils/packages.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CL-USER; Base: 10; Lowercase: Yes -*- -;; $fiHeader: packages.lisp,v 1.48 93/03/04 19:02:59 colin Exp $ +;; $fiHeader: packages.lisp,v 1.49 93/03/18 14:58:25 colin Exp $ (in-package #-ANSI-90 :user #+ANSI-90 :common-lisp-user) @@ -2754,6 +2754,7 @@ activity-frame-window-close activity-frame-window-select activity-quit + destroy-activity frame-activity select-activity-active-frame start-application-frame diff --git a/utils/region-arithmetic.lisp b/utils/region-arithmetic.lisp index f4081083..bb11324e 100644 --- a/utils/region-arithmetic.lisp +++ b/utils/region-arithmetic.lisp @@ -1,6 +1,6 @@ ;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-UTILS; Base: 10; Lowercase: Yes -*- -;; $fiHeader: region-arithmetic.lisp,v 1.10 92/11/20 08:47:20 cer Exp $ +;; $fiHeader: region-arithmetic.lisp,v 1.11 92/12/03 10:30:49 cer Exp $ (in-package :clim-utils) @@ -241,7 +241,12 @@ (t (ecase banding (:x-banding - (let ((result nil)) + (when (< top2 top1) + (rotatef left1 left2) + (rotatef right1 right2) + (rotatef top1 top2) + (rotatef bottom1 bottom2)) + (let ((result nil)) (when (< top1 top2) (push (make-bounding-rectangle left1 top1 right1 top2) result)) (when (> bottom2 bottom1) @@ -258,22 +263,27 @@ (push (make-bounding-rectangle left2 top right1 bottom) result)))) result)) (:y-banding - (let ((result nil)) - (when (< left1 left2) - (push (make-bounding-rectangle left1 top1 left2 bottom1) result)) - (when (> right2 right1) - (push (make-bounding-rectangle right1 top2 right2 bottom2) result)) - (when (< top1 top2) - (let ((left (max left1 left2)) - (right (min right1 right2))) - (when (> right left) - (push (make-bounding-rectangle left top1 right bottom2) result)))) - (when (> bottom1 bottom2) - (let ((left (min right1 right2)) - (right (max left1 left2))) - (when (> right left) - (push (make-bounding-rectangle left top2 right bottom1) result)))) - result)))))) + (when (< left2 left1) + (rotatef left1 left2) + (rotatef right1 right2) + (rotatef top1 top2) + (rotatef bottom1 bottom2)) + (let ((result nil)) + (when (< left1 left2) + (push (make-bounding-rectangle left1 top1 left2 bottom1) result)) + (when (> right2 right1) + (push (make-bounding-rectangle right1 top2 right2 bottom2) result)) + (when (< top1 top2) + (let ((left (max left1 left2)) + (right (min right1 right2))) + (when (> right left) + (push (make-bounding-rectangle left top1 right bottom2) result)))) + (when (> bottom1 bottom2) + (let ((left (min right1 right2)) + (right (max left1 left2))) + (when (> right left) + (push (make-bounding-rectangle left top2 right bottom1) result)))) + result)))))) ;; Returns a single bounding rectangle that represents the intersection, or NIL. (defun ltrb-intersection (left1 top1 right1 bottom1 diff --git a/xlib/xlib-funs.lisp b/xlib/xlib-funs.lisp index 8b99fa00..58dda3f1 100644 --- a/xlib/xlib-funs.lisp +++ b/xlib/xlib-funs.lisp @@ -45,7 +45,7 @@ ;; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION ;; WITH THE USE OR PERFORMANCE OF THIS OBJECT CODE. -;;; $fiHeader: xlib-funs.lisp,v 1.9 92/12/14 15:05:17 cer Exp $ +;;; $fiHeader: xlib-funs.lisp,v 1.10 93/03/04 19:03:17 colin Exp $ (in-package :x11) @@ -2003,6 +2003,11 @@ (keysym-return (:pointer keysym)) (status-in-out (:pointer xcomposestatus))) +(def-exported-foreign-function (xiconifywindow (:return-type int) (:name "XIconifyWindow")) + (dpy (:pointer display)) + (win window) + (scr int)) + #+ignore (def-exported-foreign-function (xmatchvisualinfo (:return-type int) (:name "XMatchVisualInfo")) @@ -2011,3 +2016,4 @@ (depth int) (class int) (vinfo-return (:pointer visual-info))) + -- GitLab