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>
>