mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-20 11:59:08 +02:00
Cocoa: LookupWord implemented in FullControlEdit
This commit is contained in:
parent
6153ab067b
commit
cfbd95b451
@ -74,6 +74,7 @@ type
|
||||
_currentMarkedText: NSString;
|
||||
public
|
||||
imeHandler: ICocoaIMEControl;
|
||||
lwHandler: ICocoaLookupWord;
|
||||
public
|
||||
procedure keyDown(theEvent: NSEvent); override;
|
||||
procedure mouseDown(event: NSEvent); override;
|
||||
@ -270,18 +271,91 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{
|
||||
the Cocoa API uses a continuous positive integer to locate the text position,
|
||||
mainly in:
|
||||
1. get the text index corresponding to the current mouse cursor through
|
||||
the return value of characterIndexForPoint()
|
||||
2. the text is obtained through the parameter aRange.location passed in by
|
||||
attributedSubstringForProposedRange_actualRange().
|
||||
note that Cocoa assumes that the index are continuous, with -1 corresponding
|
||||
to the previous character and +1 corresponding to the next character,
|
||||
which is where the trouble comes in.
|
||||
|
||||
however, in the controls such as SynEdit, there is no corresponding Index.
|
||||
although the index can be calculated by traversing each line, it increases
|
||||
the workload and complexity.
|
||||
|
||||
in Lookup Word, we only need to ensure that the index is continuous in a line,
|
||||
so a simplified method is used:
|
||||
1. controls such as SynEdit are indexed by row + column
|
||||
2. the index required by Cooca is a 64-bit integer
|
||||
3. so the rows and columns are encoded into 64-bit Index, with
|
||||
the high 32 bits corresponding to the rows and
|
||||
the lower 32 bits corresponding to the columns.
|
||||
4. the operation on the Index cannot cross line. if it does,
|
||||
a simple correction is required. see rangeToLWParams().
|
||||
}
|
||||
|
||||
const
|
||||
LW_LOCATION_BASE = $1000000000000000;
|
||||
|
||||
function rangeToLWParams( const aRange: NSRange ): TCocoaLWParameters;
|
||||
var
|
||||
location: NSUInteger;
|
||||
begin
|
||||
location:= aRange.location;
|
||||
if location >= (LW_LOCATION_BASE/2) then
|
||||
location:= location - LW_LOCATION_BASE;
|
||||
Result.row:= location shr 32;
|
||||
Result.col:= location and $FFFFFFFF;
|
||||
Result.length:= aRange.length;
|
||||
if Result.col < 0 then begin
|
||||
Result.col:= 0;
|
||||
Result.row:= Result.row + 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function LWParamsToRange( const params: TCocoaLWParameters ): NSRange;
|
||||
var
|
||||
location: NSUInteger;
|
||||
begin
|
||||
location:= (QWord(params.row) shl 32) + params.col;
|
||||
Result.location:= location + LW_LOCATION_BASE;
|
||||
Result.length:= params.length;
|
||||
end;
|
||||
|
||||
// cursor tracking
|
||||
function TCocoaFullControlEdit.firstRectForCharacterRange_actualRange(
|
||||
aRange: NSRange; actualRange: NSRangePointer): NSRect;
|
||||
|
||||
function getImeTextBound: TRect;
|
||||
var
|
||||
params: TCocoaIMEParameters;
|
||||
begin
|
||||
params:= _currentParams;
|
||||
setIMESelectedRange( params, _currentMarkedText, aRange );
|
||||
params.isFirstCall:= not hasMarkedText();
|
||||
Result:= imeHandler.IMEGetTextBound( params );
|
||||
end;
|
||||
|
||||
function getLookupWordBound: TRect;
|
||||
var
|
||||
params: TCocoaLWParameters;
|
||||
begin
|
||||
params:= rangeToLWParams( aRange );
|
||||
Result:= lwHandler.LWGetTextBound( params );
|
||||
end;
|
||||
|
||||
var
|
||||
params: TCocoaIMEParameters;
|
||||
rect : TRect;
|
||||
begin
|
||||
params:= _currentParams;
|
||||
setIMESelectedRange( params, _currentMarkedText, aRange );
|
||||
params.isFirstCall:= not hasMarkedText();
|
||||
|
||||
rect:= imeHandler.IMEGetTextBound( params );
|
||||
if aRange.location < LW_LOCATION_BASE then begin
|
||||
rect:= getImeTextBound;
|
||||
end else begin
|
||||
rect:= getLookupWordBound;
|
||||
end;
|
||||
LCLToNSRect( rect, NSGlobalScreenBottom, Result );
|
||||
end;
|
||||
|
||||
@ -317,10 +391,77 @@ begin
|
||||
Result:= ( _currentParams.textNSLength > 0 );
|
||||
end;
|
||||
|
||||
{
|
||||
1. given the previous description of not crossing lines,
|
||||
at most one line of text is returned.
|
||||
2. LW_LOCATION_BASE has been added to location to distinguish
|
||||
between IME and Lookup Word.
|
||||
}
|
||||
function TCocoaFullControlEdit.attributedSubstringForProposedRange_actualRange(
|
||||
aRange: NSRange; actualRange: NSRangePointer): NSAttributedString;
|
||||
var
|
||||
params: TCocoaLWParameters;
|
||||
textWord: NSString;
|
||||
|
||||
procedure initParams;
|
||||
begin
|
||||
params:= rangeToLWParams( aRange );
|
||||
self.lwHandler.LWLineForRow( params );
|
||||
end;
|
||||
|
||||
procedure initTextWord;
|
||||
var
|
||||
lineText: NSString;
|
||||
subRange: NSRange;
|
||||
begin
|
||||
lineText:= StrToNSString( params.text );
|
||||
subRange.location:= params.col;
|
||||
subRange.length:= aRange.length;
|
||||
if subRange.location + subRange.length > lineText.length then
|
||||
subRange.length:= lineText.length - subRange.location;
|
||||
textWord:= lineText.substringWithRange(subRange);
|
||||
end;
|
||||
|
||||
function getAttributeWord: NSAttributedString;
|
||||
var
|
||||
attribs: NSDictionary;
|
||||
lclFont: TFont;
|
||||
cocoaFont: NSFont;
|
||||
begin
|
||||
lclFont:= self.lwHandler.LWGetFont( params );
|
||||
cocoaFont:= TCocoaFont(lclFont.Reference.Handle).Font;
|
||||
attribs:= NSMutableDictionary.alloc.initWithCapacity(1);
|
||||
attribs.setValue_forKey( cocoaFont, NSFontAttributeName );
|
||||
Result:= NSAttributedString.alloc.initWithString_attributes(
|
||||
textWord, attribs );
|
||||
Result.autorelease;
|
||||
attribs.release;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := nil;
|
||||
Result:= nil;
|
||||
|
||||
if NOT Assigned(self.lwHandler) then
|
||||
Exit;
|
||||
|
||||
initParams;
|
||||
initTextWord;
|
||||
actualRange^:= LWParamsToRange( params );
|
||||
Result:= getAttributeWord;
|
||||
end;
|
||||
|
||||
function TCocoaFullControlEdit.characterIndexForPoint(aPoint: NSPoint
|
||||
): NSUInteger;
|
||||
var
|
||||
params: TCocoaLWParameters;
|
||||
lclPoint: TPoint;
|
||||
begin
|
||||
Result:= 0;
|
||||
if NOT Assigned(self.lwHandler) then
|
||||
Exit;
|
||||
lclPoint:= ScreenPointFromNSToLCL( aPoint );
|
||||
self.lwHandler.LWRowColForScreenPoint( params, lclPoint );
|
||||
Result:= LWParamsToRange(params).location;
|
||||
end;
|
||||
|
||||
function TCocoaFullControlEdit.validAttributesForMarkedText: NSArray;
|
||||
@ -328,11 +469,5 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TCocoaFullControlEdit.characterIndexForPoint(aPoint: NSPoint
|
||||
): NSUInteger;
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user