------------------------------------------------------------------------------ -- GtkAda - Ada95 binding for Gtk+/Gnome -- -- -- -- Copyright (C) 2001-2022, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- -- Software Foundation; either version 3, or (at your option) any later -- -- version. This library is distributed in the hope that it will be useful, -- -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- -- -- -- As a special exception under Section 7 of GPL version 3, you are granted -- -- additional permissions described in the GCC Runtime Library Exception, -- -- version 3.1, as published by the Free Software Foundation. -- -- -- -- You should have received a copy of the GNU General Public License and -- -- a copy of the GCC Runtime Library Exception along with this program; -- -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- -- . -- -- -- ------------------------------------------------------------------------------ -- -- This widget organizes its children into resizable panes. Within each -- pane, multiple children can be put, and they will be accessible through -- a notebook. -- -- Layout containers with Ada.Containers.Indefinite_Hashed_Maps; with Ada.Strings.Hash; with Ada.Tags; with GNAT.Strings; with Glib; use Glib; with Glib.Simple_Action; with Glib.Menu; with Glib.Object; with Glib.Xml_Int; with Glib.Values; with Gdk.Event; with Gdk.Pixbuf; with Gdk.RGBA; with Gdk.Rectangle; with Gtk.Accel_Group; with Gtk.Application; with Gtk.Box; with Gtk.Container; with Gtk.Enums; with Gtk.Event_Box; with Gtk.Handlers; with Gtk.Image; with Gtk.Label; with Gtk.Menu; with Gtk.Notebook; with Gtk.Radio_Menu_Item; with Gtk.Css_Provider; with Gtk.Widget; use Gtk.Widget; with Gtk.Window; with Gtkada.Handlers; with Gtkada.Multi_Paned; with Pango.Font; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package Gtkada.MDI is type MDI_Window_Record is new Gtk.Widget.Gtk_Widget_Record with private; type MDI_Window is access all MDI_Window_Record'Class; -- Although this widget is implemented as a gtk_layout, you shouldn't -- use the standard Gtk_Layout functions like Put and Move yourself. type MDI_Child_Record is new Gtk.Event_Box.Gtk_Event_Box_Record with private; type MDI_Child is access all MDI_Child_Record'Class; pragma No_Strict_Aliasing (MDI_Child); -- A child of the MDI, that encapsulates the widgets you have put in the -- MDI window. -- You can easily convert from this to the initial widget using the -- functions Find_MDI_Child and Get_Widget. type MDI_Child_Array is array (Natural range <>) of MDI_Child; No_Children : constant MDI_Child_Array := (1 .. 0 => null); type State_Type is (Normal, Floating, Invisible); -- This type indicates the state of an item in the MDI: -- - Normal: the item can be manipulated (moved and resized) by the user. -- It is found either in the middle notebook (maximized items), or -- in the layout. -- - Floating: the item has its own toplevel window, and is thus managed -- by the window manager. -- - Invisible: the child was part of a previously displayed perspective, -- but is no longer in the current perspective. We still keep it to -- reuse it when switching back to the previous perspective. type Allowed_Areas is (Central_Only, Sides_Only, Both); -- Where is a child allowed to be moved ? procedure Gtk_New (MDI : out MDI_Window; Group : access Gtk.Accel_Group.Gtk_Accel_Group_Record'Class; Independent_Perspectives : Boolean := False); -- Create a new MDI window. -- Note that it is recommended that you modify the style (Set_Background -- in State_Normal) to have a different color. -- You should call Setup_Toplevel_Window once you have added the MDI to a -- toplevel widget, so that focus is correctly handled when the toplevel -- window gains the focus -- When Independent_Perspectives is True, switching perspectives will not -- preserve any window. Otherwise, the windows that are in the central -- area will be preserved in the new perspective. procedure Initialize (MDI : access MDI_Window_Record'Class; Group : access Gtk.Accel_Group.Gtk_Accel_Group_Record'Class; Independent_Perspectives : Boolean := False); -- Internal initialization function. -- See the section "Creating your own widgets" in the documentation. function Get_Type return Glib.GType; function Child_Get_Type return Glib.GType; -- Return the type describing the MDI or a MDI_Child procedure Setup_Toplevel_Window (MDI : access MDI_Window_Record; Parent : access Gtk.Window.Gtk_Window_Record'Class); -- Setup Parent to properly handle focus when the window manager changes -- the window that currently has the focus. -- Parent must be the toplevel window that contains the MDI. type Show_Tabs_Policy_Enum is (Always, Never, Automatic); type Title_Bars_Policy is (Always, Never, Central_Only); type Tab_Orientation_Type is (Automatic, Horizontal, Bottom_To_Top, Top_To_Bottom); procedure Configure (MDI : access MDI_Window_Record; Opaque_Resize : Boolean := False; Close_Floating_Is_Unfloat : Boolean := True; Title_Font : Pango.Font.Pango_Font_Description := null; Title_Bar_Color : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; Focus_Title_Color : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; Draw_Title_Bars : Title_Bars_Policy := Always; Tabs_Position : Gtk.Enums.Gtk_Position_Type := Gtk.Enums.Pos_Top; Show_Tabs_Policy : Show_Tabs_Policy_Enum := Automatic; Homogeneous_Tabs : Boolean := True; Tabs_Orientation : Tab_Orientation_Type := Automatic); -- Change the setup of the MDI. -- Close_Floating_Is_Unfloat, if True, means that closing a floating child -- will put it back in the MDI instead of destroying it (unless its flag -- Always_Destroy_Float is set). -- Title_Font is the font used in the title bars (if null, "sans 8" -- is used). -- The colors, when Null_Color, will not change the current setup. -- If Draw_Title_Bars is False, then no extra title bar will be displayed -- for the MDI children when they are maximized. This saves space on the -- screen. However, the notebook tabs will be highlighted with -- Title_Bar_Color in exchange. -- Tabs_Position indicates where the notebook tabs should be put. -- Tabs_Orientation indicates how the notebook tabs should be rotated. -- Show_Tabs_Policy indicates when the notebook tabs should be displayed. -- -- If Homogeneous_Tabs is true, then the notebook tabs will only use their -- natural size when they all fit in the notebook's width. Otherwise, they -- are resized (and ellipsized as needed) so that more of them show. -- Changing this setup requires a restart of the MDI. -- -- Calling configure will define a default CSS to properly theme the MDI. -- This CSS relies on mainly two widget classes to behave: -- * mdifocused, corresponding to the notebook having the focus -- * mdititle, corresponding to the title bar -- This default CSS renders the active tab of the active notebook with the -- color defined in Focus_Title_Color. Same for the color of the title -- bar (uses Title_Bar_Color for non-active title bar). -- This behavior can at any point be overridden by users by defining -- their own and load it at run-time. -- -- Since the move to gtk3, the highlighting of the current tab is left to -- the gtk+ theme, rather than overwritten in this package. This permits a -- better integration with the user's theme. It is possible for -- applications to provide their own CSS, though, using -- Gtkada.Style.Load_Css_File. Here is an example of such a CSS, which -- highlights the current tab in the notebook that currently has the focus: -- -- @define-color mdi-tab-color grey; -- @define-color mdi-active-tab-color blue; -- .mdititle { -- border-width: 2px; -- background-image: -gtk-gradient( -- linear, left top, left bottom, -- from(@mdi-tab-color), to(shade(@mdi-tab-color, 1.1))); -- } -- .mdifocused .mdititle { -- background-image: -gtk-gradient( -- linear, left top, left bottom, -- from(@mdi-active-tab-color), -- to(shade(@mdi-active-tab-color, 1.1))); -- .mdi tab GtkLabel, .mdi tab GtkImage { opacity: 0.8 } -- .mdifocused tab GtkLabel, .mdifocused tab GtkImage { opacity: 1.0} function Independent_Perspectives (MDI : access MDI_Window_Record) return Boolean; -- Whether the MDI is using independent perspectives ------------- -- Windows -- ------------- type Child_Flags is mod 2 ** 7; Destroy_Button : constant Child_Flags := 2 ** 2; Float_As_Transient : constant Child_Flags := 2 ** 3; Float_To_Main : constant Child_Flags := 2 ** 5; Always_Destroy_Float : constant Child_Flags := 2 ** 4; All_Buttons : constant Child_Flags := Destroy_Button; -- Special flags to set up the widgets: The first is the buttons -- that should be displayed in the title bar of the MDI children. If -- Float_As_Transient is set, then the child will be set up as a transient -- window when floating: on most window managers, it will stay on top of -- the MDI, but the window will have less decorations in its title bar, -- in particular no destroy button. In such a case, will close the -- window, or unfloat it depending on the MDI's setup, as is the case for -- all dialogs in GtkAda. The MDI's setup will be ignored (and the child -- always destroyed when Esc is pressed) if Always_Destroy_Float is true. -- Float_To_Main yields the same behavior as Float_As_Transient, except -- that the floated child will always be attached to the main window. -- What this means is that the child will stay on top of the MDI, and will -- persist if you close the current MDI child. type Child_Group is new Positive; Group_Default : constant Child_Group := 1; Group_Any : constant Child_Group := Child_Group'Last; -- This type can be used to help group windows by type within the MDI. -- Group_Default as a special status when computing the initial position -- for a window. But you can create your own groups as needed, so that for -- instance editors tend to be grouped with other editors, graphs with -- other graphs,... depending on your application. -- The group has an impact when the last window from a notebook is closed: -- If the window belongs to Group_Default, and it is the last of its group, -- then the space currently occupied by that window is not reclaimed, and -- therefore an empty area will exist in the MDI. The idea is that for -- instance editors typically play a special role in an integrated -- development environment, and the users like to have them in the center -- of the window. When closing the last editor, they do not want the side -- windows (browsers, consoles,...) to take up that space that should -- really only be used for editors. -- To get such a behavior, editors should belong to Group_Default, and all -- other windows to custom groups. -- -- Do not use Group_Any, it is used internally with special meanings. procedure Gtk_New (Child : out MDI_Child; Widget : access Gtk.Widget.Gtk_Widget_Record'Class; Flags : Child_Flags := All_Buttons; Group : Child_Group := Group_Default; Focus_Widget : Gtk.Widget.Gtk_Widget := null; Areas : Allowed_Areas := Both); -- Create a new MDI child that contains widget. -- Widget mustn't be of type Gtk_Window. -- -- You shouldn't access Widget directly afterwards, but should manipulate -- Child only. However, as a special exception, you can still pass Widget -- as a parameter to the subprograms in this package to manipulate it (e.g. -- in Raise_Child, ...) -- -- If Focus_Widget is not null, this is the widget that gets the keyboard -- focus when the child is selected. procedure Initialize (Child : access MDI_Child_Record'Class; Widget : access Gtk.Widget.Gtk_Widget_Record'Class; Flags : Child_Flags := All_Buttons; Group : Child_Group := Group_Default; Focus_Widget : Gtk.Widget.Gtk_Widget := null; Areas : Allowed_Areas := Both); -- Internal initialization function. -- See the section "Creating your own widgets" in the documentation. procedure Change_Group (Child : not null access MDI_Child_Record'Class; Group : Child_Group); -- Change the child's MDI group. type Child_Position is (Position_Automatic, Position_Bottom, Position_Top, Position_Left, Position_Right, Position_Float); subtype Side_Position is Child_Position range Position_Bottom .. Position_Right; -- The initial position of windows within the MDI. -- In all cases, the initial location for a window is computed with the -- following algorithm. This algorithm is designed with the notion of -- groups of windows in mind, so that some windows (typically editors) have -- a special status. -- - If Position_Float, make the window floating -- - If another window with the same Group is already in the MDI, the -- new window is put on top of it. -- - Otherwise, if Position_Automatic, if an empty area exists within -- the MDI, the new window is put in that area. -- - Else if the Position is Bottom .. Right, the new window is put -- below all others (resp. to the top, left or right) -- - Else the window is put on top of the currently selected window procedure Put (MDI : access MDI_Window_Record; Child : access MDI_Child_Record'Class; Initial_Position : Child_Position := Position_Automatic; Position_At_Mouse : Boolean := True; X, Y : Gint := 0); -- Add a new child to the MDI window, and return its embedding widget. -- Calling Put does not give the focus to the newly inserted widget. -- To do that, you should call Set_Focus_Child. -- If Initial_Position is Position_Float, then position the floating window -- under the mouse cursor, unless Position_At_Mouse is False, in which -- case position the window at X, Y. function Save_Desktop (Self : not null access MDI_Child_Record) return Glib.Xml_Int.Node_Ptr; -- A function used to save a child into the desktop. -- This is similar to Save_Desktop_Function, but is specific to a child, -- and thus more efficient. -- -- If this function returns some data, that data is saved into the XML -- for the desktop. If it returns null, however, the MDI will call each -- of the registered Save_Desktop_Function, until one returns some data. -- -- The resulting node must have a tag that is unique for this type of -- widget, and this recognized by one of the Load_Desktop_Function so -- that the child can be recreated when the desktop is loaded from XML. procedure Set_Size (MDI : access MDI_Window_Record; Child : access MDI_Child_Record'Class; Width : Glib.Gint; Height : Glib.Gint; Fixed_Size : Boolean := False); -- Forces a new size for a child. If Width or Height is left to -1, the -- matching size will be computed from the child's requisition. If they are -- left to 0, the corresponding length is left to its current value. -- If Fixed_Size is True, then the widget will not be resized when the MDI -- itself is resized (unless the user has first moved one of the handles to -- manually resize it). Otherwise, it will grow proportionally with the -- rest of the MDI. procedure Close (MDI : access MDI_Window_Record; Child : access Gtk.Widget.Gtk_Widget_Record'Class; Force : Boolean := False); -- Close the child that contains Child, and remove its window from the -- MDI. See also Close_Child if you need to close a MDI_Child itself. -- This first checks through a delete_event callback whether the child -- accepts to be closed. -- "delete_event" is not sent, and the child is automatically closed, if -- Force is set to True. procedure Set_Title (Child : not null access MDI_Child_Record; Title : String; Short_Title : String := ""); -- Set the title for a child. Title is the title put in titlebar of -- the children, whereas Short_Title is the name of the notebook tab when -- children are maximized. By default, it is the same as Title. -- -- The default title is the empty string. -- This title will be the one used for the window when the child is set to -- floating state. -- -- Title and Short_Title should preferably be UTF8-encoded, although this -- procedure will attempt to guess the encoding if the string is not valid -- UTF8. -- -- Child should already be in the MDI at this point (via a call to Put), so -- that the "use_short_titles" preference is taken into account. function Get_MDI (Child : not null access MDI_Child_Record) return MDI_Window; -- Return the MDI to which Child is associated. In Child is a floating -- child, it might not be in the MDI window itself. function Get_Title (Child : not null access MDI_Child_Record) return UTF8_String; -- Return the title for a specific child function Get_Short_Title (Child : not null access MDI_Child_Record) return UTF8_String; -- Return the name of the notebook tab used when children are maximized. function Has_Title_Bar (Child : not null access MDI_Child_Record) return Boolean; -- Whether a title bar is currently displayed for Child function Get_State (Child : not null access MDI_Child_Record) return State_Type; -- Return the current state of the child function Get_Allowed_Areas (Child : not null access MDI_Child_Record'Class) return Allowed_Areas; -- What areas the child can be put int function Get_Tab_Orientation (Child : not null access MDI_Child_Record'Class) return Tab_Orientation_Type; -- Return the child's tab orientation function Get_Tab_Label (Child : not null access MDI_Child_Record'Class) return Gtk.Label.Gtk_Label; -- Return the child's tab label function Get_Child_Notebook (Child : access MDI_Child_Record'Class) return Gtk.Notebook.Gtk_Notebook; -- Return the notebook that directly contains Child function Get_Tooltip (Child : not null access MDI_Child_Record) return String; -- Return the text to use in tooltips for the notebook tabs. -- The default (or if this function returns the empty string) the title -- of the child (Get_Title above). function Get_Tooltip_Is_Markup (Child : not null access MDI_Child_Record) return Boolean; -- Should return True if Get_Tooltip returns a string with special -- markup like "" for bold text. When this is True, special -- characters like "<" and ">" must be quoted with backslashes. procedure Set_Icon (Child : not null access MDI_Child_Record; Icon : Gdk.Pixbuf.Gdk_Pixbuf); pragma Obsolescent (Set_Icon); procedure Set_Icon_Name (Child : not null access MDI_Child_Record; Icon_Name : String); -- Associate an icon with Child. This icon is visible in the title bar, the -- notebook tabs, the Window menu and the interactive selection dialog. -- The icon is updated dynamically on the screen. -- The Icon can safely be unrefed by the caller (and should, if the pixbuf -- was newly allocated). function Get_Icon (Child : not null access MDI_Child_Record) return Gdk.Pixbuf.Gdk_Pixbuf; pragma Obsolescent (Get_Icon); function Get_Icon_Name (Child : not null access MDI_Child_Record) return String; -- Returns the icon associated with Child. The returned pixbuf is owned -- by the MDI and must not be freed by the caller. --------------------------- -- Drag and Drop support -- --------------------------- function Dnd_Data (Child : not null access MDI_Child_Record; Copy : Boolean) return MDI_Child; -- When a drag-and-drop operation took place to move a child from one -- position to the next, this function is called to know what child should -- be moved. -- As a result, the implementor can choose whether a copy of the child -- should be returned (creating a new view for an editor for instance), or -- if the child itself should be moved (the default). -- The returned MDI_Child must have been added to the MDI before it is -- returned. -- Copy is set to true if a copy operation was requested, to False if a -- simple move operation was requested. It can be ignored if Child doesn't -- know how to create a copy of itself for instance. procedure Set_Dnd_Message (MDI : access MDI_Window_Record; Message : String); -- Override the message that is displayed in the popup window while -- performing a drag. By default, this message mentions: -- "Use control to move the whole notebook" -- "Use shift to create a new view for editors" -- so might not be suitable for all applications. -- You can use markup like "..." to put keywords in bold. -- -- Passing an empty string for Message will restore the default message. procedure Child_Drag_Begin (Child : not null access MDI_Child_Record'Class; Event : Gdk.Event.Gdk_Event_Button; Areas : Allowed_Areas); -- Starts a drag-and-drop operation for the child, so that it can be put in -- some other place on the desktop. This should only be called when a -- handler for the "button_press_event" signal, passing the event itself in -- parameter. -- The Child is immediately raised and gains the focus. -- Areas indicates where the child can be dropped. This is in particular -- useful if Dnd_Data was overridden and some other child will be dropped -- instead. procedure Cancel_Child_Drag (Child : not null access MDI_Child_Record'Class); -- Cancel a drag operation started by Child_Drag_Begin. -- It doesn't call Child_Drag_Finished. procedure Child_Drag_Finished (Child : not null access MDI_Child_Record); -- Called when a drag operation is either aborted or completed. It should -- be overridden if special cleanup should be done. ----------- -- Menus -- ----------- type Tab_Contextual_Menu_Factory is access procedure (Child : access MDI_Child_Record'Class; Menu : access Gtk.Menu.Gtk_Menu_Record'Class); procedure Set_Tab_Contextual_Menu_Factory (MDI : access MDI_Window_Record; Factory : Tab_Contextual_Menu_Factory); -- Set (or unset if Factory is null) the callback to create the contextual -- menu entries when the user clicks on a notebook tab. -- Factory should add entries to Menu (which already contains the default -- entries, but you can remove them if needed). ------------------------ -- Selecting children -- ------------------------ procedure Highlight_Child (Child : not null access MDI_Child_Record; Highlight : Boolean := True); -- Highlight the child until it is selected by the user. -- The color of its menu label and of the text in the notebook tabs is -- changed. -- Nothing is done if the child is already fully visible (either in the -- active page in one of the notebooks, or the child that has the selection -- in the layout). -- This is meant to be used as a graphical note to the user that the child -- has been updated and the user should look at it. function Get_Focus_Child (MDI : access MDI_Window_Record) return MDI_Child; -- Return the child that currently has the MDI focus. -- null is returned if no child has the focus. procedure Set_Focus_Child (MDI : access MDI_Window_Record; Containing : access Gtk.Widget.Gtk_Widget_Record'Class); -- Give the focus to the child containing Containing. This will not -- Grab_Focus for the child in all cases, since you might want to give the -- focus to some specific part of your widget (an entry field,...) in some -- cases. -- Call this with Containing = null to explicitly unset the current focus -- child. procedure Set_Focus_Child (Child : not null access MDI_Child_Record); -- Make Child the active widget, and raise it at the top. procedure Check_Interactive_Selection_Dialog (MDI : access MDI_Window_Record; Event : Gdk.Event.Gdk_Event; Move_To_Next : Boolean; Only_Group : Child_Group := Group_Any); -- Open the interactive dialog for selecting windows. -- This dialog should be open as a result of a key press event. -- Move_To_Next indicates whether we want to select the next child (True) -- or the previous child (False). -- This dialog will be closed only when the key that opened it is fully -- released. For instance, if the dialog was opened as a result of -- pressing Ctrl-Tab, the dialog will only be closed when Ctrl itself is -- released. -- You can call this procedure even if a dialog is currently open. This -- simply forces a move to the next or previous child. In fact, it is -- your responsability to call this procedure when the user presses -- the keys to move between children. -- -- If Event is null, then no dialog is displayed. Instead, the next or -- previous visible child is immediately selected. In such a mode, windows -- that are not on top of their respective notebook are ignored. This can -- be used to emulate Emacs's behavior for goto-other-window. -- -- If Only_Group is specified, then only the windows from that group will -- be shown in the dialog. -- This function is not internal to the MDI since connecting to the -- key_press_event and key_release_event should be done in the gtk_window -- that contains the MDI. Otherwise, some events are intercepted by gtk+, -- for instance the key_release_events, and the key_press_events for some -- specified keys. -- It also gives the choice to the application of whether this feature is -- wanted or not. ----------------------------------------- -- MDI_Child and encapsulated children -- ----------------------------------------- function Get_Widget (Child : access MDI_Child_Record) return Gtk.Widget.Gtk_Widget; -- Return the widget that Child encapsulates. This is the widget you -- initially Put() in MDI. function Find_MDI_Child (MDI : access MDI_Window_Record; Widget : access Gtk.Widget.Gtk_Widget_Record'Class) return MDI_Child; -- Return the MDI_Child that encapsulates Widget. -- Widget must be the exact same one you gave in argument to Put. -- If the child is currently not visible in the perspective (for instance -- it was created for another perspective, but is not present in the -- current one), it is inserted automatically back in the MDI. function Find_MDI_Child_From_Widget (Widget : access Gtk.Widget.Gtk_Widget_Record'Class) return MDI_Child; -- Return the MDI child that encapsulate the parent of Widget. -- As opposed to Find_MDI_Child, Widget can be anywhere within the -- widget tree. This function properly handles floating children -- If the child is currently not visible in the perspective (for instance -- it was created for another perspective, but is not present in the -- current one), it is inserted automatically back in the MDI. function Find_MDI_Child_By_Tag (MDI : access MDI_Window_Record; Tag : Ada.Tags.Tag; Visible_Only : Boolean := False) return MDI_Child; -- Return the first child matching Tag -- If the child is currently not visible in the perspective (for instance -- it was created for another perspective, but is not present in the -- current one), it is inserted automatically back in the MDI. -- If Visible_Only is True, an invisible child is not returned. This is -- useful to check whether a child is currently visible. function Find_MDI_Child_By_Name (MDI : access MDI_Window_Record; Name : String) return MDI_Child; -- Return the first child matching Name. -- If the child is currently not visible in the perspective (for instance -- it was created for another perspective, but is not present in the -- current one), it is inserted automatically back in the MDI. type Child_Iterator is private; function First_Child (MDI : access MDI_Window_Record; Group_By_Notebook : Boolean := False; Visible_Only : Boolean := True) return Child_Iterator; -- Return an access to the first child of the MDI. -- -- If Group_By_Notebook is True, then the children are reported one after -- the other, but all the widget from the same notebook are reported in the -- same order as the notebook pages. Floating children do not belong to a -- notebook, and are also reported together. To find out to which notebook -- a child belongs, use Get_Notebook below. -- -- If Group_By_Notebook is False, it is garanteed that the first child is -- the one that currently has the focus in the MDI. The children are -- returned in the order in which they last had the focus. -- -- If Visible_Only is true, then only those children currently visible in -- the perspective are returned. The children that were part of a former -- perspective are not returned. procedure Next (Iterator : in out Child_Iterator); -- Move to the next child in the MDI function Get_Notebook (Iterator : Child_Iterator) return Gtk.Notebook.Gtk_Notebook; -- Return the notebook to which the current child belongs. null is returned -- for floating children function Get (Iterator : Child_Iterator) return MDI_Child; -- Return the child pointed to by Iterator. -- If Iterator is no longer valid, null is returned. ----------------------- -- Floating children -- ----------------------- procedure Float_Child (Child : not null access MDI_Child_Record'Class; Float : Boolean; Position_At_Mouse : Boolean := True; X, Y : Gint := 0); -- Change the floating state of a child. -- If Float is True: -- - if Position_At_Mouse is True, position the window -- under the mouse pointer. -- - if Position_At_Mouse is False, use position the window at X, Y. function Is_Floating (Child : not null access MDI_Child_Record'Class) return Boolean; -- Return True if Child is currently in a separate window procedure Set_Default_Size_For_Floating_Window (Child : not null access MDI_Child_Record; Win : not null access Gtk.Window.Gtk_Window_Record'Class; Width, Height : Glib.Gint); -- Set the default size for a floating window. -- Width and Height are the values that have bee computed, from either -- the non-floating size of the child, or from the child's preferred -- size. This procedure can be overridden, though, to force other -- values, for instance if you would like to restore a specific size. procedure Set_All_Floating_Mode (MDI : access MDI_Window_Record; All_Floating : Boolean); -- If All_Floating is set to true, the MDI will have a size of 0x0, and all -- children are set to floating. This can be used if you wish to let the -- window manager handle the windows. If All_Floating is True, children -- can no longer be maximized. procedure Use_Short_Titles_For_Floats (MDI : access MDI_Window_Record; Short_Titles : Boolean); -- If Short_Titles is set to true, only short titles will ever be used -- either in the title bars (in notebooks) or as the title for floating -- windows. procedure Create_Float_Window_For_Child (Child : not null access MDI_Child_Record; Win : out Gtk.Window.Gtk_Window; Container : out Gtk.Container.Gtk_Container); -- Creates the window to use when a child is made floating. -- This procedure provides reasonable default, but can be overridden in -- your application if you have special needs (like creating a window -- with specific menubar or decorations for instance). -- Win must be set to the window that has been created, and Container -- to the area of the window that will contain Child. -- The window's title will be set automatically. -- The window's size will be set by the MDI by calling -- Child.Set_Default_Size_For_Floating_Window. ---------------------- -- Closing children -- ---------------------- procedure Close_Child (Child : not null access MDI_Child_Record'Class; Force : Boolean := False; Focus_Same_Area : Boolean := True); -- Same as Close, but applies directly to a MDI_Child. -- If Focus_Same_Area is True, the focus will return to the previously -- focused child in the same area / notebook as Child, and which is not -- Child itself. -- Otherwise, the focus will return to the previously focused child, no -- matter its area/notebook. --------------------------- -- Reorganizing children -- --------------------------- procedure Raise_Child (Child : not null access MDI_Child_Record'Class; Give_Focus : Boolean := True); -- Put Child in the foreground. -- Note that this does not give the focus to this child, unless -- Give_Focus is set to True. If Child and the current focus child are in -- the same notebook, Child will always gain the focus, so that the focus -- is not left on an invisible window. function Is_Raised (Child : not null access MDI_Child_Record'Class) return Boolean; -- Whether the child is currently raised, ie fully visible to the user procedure Lower_Child (Child : not null access MDI_Child_Record'Class); -- Put Child in the background. -- If the children are maximized, this selected the next page from the -- notebook. procedure Give_Focus_To_Previous_Child (Child : access MDI_Child_Record'Class; From_Same_Area : Boolean := True); -- Give focus to the last child. -- If From_Same_Area is True, it will return the previously focused child -- in the same area / notebook as Child, and which is not Child itself. -- Otherwise, it will return the previously focused child, no matter its -- area/notebook. type Split_Mode is (Before, Before_Reuse, After, After_Reuse, Any_Side_Reuse); -- How a child should be split: -- If "Before", the child is put above or to the left of its current -- position. A new window is created to containing it. If the "_Reuse" -- version is used, and a window already exist at that position, the child -- will be put in it instead of creating a new one. -- Any_Side_Reuse indicates that the child will be put on either side, -- depending on where a window already exists. If there is no window on the -- side, a new one is created. procedure Split (MDI : access MDI_Window_Record; Orientation : Gtk.Enums.Gtk_Orientation; Child : MDI_Child := null; Mode : Split_Mode := Before; Width, Height : Glib.Gint := 0); -- Split the notebook containing Child (by default, the current focus -- child). -- Mode indicates in which direction the splitting should occur. If you -- are splitting a child in the central area, splitting will never reuse -- a window outside of the central area. -- Width and Height indicate the desired geometry for the splitted area, -- 0 indicate a 50/50 split. ---------------------- -- Desktop Handling -- ---------------------- -- The MDI provides a way to save desktops, i.e the list of children -- currently open in the MDI and their location. It can then restore the -- desktop at some later point. -- -- Desktops require support from the widgets that are put in the MDI. They -- need to register a function to save them and a function to recreate -- them. Using Ada streams for this didn't prove workable since some -- children might need extra parameters not available to them through -- streams. This is why the following subprograms are in a generic package, -- so that you can pass whatever parameter(s) is needed in your -- application. -- -- Desktops are saved and restored in XML trees. -- -- If you need your application to load a "default desktop" when the user -- hasn't defined one, it is recommended that you distribute an actual -- file containing this desktop. You could also create the XML tree in -- memory yourself, and thus hard-code the default desktop if need be. generic type User_Data is private; -- Generic type of parameter that is passed to all the children's save -- and restore functions. -- This package needs to be instantiated at library level package Desktop is type Menu_Registration_Procedure is access procedure (User : User_Data; Item_Name : String; Accel_Path : String); -- Function used to register in the application a static menu -- created by the MDI. procedure Set_Menu_Model (MDI : not null access MDI_Window_Record'Class; App : not null access Gtk.Application.Gtk_Application_Record'Class; Model : access Glib.Menu.Gmenu_Record'Class; User : User_Data); -- Associates a menu model with the MDI. -- This model will be filled and maintained by the MDI, to provide -- useful actions like floating/docking items, selecting items,... function Create_Menu (MDI : access MDI_Window_Record'Class; Accel_Path_Prefix : String := ""; User : User_Data; Registration : Menu_Registration_Procedure := null) return Gtk.Menu.Gtk_Menu; -- Create a dynamic menu that can then be inserted into a menu bar. This -- menu is dynamic, ie its content will changed based on the focus -- child. -- If this function is called several times, a new menu is created -- every time. Accel_Path_Prefix must be the same for every call. -- Accel_Path_Prefix is used so that the key shortcuts associated with -- these menu items can be changed dynamically by the user (see -- gtk-accel_map.ads). The prefix must start with "<" and end with ">". -- User is used for the callbacks on perspective changes, and passed to -- Load_Perspective -- With recent versions of gtk+, the use of Glib.Menu_Model.Gmenu_Model -- is encouraged, so you should use Set_Menu_Model above instead. type Save_Desktop_Function is access function (Widget : access Gtk.Widget.Gtk_Widget_Record'Class; User : User_Data) return Glib.Xml_Int.Node_Ptr; -- A general function that dumps the parameters of a widget into an XML -- tree. -- -- Note: you should register one such function for all the widget types -- you will put in the MDI and that need to be saved when a desktop is -- saved. The MDI will call all the registered functions one after the -- other. Therefore, your function should return null if Widget is not -- of a type that is it can handle. -- -- Before calling the registered save_desktop_function, the MDI will -- first use the child's Save_Desktop primitive function. type Load_Desktop_Function is access function (MDI : MDI_Window; Node : Glib.Xml_Int.Node_Ptr; User : User_Data) return MDI_Child; -- A general function that loads a widget from an XML tree. -- -- As for Save_Desktop_Function, this function should return null if it -- doesn't know how to handle Node or if Node doesn't describe a widget -- type that it can handle. -- -- This function returns an MDI_Widget that has been put in the MDI. procedure Register_Desktop_Functions (Save : Save_Desktop_Function; Load : Load_Desktop_Function); -- Register a set of functions to save and load desktops for some -- specific widget types. This can be called multiple times. -- Save might be null. function Restore_Desktop (MDI : access MDI_Window_Record'Class; Perspectives : Glib.Xml_Int.Node_Ptr; From_Tree : Glib.Xml_Int.Node_Ptr; User : User_Data) return Boolean; -- Restore the contents of the MDI from its saved XML tree. -- Perspectives is the list of perspectives. It is cloned as needed, so -- the caller is still responsible for freeing it. The first perspective -- is loaded. -- From_Tree is the part of the desktop that describes the editor area. -- User is passed as a parameter to all of the Load_Desktop_Function -- registered by the widgets. -- Return False if the desktop couldn't be loaded -- It also restores the size and position of the toplevel window that -- contains the MDI procedure Load_Perspective (MDI : access MDI_Window_Record'Class; Name : String; User : User_Data); -- Replace the current perspective by another one. This preserves the -- editor area. -- If the perspective does not exist, nothing is done, unless no -- perspective is currently loaded (in which case we load the first -- on in the list). procedure Create_Perspective (MDI : access MDI_Window_Record'Class; Name : String; User : User_Data); -- Create a new perspective with the current desktop layout. If another -- perspective with the same name exists, it is replaced. procedure Define_Perspective (MDI : access MDI_Window_Record'Class; XML : Glib.Xml_Int.Node_Ptr; User : User_Data); -- Define a new perspective (in the same format as returned by -- Save_Desktop, the central area is under control of the user so you -- cannot change it). -- If such a perspective already exists, nothing is done (since the user -- might have modified it already). -- XML's root node is the node, including its "name" -- attribute. -- XML must be freed by the caller. procedure Save_Desktop (MDI : access MDI_Window_Record'Class; User : User_Data; Perspectives : out Glib.Xml_Int.Node_Ptr; Central : out Glib.Xml_Int.Node_Ptr); -- Return XML representations of the perspectives and central area. Both -- nodes need to be freed by the caller, and can be saved in a file (to -- be passed to Restore_Desktop later on). -- This function calls each of the registered function for the children -- of the MDI. -- It also saves the size and position of the toplevel window that -- contains the MDI function Get_XML_Content (MDI : access MDI_Window_Record'Class; Tag : String) return Glib.Xml_Int.Node_Ptr; -- Return the first XML subtree starting with 'Tag'. This allows a -- module to retrieve its content after the 'Load_Desktop' call. procedure Free_Registered_Desktop_Functions; -- Free the memory allocated for the registered functions. private type Register_Node_Record; type Register_Node is access Register_Node_Record; type Register_Node_Record is record Save : Save_Desktop_Function; Load : Load_Desktop_Function; Next : Register_Node; end record; type Perspective_Menu_Item_Record is new Gtk.Radio_Menu_Item.Gtk_Radio_Menu_Item_Record with record MDI : MDI_Window; Name : Natural; User : User_Data; end record; type Perspective_Menu_Item is access all Perspective_Menu_Item_Record'Class; procedure Change_Perspective (Item : access Gtk.Widget.Gtk_Widget_Record'Class); CP_Access : constant Gtkada.Handlers.Widget_Callback.Marshallers.Marshaller := Gtkada.Handlers.Widget_Callback.To_Marshaller (Change_Perspective'Access); -- Internal, but needed so that we can have a 'Access on a callback procedure Create_Perspective_CB (Item : access Gtk.Widget.Gtk_Widget_Record'Class); CreateP_Access : constant Gtkada.Handlers.Widget_Callback.Marshallers.Marshaller := Gtkada.Handlers.Widget_Callback.To_Marshaller (Create_Perspective_CB'Access); procedure On_Action_Select_Perspective (MDI : access MDI_Window_Record'Class; Params : Glib.Values.GValues; User : User_Data); procedure On_Action_Create_Perspective (MDI : access MDI_Window_Record'Class; Params : Glib.Values.GValues; User : User_Data); procedure On_Perspective_Changed_Update_Menu (Menu : access Gtk.Widget.Gtk_Widget_Record'Class); On_Perspective_Changed_Update_Menu_Access : constant Gtkada.Handlers.Widget_Callback.Simple_Handler := On_Perspective_Changed_Update_Menu'Access; Registers : Register_Node; -- Global variable that contains the list of functions that have been -- registered. end Desktop; function Desktop_Was_Loaded (MDI : access MDI_Window_Record) return Boolean; -- Return True if a desktop was loaded, False if the MDI is only the result -- of calls to Gtk_New and Put. function List_Of_Perspectives (MDI : access MDI_Window_Record) return GNAT.Strings.String_List_Access; -- Return the list of perspectives known to the MDI. The caller must not -- free the list function Current_Perspective (MDI : access MDI_Window_Record'Class) return String; -- Return the name of the currently displayed perspective ------------- -- Signals -- ------------- -- -- The following new signals are defined for this widget: -- -- - "child_selected" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Child : System.Address); -- -- This signal is emitted when a new child has gained the focus. Convert -- Child to a MDI_Child by calling Gtk.Arguments.To_Object. This can be -- used to change some global information at the MDI level. You should -- connect to "selected" (see below) instead if you want to change some -- information at the child level. -- Child might be null if no child has the focus anymore -- -- - "float_child" -- - "unfloat_child" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Child : System.Address); -- -- A child was set as floating in the MDI. A similar signal is emitted on -- the child itself. -- -- - "child_title_changed" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Child : System.Address); -- -- Emitted when the title of a child is changed. This signal is not -- emitted if Set_Title is called for a child that hasn't been put in the -- MDI yet. -- -- - "child_added" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Child : System.Address); -- Emitted when a new child is added. You cannot use the "add" signal -- since in fact the children are added to notebooks that are part of -- the MDI, and thus "add" is only emitted when a new notebook is -- created. -- -- - "child_removed" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Child : System.Address); -- Emitted when a new child is removed. You cannot use the "remove" -- signal since in fact the children are removed from notebooks that are -- part of the MDI, and thus "remove" is only emitted when a new -- notebook is destroyed. -- When this signal is emitted, Child no longer contains a widget, and -- is no longer part of the children, although you can still access its -- titles. -- -- - "child_icon_changed" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Child : System.Address); -- Emitted when the icon for Child has changed -- -- - "children_reorganized" -- procedure Handler (MDI : access MDI_Window_Record'Class); -- Emitted when the children have been reorganized: either a split -- occurred, or a window was dropped into another position -- -- - "perspective_changed" -- procedure Handler (MDI : access MDI_Window_Record'Class); -- Called when the user has selected a new perspective. One use is to -- save the new desktop to a file. -- -- - "perspectives_added" -- procedure Handler -- (MDI : access MDI_Window_Record'Class; Name : String); -- Called when a new perspective is created -- -- -- -- -- The following new signals are defined for the MDI_Child_Record object: -- -- - "delete_event" -- function Handler (Child : access Gtk_Widget_Record'Class) -- return Boolean; -- -- This signal is emitted for each item in the MDI window before it is -- actually deleted. The child is destroyed only if the handler returns -- False. -- Note that the Child passed in argument is exactly the one you passed -- to Put to insert it in the MDI window. -- Note that this is also the signal to use to prevent top level -- Gtk_Window from being destroyed. -- -- - "selected" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- This is emitted when the child is selected, ie gains the -- MDI focus. You should probably also connect to the "grab_focus" signal -- to be informed when the child gets the keyboard focus. This can be -- used to transfer the focus to some specific part of the -- widget. Connecting to "grab_focus" should be done with the After -- parameter set to True. -- -- - "float_child" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when a child is set as floating -- -- - "unfloat_child" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when a child is put back in the main MDI window -- -- - "before_unfloat_child" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when a child is about to be put back in the main MDI window -- -- - "child_state_changed" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when the state of the child has changed. See the function -- Get_State. In particular, this signal can be detected when a child is -- removed from the current perspective (the new state is "invisible"), -- and when it is put back (the new state is "normal" or "floating"). -- -- - "before_destroy_child" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when a child is about to be destroyed -- -- - "before_remove_child" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when a child is about to be removed from its MDI_Notebook -- -- - "double_click_child_tab" -- procedure Handler (Child : access MDI_Child_Record'Class); -- -- Emitted when double clicking on the notebook's tab of a MDI_Child -- -- type Cb_Gtkada_MDI_Window_MDI_Child_Void is not null access procedure (Self : access MDI_Window_Record'Class; Child : not null access MDI_Child_Record'Class); type Cb_GObject_MDI_Child_Void is not null access procedure (Self : access Glib.Object.GObject_Record'Class; Child : not null access MDI_Child_Record'Class); Signal_Child_Selected : constant Signal_Name := "child_selected"; procedure On_Child_Selected (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Child_Selected (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Float_Child : constant Signal_Name := "float_child"; procedure On_Float_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Float_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Child_Title_Changed : constant Signal_Name := "child_title_changed"; procedure On_Child_Title_Changed (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Child_Title_Changed (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Child_Added : constant Signal_Name := "child_added"; procedure On_Child_Added (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Child_Added (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Child_Removed : constant Signal_Name := "child_removed"; procedure On_Child_Removed (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Child_Removed (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Child_Icon_Changed : constant Signal_Name := "child_icon_changed"; procedure On_Child_Icon_Changed (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Child_Icon_Changed (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Delete_Event : constant Signal_Name := "delete_event"; procedure On_Delete_Event (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Delete_Event (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Unfloat_Child : constant Signal_Name := "unfloat_child"; procedure On_Unfloat_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Unfloat_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Before_Unfloat_Child : constant Signal_Name := "before_unfloat_child"; procedure On_Before_Unfloat_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Before_Unfloat_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Before_Destroy_Child : constant Signal_Name := "before_destroy_child"; procedure On_Before_Destroy_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Before_Destroy_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Before_Remove_Child : constant Signal_Name := "before_remove_child"; procedure On_Before_Remove_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_Gtkada_MDI_Window_MDI_Child_Void; After : Boolean := False); procedure On_Before_Remove_Child (Self : not null access MDI_Window_Record'Class; Call : Cb_GObject_MDI_Child_Void; Slot : not null access Glib.Object.GObject_Record'Class; After : Boolean := False); Signal_Selected : constant Signal_Name := "selected"; Signal_Perspective_Changed : constant Signal_Name := "perspective_changed"; Signal_Perspectives_Added : constant Signal_Name := "perspectives_added"; Signal_Children_Reorganized : constant Signal_Name := "children_reorganized"; Signal_Child_State_Changed : constant Signal_Name := "child_state_changed"; Signal_Maximize_Child : constant Signal_Name := "maximize_child"; Signal_Unmaximize : constant Signal_Name := "unmaximize"; procedure Child_Selected (Self : not null access MDI_Window_Record'Class; Child : access MDI_Child_Record'Class := null); -- Emit the "child_selected" signal private type Saved_Perspective_Record is record Height : Gint; Width : Gint; -- The sizes of the maximized container Container : Gtk.Widget.Gtk_Widget; -- The Container currently maximized end record; type Saved_Perspective is access all Saved_Perspective_Record; package Saved_Perspectives_Map is new Ada.Containers.Indefinite_Hashed_Maps (Key_Type => String, Element_Type => Saved_Perspective, Hash => Ada.Strings.Hash, Equivalent_Keys => "=", "=" => "="); use Saved_Perspectives_Map; type String_Access is access all UTF8_String; type MDI_Child_Record is new Gtk.Event_Box.Gtk_Event_Box_Record with record Initial : Gtk.Widget.Gtk_Widget; -- The widget we use to build this child. Main_Box : Gtk.Box.Gtk_Box; -- The main container. State : State_Type := Normal; Group : Child_Group := Group_Default; Areas : Allowed_Areas := Both; Title : String_Access; Short_Title : String_Access; -- Title of the item, as it appears in the title bar. -- These are UTF8-Encoded XML_Node_Name : String_Access; -- The name of the XML node when this child is saved in a desktop (if -- we know it). This is used to reuse a child when switching -- perspectives. MDI : MDI_Window; -- The MDI to which the child belongs. We cannot get this information -- directly from Get_Parent since some children are actually floating -- and do not belong to the MDI anymore. Flags : Child_Flags; Focus_Widget : Gtk.Widget.Gtk_Widget; -- The widget which should actually get the keyboard focus Title_Box : Gtk.Box.Gtk_Box; Title_Label : Gtk.Label.Gtk_Label; Title_Icon : Gtk.Image.Gtk_Image; -- Box that contains the title. It will be resized whenever the title -- font changes. Tab_Label : Gtk.Label.Gtk_Label; Tab_Icon : Gtk.Image.Gtk_Image; -- label used when child is in a notebook, null if not in a notebook Icon_Name : GNAT.Strings.String_Access; Notebook_Before_Floating : Gtk.Notebook.Gtk_Notebook := null; -- The original notebook of a floating child. Used to put the child -- back in the same notebook when unfloating it. end record; type Child_Iterator (Group_By_Notebook : Boolean := False) is record Visible_Only : Boolean; case Group_By_Notebook is when False => Iter : Gtk.Widget.Widget_List.Glist; when True => MDI : MDI_Window; -- While iterating children Paned_Iter : Gtkada.Multi_Paned.Child_Iterator; -- Whether we have already visited the children of the central -- area. This is True while iterating them, False afterward In_Central : Boolean; -- While iterating the pages of a specific notebook (notebook is -- set to null when returning floating children) Notebook : Gtk.Notebook.Gtk_Notebook; Notebook_Page : Glib.Gint; -- While iterating the floating children Floating_Iter : Gtk.Widget.Widget_List.Glist; end case; end record; type Drag_Status is (No_Drag, In_Pre_Drag, In_Drag); type MDI_Window_Record is new Gtkada.Multi_Paned.Gtkada_Multi_Paned_Record with record Items : Gtk.Widget.Widget_List.Glist := Gtk.Widget.Widget_List.Null_List; -- The list of all MDI children. This includes children in the editor -- area, even though they are technically in a separate multi_paned. -- Warning: this list might contain items which are in fact invisible in -- the MDI (in fact that are not even children of the MDI), if they -- existed in a previous perspective but no longer in the current one. Desktop_Was_Loaded : Boolean := False; -- True if a desktop was loaded Loading_Desktop : Boolean := False; -- Whether we are currently loading the desktop. This impacts a number -- of focus and sizing parameters, so that the desktop can be restored -- as accurately as possible. Focus_Child : MDI_Child := null; -- The child that currently has the focus. Some default actions will -- apply to this child only. Focus_Freeze : Natural := 0; -- We should not emit any focus change if this is > 0. Dnd_Message : String_Access; -- The message displayed during a dnd operation (see Set_Dnd_Message) Accel_Path_Prefix : String_Access; -- The Accel path used for the dynamic menu Menu_Model : Glib.Menu.Gmenu; Menu_Items_Section : Glib.Menu.Gmenu; Application : Gtk.Application.Gtk_Application; Action_Float : Glib.Simple_Action.Gsimple_Action; Action_Select : Glib.Simple_Action.Gsimple_Action; Action_Close : Glib.Simple_Action.Gsimple_Action; Action_Select_Perspective : Glib.Simple_Action.Gsimple_Action; Perspectives_Menu : Glib.Menu.Gmenu; Freeze_Float_Menu : Boolean := False; Tab_Factory : Tab_Contextual_Menu_Factory; -- Build the contextual menu when right-clicking on tabs Title_Bar_Height : Glib.Gint; -- Height of the title bar for all the children Title_Font : Pango.Font.Pango_Font_Description; -- The font used for the titles of the children Close_Floating_Is_Unfloat : Boolean; -- True if destroying a floating window will put the child back in the -- MDI instead of destroying it. False if the child should be destroyed -- (provided it accepts so in its delete_event handler). Title_Bar_Color : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; Focus_Title_Color : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; Default_Title_Color : Gdk.RGBA.Gdk_RGBA := Gdk.RGBA.Null_RGBA; Css_Provider : Gtk.Css_Provider.Gtk_Css_Provider; Cursor_Cross : Gdk.Gdk_Cursor; Cursor_Fleur : Gdk.Gdk_Cursor; -- Cached cursors Draw_Title_Bars : Title_Bars_Policy := Always; Tabs_Position : Gtk.Enums.Gtk_Position_Type := Gtk.Enums.Pos_Top; Tabs_Orientation : Tab_Orientation_Type := Automatic; Show_Tabs_Policy : Show_Tabs_Policy_Enum := Automatic; Selection_Dialog : Gtk.Widget.Gtk_Widget; -- The interactive dialog for selecting new children. Group : Gtk.Accel_Group.Gtk_Accel_Group; All_Floating_Mode : Boolean := False; -- Set to true if all windows should be set to floating Independent_Perspectives : Boolean := False; -- See documentation for Configure. Use_Short_Titles_For_Floats : Boolean := False; -- Set to true if all floating children should use their short titles. -- This also applies to docked windows. Homogeneous_Tabs : Boolean := True; -- Handling of Dnd Drag_Start_X, Drag_Start_Y : Gint; In_Drag : Drag_Status := No_Drag; -- The Dnd status Dnd_Rectangle : Gdk.Rectangle.Gdk_Rectangle; -- the Dnd highlighted area (e.g: left side of notebook) Old_Dnd_Position : Child_Position := Position_Automatic; -- The old Dnd position (e.g: top side of notebook). Used to know if -- we should refresh the Dnd overlay (and the message) or not. Dnd_Parent_Rect : Gdk.Rectangle.Gdk_Rectangle; -- The area that corresponds to the Dnd target parent (e.g: parent -- notebook) Dnd_Area_Message : Unbounded_String; -- The message displayed when Dnd is being performed, indicating the -- are where the MDI child will be dropped Dnd_Handler_Id : Gtk.Handlers.Handler_Id; -- The Dnd overlay drawing handler Dnd_Target : Gdk.Gdk_Window; -- The current target for DND Drag_Areas : Allowed_Areas; -- The allowed areas during a drag -- Loaded perspectives Perspectives : Glib.Xml_Int.Node_Ptr; View_Contents : Glib.Xml_Int.Node_Ptr; Perspective_Names : GNAT.Strings.String_List_Access; Central : Gtkada.Multi_Paned.Gtkada_Multi_Paned; Current_Perspective : Glib.Xml_Int.Node_Ptr; -- pointer into Perspectives Saved_Sizes : Saved_Perspectives_Map.Map; -- Map containing the sizes of the MDI children before the last -- child maximization Internal_Updating_Menu : Boolean := False; -- Flag to prevent giving focus to a child in response to a menu being -- toggled when it is the MDI itself that toggles the menu. end record; pragma Inline (Get_Widget); pragma Inline (Get_Focus_Child); pragma Inline (Get); pragma Inline (Next); pragma Inline (First_Child); end Gtkada.MDI;