1. ----------------------------------------------------------------------- 
  2. --               GtkAda - Ada95 binding for Gtk+/Gnome               -- 
  3. --                                                                   -- 
  4. --   Copyright (C) 1998-2000 E. Briot, J. Brobecker and A. Charlet   -- 
  5. --                Copyright (C) 2000-2010, AdaCore                   -- 
  6. --                                                                   -- 
  7. -- This library is free software; you can redistribute it and/or     -- 
  8. -- modify it under the terms of the GNU General Public               -- 
  9. -- License as published by the Free Software Foundation; either      -- 
  10. -- version 2 of the License, or (at your option) any later version.  -- 
  11. --                                                                   -- 
  12. -- This library is distributed in the hope that it will be useful,   -- 
  13. -- but WITHOUT ANY WARRANTY; without even the implied warranty of    -- 
  14. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -- 
  15. -- General Public License for more details.                          -- 
  16. --                                                                   -- 
  17. -- You should have received a copy of the GNU General Public         -- 
  18. -- License along with this library; if not, write to the             -- 
  19. -- Free Software Foundation, Inc., 59 Temple Place - Suite 330,      -- 
  20. -- Boston, MA 02111-1307, USA.                                       -- 
  21. --                                                                   -- 
  22. -- As a special exception, if other files instantiate generics from  -- 
  23. -- this unit, or you link this unit with other files to produce an   -- 
  24. -- executable, this  unit  does not  by itself cause  the resulting  -- 
  25. -- executable to be covered by the GNU General Public License. This  -- 
  26. -- exception does not however invalidate any other reasons why the   -- 
  27. -- executable file  might be covered by the  GNU Public License.     -- 
  28. ----------------------------------------------------------------------- 
  29.  
  30. --  <description> 
  31. --  This package provides an interactive canvas, on which the user can put 
  32. --  items, move them with the mouse, etc. The items can be connected together, 
  33. --  and the connections remain active while the items are moved. 
  34. -- 
  35. --  It also supports scrolling if put in a Gtk_Scrolled_Window. 
  36. --  The canvas will be scrolled (and the selected items moved) if an item is 
  37. --  selected and the mouse is dragged on a small area on the side of the canvas 
  38. --  or even directly outside of the canvas. Scrolling will continue until the 
  39. --  mouse is either released or moved back inside the canvas. 
  40. -- 
  41. --  The scrolling speed will slightly increase over time if the mouse is kept 
  42. --  outside of the canvas. This makes the canvas much more comfortable to use 
  43. --  for the user. 
  44. -- 
  45. --  All items put in this canvas must inherit from the type Canvas_Item_Record. 
  46. --  However, it is your responsability, as a programmer, to provide drawing 
  47. --  routines. In fact, all these items should draw in a pixmap, which is then 
  48. --  copied automatically to the screen whenever the canvas needs to redraw 
  49. --  itself. 
  50. -- 
  51. --  The items can also react to mouse events: mouse clicks are transmitted to 
  52. --  the item if the mouse did not move more than a given amount of pixels. 
  53. --  To decide what their reaction should be, you should override the 
  54. --  On_Button_Click subprogram. 
  55. -- 
  56. --  This canvas is not intended for cases where you want to put hundreds of 
  57. --  items on the screen. For instance, it does not provide any smart 
  58. --  double-buffering other than the one provided by gtk+ itself, and thus you 
  59. --  would get some flicker if there are too many items. 
  60. -- 
  61. --  There are three coordinate systems used by widget. All the subprograms 
  62. --  expect a specific coordinate system as input or output. Here are the three 
  63. --  systems: 
  64. --    - World coordinates 
  65. --      The position of an item is reported in pixels, as if the canvas 
  66. --      currently had a zoom level of 100%. This is fully independent, at any 
  67. --      time, from the current zoom level of the canvas. 
  68. --      Since the canvas is considered to expand ad infinitum, the top-left 
  69. --      corner doesn't have any specific fixed coordinates. It can be known by 
  70. --      checking the current lower value of the adjustments (aka scrollbars). 
  71. -- 
  72. --    - Canvas coordinates 
  73. --      This is similar to world coordinates, except these depend on the 
  74. --      current zoom level of the canvas. This also affect the width and height 
  75. --      of the objects in the canvas. 
  76. --      The subprograms To_Canvas_Coordinates and To_World_Coordinates can be 
  77. --      used to convert lengths from world to canvas coordinates. 
  78. --      The same behavior as world coordinates applies for the top-left corner. 
  79. --      All drawing to the screen, in particular for Draw_Background, must be 
  80. --      done using this coordinate systems 
  81. -- 
  82. --    - Item coordinates 
  83. --      The position of a point is relative to the top-left corner of the 
  84. --      current item. This corner therefore has coordinates (0, 0). 
  85. --      This coordinate systems assumes a zoom-level of 100% 
  86. -- 
  87. --  Items are selected automatically when they are clicked. If Control is 
  88. --  pressed at the same time, multiple items can be selected. 
  89. --  If the background is clicked (and control is not pressed), then all items 
  90. --  are unselected. 
  91. --  Pressing and dragging the mouse in the backgroudn draws a virtual box on 
  92. --  the screen. All the items fully included in this box when it is released 
  93. --  will be selected (this will replace the current selection if Control was 
  94. --  not pressed). 
  95. -- 
  96. --  </description> 
  97. --  <group>Drawing</group> 
  98. --  <testgtk>create_canvas.adb</testgtk> 
  99. --  <screenshot>gtkada-canvas</screenshot> 
  100.  
  101. with Gdk.Event; 
  102. with Gdk.GC; 
  103. with Gdk.Pixbuf; 
  104. with Gdk.Pixmap; 
  105. with Gdk.Rectangle; 
  106. with Gdk.Window; 
  107.  
  108. with Glib; 
  109. with Glib.Graphs; 
  110. with Glib.Main; 
  111.  
  112. with Gtk.Adjustment; 
  113. with Gtk.Drawing_Area; 
  114.  
  115. with Pango.Font; 
  116. with Pango.Layout; 
  117.  
  118. package Gtkada.Canvas is 
  119.  
  120.    type Interactive_Canvas_Record is new 
  121.      Gtk.Drawing_Area.Gtk_Drawing_Area_Record with private; 
  122.    type Interactive_Canvas is access all Interactive_Canvas_Record'Class; 
  123.    --  A canvas on which items are put. 
  124.    --  Each item can be moved interactively by the user, and links can be 
  125.    --  drawn automatically from an item to another. 
  126.    --  This widget can be inserted directly in a scrolled window to provide 
  127.    --  support for scrolling. 
  128.  
  129.    type Canvas_Item_Record is abstract new Glib.Graphs.Vertex with private; 
  130.    type Canvas_Item is access all Canvas_Item_Record'Class; 
  131.    --  An item that can be put on the canvas. 
  132.    --  This is an abstract type, as it does not provide any default drawing 
  133.    --  routine. You must override the abstract Draw subprogram. 
  134.  
  135.    type Canvas_Link_Record is new Glib.Graphs.Edge with private; 
  136.    type Canvas_Link is access all Canvas_Link_Record'Class; 
  137.    type Canvas_Link_Access is access all Canvas_Link_Record; 
  138.    --  A link between two items in the canvas. 
  139.    --  The implementation provided in this package provides links that can 
  140.    --  be either straight links or curved links. 
  141.    --  This type is provided as a tagged type so that you can associated your 
  142.    --  own user data with it. 
  143.  
  144.    ------------------- 
  145.    -- Customization -- 
  146.    ------------------- 
  147.    --  These are the default configuration values for the canvas. All the 
  148.    --  values can be changed by the Configure subprogram. 
  149.  
  150.    Default_Annotation_Font  : constant String := "Helvetica 8"; 
  151.    --  Font used when displaying link annotation. See Pango.Font for the 
  152.    --  format. 
  153.  
  154.    Default_Grid_Size        : constant := 15; 
  155.    --  Number of pixels between two dots on the grid. 
  156.    --  This is used for both horizontal and vertical orientation. 
  157.  
  158.    Default_Arc_Link_Offset  : constant := 25; 
  159.    --  Distance between two parallel arcs for two links. This is not the exact 
  160.    --  distance, and it only used to compute the control points for the bezier 
  161.    --  curves. 
  162.  
  163.    Default_Arrow_Angle      : constant := 30; 
  164.    --  Half angle for the arrows in degres 
  165.  
  166.    Default_Arrow_Length     : constant := 6; 
  167.    --  Length of the arrows in pixels. 
  168.  
  169.    Default_Motion_Threshold : constant := 4; 
  170.    --  Mimimum motion the mouse must have before we start moving the selected 
  171.    --  item. If the mouse has moved less than that amount of pixels in any 
  172.    --  direction, then the mouse click is considered as being a selection 
  173.    --  only and is transfered to the item itself. 
  174.    --  This is in screen coordinates 
  175.  
  176.    ---------------- 
  177.    -- Enum types -- 
  178.    ---------------- 
  179.  
  180.    type Arrow_Type is 
  181.      (No_Arrow, 
  182.       --  the link does not have an arrow 
  183.  
  184.       Start_Arrow, 
  185.       --  the link has an arrow at its beginning 
  186.  
  187.       End_Arrow, 
  188.       --  the link has an arrow at the end 
  189.  
  190.       Both_Arrow 
  191.       --  the link has an arrow on both sides 
  192.      ); 
  193.    --  Indicate whether the links have an arrow or not. 
  194.  
  195.    ----------------------- 
  196.    -- Creating a canvas -- 
  197.    ----------------------- 
  198.  
  199.    procedure Gtk_New 
  200.      (Canvas : out Interactive_Canvas; Auto_Layout : Boolean := True); 
  201.    --  Create a new empty Canvas. 
  202.    --  If Auto_Layout is True, then the items are automatically positioned as 
  203.    --  they are put in the canvas, if no coordinates are specified. 
  204.  
  205.    procedure Initialize 
  206.      (Canvas      : access Interactive_Canvas_Record'Class; 
  207.       Auto_Layout : Boolean := True); 
  208.    --  Internal function used to initialize the canvas. 
  209.  
  210.    procedure Configure 
  211.      (Canvas : access Interactive_Canvas_Record; 
  212.       Grid_Size        : Glib.Guint := Default_Grid_Size; 
  213.       Annotation_Font  : Pango.Font.Pango_Font_Description := 
  214.                            Pango.Font.From_String (Default_Annotation_Font); 
  215.       Arc_Link_Offset  : Glib.Gint := Default_Arc_Link_Offset; 
  216.       Arrow_Angle      : Glib.Gint := Default_Arrow_Angle; 
  217.       Arrow_Length     : Glib.Gint := Default_Arrow_Length; 
  218.       Motion_Threshold : Glib.Gint := Default_Motion_Threshold); 
  219.    --  Change the parameters for the canvas. 
  220.    --  A Grid_Size of 0 means than no grid should be drawn in the background of 
  221.    --  canvas. Note that in that case you can never activate Align_On_Grid. 
  222.    --  This setting doesn't apply if you have redefined Draw_Background, which 
  223.    --  may not draw a grid. 
  224.  
  225.    function Get_Vadj 
  226.      (Canvas : access Interactive_Canvas_Record'Class) 
  227.       return Gtk.Adjustment.Gtk_Adjustment; 
  228.    --  Return the vertical adjustment associated with Canvas 
  229.  
  230.    function Get_Hadj 
  231.      (Canvas : access Interactive_Canvas_Record'Class) 
  232.       return Gtk.Adjustment.Gtk_Adjustment; 
  233.    --  Return the horizontal adjustment associated with Canvas 
  234.  
  235.    procedure Draw_Area 
  236.      (Canvas : access Interactive_Canvas_Record'Class; 
  237.       Rect   : Gdk.Rectangle.Gdk_Rectangle); 
  238.    --  Draw in Canvas the specified area. 
  239.  
  240.    procedure Draw_Background 
  241.      (Canvas      : access Interactive_Canvas_Record; 
  242.       Screen_Rect : Gdk.Rectangle.Gdk_Rectangle); 
  243.    --  Draw the background of the canvas. This procedure should be overriden if 
  244.    --  you want to draw something else on the background. It must first clear 
  245.    --  the area on the screen. 
  246.    -- 
  247.    --  Screen_Rect is the rectangle on the screen that needs to be 
  248.    --  refreshed. These are canvas coordinates, therefore you must take into 
  249.    --  account the current zoom level while drawing. 
  250.    -- 
  251.    --  The default implementation draws a grid. 
  252.    -- 
  253.    --  An example implementation that draws a background image is shown at the 
  254.    --  end of this file. 
  255.  
  256.    procedure Draw_Grid 
  257.      (Canvas      : access Interactive_Canvas_Record; 
  258.       GC          : Gdk.GC.Gdk_GC; 
  259.       Screen_Rect : Gdk.Rectangle.Gdk_Rectangle); 
  260.    --  Helper function that can be called from Draw_Background. It cannot be 
  261.    --  used directly as Draw_Background, since it doesn't clear the area first. 
  262.  
  263.    procedure Set_Orthogonal_Links 
  264.      (Canvas : access Interactive_Canvas_Record; 
  265.       Orthogonal : Boolean); 
  266.    --  If Orthogonal is True, then all the links will be drawn only with 
  267.    --  vertical and horizontal lines. This is not applied for the second or 
  268.    --  more link between two items. 
  269.  
  270.    function Get_Orthogonal_Links 
  271.      (Canvas : access Interactive_Canvas_Record) return Boolean; 
  272.    --  Return True if the links are only drawn horizontally and vertically. 
  273.  
  274.    procedure Align_On_Grid 
  275.      (Canvas : access Interactive_Canvas_Record; 
  276.       Align  : Boolean := True); 
  277.    --  Choose whether the items should be aligned on the grid when moved. 
  278.    --  Existing items are not moved even if you set this parameter to True, 
  279.    --  this will only take effect the next time the items are moved. 
  280.  
  281.    function Get_Align_On_Grid 
  282.      (Canvas : access Interactive_Canvas_Record) return Boolean; 
  283.    --  Return True if items are currently aligned on grid. 
  284.  
  285.    procedure Move_To 
  286.      (Canvas : access Interactive_Canvas_Record; 
  287.       Item   : access Canvas_Item_Record'Class; 
  288.       X, Y   : Glib.Gint := Glib.Gint'First); 
  289.    --  Move the item in the canvas, to world coordinates (X, Y). 
  290.    --  Item is assumed to be already in the canvas. 
  291.    --  If you leave both coordinates X and Y to their default value, then the 
  292.    --  item's location will be automatically computed when you layout the 
  293.    --  canvas (it is your responsability to call Layout). 
  294.  
  295.    procedure Set_Items 
  296.      (Canvas : access Interactive_Canvas_Record; 
  297.       Items  : Glib.Graphs.Graph); 
  298.    --  Set the items and links to display in the canvas from Items. 
  299.    --  All items previously in the canvas are removed, and replaced by the 
  300.    --  vertices in Items. 
  301.    --  Note that the vertices in Items must be in Canvas_Item_Record'Class, and 
  302.    --  the links must be in Canvas_Link_Record'Class. 
  303.    --  If you do not have an automatic layout set up in Canvas, you need to set 
  304.    --  the coordinates of all the vertices by calling Move_To separately. 
  305.    -- 
  306.    --  You mustn't destroy items yourself, this is done automatically when the 
  307.    --  canvas is destroyed. 
  308.  
  309.    procedure Put 
  310.      (Canvas : access Interactive_Canvas_Record; 
  311.       Item   : access Canvas_Item_Record'Class; 
  312.       X, Y   : Glib.Gint := Glib.Gint'First); 
  313.    --  Add a new item to the canvas, at world coordinates (X, Y). 
  314.    --  The item is added at a specific location. 
  315.    --  If you leave both X and Y to their default value, the item's location 
  316.    --  will be computed automatically when you call Layout on the canvas, 
  317.    --  unless Auto_Layout has been set, in which case the position will be 
  318.    --  computed immediately. 
  319.  
  320.    function Item_At_Coordinates 
  321.      (Canvas : access Interactive_Canvas_Record; 
  322.       X, Y : Glib.Gint) return Canvas_Item; 
  323.    --  Return the item at world coordinates (X, Y) which is on top of all 
  324.    --  others. 
  325.    --  null is returned if there is no such item. 
  326.  
  327.    function Item_At_Coordinates 
  328.      (Canvas : access Interactive_Canvas_Record; Event : Gdk.Event.Gdk_Event) 
  329.       return Canvas_Item; 
  330.    --  Same as above, but using the canvas coordinates of the event, taking 
  331.    --  into account the current zoom level and current scrolling 
  332.  
  333.    procedure Item_At_Coordinates 
  334.      (Canvas : access Interactive_Canvas_Record; 
  335.       Event  : Gdk.Event.Gdk_Event; 
  336.       Item   : out Canvas_Item; 
  337.       X, Y   : out Glib.Gint); 
  338.    --  Same as above, but also returns the coordinates (X, Y) within the item. 
  339.    --  The coordinates are not set if Item is null on exit. 
  340.  
  341.    procedure Clear (Canvas : access Interactive_Canvas_Record); 
  342.    --  Remove all items from the canvas 
  343.  
  344.    procedure Remove 
  345.      (Canvas : access Interactive_Canvas_Record; 
  346.       Item   : access Canvas_Item_Record'Class); 
  347.    --  Remove an item and all the links to and from it from the canvas. 
  348.    --  The item itself is not freed, but the links are. 
  349.    --  Nothing is done if the item is not part of the canvas. 
  350.  
  351.    procedure Item_Updated 
  352.      (Canvas : access Interactive_Canvas_Record; 
  353.       Item   : access Canvas_Item_Record'Class); 
  354.    --  This should be called when Item has changed the contents of its 
  355.    --  pixmap, and thus the Canvas should be updated. 
  356.  
  357.    procedure Refresh_Canvas (Canvas : access Interactive_Canvas_Record); 
  358.    --  Redraw the whole canvas (both in the double buffer and on the screen). 
  359.  
  360.    procedure Raise_Item 
  361.      (Canvas : access Interactive_Canvas_Record; 
  362.       Item   : access Canvas_Item_Record'Class); 
  363.    --  Raise the item so that it is displayed on top of all the others 
  364.    --  The canvas is refreshed as needed to reflect the change. 
  365.    --  Nothing happens if Item is not part of the canvas. 
  366.  
  367.    procedure Lower_Item 
  368.      (Canvas : access Interactive_Canvas_Record; 
  369.       Item   : access Canvas_Item_Record'Class); 
  370.    --  Lower the item so that it is displayed below all the others. 
  371.    --  The canvas is refreshed as needed to reflect the change. 
  372.    --  Nothing happens if Item is not part of the canvas. 
  373.  
  374.    function Is_On_Top 
  375.      (Canvas : access Interactive_Canvas_Record; 
  376.       Item   : access Canvas_Item_Record'Class) return Boolean; 
  377.    --  Return True if Item is displayed on top of all the others in the canvas. 
  378.  
  379.    procedure Show_Item 
  380.      (Canvas : access Interactive_Canvas_Record; 
  381.       Item   : access Canvas_Item_Record'Class); 
  382.    --  Scroll the canvas so that Item is visible. Nothing is done if the item 
  383.    --  is already visible 
  384.  
  385.    procedure Align_Item 
  386.      (Canvas  : access Interactive_Canvas_Record; 
  387.       Item    : access Canvas_Item_Record'Class; 
  388.       X_Align : Float := 0.5; 
  389.       Y_Align : Float := 0.5); 
  390.    --  Scroll the canvas so that the Item appears at the given location in the 
  391.    --  canvas. If X_Align is 0.0, the item is align on the left. With 0.5, it 
  392.    --  is centered horizontally. If 1.0, it is aligned on the right. 
  393.  
  394.    function Get_Arrow_Angle 
  395.      (Canvas : access Interactive_Canvas_Record'Class) return Float; 
  396.    --  Return the angle of arrows in the canvas. 
  397.  
  398.    function Get_Arrow_Length 
  399.      (Canvas : access Interactive_Canvas_Record'Class) return Glib.Gint; 
  400.    --  Return the length of arrows in the canvas. 
  401.  
  402.    -------------------------- 
  403.    -- Iterating over items -- 
  404.    -------------------------- 
  405.  
  406.    type Item_Processor is access function 
  407.      (Canvas : access Interactive_Canvas_Record'Class; 
  408.       Item   : access Canvas_Item_Record'Class) return Boolean; 
  409.  
  410.    procedure For_Each_Item 
  411.      (Canvas            : access Interactive_Canvas_Record; 
  412.       Execute           : Item_Processor; 
  413.       Linked_From_Or_To : Canvas_Item := null); 
  414.    --  Execute an action on each of the items contained in the canvas. 
  415.    --  If Execute returns False, we stop traversing the list of children. 
  416.    --  It is safe to remove the items in Item_Processor. 
  417.    -- 
  418.    --  If Linked_From_Or_To is not null, then only the items linked to this one 
  419.    --  will be processed. It is possible that a given item will be returned 
  420.    --  twice, if it is both linked to and from the item. 
  421.  
  422.    type Item_Iterator is private; 
  423.  
  424.    function Start 
  425.      (Canvas            : access Interactive_Canvas_Record; 
  426.       Linked_From_Or_To : Canvas_Item := null; 
  427.       Selected_Only     : Boolean := False) return Item_Iterator; 
  428.    --  Return the first item in the canvas. 
  429.    --  The same restriction as above applies if Linked_From_Or_To is not null. 
  430.  
  431.    procedure Next (Iter : in out Item_Iterator); 
  432.    function Next (Iter : Item_Iterator) return Item_Iterator; 
  433.    --  Move the iterator to the next item. 
  434.    --  All items will eventually be returned if you do not add new items during 
  435.    --  the iteration and none are removed. However, it is safe to remove items 
  436.    --  at any time, except the current item 
  437.  
  438.    function Get (Iter : Item_Iterator) return Canvas_Item; 
  439.    --  Return the item pointed to by the iterator. 
  440.    --  null is returned when there are no more item in the canvas. 
  441.  
  442.    function Is_Linked_From (Iter : Item_Iterator) return Boolean; 
  443.    --  Return True if there is a link from: 
  444.    --     Get (Iter) -> Linked_From_Or_To 
  445.    --  Linked_From_Or_To is the item passed to Start. False is returned if this 
  446.    --  item was null. 
  447.  
  448.    ------------- 
  449.    -- Zooming -- 
  450.    ------------- 
  451.  
  452.    procedure Zoom 
  453.      (Canvas  : access Interactive_Canvas_Record; 
  454.       Percent : Glib.Guint := 100; 
  455.       Steps   : Glib.Guint := 1); 
  456.    --  Zoom in or out in the canvas. 
  457.    -- 
  458.    --  Steps is the number of successive zooms that will be done to provide 
  459.    --  smooth scrolling. 
  460.    -- 
  461.    --  Note that one possible use for this function is to refresh the canvas 
  462.    --  and emit the "zoomed" signal, which might redraw all the items. This can 
  463.    --  be accomplished by keeping the default 100 value for Percent. 
  464.  
  465.    function Get_Zoom 
  466.      (Canvas : access Interactive_Canvas_Record) return Glib.Guint; 
  467.    --  Return the current zoom level 
  468.  
  469.    function To_Canvas_Coordinates 
  470.      (Canvas : access Interactive_Canvas_Record'Class; 
  471.       X      : Glib.Gint) return Glib.Gint; 
  472.    --  Scale the scalar X depending on the zoom level (map from world 
  473.    --  lengths to canvas lengths). 
  474.    --  Substract the coordinates of the top-left corner if you are converting 
  475.    --  coordinates instead of lengths. 
  476.  
  477.    function Top_World_Coordinates 
  478.      (Canvas : access Interactive_Canvas_Record'Class) return Glib.Gint; 
  479.    --  Return the world coordinates for the y=0 canvas coordinates (ie for the 
  480.    --  upper-left corner of the screen). 
  481.  
  482.    function Left_World_Coordinates 
  483.      (Canvas : access Interactive_Canvas_Record'Class) return Glib.Gint; 
  484.    --  Return the world coordinates for the x=0 canvas coordinates (ie for the 
  485.    --  upper-left corner of the screen). 
  486.  
  487.    function To_World_Coordinates 
  488.      (Canvas : access Interactive_Canvas_Record'Class; 
  489.       X      : Glib.Gint) return Glib.Gint; 
  490.    --  Scale the scalar X depending by the zoom level (map from canvas 
  491.    --  coordinates to world coordinates) 
  492.  
  493.    procedure Get_World_Coordinates 
  494.      (Canvas : access Interactive_Canvas_Record'Class; 
  495.       X, Y   : out Glib.Gint; 
  496.       Width  : out Glib.Gint; 
  497.       Height : out Glib.Gint); 
  498.    --  Return the world coordinates of Canvas. 
  499.  
  500.    --------------------- 
  501.    -- Layout of items -- 
  502.    --------------------- 
  503.  
  504.    type Layout_Algorithm is access procedure 
  505.      (Canvas          : access Interactive_Canvas_Record'Class; 
  506.       Graph           : Glib.Graphs.Graph; 
  507.       Force           : Boolean; 
  508.       Vertical_Layout : Boolean); 
  509.    --  A general layout algorithm. It should compute the position of all the 
  510.    --  vertices of the graph, and set them directly in the graph itself. 
  511.    --  Note: all the vertices in the graph are of type Canvas_Item_Record'Class 
  512.    --  and you should use that to set the coordinates through a call to 
  513.    --  Move_To. 
  514.    -- 
  515.    --  Algorithms are encouraged to preserve the current layout as much as 
  516.    --  possible, taking into account items that have been moved manually by 
  517.    --  the user, so that the latter can preserver his mental map of the graph. 
  518.    --  However, if Force is set to True, then the whole layout should be 
  519.    --  recomputed as if all items had just been inserted. 
  520.    -- 
  521.    --  Items that have just been inserted in the graph, but whose position has 
  522.    --  never been computed, are set at coordinates (Gint'First, Gint'First). 
  523.    --  Check the result of Get_Coord. 
  524.    -- 
  525.    --  This function doesn't need to align items, this is done automatically by 
  526.    --  the canvas if necessary. 
  527.  
  528.    procedure Set_Layout_Algorithm 
  529.      (Canvas    : access Interactive_Canvas_Record; 
  530.       Algorithm : Layout_Algorithm); 
  531.    --  Set the layout algorithm to use to compute the position of the items. 
  532.    --  Algorithm mustn't be null. 
  533.  
  534.    procedure Default_Layout_Algorithm 
  535.      (Canvas          : access Interactive_Canvas_Record'Class; 
  536.       Graph           : Glib.Graphs.Graph; 
  537.       Force           : Boolean; 
  538.       Vertical_Layout : Boolean); 
  539.    --  The default algorithm used in the canvas. 
  540.    --  Basically, items are put next to each other, unless there is a link 
  541.    --  between two items. In that case, the second item is put below the first, 
  542.    --  as space allows. 
  543.  
  544.    procedure Set_Auto_Layout 
  545.      (Canvas      : access Interactive_Canvas_Record; 
  546.       Auto_Layout : Boolean); 
  547.    --  If Auto_Layout is true, then every time an item is inserted in the 
  548.    --  canvas, the layout algorithm is called. If set to False, it is the 
  549.    --  responsability of the caller to call Layout below to force a 
  550.    --  recomputation of the layout, preferably after inserting a number of 
  551.    --  items. 
  552.  
  553.    procedure Set_Layout_Orientation 
  554.      (Canvas          : access Interactive_Canvas_Record; 
  555.       Vertical_Layout : Boolean := False); 
  556.    --  Specify the layout orientation to use for this canvas. The setting is 
  557.    --  passed as a parameter to the layout algorithm 
  558.  
  559.    procedure Layout 
  560.      (Canvas : access Interactive_Canvas_Record; 
  561.       Force  : Boolean := False); 
  562.    --  Recompute the layout of the canvas. 
  563.    --  Force can be used to control the layout algorithm, as described above 
  564.    --  for Layout_Algorithm. 
  565.  
  566.    ----------- 
  567.    -- Links -- 
  568.    ----------- 
  569.  
  570.    procedure Configure 
  571.      (Link  : access Canvas_Link_Record; 
  572.       Arrow : Arrow_Type := End_Arrow; 
  573.       Descr : Glib.UTF8_String := ""); 
  574.    --  Configure a link. 
  575.    --  The link is an oriented bound between two items on the canvas. 
  576.    --  If Descr is not the empty string, it will be displayed in the middle 
  577.    --  of the link, and should indicate what the link means. 
  578.    --  Arrow indicates whether some arrows should be printed as well. 
  579.  
  580.    function Get_Descr 
  581.      (Link : access Canvas_Link_Record) return Glib.UTF8_String; 
  582.    --  Return the description for the link, or "" if there is none 
  583.  
  584.    function Get_Arrow_Type 
  585.      (Link : access Canvas_Link_Record) return Arrow_Type; 
  586.    --  Return the location of the arrows on Link 
  587.  
  588.    procedure Set_Src_Pos 
  589.      (Link : access Canvas_Link_Record; X_Pos, Y_Pos : Glib.Gfloat := 0.5); 
  590.    --  Set the position of the link's attachment in its source item. 
  591.    --  X_Pos and Y_Pos should be given between 0.0 and 1.0 (from left to right 
  592.    --  or top to bottom).. 
  593.    --  By default, all links are considered to be attached to the center of 
  594.    --  items. However, in some cases it is more convenient to attach it to a 
  595.    --  specific part of the item. For instance, you can force a link to always 
  596.    --  start from the top of the item by setting Y_Pos to 0.0. 
  597.  
  598.    procedure Set_Dest_Pos 
  599.      (Link : access Canvas_Link_Record; X_Pos, Y_Pos : Glib.Gfloat := 0.5); 
  600.    --  Same as Set_Src_Pos for the destination item 
  601.  
  602.    procedure Get_Src_Pos 
  603.      (Link : access Canvas_Link_Record; X, Y : out Glib.Gfloat); 
  604.    --  Return the attachment position of the link along its source item 
  605.  
  606.    procedure Get_Dest_Pos 
  607.      (Link : access Canvas_Link_Record; X, Y : out Glib.Gfloat); 
  608.    --  Return the attachment position of the link along its destination item 
  609.  
  610.    function Has_Link 
  611.      (Canvas   : access Interactive_Canvas_Record; 
  612.       From, To : access Canvas_Item_Record'Class; 
  613.       Name     : Glib.UTF8_String := "") return Boolean; 
  614.    --  Test whether there is a link from From to To, with the same name. 
  615.    --  If Name is the empty string "", then no check is done on the name, 
  616.    --  and True if returned if there is any link between the two items. 
  617.  
  618.    procedure Add_Link 
  619.      (Canvas : access Interactive_Canvas_Record; 
  620.       Link   : access Canvas_Link_Record'Class; 
  621.       Src    : access Canvas_Item_Record'Class; 
  622.       Dest   : access Canvas_Item_Record'Class; 
  623.       Arrow  : Arrow_Type := End_Arrow; 
  624.       Descr  : Glib.UTF8_String := ""); 
  625.    --  Add Link in the canvas. This connects the two items Src and Dest. 
  626.    --  Simpler procedure to add a standard link. 
  627.    --  This takes care of memory allocation, as well as adding the link to 
  628.    --  the canvas. 
  629.  
  630.    procedure Remove_Link 
  631.      (Canvas : access Interactive_Canvas_Record; 
  632.       Link   : access Canvas_Link_Record'Class); 
  633.    --  Remove a link from the canvas. 
  634.    --  It also destroys the link itself, and free the memory allocated to it. 
  635.    --  Nothing is done if Link does not belong to canvas. 
  636.  
  637.    type Link_Processor is access function 
  638.      (Canvas : access Interactive_Canvas_Record'Class; 
  639.       Link   : access Canvas_Link_Record'Class) return Boolean; 
  640.  
  641.    procedure For_Each_Link 
  642.      (Canvas   : access Interactive_Canvas_Record; 
  643.       Execute  : Link_Processor; 
  644.       From, To : Canvas_Item := null); 
  645.    --  Execute an action on each of the links contained in the canvas. 
  646.    --  If Execute returns False, we stop traversing the list of links. 
  647.    --  It is safe to remove the link from the list in Link_Processor. 
  648.    -- 
  649.    --  (From, To) can be used to limit what links are looked for. 
  650.    -- 
  651.    --  ??? Would be nicer to give direct access to the Graph iterators 
  652.  
  653.    procedure Destroy (Link : in out Canvas_Link_Record); 
  654.    --  Method called every time a link is destroyed. You should override this 
  655.    --  if you define your own link types. 
  656.    --  Note that the link might already have been removed from the canvas 
  657.    --  when this subprogram is called. 
  658.    --  This shouldn't free the link itself, only its fields. 
  659.  
  660.    ------------------- 
  661.    -- Drawing links -- 
  662.    ------------------- 
  663.    --  Drawing of links can be controlled at several levels: 
  664.    --    - Redefining Update_Links gives control at the canvas level. This can 
  665.    --      be used to implement routing algorithms for the links where the 
  666.    --      routes must be computed before any link is actually drawn (otherwise 
  667.    --      it is better to redefine Draw_Link). It can also be used to control 
  668.    --      in what order the links should be drawn. 
  669.    --    - Redefining Draw_Link gives the opportunity to draw links any way you 
  670.    --      need (several bends, ...). It can be used to control the routing of 
  671.    --      this specific link, for routing algorithms that only rely on the 
  672.    --      items layout and not on other links. Otherwise see Update_Links. 
  673.    --    - Redefining Draw_Straight_Line if slightly lower-level. This is 
  674.    --      called by the default Draw_Link procedure, once the ends of the 
  675.    --      links have been computed. 
  676.  
  677.    procedure Update_Links 
  678.      (Canvas         : access Interactive_Canvas_Record; 
  679.       GC             : Gdk.GC.Gdk_GC; 
  680.       Invert_Mode    : Boolean; 
  681.       From_Selection : Boolean); 
  682.    --  Redraw all the links in the canvas, after the items have been laid out. 
  683.    --  GC is a default graphic context that can be used for drawing. However, 
  684.    --  any other graphic context will do. If Invert_Mode is true, this graphic 
  685.    --  context must draw in xor mode. 
  686.    --  If From_Selection is true, then only the links to or from one of the 
  687.    --  selected items need to be drawn. 
  688.  
  689.    procedure Draw_Link 
  690.      (Canvas      : access Interactive_Canvas_Record'Class; 
  691.       Link        : access Canvas_Link_Record; 
  692.       Invert_Mode : Boolean; 
  693.       GC          : Gdk.GC.Gdk_GC; 
  694.       Edge_Number : Glib.Gint; 
  695.       Show_Annotation : Boolean := True); 
  696.    --  Redraw the link on the canvas. 
  697.    --  Note that this is a primitive procedure of Link, not of Canvas, and thus 
  698.    --  can easily be overrided for specific links. The default version draws 
  699.    --  either straight or arc links (the latter when there are multiple links 
  700.    --  between two given items). 
  701.    --  This function shouldn't be called if one of the two ends of the link is 
  702.    --  invisible. 
  703.    -- 
  704.    --  The link should be drawn directly in Get_Window (Canvas). 
  705.    -- 
  706.    --  GC is a possible graphic context that could be used to draw the 
  707.    --  link. You shouldn't destroy it or modify its attributes. However, you 
  708.    --  can use any other graphic context specific to your application, for 
  709.    --  instance if you want to draw the link in various colors or shapes. The 
  710.    --  graphic context you use must be in Invert mode (see Gdk.GC.Set_Function) 
  711.    --  if and only if Invert_Mode is true, so that when items are moved on the 
  712.    --  canvas, the links properly follow the items they are attached to. 
  713.    --  This graphic context is only used to draw links, so you don't need to 
  714.    --  restore it on exit if your Draw_Link function always sets it at the 
  715.    --  beginning. 
  716.    -- 
  717.    --  Edge_Number indicates the index of link in the list of links that join 
  718.    --  the same source to the same destination. It should be used so that two 
  719.    --  links do not overlap (for instance, the default is to draw the first 
  720.    --  link straight, and the others as arcs). 
  721.  
  722.    type Item_Side is (East, West, North, South); 
  723.    --  Each side of an item, along its rectangle bounding box 
  724.  
  725.    procedure Clip_Line 
  726.      (Src   : access Canvas_Item_Record; 
  727.       Canvas : access Interactive_Canvas_Record'Class; 
  728.       To_X  : Glib.Gint; 
  729.       To_Y  : Glib.Gint; 
  730.       X_Pos : Glib.Gfloat; 
  731.       Y_Pos : Glib.Gfloat; 
  732.       Side  : out Item_Side; 
  733.       X_Out : out Glib.Gint; 
  734.       Y_Out : out Glib.Gint); 
  735.    --  Clip the line that goes from Src at pos (X_Pos, Y_Pos) to (To_X, To_Y) 
  736.    --  in world coordinates. 
  737.    --  The intersection between that line and the border of Rect is returned 
  738.    --  in (X_Out, Y_Out). The result should be in world coordinates. 
  739.    --  X_Pos and Y_Pos have the same meaning as Src_X_Pos and Src_Y_Pos in the 
  740.    --  link record. 
  741.    --  This procedure is called when computing the position for the links 
  742.    --  within the default Draw_Link procedure. The default implementation only 
  743.    --  works with rectangular items. The computed coordinates are then passed 
  744.    --  on directly to Draw_Straight_Line. 
  745.  
  746.    procedure Draw_Straight_Line 
  747.      (Link      : access Canvas_Link_Record; 
  748.       Window    : Gdk.Window.Gdk_Window; 
  749.       GC        : Gdk.GC.Gdk_GC; 
  750.       Src_Side  : Item_Side; 
  751.       X1, Y1    : Glib.Gint; 
  752.       Dest_Side : Item_Side; 
  753.       X2, Y2    : Glib.Gint); 
  754.    --  Draw a straight link between two points. This could be overriden if you 
  755.    --  need to draw an something along the link. 
  756.    --  The links goes from (Src, X1, Y1) to (Dest, X2, Y2), in canvas 
  757.    --  coordinates. The coordinates have already been clipped so that they do 
  758.    --  not override the item. 
  759.  
  760.    --------------- 
  761.    -- Selection -- 
  762.    --------------- 
  763.  
  764.    procedure Clear_Selection (Canvas : access Interactive_Canvas_Record); 
  765.    --  Clear the list of currently selected items. 
  766.  
  767.    procedure Add_To_Selection 
  768.      (Canvas : access Interactive_Canvas_Record; 
  769.       Item   : access Canvas_Item_Record'Class); 
  770.    --  Add Item to the selection.  This is only meaningful during a drag 
  771.    --  operation (ie during a button press and the matching button 
  772.    --  release). Item will be moved at the same time that the selection is 
  773.    --  moved. 
  774.    --  Item is not added again if it is already in the selection. 
  775.    --  This function can be called from the Button_Click subprogram to force 
  776.    --  moving items. 
  777.    --  This emits the "item_selected" signal. 
  778.  
  779.    procedure Remove_From_Selection 
  780.      (Canvas : access Interactive_Canvas_Record; 
  781.       Item   : access Canvas_Item_Record'Class); 
  782.    --  Remove Item from the selection. 
  783.    --  This emits the "item_unselected" signal. 
  784.  
  785.    procedure Select_All (Canvas : access Interactive_Canvas_Record); 
  786.    --  Select all the Item in the canvas. 
  787.  
  788.    function Is_Selected 
  789.      (Canvas : access Interactive_Canvas_Record; 
  790.       Item   : access Canvas_Item_Record'Class) return Boolean; 
  791.    --  Return True if the item is currently selected 
  792.  
  793.    ------------------------ 
  794.    -- Items manipulation -- 
  795.    ------------------------ 
  796.  
  797.    procedure Selected 
  798.      (Item        : access Canvas_Item_Record; 
  799.       Canvas      : access Interactive_Canvas_Record'Class; 
  800.       Is_Selected : Boolean); 
  801.    --  Called when the item is selected or unselected. 
  802.    --  The default is to do nothing. 
  803.  
  804.    function Point_In_Item 
  805.      (Item : access Canvas_Item_Record; 
  806.       X, Y : Glib.Gint) return Boolean; 
  807.    --  This function should return True if (X, Y) is inside the item. X and Y 
  808.    --  are in world coordinates. 
  809.    --  This function is meant to be overriden for non-rectangular items, since 
  810.    --  the default behavior works for rectangular items. 
  811.    --  This function is never called for invisible items 
  812.  
  813.    procedure Set_Screen_Size 
  814.      (Item   : access Canvas_Item_Record; 
  815.       Width  : Glib.Gint; 
  816.       Height : Glib.Gint); 
  817.    --  Set the size of bounding box for the item in world coordinates. 
  818.    --  The item itself needn't occupy the whole area of this bounding box, 
  819.    --  see Point_In_Item. 
  820.    --  You need to redraw the item, and call Item_Updated to force the canvas 
  821.    --  to refresh the screen. 
  822.  
  823.    procedure Draw 
  824.      (Item         : access Canvas_Item_Record; 
  825.       Canvas       : access Interactive_Canvas_Record'Class; 
  826.       GC           : Gdk.GC.Gdk_GC; 
  827.       Xdest, Ydest : Glib.Gint) is abstract; 
  828.    --  This subprogram, that must be overridden, should draw the item on 
  829.    --  Get_Pixmap (Canvas), at the specific location (Xdest, Ydest). The item 
  830.    --  must also be drawn at the appropriate zoom level. To do so, all lengths 
  831.    --  must be multiplied by the current zoom level. 
  832.    --  If you need to change the contents of the item, you should call 
  833.    --  Item_Updated after having done the drawing. 
  834.  
  835.    procedure Destroy (Item : in out Canvas_Item_Record); 
  836.    --  Free the memory occupied by the item (not the item itself). You should 
  837.    --  override this function if you define your own widget type, but always 
  838.    --  call the parent's Destroy subprogram. 
  839.  
  840.    procedure On_Button_Click 
  841.      (Item  : access Canvas_Item_Record; 
  842.       Event : Gdk.Event.Gdk_Event_Button); 
  843.    --  Function called whenever the item was clicked on. 
  844.    --  Note that this function is not called when the item is moved, and thus 
  845.    --  is only called when the click was short. 
  846.    --  The coordinates (X, Y) in the Event are relative to the top-left corner 
  847.    --  of Item. 
  848.  
  849.    function Get_Coord 
  850.      (Item : access Canvas_Item_Record) return Gdk.Rectangle.Gdk_Rectangle; 
  851.    --  Return the coordinates and size of the bounding box for item, in world 
  852.    --  coordinates. 
  853.    --  If the item has never been resized, it initially has a width and height 
  854.    --  of 1. 
  855.  
  856.    procedure Set_Visibility 
  857.      (Item    : access Canvas_Item_Record; 
  858.       Visible : Boolean); 
  859.    --  Set the visibility status of the item. An invisible item will not be 
  860.    --  visible on the screen, and will not take part in the computation of the 
  861.    --  the scrollbars for the canvas. 
  862.    --  The canvas is not refreshed (this is your responsibility to do it after 
  863.    --  you have finished doing all the modifications). 
  864.  
  865.    function Is_Visible (Item : access Canvas_Item_Record) return Boolean; 
  866.    --  Return True if the item is currently visible 
  867.  
  868.    function Is_From_Auto_Layout 
  869.      (Item : access Canvas_Item_Record) return Boolean; 
  870.    --  Return True if the current location of the item is the result from the 
  871.    --  auto layout algorithm. 
  872.    --  False is returned if the item was moved manually by the user. 
  873.  
  874.    -------------------- 
  875.    -- Buffered items -- 
  876.    -------------------- 
  877.  
  878.    type Buffered_Item_Record is new Canvas_Item_Record with private; 
  879.    type Buffered_Item is access all Buffered_Item_Record'Class; 
  880.    --  A widget that has a double-buffer associated. You should use this one 
  881.    --  when drawing items can take a long time, or you do not want to handle 
  882.    --  the zoom yourself. 
  883.    --  You only need to update the contents of the double pixmap when the 
  884.    --  contents of the item changes, since all the drawing and zooming is 
  885.    --  taken care of automatically. Once the drawing is done, call Item_Updated 
  886.    --  to force the canvas to refresh the screen. 
  887.    --  This buffered_item is meant to handle rectangular items. However, it can 
  888.    --  be used for polygonal items by overriding Draw. The new version should 
  889.    --  set the clip mask for the GC, then call Draw for the buffered item, and 
  890.    --  finally reset the clip mask. The clip mask must take into account the 
  891.    --  current zoom level. 
  892.  
  893.    function Pixmap (Item : access Buffered_Item_Record) 
  894.       return Gdk.Pixmap.Gdk_Pixmap; 
  895.    --  Return the double-buffer. 
  896.    --  All the drawing on this pixmap must be done at zoom level 100%. 
  897.  
  898.    ------------- 
  899.    -- Signals -- 
  900.    ------------- 
  901.  
  902.    --  <signals> 
  903.    --  The following new signals are defined for this widget: 
  904.    -- 
  905.    --  - "background_click" 
  906.    --  procedure Handler (Canvas : access Interactive_Canvas_Record'Class; 
  907.    --                     Event  : Gdk.Event.Gdk_Event); 
  908.    -- 
  909.    --  Called every time the user clicks in the background (ie not on an item, 
  910.    --  or On_Button_Click would be called). 
  911.    --  This is called both on Button_Release and Button_Press events. 
  912.    --  The coordinates (X, Y) in the Event are relative to the top-left corner 
  913.    --  of Canvas. 
  914.    -- 
  915.    --  - "item_selected" 
  916.    --  procedure Handler (Canvas : access Interactive_Canvas_Record'Class; 
  917.    --                     Item   : Canvas_Item); 
  918.    -- 
  919.    --  Emitted when the user has clicked on an item to select it, ie before any 
  920.    --  drag even has occured. This is a good time to add other items to the 
  921.    --  selection if you need. At thee same time, the primitive operation 
  922.    --  Selected is called for the item. 
  923.    -- 
  924.    --  - "item_unselected" 
  925.    --  procedure Handler (Canvas : access Interactive_Canvas_Record'Class; 
  926.    --                     Item   : Canvas_Item); 
  927.    -- 
  928.    --  Emitted when the Item was unselected. At the same time, the primitive 
  929.    --  operation Selected is called for the item. 
  930.    -- 
  931.    --  - "item_moved" 
  932.    --  procedure Handler (Canvas : access Interactive_Canvas_Record'Class; 
  933.    --                     Item   : Canvas_Item); 
  934.    -- 
  935.    --  Emitted when Item has been moved. New coordinates have been assigned to 
  936.    --  Item. However, the canvas hasn't been refreshed yet. This signal might 
  937.    --  be called multiple time when the user finishes a drag action, in case 
  938.    --  there were several selected items. 
  939.    -- 
  940.    --  - "zoomed" 
  941.    --  procedure Handler (Canvas : access Interactive_Canvas_Record'Class); 
  942.    -- 
  943.    --  Emitted when the canvas has been zoomed in or out. You do not need to 
  944.    --  redraw the items yourself, since this will be handled by calls to Draw 
  945.    -- 
  946.    --  - "set_scroll_adjustments" 
  947.    --  procedure Handler (Canvas : access Interactive_Canvas_Record'Class); 
  948.    -- 
  949.    --  Emitted when the canvas has scrolled. 
  950.    -- 
  951.    --  </signals> 
  952.  
  953.    Signal_Background_Click       : constant Glib.Signal_Name := 
  954.                                      "background_click"; 
  955.    Signal_Item_Selected          : constant Glib.Signal_Name := 
  956.                                      "item_selected"; 
  957.    Signal_Item_Unselected        : constant Glib.Signal_Name := 
  958.                                      "item_unselected"; 
  959.    Signal_Item_Moved             : constant Glib.Signal_Name := 
  960.                                      "item_moved"; 
  961.    Signal_Zoomed                 : constant Glib.Signal_Name := 
  962.                                      "zoomed"; 
  963.    Signal_Set_Scroll_Adjustments : constant Glib.Signal_Name := 
  964.                                      "set_scroll_adjustments"; 
  965.  
  966. private 
  967.  
  968.    type String_Access is access Glib.UTF8_String; 
  969.  
  970.    type Canvas_Link_Record is new Glib.Graphs.Edge with record 
  971.       Descr  : String_Access; 
  972.       Arrow  : Arrow_Type := End_Arrow; 
  973.  
  974.       Pixbuf : Gdk.Pixbuf.Gdk_Pixbuf := Gdk.Pixbuf.Null_Pixbuf; 
  975.       --  The pixmap in which the text is displayed. This is required to 
  976.       --  properly implement zooming through pixmaps. The text is drawn at zoom 
  977.       --  level 100%. 
  978.  
  979.       Src_X_Pos  : Glib.Gfloat := 0.5; 
  980.       Src_Y_Pos  : Glib.Gfloat := 0.5; 
  981.       Dest_X_Pos : Glib.Gfloat := 0.5; 
  982.       Dest_Y_Pos : Glib.Gfloat := 0.5; 
  983.       --  Position of the link's attachment in each of the src and dest items. 
  984.    end record; 
  985.  
  986.    type Interactive_Canvas_Record is new 
  987.      Gtk.Drawing_Area.Gtk_Drawing_Area_Record 
  988.    with record 
  989.       Children          : Glib.Graphs.Graph; 
  990.  
  991.       Layout            : Layout_Algorithm := Default_Layout_Algorithm'Access; 
  992.       Auto_Layout       : Boolean := True; 
  993.       Vertical_Layout   : Boolean := False; 
  994.       --  The algorithm to use when laying out items on the canvas. 
  995.  
  996.       World_X_At_Click  : Glib.Gint; 
  997.       World_Y_At_Click  : Glib.Gint; 
  998.       --  Coordinates of the last button_press event in the canvas. 
  999.       --  These are world-coordinates, so that even if the canvas is scrolled 
  1000.       --  they remain valid 
  1001.  
  1002.       Selected_Count : Natural := 0; 
  1003.       --  Number of selected items 
  1004.  
  1005.       Offset_X_World : Glib.Gint; 
  1006.       Offset_Y_World : Glib.Gint; 
  1007.       --  How much world-coordinates have we moved the mouse since the last 
  1008.       --  button press event ? 
  1009.  
  1010.       Mouse_Has_Moved   : Boolean; 
  1011.       --  True if mouse has moved while the button was clicked. This is used 
  1012.       --  to distinguish between item motion and item selection. 
  1013.  
  1014.       Event_Press       : Gdk.Event.Gdk_Event; 
  1015.       --  Save the event that was sent when the item was clicked on. This 
  1016.       --  event will be sent to the application if the item was not moved. 
  1017.  
  1018.       Show_Item                    : Canvas_Item; 
  1019.       Show_Canvas_X, Show_Canvas_Y : Glib.Gdouble; 
  1020.       --  The item that should be made visible when the canvas is resized. 
  1021.       --  This is required since the canvas doesn't necessarily have a size yet 
  1022.       --  when Show_Item() is called the first time. 
  1023.  
  1024.       Grid_Size         : Glib.Guint := Default_Grid_Size; 
  1025.       --  The current number of pixels between each dot of the grid. If this 
  1026.       --  is strictly below 2, the grid is not drawn. 
  1027.  
  1028.       Arc_Link_Offset   : Glib.Gint := Default_Arc_Link_Offset; 
  1029.       Arrow_Angle       : Float; 
  1030.       Arrow_Length      : Glib.Gint := Default_Arrow_Length; 
  1031.       Motion_Threshold  : Glib.Gint := Default_Motion_Threshold; 
  1032.       Align_On_Grid     : Boolean := False; 
  1033.  
  1034.       --  The following variables are initialized as soon as a Gdk_Window 
  1035.       --  has been created for the canvas, in the Realized subprograms. 
  1036.  
  1037.       Clear_GC        : Gdk.GC.Gdk_GC := Gdk.GC.Null_GC; 
  1038.       Black_GC        : Gdk.GC.Gdk_GC := Gdk.GC.Null_GC; 
  1039.       Link_GC         : Gdk.GC.Gdk_GC := Gdk.GC.Null_GC; 
  1040.       Anim_GC         : Gdk.GC.Gdk_GC := Gdk.GC.Null_GC; 
  1041.  
  1042.       Annotation_Layout : Pango.Layout.Pango_Layout; 
  1043.       --  Layout used to draw the annotations 
  1044.  
  1045.       Hadj, Vadj : Gtk.Adjustment.Gtk_Adjustment; 
  1046.       Scrolling_Timeout_Id : Glib.Main.G_Source_Id := 0; 
  1047.       Dashed_Line_Visible : Boolean := False; 
  1048.  
  1049.       Orthogonal_Links : Boolean := False; 
  1050.       --  True if the links should be orthogonal 
  1051.  
  1052.       Surround_Box_Scroll : Glib.Gfloat; 
  1053.       --  Amount of scrolling for each step while the cursor is left in the 
  1054.       --  surrounding box. 
  1055.  
  1056.       Zoom : Glib.Guint := 100; 
  1057.       --  Zoom level in percent (100% is normal size) 
  1058.  
  1059.       Target_Zoom : Glib.Guint := 100; 
  1060.       Zoom_Step : Glib.Gint; 
  1061.       --  Variables used while smooth-scrolling the canvas 
  1062.    end record; 
  1063.  
  1064.    type Canvas_Item_Record is abstract new Glib.Graphs.Vertex with record 
  1065.       Coord            : Gdk.Rectangle.Gdk_Rectangle := (0, 0, 1, 1); 
  1066.       --  Change doc for Get_Coord if you ever change default values. 
  1067.       --  This is the bounding box of the item 
  1068.  
  1069.       Visible          : Boolean := True; 
  1070.       Selected         : Boolean := False; 
  1071.  
  1072.       From_Auto_Layout : Boolean := True; 
  1073.       --  True if the item's current location is the result of the automatic 
  1074.       --  layout algorithm. 
  1075.    end record; 
  1076.  
  1077.    procedure Set_Screen_Size 
  1078.      (Item   : access Buffered_Item_Record; 
  1079.       Width, Height  : Glib.Gint); 
  1080.    --  See documentation from inherited subprogram 
  1081.  
  1082.    procedure Draw 
  1083.      (Item         : access Buffered_Item_Record; 
  1084.       Canvas       : access Interactive_Canvas_Record'Class; 
  1085.       GC           : Gdk.GC.Gdk_GC; 
  1086.       Xdest, Ydest : Glib.Gint); 
  1087.    --  Draw the item's double-buffer onto Dest. 
  1088.  
  1089.    procedure Destroy (Item : in out Buffered_Item_Record); 
  1090.    --  Free the double-buffer allocated for the item 
  1091.  
  1092.    type Buffered_Item_Record is new Canvas_Item_Record with record 
  1093.       Pixmap : Gdk.Pixmap.Gdk_Pixmap; 
  1094.    end record; 
  1095.  
  1096.    type Item_Iterator is record 
  1097.       Vertex            : Glib.Graphs.Vertex_Iterator; 
  1098.       Edge              : Glib.Graphs.Edge_Iterator; 
  1099.       Linked_From_Or_To : Canvas_Item; 
  1100.       Selected_Only     : Boolean; 
  1101.    end record; 
  1102.  
  1103.    pragma Inline (To_Canvas_Coordinates); 
  1104.    pragma Inline (To_World_Coordinates); 
  1105.    pragma Inline (Get_Arrow_Type); 
  1106.    pragma Inline (Pixmap); 
  1107.  
  1108. end Gtkada.Canvas; 
  1109.  
  1110. --  <example> 
  1111. --  --  The following example shows a possible Draw_Background procedure, 
  1112. --  --  that draws a background image on the canvas's background. It fully 
  1113. --  --  handles zooming and tiling of the image. Note that drawing a large 
  1114. --  --  image will dramatically slow down the performances. 
  1115. -- 
  1116. --  Background : Gdk.Pixbuf.Gdk_Pixbuf := ...; 
  1117. -- 
  1118. --  procedure Draw_Background 
  1119. --    (Canvas        : access Image_Canvas_Record; 
  1120. --     Screen_Rect   : Gdk.Rectangle.Gdk_Rectangle) 
  1121. --  is 
  1122. --     X_Left : constant Glib.Gint := Left_World_Coordinates (Canvas); 
  1123. --     Y_Top  : constant Glib.Gint := Top_World_Coordinates (Canvas); 
  1124. --     X, Y, W, H, Ys : Gint; 
  1125. --     Xs : Gint := Screen_Rect.X; 
  1126. --     Bw : constant Gint := Get_Width (Background) 
  1127. --       * Gint (Get_Zoom (Canvas)) / 100; 
  1128. --     Bh : constant Gint := Get_Height (Background) 
  1129. --       * Gint (Get_Zoom (Canvas)) / 100; 
  1130. --     Scaled : Gdk_Pixbuf := Background; 
  1131. --  begin 
  1132. --     if Get_Zoom (Canvas) /= 100 then 
  1133. --        Scaled := Scale_Simple (Background, Bw, Bh); 
  1134. --     end if; 
  1135. -- 
  1136. --     while Xs < Screen_Rect.X + Screen_Rect.Width loop 
  1137. --        Ys := Screen_Rect.Y; 
  1138. --        X := (X_Left + Xs) mod Bw; 
  1139. --        W := Gint'Min (Screen_Rect.Width + Screen_Rect.X- Xs, Bw - X); 
  1140.  
  1141. --        while Ys < Screen_Rect.Y + Screen_Rect.Height loop 
  1142. --           Y := (Y_Top  + Ys) mod Bh; 
  1143. --           H := Gint'Min 
  1144. --             (Screen_Rect.Height + Screen_Rect.Y - Ys, Bh - Y); 
  1145. --           Render_To_Drawable 
  1146. --             (Pixbuf       => Scaled, 
  1147. --              Drawable     => Get_Window (Canvas), 
  1148. --              Gc           => Get_Black_GC (Get_Style (Canvas)), 
  1149. --              Src_X        => X, 
  1150. --              Src_Y        => Y, 
  1151. --              Dest_X       => Xs, 
  1152. --              Dest_Y       => Ys, 
  1153. --              Width        => W, 
  1154. --              Height       => H); 
  1155. --           Ys := Ys + H; 
  1156. --        end loop; 
  1157. --        Xs := Xs + W; 
  1158. --     end loop; 
  1159. -- 
  1160. --     if Get_Zoom (Canvas) /= 100 then 
  1161. --        Unref (Scaled); 
  1162. --     end if; 
  1163. --  end Draw_Background; 
  1164. --  </example>