E-Chalk
FU Logo




Chalklet Tutorial


Table of Content



Who should read this Tutorial ?


This tutorial addresses software developers that are interested in the development of an E-Chalk chalklet. Experiences in Java application development are recommended, since basic knowledge of the Java typical APIs, Jar-Files and the Class-path is required.


What are Chalklets ?


The E-Chalk API is a programming interface that has been designed to develop chalklets. Chalklets are programs that are able to communicate directly with the board of the E-Chalk system.

The idea behind is simple: Chalklets register as listeners to a certain area of the chalkboard and receive all strokes that are drawn on this area by the user. Additionally chalklets are allowed to draw their own strokes on the given chalklet area. This simple interaction to the board system offers some interesting possibilities to developers. For example, a chalklet might immediately respond to a user stroke by a drawing or an animation. Chalklets are delivered in Jar-Archives, that contain all necessary classes. Chalklets can be integrated into E-Chalk as described in Edit Chalklet Bookmarks....

Several chalklets have been developed by students or PhD. You can find some of them in the Example section.

This tutorial explains the development of a chalklet with a simple example. A chalklet, that redraws every stroke given by the user in a random color. The user also has the possibility to correct wrong strokes with the UNDO-Button.

Requirements

You will need a running installation of E-Chalk and the documentation of the E-Chalk API to develop and test your chalklet, successfully. The latest version of E-Chalk can be downloaded here.
The necessary classes of the E-Chalk API can be found in installation directory of E-Chalk in "lib/echalk.jar". To compile a chalklet successfully, you need to put these classes in the class-path of your virtual machine.
The documentation can be found in the installation directory in "doc/echalkapi/index.html".


Development

Chalklets are found by the E-Chalk system via code reflection, that means E-Chalk searches for certain classes in the Jar-Archive of a chalklet and uses these classes for initialization and execution.
For a proper working chalklet, the following two classes are needed:

  • A class that inherits "de.echalk.util.ChalkletKit" - the chalkletkit is used by the E-Chalk system to setup the parameter, that are needed by the chalklet.
  • A class that implements the interface "de.echalk.util.Chalklet" - this class contains the actual chalklet

1. The ChalkletKit (Source Code)

Lines 1 - 6, package and import instructions.
	 1 package chalkletexample;
	 2 
	 3 import de.echalk.util.*;
	 4 import java.awt.Dimension;
	 5 import java.util.Locale;
	 6
	
Inheritance of the class ChalkletKit, this class provides information on the particular chalklet. The following code snippet shows, which methods have to be overridden at least.
	 7 public class ExampleChalkletKit extends ChalkletKit{
	
A static variable, that contains the KitSetupInfo. The KitSetupInfo describes which parameters are expected by the chalklet.
	 8  private static final KitSetupInfo KIT_INFO = new ExampleChalkletKitSetupInfo();
	
The constructor of the class should be private and not visible to other classes, since the chalklet is created via the factory pattern.
	 9  private ExampleChalkletKit() {}
	10
	
Lines 11 - 31, definition of the methods.
	11  public static KitSetupInfo getKitSetupInfo() {
	12      return KIT_INFO;
	13  }
	14
Lines 15 - 22, construct the actual chalklet. The ChalkletContext aContext passed in, references to the board area the chalklet is registered for and can be used for drawing operations later on. The ChalkletContext is the connection between the chalklet and the chalkboard and can be used amongst other things to determine how much time has passed since the start of the chalklet or which color the board background on the chalklet area has.
The parameter String[] aStrings contains the user passed parameters for the chalklet and have to be evaluated according to the KitSetupInfo.
	15  public static Chalklet getChalklet( ChalkletContext aContext, 
                                                String[] aStrings ) {
	16     if ( aStrings.length != 1 )
	17        throw new IllegalArgumentException("One argument expected but "+
                                                aStrings.length+" found. ");
	18     final long _delay = Long.parseLong( aStrings[0] );
	19     if ( _delay <= 0 )
	20         throw new IllegalArgumentException( "delay is not positive: "+_delay );
	21     return new ExampleChalklet(aContext,_delay);
	22  }
	23
	
Lines 24 - 26, sets the minimal size of the chalklet in pixel.
	24  public static Dimension getMinimumChalkletSize( String[] aStrings ) {
	25     return new Dimension(200, 100);
	26  }
	27
	
Lines 28 - 30, sets the name of the chalklet, the name is displayed at different places in the graphical user interface of E-Chalk.
	28  public static String getChalkletName( Locale aLocale ) {
	29     return Txt.get("Example Chalklet", aLocale);
	30  }
	31
	
Lines 32 - 46, defines the KitSetupInfo, that specifies the parameter for the chalklet.
	32  private static final class ExampleChalkletKitSetupInfo 
	33                       extends KitSetupInfo {
	34
	
Lines 35 - 37, deliver a localized description of the chalklet. If no translation is found the string is returned as is. Translations can be added on server side to the file "dat/echalk_*.properties", where * is replaced by the particular locale extension (for example: _de for German or _en_us for US English). Localization is most important for chalklets that are supposed to be an integral part of E-Chalk.
	35     public String getDescription( Locale aLocale ) {
	36       return Txt.get( "A Simple Chalklet Example...\n", aLocale );
	37      }
	38
	
Lines 39 - 45, return an array, that specify which parameter are expected by the chalklet. The parameters are encapsulated into ParamInfo objects, each having at least a name, a description and a default value. The following parameter types are possible.
  • BooleanParam - Parameter info class for yes-or-no type parameters.
  • EnumParam - Parameter info class for a choice from a given list.
  • FileParam - Parameter info class for file parameters.
  • LongParam - Parameter info class for integer parameters.
  • PasswordParam - On input the password is hidden, but it is stored locally in plaintext (no protection against local users).
  • StringParam - Strings that contain no line breaks.
  • TextParam - Multi line texts, that are allowed to contain line breaks.

The example shows a LongParam - "Delay", that specifies how long the chalklet waits (in ms) before it responds to a user interaction. The parameter has the default value 1 and lies within 1 -Long.MAX_LONG.
	39     public ParamInfo[] getParamInfo( Locale aLocale ) {
	40         final String _aDelayName  = Txt.get( "Delay", aLocale );
	41         final String _aDelayDescription = Txt.get( 
                                                     "Delay for strokes moves in ms.",
                                                     aLocale );
	42         final ParamInfo _aDelayParam =
	43                new LongParam( _aDelayName, _aDelayDescription, 
                                         new Long(1), new Long(1), null);
	44         return new ParamInfo[] { _aDelayParam };
	45    }
	46  } // End of ExampleChalkletSetupInfo
	47} //end of ExampleChalkletKit
	

2. The Chalklet (Source Code)

Lines 1 - 7, package and import instructions.
	 1 package chalkletexample;
	 2
	 3 import de.echalk.util.*;
	 4 import java.awt.Color;
	 5 import java.util.LinkedList;
	 6 import java.util.*;
	 7
	
Line 8, definition of the chalklet class, this class must implement the interface de.echalk.util.Chalklet.
	 8 public class ExampleChalklet implements Chalklet {
	
Lines 9 - 12, definition of the chalklets private variables.
	 9  private final ChalkletContext aContext_; // Chalklet drawing context
	10  private final long aDelay_;  // time the chalklets waits after a stroke
	11  private boolean aliveFlag_;  // chalklet still alive?
	12  private LinkedList strokeBuffer_; // list of all strokes drawn so far (for undo)
	
Lines 13 - 18, chalklet constructor, that is called by getChalklet() to create the chalklet with the given parameters.
	13  public ExampleChalklet(ChalkletContext aContext, long aDelay) {
	14  aContext_=aContext;
	15  aDelay_=aDelay;
	16  strokeBuffer_= new LinkedList();
	17  aliveFlag_=true;
	18  }
	19
	
Lines 20 - 25, this function is called by E-Chalk to tell the chalklet that it is no longer needed (by user interaction or exiting the E-Chalk application).
	20  /**
	21    * endChalklet
	22    */
	23 public void endChalklet() {
	24   aliveFlag_=false;
	25  }
	26
	
Lines 32 - 59, this function is called every time a new Stroke is drawn by the user on the chalklet area. This function processes the input, in the example chalklet are all strokes drawn in another color than red, stored into a list. If the color red is used for drawing, the chalklet redraws every stored stroke in a random color.
The properties of Stroke-objects can not be manipulated directly. To redraw the strokes in a new color, new Stroke-objects have to be created with the help of the BoardStroke-constructor.

A note on stroke orders

Please note, that the order in which the strokes are drawn is not necessarily the same order as they were sent by the chalklet. The drawing order is determined by the strokes time stamps: The chalkboard always processes the stroke first, that can be first drawn onto the board, completely.
A Tip: You may send copies of strokes with manipulated timestamps to the board, to preserve a certain order of the strokes. The BoardStroke constructor provides the necessary functions.
When creating stokes, try not to create to many strokes per seconds. Since E-Chalk is designed as a live system, it limits the maximum number of drawn stroke segments per second, to make sure that all strokes can be transmitted correctly to a remote viewer and prevent the server from flooding the client. If you don't pay attention to This limitation, you may observer desired delays during the drawing of the strokes. The exact boundary can be found in the Chalklet API.
	27  /**
	28    * pushStroke
	29    *
	30    * @param boardStroke BoardStroke
	31    */
	32 public void pushStroke(BoardStroke boardStroke) {
	33   try {
	34    Thread.sleep(aDelay_); // wait delay
	35   }
	36   catch (InterruptedException ex) { }
	37   BoardStroke bs;
	38
	39   // run color is red
	40   if(boardStroke.getColor().equals(Color.red)){
	41    Iterator iter = strokeBuffer_.iterator();
	42   while (iter.hasNext()) {
	43     if(!aliveFlag_) return; // only react if still alive
	44     bs = (BoardStroke)iter.next();
	45     // redraw stroke in random color
	46     // note that strokes are drawn in "earlier ending strokes first" order
	47     aContext_.sendStroke(new BoardStroke(bs,
	48                  0,0,
	49                  0,
	50                  0,
	51                  0,
	52                  new Color((float)Math.random(),
	53                                (float)Math.random(),
	54                                (float)Math.random())));
	55    }
	56  }
	57
	58   strokeBuffer_.add(boardStroke); // add stroke to buffer for later removal
	59 }
	60
	
Lines 61 - 68, this function is called if the user presses the UNDO-button and the belonging stroke has been sent to the chalklet. This function allows the chalklet developer to keep his data models consistent by reacting to the removal of strokes. In the example the last stroke is simply removed from the stroke list and therefore not redrawn in a random color, when the chalklet is started.
The stroke must not be deleted of the board, since the E-Chalk system removes the stroke automatically. A REDO-operation is not needed to be implemented. If the user presses the REDO-button, E-Chalk simply passes the last stroke again to the chalklet.
	61  /**
	62    * removeLastStroke
	63    */
	64 public void removeLastStroke() {
	65   if(strokeBuffer_.isEmpty() || !aliveFlag_) return;
	66   // remove stroke from queue, so that it is not redrawn
	67   strokeBuffer_.removeLast();
	68 }
	69} // end of ExampleChalklet
	

Beispiele


You can find Example Chalklets here.

Last modification: Mon, 2010-08-09