From 5c58ede9d034ad591ec112128dc38a11a14c4d8c Mon Sep 17 00:00:00 2001 From: dmitry Date: Sun, 14 Jan 2018 06:14:12 +0000 Subject: [PATCH] cocoa: implementation of DesignDC for forms git-svn-id: trunk@57083 - --- lcl/interfaces/cocoa/cocoagdiobjects.pas | 1 + lcl/interfaces/cocoa/cocoalclintf.inc | 13 ++---- lcl/interfaces/cocoa/cocoalclintfh.inc | 4 +- lcl/interfaces/cocoa/cocoaprivate.pp | 54 ++++++++++++++++++++++++ lcl/interfaces/cocoa/cocoawscommon.pas | 30 +++++++++++++ lcl/interfaces/cocoa/cocoawsforms.pp | 12 +++++- 6 files changed, 101 insertions(+), 13 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoagdiobjects.pas b/lcl/interfaces/cocoa/cocoagdiobjects.pas index 9eccddf914..1caee3bcd0 100644 --- a/lcl/interfaces/cocoa/cocoagdiobjects.pas +++ b/lcl/interfaces/cocoa/cocoagdiobjects.pas @@ -400,6 +400,7 @@ type public ctx: NSGraphicsContext; isControlDC: Boolean; // control DCs should never be freed by ReleaseDC as the control will free it by itself + isDesignDC: Boolean; // this is a special Designer Overlay DC constructor Create(AGraphicsContext: NSGraphicsContext); virtual; destructor Destroy; override; diff --git a/lcl/interfaces/cocoa/cocoalclintf.inc b/lcl/interfaces/cocoa/cocoalclintf.inc index 000f12fb0c..dacfe89079 100644 --- a/lcl/interfaces/cocoa/cocoalclintf.inc +++ b/lcl/interfaces/cocoa/cocoalclintf.inc @@ -137,24 +137,17 @@ begin DebugLn('TCarbonWidgetSet.GetLCLOwnerObject Result: ' + DbgS(Result)); {$ENDIF} end; - +*) {------------------------------------------------------------------------------ Method: IsDesignerDC Params: WindowHandle - Handle of window DC - Handle of device context Returns: If the device context is designer ------------------------------------------------------------------------------} -function TCarbonWidgetSet.IsDesignerDC(WindowHandle: HWND; DC: HDC): Boolean; +function TCocoaWidgetSet.IsDesignerDC(WindowHandle: HWND; DC: HDC): Boolean; begin - Result := False; - {$IFDEF VerboseLCLIntf} - DebugLn('TCarbonWidgetSet.IsDesignerDC Handle: ' + DbgS(WindowHandle), ' DC: ' + DbgS(DC)); - {$ENDIF} - - if not CheckWidget(WindowHandle, 'IsDesignerDC', TCarbonDesignWindow) then Exit; - Result := DC = HDC(TCarbonDesignWindow(WindowHandle).GetDesignContext); + Result := (WindowHandle <> 0) and (DC <> 0) and TCocoaContext(DC).isDesignDC; end; - *) procedure TCocoaWidgetSet.InitClipboard; begin diff --git a/lcl/interfaces/cocoa/cocoalclintfh.inc b/lcl/interfaces/cocoa/cocoalclintfh.inc index 4c1f0b716f..7225b3038a 100644 --- a/lcl/interfaces/cocoa/cocoalclintfh.inc +++ b/lcl/interfaces/cocoa/cocoalclintfh.inc @@ -31,9 +31,9 @@ function GetAcceleratorString(const AVKey: Byte; const AShiftState: TShiftState) function GetControlConstraints(Constraints: TObject): boolean; override; function GetDesignerDC(WindowHandle: HWND): HDC; override; function GetLCLOwnerObject(Handle: HWnd): TObject; override; - +} function IsDesignerDC(WindowHandle: HWND; DC: HDC): Boolean; override; - +{ function PromptUser(const DialogCaption : string; const DialogMessage : string; DialogType : LongInt; diff --git a/lcl/interfaces/cocoa/cocoaprivate.pp b/lcl/interfaces/cocoa/cocoaprivate.pp index 93aceab3f3..1048536d98 100644 --- a/lcl/interfaces/cocoa/cocoaprivate.pp +++ b/lcl/interfaces/cocoa/cocoaprivate.pp @@ -58,6 +58,7 @@ type // misc events procedure Draw(ctx: NSGraphicsContext; const bounds, dirty: NSRect); procedure DrawBackground(ctx: NSGraphicsContext; const bounds, dirty: NSRect); + procedure DrawOverlay(ctx: NSGraphicsContext; const bounds, dirty: NSRect); function ResetCursorRects: Boolean; procedure BecomeFirstResponder; procedure ResignFirstResponder; @@ -414,6 +415,17 @@ type procedure lclItemSelected(sender: id); message 'lclItemSelected:'; end; + { TCocoaDesignOverlay } + + TCocoaDesignOverlay = objcclass(NSView) + callback : ICommonCallback; + procedure drawRect(r: NSRect); override; + function acceptsFirstResponder: Boolean; override; + function hitTest(aPoint: NSPoint): NSView; override; + function lclGetCallback: ICommonCallback; override; + procedure lclClearCallback; override; + end; + { TCocoaCustomControl } TCocoaCustomControl = objcclass(NSControl) @@ -469,6 +481,7 @@ type isembedded: Boolean; // true - if the content is inside of another control, false - if the content is in its own window; ownwin: NSWindow; popup_parent: HWND; // if not 0, indicates that we should set the popup parent + overlay: NSView; procedure resolvePopupParent(); message 'resolvePopupParent'; function lclOwnWindow: NSWindow; message 'lclOwnWindow'; procedure lclSetFrame(const r: TRect); override; @@ -479,6 +492,7 @@ type procedure dealloc; override; procedure setHidden(aisHidden: Boolean); override; function lclIsHandle: Boolean; override; + procedure didAddSubview(aview: NSView); override; end; { TCocoaScrollView } @@ -1032,6 +1046,35 @@ begin {$ENDIF} end; +{ TCocoaDesignOverlay } + +procedure TCocoaDesignOverlay.drawRect(r: NSRect); +begin + if Assigned(callback) then + callback.DrawOverlay(NSGraphicsContext.currentContext, bounds, r); + inherited drawRect(r); +end; + +function TCocoaDesignOverlay.acceptsFirstResponder: Boolean; +begin + Result:=false; // no focus +end; + +function TCocoaDesignOverlay.hitTest(aPoint: NSPoint): NSView; +begin + Result:=nil; // no mouse +end; + +function TCocoaDesignOverlay.lclGetCallback: ICommonCallback; +begin + Result := callback; +end; + +procedure TCocoaDesignOverlay.lclClearCallback; +begin + callback := nil; +end; + { TCocoaManualScrollView } function TCocoaManualScrollView.lclGetCallback: ICommonCallback; @@ -1272,6 +1315,17 @@ begin Result:=true; end; +procedure TCocoaWindowContent.didAddSubview(aview: NSView); +begin + if Assigned(aview) and Assigned(overlay) and (overlay<>aview) then + begin + overlay.retain; + overlay.removeFromSuperview; + addSubview_positioned_relativeTo(overlay, NSWindowAbove, nil); + end; + inherited didAddSubview(aview); +end; + procedure TCocoaWindowContent.didBecomeKeyNotification(sender: NSNotification); begin if Assigned(callback) then diff --git a/lcl/interfaces/cocoa/cocoawscommon.pas b/lcl/interfaces/cocoa/cocoawscommon.pas index 17ca057090..8934591b50 100644 --- a/lcl/interfaces/cocoa/cocoawscommon.pas +++ b/lcl/interfaces/cocoa/cocoawscommon.pas @@ -70,6 +70,7 @@ type function DeliverMessage(Msg: Cardinal; WParam: WParam; LParam: LParam): LResult; virtual; overload; procedure Draw(ControlContext: NSGraphicsContext; const bounds, dirty: NSRect); virtual; procedure DrawBackground(ctx: NSGraphicsContext; const bounds, dirtyRect: NSRect); virtual; + procedure DrawOverlay(ControlContext: NSGraphicsContext; const bounds, dirty: NSRect); virtual; function ResetCursorRects: Boolean; virtual; property HasCaret: Boolean read GetHasCaret write SetHasCaret; @@ -1191,6 +1192,35 @@ begin end; end; +procedure TLCLCommonCallback.DrawOverlay(ControlContext: NSGraphicsContext; + const bounds, dirty: NSRect); +var + PS : TPaintStruct; + nsr : NSRect; +begin + // todo: think more about draw call while previous draw still active + if Assigned(FContext) then + Exit; + FContext := TCocoaContext.Create(ControlContext); + FContext.isControlDC := True; + FContext.isDesignDC := True; + try + // debugln('Draw '+Target.name+' bounds='+Dbgs(NSRectToRect(bounds))+' dirty='+Dbgs(NSRectToRect(dirty))); + if FContext.InitDraw(Round(bounds.size.width), Round(bounds.size.height)) then + begin + nsr:=dirty; + nsr.origin.y:=bounds.size.height-dirty.origin.y-dirty.size.height; + + FillChar(PS, SizeOf(TPaintStruct), 0); + PS.hdc := HDC(FContext); + PS.rcPaint := NSRectToRect(nsr); + LCLSendPaintMsg(Target, HDC(FContext), @PS); + end; + finally + FreeAndNil(FContext); + end; +end; + function TLCLCommonCallback.ResetCursorRects: Boolean; var ACursor: TCursor; diff --git a/lcl/interfaces/cocoa/cocoawsforms.pp b/lcl/interfaces/cocoa/cocoawsforms.pp index 38748f9b23..98d8d4a874 100644 --- a/lcl/interfaces/cocoa/cocoawsforms.pp +++ b/lcl/interfaces/cocoa/cocoawsforms.pp @@ -483,7 +483,8 @@ var R: NSRect; pool:NSAutoReleasePool; lDestView: NSView; - begin + ds: TCocoaDesignOverlay; +begin //todo: create TCocoaWindow or TCocoaPanel depending on the border style // if parent is specified neither Window nor Panel needs to be created // the only thing that needs to be created is Content @@ -537,6 +538,15 @@ var // support for drag & drop win.registerForDraggedTypes(NSArray.arrayWithObjects_count(@NSFilenamesPboardType, 1)); + + if IsFormDesign(AWinControl) then begin + ds:=(TCocoaDesignOverlay.alloc).initWithFrame(cnt.frame); + ds.callback := cnt.callback; + ds.setAutoresizingMask(NSViewWidthSizable or NSViewHeightSizable); + cnt.addSubview_positioned_relativeTo(ds, NSWindowAbove, nil); + cnt.overlay := ds; + end; + end else begin