------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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-2020, Frank Singhoff, Alain Plantec, Jerome Legrand, -- Hai Nam Tran, Stephane Rubini -- -- The Cheddar project was started in 2002 by -- Frank Singhoff, Lab-STICC UMR 6285, 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$ -- $Date$ -- $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;