titanium desktop programming guides
TRANSCRIPT
Titanium Desktop Programming GuidesThe following are programming guides that provide a more in-depth set of documentation for a particular feature area or capability.
Getting Started
Getting to Know the tiapp.xml File
Using Titanium With Ruby
Using Titanium With Python
Using Titanium With PHP
Packaging on Your Own
Using UserScripts
Building Titanium Desktop from Source
How to create a full screen layout in CSS
Getting to Know the tiapp.xml FileWhen Titanium Developer creates a project templates it creates a generic tiapp.xml file for your project. This file looks like:
<?xml version='1.0' encoding='UTF-8'?>
<!-- These values are edited/maintained by Titanium Developer -->
<id>net.flipflop.flipflopr</id>
<name>FlipFlopr</name>
<version>1.0</version>
<publisher>FlipFlopr Inc.</publisher>
<url>http://flipflopr.info</url>
<icon>default_app_logo.png</icon>
<copyright>2010 by FlipFlopr Inc.</copyright>
<!-- Window Definition - these values can be edited -->
<window>
<id>initial</id>
<title>asdf</title>
<url>app://index.html</url>
<width>700</width>
<max-width>3000</max-width>
<min-width>0</min-width>
<height>500</height>
<max-height>3000</max-height>
<min-height>0</min-height>
<fullscreen>false</fullscreen>
<resizable>true</resizable>
<chrome scrollbars="true">true</chrome>
<maximizable>true</maximizable>
<minimizable>true</minimizable>
<closeable>true</closeable>
</window>
Titanium Developer maintains some of the values of this file and some are up to the Developer to change. It's generally best to modify
thetiapp.xml file when Titanium Developer is not running to avoid collisions when saving the file.
Top-level properties<id>net.flipflop.flipflopr</id>
<name>FlipFlopr</name>
<version>1.0</version>
<publisher>FlipFlopr Inc.</publisher>
<url>http://flipflopr.info</url>
<icon>default_app_logo.png</icon>
<copyright>2010 by FlipFlopr Inc.</copyright>
These properties are maintained by Titanium Developer. While it is possible to change these yourself, you may need to modify the
corresponding values in the manifest file as well.
<analytics>false</analytics>
This setting disables analytics if you do not wish to collect them.
Window elementsThe tiapp.xml file contains one or more window config elements which describe window properties. The first window element listed
will be the main window, which is the window created when your application first starts. Here is a typical window element:
<window>
<id>initial</id>
<title>asdf</title>
<url>app://index.html</url>
<width>700</width>
<max-width>3000</max-width>
<min-width>0</min-width>
<height>500</height>
<max-height>3000</max-height>
<min-height>0</min-height>
<fullscreen>false</fullscreen>
<resizable>true</resizable>
<chrome scrollbars="true">true</chrome>
<maximizable>true</maximizable>
<minimizable>true</minimizable>
<closeable>true</closeable>
</window>
id element
This element specifies the ID of this window config. This allows you to identify windows by ID. Window using this config will return this value
when you call Titanium.UI.currentWindow.getId().
title element
This element specifies the window title. On most systems the window title is visible on the title bar of the window.
url element
This element specifies the intial URL for this window. This may be an app URL such as app://idex.html, which resolves to
the index.htmlfile in the Resources directory of your application. The value of this element should contain an absolute URL.
url-regex element
If you specify a url-regex element for your window, calls to Titanium.UI.createWindow() given only a URL (no
configuration object) which matches against the URL provided wil use this config. For example if your url-regex element looks like:
<url-regex>.*special.*</url-regex>
and then have the code:
Titanium.UI.createWindow("app://special-window.html")
the next window will use this window config. The value of this element should contain a valid PCRE string.
width and height elements
The width and height attributes allow you to specify the initial width and height of your window in pixels. You may modify this setting
by calling window.setHeight() and window.setWidth().
x and y elements
The x and y elements specify the initial screen position of windows using this configuration. All platforms use an origin that is in the top-left
of the screen.
visible element
The value of the visible should either be true or false. A false value here means that the window is initially hidden i.e. the
equivalent of calling Titanium.UI.currentWindow.hide(). A hidden window may be shown by
calling UI.UserWindow.show() orUI.UserWindow.setVisible(true).
max-width, max-height, min-width, and min-height elements
These elements allow you to specify a minimum and maximum width or height for your window. A value of -1 in these fields is equivalent to
having no value specified. These values will override manual settings. For example if you specify:
<max-width>300</max-width>
<width>400</width>
the initial window width will be 300 pixels.
fullscreen element
The value of the fullscreen element should either be true or false. A value of true causes windows with this config to start
in a fullscreened state. A window may modify its fullscreen state UI.UserWindow.setFullscreen();.
maximizable element
The value of the maximizable element should either be true or false. A value of false will make user interface elements
allowing the user to maximize or zoom (OS X) the window hidden. It does not interfere with calls
to UI.UserWindow.maximize() orUI.UserWindow.unmaximize().
maximized element
The value of the maximized element should either be true or false. A value of true will cause the window to started in a
maximized or zoomed state.
minimizable element
The value of the maximizable element should either be true or false. A value of false will make user interface elements
allowing the user to minimize the window hidden. It does not interfere with calls
to UI.UserWindow.minimize() or UI.UserWindow.unminimize().
minimized element
The value of the minimized element should either be true or false. A value of true will cause the window to started in a
minimized state.
closeable element
The value of the closeable element should either be true or false. A value of false will make user interface elements
allowing the user to close the window hidden. It does not interfere with calls to UI.UserWindow.close().
chrome element
The value of the chrome element should either be true or false. A value of false will make create a window with no window
borders and controls. A window created without chrome cannot add it later. Additionally the chrome element has
a srollbars attribute which can be eithertrue or false. A window with a true or undefined value
for scrollbars property will create a scrollbar in the WebView when the content of the view extends beyond the boundaries of the
window.
resizable element
The value of the chrome element should either be true or false. A value of false will make create a window with no window
borders and controls. A window created without chrome cannot add it later.
transparency and transparent-background elements
There are two types of transparency in Titanium. Full window transparency specified with the transparency property and background
transparency specified with the transparent-background property. The transparent element should contain a value
between 0.0 and 1.0 and specifies the opacity of the total window. A window with a transparency value of 0.7 would look like:
The transparent-background property specifies that the WebView in a window has a background which is transparent.
Elements in the WebView may specify different opacities to create non-rectangular windows. Here is an example of a non-rectangular
Titanium window with atransparent-background value of true:
Note that currently the transparent-background property disables all chrome and overrides
the transparency property. If you'd like to allow your users to drag a window by its contents, you can do this via JavaScript:
var dragging = false;
document.onmousemove = function()
{
if (!dragging)
return;
Titanium.UI.currentWindow.setX(Titanium.UI.currentWindow.getX() + event.clientX - xstart);
Titanium.UI.currentWindow.setY(Titanium.UI.currentWindow.getY() + event.clientY - ystart);
}
document.onmousedown = function()
{
dragging = true;
xstart = event.clientX;
ystart = event.clientY;
}
document.onmouseup = function()
{
dragging = false;
}
Using Ruby with Titanium DesktopThe Titanium Desktop SDK includes a Ruby module, which allows developers to run Ruby code from within their applications. Here's a quick
demonstration of what this means:
<script type="text/ruby">
def my_ruby_function(l)
n = 0
l.each { |i| n+=i }
return n
end
</script>
<script>
alert(my_ruby_function([1, 2, 3, 4]));
</script>
The Ruby module currently uses the following version of Ruby depending on your platform:
Windows: Ruby 1.8
OS X (Leopard): Ruby 1.8
OS X (Snow Leopard): Ruby 1.9
Linux (all distributions): Ruby 1.8
It's recommended that you write your code to be compatible with Ruby 1.8.
Including Ruby in your applicationThere are a few ways to include Ruby scripts on your Titanium pages. As demonstrated above, you can include a script tag with
type="text/ruby." If you have a Ruby source file that you want to include you can also do this:
<script type="text/ruby" src="myfile.rb"/>
As well as using script tags to include Ruby, you can use Ruby require. By default your application's Resources directory is on the
Ruby import path, so this is the recommended place to include Ruby source files in your application.
<script type="text/ruby">
require 'myfile.rb'
</script>
The Kroll / Ruby BridgeKroll is the underlying object and communication system in Titanium. It has its own object system, including its own spectrum of types.
Whenever you call Ruby from JavaScript or JavaScript from Ruby, your data will be flowing through Kroll.
NumbersSince all JavaScript Numeric variables are floating-point, when they are passed into Ruby, they will be converted into Ruby Floats. JavaScript
Numerics are converted by value rather than converted by reference.
<script>
var globalNumber = 23;
</script>
<script type="text/ruby">
globalNumber = 13; # globalNumber will change
def changeNumber(number)
number = 10; # globalNumber will not change
end
changeNumber(globalNumber)
</script>
One important result of Kroll using floating point numbers is that if you send a Ruby Integer into JavaScript and then back into Ruby, that
number will always be a Ruby Float.
BooleansJavaScript Booleans are also converted by value directly to a Ruby bool and vice-versa.
Null, undefined and nilJavaScript null and undefined are always converted to Ruby nil. Ruby nil is always converted to JavaScript null.
ObjectsPassing a JavaScript object to Ruby involves wrapping the JavaScript object in a Ruby object. This means that if you change a JavaScript object
in Ruby, that change will be reflected in the original object. When dealing with objects that flow from one language context to another, it
suffices to think of them as the same object.
<script>
var globalObject = new Object();
globalObject.foo = "string";
</script>
<script type="text/ruby">
window.globalObject.foo = "string2"; # globalObject will change
def changeNumber(obj):
# obj is passed by reference so globalObject will change
obj.foo = "string3";
changeNumber(window.globalObject)
</script>
Ruby objects work the same way when moving to JavaScript. Here's an example:
<script type="text/ruby">
class MyObject:
def __init__(self):
self.property = "prop"
def foo(self):
return "foo!"
window.globalObject = MyObject()
</script>
<script>
alert(globalObject.property);
alert(globalObject.foo());
globalObject.property = "propagain"
alert(globalObject.property);
</script>
Ruby objects have different ways to set properties. When setting a property on a Ruby object, Kroll will try to set that property in a few
different ways. Take this code for example:
<script type="text/ruby">
window.globalObject = Object.new()
</script>
<script>
globalObject.foo = "property";
</script>
When the JavaScript code attempts to set the foo property on globalObject, it will attempt several things on the Ruby object:
1. Setting the foo property via the foo= if that method exists.
2. foo= does not exist. Set the foo property via globalObject.instance_variable_set()
Kroll follows a similar pattern when searching for a property.
<script type="text/ruby">
window.globalObject = Object.new()
</script>
<script>
alert(globalObject.foo);
</script>
1. Return the result of globalobject.foo() if it exists. 2. If @foo is defined in globalObject, return that. 3. Otherwise
callglobalObject.method_missing - Return a value if method_missing succeeds. - If a NoMethodError is thrown, return
undefined. - Otherwise throw the exception globalObject.method_missing returned.
HashesRuby hashes can be passed to JavaScript. They will be Objects whose properties are just hash accesses. For instance:
<script type="text/ruby">
window.globalObject = {}
window.globalObject['foo'] = 'string'
</script>
<script>
alert(globalObject.foo);
globalObject.property = "propagain"
</script>
ArraysJavaScript arrays in are wrapped in an Array-like object in Ruby. Be aware that although this object operates much like a Ruby Array, it is not a
true Ruby Array. You should be able to use it just like a Array in most situations though.
<script>
var globalArray = [1, 2, 3, 4];
</script>
<script type="text/ruby">
window.globalArray.each { |item|
Titanium.API.debug(item)
}
</script>
Passing Ruby Arrays to JavaScript will result in a true JavaScript Array. That means that the JavaScript object which wraps the Ruby object will
have an Array prototype and the full complement of JavaScript array methods.
<script type="text/ruby">
window.globalArray = [1, 2, 3, 4];
</script>
<script>
globalArray.push(5);
globalArray.push(6);
var elem = gloalArray.pop(); // should be 6
</script>
ExceptionsExceptions that are thrown in either Ruby or JavaScript will be converted using the same rules as normal variables when bubbling up into
different languages. This means that if an exception is thrown in Ruby, you should be able to catch it in JavaScript and vice-versa.
Using Python with Titanium Desktop
The Titanium Desktop SDK includes a Python module, which allows developers to run Python code from within their applications. Here's a
quick demonstration of what this means:
<script type="text/python">
def my_python_function(l):
return [x+2 for x in l]
</script>
<script>
alert(my_python_function([1, 2, 3, 4]));
</script>
The Python module currently uses the following version of Python depending on your platform:
Windows: Python 2.5
OS X (Leopard): Python 2.5
OS X (Snow Leopard): Python 2.6
Linux (all distributions): Python 2.5
It's recommended that you write your code to be compatible with Python 2.5.
Including Python in your applicationThere are a few ways to include Python scripts on your Titanium pages. As demonstrated above, you can include a script tag with
type="text/python." If you have a Python source file that you want to include you can also do this:
<script type="text/python" src="myfile.py"/>
As well as using script tags to include Python, you can use Python import. By default your application's Resources directory is on the
Python import path, so this is the recommended place to include Python source files in your application.
<script type="text/python">
import myfile
</script>
The Kroll / Python BridgeKroll is the underlying object and communication system in Titanium. It has its own object system, including its own spectrum of types.
Whenever you call Python from JavaScript or JavaScript from Python, your data will be flowing through Kroll.
NumbersSince all JavaScript Numeric variables are floating-point, when they are passed into Python, they will be converted into Python floats.
JavaScript Numerics are converted by value rather than converted by reference.
<script>
var globalNumber = 23;
</script>
<script type="text/python">
globalNumber = 13; # globalNumber will change
def changeNumber(number):
number = 10; # globalNumber will not change
changeNumber(globalNumber)
</script>
One important result of Kroll using floating point numbers is that if you send a Python integer into JavaScript and then back into Python, that
number will always be a Python float.
BooleansJavaScript Booleans are also converted by value directly to a Python bool and vice-versa.
ObjectsPassing a JavaScript object to Python involves wrapping the JavaScript object in a Python object. This means that if you change a JavaScript
object in Python, that change will be reflected in the original object. When dealing with objects that flow from one language context to
another, it suffices to think of them as the same object.
<script>
var globalObject = new Object();
globalObject.foo = "string";
</script>
<script type="text/python">
globalObject.foo = "string2"; # globalObject will change
def changeNumber(obj):
# obj is passed by reference so globalObject will change
obj.foo = "string3";
changeNumber(globalObject)
</script>
Python objects work the same way when moving to JavaScript. Here's an example:
<script type="text/python">
class MyObject:
def __init__(self):
self.property = "prop"
def foo(self):
return "foo!"
globalObject = MyObject()
</script>
<script>
alert(globalObject.property);
alert(globalObject.foo());
globalObject.property = "propagain"
alert(globalObject.property);
</script>
Note: If you attempt to modify a read-only Python object, Kroll will throw an exception.
DictsPython dicts can be passed to JavaScript. They will be Objects whose properties are just dict accesses. For instance:
<script type="text/python">
globalObject = {}
globalObject['foo'] = "string"
</script>
<script>
alert(globalObject.foo);
globalObject.property = "propagain"
</script>
Arrays / ListsJavaScript arrays in are wrapped in a list-like object in Python. Be aware that this object just operates much like a Python list, but is not a true
Python list. You should be able to use it just like a list in most situations though.
<script>
var globalArray = [1, 2, 3, 4];
</script>
<script type="text/python">
for item in globalArray:
Titanium.API.debug(item)
</script>
Passing Python lists to JavaScript will result in a true JavaScript array. That means that the JavaScript object wraps the Python object will have
an Array prototype and the full complement of JavaScript array methods.
<script type="text/python">
globalArray = [1, 2, 3, 4];
</script>
<script>
globalArray.push(5);
globalArray.push(6);
var elem = gloalArray.pop(); // should be 6
</script>
ExceptionsExceptions that are thrown in either Python or JavaScript will be converted using the same rules as normal variables when bubbling up into
different languages. This means that if an exception is thrown in Python, you should be able to catch it in JavaScript and vice-versa.
DOM ManipulationTitanium lets you share and access objects and variables independent of the language. This allows us to access the Javascript
objects documentand window in Python, hence we can manipulate the DOM from within Python.
QuickstartLets set up a very basic demonstration. Create a new project. Be sure to tick the "Python" select box. I'm going to be using jQuery later on in
this tutorial. Include your favorite javascript library.
Navigate to your project and open up the Resources/index.html file. I've created a simple style sheet which just makes everything easier to
see, it's not necessary but will come with the tutorial files.
index.html
<link type="text/css" rel="stylesheet" href="style.css"/>
<input type="submit" id="button" value="Click Me" onclick="change()" />
<div id="output">
This will get replaced when the button is clicked.
</div>
For our basic example we will have a button which, when clicked, will change the contents of a div. As mentioned at the start of this tutorial
thedocument object and all associated methods are available for us to use in Python. Any class, function or variable that you want to pass
from Python back to Javascript must be declared in the window object.
Add the following code to index.html:
<script type="text/python">
def change():
document.getElementById('output').innerHTML='Manipulation via Python'
window.change = change
</script>
And as you can expect, we get something like...
<object width="400" height="300"><param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="movie" value="http://vimeo.com/moogaloop.swf?
clip_id=6441734&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" />
<embed src="http://vimeo.com/moogaloop.swf?
clip_id=6441734&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-
shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed>
</object>
jQuery in PythonJavascript frameworks (such as jQuery) make JavasCript coding a great deal easier. We can use jQuery (and potentially any other Javascript
framework) in our Python code. As you can probably guess we can't use jQuery's $ alias. It errors out. Instead you need to use the
full jQueryfunction. Everything works out of the box - animations (which are very smooth on Titanium) and method chaining.
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<link type="text/css" rel="stylesheet" href="style.css"/>
<script type="text/python">
def jqchange():
jQuery("#output").hide().text("Manipulation in jQuery via Python").fadeIn("slow").animate({"font-size" : "20px"})
window.jqchange = jqchange
</script>
<input type="submit" id="jqbutton" value="jqchange()" onclick="jqchange()" />
<div id="output">
This will get replaced when the button is clicked.
</div>
Using Titanium Desktop with PHPThe Titanium Desktop SDK includes a PHP module, which allows developers to run PHP code from within their applications. Here's a quick
demonstration of what this means:
<script>
function my_php_function($item)
{
$result = array();
for ($index = 0; $index < $item->count(); $index++)
{
$result[] = $item[$index] + 2;
}
return $result;
}
</script>
<script>
alert(my_php_function([1, 2, 3, 4]));
</script>
The PHP module for each platform is bundled with PHP 5.3.1. Your users should not need to install any extra dependencies to use your PHP
code. PHP 4 code is not supported.
Including PHP in your pagesThere are a few ways to include PHP scripts on your Titanium pages. As demonstrated above, you can include a script tag
withtype="text/php." If you have a PHP source file that you want to include there are two ways to accomplish this:
<!-- method one -->
<script type="text/php" src="my_file.php"/>
<!-- method two -->
<script type="text/php">
include("my_other_file.php");
</script>
PHP code included in either of these ways has full access to the DOM and the Titanium object as usual. There is one important difference
between these two methods. When including PHP via the include or require commands you should surround your code with <?php ?> tags. When including via <script> tags, you should not surround your code with <?php ?> tags.
Preprocessed PHPIf you do surround your PHP code with <?php ?> and place it in a file that ends in the .php extension it will be preprocessed.
Preprocessed Titanium works very much like PHP code on an Apache server. The script contents are replaced with the script output before the
content is rendered by the browser. Preprocessed PHP does not have access to the Titanium object and cannot interact directly with the DOM.
Say you have a file named test.php with the contents:
<?php
echo("PHP preprocessed output!");
?>
If you navigate your application to this file, the contents of the web view will be:
PHP preprocessed output!
The Kroll / PHP BridgeKroll is the underlying object and communication system in Titanium. It has its own object system, including its own spectrum of types.
Whenever you call Python from JavaScript or JavaScript from Python, your data will be flowing through Kroll.
NumbersSince all JavaScript Numeric variables are floating-point, when they are passed into PHP, they will be converted into PHP doubles. JavaScript
numerics are converted by value rather than converted by reference.
<script>
var globalNumber = 23;
</script>
<script type="text/php">
$globalNumber = 13; // globalNumber will change
function changeNumber($number)
{
global $globalNumber;
$number = 10; // globalNumber will not change
$globalNumber = 10; // globalNumber will change
}
changeNumber($globalNumber)
</script>
One important result of all Kroll numbers being floating point numbers is that if you send a number into JavaScript and then back into PHP,
that number will always be a PHP double.
BooleansJavaScript Booleans are also converted by value directly to a PHP boolean and vice-versa.
Null and UndefinedJavaScript null and undefined both map to null in PHP. PHP null maps to null in JavaScript.
StringsJavaScript strings maps to PHP strings and PHP strings map to JavaScript strings.
ObjectsPassing a JavaScript object to PHP involves wrapping the JavaScript object in a PHP object. This means that if you change a JavaScript object in
PHP, that change will be reflected in the original object. When dealing with data that flows from one language context to another, it suffices to
think of them as the same object.
<script>
var globalObject = new Object();
globalObject.foo = "string";
</script>
<script type="text/php">
$globalObject->foo = "string2"; # globalObject will change
function changeNumber($obj)
{
# obj is passed by reference so globalObject will change
$obj->foo = "string3";
}
changeNumber($globalObject)
</script>
PHP objects work the same way when moving to JavaScript. Here's an example:
<script type="text/php">
class MyObject {
public $publicVariable;
function __construct()
{
$this->publicVariable = "bar";
}
public function publicMethod()
{
return "foo";
}
}
$globalObject = new MyObject()
</script>
<script>
alert(globalObject.publicVariable);
alert(globalObject.publicMethod());
globalObject.publicVariable = "propagain";
alert(globalObject.publicVariable);
</script>
PHP arrays in JavaScriptPHP arrays, when passed to JavaScript, are Objects whose properties are just dict accesses. For instance:
<script type="text/php">
$globalObject = array();
$globalObject['foo'] = "string";
</script>
<script>
alert(globalObject.foo);
</script>
JavaScript arrays in PHPJavaScript arrays in PHP are wrapped in an object similar to an ArrayObject.
<script>
var globalArray = [1, 2, 3, 4];
</script>
<script type="text/php">
$globalArray->append(3);
$globalArray->append(4);
$window->alert($globalArray[0]);
</script>
JQuery + Titanium + PHP funThanks to @funkatron for this nice mind blowing example:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
</head>
<body>
<div style="border-top:1px solid #404040">
<div style="padding:10px">
Welcome to Titanium
</div>
</div>
<form>
<input type="button" name="invokePHP"
value="Fade-in with PHP" id="invokePHP"/>
</form>
<div id="phpjQ" style="display:none; background-color:black; padding:10px">
This is PHP controlling jQuery
</div>
<script type="text/php">
$jQuery()->ready( function () use (&$jQuery) {
$jQuery('#invokePHP')->live('click', function () use (&$jQuery) {
$jQuery('#phpjQ')->css('color', 'red')->fadeIn(2000);
} );
} );
</script>
</body>
</html>
Known issues1. Top-level classes can be accessed in <script> tags, but they must be prefixed by a top-level namespace specifier.
2. <script type="text/php">
3. $x = new \SimpleXMLElement($someText);
</script>
4. require_once does not seem to work properly. Tinu Coman suggested this workaround:
5. if(!class_exists('MyClass'))
6. {
7. include "class1.php";
8. include "file2.php";
9. include "file3.php";
10. include "file4.php";
}
Packaging on Your OwnThe following is a how-to guide for performing application packaging using the command line.
Locating your SDKFirst, you'll need to locate your SDK. The location of your SDK is dependent on your operating system.
Common Locations OS X: /Library/Application Support/Titanium/sdk Windows: %APPDATA%Titaniumsdk
Linux: ~/.titanium/sdk or /opt/titanium/sdk
Find the scriptOnce you've located your SDK directory, go into the directory based on the operating system your machine is running and the runtime version
you would like to use. So, on an OS X system this would be: /Library/Application Support/Titanium/sdk/osx/0.4.2There will be a number of scripts in this directory, but the one you care about it named tibuild.py. It's a python script that is used for
packaging. This is the same script we use in the Titanium Developer tool as well as on our packaging servers in the cloud. The script is written
in Python so you'll need to execute it using the Python command (or in Unix variants, you can just execute the script directly).
Running the scriptThe script takes a lot of different arguments. Running the script without any arguments will give you the latest documentation on each. Here's
an example usage on OSX:
tibuild.py -d . -s /Library/Application Support/Titanium -r \
-a /Library/Application Support/Titanium/sdk/osx/0.4.0 myapp
Arguments ExplainedIn this example, we're passing a few arguments, which are explained:
-d . says output the resulting distribution into the current directory.
-s /Library/Application Support/Titanium is the source folder where your Titanium is installed. This
is the top level folder.
-r tells the builder to also execute (run) the package after making it. nice for testing
-a /Library/Application Support/Titanium/sdk/osx/0.4.0 is the folder to the assets
directory. The assets directory is underneath the SDK for a specific OS/version and contains additional files like icons, etc needed during the
packaging process.
myapp is the path to the application project folder. This needs to be the root of the folder where the tiapp.xml file lives.
Additional ArgumentsThere are a number of optional arguments you can pass to the packager. Here's some details on just a few:
-t or --type -- You can pass the type of package you want to create - either network (default) or bundle. A bundle means you
want to put everything required to run your application into the app (including the runtime, modules, etc). This means you'll get a bigger
package but means that the application will run without downloading from the network if specific dependencies aren't found on the end-user
machine.
-l or --license -- specify a LICENSE file to use. You can also just name the file LICENSE.txt at the top of your application
project and we'll pick that file up by default.
-n or --noinstall -- don't run the install dialog by default.
LimitationsThere are some inherent limitations in the packaging using the command line. The biggest limitation is that you can only package for the
operating system you're running. When you package in the cloud, the cloud packaging servers will package across all major variants.
However, when you run the packaging scripts locally, you can only package for your operating system / build type.
Packaging Titanium DeveloperTitanium Developer is packaged the same way all other Titanium applications are packaged. In fact, we have built Titanium Developer using
Titanium and it's packaged through the cloud packaging like all other apps. However, how do you package it to run locally?
The easiest is just to check out the source code from the Titanium Developer GitHub project. You can then either import the project directly
into a current version of Titanium Developer, or you can just build it from command line using the above instructions).
Here's how you can run the same command to package developer (using OSX as example):
/Library/Application Support/Titanium/sdk/osx/0.4.2/tibuild.py -d ~/tmp
-a /Library/Application Support/Titanium/sdk/osx/0.4.2 ~/titanium_developer
In this case, titanium_developer is in my $HOME folder. I'm creating the package in my ~/tmp folder.
Using UserScripts (ti.Monkey)Titanium supports Greasemonkey style user scripts for enhancing web content browsed within a titanium
To use:
1. Create a userscripts directory in your app resources directory. Currently any JavaScript file (.js extension) will be
loaded as a userscript.
2. Prefix your JavaScript with the following boilerplate:
3. // ==UserScript==
4. // @name My Fancy UserScript
5. // @author Joe Developer
6. // @description A UserScript which reverses all text on the page
7. // @include *
8. // @version 0.1
// ==/UserScript==
9. To make your userscript pages to only certain places, you can use wildcards in the @include header.
// @include *.html
// @include app://only/this/path/*.html
Building Titanium From SourceRequirements
scons 1.2.0 — build tool
git — version control
OS X OS 10.5 or greater
A recent version of XCode
pkgconfig — install via ports: sudo ports install git pkgconfig
Windows Windows XP SP2 (or greater), Windows Vista, or Windows 7
Visual Studio 2005 with the following:
o Microsoft Visual Studio 2005 Team Suite Service Pack 1
o Visual Studio 2005 Service Pack 1 ATL Security Update
or Visual C++ 2005 Express with the following:
o Microsoft Visual C++ Express 2005 Service Pack 1
o Visual Studio 2005 Service Pack 1 ATL Security Update
Windows Server 2003 Platform SDK 2003 R2
Python 2.5.4 32-bit
Extra steps for Windows Register Platform SDK 2003 with Visual Studio: Start > Programs > Microsoft Platform SDK for Windows Server 2003 R2 > Visual
Studio Registration > Register PSDK Directories with Visual Studio
Add the following to your PATH environment variable: C:Python25;C:Python25Scripts
Linux
Ubuntu / Debian sudo apt-get install build-essential ruby rubygems libzip-ruby scons
libxml2-dev libgtk2.0-dev python-dev ruby-dev libdbus-glib-1-dev libnotify-dev libgstreamer0.10-dev libxss-dev libcurl4-openssl-dev git-core
Fedora sudo yum install gcc gcc-c++ git-core python-devel ruby-devel scons
gtk2-devel gstreamer-devel libnotify-devel libXScrnSaver-devel libcurl-devel
Get the code$ git clone git://github.com/appcelerator/titanium_desktop
$ cd titanium_desktop
$ git submodule update --init
$ cd kroll
$ git checkout master
$ cd ..
Keeping up to dateWhen keeping up to date, it is important to pull both titanium_desktop and kroll:
$ git pull
$ cd kroll
$ git pull
$ cd ..
Building and runningTitanium SDKIf you want to install the Titanium SDK, it's a good idea to first remove any previous SDK installations. To remove only the SDK from a Titanium
install directory simply remove [install directory]/sdks/[version] and not the entire install directory.
To build and install the SDK run:
$ scons debug=1 sdkinstaller run=1
Unit test suite
$ scons debug=1 drillbit run=1
Testapp
$ scons debug=1 testapp run=1
Building distribution packages
$ scons debug=1 dist
How-To: Full Page CSS 3 Layout (Desktop)Published on June 10, 2010 by Kevin Whinnery (Platform Evangelist)
18 Share
Cross-browser full page layouts have long been a pain point for web developers. Luckily, for Titanium Desktop developers, you get to use all
the CSS 3 goodness Webkit has to offer across all platforms! Today we’ll take a look at how to employ CSS 3 Box Layouts- check out some
brief tutorials here and here. Using a few lines of CSS, we can create a flexible fullscreen layout that automatically resizes along with our
window. First, we’ll create the markup for the page. In this case, we’ll want to have a header, a footer, a main content area that takes up the
rest of the available space, and then a sidebar within that flexible space:
<body><div id="app">
<div id="header">This is the header</div><div id="content">
<div id="sidebar">Sidebar</div><div id="main">Main Content</div>
</div><div id="footer">
© 2010 Awesome Productions Ltd.</div>
</div></body>Let’s style the app, header, content, and footer divs first:
html,body {margin:0;padding:0;} #app {
height:100%; /* This sets the containing element up to use a box layout */
display: -webkit-box; /* We want to layout our first container vertically */ -webkit-box-orient: vertical; /* we want our child elements to stretch to fit the container */
-webkit-box-align:stretch;} #header {
height:50px; background-color:#cdcdcd;
} #footer {
height:30px; background-color:#cdcdcd;
} #content { /* content should take up 100% of the rest of the space */
-webkit-box-flex:1;}That’s a good start – here’s what the app would like like at this point:
Now we need to set up the horizontal alignment of our main content. We need to modify the styling for #content to use a horizontal box
layout, and set -webkit-box-flex on the #main div to instruct it to take up the rest of the available space:
#content {-webkit-box-flex:1;display: -webkit-box;
-webkit-box-orient: horizontal;-webkit-box-align:stretch;
} #sidebar { width:120px; background-color:#676767;} #main {
-webkit-box-flex:1;background-color:green;
}Now, when we launch our app, we’ve successfully realized our resizable, flexible layout:
CSS 3 FTW! Hopefully this technique will be useful to you when creating your next desktop application’s layout. The complete source code for
this application (which you should be able to drop in and run in the Titanium Developer desktop Sandbox), is embedded from Gist below:
<html><head><style>html,body {margin:0;padding:0;}
#app { height:100%;display: -webkit-box;
-webkit-box-orient: vertical;-webkit-box-align:stretch;
}
#header { height:50px; background-color:#cdcdcd;
}
#footer { height:30px; background-color:#cdcdcd;
}
#content {-webkit-box-flex:1;
display: -webkit-box; -webkit-box-orient: horizontal;
-webkit-box-align:stretch;}
#sidebar { width:120px; background-color:#676767;}
#main {-webkit-box-flex:1;background-color:green;
}</style></head><body>
<div id="app"><div id="header">This is the header</div><div id="content">
<div id="sidebar">Sidebar</div><div id="main">Main Content</div>
</div><div id="footer">
© 2010 Awesome Productions Ltd.</div>
</div></body></html>view raw full-page-css3.html This Gist brought to you by GitHub.
This entry was posted on Thursday, June 10th, 2010 at 10:28 am and is filed under Desktop, Tutorial. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.