Adding Text to a Smalltalk Cell - smalltalk

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:

Related

Add imagemorph to rectangle

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.

How to remove an attachMorph of HandleMorph in smalltalk from self

i need your help
i am creating a line from a spesific location to mouse location with this code.
after click i am trying to remove this line but i have no idea how
please help me remove the live after click what should i change ?
stk:= (LineMorph from: 100#100 to: 1300#1300 color: Color red width: 2) openInWorld.
handle := HandleMorph new forEachPointDo: [:newPoint | stk setVertices: {whiteBallinHole position. (newPoint-(10#10)). }.
stk on: #mouseDown send: #value: to:[:evt|
evt redButtonPressed ifTrue:[ self handlesMouseDown: evt.
"DELETE THE STICK AFTER MOUSE CLICK THIS DOSNT WORK PLEASE HELP"
stk color: Color transparent.
stk delete.
""
].
].
].
" (self currentHand attachMorph: handle)."
" self currentHand addMorph:handle. "
self currentHand attachMorph:handle.
The code is a bit of a mess. One thing that is out of place is
self handlesMouseDown: evt.
That is supposed to return true if you want to receive mouseDown: messages.
In a workspace, that self does not exist. And the result is never used. Just delete it. The resulting code would be something like
whiteBallinHole := CircleMorph new openInWorld .
stk := (LineMorph
from: 100#100 to: 1300#1300
color: Color red
width: 4) openInWorld.
handle := HandleMorph new forEachPointDo: [ :newPoint |
stk setVertices: {whiteBallinHole center. (newPoint-(10#10)). }.
stk on: #mouseDown send: #value: to: [:evt|
evt redButtonPressed ifTrue:[
stk color: Color transparent.
stk delete]]].
self currentHand attachMorph: handle.

Smalltalk Input/Output

I am having trouble regarding Smalltalk. I am attempting to populate an array with the numbers that are read from the file, but it doesn't seem to work. I've tried numerous options and I was hoping someone would explain to me what I'm doing wrong.
Object subclass: #MyStack
instanceVariableNames:'anArray aStack'
classVariableNames:''
poolDictionaries:''
!
MyStack class comment: 'Creates a Stack Class.'
!
!
MyStack methodsFor: 'initialize Stack'
!
new "instance creation"
^ super new.
!
init "initialization"
anArray := Array new: 32.
aStack := 0.
! !
!MyStack methodsFor: 'methods for stacks' !
pop "Removes the top entry from the stack"
| item |
item := anArray at: aStack.
aStack := aStack - 1.
!
push: x "Pushes a new entry onto the stack"
aStack := aStack + 1.
anArray at:aStack put:x.
!
top "Returns the current top of the stack"
^anArray at: aStack.
!
empty "True if the stack is empty"
^aStack = 0.
!
full "True if the stack is full"
^aStack = 32.
!
printOn: aStream "Prints entire stack one entry per line, starting the top entry"
aStream show: 'Stack:'.
aStack to:1 by:-1 do:[:i |(anArray at:i) printOn:aStream. ].
aStream show: ''
! !
"----------------------------------------------------------------------------------"
Object subclass: #IOExample
instanceVariableNames: 'input output'
classVariableNames: ''
poolDictionaries: ''
!
IOExample class comment: '
basic I/O.
'
!
!
IOExample methodsFor: 'initialize'
!
new
^ super new.
!
init
[ input := FileSelectionBrowser open asFilename readStream. ]
on: Error
do: [ :exception |
Dialog warn: 'Unable to open file'.
exception retry.
].
[ output := FileSelectionBrowser open asFilename writeStream. ]
on: Error
do: [ :exception |
Dialog warn: 'Unable to open file'.
exception retry.
].
! !
!
IOExample methodsFor: 'copy input to output turning :: into :'
!
copy
| data lookAhead theStack myStack|
[ input atEnd ] whileFalse: [
data := input next.
(data isKindOf: Integer)
ifTrue: [
(input atEnd) ifFalse: [
"myStack push: data."
lookAhead = input peek.
(lookAhead asCharacter isDigit)
ifTrue: [
]
].
].
output show: myStack.
].
input close.
output close.
! !
Did you try to run this code? If you did, I'm surprised you didn't get a compilation warning due to #2 below.
There are a number of problems in #copy (besides the fact that I don't understand exactly what it's trying to do)...
First you seems to expect the data to be numbers: data isKindOf: Integer. But then later you treat it as a stream of Characters: lookAhead asCharacter isDigit. If the first condition is true to get you past that point, the second one never can be, as you would've matched [0-9], which aren't ASCII values for digits.
lookAhead = input peek. Here you're comparing uninitialized lookAhead (nil) with the peeked value, and then throwing away the result. I assume you meant lookAhead := input peek.
Then there is the empty inner condition ifTrue: [ ]. What are you trying to do there?
Then there's the odd protocol name, 'copy input to output turning :: into :'. What does that mean, and what does that have to do with copying numbers between streams?
Justin, let me try to help you with the class MyStack and defer to another answer any comments on your example.
I've divided your code into fragments and appended my comments.
Fragment A:
Object subclass: #MyStack
instanceVariableNames:'anArray aStack'
classVariableNames:''
poolDictionaries:''
Comments for A:
A Smalltalker would have used instance variable names without indeterminate articles a or an
Object subclass: #MyStack
instanceVariableNames:'array stack'
classVariableNames:''
poolDictionaries:''
Fragment B:
MyStack class comment: 'Creates a Stack Class.'
Comments for B:
This is weird. I would have expected this instead (with no class):
MyStack comment: 'Creates a Stack Class.'
Fragment C:
MyStack methodsFor: 'initialize Stack'
new "instance creation"
^ super new.
Comments for C:*
This code puts new on the instance side of the class, which makes no sense because you usually send new to the class rather than its instances. The correct form requires adding class:
MyStack class methodsFor: 'initialize Stack'
new
^super new.
You forgot to send the initialization method (however, see Fragment D below)
new
^super new init.
Fragment D:
init "initialization"
anArray := Array new: 32.
aStack := 0.
Comments for D:
In Smalltalk people use the selector initialize so it can send super first
initialize
super initialize.
array := Array new: 32.
stack := 0.
Note that this change would require also writing new as
new
^super new initialize.
However, if your dialect already sends the initialize method by default, you should remove the implementation of new from your class.
Fragment E:
pop "Removes the top entry from the stack"
| item |
item := anArray at: aStack.
aStack := aStack - 1.
Comments for E:
You forgot to answer the item just popped out
pop
| item |
item := array at: stack.
stack := stack - 1.
^item
Fragment F:
push: x "Pushes a new entry onto the stack"
aStack := aStack + 1.
anArray at:aStack put:x.
Comments for F:
This is ok. Note however that the stack will refuse to push any item beyond the limit of 32.
push: x
stack := stack + 1.
array at: stack put: x.
Fragment G:
top "Returns the current top of the stack"
^anArray at: aStack.
empty "True if the stack is empty"
^aStack = 0.
full "True if the stack is full"
^aStack = 32.
Comments for G:
These are ok too. However, a more appropraite name for empty would have been isEmpty because all collections understand this polymorphic message. Similarly, the recommended selector for full would be isFull:
top
^array at: aStack.
isEmpty
^stack = 0.
isFull
^stack = 32.
Note also that isFull repeats the magic constant 32, which you used in the initialization code. That's not a good idea because if you change your mind in the future and decide to change 32 with, say, 64 you will have to modify two methods an not just one. You can eliminate this duplication in this way
isFull
^stack = array size.
Fragment H:
printOn: aStream
"Prints entire stack one entry per line, starting the top entry"
aStream show: 'Stack:'.
aStack to:1 by:-1 do:[:i |(anArray at:i) printOn:aStream. ].
aStream show: ''
Comments for H:
The last line of this code is superfluous and I would get rid of it. However, you may want to separate every item from the next with a space
printOn: aStream
stream show: 'Stack:'.
stack to: 1 by: -1 do:[:i |
aStream space.
(array at: i) printOn: aStream].

Cincom Visualworks Smalltalk - Class Methods Initialization

Apologies for the newbie question, but I failed to figure this despite of long try.
I created a matrix class using NewClass feature in Cincom Visualworks.
Smalltalk.Core defineClass: #Matrix
superclass: #{Core.Object}
indexedType: #none
private: false
instanceVariableNames: 'rowCount columnCount cellValues '
classInstanceVariableNames: ''
imports: ''
category: ''
Added the following class method:
withRowCount: rowCount withColumnCount: columnCount withCellValues: cellValues
^self new rowCount: rowCount columnCount: columnCount cellValues: cellValues.
Added the following accessor methods:
cellValues
^cellValues
cellValues: anObject
cellValues := anObject
columnCount
^columnCount
columnCount: anObject
columnCount := anObject
rowCount
^rowCount
rowCount: anObject
rowCount := anObject
I have this code in workspace:
|myMatrix|
myMatrix := Matrix rowCount: 5 columnCount: 5 cellValues: 5.
Transcript show: (myMatrix rowCount).
But compiler says that message undefined.
I guess my class method is not working as expected.
Can someone please point out where I am going wrong?
First: Matrix doesn't have a rowCount:columnCount:cellValues: method. You probably meant Matrix withRowCount: 5 withColumnCount: 5 withCellValues: 5.
Second, I'm thinking methods return the value of the last expression. So chaining methods doesn't work quite like that. (And even if it did, that still looks like one message.)
Your class method should probably read like
withRowCount: rowCount withColumnCount: columnCount withCellValues: cellValues
| newMatrix |
newMatrix := self new.
newMatrix rowCount: rowCount;
columnCount: columnCount;
cellValues: cellValues.
^newMatrix
The ; breaks up the messages and tells Smalltalk to send all three to newMatrix.
Then you can use it like
|myMatrix|
myMatrix := Matrix withRowCount: 5 withColumnCount: 5 withCellValues: 5.
Transcript show: (myMatrix rowCount).

Check how close UILabels are to each other

I am trying to make a game which has a jumbled up algebra equation. I have assigned an outlet to each component of the equation. For example, if the equation was:
x2 + y = 2(a+b)
Then x2 (which is x squared), +, y, = and 2(a+b) would all be its own outlet. But the equation is going to be jumbled up and I want the user to move the label outlets to the correct order. I have enabled touchesMoved, but my problem lies in checking if the equation is in the correct order. I would wrap the code into an IBAction button action, but how do I analyze the text? Would I check for the offset between each label? Is there an easy way/API to do this? Thanks!
Assuming your labels are called xLabel,plusLabel, yLabel, equalsLabel, and abLabel, you could do something like this:
NSUInteger xLeftBorder = CGRectGetMinX(xLabel.frame);
NSUInteger plusLeftBorder = CGRectGetMinX(plusLabel.frame);
NSUInteger yLeftBorder = CGRectGetMinX(yLabel.frame);
NSUInteger equalsLeftBorder = CGRectGetMinX(equalsLabel.frame);
NSUInteger abLeftBorder = CGRectGetMinX(abLabel.frame);
if(xLeftBorder < plusLeftBorder && plusLeftBorder < yLeftBorder && yLeftBorder < equalsLeftBorder && equalsLeftBorder < abLeftBorder){
//Correct!
}
else{
//Incorrect
}
This is kind of clumsy, but it works. An even better way to do it would be to put this in a function with each parameter being a label to check. For example:
bool isCorrect = [self checkIf:xLabel isLessThan: plusLabel isLessThan: yLabel isLessThan:equalsLabel isLessThan:abLabel];
This is assuming the function you write returns a bool.
Hope this helped!