1. ------------------------------------------------------------------------------ 
  2. --                  GtkAda - Ada95 binding for Gtk+/Gnome                   -- 
  3. --                                                                          -- 
  4. --                     Copyright (C) 2001-2014, AdaCore                     -- 
  5. --                                                                          -- 
  6. -- This library is free software;  you can redistribute it and/or modify it -- 
  7. -- under terms of the  GNU General Public License  as published by the Free -- 
  8. -- Software  Foundation;  either version 3,  or (at your  option) any later -- 
  9. -- version. This library is distributed in the hope that it will be useful, -- 
  10. -- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- -- 
  11. -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            -- 
  12. --                                                                          -- 
  13. -- As a special exception under Section 7 of GPL version 3, you are granted -- 
  14. -- additional permissions described in the GCC Runtime Library Exception,   -- 
  15. -- version 3.1, as published by the Free Software Foundation.               -- 
  16. --                                                                          -- 
  17. -- You should have received a copy of the GNU General Public License and    -- 
  18. -- a copy of the GCC Runtime Library Exception along with this program;     -- 
  19. -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    -- 
  20. -- <http://www.gnu.org/licenses/>.                                          -- 
  21. --                                                                          -- 
  22. ------------------------------------------------------------------------------ 
  23.  
  24. --  <description> 
  25. --  This widget organizes its children into resizable panes. Within each 
  26. --  pane, multiple children can be put, and they will be accessible through 
  27. --  a notebook. 
  28. --  </description> 
  29. --  <group>Layout containers</group> 
  30.  
  31. pragma Ada_2005; 
  32.  
  33. with Ada.Tags; 
  34. with Cairo; 
  35. with GNAT.Strings; 
  36. with Glib;        use Glib; 
  37. with Glib.Main; 
  38. with Glib.Xml_Int; 
  39. with Gdk.Event; 
  40. with Gdk.Pixbuf; 
  41. with Gdk.RGBA; 
  42. with Gdk.Rectangle; 
  43. with Gtk.Accel_Group; 
  44. with Gtk.Box; 
  45. with Gtk.Enums; 
  46. with Gtk.Event_Box; 
  47. with Gtk.Handlers; 
  48. with Gtk.Image; 
  49. with Gtk.Label; 
  50. with Gtk.Menu; 
  51. with Gtk.Menu_Item; 
  52. with Gtk.Notebook; 
  53. with Gtk.Check_Menu_Item; 
  54. with Gtk.Radio_Menu_Item; 
  55. with Gtk.Css_Provider; 
  56. with Gtk.Widget; 
  57. with Gtk.Window; 
  58. with Gtkada.Handlers; 
  59. with Gtkada.Multi_Paned; 
  60. with Pango.Font; 
  61.  
  62. package Gtkada.MDI is 
  63.  
  64.    type MDI_Window_Record is new Gtk.Widget.Gtk_Widget_Record with private; 
  65.    type MDI_Window is access all MDI_Window_Record'Class; 
  66.    --  Although this widget is implemented as a gtk_layout, you shouldn't 
  67.    --  use the standard Gtk_Layout functions like Put and Move yourself. 
  68.  
  69.    type MDI_Child_Record is new Gtk.Event_Box.Gtk_Event_Box_Record 
  70.      with private; 
  71.    type MDI_Child is access all MDI_Child_Record'Class; 
  72.    pragma No_Strict_Aliasing (MDI_Child); 
  73.    --  A child of the MDI, that encapsulates the widgets you have put in the 
  74.    --  MDI window. 
  75.    --  You can easily convert from this to the initial widget using the 
  76.    --  functions Find_MDI_Child and Get_Widget. 
  77.  
  78.    type MDI_Child_Array is array (Natural range <>) of MDI_Child; 
  79.    No_Children : constant MDI_Child_Array := (1 .. 0 => null); 
  80.  
  81.    type State_Type is (Normal, Floating, Invisible); 
  82.    --  This type indicates the state of an item in the MDI: 
  83.    --  - Normal: the item can be manipulated (moved and resized) by the user. 
  84.    --      It is found either in the middle notebook (maximized items), or 
  85.    --      in the layout. 
  86.    --  - Floating: the item has its own toplevel window, and is thus managed 
  87.    --      by the window manager. 
  88.    --  - Invisible: the child was part of a previously displayed perspective, 
  89.    --      but is no longer in the current perspective. We still keep it to 
  90.    --      reuse it when switching back to the previous perspective. 
  91.  
  92.    type Allowed_Areas is (Central_Only, Sides_Only, Both); 
  93.    --  Where is a child allowed to be moved ? 
  94.  
  95.    procedure Gtk_New 
  96.      (MDI   : out MDI_Window; 
  97.       Group : access Gtk.Accel_Group.Gtk_Accel_Group_Record'Class; 
  98.       Independent_Perspectives : Boolean := False); 
  99.    --  Create a new MDI window. 
  100.    --  Note that it is recommended that you modify the style (Set_Background 
  101.    --  in State_Normal) to have a different color. 
  102.    --  You should call Setup_Toplevel_Window once you have added the MDI to a 
  103.    --  toplevel widget, so that focus is correctly handled when the toplevel 
  104.    --  window gains the focus 
  105.    --  When Independent_Perspectives is True, switching perspectives will not 
  106.    --  preserve any window. Otherwise, the windows that are in the central 
  107.    --  area will be preserved in the new perspective. 
  108.  
  109.    procedure Initialize 
  110.      (MDI   : access MDI_Window_Record'Class; 
  111.       Group : access Gtk.Accel_Group.Gtk_Accel_Group_Record'Class; 
  112.       Independent_Perspectives : Boolean := False); 
  113.    --  Internal initialization function. 
  114.    --  See the section "Creating your own widgets" in the documentation. 
  115.  
  116.    function Get_Type return Glib.GType; 
  117.    function Child_Get_Type return Glib.GType; 
  118.    --  Return the type describing the MDI or a MDI_Child 
  119.  
  120.    procedure Setup_Toplevel_Window 
  121.      (MDI    : access MDI_Window_Record; 
  122.       Parent : access Gtk.Window.Gtk_Window_Record'Class); 
  123.    --  Setup Parent to properly handle focus when the window manager changes 
  124.    --  the window that currently has the focus. 
  125.    --  Parent must be the toplevel window that contains the MDI. 
  126.  
  127.    type Show_Tabs_Policy_Enum is (Always, Never, Automatic); 
  128.    type Title_Bars_Policy     is (Always, Never, Central_Only); 
  129.  
  130.    procedure Configure 
  131.      (MDI                       : access MDI_Window_Record; 
  132.       Opaque_Resize             : Boolean := False; 
  133.       Close_Floating_Is_Unfloat : Boolean := True; 
  134.       Title_Font         : Pango.Font.Pango_Font_Description := null; 
  135.       Title_Bar_Color    : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; 
  136.       Focus_Title_Color  : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; 
  137.       Draw_Title_Bars    : Title_Bars_Policy   := Always; 
  138.       Tabs_Position      : Gtk.Enums.Gtk_Position_Type := Gtk.Enums.Pos_Top; 
  139.       Show_Tabs_Policy   : Show_Tabs_Policy_Enum := Automatic; 
  140.       Homogeneous_Tabs   : Boolean := True); 
  141.    --  Change the setup of the MDI. 
  142.    --  Close_Floating_Is_Unfloat, if True, means that closing a floating child 
  143.    --  will put it back in the MDI instead of destroying it (unless its flag 
  144.    --  Always_Destroy_Float is set). 
  145.    --  Title_Font is the font used in the title bars (if null, "sans 8" 
  146.    --  is used). 
  147.    --  The colors, when Null_Color, will not change the current setup. 
  148.    --  If Draw_Title_Bars is False, then no extra title bar will be displayed 
  149.    --  for the MDI children when they are maximized. This saves space on the 
  150.    --  screen. However, the notebook tabs will be highlighted with 
  151.    --  Title_Bar_Color in exchange. 
  152.    --  Tabs_Position indicates where the notebook tabs should be put. 
  153.    --  Show_Tabs_Policy indicates when the notebook tabs should be displayed. 
  154.    -- 
  155.    --  If Homogeneous_Tabs is true, then the notebook tabs will only use their 
  156.    --  natural size when they all fit in the notebook's width. Otherwise, they 
  157.    --  are resized (and ellipsized as needed) so that more of them show. 
  158.    --  Changing this setup requires a restart of the MDI. 
  159.    -- 
  160.    --  Calling configure will define a default CSS to properly theme the MDI. 
  161.    --  This CSS relies on mainly two widget classes to behave: 
  162.    --  * mdifocused, corresponding to the notebook having the focus 
  163.    --  * mdititle, corresponding to the title bar 
  164.    --  This default CSS renders the active tab of the active notebook with the 
  165.    --  color defined in Focus_Title_Color. Same for the color of the title 
  166.    --  bar (uses Title_Bar_Color for non-active title bar). 
  167.    --  This behavior can at any point be overriden by users by defining 
  168.    --  their own and load it at run-time. 
  169.    -- 
  170.    --  Since the move to gtk3, the highlighting of the current tab is left to 
  171.    --  the gtk+ theme, rather than overwritten in this package. This permits a 
  172.    --  better integration with the user's theme. It is possible for 
  173.    --  applications to provide their own CSS, though, using 
  174.    --  Gtkada.Style.Load_Css_File. Here is an example of such a CSS, which 
  175.    --  highlights the current tab in the notebook that currently has the focus: 
  176.    -- 
  177.    --     @define-color mdi-tab-color  grey; 
  178.    --     @define-color mdi-active-tab-color blue; 
  179.    --     .mdititle { 
  180.    --         border-width: 2px; 
  181.    --         background-image: -gtk-gradient( 
  182.    --             linear, left top, left bottom, 
  183.    --             from(@mdi-tab-color), to(shade(@mdi-tab-color, 1.1))); 
  184.    --     } 
  185.    --     .mdifocused .mdititle { 
  186.    --         background-image: -gtk-gradient( 
  187.    --             linear, left top, left bottom, 
  188.    --             from(@mdi-active-tab-color), 
  189.    --             to(shade(@mdi-active-tab-color, 1.1))); 
  190.    --     .mdi tab GtkLabel, .mdi tab GtkImage { opacity: 0.8 } 
  191.    --     .mdifocused tab GtkLabel, .mdifocused tab GtkImage { opacity: 1.0} 
  192.  
  193.    function Independent_Perspectives 
  194.      (MDI : access MDI_Window_Record) return Boolean; 
  195.    --  Whether the MDI is using independent perspectives 
  196.  
  197.    ------------- 
  198.    -- Windows -- 
  199.    ------------- 
  200.  
  201.    type Child_Flags is mod 2 ** 5; 
  202.    Destroy_Button       : constant Child_Flags := 2 ** 2; 
  203.    Float_As_Transient   : constant Child_Flags := 2 ** 3; 
  204.    Always_Destroy_Float : constant Child_Flags := 2 ** 4; 
  205.    All_Buttons          : constant Child_Flags := Destroy_Button; 
  206.    --  Special flags to set up the widgets: 
  207.    --  The first is the buttons that should be displayed in the title 
  208.    --  bar of the MDI children. 
  209.    --  If Float_As_Transient is set, then the child will be set up as a 
  210.    --  transient window when floating: on most window managers, it will stay on 
  211.    --  top of the MDI, but the window will have less decorations in its title 
  212.    --  bar, in particular no destroy button. In such a case, <Esc> will close 
  213.    --  the window, or unfloat it depending on the MDI's setup, as is the case 
  214.    --  for all dialogs in GtkAda. The MDI's setup will be ignored (and the 
  215.    --  child always destroyed when Esc is pressed) if Always_Destroy_Float is 
  216.    --  true. 
  217.  
  218.    type Child_Group is new Positive; 
  219.    Group_Default : constant Child_Group := 1; 
  220.    Group_Any     : constant Child_Group := Child_Group'Last; 
  221.    --  This type can be used to help group windows by type within the MDI. 
  222.    --  Group_Default as a special status when computing the initial position 
  223.    --  for a window. But you can create your own groups as needed, so that for 
  224.    --  instance editors tend to be grouped with other editors, graphs with 
  225.    --  other graphs,... depending on your application. 
  226.    --  The group has an impact when the last window from a notebook is closed: 
  227.    --  If the window belongs to Group_Default, and it is the last of its group, 
  228.    --  then the space currently occupied by that window is not reclaimed, and 
  229.    --  therefore an empty area will exist in the MDI. The idea is that for 
  230.    --  instance editors typically play a special role in an integrated 
  231.    --  development environment, and the users like to have them in the center 
  232.    --  of the window. When closing the last editor, they do not want the side 
  233.    --  windows (browsers, consoles,...) to take up that space that should 
  234.    --  really only be used for editors. 
  235.    --  To get such a behavior, editors should belong to Group_Default, and all 
  236.    --  other windows to custom groups. 
  237.    -- 
  238.    --  Do not use Group_Any, it is used internally with special meanings. 
  239.  
  240.    procedure Gtk_New 
  241.      (Child        : out MDI_Child; 
  242.       Widget       : access Gtk.Widget.Gtk_Widget_Record'Class; 
  243.       Flags        : Child_Flags := All_Buttons; 
  244.       Group        : Child_Group := Group_Default; 
  245.       Focus_Widget : Gtk.Widget.Gtk_Widget := null; 
  246.       Areas        : Allowed_Areas := Both); 
  247.    --  Create a new MDI child that contains widget. 
  248.    --  Widget mustn't be of type Gtk_Window. 
  249.    -- 
  250.    --  You shouldn't access Widget directly afterwards, but should manipulate 
  251.    --  Child only. However, as a special exception, you can still pass Widget 
  252.    --  as a parameter to the subprograms in this package to manipulate it (e.g. 
  253.    --  in Raise_Child, ...) 
  254.    -- 
  255.    --  If Focus_Widget is not null, this is the widget that gets the keyboard 
  256.    --  focus when the child is selected. 
  257.  
  258.    procedure Initialize 
  259.      (Child        : access MDI_Child_Record'Class; 
  260.       Widget       : access Gtk.Widget.Gtk_Widget_Record'Class; 
  261.       Flags        : Child_Flags := All_Buttons; 
  262.       Group        : Child_Group := Group_Default; 
  263.       Focus_Widget : Gtk.Widget.Gtk_Widget := null; 
  264.       Areas        : Allowed_Areas := Both); 
  265.    --  Internal initialization function. 
  266.    --  See the section "Creating your own widgets" in the documentation. 
  267.  
  268.    type Child_Position is 
  269.      (Position_Automatic, 
  270.       Position_Bottom, 
  271.       Position_Top, 
  272.       Position_Left, 
  273.       Position_Right); 
  274.    subtype Side_Position is Child_Position 
  275.       range Position_Bottom .. Position_Right; 
  276.    --  The initial position of windows within the MDI. 
  277.    --  In all cases, the initial location for a window is computed with the 
  278.    --  following algorithm. This algorithm is designed with the notion of 
  279.    --  groups of windows in mind, so that some windows (typically editors) have 
  280.    --  a special status. 
  281.    --     - If another window with the same Group is already in the MDI, the 
  282.    --       new window is put on top of it. 
  283.    --     - Otherwise, if Position_Automatic, if an empty area exists within 
  284.    --       the MDI, the new window is put in that area. 
  285.    --     - Else if the Position is Bottom .. Right, the new window is put 
  286.    --       below all others (resp. to the top, left or right) 
  287.    --     - Else the window is put on top of the currently selected window 
  288.  
  289.    procedure Put 
  290.      (MDI              : access MDI_Window_Record; 
  291.       Child            : access MDI_Child_Record'Class; 
  292.       Initial_Position : Child_Position := Position_Automatic); 
  293.    --  Add a new child to the MDI window, and return its embedding widget. 
  294.    --  Calling Put does not give the focus to the newly inserted widget. 
  295.    --  To do that, you should call Set_Focus_Child. 
  296.  
  297.    function Save_Desktop 
  298.      (Self : not null access MDI_Child_Record) return Glib.Xml_Int.Node_Ptr; 
  299.    --  A function used to save a child into the desktop. 
  300.    --  This is similar to Save_Desktop_Function, but is specific to a child, 
  301.    --  and thus more efficient. 
  302.    -- 
  303.    --  If this function returns some data, that data is saved into the XML 
  304.    --  for the desktop. If it returns null, however, the MDI will call each 
  305.    --  of the registered Save_Desktop_Function, until one returns some data. 
  306.    -- 
  307.    --  The resulting node must have a tag that is unique for this type of 
  308.    --  widget, and this recognized by one of the Load_Desktop_Function so 
  309.    --  that the child can be recreated when the desktop is loaded from XML. 
  310.  
  311.    procedure Set_Size 
  312.      (MDI        : access MDI_Window_Record; 
  313.       Child      : access MDI_Child_Record'Class; 
  314.       Width      : Glib.Gint; 
  315.       Height     : Glib.Gint; 
  316.       Fixed_Size : Boolean := False); 
  317.    --  Forces a new size for a child. If Width or Height is left to -1, the 
  318.    --  matching size will be computed from the child's requisition. If they are 
  319.    --  left to 0, the corresponding length is left to its current value. 
  320.    --  If Fixed_Size is True, then the widget will not be resized when the MDI 
  321.    --  itself is resized (unless the user has first moved one of the handles to 
  322.    --  manually resize it). Otherwise, it will grow proportionally with the 
  323.    --  rest of the MDI. 
  324.  
  325.    procedure Close 
  326.      (MDI   : access MDI_Window_Record; 
  327.       Child : access Gtk.Widget.Gtk_Widget_Record'Class; 
  328.       Force : Boolean := False); 
  329.    --  Close the child that contains Child, and remove its window from the 
  330.    --  MDI. See also Close_Child if you need to close a MDI_Child itself. 
  331.    --  This first checks through a delete_event callback whether the child 
  332.    --  accepts to be closed. 
  333.    --  "delete_event" is not sent, and the child is automatically closed, if 
  334.    --  Force is set to True. 
  335.  
  336.    procedure Set_Title 
  337.      (Child       : access MDI_Child_Record; 
  338.       Title       : String; 
  339.       Short_Title : String := ""); 
  340.    --  Set the title for a child. Title is the title put in titlebar of 
  341.    --  the children, whereas Short_Title is the name of the notebook tab when 
  342.    --  children are maximized. By default, it is the same as Title. 
  343.    -- 
  344.    --  The default title is the empty string. 
  345.    --  This title will be the one used for the window when the child is set to 
  346.    --  floating state. 
  347.    -- 
  348.    --  Title and Short_Title should preferably be UTF8-encoded, although this 
  349.    --  procedure will attempt to guess the encoding if the string is not valid 
  350.    --  UTF8. 
  351.    -- 
  352.    --  Child should already be in the MDI at this point (via a call to Put), so 
  353.    --  that the "use_short_titles" preference is taken into account. 
  354.  
  355.    function Get_MDI (Child : access MDI_Child_Record) return MDI_Window; 
  356.    --  Return the MDI to which Child is associated. In Child is a floating 
  357.    --  child, it might not be in the MDI window itself. 
  358.  
  359.    function Get_Title (Child : access MDI_Child_Record) return UTF8_String; 
  360.    --  Return the title for a specific child 
  361.  
  362.    function Get_Short_Title 
  363.      (Child : access MDI_Child_Record) return UTF8_String; 
  364.    --  Return the name of the notebook tab used when children are maximized. 
  365.  
  366.    function Has_Title_Bar (Child : access MDI_Child_Record) return Boolean; 
  367.    --  Whether a title bar is currently displayed for Child 
  368.  
  369.    function Get_State (Child : access MDI_Child_Record) return State_Type; 
  370.    --  Return the current state of the child 
  371.  
  372.    function Get_Allowed_Areas 
  373.      (Child : not null access MDI_Child_Record'Class) return Allowed_Areas; 
  374.    --  What areas the child can be put int 
  375.  
  376.    procedure Set_Icon 
  377.      (Child : access MDI_Child_Record; 
  378.       Icon  : Gdk.Pixbuf.Gdk_Pixbuf); 
  379.    --  Associate an icon with Child. This icon is visible in the title bar, the 
  380.    --  notebook tabs, the Window menu and the interactive selection dialog. 
  381.    --  The icon is updated dynamically on the screen. 
  382.    --  The Icon can safely be unrefed by the caller (and should, if the pixbuf 
  383.    --  was newly allocated). 
  384.  
  385.    function Get_Icon 
  386.      (Child : access MDI_Child_Record) return Gdk.Pixbuf.Gdk_Pixbuf; 
  387.    --  Returns the icon associated with Child. The returned pixbuf is owned 
  388.    --  by the MDI and must not be freed by the caller. 
  389.  
  390.    --------------------------- 
  391.    -- Drag and Drop support -- 
  392.    --------------------------- 
  393.  
  394.    function Dnd_Data 
  395.      (Child : access MDI_Child_Record; Copy : Boolean) return MDI_Child; 
  396.    --  When a drag-and-drop operation took place to move a child from one 
  397.    --  position to the next, this function is called to know what child should 
  398.    --  be moved. 
  399.    --  As a result, the implementor can choose whether a copy of the child 
  400.    --  should be returned (creating a new view for an editor for instance), or 
  401.    --  if the child itself should be moved (the default). 
  402.    --  The returned MDI_Child must have been added to the MDI before it is 
  403.    --  returned. 
  404.    --  Copy is set to true if a copy operation was requested, to False if a 
  405.    --  simple move operation was requested. It can be ignored if Child doesn't 
  406.    --  know how to create a copy of itself for instance. 
  407.  
  408.    procedure Set_Dnd_Message 
  409.      (MDI     : access MDI_Window_Record; 
  410.       Message : String); 
  411.    --  Override the message that is displayed in the popup window while 
  412.    --  performing a drag. By default, this message mentions: 
  413.    --     "Use control to move the whole notebook" 
  414.    --     "Use shift to create a new view for editors" 
  415.    --  so might not be suitable for all applications. 
  416.    --  You can use markup like "<b>...</b>" to put keywords in bold. 
  417.    -- 
  418.    --  Passing an empty string for Message will restore the default message. 
  419.  
  420.    procedure Child_Drag_Begin 
  421.      (Child  : access MDI_Child_Record'Class; 
  422.       Event  : Gdk.Event.Gdk_Event_Button; 
  423.       Areas  : Allowed_Areas); 
  424.    --  Starts a drag-and-drop operation for the child, so that it can be put in 
  425.    --  some other place on the desktop. This should only be called when a 
  426.    --  handler for the "button_press_event" signal, passing the event itself in 
  427.    --  parameter. 
  428.    --  The Child is immediately raised and gains the focus. 
  429.    --  Areas indicates where the child can be dropped. This is in particular 
  430.    --  useful if Dnd_Data was overridden and some other child will be dropped 
  431.    --  instead. 
  432.  
  433.    procedure Cancel_Child_Drag (Child : access MDI_Child_Record'Class); 
  434.    --  Cancel a drag operation started by Child_Drag_Begin. 
  435.    --  It doesn't call Child_Drag_Finished. 
  436.  
  437.    procedure Child_Drag_Finished (Child  : access MDI_Child_Record); 
  438.    --  Called when a drag operation is either aborted or completed. It should 
  439.    --  be overriden if special cleanup should be done. 
  440.  
  441.    ----------- 
  442.    -- Menus -- 
  443.    ----------- 
  444.  
  445.    type Tab_Contextual_Menu_Factory is access procedure 
  446.      (Child : access MDI_Child_Record'Class; 
  447.       Menu  : access Gtk.Menu.Gtk_Menu_Record'Class); 
  448.  
  449.    procedure Set_Tab_Contextual_Menu_Factory 
  450.      (MDI     : access MDI_Window_Record; 
  451.       Factory : Tab_Contextual_Menu_Factory); 
  452.    --  Set (or unset if Factory is null) the callback to create the contextual 
  453.    --  menu entries when the user clicks on a notebook tab. 
  454.    --  Factory should add entries to Menu (which already contains the default 
  455.    --  entries, but you can remove them if needed). 
  456.  
  457.    ------------------------ 
  458.    -- Selecting children -- 
  459.    ------------------------ 
  460.  
  461.    procedure Highlight_Child 
  462.      (Child : access MDI_Child_Record; Highlight : Boolean := True); 
  463.    --  Highlight the child until it is selected by the user. 
  464.    --  The color of its menu label and of the text in the notebook tabs is 
  465.    --  changed. 
  466.    --  Nothing is done if the child is already fully visible (either in the 
  467.    --  active page in one of the notebooks, or the child that has the selection 
  468.    --  in the layout). 
  469.    --  This is meant to be used as a graphical note to the user that the child 
  470.    --  has been updated and the user should look at it. 
  471.  
  472.    function Get_Focus_Child 
  473.      (MDI : access MDI_Window_Record) return MDI_Child; 
  474.    --  Return the child that currently has the MDI focus. 
  475.    --  null is returned if no child has the focus. 
  476.  
  477.    procedure Set_Focus_Child 
  478.      (MDI        : access MDI_Window_Record; 
  479.       Containing : access Gtk.Widget.Gtk_Widget_Record'Class); 
  480.    --  Give the focus to the child containing Containing. This will not 
  481.    --  Grab_Focus for the child in all cases, since you might want to give the 
  482.    --  focus to some specific part of your widget (an entry field,...) in some 
  483.    --  cases. 
  484.  
  485.    procedure Set_Focus_Child (Child : access MDI_Child_Record); 
  486.    --  Make Child the active widget, and raise it at the top. 
  487.  
  488.    procedure Check_Interactive_Selection_Dialog 
  489.      (MDI          : access MDI_Window_Record; 
  490.       Event        : Gdk.Event.Gdk_Event; 
  491.       Move_To_Next : Boolean; 
  492.       Only_Group   : Child_Group := Group_Any); 
  493.    --  Open the interactive dialog for selecting windows. 
  494.    --  This dialog should be open as a result of a key press event. 
  495.    --  Move_To_Next indicates whether we want to select the next child (True) 
  496.    --  or the previous child (False). 
  497.    --  This dialog will be closed only when the key that opened it is fully 
  498.    --  released. For instance, if the dialog was opened as a result of 
  499.    --  pressing Ctrl-Tab, the dialog will only be closed when Ctrl itself is 
  500.    --  released. 
  501.    --  You can call this procedure even if a dialog is currently open. This 
  502.    --  simply forces a move to the next or previous child. In fact, it is 
  503.    --  your responsability to call this procedure when the user presses 
  504.    --  the keys to move between children. 
  505.    -- 
  506.    --  If Event is null, then no dialog is displayed. Instead, the next or 
  507.    --  previous visible child is immediately selected. In such a mode, windows 
  508.    --  that are not on top of their respective notebook are ignored. This can 
  509.    --  be used to emulate Emacs's behavior for goto-other-window. 
  510.    -- 
  511.    --  If Only_Group is specified, then only the windows from that group will 
  512.    --  be shown in the dialog. 
  513.  
  514.    --  This function is not internal to the MDI since connecting to the 
  515.    --  key_press_event and key_release_event should be done in the gtk_window 
  516.    --  that contains the MDI. Otherwise, some events are intercepted by gtk+, 
  517.    --  for instance the key_release_events, and the key_press_events for some 
  518.    --  specified keys. 
  519.    --  It also gives the choice to the application of whether this feature is 
  520.    --  wanted or not. 
  521.  
  522.    ----------------------------------------- 
  523.    -- MDI_Child and encapsulated children -- 
  524.    ----------------------------------------- 
  525.  
  526.    function Get_Widget 
  527.      (Child : access MDI_Child_Record) return Gtk.Widget.Gtk_Widget; 
  528.    --  Return the widget that Child encapsulates. This is the widget you 
  529.    --  initially Put() in MDI. 
  530.  
  531.    function Find_MDI_Child 
  532.      (MDI    : access MDI_Window_Record; 
  533.       Widget : access Gtk.Widget.Gtk_Widget_Record'Class) return MDI_Child; 
  534.    --  Return the MDI_Child that encapsulates Widget. 
  535.    --  Widget must be the exact same one you gave in argument to Put. 
  536.    --  If the child is currently not visible in the perspective (for instance 
  537.    --  it was created for another perspective, but is not present in the 
  538.    --  current one), it is inserted automatically back in the MDI. 
  539.  
  540.    function Find_MDI_Child_From_Widget 
  541.      (Widget : access Gtk.Widget.Gtk_Widget_Record'Class) return MDI_Child; 
  542.    --  Return the MDI child that encapsulate the parent of Widget. 
  543.    --  As opposed to Find_MDI_Child, Widget can be anywhere within the 
  544.    --  widget tree. This function properly handles floating children 
  545.    --  If the child is currently not visible in the perspective (for instance 
  546.    --  it was created for another perspective, but is not present in the 
  547.    --  current one), it is inserted automatically back in the MDI. 
  548.  
  549.    function Find_MDI_Child_By_Tag 
  550.      (MDI : access MDI_Window_Record; 
  551.       Tag : Ada.Tags.Tag; 
  552.       Visible_Only : Boolean := False) return MDI_Child; 
  553.    --  Return the first child matching Tag 
  554.    --  If the child is currently not visible in the perspective (for instance 
  555.    --  it was created for another perspective, but is not present in the 
  556.    --  current one), it is inserted automatically back in the MDI. 
  557.    --  If Visible_Only is True, an invisible child is not returned. This is 
  558.    --  useful to check whether a child is currently visible. 
  559.  
  560.    function Find_MDI_Child_By_Name 
  561.      (MDI  : access MDI_Window_Record; 
  562.       Name : String) return MDI_Child; 
  563.    --  Return the first child matching Name. 
  564.    --  If the child is currently not visible in the perspective (for instance 
  565.    --  it was created for another perspective, but is not present in the 
  566.    --  current one), it is inserted automatically back in the MDI. 
  567.  
  568.    type Child_Iterator is private; 
  569.  
  570.    function First_Child 
  571.      (MDI               : access MDI_Window_Record; 
  572.       Group_By_Notebook : Boolean := False; 
  573.       Visible_Only      : Boolean := True) return Child_Iterator; 
  574.    --  Return an access to the first child of the MDI. 
  575.    -- 
  576.    --  If Group_By_Notebook is True, then the children are reported one after 
  577.    --  the other, but all the widget from the same notebook are reported in the 
  578.    --  same order as the notebook pages. Floating children do not belong to a 
  579.    --  notebook, and are also reported together. To find out to which notebook 
  580.    --  a child belongs, use Get_Notebook below. 
  581.    -- 
  582.    --  If Group_By_Notebook is False, it is garanteed that the first child is 
  583.    --  the one that currently has the focus in the MDI. The children are 
  584.    --  returned in the order in which they last had the focus. 
  585.    -- 
  586.    --  If Visible_Only is true, then only those children currently visible in 
  587.    --  the perspective are returned. The children that were part of a former 
  588.    --  perspective are not returned. 
  589.  
  590.    procedure Next (Iterator : in out Child_Iterator); 
  591.    --  Move to the next child in the MDI 
  592.  
  593.    function Get_Notebook 
  594.      (Iterator : Child_Iterator) return Gtk.Notebook.Gtk_Notebook; 
  595.    --  Return the notebook to which the current child belongs. null is returned 
  596.    --  for floating children 
  597.  
  598.    function Get (Iterator : Child_Iterator) return MDI_Child; 
  599.    --  Return the child pointed to by Iterator. 
  600.    --  If Iterator is no longer valid, null is returned. 
  601.  
  602.    ----------------------------------- 
  603.    -- Floating and closing children -- 
  604.    ----------------------------------- 
  605.  
  606.    procedure Float_Child 
  607.      (Child : access MDI_Child_Record'Class; Float : Boolean); 
  608.    --  Change the floating state of a child 
  609.  
  610.    function Is_Floating 
  611.      (Child : access MDI_Child_Record'Class) return Boolean; 
  612.    --  Return True if Child is currently in a separate window 
  613.  
  614.    procedure Close_Child 
  615.      (Child : access MDI_Child_Record'Class; 
  616.       Force : Boolean := False); 
  617.    --  Same as Close, but applies directly to a MDI_Child. 
  618.  
  619.    procedure Set_All_Floating_Mode 
  620.      (MDI : access MDI_Window_Record; All_Floating : Boolean); 
  621.    --  If All_Floating is set to true, the MDI will have a size of 0x0, and all 
  622.    --  children are set to floating. This can be used if you wish to let the 
  623.    --  window manager handle the windows. If All_Floating is True, children 
  624.    --  can no longer be maximized. 
  625.  
  626.    procedure Use_Short_Titles_For_Floats 
  627.      (MDI : access MDI_Window_Record; Short_Titles : Boolean); 
  628.    --  If Short_Titles is set to true, only short titles will ever be used 
  629.    --  either in the title bars (in notebooks) or as the title for floating 
  630.    --  windows. 
  631.  
  632.    --------------------------- 
  633.    -- Reorganizing children -- 
  634.    --------------------------- 
  635.  
  636.    procedure Raise_Child 
  637.      (Child : access MDI_Child_Record'Class; Give_Focus : Boolean := True); 
  638.    --  Put Child in the foreground. 
  639.    --  Note that this does not give the focus to this child, unless 
  640.    --  Give_Focus is set to True. If Child and the current focus child are in 
  641.    --  the same notebook, Child will always gain the focus, so that the focus 
  642.    --  is not left on an invisible window. 
  643.  
  644.    function Is_Raised (Child : access MDI_Child_Record'Class) return Boolean; 
  645.    --  Whether the child is currently raised, ie fully visible to the user 
  646.  
  647.    procedure Lower_Child (Child : access MDI_Child_Record'Class); 
  648.    --  Put Child in the background. 
  649.    --  If the children are maximized, this selected the next page from the 
  650.    --  notebook. 
  651.  
  652.    type Split_Mode is 
  653.      (Before, Before_Reuse, 
  654.       After,  After_Reuse, 
  655.       Any_Side_Reuse); 
  656.    --  How a child should be split: 
  657.    --  If "Before", the child is put above or to the left of its current 
  658.    --  position. A new window is created to containing it. If the "_Reuse" 
  659.    --  version is used, and a window already exist at that position, the child 
  660.    --  will be put in it instead of creating a new one. 
  661.    --  Any_Side_Reuse indicates that the child will be put on either side, 
  662.    --  depending on where a window already exists. If there is no window on the 
  663.    --  side, a new one is created. 
  664.  
  665.    procedure Split 
  666.      (MDI           : access MDI_Window_Record; 
  667.       Orientation   : Gtk.Enums.Gtk_Orientation; 
  668.       Child         : MDI_Child := null; 
  669.       Mode          : Split_Mode := Before; 
  670.       Width, Height : Glib.Gint := 0); 
  671.    --  Split the notebook containing Child (by default, the current focus 
  672.    --  child). 
  673.    --  Mode indicates in which direction the splitting should occur. If you 
  674.    --  are splitting a child in the central area, splitting will never reuse 
  675.    --  a window outside of the central area. 
  676.    --  Width and Height indicate the desired geometry for the splitted area, 
  677.    --  0 indicate a 50/50 split. 
  678.  
  679.    ---------------------- 
  680.    -- Desktop Handling -- 
  681.    ---------------------- 
  682.    --  The MDI provides a way to save desktops, i.e the list of children 
  683.    --  currently open in the MDI and their location. It can then restore the 
  684.    --  desktop at some later point. 
  685.    -- 
  686.    --  Desktops require support from the widgets that are put in the MDI. They 
  687.    --  need to register a function to save them and a function to recreate 
  688.    --  them. Using Ada streams for this didn't prove workable since some 
  689.    --  children might need extra parameters not available to them through 
  690.    --  streams. This is why the following subprograms are in a generic package, 
  691.    --  so that you can pass whatever parameter(s) is needed in your 
  692.    --  application. 
  693.    -- 
  694.    --  Desktops are saved and restored in XML trees. 
  695.    -- 
  696.    --  If you need your application to load a "default desktop" when the user 
  697.    --  hasn't defined one, it is recommended that you distribute an actual 
  698.    --  file containing this desktop. You could also create the XML tree in 
  699.    --  memory yourself, and thus hard-code the default desktop if need be. 
  700.  
  701.    generic 
  702.       type User_Data is private; 
  703.       --  Generic type of parameter that is passed to all the children's save 
  704.       --  and restore functions. 
  705.  
  706.       --  This package needs to be instantiated at library level 
  707.  
  708.    package Desktop is 
  709.  
  710.       type Menu_Registration_Procedure is access procedure 
  711.         (User       : User_Data; 
  712.          Item_Name  : String; 
  713.          Accel_Path : String); 
  714.       --  Function used to register in the application a static menu 
  715.       --  created by the MDI. 
  716.  
  717.       function Create_Menu 
  718.         (MDI               : access MDI_Window_Record'Class; 
  719.          Accel_Path_Prefix : String := "<gtkada>"; 
  720.          User              : User_Data; 
  721.          Registration      : Menu_Registration_Procedure := null) 
  722.          return Gtk.Menu.Gtk_Menu; 
  723.       --  Create a dynamic menu that can then be inserted into a menu bar. This 
  724.       --  menu is dynamic, ie its content will changed based on the focus 
  725.       --  child. 
  726.       --  If this function is called several times, the same menu is returned 
  727.       --  every time. Accel_Path_Prefix must be the same for every call. 
  728.       --  Accel_Path_Prefix is used so that the key shortcuts associated with 
  729.       --  these menu items can be changed dynamically by the user (see 
  730.       --  gtk-accel_map.ads). The prefix must start with "<" and end with ">". 
  731.       --  User is used for the callbacks on perspective changes, and passed to 
  732.       --  Load_Perspective 
  733.       --  If Registration is specified, call it for 
  734.  
  735.       type Save_Desktop_Function is access function 
  736.         (Widget : access Gtk.Widget.Gtk_Widget_Record'Class; 
  737.          User   : User_Data) return Glib.Xml_Int.Node_Ptr; 
  738.       --  A general function that dumps the parameters of a widget into an XML 
  739.       --  tree. 
  740.       -- 
  741.       --  Note: you should register one such function for all the widget types 
  742.       --  you will put in the MDI and that need to be saved when a desktop is 
  743.       --  saved. The MDI will call all the registered functions one after the 
  744.       --  other. Therefore, your function should return null if Widget is not 
  745.       --  of a type that is it can handle. 
  746.       -- 
  747.       --  Before calling the registered save_desktop_function, the MDI will 
  748.       --  first use the child's Save_Desktop primitive function. 
  749.  
  750.       type Load_Desktop_Function is access function 
  751.         (MDI : MDI_Window; Node : Glib.Xml_Int.Node_Ptr; User : User_Data) 
  752.          return MDI_Child; 
  753.       --  A general function that loads a widget from an XML tree. 
  754.       -- 
  755.       --  As for Save_Desktop_Function, this function should return null if it 
  756.       --  doesn't know how to handle Node or if Node doesn't describe a widget 
  757.       --  type that it can handle. 
  758.       -- 
  759.       --  This function returns an MDI_Widget that has been put in the MDI. 
  760.  
  761.       procedure Register_Desktop_Functions 
  762.         (Save : Save_Desktop_Function; 
  763.          Load : Load_Desktop_Function); 
  764.       --  Register a set of functions to save and load desktops for some 
  765.       --  specific widget types. This can be called multiple times. 
  766.       --  Save might be null. 
  767.  
  768.       function Restore_Desktop 
  769.         (MDI          : access MDI_Window_Record'Class; 
  770.          Perspectives : Glib.Xml_Int.Node_Ptr; 
  771.          From_Tree    : Glib.Xml_Int.Node_Ptr; 
  772.          User         : User_Data) return Boolean; 
  773.       --  Restore the contents of the MDI from its saved XML tree. 
  774.       --  Perspectives is the list of perspectives. It is cloned as needed, so 
  775.       --  the caller is still responsible for freeing it. The first perspective 
  776.       --  is loaded. 
  777.       --  From_Tree is the part of the desktop that describes the editor area. 
  778.       --  User is passed as a parameter to all of the Load_Desktop_Function 
  779.       --  registered by the widgets. 
  780.       --  Return False if the desktop couldn't be loaded 
  781.       --  It also restores the size and position of the toplevel window that 
  782.       --  contains the MDI 
  783.  
  784.       procedure Load_Perspective 
  785.         (MDI          : access MDI_Window_Record'Class; 
  786.          Name         : String; 
  787.          User         : User_Data); 
  788.       --  Replace the current perspective by another one. This preserves the 
  789.       --  editor area. 
  790.       --  If the perspective does not exist, nothing is done, unless no 
  791.       --  perspective is currently loaded (in which case we load the first 
  792.       --  on in the list). 
  793.  
  794.       procedure Create_Perspective 
  795.         (MDI          : access MDI_Window_Record'Class; 
  796.          Name         : String; 
  797.          User         : User_Data); 
  798.       --  Create a new perspective with the current desktop layout. If another 
  799.       --  perspective with the same name exists, it is replaced. 
  800.  
  801.       procedure Define_Perspective 
  802.         (MDI          : access MDI_Window_Record'Class; 
  803.          XML          : Glib.Xml_Int.Node_Ptr; 
  804.          User         : User_Data); 
  805.       --  Define a new perspective (in the same format as returned by 
  806.       --  Save_Desktop, the central area is under control of the user so you 
  807.       --  cannot change it). 
  808.       --  If such a perspective already exists, nothing is done (since the user 
  809.       --  might have modified it already). 
  810.       --  XML's root node is the <perspective> node, including its "name" 
  811.       --  attribute. 
  812.       --  XML must be freed by the caller. 
  813.  
  814.       procedure Save_Desktop 
  815.         (MDI          : access MDI_Window_Record'Class; 
  816.          User         : User_Data; 
  817.          Perspectives : out Glib.Xml_Int.Node_Ptr; 
  818.          Central      : out Glib.Xml_Int.Node_Ptr); 
  819.       --  Return XML representations of the perspectives and central area. Both 
  820.       --  nodes need to be freed by the caller, and can be saved in a file (to 
  821.       --  be passed to Restore_Desktop later on). 
  822.       --  This function calls each of the registered function for the children 
  823.       --  of the MDI. 
  824.       --  It also saves the size and position of the toplevel window that 
  825.       --  contains the MDI 
  826.  
  827.       function Get_XML_Content 
  828.         (MDI : access MDI_Window_Record'Class; 
  829.          Tag : String) return Glib.Xml_Int.Node_Ptr; 
  830.       --  Return the first XML subtree starting with 'Tag'. This allows a 
  831.       --  module to retrieve its content after the 'Load_Desktop' call. 
  832.  
  833.       procedure Free_Registered_Desktop_Functions; 
  834.       --  Free the memory allocated for the registered functions. 
  835.  
  836.    private 
  837.       type Register_Node_Record; 
  838.       type Register_Node is access Register_Node_Record; 
  839.       type Register_Node_Record is record 
  840.          Save : Save_Desktop_Function; 
  841.          Load : Load_Desktop_Function; 
  842.          Next : Register_Node; 
  843.       end record; 
  844.  
  845.       type Perspective_Menu_Item_Record 
  846.         is new Gtk.Radio_Menu_Item.Gtk_Radio_Menu_Item_Record 
  847.       with record 
  848.          MDI  : MDI_Window; 
  849.          Name : Natural; 
  850.          User : User_Data; 
  851.       end record; 
  852.       type Perspective_Menu_Item 
  853.         is access all Perspective_Menu_Item_Record'Class; 
  854.  
  855.       procedure Change_Perspective 
  856.         (Item : access Gtk.Widget.Gtk_Widget_Record'Class); 
  857.       CP_Access : constant 
  858.         Gtkada.Handlers.Widget_Callback.Marshallers.Marshaller := 
  859.         Gtkada.Handlers.Widget_Callback.To_Marshaller 
  860.           (Change_Perspective'Access); 
  861.       --  Internal, but needed so that we can have a 'Access on a callback 
  862.  
  863.       procedure Create_Perspective_CB 
  864.         (Item : access Gtk.Widget.Gtk_Widget_Record'Class); 
  865.       CreateP_Access : constant 
  866.         Gtkada.Handlers.Widget_Callback.Marshallers.Marshaller := 
  867.         Gtkada.Handlers.Widget_Callback.To_Marshaller 
  868.           (Create_Perspective_CB'Access); 
  869.  
  870.       Registers : Register_Node; 
  871.       --  Global variable that contains the list of functions that have been 
  872.       --  registered. 
  873.    end Desktop; 
  874.  
  875.    function Desktop_Was_Loaded (MDI : access MDI_Window_Record) return Boolean; 
  876.    --  Return True if a desktop was loaded, False if the MDI is only the result 
  877.    --  of calls to Gtk_New and Put. 
  878.  
  879.    function List_Of_Perspectives 
  880.      (MDI : access MDI_Window_Record) 
  881.       return GNAT.Strings.String_List_Access; 
  882.    --  Return the list of perspectives known to the MDI. The caller must not 
  883.    --  free the list 
  884.  
  885.    function Current_Perspective 
  886.      (MDI : access MDI_Window_Record'Class) return String; 
  887.    --  Return the name of the currently displayed perspective 
  888.  
  889.    ------------- 
  890.    -- Signals -- 
  891.    ------------- 
  892.  
  893.    --  <signals> 
  894.    --  The following new signals are defined for this widget: 
  895.    -- 
  896.    --  - "child_selected" 
  897.    --    procedure Handler 
  898.    --       (MDI : access MDI_Window_Record'Class; Child : System.Address); 
  899.    -- 
  900.    --    This signal is emitted when a new child has gained the focus. Convert 
  901.    --    Child to a MDI_Child by calling Gtk.Arguments.To_Object. This can be 
  902.    --    used to change some global information at the MDI level. You should 
  903.    --    connect to "selected" (see below) instead if you want to change some 
  904.    --    information at the child level. 
  905.    --    Child might be null if no child has the focus anymore 
  906.    -- 
  907.    --  - "float_child" 
  908.    --    procedure Handler 
  909.    --       (MDI : access MDI_Window_Record'Class; Child : System.Address); 
  910.    -- 
  911.    --    A child was set as floating in the MDI. A similar signal is emitted on 
  912.    --    the child itself. 
  913.    -- 
  914.    --  - "child_title_changed" 
  915.    --    procedure Handler 
  916.    --      (MDI : access MDI_Window_Record'Class; Child : System.Address); 
  917.    -- 
  918.    --    Emitted when the title of a child is changed. This signal is not 
  919.    --    emitted if Set_Title is called for a child that hasn't been put in the 
  920.    --    MDI yet. 
  921.    -- 
  922.    --  - "child_added" 
  923.    --     procedure Handler 
  924.    --       (MDI : access MDI_Window_Record'Class; Child : System.Address); 
  925.    --     Emitted when a new child is added. You cannot use the "add" signal 
  926.    --     since in fact the children are added to notebooks that are part of 
  927.    --     the MDI, and thus "add" is only emitted when a new notebook is 
  928.    --     created. 
  929.    -- 
  930.    --  - "child_removed" 
  931.    --     procedure Handler 
  932.    --       (MDI : access MDI_Window_Record'Class; Child : System.Address); 
  933.    --     Emitted when a new child is removed. You cannot use the "remove" 
  934.    --     signal since in fact the children are removed from notebooks that are 
  935.    --     part of the MDI, and thus "remove" is only emitted when a new 
  936.    --     notebook is destroyed. 
  937.    --     When this signal is emitted, Child no longer contains a widget, and 
  938.    --     is no longer part of the children, although you can still access its 
  939.    --     titles. 
  940.    -- 
  941.    --  - "child_icon_changed" 
  942.    --     procedure Handler 
  943.    --       (MDI : access MDI_Window_Record'Class; Child : System.Address); 
  944.    --     Emitted when the icon for Child has changed 
  945.    -- 
  946.    --  - "children_reorganized" 
  947.    --     procedure Handler (MDI : access MDI_Window_Record'Class); 
  948.    --     Emitted when the children have been reorganized: either a split 
  949.    --     occurred, or a window was dropped into another position 
  950.    -- 
  951.    --  - "perspective_changed" 
  952.    --     procedure Handler (MDI : access MDI_Window_Record'Class); 
  953.    --     Called when the user has selected a new perspective. One use is to 
  954.    --     save the new desktop to a file. 
  955.    -- 
  956.    --  </signals> 
  957.    -- 
  958.    --  <signals> 
  959.    --  The following new signals are defined for the MDI_Child_Record object: 
  960.    -- 
  961.    --  - "delete_event" 
  962.    --    function Handler (Child : access Gtk_Widget_Record'Class) 
  963.    --                     return Boolean; 
  964.    -- 
  965.    --    This signal is emitted for each item in the MDI window before it is 
  966.    --    actually deleted. The child is destroyed only if the handler returns 
  967.    --    False. 
  968.    --    Note that the Child passed in argument is exactly the one you passed 
  969.    --    to Put to insert it in the MDI window. 
  970.    --    Note that this is also the signal to use to prevent top level 
  971.    --    Gtk_Window from being destroyed. 
  972.    -- 
  973.    --  - "selected" 
  974.    --    procedure Handler (Child : access MDI_Child_Record'Class); 
  975.    -- 
  976.    --    This is emitted when the child is selected, ie gains the 
  977.    --    MDI focus. You should probably also connect to the "grab_focus" signal 
  978.    --    to be informed when the child gets the keyboard focus. This can be 
  979.    --    used to transfer the focus to some specific part of the 
  980.    --    widget. Connecting to "grab_focus" should be done with the After 
  981.    --    parameter set to True. 
  982.    -- 
  983.    --  - "float_child" 
  984.    --    procedure Handler (Child : access MDI_Child_Record'Class); 
  985.    -- 
  986.    --    Emitted when a child is set as floating 
  987.    -- 
  988.    --  - "unfloat_child" 
  989.    --    procedure Handler (Child : access MDI_Child_Record'Class); 
  990.    -- 
  991.    --    Emitted when a child is put back in the main MDI window 
  992.    -- 
  993.    --  - "child_state_changed" 
  994.    --    procedure Handler (Child : access MDI_Child_Record'Class); 
  995.    -- 
  996.    --    Emitted when the state of the child has changed. See the function 
  997.    --    Get_State. In particular, this signal can be detected when a child is 
  998.    --    removed from the current perspective (the new state is "invisible"), 
  999.    --    and when it is put back (the new state is "normal" or "floating"). 
  1000.    -- 
  1001.    --  </signals> 
  1002.  
  1003.    Signal_Child_Selected       : constant Signal_Name := "child_selected"; 
  1004.    Signal_Float_Child          : constant Signal_Name := "float_child"; 
  1005.    Signal_Child_Title_Changed  : constant Signal_Name := "child_title_changed"; 
  1006.    Signal_Child_Added          : constant Signal_Name := "child_added"; 
  1007.    Signal_Child_Removed        : constant Signal_Name := "child_removed"; 
  1008.    Signal_Child_Icon_Changed   : constant Signal_Name := "child_icon_changed"; 
  1009.    Signal_Delete_Event         : constant Signal_Name := "delete_event"; 
  1010.    Signal_Selected             : constant Signal_Name := "selected"; 
  1011.    Signal_Unfloat_Child        : constant Signal_Name := "unfloat_child"; 
  1012.    Signal_Perspective_Changed  : constant Signal_Name := "perspective_changed"; 
  1013.    Signal_Children_Reorganized : constant Signal_Name := 
  1014.                                    "children_reorganized"; 
  1015.    Signal_Child_State_Changed  : constant Signal_Name := "child_state_changed"; 
  1016.  
  1017. private 
  1018.    type String_Access is access all UTF8_String; 
  1019.  
  1020.    type MDI_Child_Record is new Gtk.Event_Box.Gtk_Event_Box_Record with record 
  1021.       Initial       : Gtk.Widget.Gtk_Widget; 
  1022.       --  The widget we use to build this child. 
  1023.  
  1024.       Main_Box      : Gtk.Box.Gtk_Box; 
  1025.       --  The main container. 
  1026.  
  1027.       State         : State_Type := Normal; 
  1028.       Group         : Child_Group := Group_Default; 
  1029.       Areas         : Allowed_Areas := Both; 
  1030.  
  1031.       Title         : String_Access; 
  1032.       Short_Title   : String_Access; 
  1033.       --  Title of the item, as it appears in the title bar. 
  1034.       --  These are UTF8-Encoded 
  1035.  
  1036.       XML_Node_Name : String_Access; 
  1037.       --  The name of the XML node when this child is saved in a desktop (if 
  1038.       --  we know it). This is used to reuse a child when switching 
  1039.       --  perspectives. 
  1040.  
  1041.       MDI           : MDI_Window; 
  1042.       --  The MDI to which the child belongs. We cannot get this information 
  1043.       --  directly from Get_Parent since some children are actually floating 
  1044.       --  and do not belong to the MDI anymore. 
  1045.  
  1046.       Menu_Item     : Gtk.Radio_Menu_Item.Gtk_Radio_Menu_Item; 
  1047.       --  The item in the dynamic menu that represents this child. 
  1048.  
  1049.       Flags         : Child_Flags; 
  1050.  
  1051.       Focus_Widget  : Gtk.Widget.Gtk_Widget; 
  1052.       --  The widget which should actually get the keyboard focus 
  1053.  
  1054.       Title_Box     : Gtk.Box.Gtk_Box; 
  1055.       Title_Label   : Gtk.Label.Gtk_Label; 
  1056.       Title_Icon    : Gtk.Image.Gtk_Image; 
  1057.       --  Box that contains the title. It will be resized whenever the title 
  1058.       --  font changes. 
  1059.  
  1060.       Tab_Label     : Gtk.Label.Gtk_Label; 
  1061.       Tab_Icon      : Gtk.Image.Gtk_Image; 
  1062.       --  label used when child is in a notebook, null if not in a notebook 
  1063.    end record; 
  1064.  
  1065.    type Child_Iterator (Group_By_Notebook : Boolean := False) is record 
  1066.       Visible_Only : Boolean; 
  1067.  
  1068.       case Group_By_Notebook is 
  1069.          when False => 
  1070.             Iter : Gtk.Widget.Widget_List.Glist; 
  1071.  
  1072.          when True => 
  1073.             MDI                 : MDI_Window; 
  1074.  
  1075.             --  While iterating children 
  1076.             Paned_Iter          : Gtkada.Multi_Paned.Child_Iterator; 
  1077.  
  1078.             --  Whether we have already visited the children of the central 
  1079.             --  area. This is True while iterating them, False afterward 
  1080.             In_Central          : Boolean; 
  1081.  
  1082.             --  While iterating the pages of a specific notebook (notebook is 
  1083.             --  set to null when returning floating children) 
  1084.             Notebook            : Gtk.Notebook.Gtk_Notebook; 
  1085.             Notebook_Page       : Glib.Gint; 
  1086.  
  1087.             --  While iterating the floating children 
  1088.             Floating_Iter       : Gtk.Widget.Widget_List.Glist; 
  1089.       end case; 
  1090.    end record; 
  1091.  
  1092.    type Drag_Status is (No_Drag, In_Pre_Drag, In_Drag); 
  1093.  
  1094.    type MDI_Window_Record is new Gtkada.Multi_Paned.Gtkada_Multi_Paned_Record 
  1095.    with record 
  1096.       Items : Gtk.Widget.Widget_List.Glist := Gtk.Widget.Widget_List.Null_List; 
  1097.       --  The list of all MDI children. This includes children in the editor 
  1098.       --  area, even though they are technically in a separate multi_paned. 
  1099.       --  Warning: this list might contain items which are in fact invisible in 
  1100.       --  the MDI (in fact that are not even children of the MDI), if they 
  1101.       --  existed in a previous perspective but no longer in the current one. 
  1102.  
  1103.       Desktop_Was_Loaded : Boolean := False; 
  1104.       --  True if a desktop was loaded 
  1105.  
  1106.       Loading_Desktop : Boolean := False; 
  1107.       --  Whether we are currently loading the desktop. This impacts a number 
  1108.       --  of focus and sizing parameters, so that the desktop can be restored 
  1109.       --  as accurately as possible. 
  1110.  
  1111.       Delay_Before_Focus_Id : Glib.Main.G_Source_Id := Glib.Main.No_Source_Id; 
  1112.       Delay_Before_Focus : Glib.Guint := 700; 
  1113.       --  Delay in ms before a floating window gains the GPS focus, after the 
  1114.       --  "focus_in" event. In all floating mode, this ensures that when the 
  1115.       --  user is passing briefly over floating windows they do not gain the 
  1116.       --  focus, thus potentially leaving the focus to the window that had it 
  1117.       --  at the beginning of the move. 
  1118.       --  Set to 0 to remove any delay. 
  1119.  
  1120.       Focus_Child : MDI_Child := null; 
  1121.       --  The child that currently has the focus. Some default actions will 
  1122.       --  apply to this child only. 
  1123.  
  1124.       Dnd_Message : String_Access; 
  1125.       --  The message displayed during a dnd operation (see Set_Dnd_Message) 
  1126.  
  1127.       Accel_Path_Prefix   : String_Access; 
  1128.       --  The Accel path used for the dynamic menu 
  1129.  
  1130.       Menu                : Gtk.Menu.Gtk_Menu; 
  1131.       Float_Menu_Item     : Gtk.Check_Menu_Item.Gtk_Check_Menu_Item; 
  1132.       Float_Menu_Item_Id  : Gtk.Handlers.Handler_Id; 
  1133.       Close_Menu_Item     : Gtk.Menu_Item.Gtk_Menu_Item; 
  1134.       --  The dynamic menu used to provide access to the most common 
  1135.       --  functions of MDI. 
  1136.  
  1137.       Tab_Factory         : Tab_Contextual_Menu_Factory; 
  1138.       --  Build the contextual menu when right-clicking on tabs 
  1139.  
  1140.       Title_Bar_Height    : Glib.Gint; 
  1141.       --  Height of the title bar for all the children 
  1142.  
  1143.       Title_Font : Pango.Font.Pango_Font_Description; 
  1144.       --  The font used for the titles of the children 
  1145.  
  1146.       Close_Floating_Is_Unfloat : Boolean; 
  1147.       --  True if destroying a floating window will put the child back in the 
  1148.       --  MDI instead of destroying it. False if the child should be destroyed 
  1149.       --  (provided it accepts so in its delete_event handler). 
  1150.  
  1151.       Title_Bar_Color     : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; 
  1152.       Focus_Title_Color   : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; 
  1153.       Default_Title_Color : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; 
  1154.       Css_Provider        : Gtk.Css_Provider.Gtk_Css_Provider; 
  1155.  
  1156.       Cursor_Cross        : Gdk.Gdk_Cursor; 
  1157.       Cursor_Fleur        : Gdk.Gdk_Cursor; 
  1158.       --  Cached cursors 
  1159.  
  1160.       Draw_Title_Bars   : Title_Bars_Policy := Always; 
  1161.       Tabs_Position     : Gtk.Enums.Gtk_Position_Type := Gtk.Enums.Pos_Top; 
  1162.       Show_Tabs_Policy  : Show_Tabs_Policy_Enum := Automatic; 
  1163.  
  1164.       Selection_Dialog : Gtk.Widget.Gtk_Widget; 
  1165.       --  The interactive dialog for selecting new children. 
  1166.  
  1167.       Group : Gtk.Accel_Group.Gtk_Accel_Group; 
  1168.  
  1169.       All_Floating_Mode : Boolean := False; 
  1170.       --  Set to true if all windows should be set to floating 
  1171.  
  1172.       Independent_Perspectives : Boolean := False; 
  1173.       --  See documentation for Configure. 
  1174.  
  1175.       Use_Short_Titles_For_Floats : Boolean := False; 
  1176.       --  Set to true if all floating children should use their short titles. 
  1177.       --  This also applies to docked windows. 
  1178.  
  1179.       Homogeneous_Tabs : Boolean := True; 
  1180.  
  1181.       --  Handling of Dnd 
  1182.       Drag_Start_X, Drag_Start_Y : Gint; 
  1183.       In_Drag           : Drag_Status := No_Drag; 
  1184.       Dnd_Rectangle     : Gdk.Rectangle.Gdk_Rectangle;  --  Highlighted area 
  1185.       Old_Dnd_Position  : Child_Position; 
  1186.  
  1187.       Dnd_Rectangle_Real : Gdk.Rectangle.Gdk_Rectangle; 
  1188.       --  Area to redraw to delete the Dnd overlay window 
  1189.  
  1190.       Dnd_Target        : Gdk.Gdk_Window;     --  The current target for DND 
  1191.  
  1192.       Dnd_Overlay : Cairo.Cairo_Surface := Cairo.Null_Surface; 
  1193.  
  1194.       Drag_Areas : Allowed_Areas; 
  1195.       --  The allowed areas during a drag 
  1196.  
  1197.       --  Loaded perspectives 
  1198.       Perspective_Menu_Item  : Gtk.Menu_Item.Gtk_Menu_Item; 
  1199.       Perspectives           : Glib.Xml_Int.Node_Ptr; 
  1200.       View_Contents          : Glib.Xml_Int.Node_Ptr; 
  1201.       Perspective_Names      : GNAT.Strings.String_List_Access; 
  1202.       Central                : Gtkada.Multi_Paned.Gtkada_Multi_Paned; 
  1203.  
  1204.       Current_Perspective    : Glib.Xml_Int.Node_Ptr; 
  1205.       --  pointer into Perspectives 
  1206.    end record; 
  1207.  
  1208.    pragma Inline (Get_Widget); 
  1209.    pragma Inline (Get_Focus_Child); 
  1210.    pragma Inline (Get); 
  1211.    pragma Inline (Next); 
  1212.    pragma Inline (First_Child); 
  1213.  
  1214. end Gtkada.MDI;