------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Cheddar is a GNU GPL real-time scheduling analysis tool. -- This program provides services to automatically check schedulability and -- other performance criteria of real-time architecture models. -- -- Copyright (C) 2002-2016, Frank Singhoff, Alain Plantec, Jerome Legrand -- -- The Cheddar project was started in 2002 by -- Frank Singhoff, Lab-STICC UMR 6285 laboratory, Université de Bretagne Occidentale -- -- Cheddar has been published in the "Agence de Protection des Programmes/France" in 2008. -- Since 2008, Ellidiss technologies also contributes to the development of -- Cheddar and provides industrial support. -- -- The full list of contributors and sponsors can be found in AUTHORS.txt and SPONSORS.txt -- -- 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: 1249 $ -- $Date: 2014-08-28 07:02:15 +0200 (Fri, 28 Aug 2014) $ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Gtk.Drawing_Area; use Gtk.Drawing_Area; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Gdk.Drawable; use Gdk.Drawable; with Gtk.Handlers; use Gtk.Handlers; with Gtk.Arguments; use Gtk.Arguments; with Gtk.Object; use Gtk.Object; with Gdk; use Gdk; with Gtkada.Types; use Gtkada.Types; with System; use System; with Framework_Config; use Framework_Config; with editor_Config; use editor_Config; with Translate; use Translate; with Ada.Numerics.Aux; use Ada.Numerics.Aux; with Glib.Values; use Glib.Values; with Ada.Text_IO; package body graphical_editor.draw_buffer is PACKAGE Es_Entiers IS NEW Ada.Text_IO.Integer_IO(Integer); use Es_Entiers; package Cb is new Gtk.Handlers.Return_Callback(Gtk.Drawing_Area.Gtk_Drawing_Area_Record, boolean); use Cb; function Expose (W : access Gtk.Drawing_Area.Gtk_Drawing_Area_Record'Class) return boolean is begin --Draw_Time_Line(sys.tasks, sys.resources, sys.messages, sys.buffers, Stop_Draw, Start_Draw, Framework.Sched); return false; end Expose; -- This pointer will keep a pointer to the C 'class record' for -- gtk. To avoid allocating memory for each widget, this may be done -- only once, and reused -- Class_Record : System.Address := System.Null_Address; Class_Record : GObject_Class; package Draw_Cb is new Gtk.Handlers.Return_Callback ( Widget_Type => Draw_Buffer_Record, Return_Type => Boolean); package Allocation_Cb is new Handlers.Callback (Draw_Buffer_Record); -- package Allocation_Marshaller is new -- Allocation_Cb.Marshallers.Generic_Marshaller ( -- Gtk_Allocation_Access, -- To_Allocation); procedure Gtk_New (Draw_Buffer : out Draw_Buffer_Access; Object : access Gtkada_Builder_Record'Class) is begin Draw_Buffer := new Draw_Buffer_Record; graphical_editor.draw_buffer.Initialize (Draw_Buffer, Object); end Gtk_New; procedure Initialize (Draw_Buffer : access Draw_Buffer_Record'Class; Object : access Gtkada_Builder_Record'Class) is buffer_area : Gtk_Widget; begin buffer_area := Get_widget(Object, "drawingarea1"); Draw_Buffer.Current_Width := 0; Draw_Buffer.Current_Height := 0; -- We need to call the ancestor's Initialize function to create -- the underlying C object. Double_Buffer.Initialize (Draw_Buffer); -- The following call is required to initialize the class record, -- and the new signals created for this widget. -- Note that for now you can only create basic signals (whose -- callbacks do not have any parameters), and that you just have -- to put their name in a table. -- Note also that we keep Class_Record, so that the memory allocation -- is done only once. Gtk.Object.Initialize_Class_Record (Draw_Buffer, Null_Array, Class_Record, "buffer"); Gtk.Drawing_Area.Set_USize ( Gtk_Drawing_Area(buffer_area), Draw_Buffer.Current_Width, Draw_Buffer.Current_Height); Load (Draw_Buffer.Font, to_string(selected_font) ); Draw_Cb.Connect (Draw_Buffer, "configure_event", Draw_Cb.To_Marshaller (Configure'Access)); end Initialize; procedure Color_Allocation (Draw_Buffer : access Draw_Buffer_Record'Class) is begin if not Draw_Buffer.Have_Colors then Gdk.GC.Gdk_New (Draw_Buffer.White_Gc, Get_Window (Draw_Buffer)); Gdk.GC.Set_Foreground (Draw_Buffer.White_Gc, Gdk.Color.White (Gtk.Widget.Get_Default_Colormap)); Gdk.GC.Gdk_New (Draw_Buffer.Black_Gc, Get_Window (Draw_Buffer)); Gdk.GC.Set_Foreground (Draw_Buffer.Black_Gc, Gdk.Color.Black (Gtk.Widget.Get_Default_Colormap)); Draw_Buffer.Red_Color := Gdk.Color.Parse ("Red"); Gdk.Color.Alloc (Gtk.Widget.Get_Default_Colormap, Draw_Buffer.Red_Color); Draw_Buffer.Have_Colors := True; end if; end Color_Allocation; procedure Clear (Draw_Buffer : access Draw_Buffer_Record'Class) is begin Color_Allocation (Draw_Buffer); Draw_Buffer.Initialized := False; Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.White_Gc, Filled => True, X => 0, Y => 0, Width => Draw_Buffer.Current_Width, Height => Draw_Buffer.Current_Height); Double_Buffer.Draw (Gtk_Double_Buffer (Draw_Buffer)); end Clear; procedure draw_mod (Object : access Gtkada_Builder_Record'Class; Draw_Buffer : access Draw_Buffer_Record'Class; Buff : Buffer_Ptr; Buff1 : Buffer_Size_Table; Last_Time_Unit1 : Natural; Time_Unit_Number1 : Time_Unit_Range) is I : Gint := 0; Ok : Boolean; buffer_area : Gtk_Widget; begin buffer_area := Get_widget(Object, "drawingarea1"); Draw_Buffer.Last_Time_Unit := Last_Time_Unit1; Draw_Buffer.Time_Unit_Number := Time_Unit_Number1; Draw_Buffer.Buff := new Buffer_Size_Table; Draw_Buffer.Buff.all := Buff1; Draw_Buffer.Buff_Ptr := Buff; Ok := False; I := Gint (Draw_Buffer.Last_Time_Unit + 4) * Draw_Buffer.Timeunit_Margin + Draw_Buffer.Left_Margin; if I > Draw_Buffer.Current_Width then Draw_Buffer.Current_Width := I; Ok := True; end if; I := Draw_Buffer.High_Margin + Draw_Buffer.Buffer_Margin * 4; if I > Draw_Buffer.Current_Height then Draw_Buffer.Current_Height := I; Ok := True; end if; if Ok then Gtk.Drawing_Area.Set_USize (Gtk_Drawing_Area(buffer_area), Draw_Buffer.Current_Width, Draw_Buffer.Current_Height); end if; Redraw_mod (Object, Draw_Buffer); end draw_mod; procedure Draw (Draw_Buffer : access Draw_Buffer_Record'Class; Buff : Buffer_Ptr; Buff1 : Buffer_Size_Table; Last_Time_Unit1 : Natural; Time_Unit_Number1 : Time_Unit_Range) is I : Gint := 0; Ok : Boolean; begin Draw_Buffer.Last_Time_Unit := Last_Time_Unit1; Draw_Buffer.Time_Unit_Number := Time_Unit_Number1; Draw_Buffer.Buff := new Buffer_Size_Table; Draw_Buffer.Buff.all := Buff1; Draw_Buffer.Buff_Ptr := Buff; Ok := False; I := Gint (Draw_Buffer.Last_Time_Unit + 4) * Draw_Buffer.Timeunit_Margin + Draw_Buffer.Left_Margin; if I > Draw_Buffer.Current_Width then Draw_Buffer.Current_Width := I; Ok := True; end if; I := Draw_Buffer.High_Margin + Draw_Buffer.Buffer_Margin * 4; if I > Draw_Buffer.Current_Height then Draw_Buffer.Current_Height := I; Ok := True; end if; if Ok then Gtk.Drawing_Area.Set_USize (Gtk_Drawing_Area (Draw_Buffer), Draw_Buffer.Current_Width, Draw_Buffer.Current_Height); end if; Draw_Buffer.Initialized := True; Redraw (Draw_Buffer); end Draw; procedure Redraw_mod (Object : access Gtkada_Builder_Record'Class; Draw_Buffer : access Draw_Buffer_Record'Class) is Pixel_Buffer_Size : Gint := 0; Pixel_Buffer_Time : Gint := 0; Msg : Unbounded_String; buffer_area : Gtk_Widget; White_Gc, Black_Gc : Gdk.GC.Gdk_GC; begin buffer_area := Get_widget(Object, "drawingarea1"); --------------------------------- -- Clear work space --------------------------------- Gdk.GC.Gdk_New (White_Gc, Get_Window (buffer_area)); Gdk.GC.Set_Foreground (White_Gc, Gdk.Color.White (Gtk.Widget.Get_Default_Colormap)); Draw_Rectangle (get_window(buffer_area), White_Gc, Filled => True, X => 0, Y => 0, Width => Draw_Buffer.Current_Width, Height => Draw_Buffer.Current_Height); ---------------------------------------------------------- -- Draw buffer utilization -- in red color ---------------------------------------------------------- for J in 0 .. Draw_Buffer.Time_Unit_Number - 2 loop Pixel_Buffer_Time := Gint (Draw_Buffer.Buff.entries (Buffer_Size_Range (J + 1)).time - Draw_Buffer.Buff.entries (Buffer_Size_Range (J)).time); Pixel_Buffer_Time := Pixel_Buffer_Time * Draw_Buffer.Timeunit_Margin; Pixel_Buffer_Size := Gint (Double ( Draw_Buffer.Buff.entries (Buffer_Size_Range (J)).size) * 100.0 / Double (Draw_Buffer.Buff_Ptr.buffer_size)); Pixel_Buffer_Size := Pixel_Buffer_Size * Draw_Buffer.Buffer_Margin / 10; Gdk.GC.Gdk_New (Black_Gc, Get_Window (buffer_area)); Gdk.GC.Set_Foreground (White_Gc, Gdk.Color.Black (Gtk.Widget.Get_Default_Colormap)); Draw_Rectangle (get_window(buffer_area), Black_Gc, True, Draw_Buffer.Left_Margin + (Gint (Draw_Buffer.Buff.entries (Buffer_Size_Range (J)).time) * Draw_Buffer.Timeunit_Margin), Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin - Pixel_Buffer_Size, Pixel_Buffer_Time, Pixel_Buffer_Size); end loop; -- Draw the last buffer size unit up to the end of -- the x axis -- Pixel_Buffer_Time := Gint (Draw_Buffer.Last_Time_Unit - Draw_Buffer.Buff.entries (Buffer_Size_Range (Draw_Buffer.Time_Unit_Number - 1)).time); Pixel_Buffer_Time := Pixel_Buffer_Time * Draw_Buffer.Timeunit_Margin; Pixel_Buffer_Size := Gint (Double ( Draw_Buffer.Buff.entries (Buffer_Size_Range (Draw_Buffer.Time_Unit_Number - 1 )).size) * 100.0 / Double (Draw_Buffer.Buff_Ptr.buffer_size)); Pixel_Buffer_Size := Pixel_Buffer_Size * Draw_Buffer.Buffer_Margin / 10; Gdk.GC.Gdk_New (Black_Gc, Get_Window (buffer_area)); Gdk.GC.Set_Foreground (White_Gc, Gdk.Color.Black (Gtk.Widget.Get_Default_Colormap)); Draw_Rectangle (get_window(buffer_area), Black_Gc, True, Draw_Buffer.Left_Margin + (Gint ( Draw_Buffer.Buff.entries (Buffer_Size_Range (Draw_Buffer. Time_Unit_Number - 1 )).time) * Draw_Buffer.Timeunit_Margin), Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin - Pixel_Buffer_Size, Pixel_Buffer_Time, Pixel_Buffer_Size); Gdk.GC.Set_Foreground (Black_Gc, Gdk.Color.Black (Gtk.Widget.Get_Default_Colormap)); --------------------------------- -- Draw x and y axis --------------------------------- Msg := Lb_Time (Current_Language); Draw_Text (get_window(buffer_area), Draw_Buffer.Font, Black_Gc, Draw_Buffer.Left_Margin + 20 + Gint (Draw_Buffer.Last_Time_Unit) * Draw_Buffer.Timeunit_Margin, Draw_Buffer.High_Margin - 35 + Gint (12) * Draw_Buffer.Buffer_Margin, To_String (Msg)); Msg := Lb_Utilization_Level (Current_Language); Draw_Text (get_window(buffer_area), Draw_Buffer.Font, Black_Gc, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin, To_String (Msg)); Draw_Line (get_window(buffer_area), Black_Gc, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin + 20, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin + 20 + 10 * Draw_Buffer.Buffer_Margin); Draw_Line (get_window(buffer_area), Black_Gc, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin, Draw_Buffer.Left_Margin + Gint (Draw_Buffer.Last_Time_Unit) * Draw_Buffer.Timeunit_Margin, Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin); ---------------------------------------------------------- -- Draw Time unit and buffer size unit -- in black color ---------------------------------------------------------- for J in 0 .. Gint (10) loop Draw_Rectangle (get_window(buffer_area), Black_Gc, True, Draw_Buffer.Left_Margin - 5, Draw_Buffer.High_Margin + 20 + J * Draw_Buffer.Buffer_Margin, 10, 2); end loop; for J in 0 .. Gint (Draw_Buffer.Last_Time_Unit - 1) loop Draw_Rectangle (get_window(buffer_area), Black_Gc, True, Draw_Buffer.Left_Margin + 20 + J * Draw_Buffer.Timeunit_Margin, Draw_Buffer.High_Margin - 5 + Gint (11) * Draw_Buffer.Buffer_Margin, 2, 10); end loop; --------------------- --------------------- -- Flush data in the window --------------------- end Redraw_mod; procedure Redraw (Draw_Buffer : access Draw_Buffer_Record'Class) is Pixel_Buffer_Size : Gint := 0; Pixel_Buffer_Time : Gint := 0; Msg : Unbounded_String; begin --------------------------------- -- Clear work space --------------------------------- Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.White_Gc, Filled => True, X => 0, Y => 0, Width => Draw_Buffer.Current_Width, Height => Draw_Buffer.Current_Height); ---------------------------------------------------------- -- Draw buffer utilization -- in red color ---------------------------------------------------------- for J in 0 .. Draw_Buffer.Time_Unit_Number - 2 loop Pixel_Buffer_Time := Gint (Draw_Buffer.Buff.entries (Buffer_Size_Range (J + 1)).time - Draw_Buffer.Buff.entries (Buffer_Size_Range (J)).time); Pixel_Buffer_Time := Pixel_Buffer_Time * Draw_Buffer.Timeunit_Margin; Pixel_Buffer_Size := Gint (Double ( Draw_Buffer.Buff.entries (Buffer_Size_Range (J)).size) * 100.0 / Double (Draw_Buffer.Buff_Ptr.buffer_size)); Pixel_Buffer_Size := Pixel_Buffer_Size * Draw_Buffer.Buffer_Margin / 10; Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.Black_Gc, True, Draw_Buffer.Left_Margin + (Gint (Draw_Buffer.Buff.entries (Buffer_Size_Range (J)).time) * Draw_Buffer.Timeunit_Margin), Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin - Pixel_Buffer_Size, Pixel_Buffer_Time, Pixel_Buffer_Size); end loop; -- Draw the last buffer size unit up to the end of -- the x axis -- Pixel_Buffer_Time := Gint (Draw_Buffer.Last_Time_Unit - Draw_Buffer.Buff.entries (Buffer_Size_Range (Draw_Buffer. Time_Unit_Number - 1)).time); Pixel_Buffer_Time := Pixel_Buffer_Time * Draw_Buffer.Timeunit_Margin; Pixel_Buffer_Size := Gint (Double ( Draw_Buffer.Buff.entries (Buffer_Size_Range (Draw_Buffer. Time_Unit_Number - 1)).size) * 100.0 / Double (Draw_Buffer.Buff_Ptr.buffer_size)); Pixel_Buffer_Size := Pixel_Buffer_Size * Draw_Buffer.Buffer_Margin / 10; Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.Black_Gc, True, Draw_Buffer.Left_Margin + (Gint ( Draw_Buffer.Buff.entries (Buffer_Size_Range (Draw_Buffer. Time_Unit_Number - 1)).time) * Draw_Buffer.Timeunit_Margin), Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin - Pixel_Buffer_Size, Pixel_Buffer_Time, Pixel_Buffer_Size); Gdk.GC.Set_Foreground (Draw_Buffer.Black_Gc, Gdk.Color.Black (Gtk.Widget.Get_Default_Colormap)); --------------------------------- -- Draw x and y axis --------------------------------- Msg := Lb_Time (Current_Language); Draw_Text (Get_Pixmap (Draw_Buffer), Draw_Buffer.Font, Draw_Buffer.Black_Gc, Draw_Buffer.Left_Margin + 20 + Gint (Draw_Buffer.Last_Time_Unit) * Draw_Buffer.Timeunit_Margin, Draw_Buffer.High_Margin - 35 + Gint (12) * Draw_Buffer.Buffer_Margin, To_String (Msg)); Msg := Lb_Utilization_Level (Current_Language); Draw_Text (Get_Pixmap (Draw_Buffer), Draw_Buffer.Font, Draw_Buffer.Black_Gc, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin, To_String (Msg)); Draw_Line (Get_Pixmap (Draw_Buffer), Draw_Buffer.Black_Gc, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin + 20, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin + 20 + 10 * Draw_Buffer.Buffer_Margin); Draw_Line (Get_Pixmap (Draw_Buffer), Draw_Buffer.Black_Gc, Draw_Buffer.Left_Margin, Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin, Draw_Buffer.Left_Margin + Gint (Draw_Buffer.Last_Time_Unit) * Draw_Buffer.Timeunit_Margin, Draw_Buffer.High_Margin + 20 + Gint (10) * Draw_Buffer.Buffer_Margin); ---------------------------------------------------------- -- Draw Time unit and buffer size unit -- in black color ---------------------------------------------------------- for J in 0 .. Gint (10) loop Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.Black_Gc, True, Draw_Buffer.Left_Margin - 5, Draw_Buffer.High_Margin + 20 + J * Draw_Buffer.Buffer_Margin, 10, 2); end loop; for J in 0 .. Gint (Draw_Buffer.Last_Time_Unit - 1) loop Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.Black_Gc, True, Draw_Buffer.Left_Margin + 20 + J * Draw_Buffer.Timeunit_Margin, Draw_Buffer.High_Margin - 5 + Gint (11) * Draw_Buffer.Buffer_Margin, 2, 10); end loop; --------------------- --------------------- -- Flush data in the window --------------------- Draw (Draw_Buffer); end Redraw; --------------- -- Configure -- --------------- function Configure (Draw_Buffer : access Draw_Buffer_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean is begin if Draw_Buffer.Initialized then Redraw (Draw_Buffer); else Color_Allocation (Draw_Buffer); -- Check if window size has changed ! -- Draw_Buffer.Current_Width := Gint (Get_Allocation_Width (Draw_Buffer)); Draw_Buffer.Current_Height := Gint (Get_Allocation_Height (Draw_Buffer)); Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.White_Gc, Filled => True, X => 0, Y => 0, Width => Draw_Buffer.Current_Width, Height => Draw_Buffer.Current_Height); Double_Buffer.Draw (Gtk_Double_Buffer (Draw_Buffer)); end if; return True; end Configure; procedure Size_Allocate (Draw_Buffer : access Draw_Buffer_Record'Class; Allocation : Gtk_Allocation_Access) is begin if Realized_Is_Set (Draw_Buffer) then Draw_Buffer.Current_Width := Gint (Get_Allocation_Width (Draw_Buffer)); Draw_Buffer.Current_Height := Gint (Get_Allocation_Height (Draw_Buffer)); if Draw_Buffer.Initialized then Redraw (Draw_Buffer); else Color_Allocation (Draw_Buffer); Draw_Rectangle (Get_Pixmap (Draw_Buffer), Draw_Buffer.White_Gc, Filled => True, X => 0, Y => 0, Width => Draw_Buffer.Current_Width, Height => Draw_Buffer.Current_Height); Draw (Draw_Buffer); end if; end if; Gtk.Handlers.Emit_Stop_By_Name (Draw_Buffer, "size_allocate"); end Size_Allocate; end graphical_editor.draw_buffer;