------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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-2023, 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 README.md -- -- 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: 4203 $ -- $Date: 2022-08-29 16:48:23 +0200 (lun., 29 août 2022) $ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with Gtk; use Gtk; with Gtk.Main; use Gtk.Main; with Gtk.Menu_Item; use Gtk.Menu_Item; with Gtk.Widget; use Gtk.Widget; with Gtk.Handlers; use Gtk.Handlers; with Gtk.Dialog; use Gtk.Dialog; with Gtk.About_Dialog; use Gtk.About_Dialog; with Gtk.Check_Button; use Gtk.Check_Button; with Gtk.Text_Buffer; use Gtk.Text_Buffer; with Gtk.Label; use Gtk.Label; with Gtk.Text_Iter; use Gtk.Text_Iter; with Gtk.Menu_Item; use Gtk.Menu_Item; with Gtk.Check_Button; use Gtk.Check_Button; with Gtk.Window; use Gtk.Window; with Gtk.Drawing_Area; use Gtk.Drawing_Area; with Gtk.Combo_Box; use Gtk.Combo_Box; with Gtk.Combo_Box_Text; use Gtk.Combo_Box_Text; with Glib; use Glib; with Glib.Error; use Glib.Error; with Glib.Object; use Glib.Object; with Gdk.Window; use Gdk.Window; with feasibility_test.feasibility_interval; use feasibility_test.feasibility_interval; with double_util; use double_util; with framework; use framework; with call_framework; use call_framework; with call_framework_interface; use call_framework_interface; use call_framework_interface.framework_request_package; use call_framework_interface.framework_response_package; with time_unit_events.extended; use time_unit_events.extended; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with parameters; use parameters; with parameters.extended; use parameters.extended; use parameters.framework_parameters_table_package; with call_scheduling_framework; use call_scheduling_framework; with multiprocessor_services; use multiprocessor_services; with multiprocessor_services_interface; use multiprocessor_services_interface; use multiprocessor_services_interface.scheduling_result_per_processor_package; with framework_config; use framework_config; with editor_config; use editor_config; with strings; use strings; with unbounded_strings; use unbounded_strings; with translate; use translate; with processors; use processors; with processor_set; use processor_set; use processor_set.generic_processor_set; with tasks; use tasks; with task_set; use task_set; use task_set.generic_task_set; with resource_set; use resource_set; use resource_set.generic_resource_set; with message_set; use message_set; use message_set.generic_message_set; with buffer_set; use buffer_set; use buffer_set.generic_buffer_set; with time_unit_events; use time_unit_events; with time_unit_events.extended; use time_unit_events.extended; with doubles; use doubles; with graphical_editor; use graphical_editor; with graphical_editor.processors; use graphical_editor.processors; with graphical_editor.generic_package_widget; use graphical_editor.generic_package_widget; with graphical_editor.event_analyzers; use graphical_editor.event_analyzers; with graphical_editor.user_message; use graphical_editor.user_message; with graphical_editor.select_time_line; use graphical_editor.select_time_line; with graphical_editor.draw_scheduling; use graphical_editor.draw_scheduling; with graphical_editor.message_text; use graphical_editor.message_text; package body graphical_editor.scheduling_simulations_callbacks is draw_from, draw_upto, schedule_to : Unbounded_String; last_period : constant Natural := framework_config.max_scheduling_period - 1; max_period : Integer := 0; start_draw : Integer := 0; stop_draw : Integer := 0; max_draw : Natural := Max_Time_Line_Size_To_Display; ok : Boolean; line_number : Integer := 0; procedure read_scheduling_duration_and_draw_scheduling (object : access gtkada_builder_record'class) is object_number : Natural := 0; begin draw_from := suppress_space (get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer2")))); draw_upto := suppress_space (get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer3")))); schedule_to := suppress_space (get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer1")))); graphical_editor.scheduling_simulations_callbacks.close_widget(object); to_integer (draw_upto, stop_draw, ok); if not ok then show_message_box (lb_double_quote & lb_draw_to (current_language) & lb_double_quote & lb_must_be_numeric (current_language)); return; end if; to_integer (draw_from, start_draw, ok); if not ok then show_message_box (lb_double_quote & lb_draw_from (current_language) & lb_double_quote & lb_must_be_numeric (current_language)); return; end if; to_integer (schedule_to, max_period, ok); if not ok then show_message_box (lb_double_quote & lb_schedule_to (current_language) & lb_double_quote & lb_must_be_numeric (current_language)); return; end if; if (max_period > Integer (last_period)) then show_message_box (lb_double_quote & lb_schedule_to (current_language) & lb_double_quote & lb_must_be (current_language) & lb_less_or_equal_than (current_language) & last_period'img); return; end if; if (max_period <= 0) then show_message_box (lb_double_quote & lb_schedule_to (current_language) & lb_double_quote & lb_must_be (current_language) & lb_greater_than (current_language) & To_Unbounded_String (" 0")); return; end if; if (start_draw < 0) then show_message_box (lb_double_quote & lb_draw_from (current_language) & lb_double_quote & lb_must_be (current_language) & lb_greater_or_equal_than (current_language) & To_Unbounded_String (" 0")); return; end if; if (stop_draw < 0) then show_message_box (lb_double_quote & lb_draw_to (current_language) & lb_double_quote & lb_must_be (current_language) & lb_greater_or_equal_than (current_language) & To_Unbounded_String (" 0")); return; end if; if (start_draw > max_period) then show_message_box (lb_double_quote & lb_draw_from (current_language) & lb_double_quote & lb_must_be (current_language) & lb_less_or_equal_than (current_language) & lb_double_quote & lb_schedule_to (current_language) & lb_double_quote); return; end if; if (stop_draw - start_draw > max_draw) then show_message_box (lb_draw_time_line_too_large (current_language)); return; end if; -- Check if we need to select which tasks/messages/buffers -- to display with time lines -- object_number := Natural (get_number_of_elements (sys.tasks)) + Natural (get_number_of_elements (sys.messages)) + Natural (get_number_of_elements (sys.buffers)); if schedule_with_resources then object_number := object_number + Natural (get_number_of_elements (sys.resources)); end if; if customized_simulation then if object_number > editor_config.max_time_line_to_display then graphical_editor.select_time_line.gtk_new (graphical_editor.select_time_line.select_time_line, sys, call_customized_simulation'access); Show_All (graphical_editor.select_time_line.select_time_line); else call_customized_simulation; end if; else if object_number > editor_config.max_time_line_to_display then graphical_editor.select_time_line.gtk_new (graphical_editor.select_time_line.select_time_line, sys, call_uncustomized_simulation'access); Show_All (graphical_editor.select_time_line.select_time_line); else call_uncustomized_simulation; end if; end if; customized_simulation := False; end read_scheduling_duration_and_draw_scheduling; procedure call_processor_analysis (name : Unbounded_String) is response_list : framework_response_table; request_list : framework_request_table; a_request : framework_request; a_param : parameter_ptr; begin if preemption_from_simulation then initialize (response_list); initialize (request_list); initialize (a_request); initialize (a_request.param); a_request.target := name; a_request.statement := scheduling_simulation_preemption_number; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; if context_switch_from_simulation then initialize (response_list); initialize (request_list); initialize (a_request); initialize (a_request.param); a_request.target := name; a_request.statement := scheduling_simulation_context_switch_number; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; if (response_time_from_simulation (worst_case) or response_time_from_simulation (best_case) or response_time_from_simulation (average_case) or response_time_from_simulation (plot_case)) then initialize (a_request); initialize (a_request.param); initialize (response_list); initialize (request_list); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("worst_case"); if response_time_from_simulation (worst_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("best_case"); if response_time_from_simulation (best_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("average_case"); if response_time_from_simulation (average_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_request.target := name; a_request.statement := scheduling_simulation_response_time; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; if (blocking_time_from_simulation (worst_case) or blocking_time_from_simulation (best_case) or blocking_time_from_simulation (average_case) or blocking_time_from_simulation (plot_case)) then initialize (a_request); initialize (a_request.param); initialize (response_list); initialize (request_list); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("worst_case"); if blocking_time_from_simulation (worst_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("best_case"); if blocking_time_from_simulation (best_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("average_case"); if blocking_time_from_simulation (average_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_request.target := name; a_request.statement := scheduling_simulation_blocking_time; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; end call_processor_analysis; procedure call_uncustomized_simulation is response_list : framework_response_table; request_list : framework_request_table; a_request : framework_request; a_param : parameter_ptr; begin initialize (a_request); initialize (a_request.param); a_request.statement := scheduling_simulation_time_line; a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("period"); a_param.integer_value := max_period; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_offsets"); a_param.boolean_value := schedule_with_offsets; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_precedencies"); a_param.boolean_value := schedule_with_precedencies; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("minimize_preemption"); a_param.boolean_value := minimize_preemption; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_jitters"); a_param.boolean_value := schedule_with_jitters; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_resources"); a_param.boolean_value := schedule_with_resources; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_crpd"); a_param.boolean_value := schedule_with_crpd; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("anomaly_detection"); a_param.boolean_value := anomaly_detection; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("dvfs"); a_param.boolean_value := dvfs; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("predictable"); a_param.boolean_value := is_global_predictable_seed; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_discard_missed_deadlines"); a_param.boolean_value := schedule_with_discard_missed_deadlines; add (a_request.param, a_param); if has_global_seed then a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("seed_value"); a_param.integer_value := global_seed_value; add (a_request.param, a_param); end if; for i in time_unit_event_type'range loop a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String (to_lower (i'img)); if generate_events (i) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); end loop; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title_and_text (response_list); initialize (a_request); initialize (a_request.param); initialize (response_list); initialize (request_list); a_request.target := empty_string; a_request.statement := scheduling_simulation_basics; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title_and_text (response_list); graphical_editor.draw_scheduling.draw_scheduling_events (stop_draw, start_draw); end call_uncustomized_simulation; procedure call_customized_simulation is a_processor : generic_processor_ptr; my_processor_iterator : processors_iterator; response_list : framework_response_table; request_list : framework_request_table; a_request : framework_request; a_param : parameter_ptr; begin initialize (a_request); initialize (a_request.param); a_request.statement := scheduling_simulation_time_line; a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("period"); a_param.integer_value := max_period; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_offsets"); a_param.boolean_value := schedule_with_offsets; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("minimize_preemption"); a_param.boolean_value := minimize_preemption; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_jitters"); a_param.boolean_value := schedule_with_jitters; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_precedencies"); a_param.boolean_value := schedule_with_precedencies; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_resources"); a_param.boolean_value := schedule_with_resources; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_crpd"); a_param.boolean_value := schedule_with_crpd; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("anomaly_detection"); a_param.boolean_value := anomaly_detection; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("dvfs"); a_param.boolean_value := dvfs; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("predictable"); a_param.boolean_value := is_global_predictable_seed; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_discard_missed_deadlines"); a_param.boolean_value := schedule_with_discard_missed_deadlines; add (a_request.param, a_param); if has_global_seed then a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("seed_value"); a_param.integer_value := global_seed_value; add (a_request.param, a_param); end if; for i in time_unit_event_type'range loop a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String (to_lower (i'img)); if generate_events (i) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); end loop; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); -- Put to the screen the resulting event table -- if schedule_and_display_event_table then display_scheduling (framework.sched); end if; write_title_and_text (response_list); graphical_editor.draw_scheduling.draw_scheduling_events (stop_draw, start_draw); -- export event table in the targeted XML file -- if schedule_and_export_event_table then write_to_xml_file (framework.sched, sys, xml_event_table_file_name); end if; if schedule_all_processors = False then call_processor_analysis (last_selected_processor); else reset_iterator (sys.processors, my_processor_iterator); loop current_element (sys.processors, a_processor, my_processor_iterator); call_processor_analysis (a_processor.name); exit when is_last_element (sys.processors, my_processor_iterator); next_element (sys.processors, my_processor_iterator); end loop; end if; -- Now run, event analyzers, -- if run_event_analyzer_from_simulation then initialize (response_list); initialize (request_list); initialize (a_request); a_request.statement := scheduling_simulation_run_event_handler; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title_and_text (response_list); end if; end call_customized_simulation; procedure close_widget (object : access gtkada_builder_record'class) is my_widget : gobject; begin my_widget := Get_Object (object, "window1"); Destroy(gtk_widget (my_widget)); Gtk.Main.Main_Quit; end close_widget; procedure read_scheduling_customization_widget (object : access gtkada_builder_record'class) is begin close_widget (object); customized_simulation := True; last_selected_processor := To_Unbounded_String (Get_Active_Text (gtk_combo_box_text (Get_Object (object, "combobox1")))); schedule_and_export_event_table := Get_Active (gtk_check_button (Get_Object (object, "checkbutton12"))); schedule_all_processors := Get_Active (gtk_check_button (Get_Object (object, "checkbutton9"))); run_event_analyzer_from_simulation := Get_Active (gtk_check_button (Get_Object (object, "checkbutton10"))); preemption_from_simulation := Get_Active (gtk_check_button (Get_Object (object, "checkbutton14"))); context_switch_from_simulation := Get_Active (gtk_check_button (Get_Object (object, "checkbutton13"))); schedule_and_display_event_table := Get_Active (gtk_check_button (Get_Object (object, "checkbutton11"))); schedule_and_export_event_table := Get_Active (gtk_check_button (Get_Object (object, "checkbutton12"))); event_table_file_name := get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer1"))); xml_event_table_file_name := get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer1"))); response_time_from_simulation (worst_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton1"))); response_time_from_simulation (best_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton3"))); response_time_from_simulation (average_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton5"))); response_time_from_simulation (plot_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton7"))); blocking_time_from_simulation (worst_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton2"))); blocking_time_from_simulation (best_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton4"))); blocking_time_from_simulation (average_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton6"))); blocking_time_from_simulation (plot_case) := Get_Active (gtk_check_button (Get_Object (object, "checkbutton8"))); -- Do controls : if everything is ok, open next windows -- Otherwise continue the current windows -- if schedule_and_export_event_table then if xml_event_table_file_name = empty_string then show_message_box (lb_event_table_file_name (current_language) & lb_mandatory (current_language)); return; end if; end if; -- Display the widget to select scheduling simulation duration -- show_scheduling_simulation_duration_widget(object); end read_scheduling_customization_widget; procedure show_scheduling_simulation_duration_widget (object : access gtkada_builder_record'class) is builder : gtkada_builder; error : aliased Glib.Error.gerror; diag : guint; buf1 : gobject; buf2 : gobject; buf3 : gobject; a_task : generic_task_ptr; iterator1 : tasks_iterator; a_processor : generic_processor_ptr; iterator2 : processors_iterator; max_period : Natural := 0; period : Natural := 0; max_draw : Natural := Max_Time_Line_Size_To_Display; validate : Boolean; double_period : Double; msg : Unbounded_String; begin if (get_number_of_elements (sys.tasks) = 0) then show_message_box (lb_define_tasks_before (current_language)); return; end if; Gtk.Main.Init; Gtk_New (builder); diag := Add_From_File (builder, To_String (glade_path) & "scheduling_simulation_draw.glade", error'access); if diag = 0 then Ada.Text_IO.Put_Line ("Error : " & Get_Message (error)); Error_Free (error); return; end if; buf1 := Get_Object (builder, "textbuffer1"); buf2 := Get_Object (builder, "textbuffer2"); buf3 := Get_Object (builder, "textbuffer3"); reset_iterator (sys.tasks, iterator1); if not is_empty (sys.tasks) then loop current_element (sys.tasks, a_task, iterator1); if (a_task.task_type = periodic_type) or (a_task.task_type = poisson_type) or (a_task.task_type = sporadic_type) then max_period := Natural'max (max_period, periodic_task_ptr (a_task).period); else max_period := Natural'max (max_period, a_task.deadline); end if; exit when is_last_element (sys.tasks, iterator1); next_element (sys.tasks, iterator1); end loop; end if; reset_iterator (sys.processors, iterator2); loop current_element (sys.processors, a_processor, iterator2); if (get_number_of_task_from_processor (sys.tasks, a_processor.name) /= 0) then begin calculate_feasibility_interval (sys, a_processor, validate, double_period, msg); period := Natural (double_period); if period > max_period then max_period := period; end if; exception when others => null; end; end if; exit when is_last_element (sys.processors, iterator2); next_element (sys.processors, iterator2); end loop; if (max_period < max_draw) then max_draw := max_period; end if; Set_Text (gtk_text_buffer (buf1), max_period'img); Set_Text (gtk_text_buffer (buf2), "0"); Set_Text (gtk_text_buffer (buf3), max_draw'img); Register_Handler (Builder => builder, Handler_Name => "on_button1_clicked", Handler => graphical_editor.scheduling_simulations_callbacks .read_scheduling_duration_and_draw_scheduling' access); Register_Handler (Builder => builder, Handler_Name => "on_button2_clicked", Handler => graphical_editor.scheduling_simulations_callbacks.close_widget' access); graphical_editor.draw_scheduling.clear_time_line; Do_Connect (builder); declare Custom_Widget : constant Gtk.Widget.Gtk_Widget := Gtk.Widget.Gtk_Widget (Get_Object (Builder, "window1")); begin Gtk.Widget.Show_All (Custom_Widget); end; Gtk.Main.Main; Unref (builder); end show_scheduling_simulation_duration_widget; procedure show_scheduling_simulation_zoom_in (object : access gtkada_builder_record'class) is begin if zoom_level < zoom_range'last then zoom_level := zoom_level + 1; Set_Text (zoom_level_entry, To_String (display_zoom)); end if; if (sched.nb_entries /= 0) then graphical_editor.draw_scheduling.clear_time_line; graphical_editor.draw_scheduling.draw_scheduling_events (stop_draw, start_draw); end if; end show_scheduling_simulation_zoom_in; procedure show_scheduling_simulation_zoom_out (object : access gtkada_builder_record'class) is begin if zoom_level > zoom_range'first then zoom_level := zoom_level - 1; Set_Text (zoom_level_entry, To_String (display_zoom)); end if; if (sched.nb_entries /= 0) then graphical_editor.draw_scheduling.clear_time_line; graphical_editor.draw_scheduling.draw_scheduling_events (stop_draw, start_draw); end if; end show_scheduling_simulation_zoom_out; procedure show_scheduling_simulation_zoom_reset (object : access gtkada_builder_record'class) is begin zoom_level := 0; Set_Text (zoom_level_entry, To_String (display_zoom)); if (sched.nb_entries /= 0) then graphical_editor.draw_scheduling.clear_time_line; graphical_editor.draw_scheduling.draw_scheduling_events (stop_draw, start_draw); end if; end show_scheduling_simulation_zoom_reset; procedure show_scheduling_simulation_zoom_fit (object : access gtkada_builder_record'class) is width : gint; height : gint; target_zoom : gDouble; begin Get_Size (window_cheddar, width, height); if (sched.nb_entries /= 0) then target_zoom := gdouble(width) / gDouble (scheduling_base_period); zoom_level := zoom_range'first; for i in zoom_range'range loop if zoom_values (i) * timeunit_margin / 100.0 < target_zoom then zoom_level := i; end if; end loop; Set_Text (zoom_level_entry, To_String (display_zoom)); graphical_editor.draw_scheduling.clear_time_line; graphical_editor.draw_scheduling.draw_scheduling_events (stop_draw, start_draw); end if; end show_scheduling_simulation_zoom_fit; end graphical_editor.scheduling_simulations_callbacks;