How to get vertical labels with Roassal? - smalltalk

I could not find a way to get vertical labels in a Roassal visualization. Is there a way? Or a general way to rotate elements?

The new version, Roassal2, does supports rotated labels.
In the case of the example above, now you can do:
| view |
view := RTView new.
-15 to: 10 do: [ :i |
view add: ((RTRotatedLabel new angleInDegree: -90) elementOn: 'hello world').
].
RTHorizontalLineLayout on: view elements.
view open
You will get:
Another example:
| v shape |
v := RTView new.
shape := RTRotatedLabel new.
shape angleInDegree: [ :cls | cls numberOfMethods negated / 1.5 ].
shape text: [ :cls | ' ', cls name ].
shape color: (Color black alpha: 0.2).
v addAll: (shape elementsOn: Collection withAllSubclasses).
v canvas color: Color white.
v open
You will have:
I hope it helps :-)

Currently, Roassal does not support such a feature. However you can get something close to.
| view |
view := ROView new.
-15 to: 10 do: [ :i |
view add: ((ROLabel verticalText interlineSpace: i) elementOn: 'hello world').
].
ROHorizontalLineLayout on: view elements.
view open
In Roassal 1.422

Related

Adding Text to a Smalltalk Cell

I'm doing a project in which I am adapting the Lights Out program in Pharo to a Minesweeper program, but I can't figure out how to add text to the cells so it shows up on-click like the color change does when it's "turned on". I've looked everywhere for a method for it with no dice.
Initialization method:
initialize
super initialize.
self label: ''.
self borderWidth: 4.
mineState := false.
cellValue := 0.
bounds := 0#0 corner: 32#32.
offColor := Color paleYellow.
onColor := Color paleBlue darker.
self useSquareCorners.
self turnOff
New Cell code:
newCellAt: i at: j
"Create a cell for position (i,j) and add it to my on-screen
representation at the appropriate screen position. Answer the new cell"
| c origin |
c := MFCell new.
"self labelString: 'hidden'."
origin := self innerBounds origin.
self addMorph: c.
c position: ((i - 1) * c width) # ((j - 1) * c height) + origin.
c mouseAction: [self checkMineAt: i at: j].
^ c
Maybe you are approaching your issue in too complex manner. You need to overload two selectors and you are done (not with the minesweeper, but the string on Cell).
I have taken the original code and just applied the label.
You have to just redefine turnOn and turnOff, which are in SimpleSwitchMorph which you are using, and apply a selector label: which can be found in super class SimpleButtonMorph. You can even have the same logic as the in the superclass.
In LOCell you can do (create a new protocol switching for them):
turnOn
super turnOn.
self label: 'X'
turnOff
super turnOff.
self label: ''
When running the example now, the X String will be added to the cells that are turned on.
It will look like this:
The protocol:
The morph now:

Can a block in Smalltalk be run by itself?

I know blocks can be passed and used in that way.
But is there any way to call a block, just by having a block? Something like this?
aBlock := [ ... ].
aBlock run.
I tried searching for the BlockClosure class in the System browser, but couldn't find it.
Yes! And in fact, you can do pretty interesting things with them, like activating them within themselves. For example, this block computes factorial recursively calling itself:
factorialBlock := [:n |
n <= 1
ifTrue: [n]
ifFalse: [n * (factorialBlock value: n - 1)]
]
and to try it:
factorialBlock value: 5
That would not be an example of a very good coding practice, but it is of the power of block closures!
Let's add that besides value, if your block has arguments, you can also use
[:f | <do something with f>] value: a
where f is a formal argument (an unbound variable name) and a is an actual object that will bind to f when #value: is sent.
For two arguments use value:value: and for many valueWithArguments:, which receives an Array.
Examples
[:x | x squared - 1] value: 3
-> 3 squared - 1 (i.e., 8)
[:x :y | x + 2 / (y - 4)] value: 2 value: 0
-> 2 + 2 / (0 - 4) (i.e., -1)
Exercise
What's the result of evaluating the following?:
block := [:x | x value: 2].
block value: [:y | y + 1]
Yes it can. Also, you send the message 'value' to it to evaluate the block, not 'run'. In fact, you do not have to assign it to a variable. You can just do this:
[ ... ] value.
Check this one:
Lambda Calculus in Pharo
Yes, the Y Combinator is useful in normal programs
https://medium.com/concerning-pharo/lambda-calculus-in-pharo-a4a571869594#.2a78xp31s
From the article:
ycombinator := [ :f |
[ :g | g value: g ] value: [ :g |
f value: [ :x |
(g value: g) value: x ] ] ]
The force is strong in this one.

Make edges not clickable in Roassal visualization from within a Glamour browser

I draw a dynamic callgraph with Roassal from within a Glamour browser in Pharo 2.0.
By default not only the nodes, but also the edges are clickable.
As i have no further information to display for the edges, i want them not to be clickable. How do i remove the "clickability"?
That's how i draw the callgraph from within a Glamour browser:
methodsUnderTestAsCallGraphIn: constructor
constructor roassal
painting: [ :view :testFailure |
view shape rectangle
size: 30;
fillColor: ThreeColorLinearNormalizer new.
view nodes: (tests methodsUnderTest: testFailure).
view shape arrowedLine.
view edges: (tests methodsUnderTest: testFailure) from: #yourself toAll: #outgoingCalls.
view treeLayout ];
title: 'Callgraph of methods under test'
I think GLMRoassalPresentation>>renderOn: is responsible for adding the "clickability":
[...]
self shouldPopulateSelection ifTrue: [
aView raw allElementsDo: [:each |
each on: ROMouseClick do: [:event | self selection: each model ]] ].
[...]
I want to to keep this behaviour for the nodes, but not for the edges.
It helps to have a self contained example to clarify the behaviour you want, so I've re-framed your question.
With the two commented-out lines , I guess is the behaviour you don't want. Does uncommmenting those two lines provide the behaviour you want?
browser := GLMTabulator new.
browser column: #myRoassal ; column: #mySelection.
browser transmit
to: #myRoassal ;
andShow:
[ : aGLMPresentation |
aGLMPresentation roassal
painting:
[ : view : numbers | |edges|
view shape rectangle ; withText ; size: 30.
view nodes: numbers.
view interaction noPopup.
view edges: numbers from: [ :x | x / 2] to: [ :x | x ].
" view edges do: [ :edge | edge model:#doNotSelectMe ]."
view treeLayout.
].
].
browser transmit
to: #mySelection ;
from: #myRoassal ;
" when: [ :selection | selection ~= #doNotSelectMe ] ;"
andShow:
[ : aGLMPresentation |
aGLMPresentation text
display: [ : selectedItem | selectedItem asString ]
].
browser openOn: (1 to: 10).
Unfortunately, this is not possible at the moment because the clicking is hardcoded in GLMRoassalPresentation. However, you are right that we should find a solution, so I opened an issue:
http://code.google.com/p/moose-technology/issues/detail?id=981
I am not sure what you mean by "clickability". You have no interaction defined, so the default interaction is a simple popup. If you want to remove the popup, then just insert a "view interaction noPopup". Try this in a fresh Roassal easel:
view shape rectangle size: 40.
view nodes: #(1 2).
view interaction noPopup.
view edgesFrom: 1 to: 2.

Progress/seek bar for Pharo morphic

I'm searching for a visual component such as video progress bar / seek bar or something like this:
are there something like it ?
From Benjamin van Ryseghem
| slider |
slider := SliderModel new.
slider
min: 0;
max: 100;
whenValueChangedDo: [:value | slider label: value asString ].
slider openWithSpec
You could use a PluggableSliderMorph for this purpose:

How to create dynamic panel layout for this logo creation wizard?

I want to create a wizard for the logo badge below with 3 parameters. I can make the title dynamic but for image and gradient it's hardcoded because I can't see how to make them dynamic. Code follows after pictures:
alt text http://reboltutorial.com/bugs/wizard1.png
alt text http://reboltutorial.com/bugs/wizard2.png
custom-styles: stylize [
lab: label 60x20 right bold middle font-size 11
btn: button 64x20 font-size 11 edge [size: 1x1]
fld: field 200x20 font-size 11 middle edge [size: 1x1]
inf: info font-size 11 middle edge [size: 1x1]
ari: field wrap font-size 11 edge [size: 1x1] with [flags: [field tabbed]]
]
panel1: layout/size [
origin 0 space 2x2 across
styles custom-styles
h3 "Parameters" font-size 14 return
lab "Title" fld_title: fld "EXPERIMENT" return
lab "Logo" fld_logo: fld "http://www.rebol.com/graphics/reb-logo.gif" return
lab "Gradient" fld_gradient: fld "5 55 5 10 10 71.0.6 30.10.10 71.0.6"
] 278x170
panel2: layout/size [
;layout (window client area) size is 278x170 at the end of the spec block
at 0x0 ;put the banner on the top left corner
box 278x170 effect [ ; default box face size is 100x100
draw [
anti-alias on
line-width 2.5 ; number of pixels in width of the border
pen black ; color of the edge of the next draw element
fill-pen radial 100x50 5 55 5 10 10 71.0.6 30.10.10 71.0.6
; the draw element
box ; another box drawn as an effect
15 ; size of rounding in pixels
0x0 ; upper left corner
278x170 ; lower right corner
]
]
pad 30x-150
Text fld_title/text font [name: "Impact" size: 24 color: white]
image http://www.rebol.com/graphics/reb-logo.gif
] 278x170
main: layout [
vh2 "Logo Badge Wizard"
guide
pad 20
button "Parameters" [panels/pane: panel1 show panels ]
button "Rendering" [show panel2 panels/pane: panel2 show panels]
button "Quit" [Unview]
return
box 2x170 maroon
return
panels: box 278x170
]
panel1/offset: 0x0
panel2/offset: 0x0
panels/pane: panel1
view main
Make the block for the 2nd layout a template.
Put the variables you want there and surround with ( )
When rendering, do a copy/deep to make a template copy, then compose/deep to replace the variables as taken from the parameters screen, create the layout from your copy of the template and set the pane to the new layout.