mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-31 08:32:35 +02:00
Separates gtk1 and gtk2 menu item code. Started implementing shortcuts for gtk2 menu items, but was unable to finish it. It didn't work before, so commited anyway because the new code is at least cleaner.
git-svn-id: trunk@14842 -
This commit is contained in:
parent
34f7f58085
commit
f54bea2fc5
@ -43,6 +43,7 @@ type
|
||||
private
|
||||
protected
|
||||
public
|
||||
{$IFDEF GTK1}
|
||||
class procedure AttachMenu(const AMenuItem: TMenuItem); override;
|
||||
class function CreateHandle(const AMenuItem: TMenuItem): HMENU; override;
|
||||
class procedure DestroyHandle(const AMenuItem: TMenuItem); override;
|
||||
@ -54,6 +55,7 @@ type
|
||||
class function SetRadioItem(const AMenuItem: TMenuItem; const RadioItem: boolean): boolean; override;
|
||||
class function SetRightJustify(const AMenuItem: TMenuItem; const Justified: boolean): boolean; override;
|
||||
class procedure UpdateMenuIcon(const AMenuItem: TMenuItem; const HasIcon: Boolean; const AIcon: TBitmap); override;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
{ TGtkWSMenu }
|
||||
@ -91,6 +93,7 @@ uses Controls;
|
||||
|
||||
{ TGtkWSMenuItem }
|
||||
|
||||
{$IFDEF GTK1}
|
||||
class procedure TGtkWSMenuItem.AttachMenu(const AMenuItem: TMenuItem);
|
||||
var
|
||||
//AccelKey: Integer;
|
||||
@ -183,16 +186,10 @@ begin
|
||||
// set 'Checked'
|
||||
gtk_check_menu_item_set_active(PGtkCheckMenuItem(Widget),
|
||||
AMenuItem.Checked);
|
||||
{$ifdef GTK2}
|
||||
if (OldCheckMenuItemToggleSize=0) then
|
||||
begin
|
||||
gtk_menu_item_toggle_size_request(GTK_MENU_ITEM(Widget), @OldCheckMenuItemToggleSize);
|
||||
OldCheckMenuItemToggleSize := GTK_MENU_ITEM(Widget)^.toggle_size;
|
||||
end;
|
||||
{$else}
|
||||
|
||||
if (OldCheckMenuItemToggleSize=0) then
|
||||
OldCheckMenuItemToggleSize := MENU_ITEM_CLASS(Widget)^.toggle_size;
|
||||
{$endif}
|
||||
|
||||
g_signal_connect_after(PGTKObject(Widget), 'toggled',
|
||||
TGTKSignalFunc(@GTKCheckMenuToggeledCB), Pointer(AMenuItem));
|
||||
end;
|
||||
@ -329,6 +326,7 @@ begin
|
||||
Exit;
|
||||
// TODO
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{ TGtkWSMenu }
|
||||
|
||||
@ -457,7 +455,9 @@ initialization
|
||||
// To improve speed, register only classes
|
||||
// which actually implement something
|
||||
////////////////////////////////////////////////////
|
||||
{$IFDEF GTK1}
|
||||
RegisterWSComponent(TMenuItem, TGtkWSMenuItem);
|
||||
{$ENDIF}
|
||||
RegisterWSComponent(TMenu, TGtkWSMenu);
|
||||
// RegisterWSComponent(TMainMenu, TGtkWSMainMenu);
|
||||
RegisterWSComponent(TPopupMenu, TGtkWSPopupMenu);
|
||||
|
@ -160,7 +160,7 @@ uses
|
||||
// Gtk2WSGrids,
|
||||
// Gtk2WSImgList,
|
||||
// Gtk2WSMaskEdit,
|
||||
// Gtk2WSMenus,
|
||||
Gtk2WSMenus,
|
||||
// Gtk2WSPairSplitter,
|
||||
// Gtk2WSSpin,
|
||||
Gtk2WSStdCtrls,
|
||||
|
@ -27,15 +27,10 @@ unit Gtk2WSMenus;
|
||||
interface
|
||||
|
||||
uses
|
||||
////////////////////////////////////////////////////
|
||||
// I M P O R T A N T
|
||||
////////////////////////////////////////////////////
|
||||
// To get as little as posible circles,
|
||||
// uncomment only when needed for registration
|
||||
////////////////////////////////////////////////////
|
||||
// Menus,
|
||||
////////////////////////////////////////////////////
|
||||
WSMenus, WSLCLClasses;
|
||||
glib2, gdk2pixbuf, gdk2, gtk2, Pango,
|
||||
GtkInt, GtkProc, GtkGlobals, GtkDef, GtkExtra,
|
||||
Classes, InterfaceBase, Types, LCLProc, LCLType, WSMenus, WSLCLClasses,
|
||||
Graphics, Menus, Forms, LCLIntf;
|
||||
|
||||
type
|
||||
|
||||
@ -45,6 +40,17 @@ type
|
||||
private
|
||||
protected
|
||||
public
|
||||
class procedure AttachMenu(const AMenuItem: TMenuItem); override;
|
||||
class function CreateHandle(const AMenuItem: TMenuItem): HMENU; override;
|
||||
class procedure DestroyHandle(const AMenuItem: TMenuItem); override;
|
||||
class procedure SetCaption(const AMenuItem: TMenuItem; const ACaption: string); override;
|
||||
class procedure SetShortCut(const AMenuItem: TMenuItem; const OldShortCut, NewShortCut: TShortCut); override;
|
||||
class procedure SetVisible(const AMenuItem: TMenuItem; const Visible: boolean); override;
|
||||
class function SetCheck(const AMenuItem: TMenuItem; const Checked: boolean): boolean; override;
|
||||
class function SetEnable(const AMenuItem: TMenuItem; const Enabled: boolean): boolean; override;
|
||||
class function SetRadioItem(const AMenuItem: TMenuItem; const RadioItem: boolean): boolean; override;
|
||||
class function SetRightJustify(const AMenuItem: TMenuItem; const Justified: boolean): boolean; override;
|
||||
class procedure UpdateMenuIcon(const AMenuItem: TMenuItem; const HasIcon: Boolean; const AIcon: TBitmap); override;
|
||||
end;
|
||||
|
||||
{ TGtk2WSMenu }
|
||||
@ -74,6 +80,264 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
{ TGtk2WSMenuItem }
|
||||
|
||||
class procedure TGtk2WSMenuItem.AttachMenu(const AMenuItem: TMenuItem);
|
||||
var
|
||||
//AccelKey: Integer;
|
||||
//AccelGroup: PGTKAccelGroup;
|
||||
MenuItem, ParentMenuWidget, ContainerMenu: PGtkWidget;
|
||||
|
||||
procedure SetContainerMenuToggleSize;
|
||||
var MenuClass: PGtkWidgetClass;
|
||||
begin
|
||||
if GtkWidgetIsA(ContainerMenu,GTK_TYPE_MENU) then begin
|
||||
MenuClass:=GTK_WIDGET_CLASS(gtk_object_get_class(ContainerMenu));
|
||||
if OldMenuSizeRequestProc=nil then begin
|
||||
OldMenuSizeRequestProc:=MenuClass^.size_request;
|
||||
end;
|
||||
MenuClass^.size_request:=@MenuSizeRequest;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
//DebugLn('TGtkWidgetSet.AttachMenu START ',AMenuItem.Name,':',AMenuItem.ClassName,' Parent=',AMenuItem.Parent.Name,':',AMenuItem.Parent.ClassName);
|
||||
with AMenuItem do
|
||||
begin
|
||||
MenuItem := PGtkWidget(Handle);
|
||||
if MenuItem=nil then
|
||||
RaiseGDBException('TGtkWidgetSet.AttachMenu Handle=0');
|
||||
ParentMenuWidget := PGtkWidget(Parent.Handle);
|
||||
if ParentMenuWidget=nil then
|
||||
RaiseGDBException('TGtkWidgetSet.AttachMenu ParentMenuWidget=nil');
|
||||
|
||||
if GtkWidgetIsA(ParentMenuWidget,GTK_TYPE_MENU_BAR) then begin
|
||||
// mainmenu (= a menu bar)
|
||||
ContainerMenu:=ParentMenuWidget;
|
||||
gtk_menu_bar_insert(ParentMenuWidget,MenuItem, AMenuItem.MenuVisibleIndex);
|
||||
end
|
||||
else begin
|
||||
// menu item
|
||||
|
||||
// find the menu container
|
||||
ContainerMenu := PGtkWidget(gtk_object_get_data(
|
||||
PGtkObject(ParentMenuWidget),
|
||||
'ContainerMenu'));
|
||||
if ContainerMenu = nil then begin
|
||||
if (GetParentMenu is TPopupMenu) and (Parent.Parent=nil) then begin
|
||||
ContainerMenu:=PGtkWidget(GetParentMenu.Handle);
|
||||
gtk_object_set_data(PGtkObject(ContainerMenu), 'ContainerMenu',
|
||||
ContainerMenu);
|
||||
end else begin
|
||||
ContainerMenu := gtk_menu_new;
|
||||
gtk_object_set_data(PGtkObject(ParentMenuWidget), 'ContainerMenu',
|
||||
ContainerMenu);
|
||||
gtk_menu_item_set_submenu(PGTKMenuItem(ParentMenuWidget),ContainerMenu);
|
||||
end;
|
||||
end;
|
||||
gtk_menu_insert(ContainerMenu, MenuItem, AMenuItem.MenuVisibleIndex);
|
||||
end;
|
||||
|
||||
SetContainerMenuToggleSize;
|
||||
|
||||
if GtkWidgetIsA(MenuItem, GTK_TYPE_RADIO_MENU_ITEM) then
|
||||
TGtkWidgetSet(WidgetSet).RegroupMenuItem(HMENU(PtrUInt(MenuItem)),GroupIndex);
|
||||
end;
|
||||
//DebugLn('TGtkWidgetSet.AttachMenu END ',AMenuItem.Name,':',AMenuItem.ClassName);
|
||||
end;
|
||||
|
||||
class function TGtk2WSMenuItem.CreateHandle(const AMenuItem: TMenuItem): HMENU;
|
||||
var
|
||||
Widget: PGtkWidget;
|
||||
WidgetInfo: PWidgetInfo;
|
||||
begin
|
||||
// create the menuitem widget (normal, check or radio)
|
||||
if AMenuItem.Caption='-' then // create separator
|
||||
Widget := gtk_menu_item_new
|
||||
else
|
||||
if AMenuItem.RadioItem and not AMenuItem.HasIcon then
|
||||
Widget := gtk_radio_menu_item_new(nil)
|
||||
else
|
||||
if AMenuItem.IsCheckItem or AMenuItem.HasIcon then
|
||||
Widget := gtk_check_menu_item_new
|
||||
else
|
||||
Widget := gtk_menu_item_new;
|
||||
|
||||
WidgetInfo := CreateWidgetInfo(Widget);
|
||||
WidgetInfo^.LCLObject := AMenuItem;
|
||||
|
||||
if GtkWidgetIsA(Widget, GTK_TYPE_CHECK_MENU_ITEM) then
|
||||
begin
|
||||
// set 'ShowAlwaysCheckable'
|
||||
gtk_check_menu_item_set_show_toggle(PGtkCheckMenuItem(Widget),
|
||||
AMenuItem.ShowAlwaysCheckable);
|
||||
// set 'Checked'
|
||||
gtk_check_menu_item_set_active(PGtkCheckMenuItem(Widget),
|
||||
AMenuItem.Checked);
|
||||
|
||||
if (OldCheckMenuItemToggleSize=0) then
|
||||
begin
|
||||
gtk_menu_item_toggle_size_request(GTK_MENU_ITEM(Widget), @OldCheckMenuItemToggleSize);
|
||||
OldCheckMenuItemToggleSize := GTK_MENU_ITEM(Widget)^.toggle_size;
|
||||
end;
|
||||
|
||||
g_signal_connect_after(PGTKObject(Widget), 'toggled',
|
||||
TGTKSignalFunc(@GTKCheckMenuToggeledCB), Pointer(AMenuItem));
|
||||
end;
|
||||
|
||||
// set attributes (enabled and rightjustify)
|
||||
gtk_widget_set_sensitive(Widget,
|
||||
AMenuItem.Enabled and (AMenuItem.Caption<>'-'));
|
||||
if AMenuItem.RightJustify then
|
||||
gtk_menu_item_right_justify(PGtkMenuItem(Widget));
|
||||
|
||||
// create the hbox containing the label and the icon
|
||||
UpdateInnerMenuItem(AMenuItem, Widget);
|
||||
|
||||
// connect activate signal (i.e. clicked)
|
||||
g_signal_connect(PGTKObject(Widget), 'activate',
|
||||
TGTKSignalFunc(@gtkactivateCB), AMenuItem);
|
||||
|
||||
gtk_widget_show(Widget);
|
||||
{$IFDEF DebugLCLComponents}
|
||||
DebugGtkWidgets.MarkCreated(Widget, dbgsName(AMenuItem));
|
||||
{$ENDIF}
|
||||
Result := HMENU(PtrUInt(Widget));
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSMenuItem.DestroyHandle(const AMenuItem: TMenuItem);
|
||||
begin
|
||||
{ TODO: cleanup }
|
||||
TGtkWidgetSet(WidgetSet).DestroyLCLComponent(AMenuItem);
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSMenuItem.SetCaption(const AMenuItem: TMenuItem;
|
||||
const ACaption: string);
|
||||
var
|
||||
MenuItemWidget: PGtkWidget;
|
||||
begin
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetCaption') then
|
||||
Exit;
|
||||
MenuItemWidget:=PGtkWidget(AMenuItem.Handle);
|
||||
UpdateInnerMenuItem(AMenuItem,MenuItemWidget);
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSMenuItem.SetShortCut(const AMenuItem: TMenuItem;
|
||||
const OldShortCut, NewShortCut: TShortCut);
|
||||
var
|
||||
MenuWidget: PGtkMenuItem;
|
||||
accel_path: String;
|
||||
CurKey: Word;
|
||||
CurShift: TShiftState;
|
||||
begin
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetShortCut') then Exit;
|
||||
|
||||
//DebugLn(['TGtkWSMenuItem.SetShortCut ',dbgsName(AMenuItem),' ',ShortCutToText(NewShortCut)]);
|
||||
|
||||
// Gets the inner widgets. They should already be created by now
|
||||
|
||||
MenuWidget := PGtkMenuItem(AMenuItem.Handle);
|
||||
|
||||
if (MenuWidget=nil) then Exit;
|
||||
|
||||
// Converts the shortcut to a gtk friendly format and sets it
|
||||
|
||||
{ ShortCutToKey(NewShortCut, CurKey, CurShift);
|
||||
|
||||
accel_path := 'LCLApp/Menu/' + GetAcceleratorString(CurKey, CurShift);
|
||||
|
||||
gtk_accel_map_add_entry(accel_path, CurKey, ShiftToGdkModifierType);
|
||||
|
||||
gtk_menu_item_set_accel_path(); }
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSMenuItem.SetVisible(const AMenuItem: TMenuItem;
|
||||
const Visible: boolean);
|
||||
var
|
||||
MenuItemWidget: PGtkWidget;
|
||||
begin
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetVisible') then
|
||||
Exit;
|
||||
MenuItemWidget := PGtkWidget(AMenuItem.Handle);
|
||||
if gtk_widget_visible(MenuItemWidget) = Visible then
|
||||
Exit;
|
||||
if Visible then
|
||||
gtk_widget_show(MenuItemWidget)
|
||||
else
|
||||
gtk_widget_hide(MenuItemWidget);
|
||||
end;
|
||||
|
||||
class function TGtk2WSMenuItem.SetCheck(const AMenuItem: TMenuItem;
|
||||
const Checked: boolean): boolean;
|
||||
var
|
||||
IsRadio: Boolean;
|
||||
Group: PGSList;
|
||||
Item: Pointer;
|
||||
begin
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetCheck') then
|
||||
Exit;
|
||||
Item := Pointer(AMenuItem.Handle);
|
||||
IsRadio := gtk_is_radio_menu_item(Item);
|
||||
if IsRadio or gtk_is_check_menu_item(Item)
|
||||
then begin
|
||||
if IsRadio
|
||||
then begin
|
||||
Group := gtk_radio_menu_item_group(Item);
|
||||
LockRadioGroupOnChange(Group, +1);
|
||||
end
|
||||
else LockOnChange(Item, +1);
|
||||
gtk_check_menu_item_set_active(Item, Checked);
|
||||
if IsRadio
|
||||
then LockRadioGroupOnChange(Group, -1)
|
||||
else LockOnChange(Item, -1);
|
||||
Result := True;
|
||||
end
|
||||
else begin
|
||||
AMenuItem.RecreateHandle;
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TGtk2WSMenuItem.SetEnable(const AMenuItem: TMenuItem;
|
||||
const Enabled: boolean): boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
|
||||
Exit;
|
||||
gtk_widget_set_sensitive(PGtkWidget(AMenuItem.Handle),
|
||||
Enabled and (AMenuItem.Caption<>'-'));
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
class function TGtk2WSMenuItem.SetRadioItem(const AMenuItem: TMenuItem;
|
||||
const RadioItem: boolean): boolean;
|
||||
begin
|
||||
AMenuItem.RecreateHandle;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
class function TGtk2WSMenuItem.SetRightJustify(const AMenuItem: TMenuItem;
|
||||
const Justified: boolean): boolean;
|
||||
var
|
||||
MenuItemWidget: PGtkMenuItem;
|
||||
begin
|
||||
Result := False;
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetRightJustify') then
|
||||
Exit;
|
||||
MenuItemWidget := PGtkMenuItem(AMenuItem.Handle);
|
||||
gtk_menu_item_set_right_justified(MenuItemWidget, Justified);
|
||||
gtk_widget_queue_resize(GTK_WIDGET(MenuItemWidget));
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSMenuItem.UpdateMenuIcon(const AMenuItem: TMenuItem;
|
||||
const HasIcon: Boolean; const AIcon: TBitmap);
|
||||
begin
|
||||
if not WSCheckMenuItem(AMenuItem, 'UpdateMenuIcon') then
|
||||
Exit;
|
||||
// TODO
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
@ -82,9 +346,9 @@ initialization
|
||||
// To improve speed, register only classes
|
||||
// which actually implement something
|
||||
////////////////////////////////////////////////////
|
||||
// RegisterWSComponent(TMenuItem, TGtk2WSMenuItem);
|
||||
RegisterWSComponent(TMenuItem, TGtk2WSMenuItem);
|
||||
// RegisterWSComponent(TMenu, TGtk2WSMenu);
|
||||
// RegisterWSComponent(TMainMenu, TGtk2WSMainMenu);
|
||||
// RegisterWSComponent(TPopupMenu, TGtk2WSPopupMenu);
|
||||
////////////////////////////////////////////////////
|
||||
end.
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user