--------------------------------------------------------------------------------
--                                                                            --
-- Copyright (C) 2004, RISC OS Ada Library (RASCAL) developers.               --
--                                                                            --
-- This library is free software; you can redistribute it and/or              --
-- modify it under the terms of the GNU Lesser General Public                 --
-- License as published by the Free Software Foundation; either               --
-- version 2.1 of the License, or (at your option) any later version.         --
--                                                                            --
-- This library is distributed in the hope that it will be useful,            --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of             --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU           --
-- Lesser General Public License for more details.                            --
--                                                                            --
-- You should have received a copy of the GNU Lesser General Public           --
-- License along with this library; if not, write to the Free Software        --
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    --
--                                                                            --
--------------------------------------------------------------------------------

-- @brief ToolboxTreeView related types and methods.
-- $Author$
-- $Date$
-- $Revision$

with System;                     use System;
with System.Unsigned_Types;      use System.Unsigned_Types;

with RASCAL.Toolbox;             use RASCAL.Toolbox;
with RASCAL.OS;                  use RASCAL.OS;
with RASCAL.Sprite;              use RASCAL.Sprite;

package RASCAL.ToolboxTreeView is

   Empty_Tree : exception;

   type Node_List_Type is array (natural range <>) of Integer;
   type Node_List_Pointer is access Node_List_Type;

   -- Flags
   TreeView_AddNode_NoData        : constant := 2#0000000000000010#;
   TreeView_AddNode_AsChild       : constant := 2#0000000000000001#;
   TreeView_AddNode_AsSibling     : constant := 2#0000000000000000#;   

   TreeView_NodeSelected_Selected : constant := 2#0000000000000001#;
   TreeView_NodeSelected_Multiple : constant := 2#0000000000000010#;

   TreeView_AllowVScroll          : constant := 2#0000000000000001#;
   TreeView_AllowHScroll          : constant := 2#0000000000000010#;
   TreeView_AutoUpdate            : constant := 2#0000000000000100#;
   TreeView_Show_CurrentNode      : constant := 2#0000000000001000#;
   TreeView_PlotLines             : constant := 2#0000000000010000#;
                                  
   TreeView_AllowSelection        : constant := 2#0000000000100000#;
   TreeView_NotifySelection       : constant := 2#0000000001000000#;
   TreeView_SelectChildren        : constant := 2#0000000010000000#;
                                  
   TreeView_AllowExpand           : constant := 2#0000000100000000#;
   TreeView_NotifyExpansion       : constant := 2#0000001000000000#;
   TreeView_ExpandByDefault       : constant := 2#0000010000000000#;
                                  
   TreeView_AllowRename           : constant := 2#0000100000000000#;
   TreeView_NotifyRename          : constant := 2#0001000000000000#;
                                  
   TreeView_AllowDrags            : constant := 2#0010000000000000#;
   TreeView_NotifyDragEnd         : constant := 2#0100000000000000#;
                                  
   TreeView_AllEvents             : constant := 2#1000000000000000#;

   --
   -- Event which is sent when a node is selected or deselected.
   --Flag bit 0 is {/}set{/} for a selection and {/}unset{/} for a deselectio.
   --If the tree has the 'Select Children' flag set, and this selection caused more than one node to change selection state, flag bit 1 is set.
   --
   type Toolbox_TreeView_NodeSelected is
   record
   Header: Toolbox_Event_Header;
   Flags : System.Unsigned_Types.unsigned;
   Node  : Integer;
   end record;
   pragma Convention (C, Toolbox_TreeView_NodeSelected);

   type Toolbox_TreeView_NodeSelected_Pointer is access Toolbox_TreeView_NodeSelected;

   type ATEL_Toolbox_TreeView_NodeSelected is abstract new
             Toolbox_EventListener(Toolbox_Event_TreeViewNodeSelected,-1,-1) with
   record
   Event : Toolbox_TreeView_NodeSelected_Pointer;
   end record;

   TreeView_NodeExpanded_Expanded  : constant := 2#0000000000000001#;

   --
   -- Event which is sent when a node is expanded or unexpanded.
   --Flag bit 0 is {/}set{/} if the node was expanded, and zero otherwise.
   --
   type Toolbox_TreeView_NodeExpanded is
   record
   Header: Toolbox_Event_Header;
   Flags : System.Unsigned_Types.unsigned;
   Node  : Integer;
   end record;
   pragma Convention (C, Toolbox_TreeView_NodeExpanded);

   type Toolbox_TreeView_NodeExpanded_Pointer is access Toolbox_TreeView_NodeExpanded;

   type ATEL_Toolbox_TreeView_NodeExpanded is abstract new
             Toolbox_EventListener(Toolbox_Event_TreeViewNodeExpanded,-1,-1) with
   record
   Event : Toolbox_TreeView_NodeExpanded_Pointer;
   end record;

   --
   --
   --
   type Toolbox_TreeView_NodeRenamed is
   record
   Header: Toolbox_Event_Header;
   Flags : System.Unsigned_Types.unsigned;
   Node  : Integer;
   end record;
   pragma Convention (C, Toolbox_TreeView_NodeRenamed);

   type Toolbox_TreeView_NodeRenamed_Pointer is access Toolbox_TreeView_NodeRenamed;

   type ATEL_Toolbox_TreeView_NodeRenamed is abstract new
             Toolbox_EventListener(Toolbox_Event_TreeViewNodeRenamed,-1,-1) with
   record
   Event : Toolbox_TreeView_NodeRenamed_Pointer;
   end record;


   --
   --
   --
   type Toolbox_TreeView_NodeDataRequired is
   record
   Header: Toolbox_Event_Header;
   Flags : System.Unsigned_Types.unsigned;
   Node  : Integer;
   end record;
   pragma Convention (C, Toolbox_TreeView_NodeDataRequired);

   type Toolbox_TreeView_NodeDataRequired_Pointer is access Toolbox_TreeView_NodeDataRequired;

   type ATEL_Toolbox_TreeView_NodeDataRequired is abstract new
             Toolbox_EventListener(Toolbox_Event_TreeViewNodeDataRequired,-1,-1) with
   record
   Event : Toolbox_TreeView_NodeDataRequired_Pointer;
   end record;

   TreeView_NodeExpanded_NodeDragged_OutsideGadget : constant := 2#0000000000000001#;

   --
   -- Sent when a node is dragged (if the 'Notify Drag' flag is set).
   --Bit 0 of the flags word is set if the drag ended outside the TreeView gadget, otherwise it is zero.
   --{/}Destination_Node{/} is the node handle that the drag ended on if it ended inside the gadget. If the drag didn't end on a node, this is Zero.
   --
   type Toolbox_TreeView_NodeDragged is
   record
   Header           : Toolbox_Event_Header;
   Flags            : System.Unsigned_Types.unsigned;
   Node             : Integer;
   Destination_Node : Integer;
   Pointer          : Address;
   end record;
   pragma Convention (C, Toolbox_TreeView_NodeDragged);

   type Toolbox_TreeView_NodeDragged_Pointer is access Toolbox_TreeView_NodeDragged;

   type ATEL_Toolbox_TreeView_NodeDragged is abstract new
             Toolbox_EventListener(Toolbox_Event_TreeViewNodeDragged,-1,-1) with
   record
   Event : Toolbox_TreeView_NodeDragged_Pointer;
   end record;

   --
   -- Sets the TreeView_Flags.
   --
   procedure Set_State (Window    : in Object_ID;
                        Component : in Component_ID;
                        State     : in System.Unsigned_Types.unsigned;
                        Flags     : in System.Unsigned_Types.unsigned :=0);

   --
   -- Returns the current TreeView_Flags.
   --
   function Get_State (Window    : in Object_ID;
                       Component : in Component_ID;
                       Flags     : in System.Unsigned_Types.unsigned := 0) return System.Unsigned_Types.unsigned;

   --
   -- Adds a new node after the current one.
   --If the TreeView_AutoUpdate flag is not set, changes will not be visible until TreeView_UpdateDisplay is called.
   --
   function Add_Node (Window    : in Object_ID;
                      Component : in Component_ID;
                      Text      : in String;
                      Flags     : in System.Unsigned_Types.unsigned := 0) return integer;

   --
   -- Returns a unique 32 bit handle for the current node.
   --
   function Get_NodeID (Window    : in Object_ID;
                        Component : in Component_ID;
                        Flags     : in System.Unsigned_Types.unsigned := 0) return integer;

   --
   -- Sets the text for the current node. You can set it to NULL (0) for no text.
   --
   procedure Set_NodeText (Window    : in Object_ID;
                           Component : in Component_ID;
                           Text      : in String;
                           Flags     : in System.Unsigned_Types.unsigned := 0);

   --
   -- Specifies a sprite to use for a node in the tree.
   --You can use a sprite in your own area in which case supply the sprite area pointer, or a sprite in the wimp pool in which case supply a sprite area pointer of 1.
   --The expanded sprite is the sprite used when the node has an expanded child. Supply NULL in this parameter if you don't want an expanded sprite.
   --
   procedure Set_NodeSprite (Window      : in Object_ID;
                             Component   : in Component_ID;
                             Name        : in String;
                             Exp_Name    : in String := "";
                             Sprite_Area : in Sprite_Area_Ptr := null;
                             Flags       : in System.Unsigned_Types.unsigned := 0);

   --
   -- Sets the private word of the current node. This is a 32 bit value that you can use to signify anything you like. It is not used by the TreeView.
   --
   procedure Set_NodePrivateWord (Window    : in Object_ID;
                                  Component : in Component_ID;
                                  Word      : in integer;
                                  Flags     : in System.Unsigned_Types.unsigned := 0);

   --
   -- Copies the current node's text into a buffer, or if the pointer to the buffer passed to the method is NULL, returns the size of buffer required to hold the node's text.
   --
   function Get_NodeText (Window    : in Object_ID;
                          Component : in Component_ID;
                          Flags     : in System.Unsigned_Types.unsigned := 0) return String;
                          
   --
   -- Copies the current node's sprite name into a buffer. If flag bit 0 is set the expanded sprite name is copied, otherwise the normal one is.
   --If the supplied buffer pointer is NULL, the size of buffer required to hold the sprite name is returned.
   --
   function Get_NodeSprite (Window    : in Object_ID;
                            Component : in Component_ID;
                            Flags     : in System.Unsigned_Types.unsigned := 0) return String;

   --
   -- Returns the current node's private word.
   --
   function Get_NodePrivateWord (Window    : in Object_ID;
                                 Component : in Component_ID;
                                 Flags     : in System.Unsigned_Types.unsigned := 0) return integer;

   --
   -- Sets the current node to the one specified by the unique handle. This is the handle as returned from TreeView_GetNodeID.
   --WARNING - trying to move to a non existant node is not yet fully trapped.
   --
   procedure Move_To (Window    : in Object_ID;
                      Component : in Component_ID;
                      Node      : in Integer;
                      Flags     : in System.Unsigned_Types.unsigned :=0);

   --
   -- Sets the current node to its next sibling. If there is no next node, an error is returned and the current node does not change.
   --The returned value is the unique id of the new current node.
   --
   function Move_Next (Window    : in Object_ID;
                       Component : in Component_ID;
                       Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   -- Sets the current node to its previous sibling. If there is no previous node, an error is returned and the current node does not change.
   --The returned value is the unique id of the new current node.
   --
   function Move_Previous (Window    : in Object_ID;
                           Component : in Component_ID;
                           Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   -- Sets the current node to the current node's child. If the current node has no child, an error (-1) is returned and the current node does not change.
   --The returned value is the unique id of the new current node.
   --
   function Move_Child (Window    : in Object_ID;
                        Component : in Component_ID;
                        Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   --Sets the current node to the current node'sparent. Note that all nodes have a parent.
   --The parent of the root node of a tree is itself. The returned value is the unique id of the new current node.
   --
   function Move_Parent (Window    : in Object_ID;
                         Component : in Component_ID;
                         Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   -- Deletes the current node, and any descendants it has ({/}ie{/} its child and any nodes connected to the child).
   --If the {/}TreeView_AutoUpdate{/} flag is not set, changes will not be visible until TreeView_UpdateDisplay is called.
   --The returned value is the unique id of the new current node.
   --
   function Delete_Node (Window    : in Object_ID;
                         Component : in Component_ID;
                         Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   -- Deletes the entire tree.
   --If the {/}TreeView_AutoUpdate{/} flag is not set, changes will not be visible until TreeView_UpdateDisplay is called.
   --
   procedure Delete_All (Window    : in Object_ID;
                         Component : in Component_ID;
                         Flags     : in System.Unsigned_Types.unsigned :=0);

   --
   -- Ensures the gadget's display is up to date.
   --If the {/}TreeView_AutoUpdate{/} flag is set, the gadget will update itself after every change.
   --However this could be {/}really slow{/} if you are adding large numbers of nodes all at once.
   --
   procedure Update_Display (Window    : in Object_ID;
                             Component : in Component_ID;
                             Flags     : in System.Unsigned_Types.unsigned := 0);


   --
   -- Moves the current node to the first selected node. Returns an error if there is no selection.
   --This call in combination with TreeView_MoveNextSelected allows you to enumerate through all the selected nodes in a tree.
   --The returned value is the unique id of the new current node.
   --Note that the "first" selected node is not necessarily the node nearest to the top of the tree.
   --The only guarantee is that enumerating through the selected nodes using this call will visit each selected node exactly once.
   --
   function Move_FirstSelected (Window    : in Object_ID;
                                Component : in Component_ID;
                                Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   -- Moves the current node to the next selected node.
   --Returns an error if there is no such node, otherwise returns the unique id of the new current node.
   --
   function Move_NextSelected (Window    : in Object_ID;
                               Component : in Component_ID;
                               Flags     : in System.Unsigned_Types.unsigned :=0) return integer;

   --
   -- Return true if the tree is empty.
   --
   function Is_Empty (Window    : in Object_ID;
                      Component : in Component_ID;
                      Flags     : in System.Unsigned_Types.unsigned :=0) return boolean;

   --
   -- Has any item been selected ? Preserves current node setting.
   --
   function Is_Selection (Window    : in Object_ID;
                          Component : in Component_ID;
                          Flags     : in System.Unsigned_Types.unsigned :=0) return Boolean;

   --
   -- Returns the number of currently selected nodes. Current node setting is preserved.
   --
   function Count_Selections (Window    : in Object_ID;
                              Component : in Component_ID;
                              Flags     : in System.Unsigned_Types.unsigned :=0) return Integer;

   --
   -- Returns an array containing the id numbers of all selected nodes. Current node setting is preserved.
   --
   function Get_Selections (Window    : in Object_ID;
                            Component : in Component_ID;
                            Flags     : in System.Unsigned_Types.unsigned :=0) return Node_list_Type;

   --
   -- Returns the number of nodes in a tree. Current node setting is preserved.
   --
   function Count_Children (Window    : in Object_ID;
                            Component : in Component_ID;
                            Node      : in Integer;
                            Flags     : in System.Unsigned_Types.unsigned :=0) return Integer;

   --
   -- Returns an array with ids for all nodes in a tree. Current node setting is preserved.
   --
   function Get_Children (Window    : in Object_ID;
                          Component : in Component_ID;
                          Node      : in Integer;
                          Flags     : in System.Unsigned_Types.unsigned :=0) return Node_List_Type;

   --
   -- Returns the node id of the root which also becomes the current node.
   --
   function Get_Root (Window    : in Object_ID;
                      Component : in Component_ID;
                      Flags     : in System.Unsigned_Types.Unsigned :=0) return Integer;

   --
   -- Returns true if the current node is the root of the tree. It remains current root even if its not the root.
   --
   function Is_Root (Window    : in Object_ID;
                     Component : in Component_ID;
                     Flags     : in System.Unsigned_Types.Unsigned :=0) return Boolean;

end RASCAL.ToolboxTreeView;
