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 Don@Scorgie.org.  
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
