LAST UPDATE: 6th October 2006

0. Preamble
-----------

This describes the current save format for Labyrinth maps.  It is intended to make life easier for anyone interested in accessing them or importing them.

WARNING: At the time of writing, Labyrinth is at version 0.2.  The file format is liable to change up to V1.0.  The format described here isn't the final version.  I'll keep this file up to date with any changes that happen to the format.  The date at the top of the file states when this was last updated.

1. Location
-----------

Currently, Labyrinth stores its files "internally".  The files themselves can be found in the $HOME/.gnome2/labyrinth/ folder with a format like f59b62e734f3f65a1e34d7bf1fc33bb191c3777f.map.  That is to say <hexdigest>.map though labyrinth will attempt to read any .map file in that folder.  The hexdigest is created using the sha of the generated XML the first time the file is saved.

Currently, Labyrinth is unable to import / export in other formats (hey, its only at v0.2).  This is (potentially) planned for V0.3.

The maps are saved in standard (i.e. non-pretty) XML - all nodes on 1 line.  This makes them difficult to read, but makes the formatting come out properly within text thoughts.  Pretty formatting + python seems to screw up the text thought formatting in some cases.

2. Format
---------

The basic format is a flat XML file.  The file starts with the XML declaration:
<?xml version="1.0" ?>

An example top-level node is:
<MMap mode="0" number="1" position="(35, 97)" size="(523, 609)" title="Labyrinth 0.2">
All other nodes are children of this.

MMap is the name of the node (duh).  All files must have this.  In addition, each of the Attributes are required to form a valid file:

Attribute				Description
-----------------------------------
mode					The current "mode" Labyrinth is working in for that map
						1: "Edit" mode - typing into thoughts, linking thoughts, resizing thoughts (if available)
						2: "Move" mode - move thoughts around
						3: "Image" mode - add an (external) image to the map.  Clicking somewhere will pop up a
						   dialog to select the image file
						4: "Drawing" mode - With drawing thoughts (described below), draw within thoughts.
						   Otherwise, add new drawing thought and begin drawing (in empty space)
						   
number					Current map number.  Used internally to set initial title.  Can be set to any number.
						(Currently broken.  I think)

position				Screen location (in pixels) of upper-left corner of map window

size					Size (in pixels) of map window

title					Map name.  Generally same as primary root text

3. Children
-----------

The children are the "meat" of the map.  They come in several flavours, described in subsections here

3.1. Links
----------

Unlike other programs (I believe), Labyrinth stored links as top-level objects.  That is to say, they don't actually belong to thoughts.

An example link might look like:
<link child="6" end="(437.5, 55.5)" parent="1" start="(324.0, 79.0)" strength="2"/>

Again, all attributes must be specified (sorry!)

Attribute					Description
---------------------------------------
child						The thought number of the child thought connected by the link

parent						The thought number of the originating thought for the link

start						Canvas coordinates of the start location (parent location) for the link

end							Canvas coordinates of the end location (child location) for the link

strength					The "Strength" of the link.  In Labyrinth, specifies the line width in pixels.  Integer value
							always (for now).

3.2. Thoughts
-------------

Thoughts, in Labyrinth-speak, are the text, images and drawing that appear on the canvas.  There are 3 types currently and each have some attributes in common.

The three types are: Text, Image and Drawing.  Text is (surprisingly) text thoughts.  Image thoughts are external images while drawings are "internal" images - simple lines that the user has drawn to make simple diagrams.

3.2.1. Common Attributes
------------------------

As stated above, thoughts have several attributes that may be set that are common across all thought types:

Attribute					Description
---------------------------------------
current_root				If set, the thoughts is "selected" - any new thoughts are automatically linked to this one
							(Currently, only 1 may be set.  In Labyrinth, they show up as blue)

primary_root				The "Major thought" for the map.  Generally, places at the centre of the map
							(Only 1 may be set.  In Labyrinth, they show up as reddish-pink)

ul-coords					The upper-left canvas coords for the thought

lr-coords					The lower-right canvas coords for the thought

identity					The thought number (for link child / parent numbers and other things internally)

Current_root and primary_root are only set when the thought is actually current root or primary root respectively.  Otherwise, these are not set.  Examples of these are given later.

3.2.2. Text Thoughts
--------------------

<thought cursor="13" identity="0" edit="true" lr-coords="(249.0, 196.0)" ul-coords="(161.0, 174.0)">Labyrinth 0.2</thought>

Text thoughts are denoted by "thought" XML elements.  In addition to the common attributes, there are several more available

Attribute					Description
---------------------------------------
cursor						Cursor location in text.  Specified in terms of characters.

edit						Whether the current node is being edited.  Thoughts being edited don't get a full box
							drawn around then, instead only a small sector is drawn in the upper-left corner in Labyrinth


The text within the XML node is as should be displayed onscreen (i.e. line-breaks mean the line breaks at that point within the thought).  As before, "edit" is only set if the thought is currently being edited.

3.2.3. Image Thoughts
---------------------

<image_thought file="/home/don/Pictures/Picture.jpg" identity="6" image_height="80.0" image_width="136.0" lr-coords="(508.0, 98.0)" ul-coords="(367.0, 13.0)"/>

Attribute					Description
---------------------------------------
file						The file path for the image to use within the thought

image_height				Labyrinth can resize images.  This gives the current height the image should be

image_width					Ditto above for width


3.2.4. Drawing Thoughts
-----------------------

<drawing_thought identity="1" lr-coords="(184.0, 463.0)" max_x="165.0" max_y="463.0" min_x="83.0" min_y="212.0" ul-coords="(79.0, 190.0)"><point coords="(146.0, 222.0)" type="2"/><point coords="(144.0, 232.0)" type="0
"/><point coords="(164.0, 65.0)" type="1"/></drawing_thought>

The "big one".  Children of the drawing thought are all the points that make up the image.  Before that, the attributes for the drawing_thought itself.

Attribute					Description
---------------------------------------
max_{x,y}					The {x,y} location of the furthest {right,down} points of the drawing.
							Used to determine where the thought can be resized to (i.e. right edge cannot be dragged
							left of max_x and similar for max_y)

min_{x,y}					Same for {left, top} points


3.2.4.1. Children
-----------------

Each child node is another point to draw.  It is assumed (under normal circumstances) that each point is connected with a straight line.

The coords give the canvas coordinates of the point.  The "type" can be  of (currently) 3 types:
0: Continue
Draw a line from  the previous point to this one

1: End
End of a line segment

2: Begin
Move from the previous point to this one without drawing

3.3 Examples
------------

An example file might look like:
<?xml version="1.0" ?>
<MMap mode="3" number="1" position="(50, 73)" size="(500, 580)" title="i"><thought cursor="1" identity="0" lr-coords="(169.0, 181.0)" primary_root="true" ul-coords="(161.0, 159.0)">i</thought><thought cursor="3" identity="1" lr-coords="(313.0, 115.0)" ul-coords="(295.0, 93.0)">jkl</thought><link child="1" end="(304.0, 104.0)" parent="0" start="(165.0, 170.0)" strength="2"/><thought cursor="1" identity="2" lr-coords="(339.0, 311.0)" ul-coords="(321.0, 289.0)">m</thought><link child="2" end="(330.0, 300.0)" parent="0" start="(165.0, 170.0)" strength="2"/><thought current_root="true" cursor="1" identity="4" lr-coords="(375.0, 209.0)" ul-coords="(362.0, 187.0)">p</thought><link child="4" end="(368.5, 198.0)" parent="0" start="(165.0, 170.0)" strength="2"/><thought cursor="1" identity="5" lr-coords="(174.0, 239.0)" ul-coords="(166.0, 217.0)">i</thought><link child="5" end="(170.0, 228.0)" parent="0" start="(165.0, 170.0)" strength="2"/><thought cursor="1" identity="6" lr-coords="(189.0, 364.0)" ul-coords="(181.0, 342.0)">j</thought><link child="6" end="(185.0, 353.0)" parent="0" start="(165.0, 170.0)" strength="2"/><thought cursor="4" identity="8" lr-coords="(82.0, 342.0)" ul-coords="(65.0, 320.0)">jjjj</thought><link child="8" end="(73.5, 331.0)" parent="0" start=
"(165.0, 170.0)" strength="2"/></MMap>

Or, in more human-readable format:

<?xml version="1.0" ?>
<MMap mode="3" number="1" position="(50, 73)" size="(500, 580)" title="i">
<thought cursor="1" identity="0" lr-coords="(169.0, 181.0)" primary_root="true" ul-coords="(161.0, 159.0)">i</thought>
<thought cursor="3" identity="1" lr-coords="(313.0, 115.0)" ul-coords="(295.0, 93.0)">jkl</thought>
<link child="1" end="(304.0, 104.0)" parent="0" start="(165.0, 170.0)" strength="2"/>
<thought cursor="1" identity="2" lr-coords="(339.0, 311.0)" ul-coords="(321.0, 289.0)">m</thought>
<link child="2" end="(330.0, 300.0)" parent="0" start="(165.0, 170.0)" strength="2"/>
<thought current_root="true" cursor="1" identity="4" lr-coords="(375.0, 209.0)" ul-coords="(362.0, 187.0)">p</thought>
<link child="4" end="(368.5, 198.0)" parent="0" start="(165.0, 170.0)" strength="2"/>
<thought cursor="1" identity="5" lr-coords="(174.0, 239.0)" ul-coords="(166.0, 217.0)">i</thought>
<link child="5" end="(170.0, 228.0)" parent="0" start="(165.0, 170.0)" strength="2"/>
<thought cursor="1" identity="6" lr-coords="(189.0, 364.0)" ul-coords="(181.0, 342.0)">j</thought>
<link child="6" end="(185.0, 353.0)" parent="0" start="(165.0, 170.0)" strength="2"/>
<thought cursor="4" identity="8" lr-coords="(82.0, 342.0)" ul-coords="(65.0, 320.0)" edit="true">jjjj</thought>
<link child="8" end="(73.5, 331.0)" parent="0" start="(165.0, 170.0)" strength="2"/>
</MMap>


Here, Thought 0 (first thought in list) is the "primary root" (i.e. main thought) with the contents "i" - same as the title of the map (as expected).

Thought 4 (content "p") is the current root.  All future thoughts will automagically link to that one until current_root is changed.

Thought 8 (content 'jjjj') is currently being edited.  All the links have a strength of 2.

4. Conclusion
-------------

That's it.  If there's anything unclear about this document, or something could be better explained, please let me know and I'll try and clarify.  I normally respond to email quite quickly on DonScorgie@Blueyonder.co.uk.  If you do implement importing of Labyrinth maps, please let me know and I'll add a nice link on the Labyrinth homepage.  If you want Labyrinth to import maps from you're app, again let me know and I'll look into it.  If you have a sample map, that'd be great.  If you have the specs for the file format, even better :)

Don
