Skip to content
This repository has been archived by the owner on Mar 13, 2023. It is now read-only.

Medium transformations do not work well with presentation output records #658

Closed
scymtym opened this issue Jan 3, 2019 · 2 comments
Closed

Comments

@scymtym
Copy link
Collaborator

scymtym commented Jan 3, 2019

In the following example, the rectangles and presentations are initially painted surprisingly (all presentations in the first rectangle). Forcing a redisplay places each presentation in "its" rectangles. Forcing another repaint, e.g. by changing the window size, goes back to the initial state.

(cl:defpackage #:presentation-test
  (:use
   #:clim-lisp))

(cl:in-package #:presentation-test)

(clim:define-presentation-type presentation ())

(clim:define-presentation-method clim:present ((object t)
                                               (type   presentation)
                                               (stream t)
                                               (view   t)
                                               &key)
  (clim:draw-rectangle* stream 0 0 100 20 :filled nil)

  (clim:present #1=5 (clim:presentation-type-of #1#) :stream stream :view view)
  (write-string "-" stream)
  (clim:present #2=6 (clim:presentation-type-of #2#) :stream stream :view view))

(clim:define-application-frame test ()
  ()
  (:panes
   (application :application
                :scroll-bars      nil
                :display-function (lambda (frame pane)
                                    (clim:present :foo 'presentation :stream pane)
                                    (clim:with-translation (pane 100 100)
                                      (clim:present :foo 'presentation :stream pane))
                                    (clim:with-translation (pane 100 200)
                                      (clim:present :foo 'presentation :stream pane))))
   (interactor :interactor))
  (:layouts (:default
             (clim:vertically ()
               (clim:scrolling () application)
               interactor))))

(bt:make-thread (lambda () (clim:run-frame-top-level (clim:make-application-frame 'test))))
@dkochmanski
Copy link
Member

The problem comes from the fact that all default presentation methods present use stream protocol primitives (princ, prin1, write-string and such). That is understandable because default view on which they are specialized is textual-view, so they can't assume graphics output (and transformations) are available. In particular that means that the stream cursor position is used as defined in stream protocol (so the text is printed at the current cursor position). That's why during display they are placed at left top corner. This is (arguably) correct.

Later behavior is a result of a bug. When we record text output medium transformation is recorded too, but the soes calls draw-text* directly on medium (and not on a stream) and separately adds the output record (in order to concatenate consecutive text output records). So during display we draw without transformation, but replay is triggered with the transformation applied.

When you resize the window (make it bigger) you in fact trigger redisplay, that's why you observe the behavior repeating. It is not repaint but redisplay.

I've identified two bugs:

  • one is that we do such underhanded draw on a medium (instead of a stream)
  • another one is related to subsequent write-output (I'm still not sure what's going on)
  • I think that there is something fishy going on with recording transformation (remotely related to this issue)

Since I don't want to miss the second issue (which may root deeper and may reveal another can of worms), I'm not making a PR with fix yet. You may compile this function to trigger the "arguably correct" behavior (that is to have a consistent behavior intended for textual-view):

(in-package climi)
(defmethod stream-write-output ((stream standard-extended-output-stream)
                                line string-width
                                &optional (start 0) end)
  (declare (ignore string-width))
  (with-identity-transformation (stream)
    (with-slots (baseline vspace) stream
      (multiple-value-bind (cx cy) (stream-cursor-position stream)
        (draw-text* stream line
                    cx (+ cy baseline)
                    :transformation +identity-transformation+
                    :start start :end end)))))

I'll get to this (eventually). Here comes a potential project idea: define default presentation methods for a graphical-view. Also finding out if it is possible to marry text stream protocol with transformations is a fine idea.

dkochmanski added a commit that referenced this issue Jan 4, 2019
Transformation should not be captured because this is a stream text interface -
it should always write at the cursor position. That caused non-uniform behavior
between display and replay.

Provide informative comment about reasons why we wrap thing in
with-identity-transformation and why we draw-text* on sheet's medium.. Fixes
inconsistent behavior in #658.
dkochmanski added a commit that referenced this issue Jan 6, 2019
Transformation should not be captured because this is a stream text interface -
it should always write at the cursor position. That caused non-uniform behavior
between display and replay.

Provide informative comment about reasons why we wrap thing in
with-identity-transformation and why we draw-text* on sheet's medium.. Fixes
inconsistent behavior in #658.
dkochmanski added a commit that referenced this issue Jan 7, 2019
Transformation should not be captured because this is a stream text interface -
it should always write at the cursor position. That caused non-uniform behavior
between display and replay.

Provide informative comment about reasons why we wrap thing in
with-identity-transformation and why we draw-text* on sheet's medium.. Fixes
inconsistent behavior in #658.
dkochmanski added a commit that referenced this issue Jan 7, 2019
Transformation should not be captured because this is a stream text interface -
it should always write at the cursor position. That caused non-uniform behavior
between display and replay. Fixes inconsistent behavior in #658.
dkochmanski added a commit that referenced this issue Jan 8, 2019
Transformation should not be captured because this is a stream text interface -
it should always write at the cursor position. That caused non-uniform behavior
between display and replay. Fixes inconsistent behavior in #658.
josrr added a commit to josrr/McCLIM that referenced this issue Jan 12, 2019
…ed in issue McCLIM#580

option-pane to choose the layout

examples: draggable-graph: feedback for edges and simplifications (McCLIM#662)

Also add {TO,FROM}-NODE readers to graph formatting.

Button to run the test in a separate application-frame

text-size: ensure that character is a valid argument

Fixes McCLIM#663.

normalize-font-size: handle numeric default-text-size gracefully

Previous version could return NIL if the value was numeric! that was clearly
bogus. Now we handle it just fine.

climb:parse-text-style*: add a new utility

parse-text-style* returns complete text-style which doesn't have NIL components.

text-style-to-font: be more resilient to incomplete text-styles

We "merge" text-style with default-text-style to avoid situation, when it is not
complete. We achieve this with a new macro parse-text-style*. Fixes McCLIM#624.

This is not a real merge, because we do not meld :italic and :bold fonts. Also
function is cheaper to execute.

In DESIGN-INK, use consistent rounding for coordinates (McCLIM#661)

Previously, ROUND was used to ensure that the arguments to DESIGN-INK
were integers. This caused a problem in some situations when the
coordinates have a fractional part of 0.5. In such cases, ROUND will
either round up or down depending on whether the integer part is odd
or even. Fixes McCLIM#641.

panes to customize the separate application-frame

Resolve regression in CONVERT-TO-GESTURE (McCLIM#669)

The change 104b315 introduced a
problem where modifier keys could not be used together with return.
This fix restores the old behaviour.

Fixes McCLIM#668

Menu to change the layout

revert change of application-pane to interactor-pane in the description-pane

now is possible to use custom server-port

parse-text-style*: assure that size is always normalized

*default-text-style* may have size being keyword. We want to normalize it, so we
have too go through prase-text-style* even when we know text-style is complete.

Fixes McCLIM#671.

'#\r' and '#\space' to redisplay and repaint the application-pane

cosmetic: fix a typo in manual files (texinfo and latex)

Closes McCLIM#677.

stream-write-output: prevent capturing transformation

Transformation should not be captured because this is a stream text interface -
it should always write at the cursor position. That caused non-uniform behavior
between display and replay. Fixes inconsistent behavior in McCLIM#658.

examples: add seos-baseline regression test

cosmetic: change indentation and replace some operators

To be exact: use when-let and maxf where appropriate.

seos: don't call (setf stream-cursor-position) in seos-write-string

This method is explicitly specified to call close-text-output-record. That
effectively prevented us from aligning baseline when outputs were replayed as
described in McCLIM#667.

standard-output-recording-stream: don't draw text eagerly

To maintain a baseline (see 15.3 The Text Cursor) we need to see into the future
about other baselines on the line. While this is not possible for streams which
are not recorded it can be done for recording streams.

It is important to remember that we can't immedietely draw text but rather wait
for line completion (or to be more exact, for output record completion which is
finialized with STREAM-CLOSE-TEXT-OUTPUT-RECORD. Otherwise during initial
display result is different on a screen than after repaint.

Additionally we avoid reaching back to STREAM-WRITE-OUTPUT from
REPLAY-OUTPUT-RECORD to skip unnecessary roundtrip (and possible recursion).

CLIM-STREAM-PANE inheritance order is changed: STANDARD-OUTPUT-RECORDING-STREAM
methods take precedence over STANDARD-EXTENDED-OUTPUT-STREAM
ones. OUTPUT-RECORDING-STREAMs abstraction-wise are above
EXTENDED-OUTPUT-STREAMs. This also allows us to drop :around method in favor of
primary method on STREAM-WRITE-OUTPUT.

Fixes McCLIM#667.

clim-stream-pane: ensure call to finish-output on redisplay

Last text-output-record may not be closed yet what leads to a missing line
during redisplay. This call ensures that all stream operations are wrapped up
before we finish redisplay.

Now is possible to navigate the test list with arrow keys

commands with keystrokes instead of handle-event methods to navigate the lists.

deleted space-requeriments options in the layout panes

Freetype: Don't try to parse text styles in list form (McCLIM#683)

The method TEXT-STYLE-TO-FONT can be called with a list as argument.
This specifically happened in the "German towns" demo when clicking on
a town on the map.

This changes the method so that it only specialises on
STANDARD-TEXT-STYLE.

'Run in backend' functionality

added the category to the output filenames of the pdf, png and ps backends

basic benchmarking functionality

added score calculation (operation/s) to benchmark

run benchmark only when a test is selected

return error to simple-error

print a message in the description pane when writing a file

changed 'Writing' instead of 'Printing'

deleted old define-drawing-test%

deleted commented code and unnecessary also blank lines

deleted unnecessary display-app-pane function

display-backend-output record its output according to the recording option

added the category to the messages printed in case of skipping a test while printing

moved up the benchmark pane

added the recording option status to the benchmark message

added category and name to the score message
@dkochmanski
Copy link
Member

Now things are consistent between redisplay and repaint (so there is no transformation issue in draw-text). To ensure, that output records are placed as desired, either use draw-text* as means to present the object (in that case it will be a subject of a transformation), or change the cursor position to match the translation, like here:

(cl:defpackage #:presentation-test
  (:use
   #:clim-lisp))

(cl:in-package #:presentation-test)

(clim:define-presentation-type presentation ())

(clim:define-presentation-method clim:present ((object t)
                                               (type   presentation)
                                               (stream t)
                                               (view   t)
                                               &key)
  (clim:draw-rectangle* stream 0 0 100 20 :filled nil)
  (clim:present #1=5 (clim:presentation-type-of #1#) :stream stream :view view)
  (write-string "-" stream)
  (clim:present #2=6 (clim:presentation-type-of #2#) :stream stream :view view))

(clim:define-application-frame test ()
  ()
  (:panes
   (application :application
                :display-time :command-loop
                :scroll-bars      nil
                :display-function (lambda (frame pane)
                                    (clim:present :foo 'presentation :stream pane)
                                    (setf (clim:stream-cursor-position pane)
                                          (values 100 100))
                                    (clim:with-translation (pane 100 100)
                                      (clim:present :foo 'presentation :stream pane))
                                    (setf (clim:stream-cursor-position pane)
                                          (values 100 200))
                                    (clim:with-translation (pane 100 200)
                                      (clim:present :foo 'presentation :stream pane))))
   (interactor :interactor))
  (:layouts (:default
             (clim:vertically ()
               (clim:scrolling () application)
               interactor))))

(define-test-command (com-redisplay :name t) ())

(bt:make-thread (lambda () (clim:run-frame-top-level (clim:make-application-frame 'test))))

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants