Hi David,

this is the bug with LayoutFrame>>#fractions:offsets: we were talking
about relative to that class comment.

In Pharo, Rectangles are constrained to have the smallest vertical value
as the top, smallest horizontal value as the left, largest vertical
value as bottom and largest horizontal value as right. So, your
rectangle 'offsets' was in fact:
        -3 @ -3 corner: 3 @ 3
which is exactly the reverse of what you intended ;)

Using the elementary distance accessors is the correct approach.

Regards,

Thierry

Le 10/01/2016 23:05, David Allouche a écrit :
I guess that is a class comment for LayoutFrame. I think this is
great improvement.

By I the way, I noticed something really strange when I was using it
in my learning project of a TicTacToe game. I started initializing a
LayoutFrame using #fractions:offsets:, but I had strange incorrect
results. I have fixed them by using the elementary distance
accessors.

Here is the relevant method in my code.

drawCircleOn: aCanvas "Draw a circle cell" | layout oval | "That
should worlk, but does not!" "offsets := (1@1 corner: (-1)@(-1))
scaleBy: lineWidth*3." "layout := LayoutFrame fractions: (0@0 corner:
1@1) offsets: offsets." layout := (0@0 corner: 1@1) asLayoutFrame.
layout topOffset: lineWidth*3; leftOffset: lineWidth*3; bottomOffset:
lineWidth*(-3); rightOffset: lineWidth*(-3). oval := layout
transform: self bounds. aCanvas frameOval: oval width: lineWidth
color: color.

I could not find an online syntax highlighter that supports
Smalltalk, so here it comes unstyled.

Should I write a test case for that, or did I try to do something
obviously incorrect?

On 9 Jan 2016, at 10:22, stepharo <[email protected]> wrote:

I define a transformation frame relative to some rectangle. I'm
basic data structure used for graphics. I represent two groups of
distances: - The fractional distance (between 0 and 1) to place the
morph in its owner's bounds - Fixed pixel offset to apply after
fractional positioning (e.g., "10 pixel right of the center of the
owner")

!! API usage It is important to understand that it is better to use
the fine grained API using elementary distances (bottomFraction:,
bottomOffset:, leftFraction: ....) than the ones (historical) using
points and rectangles (fractions:offsets:)

The reason is that the old API (fractions:offsets:) is only
interesting if you already have a rectangle and point at hand. If
you need to create new ones, then they are created for nothing
because they will be destructured to extract their information to
be feed into the layoutFrame. So please do not blindly copy and
paste code!

Example: Favor

(LayoutFrame identity leftFraction: 0; yourself);

(LayoutFrame identity leftFraction: 0.5; rightFraction: 0.95;

(LayoutFrame identity topOffset: topHeight; bottomFraction: 0;
bottomOffset: self buttonsBarHeight; leftOffset: -1; rightOffset:
1) over

(LayoutFrame fractions: (0 @ 0 corner: 1 @ 1))

For this one in particular it is better to use LayoutFrame
identity

It is faster and more readable

because you are creating for nothing a new rectangle and some
points.

!! Final point: Do not use Rectangles for specifying layoutFrames

If you happen to need to create a rectangle and use the
fractions:offsets: class methods, refrain from creating a
rectangle. The reason is that a rectangle is not 4 numbers, it
represents a space area and when you use a rectangle to represent
random numbers you end up creating rectangles with negative extents
and this is not good. In this case use Margin, Margin is a nice
class holding either one number (the same "margin" on the four
sides of a rectangle), or two number (top/bottom, left/right
margins) or 4 numbers.

!! Implementation

Instance variables: The fractional distance (between 0 and 1) to
place the morph in its owner's bounds is represented by the
following instance variables: leftFraction topFraction
rightFraction bottomFraction     <Float>


Fixed pixel offset to apply after fractional positioning (e.g., "10
pixel right of the center of the owner")  is represented by the
following instance variables: leftOffset topOffset rightOffset
bottomOffset     <Integer>






Reply via email to