----------------------------------------- --------------------------------------- ------------------------------------------------------------------------------ -- Cheddar is a GNU GPL real time scheduling analysis tool. -- This program provides services to automatically check performances -- of real time architectures. -- -- Copyright (C) 2002-2010, by Frank Singhoff, Alain Plantec, Jerome Legrand -- -- The Cheddar project was started in 2002 by -- the LISyC Team, University of Western Britanny. -- -- Since 2008, Ellidiss technologies also contributes to the development of -- Cheddar and provides industrial support. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- -- -- Contact : cheddar@listes.univ-brest.fr -- ----------------------------------------------------------------------------- -- Last update : -- $Rev: 523 $ -- $Date: 2012-09-26 15:09:39 +0200 (mer. 26 sept. 2012) $ -- $Author: fotsing $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Glib; use Glib; with Gtk.Enums; use Gtk.Enums; with Gtk.Style; use Gtk.Style; with Gdk.Drawable; use Gdk.Drawable; with Gdk.Event; use Gdk.Event; with Gdk.Window; use Gdk.Window; with Gdk.Rectangle; use Gdk.Rectangle; with Gtk.Drawing_Area; use Gtk.Drawing_Area; with Gtk.Handlers; use Gtk.Handlers; --with graphical_editor.scheduling_simulation_callbacks; use graphical_editor.scheduling_simulation_callbacks; package body Double_Buffer is package Event_Cb is new Gtk.Handlers.Return_Callback ( Widget_Type => Gtk_Double_Buffer_Record, Return_Type => Boolean); package Void_Cb is new Gtk.Handlers.Callback ( Widget_Type => Gtk_Double_Buffer_Record); function Configure (Buffer : access Gtk_Double_Buffer_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean; -- Callback when the buffer is resized function Expose (Buffer : access Gtk_Double_Buffer_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean; -- Callback when the window needs to redraw itself on the screen function Create_Internal_Pixmap (Buffer : access Gtk_Double_Buffer_Record'Class) return Gdk.Pixmap.Gdk_Pixmap; -- Create one of the internal pixmaps used by the buffer, with the -- correct size. procedure Destroy_Cb (Buffer : access Gtk_Double_Buffer_Record'Class); -- Called when the widget is destroyed, to free up some memory ------------- -- Gtk_New -- ------------- procedure Gtk_New (Buffer : out Gtk_Double_Buffer) is begin Buffer := new Gtk_Double_Buffer_Record; Double_Buffer.Initialize (Buffer); --Buffer := Gtk_Double_Buffer(my_area); end Gtk_New; ---------------- -- Initialize -- ---------------- procedure Initialize (Buffer : access Gtk_Double_Buffer_Record'Class) is begin Gtk.Drawing_Area.Initialize (Buffer); -- Gtk.Drawing_Area.Initialize (Gtk_Double_Buffer(my_area)); -- Note: the pixmap is created in the resize routine -- and the GC is created in the Realize_Cb routine. -- Connect the signals Event_Cb.Connect (Buffer, "configure_event", Event_Cb.To_Marshaller (Configure'Access)); Event_Cb.Connect (Buffer, "expose_event", Event_Cb.To_Marshaller (Expose'Access)); Void_Cb.Connect (Buffer, "destroy", Void_Cb.To_Marshaller (Destroy_Cb'Access)); end Initialize; ---------------------------- -- Create_Internal_Pixmap -- ---------------------------- function Create_Internal_Pixmap (Buffer : access Gtk_Double_Buffer_Record'Class) return Gdk.Pixmap.Gdk_Pixmap is Pix : Gdk.Pixmap.Gdk_Pixmap; begin Gdk.Pixmap.Gdk_New (Pix, Get_Window (Buffer), Gint (Get_Allocation_Width (Buffer)), Gint (Get_Allocation_Height (Buffer))); return Pix; end Create_Internal_Pixmap; --------------- -- Configure -- --------------- function Configure (Buffer : access Gtk_Double_Buffer_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean is Old_Pixmap : constant Gdk.Pixmap.Gdk_Pixmap := Buffer.Pixmap; Old_Triple : constant Gdk.Pixmap.Gdk_Pixmap := Buffer.Triple_Buffer; use type Gdk.Pixmap.Gdk_Pixmap; begin Buffer.Pixmap := Create_Internal_Pixmap (Buffer); if Buffer.Use_Triple_Buffer then Buffer.Triple_Buffer := Create_Internal_Pixmap (Buffer); end if; if Old_Pixmap /= null then -- If Back_Store is True, then we want to keep the content -- of the old pixmap, and thus we copy it to the new one. if Buffer.Back_Store then declare Old_Width : Gint; Old_Height : Gint; begin Get_Size (Gdk_Window (Old_Pixmap), Old_Width, Old_Height); Gdk.Drawable.Draw_Rectangle (Buffer.Pixmap, Get_Background_GC (Get_Style (Buffer), State_Normal), Filled => True, X => 0, Y => 0, Width => Gdk.Event.Get_Width (Event), Height => Gdk.Event.Get_Height (Event)); -- Gdk.Drawable.Copy_Area --(Buffer.Pixmap, --Get_Foreground_GC (Get_Style (Buffer), State_Normal), -- X => 0, -- Y => 0, -- Source => Old_Pixmap, -- Source_X => 0, -- Source_Y => 0, -- Width => Old_Width, -- Height => Old_Height); Gdk.Drawable.Draw_Drawable (Buffer.Pixmap, Get_Foreground_GC (Get_Style (Buffer), State_Normal), Old_Pixmap, 0, 0, 0, 0, Width => Old_Width, Height => Old_Height); end; end if; Gdk.Pixmap.Unref (Old_Pixmap); end if; if Old_Triple /= null then -- If Back_Store is True, then we want to keep the content -- of the old pixmap, and thus we copy it to the new one. if Buffer.Back_Store then declare Old_Width : Gint; Old_Height : Gint; begin Get_Size (Gdk_Window (Old_Triple), Old_Width, Old_Height); Gdk.Drawable.Draw_Rectangle (Buffer.Triple_Buffer, Get_Background_GC (Get_Style (Buffer), State_Normal), Filled => True, X => 0, Y => 0, Width => Gdk.Event.Get_Width (Event), Height => Gdk.Event.Get_Height (Event)); -- Gdk.Drawable.Copy_Area Gdk.Drawable.Draw_Drawable (Buffer.Triple_Buffer, Get_Foreground_GC (Get_Style (Buffer), State_Normal), Old_Triple, 0, 0, --X => 0, -- Y => 0, --Source => Old_Triple, -- Source_X => 0, -- Source_Y => 0, 0, 0, Width => Old_Width, Height => Old_Height); end; end if; Gdk.Pixmap.Unref (Old_Triple); end if; return True; end Configure; ---------------- -- Destroy_Cb -- ---------------- procedure Destroy_Cb (Buffer : access Gtk_Double_Buffer_Record'Class) is use type Gdk.Pixmap.Gdk_Pixmap; begin if Buffer.Pixmap /= null then Gdk.Pixmap.Unref (Buffer.Pixmap); end if; if Buffer.Triple_Buffer /= null then Gdk.Pixmap.Unref (Buffer.Triple_Buffer); end if; end Destroy_Cb; ------------ -- Expose -- ------------ function Expose (Buffer : access Gtk_Double_Buffer_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean is Area : constant Gdk.Rectangle.Gdk_Rectangle := Gdk.Event.Get_Area (Event); begin if Buffer.Use_Triple_Buffer then -- If the event was generated manually, we need to update -- the Triple_Buffer with the value of the double_buffer, -- unless of course the buffer is frozen. if Gdk.Event.Get_Send_Event (Event) then if Buffer.Is_Frozen then Buffer.Should_Update_On_Screen := True; else --Gdk.Drawable.Copy_Area Gdk.Drawable.Draw_Drawable (Buffer.Triple_Buffer, Get_Foreground_GC (Get_Style (Buffer), State_Normal), Buffer.Pixmap, --X => 0, 0, -- Y => 0, 0, -- Source => Buffer.Pixmap, --Source_X => 0, 0, 0, -- Source_Y => 0, Width => Gint (Get_Allocation_Width (Buffer)), Height => Gint (Get_Allocation_Height (Buffer))); end if; end if; -- Copy the triple buffer to the screen --Gdk.Drawable.Copy_Area Gdk.Drawable.Draw_Drawable (Get_Window (Buffer), Get_Foreground_GC (Get_Style (Buffer), State_Normal), Buffer.Triple_Buffer, Area.X, -- X => Area.X, -- Y => Area.Y, Area.Y, -- Source => Buffer.Triple_Buffer, -- Source_X => Area.X, Area.X, --Source_Y => Area.Y, Area.Y, Width => Gint (Area.Width), Height => Gint (Area.Height)); elsif not Buffer.Is_Frozen then -- Copy the double buffer to the screen --Gdk.Drawable.Copy_Area Gdk.Drawable.Draw_Drawable (Get_Window (Buffer), Get_Foreground_GC (Get_Style (Buffer), State_Normal), Buffer.Pixmap, -- X => Area.X, Area.X, -- Y => Area.Y, Area.Y, -- Source => Buffer.Pixmap, -- Source_X => Area.X, Area.X, -- Source_Y => Area.Y, Area.Y, Width => Gint (Area.Width), Height => Gint (Area.Height)); else Buffer.Should_Update_On_Screen := True; end if; return False; end Expose; ---------------- -- Get_Pixmap -- ---------------- function Get_Pixmap (Buffer : access Gtk_Double_Buffer_Record) return Gdk.Drawable.Gdk_Drawable is begin return Gdk.Drawable.Gdk_Drawable (Buffer.Pixmap); end Get_Pixmap; -------------------- -- Set_Back_Store -- -------------------- procedure Set_Back_Store (Buffer : access Gtk_Double_Buffer_Record; Back_Store : Boolean := True) is begin Buffer.Back_Store := Back_Store; end Set_Back_Store; ------------ -- Freeze -- ------------ procedure Freeze (Buffer : access Gtk_Double_Buffer_Record) is begin Buffer.Is_Frozen := True; end Freeze; ---------- -- Thaw -- ---------- procedure Thaw (Buffer : access Gtk_Double_Buffer_Record) is begin Buffer.Is_Frozen := False; if Buffer.Should_Update_On_Screen then Draw (Buffer); end if; end Thaw; ----------------------- -- Set_Triple_Buffer -- ----------------------- procedure Set_Triple_Buffer (Buffer : access Gtk_Double_Buffer_Record; Use_Triple_Buffer : Boolean := True) is use type Gdk.Gdk_Window; begin Buffer.Use_Triple_Buffer := Use_Triple_Buffer; -- If we do not want triple_buffer but already have one, delete it if not Use_Triple_Buffer and then Buffer.Triple_Buffer /= null then Gdk.Pixmap.Unref (Buffer.Triple_Buffer); end if; -- If we do want a triple buffer, create the pixmap if Use_Triple_Buffer then Buffer.Triple_Buffer := Create_Internal_Pixmap (Buffer); -- Copy the current value of the pixmap in it --Gdk.Drawable.Copy_Area Gdk.Drawable.Draw_Drawable (Buffer.Triple_Buffer, Get_Foreground_GC (Get_Style (Buffer), State_Normal), Buffer.Pixmap, 0, 0, -- X => 0, -- Y => 0, --Source => Buffer.Pixmap, 0, 0, -- Source_X => 0, -- Source_Y => 0, Width => Gint (Get_Allocation_Width (Buffer)), Height => Gint (Get_Allocation_Height (Buffer))); end if; end Set_Triple_Buffer; end Double_Buffer;