Browse Source

Extract trait TSilkBuilder.

Both instance-side and class-side Silk use it.
Herby Vojčík 4 years ago
parent
commit
62510df349
2 changed files with 99 additions and 95 deletions
  1. 71 78
      src/Silk.js
  2. 28 17
      src/Silk.st

+ 71 - 78
src/Silk.js

@@ -10,67 +10,52 @@ $globals.Silk.comment="I am subclass of `Domite` with more convenient high-level
 //>>excludeEnd("ide");
 $core.addMethod(
 $core.method({
-selector: "doesNotUnderstand:",
-protocol: "writing",
-fn: function (aMessage){
+selector: "namespace",
+protocol: "accessing",
+fn: function (){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1,$2,$receiver;
-$1=$recv($self._class())._tryMakeDnuElement_in_(aMessage,self);
-if(($receiver = $1) == null || $receiver.a$nil){
-$2=(
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = true,
-//>>excludeEnd("ctx");
-($globals.Silk.superclass||$boot.nilAsClass).fn.prototype._doesNotUnderstand_.apply($self, [aMessage]));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = false;
-//>>excludeEnd("ctx");;
-return $2;
-} else {
-var newElement;
-newElement=$receiver;
-$self.__lt_lt(newElement);
-return newElement;
-}
-return self;
+return $recv($self._element())._namespaceURI();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"doesNotUnderstand:",{aMessage:aMessage})});
+}, function($ctx1) {$ctx1.fill(self,"namespace",{})});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aMessage"],
-source: "doesNotUnderstand: aMessage\x0a\x09\x22`aSilk DIV` creates a div element and inserts it.\x0a\x09`aSilk DIV: anObject` creates a div element, inserts it\x0a\x09and puts contents in it\x22\x0a\x09(self class tryMakeDnuElement: aMessage in: self)\x0a\x09\x09ifNil: [ ^ super doesNotUnderstand: aMessage ]\x0a\x09\x09ifNotNil: [ :newElement | self << newElement. ^ newElement ]",
+args: [],
+source: "namespace\x0a\x09\x22<String>\x0a\x09XML namespace for elements: html.\x0a\x09The default for all virtual Silk tag messages\x22\x0a\x09\x0a\x09^ self element namespaceURI",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["ifNil:ifNotNil:", "tryMakeDnuElement:in:", "class", "doesNotUnderstand:", "<<"]
+messageSends: ["namespaceURI", "element"]
 }),
 $globals.Silk);
 
 $core.addMethod(
 $core.method({
-selector: "namespace",
-protocol: "accessing",
-fn: function (){
+selector: "newElement:xmlns:",
+protocol: "writing",
+fn: function (aString,anotherString){
 var self=this,$self=this;
+var el;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-return $recv($self._element())._namespaceURI();
+el=$recv($self._class())._newElement_xmlns_(aString,anotherString);
+$self.__lt_lt(el);
+return el;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"namespace",{})});
+}, function($ctx1) {$ctx1.fill(self,"newElement:xmlns:",{aString:aString,anotherString:anotherString,el:el})});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "namespace\x0a\x09\x22<String>\x0a\x09XML namespace for elements: html.\x0a\x09The default for all virtual Silk tag messages\x22\x0a\x09\x0a\x09^ self element namespaceURI",
+args: ["aString", "anotherString"],
+source: "newElement: aString xmlns: anotherString\x0a\x09| el |\x0a\x09\x0a\x09el := self class newElement: aString xmlns: anotherString.\x0a\x09self << el.\x0a\x09^ el",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["namespaceURI", "element"]
+messageSends: ["newElement:xmlns:", "class", "<<"]
 }),
 $globals.Silk);
 
@@ -113,43 +98,6 @@ messageSends: ["ifNil:", "renderOnSilk:", "nextPut:"]
 $globals.Silk);
 
 
-$core.addMethod(
-$core.method({
-selector: "doesNotUnderstand:",
-protocol: "message handling",
-fn: function (aMessage){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1,$receiver;
-$1=$self._tryMakeDnuElement_in_(aMessage,self);
-if(($receiver = $1) == null || $receiver.a$nil){
-return (
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = true,
-//>>excludeEnd("ctx");
-($globals.Silk.a$cls.superclass||$boot.nilAsClass).fn.prototype._doesNotUnderstand_.apply($self, [aMessage]));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = false;
-//>>excludeEnd("ctx");;
-} else {
-return $1;
-}
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"doesNotUnderstand:",{aMessage:aMessage})});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aMessage"],
-source: "doesNotUnderstand: aMessage\x0a\x09\x22`Silk DIV` creates a div element.\x0a\x09`Silk DIV: anObject` creates a div element and puts contents in it\x22\x0a\x09^ (self tryMakeDnuElement: aMessage in: self)\x0a\x09\x09ifNil: [ super doesNotUnderstand: aMessage ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-pragmas: [],
-messageSends: ["ifNil:", "tryMakeDnuElement:in:", "doesNotUnderstand:"]
-}),
-$globals.Silk.a$cls);
-
 $core.addMethod(
 $core.method({
 selector: "htmlNamespace",
@@ -193,11 +141,53 @@ messageSends: ["htmlNamespace"]
 }),
 $globals.Silk.a$cls);
 
+
+$core.addTrait("TSilkBuilder", "Silk");
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.TSilkBuilder.comment="I contain Silk's \x22build element via DNU\x22 behaviour.\x0a\x0aI expect #namespace and #newElement:xmns: to be implemented.";
+//>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "doesNotUnderstand:",
+protocol: "message handling",
+fn: function (aMessage){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$receiver;
+$1=$self._tryMakeDnuElement_(aMessage);
+if(($receiver = $1) == null || $receiver.a$nil){
+return (
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.TSilkBuilder.superclass||$boot.nilAsClass).fn.prototype._doesNotUnderstand_.apply($self, [aMessage]));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+} else {
+return $1;
+}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"doesNotUnderstand:",{aMessage:aMessage})});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aMessage"],
+source: "doesNotUnderstand: aMessage\x0a\x09\x22`self DIV` creates (and optionally inserts) a div element.\x0a\x09`aSilk DIV: anObject` creates (and optionally inserts)\x0a\x09a div element, and puts contents in it\x22\x0a\x09^ (self tryMakeDnuElement: aMessage)\x0a\x09\x09ifNil: [ super doesNotUnderstand: aMessage ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["ifNil:", "tryMakeDnuElement:", "doesNotUnderstand:"]
+}),
+$globals.TSilkBuilder);
+
 $core.addMethod(
 $core.method({
-selector: "tryMakeDnuElement:in:",
+selector: "tryMakeDnuElement:",
 protocol: "instance creation",
-fn: function (aMessage,aSilk){
+fn: function (aMessage){
 var self=this,$self=this;
 var selector,newElement,useArg;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -225,25 +215,28 @@ $3=$recv(selector)._includes_(":");
 if($core.assert($3)){
 return nil;
 }
-newElement=$self._newElement_xmlns_($recv(selector)._asLowercase(),$recv(aSilk)._namespace());
+newElement=$self._newElement_xmlns_($recv(selector)._asLowercase(),$self._namespace());
 $4=useArg;
 if($core.assert($4)){
 $recv(newElement).__lt_lt($recv($recv(aMessage)._arguments())._first());
 }
 return newElement;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"tryMakeDnuElement:in:",{aMessage:aMessage,aSilk:aSilk,selector:selector,newElement:newElement,useArg:useArg})});
+}, function($ctx1) {$ctx1.fill(self,"tryMakeDnuElement:",{aMessage:aMessage,selector:selector,newElement:newElement,useArg:useArg})});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aMessage", "aSilk"],
-source: "tryMakeDnuElement: aMessage in: aSilk\x0a\x09\x22`DIV` creates a div element.\x0a\x09`DIV: anObject` creates a div element and puts contents in it.\x0a\x09When aSilk is an instance and not the class Silk, \x0a\x09and the instance has an xml namespace other than the default #html,\x0a\x09Then that namespace is used for the new element.\x0a\x09You can do:\x0a\x09\x09svg := Silk newElement: 'svg' xmlns: 'http://www.w3.org/2000/svg'.\x0a\x09\x09svg CIRCLE: {'cx' -> 60. 'cy' -> 25. 'r' -> 10}.\x0a\x09This creates a svg circle, not a html circle.\x22\x0a\x09\x0a\x09| selector newElement useArg |\x0a\x09selector := aMessage selector.\x0a\x09selector asUppercase = selector\x0a\x09\x09ifFalse: [ ^ nil ].\x0a\x09selector last = ':'\x0a\x09\x09ifTrue: [ useArg := true. selector := selector allButLast ]\x0a\x09\x09ifFalse: [ useArg := false ].\x0a\x09(selector includes: ':')\x0a\x09\x09ifTrue: [ ^ nil ].\x0a\x09newElement := self newElement: selector asLowercase xmlns: aSilk namespace.\x0a\x09useArg ifTrue: [ newElement << aMessage arguments first ].\x0a\x09^ newElement",
+args: ["aMessage"],
+source: "tryMakeDnuElement: aMessage\x0a\x09\x22`DIV` creates a div element.\x0a\x09`DIV: anObject` creates a div element and puts contents in it.\x0a\x09An element can be optionally inserted by #newElement:xmlns:.\x0a\x09When self is an instance and not the class Silk, \x0a\x09then the instance's namespace is used for the new element.\x0a\x09You can do:\x0a\x09\x09svg := Silk newElement: 'svg' xmlns: 'http://www.w3.org/2000/svg'.\x0a\x09\x09svg CIRCLE: {'cx' -> 60. 'cy' -> 25. 'r' -> 10}.\x0a\x09This creates a svg circle, not a html circle.\x22\x0a\x09\x0a\x09| selector newElement useArg |\x0a\x09selector := aMessage selector.\x0a\x09selector asUppercase = selector\x0a\x09\x09ifFalse: [ ^ nil ].\x0a\x09selector last = ':'\x0a\x09\x09ifTrue: [ useArg := true. selector := selector allButLast ]\x0a\x09\x09ifFalse: [ useArg := false ].\x0a\x09(selector includes: ':')\x0a\x09\x09ifTrue: [ ^ nil ].\x0a\x09newElement := self newElement: selector asLowercase xmlns: self namespace.\x0a\x09useArg ifTrue: [ newElement << aMessage arguments first ].\x0a\x09^ newElement",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
 messageSends: ["selector", "ifFalse:", "=", "asUppercase", "ifTrue:ifFalse:", "last", "allButLast", "ifTrue:", "includes:", "newElement:xmlns:", "asLowercase", "namespace", "<<", "first", "arguments"]
 }),
-$globals.Silk.a$cls);
+$globals.TSilkBuilder);
+
+$core.setTraitComposition([{trait: $globals.TSilkBuilder}], $globals.Silk);
+$core.setTraitComposition([{trait: $globals.TSilkBuilder}], $globals.Silk.a$cls);
 
 $core.addMethod(
 $core.method({

+ 28 - 17
src/Silk.st

@@ -63,13 +63,12 @@ namespace
 
 !Silk methodsFor: 'writing'!
 
-doesNotUnderstand: aMessage
-	"`aSilk DIV` creates a div element and inserts it.
-	`aSilk DIV: anObject` creates a div element, inserts it
-	and puts contents in it"
-	(self class tryMakeDnuElement: aMessage in: self)
-		ifNil: [ ^ super doesNotUnderstand: aMessage ]
-		ifNotNil: [ :newElement | self << newElement. ^ newElement ]
+newElement: aString xmlns: anotherString
+	| el |
+	
+	el := self class newElement: aString xmlns: anotherString.
+	self << el.
+	^ el
 !
 
 nextPut: anObject
@@ -99,14 +98,21 @@ namespace
 	^ self htmlNamespace
 ! !
 
-!Silk class methodsFor: 'instance creation'!
+Trait named: #TSilkBuilder
+	package: 'Silk'!
+!TSilkBuilder commentStamp!
+I contain Silk's "build element via DNU" behaviour.
+
+I expect #namespace and #newElement:xmns: to be implemented.!
 
-tryMakeDnuElement: aMessage in: aSilk
+!TSilkBuilder methodsFor: 'instance creation'!
+
+tryMakeDnuElement: aMessage
 	"`DIV` creates a div element.
 	`DIV: anObject` creates a div element and puts contents in it.
-	When aSilk is an instance and not the class Silk, 
-	and the instance has an xml namespace other than the default #html,
-	Then that namespace is used for the new element.
+	An element can be optionally inserted by #newElement:xmlns:.
+	When self is an instance and not the class Silk, 
+	then the instance's namespace is used for the new element.
 	You can do:
 		svg := Silk newElement: 'svg' xmlns: 'http://www.w3.org/2000/svg'.
 		svg CIRCLE: {'cx' -> 60. 'cy' -> 25. 'r' -> 10}.
@@ -121,20 +127,25 @@ tryMakeDnuElement: aMessage in: aSilk
 		ifFalse: [ useArg := false ].
 	(selector includes: ':')
 		ifTrue: [ ^ nil ].
-	newElement := self newElement: selector asLowercase xmlns: aSilk namespace.
+	newElement := self newElement: selector asLowercase xmlns: self namespace.
 	useArg ifTrue: [ newElement << aMessage arguments first ].
 	^ newElement
 ! !
 
-!Silk class methodsFor: 'message handling'!
+!TSilkBuilder methodsFor: 'message handling'!
 
 doesNotUnderstand: aMessage
-	"`Silk DIV` creates a div element.
-	`Silk DIV: anObject` creates a div element and puts contents in it"
-	^ (self tryMakeDnuElement: aMessage in: self)
+	"`self DIV` creates (and optionally inserts) a div element.
+	`aSilk DIV: anObject` creates (and optionally inserts)
+	a div element, and puts contents in it"
+	^ (self tryMakeDnuElement: aMessage)
 		ifNil: [ super doesNotUnderstand: aMessage ]
 ! !
 
+Silk setTraitComposition: {TSilkBuilder} asTraitComposition!
+Silk class setTraitComposition: {TSilkBuilder} asTraitComposition!
+! !
+
 !Association methodsFor: '*Silk'!
 
 renderOnSilk: aSilk