Browse Source

New working version of a first demo of Jtalk and Enyo running in WebOS 3.0.2. Works in emulator.

Göran Krampe 13 years ago
parent
commit
9dcccbd1ba
4 changed files with 147 additions and 57 deletions
  1. 36 0
      webos/hellojtalk/EnyoJtalk.st
  2. 78 46
      webos/hellojtalk/HelloJtalk.st
  3. 32 10
      webos/hellojtalk/Makefile
  4. 1 1
      webos/hellojtalk/index.html

+ 36 - 0
webos/hellojtalk/EnyoJtalk.st

@@ -0,0 +1,36 @@
+"This is a base class for Jtalk Enyo UI classes. We keep track of an optional sister kind
+in Enyo and typically an instance of it, or an instance without a kind, called ui.
+
+NOTE: Inheritance of ivars seems broken, I need to use #ui: in subclass to set it"
+
+Object subclass: #EnyoFriend
+        instanceVariableNames: 'ui kind'
+        category: 'EnyoJtalk'!
+
+!EnyoFriend methodsFor: 'accessing'!
+
+ui
+	^ui
+!
+
+ui: aUI
+	ui := aUI
+!
+
+dollar
+	"Return the $ of ui for easy access to the components of the UI."
+	<return this['@ui'].$>
+!
+
+kind
+	^kind
+! !
+
+!EnyoFriend methodsFor: 'initializing'!
+initialize
+	"We make sure our JS functions can be used transparently from Jtalk,
+	at this moment we do not use it - trying to create Enyo kinds that are
+	at the same time Jtalk classes failed for me."
+	super initialize.
+	<this.allowJavaScriptCalls = true>
+! !

+ 78 - 46
webos/hellojtalk/HelloJtalk.st

@@ -1,54 +1,86 @@
-
-Dictionary subclass: #EKind
-        instanceVariableNames: ''
+EnyoFriend subclass: #HelloJtalk
+        instanceVariableNames: 'count popup'
         category: 'HelloJtalk'!
 
-Dictionary subclass: #EComponent
-        instanceVariableNames: ''
-        category: 'HelloJtalk'!
+!HelloJtalk methodsFor: 'accessing'!
+count
+	^count
+! !
 
-EKind subclass: #HelloJtalk
-        instanceVariableNames: ''
-        category: 'HelloJtalk'!
+!HelloJtalk methodsFor: 'actions'!
+buttonClicked
+	count := count + 1.
+	self dollar input setValue: (self dollar input getValue, 'You clicked the button ', count asString, ' times so far').
+
+	"Okidoki, why not throw up a popup?"
+	popup openAtCenter
+!
 
-!HelloJtalk class methodsFor: 'initializing'!
+popupSelected: value
+	"The user picked a value in the popup."
+	self dollar input setValue: (self dollar input getValue, ' ', value)
+! !
+
+!HelloJtalk methodsFor: 'initialization'!
 initialize
-        | me control button input popup myInput pageHeader arr field children |
-	pageHeader := EComponent new.
-	pageHeader at: 'kind' put: 'PageHeader'; at: 'content' put: 'JTalk Live'.
-	button := EComponent new.
-	<popup = {kind: "Popup", components: [
-    		{content: "Pick something you like"},
-    		{kind: "ListSelector", value: "Foo", items: ["Foo", "Bar", "Bot"]}]}>.
-	button at: 'kind' put: 'Button';
-		at: 'caption' put: 'Click here please';
-		at: 'onclick' put: 'buttonClick'.
-	input := EComponent new.
-	input at: 'kind' put: 'Input'.
-	me := self new.
-	arr := Array new.
-	arr add: pageHeader; add: button; add: input; add: popup.
-	me at: 'components' put: arr; 
-             at: 'name' put: 'jtalk.HelloJtalk';
-	     at: 'kind' put: 'VFlexBox';
-	     at: 'buttonClick' put: [
-		children := <this.$>.
-
-		field := children input.
-
-"This next line works fine"
-
-		<field.setValue('Yo')>.
-
-"But for some reason I can not get this next line to do anything"
-
-		field setValue: 'Yowza'.
-
-"But this line works fine, but has no arguments... ?"
-		children popup openAtCenter].
-
-	enyo kind: me.
-	enyo log: 'Done initializing.'
+	"Create Enyo stuff and hook in callback blocks calling our action methods,
+	very similar to how Seaside does it.
+	Creating the templates for component construction
+	is clearly simpler to do in js. Yes, we can use
+	method temps inside the js code and ivars are accessed
+	using this syntax:
+
+		this['@ivarname']
+
+	We can not easily mix in arbitrary Jtalk expressions in the js code, thus
+	we use method temps for holding the blocks instead of embedding the blocks
+	directly. Blocks are js functions which is really neat. And we can use:
+
+		this._jtalkMessage()
 
+	to send messages to self for embedding the result."
+
+	| props block block2 |
+	super initialize.
+	count := 0.
+
+	"Create a callback block to embed below."
+	block := [self buttonClicked].
+
+	"We need to go through a method temp (props) for doing js, just inlining it
+	after 'enyo create:' does not work so js escaping is on the statement level
+	and not on the expression level."
+	<props = {
+		kind: 'VFlexBox',
+		components: [
+			{kind: 'PageHeader', content: 'Jtalk Live'},
+ 			{kind: "RowGroup", caption: "Rock on", components: [
+				{kind: 'Input', components: [
+					{kind: 'Button', caption: 'Click me', onclick: 'ablock'}]
+				}]
+			}],
+		ablock: block}>.
+	self ui: (enyo create: props).
+
+	"If we like we can create a kind for the UI (then the props need a name EnyoHelloJtalk),
+	but we do not have to in this case so this is commented out."
+	"self kind: (enyo kind: props).
+	<this['@ui'] = new EnyoHelloJtalk()>"
+
+	"This Enyo popup instance is created and held in an ivar for later use."
+	block2 := [:sender :value :old | self popupSelected: value].
+
+	<props = {kind: "Popup", components: [
+	    		{content: "Pick something you like a lot"},
+	    		{kind: "ListSelector", onChange: "popupSelected", value: "Foo", items: ["Foo", "Bar", "Bot"]
+			}],
+		popupSelected: block2}>.
+	popup := enyo create: props
+	
 ! !
 
+!HelloJtalk class methodsFor: 'initialization'!
+initialize
+
+	enyo log: 'Class initialized'
+! !

+ 32 - 10
webos/hellojtalk/Makefile

@@ -1,16 +1,38 @@
-Program.js: HelloJtalk.st
-	../../bin/jtalkc -K -I HelloJtalk.st Program
+#
+# If you copy this file for an Enyo/Jtalk project, just
+# modify these first two lines
+# and then add .st files as you please. This Makefile
+# should pick them all up and compile into Program.js.
+#
+PACKAGE  := jtalk.hellojtalk
+VERSION  := 1.0.0
 
-jtalk.hellojtalk_1.0.0_all.ipk: Program.js
+# -E for Enyo, -O for Closure optimization of js code.
+FLAGS    := -E -O
+IPK      := $(PACKAGE)_$(VERSION)_all.ipk
+FILE     := Program
+SOURCES  := $(wildcard *.st)
+OBJECTS  := $(patsubst %.st,%.js,$(wildcard *.st))
+FILEJS   := $(FILE).js
+
+$(FILEJS): $(SOURCES)
+	../../bin/jtalkc $(FLAGS) $(SOURCES) $(FILE)
+
+$(IPK): $(FILEJS)
 	palm-package .
 
 clean:
-	rm -f Program.js HelloJtalk.js jtalk.hellojtalk_1.0.0_all.ipk
-	palm-install -r jtalk.hellojtalk
+	rm -f $(FILEJS) $(OBJECTS) $(IPK)
+	palm-install -r $(PACKAGE)
+
+install: $(IPK)
+	palm-install $(IPK)
 
-install:jtalk.hellojtalk_1.0.0_all.ipk
-	palm-install jtalk.hellojtalk_1.0.0_all.ipk
+# If you want to run it in the emulator, start the emulator first with palm-emulator
+run:    $(IPK)
+	palm-install $(IPK)
+	palm-launch $(PACKAGE)
 
-run:    jtalk.hellojtalk_1.0.0_all.ipk
-	palm-install jtalk.hellojtalk_1.0.0_all.ipk
-	palm-launch jtalk.hellojtalk
+# This should fire it up in Chromium (at least under Ubuntu)
+chromium: $(FILEJS)
+	chromium-browser --allow-file-access-from-files index.html

+ 1 - 1
webos/hellojtalk/index.html

@@ -6,7 +6,7 @@
 </head>
 <body>
 <script type="text/javascript">
-	new jtalk.HelloJtalk().renderInto(document.body);
+	smalltalk.HelloJtalk._new()._ui().renderInto(document.body);
 </script>
 </body>
 </html>