Scrolling a drawingarea

336 views Asked by At

For information: I use Ada as programming language, The Windowing software is Gtk and GtkAda.

I have a drawing on a drawing area that sometimes not fits witkin my window, not even if I use full screen. Therefore I need to have a scrolled area. I use the enclosed code to get such a window but the scrollbars always cannot move so a part of my drawing cannot been seen. What must I add to my program, and what must I do when in a running program the range for the scrollbars must be altered?

    Gtk_New (MainWindow.Scrolledwindow);
    Set_Policy (MainWindow.Scrolledwindow, Policy_Always, Policy_Always);
    Set_Shadow_Type (MainWindow.Scrolledwindow, Shadow_None);
    Set_Placement (MainWindow.Scrolledwindow, Corner_Top_Left);
    Gtk_New (MainWindow.View_Port);
    Gtk_New (MainWindow.DrawingArea);
    MainWindow.Scrolledwindow.Add(MainWindow.View_Port);
    MainWindow.View_Port.Add(MainWindow.DrawingArea);
    Pack_Start
      (MainWindow.Main_Box1,
       MainWindow.Scrolledwindow,
       Expand  => True,
       Fill    => True,
       Padding => 0);


1

There are 1 answers

1
DeeDee On

I think you can omit the view port widget and replace it with just a box. As @lb90, stated, you can set the size of the drawing area using Set_Size_Request. This seems to do the trick:

main.adb

with Gtk.Main;
with Demo.Main_Window;

procedure Main is
   use Demo.Main_Window;
   Main_Window : Demo_Main_Window;
begin
   Gtk.Main.Init;
   Gtk_New (Main_Window);
   Gtk.Main.Main;
end Main;

demo.ads

package Demo is

end Demo;

demo-main_window.ads

with Glib; use Glib;

with Gtk.Window;
with Gtk.Scrolled_Window;
with Gtk.Box;
with Gtk.Drawing_Area;

package Demo.Main_Window is

   type Demo_Main_Window_Record is new Gtk.Window.Gtk_Window_Record with private;
   type Demo_Main_Window is access all Demo_Main_Window_Record'Class;

   ------------------
   -- Constructors --
   ------------------

   procedure Gtk_New
     (Main_Window : out Demo_Main_Window);
   procedure Initialize
     (Main_Window : not null access Demo_Main_Window_Record'Class);

private

   use Gtk.Scrolled_Window;
   use Gtk.Box;
   use Gtk.Drawing_Area;

   Window_Width  : constant Gint := 640;
   Window_Height : constant Gint := 480;

   Draw_Area_Width  : constant Gint := 1000;
   Draw_Area_Height : constant Gint := 1000;

   type Demo_Main_Window_Record is
     new Gtk.Window.Gtk_Window_Record with
      record
         SW : Gtk_Scrolled_Window;
         VB : Gtk_Vbox;
         DA : Gtk_Drawing_Area;
      end record;

end Demo.Main_Window;

demo-main_window.adb

with Glib; use Glib;

with Gtk.Main;
with Gtk.Widget;
with Gtk.Window;
with Gtk.Enums;
with Gtk.Adjustment;

with Cairo;

package body Demo.Main_Window is

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class);

   function Draw_Event_Callback
     (Self : access Gtk.Widget.Gtk_Widget_Record'Class;
      Cr   : Cairo.Cairo_Context) return Boolean;

   -------------
   -- Gtk_New --
   -------------

   procedure Gtk_New (Main_Window : out Demo_Main_Window) is
   begin
      Main_Window := new Demo_Main_Window_Record;
      Demo.Main_Window.Initialize (Main_Window);
   end Gtk_New;

   ----------------
   -- Initialize --
   ----------------

   procedure Initialize
     (Main_Window : not null access Demo_Main_Window_Record'Class)
   is      
   begin

      Gtk.Window.Initialize (Main_Window);

      --  Setup window
      Main_Window.Set_Title ("Demo");
      Main_Window.Set_Size_Request (Window_Width, Window_Height);
      Main_Window.Set_Resizable (False);

      Main_Window.On_Destroy (Destroy_Event_Callback'Access);

      --  Add controls
      Gtk_New (Main_Window.SW);
      Gtk_New_Vbox (Main_Window.VB);
      Gtk_New (Main_Window.DA);

      Main_Window.SW.Set_Policy
        (Hscrollbar_Policy => Gtk.Enums.Policy_Always,
         Vscrollbar_Policy => Gtk.Enums.Policy_Always);

      Main_Window.DA.Set_Size_Request (Draw_Area_Width, Draw_Area_Height);
      Main_Window.DA.On_Draw (Draw_Event_Callback'Access);

      Main_Window.VB.Pack_Start (Main_Window.DA, True, True, 0);
      Main_Window.SW.Add (Main_Window.VB);
      Main_Window.Add (Main_Window.SW);      

      --  Show the window.
      Main_Window.Show_All;

   end Initialize;

   ----------------------------
   -- Destroy_Event_Callback --
   ----------------------------

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class)
   is
   begin
      Gtk.Main.Main_Quit;
   end Destroy_Event_Callback;

   -------------------------
   -- Draw_Event_Callback --
   -------------------------

   function Draw_Event_Callback
     (Self : access Gtk.Widget.Gtk_Widget_Record'Class;
      Cr   : Cairo.Cairo_Context) return Boolean
   is

      --  Draw some rectangles. This function is not optimal in terms of 
      --  performance as everything is being redrawn, including the non 
      --  visible parts, but it's OK (I think) for the demo.

      Num_X : constant Gint := 20;
      Num_Y : constant Gint := 20;  

      Ratio : constant Gdouble := 0.8;            

      Dx : constant GDouble := GDouble (Self.Get_Allocated_Width  / Num_X);
      Dy : constant GDouble := GDouble (Self.Get_Allocated_Height / Num_Y);

      --  Or, alternatively (same outcome)
      --    Dx : constant GDouble := GDouble (Draw_Area_Width  / Num_X);
      --    Dy : constant GDouble := GDouble (Draw_Area_Height / Num_Y);

   begin

      for X in 0 .. Num_X - 1 loop
         for Y in 0 .. Num_Y - 1 loop

            Cairo.Set_Source_RGB 
              (Cr    => Cr,
               Red   => GDouble (X)     / GDouble (Num_X),
               Green => GDouble (X * Y) / GDouble (Num_X * Num_Y),
               Blue  => GDouble (Y)     / GDouble (Num_Y));

            Cairo.Rectangle
              (Cr     => Cr,
               X      => Dx * (GDouble (X) + 0.5 * (1.0 - Ratio)),
               Y      => Dy * (GDouble (Y) + 0.5 * (1.0 - Ratio)),
               Width  => Dx * Ratio,
               Height => Dy * Ratio);

            Cairo.Fill (Cr);

         end loop;
      end loop;

      return True;   -- GDK_EVENT_STOP, do not propagate event to parent.

   end Draw_Event_Callback;

end Demo.Main_Window;