--------------------------------------------------------------------------------
--                                                                            --
-- 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 Menu related types and methods.
-- $Author$
-- $Date$
-- $Revision$

with RASCAL.OS;             use RASCAL.OS;
with RASCAL.Memory;         use RASCAL.Memory;
with System.Unsigned_Types; use System.Unsigned_Types;
with System;                use System;

package RASCAL.WimpMenu is

   too_many_menu_items : Exception;
   
   -- Abstract data type for menu creation/manipulation
   --first item is 0!
   type Menu_Type is private;
   subtype Icon_Data_String is Char_Array (1..12);

   --
   -- Initialises a Menu object (of Type Menu_Type)
   -- "items" is the maximum number of allowed Menu entries
   --
   function Init (Items : in Natural) return Menu_Type;

   --
   -- Opens a Menu using the Menu structure at address "MenuPtr"
   --direct wrap to Wimp_CreateMenu
   --
   procedure Create (MenuPtr : in Integer;
                     X       : in Integer;
                     Y       : in Integer);

   --
   -- Opens a submenu using the menu structure at address "MenuPtr"
   --direct wrap to Wimp_CreateSubMenu
   --
   procedure Create_SubMenu (MenuPtr : in Integer;
                             X       : in Integer;
                             Y       : in Integer);

   --
   -- Opens a Menu at the given position
   --
   procedure Open (Menu : in Menu_Type;
                   X    : in Integer;
                   Y    : in Integer);

   --
   -- Reopens the last opened Menu at the last position
   --(necessary if the user clicked with adjust button)
   --
   procedure Reopen;

   --
   -- Opens menu as a submenu at the given position.
   --
   procedure Open_SubMenu (Menu : in Menu_Type;
                           X    : in Integer;
                           Y    : in Integer);
                           
   --
   -- Closes the active Menu
   --
   procedure Close;

   --
   -- Returns the currently displayed Menu
   --
   function Current return Menu_Type;

   --
   -- Sets the Menu title
   --
   procedure Set_Title (Menu  : in Menu_Type;
                        Title : in String);

   --
   -- Gets the Menu title
   --
   function Get_Title (Menu : in Menu_Type) return String;

   --
   -- Gets the Menu title
   --
   function Get_Item (Menu : in Address;
                      Item : in Natural) return String;

   --
   -- Adds a Menu item to the given Menu
   --Menu entries are always added at the end of the Menu - the position
   --can be read via "item" by the caller
   --with specifying "reserve_space", the caller can allocate a defined number
   --of bytes for the text of the Menu item - if it is left at 0, memory
   --is automatically allocated to cope with the length of the given string
   --
   procedure Add_Last_Item (Menu          : in out Menu_Type;
                            Item          : out Natural;
                            Name          : in String;
                            Reserve_space : in Natural := 0;
                            Tick          : in Boolean := false;
                            Dotted        : in Boolean := false;
                            Writable      : in Boolean := false;
                            Message       : in Boolean := false;
                            SubMenu       : in Boolean := false);
   

   --
   -- Adds a Menu item to the given Menu
   --Menu entries are always added at the end of the Menu - the position
   --can be read via "item" by the caller.
   --This is the low level version of Add_last_Item,
   --the caller has to supply the contents of the menu entry and allocate memory if necessary.
   --
   procedure Add_Last_Item (Menu          : in out Menu_Type;
                            Item          : out Natural;
                            Item_Flags    : in System.Unsigned_Types.Unsigned;
                            Icon_Flags    : in System.Unsigned_Types.Unsigned;
                            Icon_Data     : in Icon_Data_String);

   --
   -- Gets the text of a given Menu item
   --
   function Get_Item (Menu : in Menu_Type;
                      Item : in Natural) return String;

   --
   -- Changes the text of a given Menu item
   --Be careful! No checks for sufficiently allocated memory is done!
   --
   procedure Change_Item (Menu : in Menu_Type;
                          Item : in Natural;
                          Name : in String);


   --
   -- Change item count.
   --
   procedure Change_ItemCount (Menu      : in out Menu_Type;
                               New_Count : in Natural);

   --
   -- Shades the specified Menu item to make it unselectable
   --
   procedure Shade_Item (Menu : in Menu_Type;
                         Item : in Natural;
                         Shade: in Boolean := true);

   --
   -- Puts a tick in front of the specified Menu item
   --
   procedure Tick_Item (Menu : in Menu_Type;
                        Item : in Natural;
                        Tick : in Boolean := true);
   
   --
   -- Attaches a subwindow to the specified Menu item
   --
   procedure Attach_Window (Menu : in Menu_Type;
                            Item : in Natural;
                            WH   : in Wimp_Handle_Type);

   --
   -- Attaches a subwindow to the specified Menu item
   --
   procedure Attach_SubMenu (Menu    : in Menu_Type;
                             Item    : in Natural;
                             SubMenu : in Menu_Type);

   --
   -- Sets the Menu colours
   --
   procedure Set_Colours (Menu         : in Menu_Type;
                          Title_FG     : in Integer := 7;
                          Title_BG     : in Integer := 2;
                          Work_Area_FG : in Integer := 7;
                          Work_Area_BG : in Integer := 0);
   
   --
   -- Gets the Menu colours
   --
   procedure Get_Colours (Menu         : in Menu_Type;
                          Title_FG     : out Integer;
                          Title_BG     : out Integer;
                          Work_Area_FG : out Integer;
                          Work_Area_BG : out Integer);

   --
   -- Sets the Menu parameters
   --
   procedure Set_Parameters (Menu   : in Menu_Type;
                             Width  : in Integer := 0;
                             Height : in Integer := 44;
                             Gap    : in Integer := 0);

   --
   -- Gets the Menu parameters
   --
   procedure Get_Parameters (Menu   : in Menu_Type;
                             Width  : out Integer;
                             Height : out Integer;
                             Gap    : out Integer);

   --
   -- Returns a pointer to memory block containing the menu.
   --
   function Get_Pointer (Menu : in Menu_Type) return Mem_Adr_Type;

   --
   -- This message is sent when your Menu was closed without a selection having been made.
   --
   Type Message_MenusDeleted is
   record
   Header         : Message_Event_Header;
   Menu_Block     : Integer;
   end record;
   pragma Convention (C, Message_MenusDeleted);

   Type Message_MenusDeleted_Pointer is access Message_MenusDeleted;

   Type AMEL_Message_MenusDeleted is abstract new
        Message_EventListener(Message_Event_MenusDeleted) with
   record
   Event : Message_MenusDeleted_Pointer;
   end record;

   --
   -- You receive this message when pointer moves over the subMenu arrow in a Menu entry with the 'generate message' bit set.
   --
   --You can use the 'subMenu pointer' and/or the selection list, to decide which window or Menu to open with Wimp_CreateSubMenu.
   --The subMenu you actually open doesn't have to be the same as the one passed to you.
   --However, if you wish the subMenu to be re-opened when the Wimp recreates the Menu you should store the new handle.
   --
   Type Message_MenuWarning is
   record
   Header         : Message_Event_Header;
   Submenu        : Integer;
   X              : Integer;
   Y              : Integer;
   Main_Menu      : Integer;
   SubMenu_01     : Integer;
   SubMenu_02     : Integer;
   SubMenu_03     : Integer;
   SubMenu_04     : Integer;
   SubMenu_05     : Integer;
   SubMenu_06     : Integer;
   SubMenu_07     : Integer;
   SubMenu_08     : Integer;
   SubMenu_09     : Integer;
   SubMenu_10     : Integer;
   SubMenu_11     : Integer;
   SubMenu_12     : Integer;
   SubMenu_13     : Integer;
   SubMenu_14     : Integer;
   SubMenu_15     : Integer;
   SubMenu_16     : Integer;
   SubMenu_17     : Integer;
   SubMenu_18     : Integer;
   SubMenu_19     : Integer;
   SubMenu_20     : Integer;
   end record;
   pragma Convention (C, Message_MenuWarning);

   Type Message_MenuWarning_Pointer is access Message_MenuWarning;

   Type AMEL_Message_MenuWarning is abstract new
        Message_EventListener(Message_Event_MenuWarning) with
   record
   Event : Message_MenuWarning_Pointer;
   end record;

   --
   -- The datastructure contains the path of selection starting with the element selected in the main Menu.
   --
   --If the user clicks with adjust (call Wimp_GetPointerInfo to find out), the Menu should remain on screen.
   --To do this, you have to reopen the Menu after having responded to selection.
   --This is done by calling Wimp_CreateMenu again.
   --
   Type Reason_MenuSelection is
   record
   Main_Menu   : Integer;
   SubMenu_01  : Integer;
   SubMenu_02  : Integer;
   SubMenu_03  : Integer;
   SubMenu_04  : Integer;
   SubMenu_05  : Integer;
   SubMenu_06  : Integer;
   SubMenu_07  : Integer;
   SubMenu_08  : Integer;
   SubMenu_09  : Integer;
   SubMenu_10  : Integer;
   SubMenu_11  : Integer;
   SubMenu_12  : Integer;
   SubMenu_13  : Integer;
   SubMenu_14  : Integer;
   SubMenu_15  : Integer;
   SubMenu_16  : Integer;
   SubMenu_17  : Integer;
   SubMenu_18  : Integer;
   SubMenu_19  : Integer;
   SubMenu_20  : Integer;
   end record;
   pragma Convention (C, Reason_MenuSelection);

   Type Reason_MenuSelection_Pointer is access Reason_MenuSelection;

   Type AWEL_Reason_MenuSelection is abstract new
        Wimp_EventListener(Reason_Event_MenuSelection,-1,-1) with
   record
   Event : Reason_MenuSelection_Pointer;
   end record;

private

   Type Menu_Type is
    record
    Pointer   : Mem_Adr_Type;
    Items     : Natural := 0;
    Max_Items : Natural := 0;
    end record;

end RASCAL.WimpMenu;
