pharo-graphics / Bloc

Low-level UI infrastructure & framework for Pharo
MIT License
82 stars 40 forks source link

We need a way to enable or disable part of a rectangle border #534

Open plantec opened 4 months ago

plantec commented 4 months ago

As examples:

https://www.w3schools.com/cssref/tryit.php?filename=trycss_border-left-style6

https://developer.mozilla.org/en-US/docs/Web/CSS/border-left

tinchodias commented 4 months ago

Hello @plantec I played with dashes to provide a first approach to the feature, and maybe a workaround in the case you need it fast:

borderSides You may notice a glitch in top-left corner, a dot that shouldn't be there, when both top and left border sides are disabled.

Code:

extent := 200 @ 100.

" This is a visual reference, and container of the animated border element added below "
a := BlElement new.
a beOutskirtsCentered.
a clipChildren: false.
a position: extent / 2.
a border: (BlBorder paint: Color gray width: 0.5).
a size: extent.

" This is the element whose border is animated by the infinitely repeatable task "
b := BlElement new.
b beOutskirtsCentered.
b size: extent.
a addChild: b.

" This generator serves to iterate over all combinations of enabling top, right,
bottom and left sides of the rectangle. "
sidesGenerator := Generator on: [ :g |
    [ #(true false)
            permutationsWithRepetitionsOfSize: 4
            do: [ :sides | g yield: sides ] ] repeat ].

" This block answers the dash array for cairo that corresponds
to the received array of booleans. " 
dashArrayBlock := [ :topRightBottomLeftEnabled |
    Array streamContents: [ :stream |
        topRightBottomLeftEnabled
            with: { extent x. extent y. extent x. extent y }
            do: [ :isEnabled :length |
                stream << (isEnabled
                    ifTrue: [ { length. 0.0 } ]
                    ifFalse: [ { 0.0. length } ]) ] ] ].

" This infinite task regularly switches to a new combination of border sides "
a enqueueTask:
    (BlRepeatedTaskAction new
        delay: 300 milliSeconds;
        action: [
            b border:
                (BlBorder builder
                    dashArray: (dashArrayBlock value: sidesGenerator next);
                    width: 10;
                    paint: Color blue;
                    capSquare; joinMiter; "this was the best set up"
                    build) ];
        yourself).

space := a inSpace.
space extent: extent * 2.
space show
tinchodias commented 4 months ago

The cairo function that receives the dash array is https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-set-dash