1. private with Ada.Containers.Indefinite_Doubly_Linked_Lists; 
  2.  
  3. package Widgets.Containers is 
  4.  
  5.     -- A Container widget is a parent widget that contains multiple child 
  6.     -- widgets. Each child widget is drawn within the content area of the 
  7.     -- parent. Widget layouts applied to child widgets are relative to the 
  8.     -- content area of their container. An input event not handled by a widget 
  9.     -- will be passed up the widget tree to its container. 
  10.     type Container is abstract new Widget with private; 
  11.     type A_Container is access all Container'Class; 
  12.  
  13.     -- Adds 'child' as a child widget of this container. The child's parent is 
  14.     -- set by this procedure. If 'consume' is True, 'child' will be consumed, 
  15.     -- otherwise it will be left as-is. In either case, however, the Container 
  16.     -- will own 'child' after this is called, and will delete it if it's still a 
  17.     -- child at the time of deletion. 
  18.     procedure Add( this    : access Container; 
  19.                    child   : in out A_Widget; 
  20.                    consume : Boolean := True ); 
  21.     pragma Precondition( child /= null ); 
  22.     pragma Postcondition( consume xor child /= null ); 
  23.  
  24.     -- Brings the 'child' widget to the front of the drawing Z-order within this 
  25.     -- container. If 'child' overlaps any sibling widgets, it will be drawn on 
  26.     -- top. 
  27.     procedure Bring_To_Front( this  : access Container; 
  28.                               child : not null A_Widget ); 
  29.  
  30.     -- Applies the container's special child layout to the given child widget. 
  31.     procedure Apply_Container_Layout( this  : access Container; 
  32.                                       child : not null A_Widget ); 
  33.  
  34.     -- Removes and deletes all child widgets. 
  35.     procedure Delete_Children( this : access Container ); 
  36.  
  37.     -- Draws the container's content behind its children. This will be called 
  38.     -- before child widgets are drawn, in the back-to-front drawing model. 
  39.     procedure Draw_Content( this : access Container; dc : Drawing_Context ) is abstract; 
  40.  
  41.     -- Removes the widget from the child list without deleting it. The child's 
  42.     -- parent reference is not modified. 
  43.     procedure Remove( this : access Container; child : not null A_Widget ); 
  44.  
  45. private 
  46.  
  47.     WIDGET_NOT_FOUND : exception; 
  48.  
  49.     -- provides a linked list of widgets 
  50.     package Widget_Lists is new Ada.Containers.Indefinite_Doubly_Linked_Lists( A_Widget, "=" ); 
  51.  
  52.     ---------------------------------------------------------------------------- 
  53.  
  54.     type Container is abstract new Widget with 
  55.         record 
  56.             childbmp        : A_Bitmap := null; 
  57.             children        : Widget_Lists.List; 
  58.             childLayout     : A_Layout := null; 
  59.  
  60.             -- If True, Draw_Content will be called a second time after drawing 
  61.             -- children, with the layer of the drawing context set to Foreground. 
  62.             -- This is so the widget can draw over its children. Setting this to 
  63.             -- True will cause Draw_Content to be called twice on every redraw, 
  64.             -- regardless of the container's dirty flag, which is expensive. 
  65.             drawForeground : Boolean := False; 
  66.         end record; 
  67.  
  68.     procedure Delete( this : in out Container ); 
  69.  
  70.     -- Removes and deletes a child widget. If the given widget is not a child 
  71.     -- then a WIDGET_NOT_FOUND exception will be raised. 'child' will be 
  72.     -- consumed if successful. 
  73.     procedure Delete_Child( this : access Container; child : in out A_Widget ); 
  74.     pragma Precondition( child /= null ); 
  75.     pragma Postcondition( child = null ); 
  76.  
  77.     -- Draws self before drawing children, in a back-to-front order. 
  78.     procedure Draw( this : access Container; 
  79.                     bmp  : not null A_Bitmap; 
  80.                     x, y : Integer ); 
  81.  
  82.     -- Draws each of the children onto 'bmp'. 'bmp' must match the size of the 
  83.     -- container's content area. 
  84.     procedure Draw_Children( this : access Container; 
  85.                              bmp  : not null A_Bitmap ); 
  86.  
  87.     -- Returns the child widget (or self) containing the given coordinates 
  88.     -- relative to the widget's viewport, and the widget coordinates that 
  89.     -- 'x','y' map to ('wx','wy') within the found widget's content area. 
  90.     procedure Find_Widget( this   : access Container; 
  91.                            x, y   : Integer; 
  92.                            wx, wy : out Integer; 
  93.                            found  : out A_Widget ); 
  94.  
  95.     -- Calls Handle_Ancestor_Hidden on each of the children after handling 
  96.     -- Handle_Ancestor_Hidden for self. 
  97.     procedure Handle_Ancestor_Hidden( this : access Container ); 
  98.  
  99.     -- Calls Handle_Ancestor_Unhidden on each of the children after handling 
  100.     -- Handle_Ancestor_Unhidden for self. 
  101.     procedure Handle_Ancestor_Unhidden( this : access Container ); 
  102.  
  103.    -- Invokes Handle_Resize on each of the children after resizing self. 
  104.     procedure Handle_Resize( this : access Container ); 
  105.  
  106.     -- Calls Pack on each of the children after packing self. 
  107.     procedure Pack( this : access Container ); 
  108.  
  109.     -- Sets the zoom level of the container. If zooming in, the child widgets 
  110.     -- will appear proportionately larger in size. Their zoom levels remain 
  111.     -- independently controlled, as expected. 
  112.     procedure Set_Zoom( this : access Container; zoom : Float ); 
  113.  
  114. end Widgets.Containers;