GEMï
The Web Operating System Open Project

Author: Domenico Strazzullo
Principal

Dotuscomus
Paris
France

Co-presenter: Jayne De Sesa
Creative Director

Dotuscomus
Paris
France

Domenico Strazzullo is a SVG evangelist, committed to this discipline since 2001. He is the author of some legendary demos, several commercial applications, a GPL library of JavaScript routines, as well as Pergola (JavaScript framework for SVG) and GEMï.

Jayne De Sesa holds a Bachelor of Arts degree in Visual Arts and Human Development from the State University of New York, Empire State College; undergraduate college, The Maryland Institute, College of Art, Fine Arts Major. She is an award-winning advertising art director and designer.

Abstract

The purposes of this presentation are: to survey the features and capabilities of GEMï, as well as its possible domains of application; to review the techniques employed for its construction; to present the Open Project proposals for evolution available at the time of the conference. Version 2 underwent complete refactoring and is now powered by the Pergola JavaScript framework.

Table of Contents

  1. 1. What is GEMï?
    1. 1.1 Overview
    2. 1.2 Domains of application
  2. 2. Technical Aspects
    1. 2.1 The Architecture
    2. 2.2 Building the Interface
    3. 2.3 Design of the Interface
  3. 3. The Open Project
  4. 4. Resources
1. What is GEMï?
Overview

GEMï is a cross-browser Web Operating System. It consists of an Application Environment Manager and a Graphical User Interface using SVG as Virtual Device Interface.

GEMï has the system features commonly found in window based operating systems, including a system menu. The windows are fully featured and have the particularity of carrying in their tool bars sophisticated tools, proper to SVG transformation capabilities, for zooming and panning their contents.

It can run simultaneously a theoretically unlimited number of documents, which can be either inline, i.e. embedded in the main .svg document, or downloaded on request by the user through the menu File > Open Document. In compliance with the JavaScript security restrictions, only documents from the same domain where GEMï is located can be downloaded.

Two notable features are Preferences and Session which can both be saved in remote mode. The Preferences relate to display options like background color, background image, background image opacity, size and orientation of the window tabs bar, size of the window thumbnails and thumbs tray, windows' background color, skin and theme of the interface.

The Session relates to the windows with their status (open, closed, minimized, full) and their current layout. Besides the common layout options (cascade, mosaic, tile horizontal and vertical) the user has the possibility of defining a Custom Layout as a preferred workspace. However, at the time of writing this option is not fully implemented.

GEMï also has these libraries: symbol (native format), quick tips, filters, cursors, skins.

Domains of application

The range of domains of application is wide and includes engineering, cartography, scientific, educational, illustration, presentations and more.

A typical scenario is this: the person in charge of the project links the documents to it, eventually embedding inline relevant documents that she wishes to be rendered at runtime. The Users can then open as many of the documents pertaining to the project as they need. As we have seen, they can override the default layout by determining which documents are to be rendered at runtime and by saving the Session, the other documents remaining available through the menu File > Open or File > Reload Closed Document. The Users' Preferences and Session are saved in cookies on their workstations (in remote mode only). Users are informed of project changes –files added or removed– upon launching the application.

2. Technical Aspects
The Architecture

The architectural scheme of GEMï is based on class inheritance and prototype extensions of the subclasses, and it's built around a placeholder object, establishing a namespace, a superclass and subclasses.

The subclasses are designed to produce micro and macro assemblies constituting interface elements. There are no classes defined for SVG elements. Instead, GEMï uses a revolutionary node builder which, as we will see, allows to build any SVG element in the most simple and intuitive manner, without any restrictions or constraints, using SVG grammar.

The class inheritance method used in GEMï is based on the model proposed by Kevin Lindsay (with slight modifications), which I find concise, efficient and above all, that doesn't backfire. It was also the one that best matched the conclusions from my findings.

subclass: function(subClass, baseClass) {
  if (!arguments[0].length) subClass = [subClass];
  function inheritance() {}
  inheritance.prototype = baseClass.prototype;
  for (var c in subClass) {
    var clss = subClass[c];
    clss.prototype = new inheritance();
    clss.prototype.constructor = clss;
    clss.baseConstructor = baseClass;
    clss.superClass = baseClass.prototype;
  }
},
The prototype inheritance method

The Class constructor, a property of the gemi object, is the superclass from which most classes inherit. All the prototype methods are defined in gemi.Class. This superclass also defines some class methods.

The classes, all properties of gemi, are specialized constructors. Most classes define private extensions of the prototype inherited by their superclass, if any. These extensions are class properties, therefore an instance does not have its own copy of those properties, unless overridden, resulting in a lesser occupation of memory.

We can subdivide the classes in two categories, concrete and abstract (in the literary sense, not C++), the majority belonging to the former and designed to produce SVG visible or invisible objects. They are always subclassed to gemi.Class. Other classes designed to carry out particular tasks, like Timer for example, are not necessarily subclassed.

Here we come to a fundamental particularity of GEMï: it does not have any classes for SVG elements. Instead, for those it uses the library that is constituted by the browser's implementation of SVG. To achieve this the gemi object defines a method (node builder) which acts as an interface between the internal library and the implementation's library. This methods expects exactly 1 argument, an object where the property/value pairs use SVG grammar, the property names containing JavaScript illegal characters for variable/property names being specified in string notation. Examples:

var g = $C({element:"g", transform:"translate(150 200)", appendTo:gemi.desktop});
A referenced <g> element
$C({
  element: "path", 
  d: pathData, 
  fill: "none", 
  stroke: "#C0C0C0", 
  'stroke-width': 2,
  'stroke-dasharray': "3,3",
  opacity: .75,
  'pointer-events': "none", 
  appendTo: parentNode
});
A non referenced <path> element
this.text = $C({
  element: "text",
  'font-family': "'...'",
  'font-size': "9pt",
  x: 27, 
  y: 11, 
  textNode: string, 
  appendTo: parentNode
});
A referenced <text> element. Note the “textNode” property

In the objects above we define any properties corresponding to SVG attributes that we need to set. These properties will be named using the attribute name itself, exactly. For properties designating attributes in the SVG namespace that contain illegal characters for JavaScript variable/property names we use the string notation, also known as array notation.

We also define 3 properties the names of which are predefined and are not SVG attribute names. These are:

elementStringRequireddesignates the element
appendToReferenceOptionaldesignates a parent node
textNodeStringOptionalused with text element, defines the text node

These are the only properties that are processed by the node builder. Those representing the SVG element's attributes are simply set for that element and it is the responsibility of the programmer to ensure that they are contextually appropriate, just like when authoring an SVG document.

The node builder, which can be downloaded here, creates any SVG element:

createSVGElement: function(o) {
  for (var p in o) {
    var value = o[p];
    switch(p) {
      case "element" : var element = document.createElementNS(gemi.svgNS, value);
      break;
      case "textNode" : element.appendChild(document.createTextNode(value));
      break;
      case "appendTo" : value.appendChild(element);
      break;
      default : element.setAttributeNS((p == "xlink:href") ? gemi.xlinkNS : null, p, value);
    }
  }
  return element;
},
The SVG node builder

The returned DOM nodes that have any degree of relevance for the object are referenced by instance properties.

In addition, a HTML node builder is available for use with the <foreignObject> element:

createHTMLElement: function(o) {
  for (var p in o) {
    var value = o[p];
    switch(p) {
      case "element" : var element = document.createElementNS("http://www.w3.org/1999/xhtml", value);
      break;
      case "textNode" : element.appendChild(document.createTextNode(value));
      break;
      case "appendTo" : value.appendChild(element);
      break;
      default : element.setAttribute(p, value);
    }
  }
  return element;
},
The HTML node builder

Note that this HTML node builder is designed for use within an XML document. To be used in a HTML context it needs one modification. Note also that the textNode property can be set for any HTML element that can have a text node.

Note: the HTML node builder is not used in GEMï but it can be seen in action in the examples provided with the Pergola package.

Building the Interface

The section in the DOM tree constituting the interface is organized in the following manner:

Initially it contains a <g id="gemi_windowstree"> element, referenced by gemi.windowsTree, which is hard-coded in the gemi.svg document in order to allow the embedding of those inner <svg> fragments that are intended to be rendered at runtime. One other good reason for this is to make GEMï accessible for those authors who feel more comfortable with this technique, or simply don't have any practice with scripting.

The other technique of referencing the project documents by script, making them available through the menu File > Open Document, is straightforward and well documented.

A <g> element, referenced by gemi.desktop, is first created and the gemi.windowsTree group appended to it. The inner <svg> fragments are removed, wrapped in container windows and appended to gemi.windowsTree. Other system components are then created and properly stacked, the drag-area being on the topmost layer for example.

The GEMï Skin has the primary role of determining the appearance of the interface. It is designed to work in a manner similar to that of a CSS file, while adding some notable features:

A great deal of attention has been devolved to the design of the skin as a conceptual entity, not precisely as an application in itself. It is intended as a dependency, and the mechanism through which the classes communicate with the gemi.presentationAttributes object –the product of the gemi.skins methods– is simply by assigning references of said object's properties, to properties set in the prototype extensions of the classes, properties which can be overridden of course.

Worth of note is the fact that this technique does not at any point prevent the use of the style attribute. For a direct call to the node builder, it is as simple as this:

var myCircle = $C({
  element: "circle", 
  r: "1cm", 
  style: "...", 
  appendTo: parentNode
});
Using the style attribute

Yes, but can this be done while creating new instances? Would this mean that the prototype extensions define properties to designate all possible attributes, or at least the most frequently used? The answer to the first question is: it is possible for those classes which won the prize for eligibility, meaning that I arbitrarily decided which would be the lucky ones. The answer to the second question is: absolutely not. As a principle the prototype extensions for any of the classes never define properties to designate SVG attributes with initial values. This, in order to produce a lean output, without any redundancies. If we care to DOM inspect we will never see such things as “ x="0" ”, or “ stroke-width="1" ”, or “ style="" ”. The library produces optimal SVG code exactly like a competent developer would.

How is it done then? Those lucky classes are abilitated to process the extra property. This property is an object where we can set properties designating any SVG attribute, using strictly SVG grammar. An example will clarify this:

var myButton = new pergola.Button();
button.build({
  parent: g,
  x: 80,
  extra: {
    rx: 3,
    transform: "rotate(-45)"
  },
  symbol: {
    symbol: pergola.symbols.arrow.large.left,
    x: 5,
    y: 5
  },
  quickTip: {tip: "this button is rotated but|its symbol is straight"},
  ev: "mouseup",
  target: legend.tip6,
  fn: legend.hilight
});
The extra attribute

As we have seen, GEMï 2 has been entirely rewritten using the Pergola framework/library, which has a double license, commercial and GPL, making it usable in the GEMï Open Project context. Pergola has a rich documentation/tutorial where every aspect is covered in detail. Every subject found there applies to GEMï as well. On the other hand, GEMï has some specific extensions and logic which will be documented separately, within the Open Project scope.

Design of the Interface

T.B.D.

3. The Open Project

At writing time the GEMï Open Project is at the proposal stage and possible evolutions, apart from minor enhancements and fixes, are yet to be defined.

4. Resources