GtkAda
Button Clicks and Containers
Since I reported that I was beginning to understand GtkAda
I've found that I had more to learn.
I've gone further to display a group of buttons at different
positions within the display window and to field button clicks to hide and show
a button as well as to display text on the button in different fonts, sizes,
colors and font styles.
The examples to hide a button all seemed to be to hide the
button that was clicked. So it took a
little bit to figure out how to reference a different button instead. (How can you click on a hidden button to
redisplay it?) And even more time to
find out how to select the font, font size, etc. The examples just didn't seem to compile. Maybe I've developed old age disease but it
took me a while to come up with what would compile. (The GtkAda code makes use of some esoteric Ada constructs.) But when I got the solution it became easy.
I then wanted to put the button widgets into a parent
container widget since this is standard practice in aircraft ARINC 661
standard. Thus being able to hide the
parent widget to hide all its child widgets.
However, looking at the GtkAda types of containers (vertical boxes, horizontal
boxes, grids) they all wanted to place the widget themselves whereas A661 has
widgets placed within their container by their x, y position from the container
boundary.
So I wrote my own container widget generic package so as to
be able to hide or show the container and have its widgets hidden or
visible. After my attempts to use
GtkAda this was a snap. Although it
doesn't yet place the widgets relative to the containers position or even
specify a position for the container.
So the widgets are still placed relative to the window.
This resulted in the following set of views.
First I have a view with only one button (the one not in the
container) visible. To do this I had to
first do a Show All on the window and all its contents and then do a hide of
the container. This doesn't flash the
buttons since GtkAda doesn't act on the Show All until the signal handling loop
is activated. View 1 shows the result.
Next I clicked on the Sixth button which is tied to an event
handler that toggles the display of the container from hidden to displayed or
vice versa. See View 2 where buttons
First thru Fifth are also displayed in their different sizes, fonts and
positions.
Next I clicked the First button which is tied to an event
handler that toggles the display of the second button. The results are shown in View 3 where the
Second button is no longer displayed.
To illustrate how the Second button will remain hidden when
the container is hidden and then redisplayed, the Sixth button was again
clicked resulting in View 5. Then the
First button was clicked to redisplay the Second button as in the final view.
View 1
View 2
View 3
View 4
View 5
View 6
For those interested, the applicable code follows.
with Gtk;
with Gtk.Box;
with Gtk.Button;
with Gtk.Button_Box;
with Gtk.Enums;
with Gtk.Handlers;
with Gtk.Fixed;
with Gtk.Font_Button;
with Gtk.Frame;
with Gtk.Hbutton_Box;
with Gtk.Widget;
with Gtk.Window;
package body Layer1 is
Win
-- Main
Window of layer 1
:
Gtk.Window.Gtk_Window;
Frame : Gtk.Frame.Gtk_Frame;
-- where
Gtk_Frame is access all Gtk_Frame_Record'Class;
Fix : Gtk.Fixed.Gtk_Fixed;
FButtonFirst :
Gtk.Button.Gtk_Button;
FButtonSecond : Gtk.Button.Gtk_Button;
FButtonThird :
Gtk.Button.Gtk_Button;
FButtonFourth : Gtk.Button.Gtk_Button;
FButtonFifth :
Gtk.Button.Gtk_Button;
FButtonSixth : Gtk.Button.Gtk_Button;
function
Delete_Event
-- Treat
Delete button of upper right of Window
( Object :
access Gtk.Widget.Gtk_Widget_Record'Class
) return
Boolean;
-- Callback
when the main window is killed
package
Container
--| Instantiate Container for buttons First
thru Fifth
is new
Gtk_Container( Size => 10 );
-----------------------------------------------------------------------------
package
Events is
-- Treat
widget events
procedure
Treat_First_Click_Event
( Object
: access Gtk.Widget.Gtk_Widget_Record'Class );
--
Callback when the FButtonFirst button is clicked
procedure
Treat_Second_Click_Event
( Object
: access Gtk.Widget.Gtk_Widget_Record'Class );
--
Callback when the FButtonSecond button is clicked
procedure
Treat_Third_Click_Event
( Object
: access Gtk.Widget.Gtk_Widget_Record'Class );
-- Callback when the FButtonThird button is
clicked
procedure
Treat_Fourth_Click_Event
( Object
: access Gtk.Widget.Gtk_Widget_Record'Class );
-- Callback when the FButtonFourth button is
clicked
procedure
Treat_Fifth_Click_Event
( Object
: access Gtk.Widget.Gtk_Widget_Record'Class );
-- Callback when the FButtonFifth button is
clicked
procedure
Treat_Sixth_Click_Event
( Object
: access Gtk.Widget.Gtk_Widget_Record'Class );
-- Callback when the FButtonSixth button is
clicked
end Events;
-----------------------------------------------------------------------------
-- Window
events
function
Delete_Event
( Object :
access Gtk.Widget.Gtk_Widget_Record'Class) return Boolean
is
pragma
Unreferenced (Object);
begin
return
True; -- to avoid killing the Layer1 window when
–- the X button is clicked
end
Delete_Event;
package
body Events is separate;
end Layer1;
with Glib;
with Gtk.Font_Chooser;
with Gtk.Font_Chooser_Widget;
with Gtk.Handlers;
with Gtk.Label;
with Pango.Font;
separate( A661.Layer1 )
procedure Initialize is
begin -- Initialize
-- Install
the configuration.
Configuration.Initialize;
-- Build
the main window.
Configuration.Build_Window( Window => 100 );
--
Initializes GtkAda
Gtk.Main.Init;
-- Create
the basic window
Gtk.Window.Gtk_New
(
Window => Win,
The_Type
=> Gtk.Enums.Window_Toplevel );
-- Position
the window in the center of the screen
Gtk.Window.Set_Position( Win, Gtk.Enums.Win_Pos_Center );
-- Set the
window size
Gtk.Window.Set_Default_Size( Win, 800, 500 );
-- Set a window title
Gtk.Window.Set_Title
( Window
=> Win,
Title => "Layer 1"
);
-- Connect
the Delete_Event procedure to the Window Close button
Return_Window_CB.Connect
( Win,
"delete_event", -- Close button event
Return_Window_CB.To_Marshaller( Delete_Event'Access) );
--------------------------
-- create a
frame
Gtk.Frame.Gtk_New( Frame );
Frame.Set_Shadow_Type( Gtk.Enums.Shadow_In );
Win.Add(
Frame );
Gtk.Fixed.Gtk_New( Fix );
Gtk.Frame.Add( Frame, Fix );
Gtk.Button.Gtk_New( FButtonFirst, "First" );
Gtk.Fixed.Put( Fix, FButtonFirst, 10, 10 );
Gtk.Label.Set_Markup
(
Gtk.Label.GTk_Label(Gtk.Button.Get_Child(FButtonFirst)),
"<span font=""Calibri""
style=""oblique"" weight=""100""
color=""green""
size=""small"">First</span>");
Window_CB.Object_Connect
(
FButtonFirst, "clicked",
Window_CB.To_Marshaller(Events.Treat_First_Click_Event'Access), Win );
declare
Added : Boolean;
ButtonRec
: Container.Widget_Record;
begin
ButtonRec.Widget :=
FButtonFirst;
ButtonRec.Id := 1001;
ButtonRec.Visible := True;
Added :=
Container.Add( Widget => ButtonRec );
end;
Gtk.Button.Gtk_New( FButtonSecond, "Second" );
Gtk.Fixed.Put( Fix, FButtonSecond, 20, 80 );
Gtk.Label.Set_Markup
(
Gtk.Label.GTk_Label(Gtk.Button.Get_Child(FButtonSecond)),
"<span font=""Arial""
style=""italic"" weight=""900""
color=""blue""
size=""xx-large"">Second</span>");
Window_CB.Object_Connect
(
FButtonSecond, "clicked",
Window_CB.To_Marshaller(Events.Treat_Second_Click_Event'Access), Win );
declare
Added : Boolean;
ButtonRec
: Container.Widget_Record;
begin
ButtonRec.Widget :=
FButtonSecond;
ButtonRec.Id := 1002;
ButtonRec.Visible := True;
Added :=
Container.Add( Widget => ButtonRec );
end;
Gtk.Button.Gtk_New( FButtonThird, "Third" );
Gtk.Fixed.Put( Fix, FButtonThird, 80, 30 );
Gtk.Label.Set_Markup
(
Gtk.Label.Gtk_Label(Gtk.Button.Get_Child(FButtonThird)),
"<span font=""Sans""
style=""normal"" weight=""800"" color=""Orange""
size=""medium"">Third</span>");
Window_CB.Object_Connect
(
FButtonThird, "clicked",
Window_CB.To_Marshaller(Events.Treat_Third_Click_Event'Access), Win );
declare
Added : Boolean;
ButtonRec
: Container.Widget_Record; --My_Button_Record;
begin
ButtonRec.Widget :=
FButtonThird;
ButtonRec.Id := 1003;
ButtonRec.Visible := True;
Added :=
Container.Add( Widget => ButtonRec );
end;
Gtk.Button.Gtk_New( FButtonFourth, "Fourth" );
Gtk.Button.Set_Size_Request( FButtonFourth, 40, 50 );
Gtk.Fixed.Put( Fix, FButtonFourth, 100, 150 );
Gtk.Label.Set_Markup
(
Gtk.Label.GTk_Label(Gtk.Button.Get_Child(FButtonFourth)),
"<span font=""Book Antiqua""
style=""normal"" weight=""300""
color=""Red"" size=""xx-small"">Fourth</span>");
Window_CB.Object_Connect
(
FButtonFourth, "clicked",
Window_CB.To_Marshaller(Events.Treat_Fourth_Click_Event'Access), Win );
declare
Added : Boolean;
ButtonRec
: Container.Widget_Record;
begin
ButtonRec.Widget := FButtonFourth;
ButtonRec.Id := 1004;
ButtonRec.Visible := True;
Added :=
Container.Add( Widget => ButtonRec );
end;
Gtk.Button.Gtk_New( FButtonFifth, "Fifth" );
Gtk.Button.Set_Size_Request( FButtonFifth, 150, 50 );
Gtk.Fixed.Put( Fix, FButtonFifth, 10, 280 );
Gtk.Label.Set_Markup
(
Gtk.Label.GTk_Label(Gtk.Button.Get_Child(FButtonFifth)),
"<span font=""Courier New""
style=""normal"" weight=""900""
color=""Violet""
size=""medium"">Fifth</span>");
Window_CB.Object_Connect
(
FButtonFifth, "clicked",
Window_CB.To_Marshaller(Events.Treat_Fifth_Click_Event'Access), Win );
declare
Added : Boolean;
ButtonRec
: Container.Widget_Record; --My_Button_Record;
begin
ButtonRec.Widget := FButtonFifth;
ButtonRec.Id := 1005;
ButtonRec.Visible := True;
Added :=
Container.Add( Widget => ButtonRec );
end;
Gtk.Button.Gtk_New( FButtonSixth, "Sixth" );
Gtk.Button.Set_Size_Request( FButtonSixth, 150, 50 );
Gtk.Fixed.Put( Fix, FButtonSixth, 200, 280 );
Gtk.Label.Set_Markup
(
Gtk.Label.GTk_Label(Gtk.Button.Get_Child(FButtonSixth)),
"<span font=""Tahoma""
style=""normal"" weight=""900""
color=""Purple""
size=""large"">Sixth</span>");
Window_CB.Object_Connect
( FButtonSixth,
"clicked",
Window_CB.To_Marshaller(Events.Treat_Sixth_Click_Event'Access), Win );
-- Note:
Not part of the Container since it must stay visible for alternate
-- clicks to show the container again.
–-> code from Parse that displays the window when
App2
–- sends the
command to do so
--
Show the window.
Gtk.Window.Show_All( Win );
--
Hide the container and its widgets to start
Container.Hide;
--
Activate the signal handling loop to allow use of click events
Gtk.Main.Main;
end Initialize;
package body Events is
-----------------------------------------------------------------------------
-- Button
click event handlers
procedure
Treat_First_Click_Event
( Object :
access Gtk.Widget.Gtk_Widget_Record'Class
) is
-- Callback when the FButtonFirst button is
clicked
pragma
Unreferenced( Object );
begin --
Treat_First_Click_Event
if
Container.Is_Visible( Widget => FButtonSecond ) then
Container.Hide( Widget => FButtonSecond );
else
Container.Show( Widget => FButtonSecond );
end if;
end
Treat_First_Click_Event;
procedure
Treat_Sixth_Click_Event
( Object :
access Gtk.Widget.Gtk_Widget_Record'Class
) is
-- Callback when the FButtonSixth button is
clicked
pragma
Unreferenced( Object );
begin --
Treat_Sixth_Click_Event
Console.Write( "Button Sixth clicked" );
if
Container.Is_Visible then
Container.Hide;
else --
supposed to be visible, refresh it
Container.Show;
end if;
end
Treat_Sixth_Click_Event;
end Events;
with Gtk.Button; -- change to Gtk.Widget
generic
-- Overview:
-- Generic
package to group widgets as their parent.
--
-- Widgets
can be added to the container and then the widgets
-- can be hidden
or made visible as a group by invoking the
-- Hide or
Show procedure of the container.
--
-- The
container is different from a GtkAda container package
-- since
there is no restriction as to how the widgets can be
-- placed
in relation to each other.
-- Notes:
--
Parameter to supply when instantiate an instance of a topic.
Size
-- Maximum
number of widgets allowed to be added to the container.
: Integer;
package Gtk_Container is
-- Treat a group/array of widgets as being in a
container as far as hiding
-- or making visible.
type
Widget_Id_Type
--| Define
16-bit widget identifier
is new
Integer range 0..32767;
for
Widget_Id_Type'size use 16; -- bits
-- Note:
Needs its own declaration since circularity results if use A661.Types
type
Widget_Record is new Gtk.Button.Gtk_Button_Record with record
Widget : Gtk.Button.Gtk_Button;
--<<< will need to generalize to a Gtk
Widget >>>
Id : Widget_Id_Type;
Visible :
Boolean;
end record;
type Widget
is access all Widget_Record'Class;
function
Add
( Widget :
in Widget_Record
--will
want a general type (from Configuration) rather than just for buttons
) return
Boolean;
-- Add a
widget to the container.
-- Return
True if the Add was successful
procedure
Hide;
-- Hide all
the widgets of the container
procedure
Hide
( Widget :
in Gtk.Button.Gtk_Button
-- Widget
being hidden
);
-- Hide the
named widget of the container
procedure
Show;
-- Show all
the widgets of the container
procedure
Show
( Widget :
in Gtk.Button.Gtk_Button
-- Widget
being shown
);
-- Show the
named widget of the container
function
Is_Visible
return
Boolean;
-- Returns
whether the container is set to be visible
function
Is_Visible
( Widget :
in Gtk.Button.Gtk_Button
-- Widget
being checked
) return
Boolean;
-- Returns
whether the widget is set to be visible
end Gtk_Container;
with Gtk.Widget;
package body Gtk_Container is
type
Widget_Count_Type
is new
Integer range 0..Size; --Max;
type
Widget_Array_Type
is array
(1..Widget_Count_Type'last) of Widget_Record;
type
Widget_List_Type
is record
Count : Widget_Count_Type;
Visible :
Boolean;
List : Widget_Array_Type;
end record;
type
Container_Type
is record
Visible :
Boolean;
-- True
if container has been requested to be visible
Data : Widget_List_Type;
-- Data
concerning the widgets of the container
end record;
Container
--
Container attributes including its widgets
: Container_Type;
-----------------------------------------------------------------------------
function
Add
( Widget :
in Widget_Record
--will want
a general type
) return
Boolean is
-- Note:
The initialized Visible condition of the Widget is contained in
-- the record.
begin --
Add
if
Container.Data.Count < Widget_Count_Type'last then
Container.Data.Count := Container.Data.Count + 1;
Container.Data.List(Container.Data.Count) := Widget;
return
True;
else
return
False; -- widget not added
end if;
end Add;
procedure
Hide is
-- Hide all
the widgets of the container but leave the status of the
--
individual widgets unchanged so when the container is made visible
-- the
widgets that were hidden prior to hiding the container will
-- remain
hidden.
begin --
Hide
for I in
1..Container.Data.Count loop
Gtk.Widget.Hide( Gtk.Widget.Gtk_Widget(Container.Data.List(I).Widget) );
end loop;
Container.Visible := False;
end Hide;
procedure
Hide
( Widget :
in Gtk.Button.Gtk_Button
) is
-- Hide the
Widget
use type
Gtk.Button.Gtk_Button;
begin --
Hide
for I in
1..Container.Data.Count loop
if
Widget = Container.Data.List(I).Widget then
if
Container.Data.List(I).Visible then
Gtk.Widget.Hide( Gtk.Widget.Gtk_Widget(Widget) );
Container.Data.List(I).Visible := False;
exit; -- loop
--else
already hidden
end
if;
end if;
end loop;
end Hide;
procedure
Show is
-- Show all the widgets of the container that
weren't hidden before the
-- Hide of
the container was done
begin --
Show
if not
Container.Visible then
for I
in 1..Container.Data.Count loop
if
Container.Data.List(I).Visible then -- reshow the widget
Gtk.Widget.Show( Gtk.Widget.Gtk_Widget(Container.Data.List(I).Widget) );
--else
keep hidden
end
if;
end
loop;
end if;
Container.Visible := True;
end Show;
procedure
Show
( Widget :
in Gtk.Button.Gtk_Button
) is
-- Show the
Widget. Refresh it as supposed to be
visible already.
use type
Gtk.Button.Gtk_Button;
begin --
Show
for I in
1..Container.Data.Count loop
if
Widget = Container.Data.List(I).Widget then
Gtk.Widget.Show( Gtk.Widget.Gtk_Widget(Widget) );
Container.Data.List(I).Visible := True;
exit;
-- loop
end if;
end loop;
end Show;
function
Is_Visible
return
Boolean is
-- Returns
whether the container is set to be visible
begin -- Is_Visible
return
Container.Visible;
end
Is_Visible;
function
Is_Visible
( Widget :
in Gtk.Button.Gtk_Button
-- Widget
being checked
) return
Boolean is
-- Returns
whether the widget is set to be visible
use type
Gtk.Button.Gtk_Button;
begin --
Is_Visible
for I in
1..Container.Data.Count loop
if
Widget = Container.Data.List(I).Widget then
return Container.Data.List(I).Visible;
end if;
end loop;
return
False; -- widget isn't in container
end
Is_Visible;
begin -- at instantiation
Container.Visible := False; -- assume container hidden
Container.Data.Count := 0;
end Gtk_Container;
No comments:
Post a Comment