Add imagemorph to rectangle - smalltalk

I have a rectangle in smalltalk like this
cell := RectangleMorph new
extent: 70#70;
position: (500 + (aPositionWidth))#(100 + (aPositionHeight));
color: lastCellColor.
I'm trying to add an image to each rectangle like this:
queen := ImageReadWriter formFromFileNamed: '9813.gif'.
cell addMorph: queen.
queen position: cell position.
It's not working how can I add an image?
Thank you in advanced

ImageReadWriter class>>formFromFileNamed: returns a Form object. A form doesn't understand #position:. You need to convert it first to a morph. Try:
queen := (ImageReadWriter formFromFileNamed: 'queen.jpg') asMorph.

Related

How to add a bounding box to a composite shape in Roassal 3?

I'm trying to draw a bounding box around a group of shapes. I get everything in the scene, but I don't know how to make the bounding box and the text get correctly aligned:
c := RSCanvas new.
text := RSGroup new.
foo := RSLabel new text: 'foo'.
bar := RSLabel new text: 'bar'.
text add: foo; add: bar.
RSVerticalLineLayout on: text.
bound := RSShapeFactory box
model: self;
border: (RSBorder new width: 1; color: Color black);
cornerRadius: 5;
width: text encompassingRectangle width + 15;
height: text encompassingRectangle height + 10.
all := RSComposite new shapes: { bound. text asShape }.
c add: all.
c # RSCanvasController.
^ c
So here is how I did it. The missing key point was to put an RSLocation.
c := RSCanvas new.
text := RSGroup new.
foo := RSLabel new text: 'foo'.
bar := RSLabel new text: 'bar'.
text add: foo; add: bar.
RSVerticalLineLayout on: text.
bound := RSShapeFactory box
model: self;
border: (RSBorder new width: 1; color: Color black);
cornerRadius: 5;
width: text encompassingRectangle width + 15;
height: text encompassingRectangle height + 10.
contents := text asShape.
all := RSComposite new shapes: { bound. contents }.
RSLocation new center; outer; stick: contents on: bound.
c add: all.
c # RSCanvasController.
^ c
here is another solution
text := 'Foo
bar'.
label := RSMultilineLabelBuilder new shapeFor: text.
box := RSBox new
fromRectangle: label encompassingRectangle;
cornerRadius: 10;
noPaint
withBorder.
box extent: box extent + 15.
all := { box . label} asGroup asShape.
canvas := RSCanvas new.
canvas add: all.
canvas # RSCanvasController
Maybe in a future we can add an extension method for strings 'hello world' asRoassalShape.

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:

How to get vertical labels with Roassal?

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

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:

Morphic: Automatically resize contained group box in a scroll pane?

Testing with Pharo 1.4 summer. I think is better to explain it using screenshots, code is below.
This is my initial state (what I'm getting now with my code):
I want the group box morph to be filled horizontally on opening, like this:
And after resizing, I want the group box morph to maintain the bounds, i.e.:
This is the code I've tried:
| s morph1 morph2 row groupBox scroller |
s := ScrollPane new.
morph1 := BorderedMorph new.
morph2 := BorderedMorph new.
row := UITheme builder newRow: {morph1 . morph2}.
groupBox := UITheme builder newGroupbox: 'Group Box Test' for: row.
groupBox
layoutFrame: (LayoutFrame fractions: (0 # 0 corner: 1 # 0.8));
vResizing: #spaceFill;
hResizing: #spaceFill;
layoutChanged.
scroller := s scroller.
scroller
addMorph: (groupBox position: 0#0)
fullFrame: (0 # 0 corner: 0.8#0.5).
s scroller color: Color white.
s
extent: 250#150;
openCenteredInWorld
The container must be a ScrollPane.
I have adapted the code of Bert to not to use the Polymorph UIBuilder, resulting in:
morph1 := Morph new.
morph2 := Morph new.
row := ScrollPane new.
row
color: Color white; borderColor: Color gray; borderWidth: 1;
layoutPolicy: ProportionalLayout new.
row scroller
addMorph: morph1 fullFrame: (LayoutFrame fractions: (0#0 corner: 1#0) offsets: (5#5 corner: -60#45));
addMorph: morph2 fullFrame: (LayoutFrame fractions: (1#0 corner: 1#0) offsets: (-50#5 corner: -5#45)).
row
extent: 250#150;
openInHand
but also doesn't work because the inner blue morphs are overlapped and not filling the specified frame. I tried many combinations using frames but nothing worked so far. Do you know what I'm missing?
Using UIBuilder you don't need to create manually a scroller. Check the following script by resizing until vertical or horizontal scroll bars appear automatically.
| dialog morphList row morph1 morph2 morph3 morph4 |
morph1 := BorderedMorph new hResizing: #spaceFill.
morph2 := BorderedMorph new.
morph3 := BorderedMorph new.
morph4 := BorderedMorph new.
row := UITheme builder newRow: {morph1 . morph2 . morph3}.
morphList := UITheme builder
newMorphListFor: (ListModel new list: {row . morph4})
list: #list
getSelected: #selectionIndex
setSelected: #selectionIndex:
help: 'This is a morph list'.
dialog := UITheme builder newWindowFor: nil title: 'titleString'.
dialog addMorph: morphList fullFrame: (LayoutFrame fractions: (0#0 corner: 1#0.5)).
dialog openInWorld
You're missing that ProportionalLayout does not use #spaceFill etc. So either use TableLayout:
morph1 := Morph new hResizing: #spaceFill.
morph2 := Morph new.
row := Morph new
color: Color white; borderColor: Color gray; borderWidth: 1;
layoutPolicy: TableLayout new;
layoutInset: 5; cellInset: 5;
listDirection: #leftToRight;
addAllMorphs: {morph1. morph2};
extent: 250#150;
openInHand
or a ProportionalLayout with offsets, which is how you can mix fixed-width and relative dimensions:
morph1 := Morph new.
morph2 := Morph new.
row := Morph new
color: Color white; borderColor: Color gray; borderWidth: 1;
layoutPolicy: ProportionalLayout new;
addMorph: morph1 fullFrame: (LayoutFrame fractions: (0#0 corner: 1#0) offsets: (5#5 corner: -60#45));
addMorph: morph2 fullFrame: (LayoutFrame fractions: (1#0 corner: 1#0) offsets: (-50#5 corner: -5#45));
extent: 250#150;
openInHand
I tried this in Squeak which does not have UITheme, so this is using Morphs directly.