Tag Archive | sample

Google Summer of Code 2013 (Sugar Labs)

Sugar

The award-winning Sugar Learning Platform promotes collaborative learning through Sugar Activities that encourage critical thinking, the heart of a quality education. Designed from the ground up especially for children, Sugar offers an alternative to traditional “office-desktop” software. Sugar Activities cover a broad range of applications: browsing, drawing, composing, writing, programming, etc. See this gallery of screenshots.

Introduction to the Sugar Interface describes multiple full-screen views: a Home view, from which Activities are launched; a Neighborhood view, where learners can connect to each other through a Jabber network; a Journal view, which can be used as a lab notebook; and the Activity view, where Sugar Activities are run.

Activities in Sugar

Learner applications in Sugar are called Activities. They are software packages that automatically save your work—producing specific instances of the Activity that can be resumed at a later time. A specific Activity instance is a Journalevent (see this discussion of The Notion of “Keeping”). Many Activities support learner collaboration, where multiple learners may be invited to join a collective Activity session.

Sugar Activities have no Save menu: everything is saved automatically. While the interface uses very little text, additional information is revealed when the user hovers over icons.

Writing activities in full HTML5-JavaScript.

The objective of this project is to allow developers to write activities for Sugar using only HTML5 and JavaScript (instead of the conventional Python code). HTML5 activities could be hosted on Sugar side-by-side with “standard” Python activities. Specifically HTML5 will be displayed on the Sugar Home view like any other activities. HTML5 activities could benefit from common Sugar features (Sugar UI, Datastore/journal, telepathy, …) like any other activities. Finally there should be no visual difference from the user perspective between a Python activity and a HTML5 activity. HTML5 activities could be named “Sugar Web Activity”.

This feature will be accommodated as a part of Sugar 0.100. Also, this project has been accepted as a Google Summer of Code 2013 project by Sugar Labs and I shall be working on this for the next few months.

HTML5 activities will be run via a WebKit instance. A JavaScript framework will expose Sugar Features to HTML5 activities. Specifically, this framework will allow to use HTML controls matching the Sugar widgets look&feel and will expose common and customized activity toolbars. The framework will also expose API for handling Telepathy (communication and collaboration between multiple Sugar machine) and Datastore (Sugar Journal reading and writing).

Before you commence, ensure that you have a work development environment http://developer.sugarlabs.org/dev-environment.md.html.

Creating Web Activity

To create your own web activity, enter the sugar-build shell

./osbuild

Create an activity based on the default template

volo create my-activity ./sugar-web-template
cd my-activity

Choose a name for your activity. Write it in the activity name and bundle-id in activity/activity.info, and also in the title tag of index.html.

Install the activity for development

python setup.py dev

Now you should have a basic activity running!

You can refer http://developer.sugarlabs.org/activity.md.html for more details,

The working of the activity:

index.html

Here lies the skeleton of the activity that you’re going create. It comes with a basic template (sugar-web-template) but as you go

on developing your activity, you will be making changes to it.

For the current template we make use of the require js framework.

Notice that in the script tag we do not include all the js files in it, but rather a more subtle,

  <script data-main=“js/loader”src=“lib/require.js”></script>

 This can be done because the require js framework holds together all the dependencies and links them together.

  DOM ready feature of requirejs,

 In activity.js we make use of this feature:

require([‘domReady!’], function (doc) {

//code

}
 It is made use of to ensure that the various elements of the DOM must be ready before we attempt to communicate with them using
the JavaScript. In modern browsers it is done by waiting for the DOMContentLoaded event.
But not all browsers support DOMContentLoaded event hence we make use of domReady module which implements a cross-browser to determine
when DOM is ready.

If you need more details about the working of require js, please refer the documentation here http://requirejs.org/.

How the Sugar UI is replicated:

sugar-web/graphics/

The contents inside this provide the JavaScript and CSS files which are responsible for replicating the sugar UI.

We make use of LESS framework to write and compile the CSS to ensure that the sugar UI is dynamic and flexible to ensure that the

Sugar UI will work even when it is run under different screen resolutions, namely android phones, tablets, etc.

Example:

Let us for instance take a function palette.js which is used to replicate the palettes in Sugar.

function createPaletteElement() {
            if (paletteElem !== undefined) {
                return;
            }
            paletteElem = document.createElement(‘div’);
            paletteElem.className = “palette”;
            paletteElem.style.visibility = “hidden”;
            document.body.appendChild(paletteElem);
            if (that.invoker.classList.contains(“toolbutton”)) {
                invokerElem = document.createElement(‘div’);
                invokerElem.className = “palette-invoker”;
                var style = that.invoker.currentStyle ||
                    window.getComputedStyle(that.invoker, ”);
                invokerElem.style.backgroundImage = style.backgroundImage;
                invokerElem.addEventListener(‘click’, function (e) {
                    that.toggle();
                });
                paletteElem.appendChild(invokerElem);
           }
            wrapperElem = document.createElement(‘div’);
            wrapperElem.className = “wrapper”;
            paletteElem.appendChild(wrapperElem);
            if (that.primaryText !== undefined) {
                headerElem = document.createElement(‘div’);
                headerElem.className = “header”;
                headerElem.innerText = that.primaryText;
                wrapperElem.appendChild(headerElem);
            }
            headerSeparatorElem = document.createElement(‘hr’);
            headerSeparatorElem.className = “header-separator”;
            headerSeparatorElem.style.display = “none”;
            wrapperElem.appendChild(headerSeparatorElem);
            containerElem = document.createElement(‘div’);
            containerElem.className = “container”;
            wrapperElem.appendChild(containerElem);
            updatePosition();
        }

Whenever we need to create a palette this function is called , div element is created and appended to the required tags. These div tags are given the class names as “palette” and the respective styling for them is done in the sugar.css/sugar.less files. To append content to the palettes, we simple create instantiate palette.Palette and call setContent using the same object and pass the tags as parameters.

Communication between sugar and the JavaScript framework:

When Web Activity needs to call Sugar system API, JavaScript has to call Python code. The communication between the webkit and the python code happens through websockets, through which the data is encoded in JSON/binary format.   bus.sendMessage(“function.name”,parameters, callback);   The corresponding calls from the framework are matched here in this python program: /sugar/src/jarabe/apisocket.py In the respective methods which map the “sugar calls” from the JavaScript framework, we’d have to write the python code in this file.

Mapping sugar api with the framework:

Taking the example of the datastore api:

sugar-web/datastore.js:

Lets consider the function “datastore.create” in datastore.js:

    datastore.create = function (metadata, callback) {
        function onResponseReceived(responseError, result) {
            if (responseError === null) {
                callback(null, result[0]);
            } else {
                callback(responseError, null);
            }
        }
        var params = [metadata];
        bus.sendMessage(“datastore.create”, params, onResponseReceived);
    };

This function is made use of in order to create a new datastore object.

We pass the metadata as parameters to the function call.

Metadata contains all the activity details such as activity id, name, creation date,etc.

The parameters of bus.sendMessage() is passed to :

 sugar-web/bus.js:

    bus.sendMessage = function (method, params, callback) {
        var message = {
            “method”: method,
            “id”: lastId,
            “params”: params
        };
        if (callback) {
            callbacks[lastId] = callback;
        }
        client.send(JSON.stringify(message));
        lastId++;
    };

These parts in bus .js are primarily responsible for the communication from and to the activity .

The data is encoded into JSON format and then is sent through the websockets to interact with the python functions in Sugar.

In /sugar/src/jarabe/apisocket.py:

we have the matching function under the DatastoreAPI classs

def create(self, request):

        def reply_handler(object_id):
            self._client.send_result(request, [object_id])
        def error_handler(error):
            self._client.send_error(request, error)
        self._data_store.create(request[“params”][0], “”, True,
                                reply_handler=reply_handler,
                                error_handler=error_handler)

Here we make the sugar call in python and create the datastore object and send it back to the JavaScript framework using self._client.send_result().

Writing test specifications:

sugar-web/test/

The unit test specifications reside here and we make use of the Jasmine framework [1].

These are written to ensure that sugar doesn’t break.

Let’s take a peek at sugar-web/test/envSpec.js 

define([“sugar-web/env”], function (env) {
    describe(“environment”, function () {
        it(“should not return undefined”, function () {
            env.getEnvironment(function (error, environment) {
                expect(environment.bundleId).not.toBeUndefined();
                expect(environment.activityId).not.toBeUndefined();
                expect(environment.activityName).not.toBeUndefined();
            });
        });
    });
});

Here we assert the fact that the variables (bundleId, activityId and activityName) are there in environment. The expectation is defined within ‘expect()’ and each expectation has a matcher. We make use of not.toBeDefined() matcher to make sure that the expected variables are present.

My works:

Under the watchful guidance of Lionel Laské (my mentor for the GSoC project), so far I’ve been assisting Daniel Narvaez and Manuel (the sugar lab developers who are currently working on the framework ) and contributed a few patches.

Namely, added sugar like radio-buttons and check boxes. Created an activity palette, which syncs with the datastore.

I also wrote a small test for env.js using the Jasmine framework.

I’m also simultaneously creating a small game while working on the framework, which I’ll probably complete by the end of the GSoC period [2].

You can track the work here on our wiki page in sugar labs [3].
Hopefully, I’ll be back with an update on this work by the end of this month

Advertisements