.. _dev-intro-application-structure:

=====================
Application Structure
=====================
Applications are Dojo modules
=============================
Lucid applications are essentially dojo modules. They live in the ``lucid.apps`` namespace. The name of the module in this namespace is known as the application's system name, or sysname. All applications extend the ``desktop.apps._App`` class, which contains some bootstrap code and self-management functions.

Metadata
========
Each app has metadata associated with it, which is stored in the database. This tells Lucid what category it is, which file types it can open, and other things.

Application Skeleton
====================
.. code-block:: javascript

    dojo.provide("lucid.apps.TestApp");

    dojo.declare("lucid.apps.TestApp", lucid.apps._App, {
        init: function(args){
            /*Startup code goes here*/
        },
        kill: function(){
            /*Cleanup code goes here*/
        }
    });

Here, ``dojo.provide`` tells Dojo's package manager that the module loaded OK, and that it does in fact have our ``TestApp`` class in it. The ``dojo.declare`` call is what makes the class for our application. As you can see, it's extending ``_App``, which takes care of process management, and other low-level tasks in our app.

An application, at the very least, has an init and a kill function. These are run by Lucid when the app starts and when it exits, respectively. You can call the ``kill`` function from any function in your code to kill the application. ``init``, on the other hand, is only run once, and by Lucid. Your application shouldn't call the ``init`` function.

File layout
===========
The layout for applications consists of the following:

    SysName/

    SysName.js

SysName being the sysname of your application. Depending on how complex your application is, you can take two routes when choosing a layout.

Single-file applications
------------------------
These are good for quick applications that don't do too much. If you're writing an application that doesn't need `custom widgets <dev-howto-custom-widgets>` or templates, and doesn't need too much organization, you can write the entire app in one single class.

Multiple-file applications
--------------------------
Applications that need more structure can use multiple files. This makes the application much easier to maintain. Since Lucid applicatons are basically Dojo modules, we can split it up into several different files, each can have a widget, class, or other resource that the application can use.

With this pattern, usually you put all the ``dojo.require`` statements in your app's main file. For example:

.. code-block:: javascript
    
    dojo.declare("lucid.apps.MyApp");
    dojo.require("lucid.apps.MyApp._base");
    dojo.require("lucid.apps.MyApp.SomeClass");
    dojo.require("lucid.apps.MyApp.SomeWidget");
    dojo.require("lucid.apps.MyApp.submethods");

Each module coresponds to a javascript file in the ``MyApp`` folder. Fore example, ``MyApp._base`` would corespond to ``MyApp/_base.js``. It's important that you load``_base`` before the other modules in your app, otherwise ``_base`` will overwrite the declarations.

``_base`` contains the application declaration itself:

.. code-block:: javascript

    dojo.provide("lucid.apps.MyApp._base");

    dojo.declare("lucid.apps.MyApp", lucid.apps._App, {
        // ...
    });

``SomeClass`` and ``SomeWidget`` will contain some resource that we can use in our application. For example:

.. code-block:: javascript

    dojo.provide("lucid.apps.MyApp.SomeClass");

    dojo.declare("lucid.apps.MyApp.SomeClass", [], {
        // ...
    });

We can also add methods to our original application declaration using ``dojo.extend``:

.. code-block:: javascript

    dojo.provide("lucid.apps.MyApp.submethods");

    dojo.extend(lucid.apps.MyApp, {
        // ...
    });

This way, we can separate our functions based on what they do. For example, we can have one file that just deals with UI, while another deals with some sort of calculations, etc.

Accessing files/backends bundled with an application
----------------------------------------------------
You can get the path to scripts, images, audio, etc. using ``dojo.moduleUrl``:

.. code-block:: javascript

   var soundPath = dojo.moduleUrl("lucid.apps.SystemName", "resources/sound.mp3");


Note that some APIs (such as the Sound API) require that you pass a string. Since moduleUrl returns an object containing a toString method, you need to pass the ``uri`` property of the object returned.

.. code-block:: javascript
    
    soundPath = soundPath.uri;

When used in conjunction with the ``lucid.xhr`` method, you can make calls to custom backends packaged with your app this way.

.. code-block:: javascript

   lucid.xhr({
       url: dojo.moduleUrl("lucid.apps.SystemName", "backends/someFile.php"),
       load: function(data){
           console.log("Returned from backend: "+data);
       }
   })
