Carbon intf:

- improved custom control focusing
- fixed visibility in IDE designer
- improved file dialog filtering using masks
LCL masks: added TParseStringList for parsing mask lists

git-svn-id: trunk@11944 -
This commit is contained in:
tombo 2007-09-05 11:38:47 +00:00
parent 61d494b039
commit f488c6af5e
7 changed files with 93 additions and 27 deletions

View File

@ -468,7 +468,7 @@ begin
{$ENDIF} {$ENDIF}
RegisterEvents; RegisterEvents;
LCLObject.InvalidateClientRectCache(True); LCLObject.InvalidateClientRectCache(True);
BoundsChanged; BoundsChanged;

View File

@ -173,7 +173,6 @@ type
FScrollOrigin: TPoint; FScrollOrigin: TPoint;
FScrollSize: TPoint; FScrollSize: TPoint;
FScrollPageSize: TPoint; FScrollPageSize: TPoint;
FFocusPart: ControlPartCode;
protected protected
procedure RegisterEvents; override; procedure RegisterEvents; override;
procedure CreateWidget(const AParams: TCreateParams); override; procedure CreateWidget(const AParams: TCreateParams); override;
@ -452,8 +451,6 @@ begin
Widget := CreateCustomHIView(ParamsToHIRect(AParams)); Widget := CreateCustomHIView(ParamsToHIRect(AParams));
if Widget = nil then RaiseCreateWidgetError(LCLObject); if Widget = nil then RaiseCreateWidgetError(LCLObject);
FFocusPart := kControlNoPart;
FScrollView := EmbedInScrollView(AParams); FScrollView := EmbedInScrollView(AParams);
FScrollSize := Classes.Point(0, 0); FScrollSize := Classes.Point(0, 0);
FScrollPageSize := Classes.Point(0, 0); FScrollPageSize := Classes.Point(0, 0);

View File

@ -40,6 +40,7 @@ function CarbonCommon_Draw(ANextHandler: EventHandlerCallRef;
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF} AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
var var
AStruct: PPaintStruct; AStruct: PPaintStruct;
EraseMsg: TLMEraseBkgnd;
begin begin
{$IFDEF VerbosePaint} {$IFDEF VerbosePaint}
Debugln('CarbonCommon_Draw ', DbgSName(AWidget.LCLObject)); Debugln('CarbonCommon_Draw ', DbgSName(AWidget.LCLObject));
@ -54,9 +55,13 @@ begin
SizeOf(CGContextRef), nil, @(AWidget.Context.CGContext)), SizeOf(CGContextRef), nil, @(AWidget.Context.CGContext)),
'CarbonCommon_Draw', SGetEvent, 'kEventParamCGContextRef') then Exit; 'CarbonCommon_Draw', SGetEvent, 'kEventParamCGContextRef') then Exit;
// erase background
EraseMsg.Msg := LM_ERASEBKGND;
EraseMsg.DC := HDC(AWidget.Context);
DeliverMessage(AWidget.LCLObject, EraseMsg);
// let carbon draw/update // let carbon draw/update
Result := CallNextEventHandler(ANextHandler, AEvent); Result := CallNextEventHandler(ANextHandler, AEvent);
if (AWidget is TCarbonControl) and if (AWidget is TCarbonControl) and
(cceDraw in (AWidget as TCarbonControl).GetValidEvents) then (cceDraw in (AWidget as TCarbonControl).GetValidEvents) then
@ -304,14 +309,13 @@ function CarbonCommon_SetFocusPart(ANextHandler: EventHandlerCallRef;
AEvent: EventRef; AEvent: EventRef;
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF} AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
var var
CurrentFocus,
FocusPart: ControlPartCode; FocusPart: ControlPartCode;
const const
SName = 'CarbonCommon_SetFocusPart'; SName = 'CarbonCommon_SetFocusPart';
begin begin
if not (AWidget.LCLObject is TCustomControl) then if not (AWidget is TCarbonCustomControl) then
Result := CallNextEventHandler(ANextHandler, AEvent) Result := CallNextEventHandler(ANextHandler, AEvent);
else
Result := noErr;
if OSError( if OSError(
GetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode, nil, GetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode, nil,
@ -322,6 +326,28 @@ begin
DebugLn('CarbonCommon_SetFocusPart: ', DbgSName(AWidget.LCLObject), ' ' + DebugLn('CarbonCommon_SetFocusPart: ', DbgSName(AWidget.LCLObject), ' ' +
IntToStr(Integer(FocusPart))); IntToStr(Integer(FocusPart)));
{$ENDIF} {$ENDIF}
if AWidget is TCarbonCustomControl then
begin
OSError(HIViewGetFocusPart(AWidget.Content, CurrentFocus),
SName, 'HIViewGetFocusPart');
case FocusPart of
kControlFocusPrevPart,
kControlFocusNextPart:
if CurrentFocus = kControlNoPart then FocusPart := kControlEditTextPart
else FocusPart := kControlEditTextPart;
kControlEditTextPart:;
else
FocusPart := kControlNoPart;
end;
OSError(
SetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode,
SizeOf(ControlPartCode), @FocusPart), SName, SSetEvent, SControlPart);
Result := noErr;
end;
if FocusPart <> kControlFocusNoPart then if FocusPart <> kControlFocusNoPart then
LCLSendSetFocusMsg(AWidget.LCLObject) LCLSendSetFocusMsg(AWidget.LCLObject)

View File

@ -853,7 +853,8 @@ var
begin begin
//DebugLn('TCarbonControl.ShowHide ' + DbgSName(LCLobject),' ', DbgS(AVisible)); //DebugLn('TCarbonControl.ShowHide ' + DbgSName(LCLobject),' ', DbgS(AVisible));
for I := 0 to GetFrameCount - 1 do for I := 0 to GetFrameCount - 1 do
OSError(HIViewSetVisible(Frames[I], AVisible), Self, 'ShowHide', SViewVisible); OSError(HIViewSetVisible(Frames[I], AVisible or (csDesigning in LCLobject.ComponentState)),
Self, 'ShowHide', SViewVisible);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------

View File

@ -978,7 +978,7 @@ begin
SetBounds(Bounds(AParams.X, AParams.Y, AParams.Width, AParams.Height)); SetBounds(Bounds(AParams.X, AParams.Y, AParams.Width, AParams.Height));
SetText(AParams.Caption); SetText(AParams.Caption);
DebugLn('TCarbonWindow.CreateWidget succeeds'); //DebugLn('TCarbonWindow.CreateWidget succeeds');
SetColor(LCLObject.Color); SetColor(LCLObject.Color);
MinSize.width := LCLObject.Constraints.EffectiveMinWidth; MinSize.width := LCLObject.Constraints.EffectiveMinWidth;
@ -1303,7 +1303,9 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TCarbonWindow.ShowHide(AVisible: Boolean); procedure TCarbonWindow.ShowHide(AVisible: Boolean);
begin begin
if AVisible then //DebugLn('TCarbonWindow.ShowHide ' + DbgSName(LCLobject),' ', DbgS(AVisible));
if AVisible or (csDesigning in LCLobject.ComponentState) then
FPCMacOSAll.ShowWindow(WindowRef(Widget)) FPCMacOSAll.ShowWindow(WindowRef(Widget))
else else
FPCMacOSAll.HideWindow(WindowRef(Widget)); FPCMacOSAll.HideWindow(WindowRef(Widget));

View File

@ -33,7 +33,7 @@ uses
// libs // libs
FPCMacOSAll, FPCMacOSAll,
// LCL // LCL
SysUtils, Controls, Dialogs, LCLType, LCLProc, Classes, SysUtils, Controls, Dialogs, LCLType, LCLProc, Masks,
// widgetset // widgetset
WSLCLClasses, WSProc, WSDialogs, WSLCLClasses, WSProc, WSDialogs,
// LCL Carbon // LCL Carbon
@ -115,15 +115,17 @@ uses
{ TCarbonWSFileDialog } { TCarbonWSFileDialog }
function FilterByExtCallback(var theItem: AEDesc; info: NavFileOrFolderInfoPtr; var
FilterMask: TMaskList;
function FilterCallback(var theItem: AEDesc; info: NavFileOrFolderInfoPtr;
callbackUD: UnivPtr; filterMode: NavFilterModes): Boolean; stdcall; callbackUD: UnivPtr; filterMode: NavFilterModes): Boolean; stdcall;
{Custom filter callback function. Pointer to this function is passed as {Custom filter callback function. Pointer to this function is passed as
inFilterProc to NavCreateGetFileDialog and NavCreateChooseFolderDialog. inFilterProc to NavCreateGetFileDialog and NavCreateChooseFolderDialog.
If theItem file should be highlighted in file dialog, return True; If theItem file should be highlighted in file dialog, return True;
if it should be dimmed in file dialog, return False. if it should be dimmed in file dialog, return False.
The callbackUD param contains file dialog object passed as inClientData The callbackUD param contains file dialog object passed as inClientData
to NavCreateGetFileDialog and NavCreateChooseFolderDialog. to NavCreateGetFileDialog and NavCreateChooseFolderDialog.}
Note: This function filters only by file extension, not by wildcard file spec.}
var var
FileRef: FSRef; FileRef: FSRef;
FileURL: CFURLRef; FileURL: CFURLRef;
@ -161,11 +163,9 @@ begin
FreeCFString(FileURL); FreeCFString(FileURL);
FreeCFString(FileCFStr); FreeCFString(FileCFStr);
// TODO: use mask for filtering Result := (FilterMask = nil) or FilterMask.Matches(ExtractFilename(FilePath));
Result := Pos(LowerCase(ExtractFileExt(FilePath)), //DebugLn('FilterCallback ' + DbgS(FilterMask) + ' ' + ExtractFilename(FilePath) + ' ' + DbgS(Result));
LowerCase(TFileDialog(callbackUD).Filter)) > 0; end; {FilterCallback}
end; {FilterByExtCallback}
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
@ -195,6 +195,8 @@ var
FileRef: FSRef; FileRef: FSRef;
FileURL: CFURLRef; FileURL: CFURLRef;
FileCFStr: CFStringRef; FileCFStr: CFStringRef;
Filters: TParseStringList;
I: Integer;
begin begin
{$IFDEF VerboseWSClass} {$IFDEF VerboseWSClass}
DebugLn('TCarbonWSFileDialog.ShowModal for ' + ACommonDialog.Name); DebugLn('TCarbonWSFileDialog.ShowModal for ' + ACommonDialog.Name);
@ -211,8 +213,20 @@ begin
FileDialog.UserChoice := mrCancel; // Return this if user cancels or we need to exit FileDialog.UserChoice := mrCancel; // Return this if user cancels or we need to exit
FilterUPP := NewNavObjectFilterUPP(NavObjectFilterProcPtr(@FilterByExtCallback)); FilterUPP := NewNavObjectFilterUPP(NavObjectFilterProcPtr(@FilterCallback));
Filters := TParseStringList.Create(FileDialog.Filter, '|');
try
if (FileDialog.FilterIndex >= 0) and
(FileDialog.FilterIndex * 2 + 1 < Filters.Count) then
begin
//DebugLn('Filter ' + Filters[FileDialog.FilterIndex * 2 + 1]);
FilterMask := TMaskList.Create(Filters[FileDialog.FilterIndex * 2 + 1]);
end;
finally
Filters.Free;
end;
try try
if FileDialog is TSaveDialog then if FileDialog is TSaveDialog then
begin // Checking for TSaveDialog first since it's descendent of TOpenDialog begin // Checking for TSaveDialog first since it's descendent of TOpenDialog
@ -315,6 +329,7 @@ begin
end; end;
finally finally
FreeAndNil(FilterMask);
DisposeNavObjectFilterUPP(FilterUPP); DisposeNavObjectFilterUPP(FilterUPP);
FreeCFString(CreationOptions.windowTitle); FreeCFString(CreationOptions.windowTitle);
FreeCFString(CreationOptions.saveFileName); FreeCFString(CreationOptions.saveFileName);

View File

@ -58,6 +58,13 @@ type
function Matches(const AFileName: String): Boolean; function Matches(const AFileName: String): Boolean;
end; end;
{ TParseStringList }
TParseStringList = class(TStringList)
public
constructor Create(const AText, ASeparators: String);
end;
{ TMaskList } { TMaskList }
TMaskList = class TMaskList = class
@ -322,6 +329,27 @@ begin
Result := MatchToEnd(0, 1); Result := MatchToEnd(0, 1);
end; end;
{ TParseStringList }
constructor TParseStringList.Create(const AText, ASeparators: String);
var
I, S: Integer;
begin
inherited Create;
S := 1;
for I := 1 to Length(AText) do
begin
if Pos(AText[I], ASeparators) > 0 then
begin
if I > S then Add(Copy(AText, S, I - S));
S := I + 1;
end;
end;
if Length(AText) > S then Add(Copy(AText, S, Length(AText) - S + 1));
end;
{ TMaskList } { TMaskList }
function TMaskList.GetItem(Index: Integer): TMask; function TMaskList.GetItem(Index: Integer): TMask;
@ -336,16 +364,13 @@ end;
constructor TMaskList.Create(const AValue: String; ASeparator: Char); constructor TMaskList.Create(const AValue: String; ASeparator: Char);
var var
S: TStringList; S: TParseStringList;
I: Integer; I: Integer;
begin begin
FMasks := TObjectList.Create(True); FMasks := TObjectList.Create(True);
S := TStringList.Create; S := TParseStringList.Create(AValue, ASeparator + ' ');
try try
S.Delimiter := ASeparator;
S.DelimitedText := AValue;
for I := 0 to S.Count - 1 do for I := 0 to S.Count - 1 do
FMasks.Add(TMask.Create(S[I])); FMasks.Add(TMask.Create(S[I]));
finally finally