From 2bd8349602b40b46d70bea54dbe423a19d899128 Mon Sep 17 00:00:00 2001 From: sekelsenmat Date: Mon, 10 Aug 2015 05:12:52 +0000 Subject: [PATCH] cocoa: Fixes tab sheet positioning (bug #28489) and starts improving main menu code git-svn-id: trunk@49626 - --- lcl/interfaces/cocoa/cocoaint.pas | 9 +++++-- lcl/interfaces/cocoa/cocoaobject.inc | 31 +++++++++++++++++++++++- lcl/interfaces/cocoa/cocoaprivate.pp | 26 +++++++++++++++++--- lcl/interfaces/cocoa/cocoawscomctrls.pas | 21 ++++++++++++++++ lcl/interfaces/cocoa/cocoawscommon.pas | 3 ++- lcl/interfaces/cocoa/cocoawsforms.pp | 7 +++--- lcl/interfaces/cocoa/cocoawsmenus.pas | 13 +++++++--- 7 files changed, 97 insertions(+), 13 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 3590006368..618381bf77 100644 --- a/lcl/interfaces/cocoa/cocoaint.pas +++ b/lcl/interfaces/cocoa/cocoaint.pas @@ -36,7 +36,7 @@ uses CocoaProc, // LCL LCLStrConsts, LMessages, LCLMessageGlue, LCLProc, LCLIntf, LCLType, - Controls, Forms, Themes, + Controls, Forms, Themes, Menus, IntfGraphics, Graphics, CocoaWSFactory; type @@ -59,6 +59,11 @@ type constructor Create(AMimeType: string; ACocoaFormat: NSString; ADataType: TCocoaClipboardDataType); end; + {// private since 10.5, doesn't seam to do anything in 10.10 + NSApplicationSetAppleMenu = objccategory external(NSApplication) + procedure setAppleMenu(AMenu: NSMenu); message 'setAppleMenu:'; + end;} + { TCocoaWidgetSet } TCocoaWidgetSet = class(TWidgetSet) @@ -129,7 +134,7 @@ type procedure FreeStockItems; procedure FreeSysColorBrushes; - procedure SetMainMenu(const AMenu: HMENU); + procedure SetMainMenu(const AMenu: HMENU; const ALCLMenu: TMenu); {todo:} function DCGetPixel(CanvasHandle: HDC; X, Y: integer): TGraphicsColor; override; diff --git a/lcl/interfaces/cocoa/cocoaobject.inc b/lcl/interfaces/cocoa/cocoaobject.inc index 1d30243c8a..55e3b3ed49 100644 --- a/lcl/interfaces/cocoa/cocoaobject.inc +++ b/lcl/interfaces/cocoa/cocoaobject.inc @@ -418,10 +418,39 @@ begin DeleteAndNilObject(FSysColorBrushes[i]); end; -procedure TCocoaWidgetSet.SetMainMenu(const AMenu: HMENU); +procedure TCocoaWidgetSet.SetMainMenu(const AMenu: HMENU; const ALCLMenu: TMenu); +var + i: Integer; + lCurItem: TMenuItem; + lMenuObj: NSObject; begin if AMenu<>0 then + begin NSApp.setMainMenu(NSMenu(AMenu)); + if (ALCLMenu = nil) or not ALCLMenu.HandleAllocated then Exit; + + // Some older docs say we should use setAppleMenu to obtain the Services/Hide/Quit items, + // but its now private and in 10.10 it doesn't seam to do anything + { + for i := 0 to ALCLMenu.Items.Count-1 do + begin + lCurItem := ALCLMenu.Items.Items[i]; + if not lCurItem.HandleAllocated or (lCurItem.Caption <> '') then Continue; + + lMenuObj := NSObject(lCurItem.Handle); + if lMenuObj.isKindOfClass_(NSMenuItem) and NSMenuItem(lMenuObj).hasSubmenu and + (NSMenuItem(lMenuObj).submenu <> nil) then + begin + NSApp.setAppleMenu(NSMenuItem(lMenuObj).submenu); + Exit; + end + else if lMenuObj.isKindOfClass_(NSMenu) then + begin + NSApp.setAppleMenu(NSMenu(lMenuObj)); + Exit; + end; + end;} + end; end; {------------------------------------------------------------------------------ diff --git a/lcl/interfaces/cocoa/cocoaprivate.pp b/lcl/interfaces/cocoa/cocoaprivate.pp index 2f71d49b62..91d712a57e 100644 --- a/lcl/interfaces/cocoa/cocoaprivate.pp +++ b/lcl/interfaces/cocoa/cocoaprivate.pp @@ -22,6 +22,7 @@ unit CocoaPrivate; {.$DEFINE COCOA_DEBUG_LISTVIEW} {.$DEFINE COCOA_SPIN_DEBUG} {.$DEFINE COCOA_SPINEDIT_INSIDE_CONTAINER} +{.$DEFINE COCOA_SUPERVIEW_HEIGHT} interface @@ -202,6 +203,7 @@ type TCocoaMenu = objcclass(NSMenu) public + isMainMenu: Boolean; procedure lclItemSelected(sender: id); message 'lclItemSelected:'; function lclIsHandle: Boolean; override; end; @@ -635,6 +637,7 @@ type public callback: ICommonCallback; LCLPage: TCustomPage; + LCLParent: TCustomTabControl; function lclGetCallback: ICommonCallback; override; procedure lclClearCallback; override; function lclFrame: TRect; override; @@ -862,6 +865,8 @@ function GetNSViewSuperViewHeight(view: NSView): CGFloat; implementation +uses CocoaWSComCtrls; + {$I mackeycodes.inc} procedure SetViewDefaults(AView: NSView); @@ -884,6 +889,9 @@ begin Result := TCocoaTabPageView(view.superview).tabview.contentRect.size.height else Result := view.superview.frame.size.height; + {$IFDEF COCOA_SUPERVIEW_HEIGHT} + WriteLn(Format('GetNSViewSuperViewHeight Result=%f', [Result])); + {$ENDIF} end; { TCocoaWindowContent } @@ -2757,10 +2765,22 @@ end; function TCocoaTabPage.lclFrame: TRect; var svh: CGFloat; + lParent: TCocoaTabControl; begin - svh := tabView.frame.size.height; - NSToLCLRect(tabView.contentRect, svh, Result); - //WriteLn('[TCocoaTabPage.lclFrame] '+dbgs(Result)+' '+NSStringToString(Self.label_)); + lParent := TCocoaWSCustomTabControl.GetCocoaTabControlHandle(LCLParent); + if lParent <> nil then + begin + svh := lParent.contentRect.size.height; + NSToLCLRect(lParent.contentRect, svh, Result); + end + else + begin + svh := tabView.frame.size.height; + NSToLCLRect(tabView.contentRect, svh, Result); + end; + {$IFDEF COCOA_DEBUG_TABCONTROL} + WriteLn('[TCocoaTabPage.lclFrame] '+dbgs(Result)+' '+NSStringToString(Self.label_)); + {$ENDIF} end; function TCocoaTabPage.lclClientFrame: TRect; diff --git a/lcl/interfaces/cocoa/cocoawscomctrls.pas b/lcl/interfaces/cocoa/cocoawscomctrls.pas index ce67e0275b..5c07f8b286 100644 --- a/lcl/interfaces/cocoa/cocoawscomctrls.pas +++ b/lcl/interfaces/cocoa/cocoawscomctrls.pas @@ -47,6 +47,8 @@ type class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class procedure UpdateProperties(const ACustomPage: TCustomPage); override; class procedure SetProperties(const ACustomPage: TCustomPage; ACocoaControl: NSTabViewItem); + // + class procedure SetBounds(const AWinControl: TWinControl; const ALeft, ATop, AWidth, AHeight: Integer); override; end; { TCocoaWSCustomTabControl } @@ -54,6 +56,8 @@ type TCocoaWSCustomTabControl = class(TWSCustomTabControl) private class function LCLTabPosToNSTabStyle(AShowTabs: Boolean; ABorderWidth: Integer; ATabPos: TTabPosition): NSTabViewType; + public + class function GetCocoaTabControlHandle(ATabControl: TCustomTabControl): TCocoaTabControl; published class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; @@ -330,6 +334,14 @@ begin ACocoaControl.setToolTip(NSStringUTF8(lHintStr)); end; +class procedure TCocoaWSCustomPage.SetBounds(const AWinControl: TWinControl; + const ALeft, ATop, AWidth, AHeight: Integer); +begin + // Pages should be fixed into their PageControl owner, + // allowing the TCocoaWSWinControl.SetBounds function to operate here + // was causing bug 28489 +end; + { TCocoaWSCustomTabControl } class function TCocoaWSCustomTabControl.LCLTabPosToNSTabStyle(AShowTabs: Boolean; ABorderWidth: Integer; ATabPos: TTabPosition): NSTabViewType; @@ -355,6 +367,14 @@ begin end; end; +class function TCocoaWSCustomTabControl.GetCocoaTabControlHandle(ATabControl: TCustomTabControl): TCocoaTabControl; +begin + Result := nil; + if ATabControl = nil then Exit; + if not ATabControl.HandleAllocated then Exit; + Result := TCocoaTabControl(ATabControl.Handle); +end; + class function TCocoaWSCustomTabControl.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; var lControl: TCocoaTabControl; @@ -387,6 +407,7 @@ begin AChild.HandleNeeded(); if not Assigned(AChild) or not AChild.HandleAllocated then Exit; lTabPage := TCocoaWSCustomPage.GetCocoaTabPageFromHandle(AChild.Handle); + lTabPage.LCLParent := ATabControl; lTabControl.insertTabViewItem_atIndex(lTabPage, AIndex); {$IFDEF COCOA_DEBUG_TABCONTROL} diff --git a/lcl/interfaces/cocoa/cocoawscommon.pas b/lcl/interfaces/cocoa/cocoawscommon.pas index 83802274b6..f4fc853dd3 100644 --- a/lcl/interfaces/cocoa/cocoawscommon.pas +++ b/lcl/interfaces/cocoa/cocoawscommon.pas @@ -1259,7 +1259,8 @@ begin if AWinControl.HandleAllocated then begin {$IFDEF COCOA_DEBUG_SETBOUNDS} - writeln('TCocoaWSWinControl.SetBounds: '+AWinControl.Name+'Bounds='+dbgs(Bounds(ALeft, ATop, AWidth, AHeight))); + writeln(Format('TCocoaWSWinControl.SetBounds: %s Bounds=%s', + [AWinControl.Name, dbgs(Bounds(ALeft, ATop, AWidth, AHeight))])); {$ENDIF} NSObject(AWinControl.Handle).lclSetFrame(Bounds(ALeft, ATop, AWidth, AHeight)); end; diff --git a/lcl/interfaces/cocoa/cocoawsforms.pp b/lcl/interfaces/cocoa/cocoawsforms.pp index 31ea248c75..37d691cb18 100644 --- a/lcl/interfaces/cocoa/cocoawsforms.pp +++ b/lcl/interfaces/cocoa/cocoawsforms.pp @@ -285,15 +285,15 @@ begin if NSObject(ACustForm.Menu.Handle).isKindOfClass_(TCocoaMenuItem) then begin if TCocoaMenuItem(ACustForm.Menu.Handle).hasSubmenu then - CocoaWidgetSet.SetMainMenu(HMENU(TCocoaMenuItem(ACustForm.Menu.Handle).submenu)) + CocoaWidgetSet.SetMainMenu(HMENU(TCocoaMenuItem(ACustForm.Menu.Handle).submenu), ACustForm.Menu) else debugln('Warning: Menu does not have a valid handle.'); end else - CocoaWidgetSet.SetMainMenu(ACustForm.Menu.Handle); + CocoaWidgetSet.SetMainMenu(ACustForm.Menu.Handle, ACustForm.Menu); end else - CocoaWidgetSet.SetMainMenu(0); + CocoaWidgetSet.SetMainMenu(0, nil); LCLSendActivateMsg(Target, WA_ACTIVE, false); LCLSendSetFocusMsg(Target); @@ -528,6 +528,7 @@ end; class procedure TCocoaWSCustomForm.ShowModal(const ACustomForm: TCustomForm); begin + // modal is started in ShowHide with (fsModal in AForm.FormState) // if ACustomForm.HandleAllocated then // NSPanel(ACustomForm.Handle).setStyleMask(NSwindow(ACustomForm.Handle).styleMask or NSDocModalWindowMask); end; diff --git a/lcl/interfaces/cocoa/cocoawsmenus.pas b/lcl/interfaces/cocoa/cocoawsmenus.pas index 5205cf9a93..dd7c5a8e1c 100644 --- a/lcl/interfaces/cocoa/cocoawsmenus.pas +++ b/lcl/interfaces/cocoa/cocoawsmenus.pas @@ -62,9 +62,8 @@ type { TCocoaWSMainMenu } TCocoaWSMainMenu = class(TWSMainMenu) - private - protected - public + published + class function CreateHandle(const AMenu: TMenu): HMENU; override; end; { TCocoaWSPopupMenu } @@ -119,6 +118,14 @@ begin Result := HMENU(TCocoaMenu.alloc.initWithTitle(NSStringUtf8(''))); end; +{ TCocoaWSMainMenu } + +class function TCocoaWSMainMenu.CreateHandle(const AMenu: TMenu): HMENU; +begin + Result := HMENU(TCocoaMenu.alloc.initWithTitle(NSStringUtf8(''))); + TCocoaMenu(Result).isMainMenu := True; +end; + { TCocoaWSMenuItem } {------------------------------------------------------------------------------