1. ----------------------------------------------------------------------- 
  2. --               GtkAda - Ada95 binding for Gtk+/Gnome               -- 
  3. --                                                                   -- 
  4. --                 Copyright (C) 2003-2006 AdaCore                   -- 
  5. --                                                                   -- 
  6. -- This library is free software; you can redistribute it and/or     -- 
  7. -- modify it under the terms of the GNU General Public               -- 
  8. -- License as published by the Free Software Foundation; either      -- 
  9. -- version 2 of the License, or (at your option) any later version.  -- 
  10. --                                                                   -- 
  11. -- This library is distributed in the hope that it will be useful,   -- 
  12. -- but WITHOUT ANY WARRANTY; without even the implied warranty of    -- 
  13. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -- 
  14. -- General Public License for more details.                          -- 
  15. --                                                                   -- 
  16. -- You should have received a copy of the GNU General Public         -- 
  17. -- License along with this library; if not, write to the             -- 
  18. -- Free Software Foundation, Inc., 59 Temple Place - Suite 330,      -- 
  19. -- Boston, MA 02111-1307, USA.                                       -- 
  20. --                                                                   -- 
  21. -- -- -- -- -- -- -- -- -- -- -- --
  22. ----------------------------------------------------------------------- 
  23.  
  24. --  <description> 
  25. --  This widget implements a multi-paned widget, similar to the standard 
  26. --  Gtk_Paned widget, but which can contain several children side to side. 
  27. --  This widget can mix vertical and horizontal splits 
  28. --  </description> 
  29. --  <group>Layout containers</group> 
  30. --  <testgtk>create_splittable.adb</testgtk> 
  31.  
  32. with Glib;       use Glib; 
  33. with Gdk.Cursor; 
  34. with Gdk.GC; 
  35. with Gtk.Enums; 
  36. with Gtk.Fixed; 
  37. with Gtk.Widget; 
  38.  
  39. package Gtkada.Multi_Paned is 
  40.    type Gtkada_Multi_Paned_Record is new Gtk.Fixed.Gtk_Fixed_Record 
  41.      with private; 
  42.    type Gtkada_Multi_Paned is access all Gtkada_Multi_Paned_Record'Class; 
  43.  
  44.    Handle_Width : constant := 6; 
  45.    --  Width, in pixels, of the resizing handles. 
  46.    --  ??? Should be read from theme with 
  47.    --     gtk_widget_style_get (gtk_paned, "handle_size", &handle_size, NULL) 
  48.  
  49.    type Pane is private; 
  50.    --  An area of the window, which can is splitted either horizontally or 
  51.    --  vertically. It can contain one or several children, next to each other, 
  52.    --  or on top of one another. 
  53.  
  54.    Root_Pane : constant Pane; 
  55.    --  The root pane. If you split this one, the newly added window will be 
  56.    --  next to all other windows. For instance, if you split vertically with 
  57.    --  the main_pane the following window, you will get: 
  58.    --     +-----+------+        +-----+------+ 
  59.    --     |  1  |      |        |  1  |      | 
  60.    --     +-----+  3   |    =>  +-----+  3   | 
  61.    --     |  2  |      |        |  2  |      | 
  62.    --     +-----+------+        +-----+------+ 
  63.    --                           |     4      | 
  64.    --                           +------------+ 
  65.  
  66.    procedure Gtk_New (Win : out Gtkada_Multi_Paned); 
  67.    procedure Initialize (Win : access Gtkada_Multi_Paned_Record'Class); 
  68.    --  Create a new paned window. 
  69.  
  70.    procedure Set_Opaque_Resizing 
  71.      (Win : access Gtkada_Multi_Paned_Record; Opaque : Boolean); 
  72.    --  Whether resizing of the widgets should be opaque or not. The default 
  73.    --  is not to do opaque resizing for efficiency reasons 
  74.  
  75.    procedure Add_Child 
  76.      (Win           : access Gtkada_Multi_Paned_Record; 
  77.       New_Child     : access Gtk.Widget.Gtk_Widget_Record'Class; 
  78.       Orientation   : Gtk.Enums.Gtk_Orientation := 
  79.         Gtk.Enums.Orientation_Horizontal; 
  80.       Fixed_Size    : Boolean := False; 
  81.       Width, Height : Glib.Gint := 0; 
  82.       After         : Boolean := True); 
  83.    --  Add new child, splitting as needed. 
  84.    --  This should be used when there is no child yet 
  85.    --  The window is splitted in two by default. However, if Width and Height 
  86.    --  are specified (or left to -1 for automatic computation), the window is 
  87.    --  splitted so that amount of screen space is left to the widget 
  88.    --  (leaving some minimum amount of space to other children as needed). 
  89.    --  If Fixed_Size is true, then the size of the dock will not change when 
  90.    --  Win is resized. Otherwise, it will keep its relative size (x% of the 
  91.    --  total size of Win). This Fixed_Size setting will be reset to False 
  92.    --  as soon as the user has resized a pane with the mouse. 
  93.  
  94.    procedure Split 
  95.      (Win           : access Gtkada_Multi_Paned_Record; 
  96.       Ref_Widget    : access Gtk.Widget.Gtk_Widget_Record'Class; 
  97.       New_Child     : access Gtk.Widget.Gtk_Widget_Record'Class; 
  98.       Orientation   : Gtk.Enums.Gtk_Orientation; 
  99.       Fixed_Size    : Boolean := False; 
  100.       Width, Height : Glib.Gint := 0; 
  101.       After         : Boolean := True); 
  102.    --  Split the pane containing Ref_Widget, and add New_Child 
  103.    --  in the new pane (on the right or at the bottom if After is True, on the 
  104.    --  left or at the top if After is False). 
  105.  
  106.    procedure Set_Size 
  107.      (Win           : access Gtkada_Multi_Paned_Record; 
  108.       Widget        : access Gtk.Widget.Gtk_Widget_Record'Class; 
  109.       Width, Height : Glib.Gint := -1; 
  110.       Fixed_Size    : Boolean := False); 
  111.    --  Force a specific size for Widget 
  112.  
  113.    function Splitted_Area 
  114.      (Win           : access Gtkada_Multi_Paned_Record; 
  115.       Ref_Widget    : access Gtk.Widget.Gtk_Widget_Record'Class; 
  116.       Orientation   : Gtk.Enums.Gtk_Orientation; 
  117.       After         : Boolean := True) return Gtk.Widget.Gtk_Widget; 
  118.    --  Return the widget in the splitted area next to Ref_Widget if any exist. 
  119.    --  Orientation and After define which splitted area we are looking at. 
  120.    --  null is returned if there are no such splitted area. 
  121.  
  122.    function Get_Pane 
  123.      (Win    : access Gtkada_Multi_Paned_Record; 
  124.       Widget : access Gtk.Widget.Gtk_Widget_Record'Class) return Pane; 
  125.    function Get_Pane (Current_Pane : Pane) return Pane; 
  126.    --  Return the pane that contains the widget. See comment for Split below. 
  127.  
  128.    procedure Split 
  129.      (Win           : access Gtkada_Multi_Paned_Record; 
  130.       Ref_Pane      : Pane; 
  131.       New_Child     : access Gtk.Widget.Gtk_Widget_Record'Class; 
  132.       Orientation   : Gtk.Enums.Gtk_Orientation; 
  133.       Fixed_Size    : Boolean := False; 
  134.       Width, Height : Glib.Gint := 0; 
  135.       After         : Boolean := True); 
  136.    --  Split Ref_Pane to display New_Child to one of its sides. 
  137.    --  See the comments for Root_Pane above. 
  138.    --  The examples below assume that you are using one of the two split 
  139.    --  procedures, either with a Ref_Pane or a Ref_Widget. In the former case, 
  140.    --  the pane is obtained with a call to Get_Pane(Ref_Widget). 
  141.    --  As you will see, the results are different (although they might appear 
  142.    --  similar sometimes on this simple example. 
  143.    --  In all these examples, we split either vertically or horizontally, and 
  144.    --  add a new widget "4". 
  145.    -- 
  146.    --  Given the following setup: 
  147.    --     +---+---+ 
  148.    --     | 1 |   | 
  149.    --     +---+ 3 | 
  150.    --     | 2 |   | 
  151.    --     +---+---+ 
  152.    -- 
  153.    --  Ref_Pane = Get_Pane ("1")              Ref_Widget = "1" 
  154.    --  Split vertically 
  155.    --    After=True  After=False        After=True   After=False 
  156.    --    +---+---+   +---+---+          +---+---+    +---+---+ 
  157.    --    | 1 | 3 |   | 4 | 3 |          | 1 | 3 |    | 4 | 3 | 
  158.    --    +---+   |   +---+   |          +---+   |    +---+   | 
  159.    --    | 2 |   |   | 1 |   |          | 4 |   |    | 1 |   | 
  160.    --    +---+   |   +---+   |          +---+   |    +---+   | 
  161.    --    | 4 |   |   | 2 |   |          | 2 |   |    | 2 |   | 
  162.    --    +---+---+   +---+---+          +---+---+    +---+---+ 
  163.    -- 
  164.    --  Split horizontally 
  165.    --    After=True     After=False     After=True     After=False 
  166.    --    +---+---+---+  +---+---+---+   +---+---+---+  +---+---+---+ 
  167.    --    | 1 | 4 | 3 |  | 4 | 1 | 3 |   | 1 | 4 | 3 |  | 4 | 1 | 3 | 
  168.    --    +---+   |   |  |   +---+   |   +---+---+   |  +---+---+   | 
  169.    --    | 2 |   |   |  |   | 2 |   |   |   2   |   |  |   2   |   | 
  170.    --    +---+---+---+  +---+---+---+   +-------+---+  +-------+---+ 
  171.    -- 
  172.    -- 
  173.    --  Ref_Pane = Get_Pane ("3")             Ref_Widget = "3" 
  174.    --  Split vertically 
  175.    --    After=True   After=False       After=True     After=False 
  176.    --    +---+---+    +-------+         +---+---+      +---+---+ 
  177.    --    | 1 | 3 |    |   4   |         | 1 | 3 |      | 1 | 4 | 
  178.    --    +---+   |    +---+---+         +---+---+      +---+---+ 
  179.    --    | 2 |   |    | 1 | 3 |         | 2 | 4 |      | 2 | 3 | 
  180.    --    +---+---+    +---+   |         +---+---+      +---+---+ 
  181.    --    |   4   |    | 2 |   | 
  182.    --    +-------+    +---+---+ 
  183.    -- 
  184.    --  Split horizontally 
  185.    --    After=True     After=False     After=True     After=False 
  186.    --    +---+---+---+  +---+---+---+   +---+---+---+  +---+---+---+ 
  187.    --    | 1 | 3 | 4 |  | 4 | 1 | 3 |   | 1 | 3 | 4 |  | 1 | 4 | 3 | 
  188.    --    +---+   |   |  |   +---+   |   +---+   |   |  +---+   |   | 
  189.    --    | 2 |   |   |  |   | 2 |   |   | 2 |   |   |  | 2 |   |   | 
  190.    --    +---+---+---+  +---+---+---+   +---+---+---+  +---+---+---+ 
  191.  
  192.    procedure Freeze (Win : access Gtkada_Multi_Paned_Record); 
  193.    --  Freeze the window, ie when a child is inserted, no computation of its 
  194.    --  size is done, and will not generate immediate resizing. 
  195.    --  You only need to call this procedure when restoring Win to a previously 
  196.    --  state saved, and never if you are using the GtkAda.MDI which takes care 
  197.    --  of it on its own. 
  198.  
  199.    procedure Thaw (Win : access Gtkada_Multi_Paned_Record); 
  200.    --  Opposite of Freeze. You should call Size_Allocate on Win afterward to 
  201.    --  force a recomputation of the size 
  202.  
  203.    --------------- 
  204.    -- Iterators -- 
  205.    --------------- 
  206.  
  207.    type Child_Iterator is private; 
  208.  
  209.    function Start 
  210.      (Win : access Gtkada_Multi_Paned_Record) return Child_Iterator; 
  211.    --  Return an iterator to the first child of the window. This also returns 
  212.    --  children which are not widget, but are used to organize the window into 
  213.    --  horizontal and vertical panes 
  214.  
  215.    function At_End (Iter : Child_Iterator) return Boolean; 
  216.    --  True if there is no more child to be returned 
  217.  
  218.    procedure Next (Iter : in out Child_Iterator); 
  219.    --  Move to the next child of Iterator 
  220.  
  221.    function Get_Widget (Iter : Child_Iterator) return Gtk.Widget.Gtk_Widget; 
  222.    --  Return the widget embedded in the current child. This returns null if 
  223.    --  the current child is only used as a pane separator (horizontal or 
  224.    --  vertical). You mustn't remove the widget from the paned widget, or the 
  225.    --  iterator becomes invalid. 
  226.  
  227.    function Get_Orientation 
  228.      (Iter : Child_Iterator) return Gtk.Enums.Gtk_Orientation; 
  229.    --  Return the orientation of the current child. This is only relevant if 
  230.    --  the child doesn't contain a widget (and therefore Get_Widget has 
  231.    --  returned null). 
  232.  
  233.    function Get_Depth (Iter : Child_Iterator) return Natural; 
  234.    --  Return the depth of the current child (0 means the child is at the 
  235.    --  toplevel, 1 that this is a child directly underneath,...). 
  236.    --  This can be used to detect when the Iter has finished traversing one 
  237.    --  of the panes. 
  238.  
  239.    procedure Get_Size 
  240.      (Iter                        : Child_Iterator; 
  241.       Width, Height               : out Gint; 
  242.       Parent_Width, Parent_Height : out Gint; 
  243.       Parent_Orientation          : out Gtk.Enums.Gtk_Orientation); 
  244.    --  Return the size of the current element (pane or widget), as well as the 
  245.    --  parent's pane (the resizable area that contains notebooks or other 
  246.    --  panes). The parent size is the total size devoted to its children, 
  247.    --  omitting the size occupied by resize handles. 
  248.  
  249.    procedure Dump (Split : access Gtkada_Multi_Paned_Record'Class); 
  250.    --  Dump the configuration of Split to stdout. This is only intended for 
  251.    --  testing purposes. If you want to save and restore this configuration, 
  252.    --  you should look at Gtkada.MDI instead, which contains all the 
  253.    --  subprograms needed to handle desktops. 
  254.  
  255. private 
  256.    type Child_Description; 
  257.    type Child_Description_Access is access Child_Description; 
  258.  
  259.    type Pane is new Child_Description_Access; 
  260.    Root_Pane : constant Pane := null; 
  261.  
  262.    type Child_Iterator is record 
  263.       Current : Child_Description_Access; 
  264.       Depth   : Natural := 0; 
  265.    end record; 
  266.  
  267.    type Gtkada_Multi_Paned_Record is new Gtk.Fixed.Gtk_Fixed_Record with record 
  268.       Frozen      : Boolean := False; 
  269.       Children    : Child_Description_Access; 
  270.       GC          : Gdk.GC.Gdk_GC; 
  271.  
  272.       Initial_Pos  : Gint; 
  273.       Selected     : Child_Description_Access; 
  274.       Selected_Pos : Gtk.Widget.Gtk_Allocation; 
  275.  
  276.       Cursor_Double_H_Arrow : Gdk.Cursor.Gdk_Cursor; 
  277.       Cursor_Double_V_Arrow : Gdk.Cursor.Gdk_Cursor; 
  278.  
  279.       Opaque_Resizing        : Boolean := False; 
  280.    end record; 
  281.  
  282. end Gtkada.Multi_Paned;