mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-22 04:39:27 +02:00
Cocoa: LookupWord implemented in FullControlEdit
This commit is contained in:
parent
6153ab067b
commit
cfbd95b451
@ -74,6 +74,7 @@ type
|
|||||||
_currentMarkedText: NSString;
|
_currentMarkedText: NSString;
|
||||||
public
|
public
|
||||||
imeHandler: ICocoaIMEControl;
|
imeHandler: ICocoaIMEControl;
|
||||||
|
lwHandler: ICocoaLookupWord;
|
||||||
public
|
public
|
||||||
procedure keyDown(theEvent: NSEvent); override;
|
procedure keyDown(theEvent: NSEvent); override;
|
||||||
procedure mouseDown(event: NSEvent); override;
|
procedure mouseDown(event: NSEvent); override;
|
||||||
@ -270,18 +271,91 @@ begin
|
|||||||
end;
|
end;
|
||||||
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
|
// cursor tracking
|
||||||
function TCocoaFullControlEdit.firstRectForCharacterRange_actualRange(
|
function TCocoaFullControlEdit.firstRectForCharacterRange_actualRange(
|
||||||
aRange: NSRange; actualRange: NSRangePointer): NSRect;
|
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
|
var
|
||||||
params: TCocoaIMEParameters;
|
|
||||||
rect : TRect;
|
rect : TRect;
|
||||||
begin
|
begin
|
||||||
params:= _currentParams;
|
if aRange.location < LW_LOCATION_BASE then begin
|
||||||
setIMESelectedRange( params, _currentMarkedText, aRange );
|
rect:= getImeTextBound;
|
||||||
params.isFirstCall:= not hasMarkedText();
|
end else begin
|
||||||
|
rect:= getLookupWordBound;
|
||||||
rect:= imeHandler.IMEGetTextBound( params );
|
end;
|
||||||
LCLToNSRect( rect, NSGlobalScreenBottom, Result );
|
LCLToNSRect( rect, NSGlobalScreenBottom, Result );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -317,10 +391,77 @@ begin
|
|||||||
Result:= ( _currentParams.textNSLength > 0 );
|
Result:= ( _currentParams.textNSLength > 0 );
|
||||||
end;
|
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(
|
function TCocoaFullControlEdit.attributedSubstringForProposedRange_actualRange(
|
||||||
aRange: NSRange; actualRange: NSRangePointer): NSAttributedString;
|
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
|
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;
|
end;
|
||||||
|
|
||||||
function TCocoaFullControlEdit.validAttributesForMarkedText: NSArray;
|
function TCocoaFullControlEdit.validAttributesForMarkedText: NSArray;
|
||||||
@ -328,11 +469,5 @@ begin
|
|||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaFullControlEdit.characterIndexForPoint(aPoint: NSPoint
|
|
||||||
): NSUInteger;
|
|
||||||
begin
|
|
||||||
Result := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user