自分自身を再描画する

Morph の描画をゴリゴリやっているアプリでは、自分自身を再描画したい場合がありますよね。つまり具体的に例えば時計モーフを考えたとき、 self step 内で、自身を描画したい時がありますね。その時にどうコードを書くか?ってことです。

正解は、

ClockMorph>>step

step
    time := Time now.
    self changed

とします。

(Form とかゴニョゴニョしてキャンバスを取得してw、)
自分自身に drawOn: を送ったりしてはダメですよ?w*1

changed メッセージを送って、「自分を再描画してー」とお行儀よくお願いします。
自分が描画する番がまわってくると、drawOn: メソッドが呼び出されます。

*1:お行儀悪い子はおしりペンペンの刑に処す!

FreeType2 primitive failed

Pharo 6.1 を使っていますが、プリミティブエラーが出るようになってしまって。Pharo を再インストールしたりいろいろ試しましたがまったく直りません。フォントが読み込めないようでおかしくなってしまった(以前から変な動作はしていたのですが)。
ググるとバグみたいです。Pharo 7 ではこの現象出ないので直っている感じがします。
自宅PCは 7(x64 テクニカルプレビュー版)上げようかな。6,1 のリリースから 1 年ぐらい経ちますし、そろそろ 7(x64)の正式安定版が来そうです。

[プログラミング]モーフの描画ではまる

モーフの中に自由に描画するには、

1.モーフのサブクラスを作る
2.drawOn: メソッドを書く(オーバーライドする)

なのですが、drawOn: メソッドに渡されるキャンバスの座標系がワールド座標なのですよ。モーフのオフセット(self bounds origin)座標系じゃないのですよ。モーフのサブクラスを作って、その中に普通描画したいのですから、ワールド座標系よりモーフのオフセット座標のほうが良い気がするけどね。
モーフを移動すると描画したものが消え、元の位置に戻すと描画したものが再び現れます。って動きをするんだけど、この仕様で嬉しい人いるの?
いちいちワールド座標をオフセット座標に変換(座標object translateBy: self bounds origin)しなきゃいけないし。面倒くさくてしょーがない。

サブクラスだけど、サブモーフじゃないから親モーフには追従しないよ。って事なんかな。計算式(二項メッセージ)の件と良い、Smalltalk は頑固だからきっとそうだ。計算結果を間違えようが、オブジェクト指向(メッセージパッシング)を貫くからね。頑固ジジイ並みに頑固だ!!描画内容がモーフの外になろうが、サブモーフじゃないから追従なんかしねーよ!ってのを貫いてるんだきっと。頑固ジジイめ!!

まんまとこれに騙されましたね。

頭来た

自分「近畿地方の人、台風が来るから気をつけて」

どっかのバカ「きをつけてもどうにもならんわ」

 

OK。OK。

近畿の人間は、人が心配して声をかけた事に関して、

感謝なんてできない連中なんだな。

 

近畿地方の人は、

台風に流されて

くたばっちまえ!」

 

こうコメントするのが正解でよろしいか?

 

どんだけ被害を被ろうが、義捐金なんて絶対送らないから安心してくれ。

どうなろうが知ったことか。おまえらには情けをかける気もおきん。

もう頭来た。

ソフトウェアメトリクス(初歩)

数年に一度作るかどうかという奇跡のまともアプリw「マイ○スィー○ーもどき」のメソッドあたりの平均ライン数を求めてみます。
Smalltalk は強力なリフレクションを備えるため、いとも簡単に求めることができます。
商用のメトリクスツールなんて要りません。

| aBlock |
aBlock := [ :aClass |
		| lines methods |
		lines := aClass methodDict inject: 0 into: [ :result :each |
				result + (each value sourceCode substrings: { Character cr }) size].
		methods := aClass methodDict size.
		Transcript show: aClass printString, ' : '.
		Transcript show: lines printString , ' total lines, '.
		Transcript show: methods printString, ' methods, '.
		Transcript show: (lines / methods) asFloat printString, ' lines/method.'; cr].
Transcript clear.
(RPackageOrganizer default packageNamed: 'PBE-LightsOut') definedClasses
	do: [ :each | aBlock value: each ]

これをワークスペースにコピペして Do it します。*1

結果は面倒なのでトランスクリプトに吐きます(手抜き
コードにコメントは書かないので考慮しません!
空行も入れないので無視です!
カテゴリが LightsOut のままですが気にしない。面倒くさいのでリスペクトしたいので変更しませんw
コードはすべて Pharo のフォーマット機能で整形しています。

LOCellTest : 199 total lines, 31 methods, 6.419354838709677 lines/method.
LOGame : 134 total lines, 24 methods, 5.583333333333333 lines/method.
LOCell : 132 total lines, 36 methods, 3.6666666666666665 lines/method.
LOGameTest : 244 total lines, 22 methods, 11.090909090909092 lines/method.

メソッドあたりのステップ数は 10 行にもなっていませんね。
テストコードの方がボリュームがありますね。普通こうなるのが傾向でしょう。

Smalltalk の場合、文の区切りはピリオドなので、改行で区切って意味あるのか!
というツッコミはごもっともです。ピリオド区切りで計測した場合、メソッドあたりのステップ数はもっと少なくなります。ヤバイです!

*1:'PBE-LightsOut' の部分を好きに変えれば、お好みのパッケージ配下にあるクラス群の計測ができるよ!