Getting Started #
GraffitiBundle can be added to existing Web projects — to expand functionality as a desktop companion app — or new Web projects.
To add GraffitiBundle to your project, follow these simple steps:
- Extract the downloaded archive
- Open the bundle-web Xojo project
- Select the “GraffitiBundle” module in the IDE’s project navigator (left-hand pane)
- Right-click and select “Copy”
- Open the destination project where you wish to implement GraffitiBundle
- Select Edit > Paste from the menubar
To implement GraffitiBundle, the easiest way is to added the following property to your Session object:
Public Property controller As GraffitiBundle.Controller
Then, in the Session Opening event, add the following code replacing <YourBundleID>
with a unique string identifying your application pair (these IDs must be identical for the Web and Desktop applications), something like com.mycompany.myapplication
:
controller = new GraffitiBundle.Controller( self.Identifier )
controller.BundleID = "<YourBundleID>"
Now, in your App object’s Opening event, you can add the following code if you wish for your app to serve requests other than those from a GraffitiBundle client application:
GraffitiBundle.Controller.BundleRequestsOnly = False
Next, in your App.HandleURL event, add the following code to direct requests to GraffitiBundle and cancel further processing if those requests have been handled:
if GraffitiBundle.Controller.HandleURL( request, response ) then Return True
Finally, add a Receiver to your page(s) by dragging a GraffitiBundle.Receiver from the project navigator to your destination page(s). Receivers will intercept all events emitted by the GraffitiBundle controller, but need to be added to the controller in order to function. Remember that any added receiver will have all events raised, so you may need to devise a method of determining which events are meant for which receivers if you plan to implement a multi-page application.
Once you’ve added a receiver to a page, add it to the controller by using the following code:
Session.controller.AddReceiver( Receiver1 )
When closing a page, be sure to remove that page’s receiver:
Session.controller.RemoveReceiver( Receiver1 )
Now you’re ready to implement the events of the receiver and use the methods of the Session.controller object to communicate with a GraffitiBundle client application.
File Path Tokens #
While GraffitiBundle child Web applications distributed with a client Desktop application will have, depending on system security, unfettered access to the file system on their own, GraffitiBundle Desktop does incorporate some helpers. Path tokens are replaced in real-time when a path operation is passed from the Web application to the Desktop application. This allows you to build URI paths such as the following to reference a file named “test.txt” on the user’s desktop:
{desktop}/test.txt
Various tokens have been provided:
Token | Equivalent |
---|---|
{app} | Path to the client Desktop application. |
{appuser} | Path to the user’s local storage directory (IE: /Users/TomSelleck/Library/Application Support/com.graffitisuite.bundledemo ). |
{appchild} | Path to the child application directory in the user’s local storage directory (IE: {appuser}/application ). |
{appdata} | SpecialFolder.ApplicationData |
{desktop} | SpecialFolder.Desktop |
{documents} | SpecialFolder.Documents |
{home} | SpecialFolder.UserHome |
{library} | SpecialFolder.UserLibrary |
{preferences} | SpecialFolder.Preferences |
{fonts} | SpecialFolder.Fonts |
{resources} | SpecialFolder.Resources |
{temporary} | SpecialFolder.Temporary |
{sharedappdata} | SpecialFolder.SharedApplicationData |
{shareddesktop} | SpecialFolder.SharedDesktop |
{shareddocuments} | SpecialFolder.SharedDocuments |
{sharedpreferences} | SpecialFolder.SharedPreferences |
Additionally, as a basic security measure, directory traversal is not allowed using “..” or “.” path parts, even though full URI paths may be passed to functions.
DirectoryListingReceived JSONItem Contents #
The DirectoryListingReceived event has a data as JSONItem
parameter. This JSONItem will be an object containing the original path and an array of data representing the files with the following child item properties that match those of the FolderItems:
Key | Value |
---|---|
path | FolderItem.ShellPath |
name | FolderItem.Name |
isFolder | FolderItem.IsFolder |
length | FolderItem.Length |
creationDateTime | FolderItem.CreationDateTime |
modificationDateTime | FolderItem.ModificationDateTime |
isReadable | FolderItem.IsReadable |
isWriteable | FolderItem.IsWriteable |
nativePath | FolderItem.NativePath |
owner | FolderItem.Owner |
permissions | FolderItem.Permissions |
type | FolderItem.Type |
Example:
var path as String = data.Lookup( "path", "" ).StringValue
labelPath.Text = path
var children as JSONItem = data.Lookup( "children", nil )
if children = nil then Return
var max as Integer = children.LastRowIndex
var child as JSONItem
for index as Integer = 0 to max
child = children.ValueAt(index)
listChildren.AddRow( child.Value( "name" ).StringValue, child.Value( "length" ).StringValue )
listChildren.RowTagAt( listChildren.LastAddedRowIndex ) = child.Value( "path" )
next