Writing widgets based on Microsoft 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:

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