Extending the Rich UI widget set with Silverlight®

You can write widgets that are based on Silverlight®, a browser plugin that is described at http://silverlight.org. Silverlight® uses an XML dialect called XAML for defining user interfaces and uses the .Net platform for handling events. You can access the Silverlight® runtime from the browser by running JavaScript™ code.

The next sections describe a sample that is composed of the following components:
  • Button.egl, which defines an external type.
  • Button.js, which is the JavaScript™ code that define a new widget and that is referenced by the external type.
  • canvas.xaml, which is an XAML file that defines an empty container for the JavaScript™ to use as a canvas when painting a button
  • Silverlight.html, which includes a <script> tag for inclusion in the EGL-generated JavaScript™.
  • SilverDemo.egl, which demonstrates the functionality.

You can try the sample in a Rich UI project. However, please note that this topic is a proof of concept and that far more detail is needed to incorporate Silverlight® meaningfully in your EGL applications.

Silverlight® is a trademark of Microsoft™ Corporation.

Button.egl

The Button.egl file introduces the following EGL external type, which extends the Rich UI Widget type.

Here is the content, which goes in an EGL package named myPkg:
package myPkg;

ExternalType Button extends Widget type JavaScriptObject 
   {
      relativePath = "silverlight",
      javaScriptName = "Button",
      includeFile = "silverlight/Silverlight.html"
   }       
   text String
      { @JavaScriptProperty
         { getMethod="getText", setMethod="setText" } };
end

Button.js

Button.js contains the JavaScript™ implementation that is referenced in the external type definition. The JavaScript™ identifies the new widget and defines the following functions:
  • setText ensures that the new widget can write text into the DOM node.
  • getText ensures that the new widget can retrieve text from the DOM node.
  • egl$$update defines an XAML fragment and enables EGL event handling for the onClick event.
Here is the content, which goes in WebContent/silverlight:
egl.defineWidget(
   'silverlight', 'Button',   // this class
   'egl.ui.rui', 'Widget',    // the super class
   'div',                     // dom element type name
   {
      "setText" : function( /*String*/ text ) {
         this.text = text;
         this.eze$$update();
      },

      "getText" : function() {
         return this.text;
      },
  	
      "eze$$update" : function() {
         width = Math.max(85, 8 * this.text.length);
         var xamlFragment = 
         '<Canvas Canvas.Left="0" Canvas.Top="0" Width="'+width+'" Height="24" >' + 
         '<Rectangle Canvas.Top="0" Canvas.Left="0" Width="' + width +
         '" Height="24" Fill="#FFFFFFFF" Stroke="#FF000000" StrokeThickness="1" />' +
         '<TextBlock Foreground="#FF000000" Canvas.Left="5" Canvas.Top="2">' + 
         this.text + '</TextBlock>' + '</Canvas>';

         var eglButton = this;

         window.eze$$silverlight_canvasLoaded = function(sender, eventArgs) {
            sender.children.add(sender.getHost().content.createFromXaml(xamlFragment)); 

         var textBlock = sender.children.getItem(0).children.getItem(1);
         var rectangle = sender.children.getItem(0).children.getItem(0);
         var canvas = sender.children.getItem(0).children.getItem(0);

         textBlock.addEventListener("MouseLeftButtonDown", function(sender, eventArgs)
         { 
            rectangle.StrokeThickness = 3;
            var handlers = eglButton.getOnClick();

            // find each EGL eventhandler
            for (var n=0; n<handlers.length; n++) {
               handlers[n]({ widget: eglButton});
               // call it
      				} 			
         });

         textBlock.addEventListener("MouseLeftButtonUp", function(sender, eventArgs){
            rectangle.StrokeThickness = 1;	
         }); 

         textBlock.addEventListener("MouseEnter", function(sender, eventArgs){
            canvas.fill="orange";
         });

         textBlock.addEventListener("MouseLeave", function(sender, eventArgs) {
            canvas.fill="white";
         }); 

         canvas.addEventListener("MouseEnter", function(sender, eventArgs) {
            sender.fill="orange"; 			}); 	        

         canvas.addEventListener("MouseLeave", function(sender, eventArgs) {
            sender.fill="white";
         }); 
      } 		

      try { 			
         Silverlight.createObject( "silverlight/canvas.xaml",
         this.eze$$DOMElement,
         "uniqueID",
         { width: String(width), height: "24", version:'1.0' },
         { onError: 
            function (sender, errorArgs) {
            var errorMsg = "Silverlight Error: \n\n";
                errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
                errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
                errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";

            switch(errorArgs.errorType) { 
               case "RuntimeError":
                  if (errorArgs.lineNumber != 0) {
                  errorMsg += "Line: " + errorArgs.lineNumber + "\n";
                  errorMsg += "Position: " +  errorArgs.charPosition + "\n"; }
                  errorMsg += "MethodName: " + errorArgs.methodName + "\n";
                  break;
               case "ParserError":
                  errorMsg += "Xaml File:      " + errorArgs.xamlFile + "\n";
                  errorMsg += "Xml Element:    " + errorArgs.xmlElement    + "\n";
                  errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute  + "\n";
                  errorMsg += "Line:           " + errorArgs.lineNumber    + "\n";
                  errorMsg += "Position:       " + errorArgs.charPosition  + "\n";
                  break;
               default:
                   break;
            }

           alert(errorMsg);
         },
         onLoad: null
      },
      null
      );
      egl.setWidth(this.eze$$DOMElement, width);
   } 		
   catch (e) { 
      egl.printError(
         "Silverlight error. Please make sure you included Silverlight.html. ", e); 
   }
} });

canvas.xaml

Canvas.xaml contains an empty container for Button.js to use as a canvas when painting a button.

Here is the content, which goes in WebContent/silverlight:
<Canvas xmlns="http://schemas.microsoft.com/client/2007" 
        Loaded="eze$$silverlight_canvasLoaded">
</Canvas>

Silverlight®.html

Silverlight®.html is an HTML file that contains a script tag for inclusion in the EGL-generated JavaScript™.

Here is the content, which goes in WebContent/silverlight and includes a security warning:
<script type="text/javascript" 
        src="http://silverlight.net/samples/1.0/clock/js/Silverlight.js">

SilverDemo.egl

SilverDemo.egl demonstrates use of the widget.

Here is the content, which goes in the EGL package named myPkg:

package myPkg;

import com.ibm.egl.rui.widgets.Box;

Handler SilverDemo Type RUIHandler { initialUI = [ui] }

   ui Box { columns=1, backgroundColor="#EEDDEE", width=110, children = 
   [
      new myPkg.Button { margin=5, text="Silverlight", onClick ::= click },
      new dojo.widgets.DojoButton { margin=5, text="Dojo", onClick ::= click },
      new com.ibm.egl.rui.widgets.Button { margin=5, text="EGL", onClick ::= click}]};
	
   function click(e Event in)
      buttonText String = (e.widget as Button).text;
      strlen INT = strLib.characterLen(buttonText);

      if (buttonText[strlen:strlen] == "!")
         buttonText = buttonText[1:strlen-1];
      else
         buttonText = buttonText + "!";
      end

      (e.widget as Button).text = buttonText;	  		
   end
end