cocoa: reimplement form using NSPanel, reimplement modality using form enabling/disabling

git-svn-id: trunk@34706 -
This commit is contained in:
paul 2012-01-11 07:07:25 +00:00
parent e51a29d78d
commit 76ea22831e
3 changed files with 249 additions and 171 deletions

View File

@ -211,6 +211,7 @@ begin
lcNeedMininimizeAppWithMainForm,
lcApplicationTitle,
lcFormIcon,
lcModalWindow,
lcReceivesLMClearCutCopyPasteReliably:
Result := LCL_CAPABILITY_NO;
lcAntialiasingEnabledByDefault:

View File

@ -149,12 +149,18 @@ type
{ IWindowCallback }
IWindowCallback = interface(ICommonCallBack)
function CanActivate: Boolean;
procedure Activate;
procedure Deactivate;
procedure CloseQuery(var CanClose: Boolean);
procedure Close;
procedure Resize;
procedure Move;
function GetEnabled: Boolean;
procedure SetEnabled(AValue: Boolean);
property Enabled: Boolean read GetEnabled write SetEnabled;
end;
{ TCocoaMenu }
@ -235,9 +241,9 @@ type
procedure resetCursorRects; override;
end;
{ TCocoaWindow }
{ TCocoaPanel }
TCocoaWindow = objcclass(NSWindow, NSWindowDelegateProtocol)
TCocoaPanel = objcclass(NSPanel, NSWindowDelegateProtocol)
protected
function windowShouldClose(sender : id): LongBool; message 'windowShouldClose:';
procedure windowWillClose(notification: NSNotification); message 'windowWillClose:';
@ -248,6 +254,7 @@ type
public
callback: IWindowCallback;
function acceptsFirstResponder: Boolean; override;
function canBecomeKeyWindow: Boolean; override;
function becomeFirstResponder: Boolean; override;
function resignFirstResponder: Boolean; override;
function lclGetCallback: ICommonCallback; override;
@ -414,6 +421,160 @@ begin
AView.setAutoresizingMask(NSViewMinYMargin or NSViewMaxXMargin);
end;
{ TCocoaPanel }
function TCocoaPanel.windowShouldClose(sender: id): LongBool;
var
canClose: Boolean;
begin
canClose := True;
callback.CloseQuery(canClose);
Result := canClose;
end;
procedure TCocoaPanel.windowWillClose(notification: NSNotification);
begin
callback.Close;
end;
procedure TCocoaPanel.windowDidBecomeKey(notification: NSNotification);
begin
callback.Activate;
end;
procedure TCocoaPanel.windowDidResignKey(notification: NSNotification);
begin
callback.Deactivate;
end;
procedure TCocoaPanel.windowDidResize(notification: NSNotification);
begin
callback.Resize;
end;
procedure TCocoaPanel.windowDidMove(notification: NSNotification);
begin
callback.Move;
end;
function TCocoaPanel.acceptsFirstResponder: Boolean;
begin
Result := True;
end;
function TCocoaPanel.canBecomeKeyWindow: Boolean;
begin
Result := callback.CanActivate;
end;
function TCocoaPanel.becomeFirstResponder: Boolean;
begin
Result := inherited becomeFirstResponder;
callback.BecomeFirstResponder;
end;
function TCocoaPanel.resignFirstResponder: Boolean;
begin
Result := inherited resignFirstResponder;
callback.ResignFirstResponder;
end;
function TCocoaPanel.lclGetCallback: ICommonCallback;
begin
Result := callback;
end;
procedure TCocoaPanel.mouseDown(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited mouseDown(event);
end;
procedure TCocoaPanel.mouseUp(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited mouseUp(event);
end;
procedure TCocoaPanel.rightMouseDown(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited rightMouseUp(event);
end;
procedure TCocoaPanel.rightMouseUp(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited rightMouseDown(event);
end;
procedure TCocoaPanel.otherMouseDown(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited otherMouseDown(event);
end;
procedure TCocoaPanel.otherMouseUp(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited otherMouseUp(event);
end;
procedure TCocoaPanel.mouseDragged(event: NSEvent);
begin
if not callback.MouseMove(event) then
inherited mouseDragged(event);
end;
procedure TCocoaPanel.mouseEntered(event: NSEvent);
begin
inherited mouseEntered(event);
end;
procedure TCocoaPanel.mouseExited(event: NSEvent);
begin
inherited mouseExited(event);
end;
procedure TCocoaPanel.mouseMoved(event: NSEvent);
begin
if not callback.MouseMove(event) then
inherited mouseMoved(event);
end;
procedure TCocoaPanel.sendEvent(event: NSEvent);
var
Message: NSMutableDictionary;
Handle: HWND;
Msg: Cardinal;
WP: WParam;
LP: LParam;
Result: NSNumber;
Obj: NSObject;
begin
if event.type_ = NSApplicationDefined then
begin
// event which we get through PostMessage or SendMessage
if event.subtype = LCLEventSubTypeMessage then
begin
// extract message data
Message := NSMutableDictionary(event.data1);
Handle := NSNumber(Message.objectForKey(NSMessageWnd)).unsignedIntegerValue;
Msg := NSNumber(Message.objectForKey(NSMessageMsg)).unsignedLongValue;
WP := NSNumber(Message.objectForKey(NSMessageWParam)).integerValue;
LP := NSNumber(Message.objectForKey(NSMessageLParam)).integerValue;
// deliver message and set result
Obj := NSObject(Handle);
// todo: check that Obj is still a valid NSView/NSWindow
Result := NSNumber.numberWithInteger(Obj.lclDeliverMessage(Msg, WP, LP));
Message.setObject_forKey(Result, NSMessageResult);
Result.release;
end;
end
else
inherited sendEvent(event);
end;
{ TCocoaScrollView }
function TCocoaScrollView.acceptsFirstResponder: Boolean;
@ -602,7 +763,8 @@ end;
procedure TCocoaButton.mouseDragged(event: NSEvent);
begin
inherited mouseDragged(event);
if not callback.MouseMove(event) then
inherited mouseDragged(event);
end;
procedure TCocoaButton.mouseEntered(event: NSEvent);
@ -617,7 +779,8 @@ end;
procedure TCocoaButton.mouseMoved(event: NSEvent);
begin
inherited mouseMoved(event);
if not callback.MouseMove(event) then
inherited mouseMoved(event);
end;
{ TCocoaTextField }
@ -683,155 +846,6 @@ begin
inherited resetCursorRects;
end;
{ TCocoaWindow }
function TCocoaWindow.windowShouldClose(sender: id): LongBool;
var
canClose: Boolean;
begin
canClose := True;
callback.CloseQuery(canClose);
Result := canClose;
end;
procedure TCocoaWindow.windowWillClose(notification: NSNotification);
begin
callback.Close;
end;
procedure TCocoaWindow.windowDidBecomeKey(notification: NSNotification);
begin
callback.Activate;
end;
procedure TCocoaWindow.windowDidResignKey(notification: NSNotification);
begin
callback.Deactivate;
end;
procedure TCocoaWindow.windowDidResize(notification: NSNotification);
begin
callback.Resize;
end;
procedure TCocoaWindow.windowDidMove(notification: NSNotification);
begin
callback.Move;
end;
function TCocoaWindow.acceptsFirstResponder: Boolean;
begin
Result := True;
end;
function TCocoaWindow.becomeFirstResponder: Boolean;
begin
Result := inherited becomeFirstResponder;
callback.BecomeFirstResponder;
end;
function TCocoaWindow.resignFirstResponder: Boolean;
begin
Result := inherited resignFirstResponder;
callback.ResignFirstResponder;
end;
function TCocoaWindow.lclGetCallback: ICommonCallback;
begin
Result := callback;
end;
procedure TCocoaWindow.mouseUp(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited mouseUp(event);
end;
procedure TCocoaWindow.rightMouseDown(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited rightMouseDown(event);
end;
procedure TCocoaWindow.rightMouseUp(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited rightMouseUp(event);
end;
procedure TCocoaWindow.otherMouseDown(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited otherMouseDown(event);
end;
procedure TCocoaWindow.otherMouseUp(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited otherMouseUp(event);
end;
procedure TCocoaWindow.mouseDown(event: NSEvent);
begin
if not callback.MouseUpDownEvent(event) then
inherited mouseDown(event);
end;
procedure TCocoaWindow.mouseDragged(event: NSEvent);
begin
if not callback.MouseMove(event) then
inherited mouseDragged(event);
end;
procedure TCocoaWindow.mouseMoved(event: NSEvent);
begin
if not callback.MouseMove(event) then
inherited mouseMoved(event);
end;
procedure TCocoaWindow.sendEvent(event: NSEvent);
var
Message: NSMutableDictionary;
Handle: HWND;
Msg: Cardinal;
WP: WParam;
LP: LParam;
Result: NSNumber;
Obj: NSObject;
begin
if event.type_ = NSApplicationDefined then
begin
// event which we get through PostMessage or SendMessage
if event.subtype = LCLEventSubTypeMessage then
begin
// extract message data
Message := NSMutableDictionary(event.data1);
Handle := NSNumber(Message.objectForKey(NSMessageWnd)).unsignedIntegerValue;
Msg := NSNumber(Message.objectForKey(NSMessageMsg)).unsignedLongValue;
WP := NSNumber(Message.objectForKey(NSMessageWParam)).integerValue;
LP := NSNumber(Message.objectForKey(NSMessageLParam)).integerValue;
// deliver message and set result
Obj := NSObject(Handle);
// todo: check that Obj is still a valid NSView/NSWindow
Result := NSNumber.numberWithInteger(Obj.lclDeliverMessage(Msg, WP, LP));
Message.setObject_forKey(Result, NSMessageResult);
Result.release;
end;
end
else
inherited sendEvent(event);
end;
procedure TCocoaWindow.mouseEntered(event: NSEvent);
begin
inherited mouseEntered(event);
end;
procedure TCocoaWindow.mouseExited(event: NSEvent);
begin
inherited mouseExited(event);
end;
{ TCocoaSecureTextField }
function TCocoaSecureTextField.acceptsFirstResponder: Boolean;
@ -1263,13 +1277,25 @@ begin
end;
function LCLWindowExtension.lclIsEnabled: Boolean;
var
Callback: ICommonCallback;
begin
Result := contentView.lclIsEnabled;
Callback := lclGetCallback;
if Assigned(Callback) then
Result := IWindowCallback(Callback).Enabled
else
Result := contentView.lclIsEnabled;
end;
procedure LCLWindowExtension.lclSetEnabled(AEnabled: Boolean);
var
Callback: ICommonCallback;
begin
contentView.lclSetEnabled(AEnabled);
Callback := lclGetCallback;
if Assigned(Callback) then
IWindowCallback(Callback).Enabled := AEnabled
else
contentView.lclSetEnabled(AEnabled);
end;
function LCLWindowExtension.lclWindowState: Integer;

View File

@ -42,12 +42,18 @@ type
TLCLWindowCallback = class(TLCLCommonCallBack, IWindowCallback)
public
function CanActivate: Boolean; virtual;
procedure Activate; virtual;
procedure Deactivate; virtual;
procedure CloseQuery(var CanClose: Boolean); virtual;
procedure Close; virtual;
procedure Resize; virtual;
procedure Move; virtual;
function GetEnabled: Boolean; virtual;
procedure SetEnabled(AValue: Boolean); virtual;
property Enabled: Boolean read GetEnabled write SetEnabled;
end;
@ -127,7 +133,7 @@ type
private
protected
public
// class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
end;
{ TCocoaWSScreen }
@ -152,8 +158,44 @@ implementation
uses
CocoaInt;
{ TCocoaWSHintWindow }
class function TCocoaWSHintWindow.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle;
var
win: TCocoaPanel;
cnt: TCocoaCustomControl;
const
WinMask = NSBorderlessWindowMask or NSUtilityWindowMask;
begin
win := TCocoaPanel(TCocoaPanel.alloc);
if not Assigned(win) then
begin
Result := 0;
Exit;
end;
win := TCocoaPanel(win.initWithContentRect_styleMask_backing_defer(CreateParamsToNSRect(AParams), WinMask, NSBackingStoreBuffered, False));
win.enableCursorRects;
TCocoaPanel(win).callback := TLCLWindowCallback.Create(win, AWinControl);
win.setDelegate(win);
win.setAcceptsMouseMovedEvents(True);
cnt := TCocoaCustomControl.alloc.init;
cnt.callback := TCocoaPanel(win).callback;
win.setContentView(cnt);
Result := TLCLIntfHandle(win);
end;
{ TLCLWindowCallback }
function TLCLWindowCallback.CanActivate: Boolean;
begin
Result := Enabled;
end;
procedure TLCLWindowCallback.Activate;
begin
LCLSendActivateMsg(Target, True, false);
@ -167,7 +209,7 @@ end;
procedure TLCLWindowCallback.CloseQuery(var CanClose: Boolean);
begin
// Message results : 0 - do nothing, 1 - destroy window
CanClose:=LCLSendCloseQueryMsg(Target)>0;
CanClose := LCLSendCloseQueryMsg(Target) > 0;
end;
procedure TLCLWindowCallback.Close;
@ -185,6 +227,16 @@ begin
boundsDidChange;
end;
function TLCLWindowCallback.GetEnabled: Boolean;
begin
Result := NSWindow(Owner).contentView.lclIsEnabled;
end;
procedure TLCLWindowCallback.SetEnabled(AValue: Boolean);
begin
NSWindow(Owner).contentView.lclSetEnabled(AValue);
end;
{ TCocoaWSCustomForm }
@ -234,13 +286,13 @@ end;
class function TCocoaWSCustomForm.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle;
var
win: TCocoaWindow;
win: TCocoaPanel;
cnt: TCocoaCustomControl;
ns: NSString;
const
WinMask = NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask or NSResizableWindowMask;
WinMask= NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask or NSResizableWindowMask;
begin
win := TCocoaWindow(TCocoaWindow.alloc);
win := TCocoaPanel(TCocoaPanel.alloc);
if not Assigned(win) then
begin
@ -248,9 +300,9 @@ begin
Exit;
end;
win := TCocoaWindow(win.initWithContentRect_styleMask_backing_defer(CreateParamsToNSRect(AParams), WinMask, NSBackingStoreBuffered, False));
win := TCocoaPanel(win.initWithContentRect_styleMask_backing_defer(CreateParamsToNSRect(AParams), WinMask, NSBackingStoreBuffered, False));
win.enableCursorRects;
TCocoaWindow(win).callback := TLCLWindowCallback.Create(win, AWinControl);
TCocoaPanel(win).callback := TLCLWindowCallback.Create(win, AWinControl);
win.setDelegate(win);
ns := NSStringUtf8(AWinControl.Caption);
win.setTitle(ns);
@ -258,7 +310,7 @@ begin
win.setAcceptsMouseMovedEvents(True);
cnt := TCocoaCustomControl.alloc.init;
cnt.callback := TCocoaWindow(win).callback;
cnt.callback := TCocoaPanel(win).callback;
win.setContentView(cnt);
if (AParams.Style and WS_CHILD) = 0 then
@ -278,14 +330,14 @@ class function TCocoaWSCustomForm.GetText(const AWinControl: TWinControl; var AT
begin
Result := AWinControl.HandleAllocated;
if Result then
AText := NSStringToString(TCocoaWindow(AWinControl.Handle).title);
AText := NSStringToString(NSWindow(AWinControl.Handle).title);
end;
class function TCocoaWSCustomForm.GetTextLen(const AWinControl: TWinControl; var ALength: Integer): Boolean;
begin
Result := AWinControl.HandleAllocated;
if Result then
ALength := TCocoaWindow(AWinControl.Handle).title.length;
ALength := NSWindow(AWinControl.Handle).title.length;
end;
class procedure TCocoaWSCustomForm.SetText(const AWinControl: TWinControl; const AText: String);
@ -294,21 +346,20 @@ var
begin
if not AWinControl.HandleAllocated then Exit;
ns := NSStringUtf8(AText);
TCocoaWindow(AWinControl.Handle).setTitle(ns);
NSwindow(AWinControl.Handle).setTitle(ns);
ns.release;
end;
class procedure TCocoaWSCustomForm.CloseModal(const ACustomForm: TCustomForm);
begin
if ACustomForm.HandleAllocated then
if CocoaWidgetSet.NSApp.modalWindow = NSWindow(ACustomForm.Handle) then
CocoaWidgetSet.NSApp.stopModal;
// if ACustomForm.HandleAllocated then
// NSPanel(ACustomForm.Handle).setStyleMask(NSwindow(ACustomForm.Handle).styleMask and not NSDocModalWindowMask);
end;
class procedure TCocoaWSCustomForm.ShowModal(const ACustomForm: TCustomForm);
begin
if ACustomForm.HandleAllocated then
CocoaWidgetSet.NSApp.runModalForWindow(NSWindow(ACustomForm.Handle));
// if ACustomForm.HandleAllocated then
// NSPanel(ACustomForm.Handle).setStyleMask(NSwindow(ACustomForm.Handle).styleMask or NSDocModalWindowMask);
end;
class procedure TCocoaWSCustomForm.SetAlphaBlend(const ACustomForm: TCustomForm; const AlphaBlend: Boolean; const Alpha: Byte);