mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-01 21:01:14 +02:00
Cocoa: IME: implements a base NSTextInputClient for non-editable LCL CustomControl
implements a base NSTextInputClient for non-editable LCL CustomControl, like Form, Grid, ListView, that are not system control and not FullEditControl. 1. when using IME in these controls, a temporary and one-time editor is shown at the bottom of the control, supporting IME such as Chinese. 2. refers to MacOS Finder, when using IME in the file list view, a small window will pop up at the bottom of the screen for input. the text can then be used for filename starting character match. 3. it is useful for implementing IME support for controls that do not have a text input window.
This commit is contained in:
parent
873c352755
commit
7031b6b752
@ -203,6 +203,8 @@ type
|
|||||||
|
|
||||||
isdrawing : integer;
|
isdrawing : integer;
|
||||||
faileddraw : Boolean;
|
faileddraw : Boolean;
|
||||||
|
|
||||||
|
_inIME: Boolean;
|
||||||
public
|
public
|
||||||
callback: ICommonCallback;
|
callback: ICommonCallback;
|
||||||
auxMouseByParent: Boolean;
|
auxMouseByParent: Boolean;
|
||||||
@ -234,9 +236,19 @@ type
|
|||||||
function stringValue: NSString; override;
|
function stringValue: NSString; override;
|
||||||
procedure addSubView(aview: NSView); override;
|
procedure addSubView(aview: NSView); override;
|
||||||
|
|
||||||
// this is parts of
|
public
|
||||||
|
// NSTextInputClientProtocol related.
|
||||||
|
// implements a base NSTextInputClient for non-editable LCL CustomControl,
|
||||||
|
// like Form, Grid, ListView, that are not system control and not FullEditControl.
|
||||||
|
// 1. when using IME in these controls, a temporary and one-time editor is shown
|
||||||
|
// at the bottom of the control, supporting IME such as Chinese.
|
||||||
|
// 2. refers to MacOS Finder, when using IME in the file list view,
|
||||||
|
// a small window will pop up at the bottom of the screen for input.
|
||||||
|
// the text can then be used for filename starting character match.
|
||||||
|
// 3. it is useful for implementing IME support for controls that do not
|
||||||
|
// have a text input window.
|
||||||
|
procedure keyDown(theEvent: NSEvent); override;
|
||||||
procedure insertText_replacementRange (aString: id; replacementRange: NSRange);
|
procedure insertText_replacementRange (aString: id; replacementRange: NSRange);
|
||||||
procedure doCommandBySelector (aSelector: SEL); override;
|
|
||||||
procedure setMarkedText_selectedRange_replacementRange (aString: id; selectedRange: NSRange; replacementRange: NSRange);
|
procedure setMarkedText_selectedRange_replacementRange (aString: id; selectedRange: NSRange; replacementRange: NSRange);
|
||||||
procedure unmarkText;
|
procedure unmarkText;
|
||||||
function selectedRange: NSRange;
|
function selectedRange: NSRange;
|
||||||
@ -246,6 +258,7 @@ type
|
|||||||
function validAttributesForMarkedText: NSArray;
|
function validAttributesForMarkedText: NSArray;
|
||||||
function firstRectForCharacterRange_actualRange (aRange: NSRange; actualRange: NSRangePointer): NSRect;
|
function firstRectForCharacterRange_actualRange (aRange: NSRange; actualRange: NSRangePointer): NSRect;
|
||||||
function characterIndexForPoint (aPoint: NSPoint): NSUInteger;
|
function characterIndexForPoint (aPoint: NSPoint): NSUInteger;
|
||||||
|
procedure doCommandBySelector (aSelector: SEL); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ ICocoaIMEControl }
|
{ ICocoaIMEControl }
|
||||||
@ -585,6 +598,14 @@ end;
|
|||||||
|
|
||||||
{ TCocoaCustomControl }
|
{ TCocoaCustomControl }
|
||||||
|
|
||||||
|
function getNSStringObject( const aString: id ) : NSString;
|
||||||
|
begin
|
||||||
|
if aString.isKindOfClass( NSAttributedString.classClass ) then
|
||||||
|
Result:= NSAttributedString( aString ).string_
|
||||||
|
else
|
||||||
|
Result:= NSString( aString );
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCocoaCustomControl.setStringValue(avalue: NSString);
|
procedure TCocoaCustomControl.setStringValue(avalue: NSString);
|
||||||
begin
|
begin
|
||||||
if Assigned(fstr) then fstr.release;
|
if Assigned(fstr) then fstr.release;
|
||||||
@ -617,25 +638,78 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaCustomControl.insertText_replacementRange(aString: id;
|
procedure TCocoaCustomControl.keyDown(theEvent: NSEvent);
|
||||||
replacementRange: NSRange);
|
var
|
||||||
|
view: NSView;
|
||||||
|
isFirst: Boolean;
|
||||||
begin
|
begin
|
||||||
lclGetCallback.InputClientInsertText(NSStringToString(NSString(astring)));
|
isFirst:= not _inIME;
|
||||||
|
inputContext.handleEvent(theEvent);
|
||||||
|
if _inIME and isFirst then
|
||||||
|
begin
|
||||||
|
view:= self.window.fieldEditor_forObject(true, nil);
|
||||||
|
view.setFrameSize( NSMakeSize(self.frame.size.width,16) );
|
||||||
|
self.addSubView( view );
|
||||||
|
end
|
||||||
|
else if not _inIME then
|
||||||
|
inputContext.discardMarkedText;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaCustomControl.doCommandBySelector(aSelector: SEL);
|
procedure TCocoaCustomControl.insertText_replacementRange(aString: id;
|
||||||
|
replacementRange: NSRange);
|
||||||
|
var
|
||||||
|
textView: NSTextView;
|
||||||
|
nsText: NSString;
|
||||||
begin
|
begin
|
||||||
inherited doCommandBySelector(ASelector);
|
if not _inIME then exit;
|
||||||
|
|
||||||
|
textView:= NSTextView(self.window.fieldEditor_forObject(false,nil));
|
||||||
|
if Assigned(textView) then
|
||||||
|
textView.removeFromSuperview;
|
||||||
|
|
||||||
|
nsText:= getNSStringObject(aString);
|
||||||
|
lclGetCallback.InputClientInsertText(nsText.UTF8String);
|
||||||
|
|
||||||
|
unmarkText;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaCustomControl.setMarkedText_selectedRange_replacementRange(
|
procedure TCocoaCustomControl.setMarkedText_selectedRange_replacementRange(
|
||||||
aString: id; selectedRange: NSRange; replacementRange: NSRange);
|
aString: id; selectedRange: NSRange; replacementRange: NSRange);
|
||||||
|
var
|
||||||
|
textView: NSTextView;
|
||||||
|
nsText: NSString;
|
||||||
begin
|
begin
|
||||||
|
nsText:= getNSStringObject(aString);
|
||||||
|
if nsText.length > 0 then
|
||||||
|
begin
|
||||||
|
_inIME:= true;
|
||||||
|
textView:= NSTextView(self.window.fieldEditor_forObject(false,nil));
|
||||||
|
if Assigned(textView) then
|
||||||
|
textView.setMarkedText_selectedRange_replacementRange(aString,selectedRange,replacementRange);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
unmarkText;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCocoaCustomControl.hasMarkedText: LCLObjCBoolean;
|
||||||
|
begin
|
||||||
|
Result := _inIME;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaCustomControl.unmarkText;
|
procedure TCocoaCustomControl.unmarkText;
|
||||||
begin
|
begin
|
||||||
|
_inIME:= false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCocoaCustomControl.firstRectForCharacterRange_actualRange(
|
||||||
|
aRange: NSRange; actualRange: NSRangePointer): NSRect;
|
||||||
|
var
|
||||||
|
point: NSPoint;
|
||||||
|
rect: NSRect;
|
||||||
|
begin
|
||||||
|
point:= self.convertPoint_toView(NSZeroPoint, nil);
|
||||||
|
rect:= NSMakeRect(point.x, point.y, 0, 16);
|
||||||
|
Result:= self.window.convertRectToScreen(rect);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaCustomControl.selectedRange: NSRange;
|
function TCocoaCustomControl.selectedRange: NSRange;
|
||||||
@ -648,11 +722,6 @@ begin
|
|||||||
Result := NSMakeRange(0,0);
|
Result := NSMakeRange(0,0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaCustomControl.hasMarkedText: LCLObjCBoolean;
|
|
||||||
begin
|
|
||||||
Result := false;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TCocoaCustomControl.attributedSubstringForProposedRange_actualRange(
|
function TCocoaCustomControl.attributedSubstringForProposedRange_actualRange(
|
||||||
aRange: NSRange; actualRange: NSRangePointer): NSAttributedString;
|
aRange: NSRange; actualRange: NSRangePointer): NSAttributedString;
|
||||||
begin
|
begin
|
||||||
@ -664,18 +733,17 @@ begin
|
|||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCocoaCustomControl.firstRectForCharacterRange_actualRange(
|
|
||||||
aRange: NSRange; actualRange: NSRangePointer): NSRect;
|
|
||||||
begin
|
|
||||||
Result := NSMakeRect(0,0,0,0);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TCocoaCustomControl.characterIndexForPoint(aPoint: NSPoint
|
function TCocoaCustomControl.characterIndexForPoint(aPoint: NSPoint
|
||||||
): NSUInteger;
|
): NSUInteger;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaCustomControl.doCommandBySelector(aSelector: SEL);
|
||||||
|
begin
|
||||||
|
inherited doCommandBySelector(ASelector);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCocoaCustomControl.dealloc;
|
procedure TCocoaCustomControl.dealloc;
|
||||||
begin
|
begin
|
||||||
if Assigned(fstr) then fstr.release;
|
if Assigned(fstr) then fstr.release;
|
||||||
@ -916,14 +984,6 @@ begin
|
|||||||
Result := not hasMarkedText();
|
Result := not hasMarkedText();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function getNSStringObject( const aString: id ) : NSString;
|
|
||||||
begin
|
|
||||||
if aString.isKindOfClass( NSAttributedString.classClass ) then
|
|
||||||
Result:= NSAttributedString( aString ).string_
|
|
||||||
else
|
|
||||||
Result:= NSString( aString );
|
|
||||||
end;
|
|
||||||
|
|
||||||
function isIMEDuplicateCall( const newParams, currentParams: TCocoaIMEParameters ) : Boolean;
|
function isIMEDuplicateCall( const newParams, currentParams: TCocoaIMEParameters ) : Boolean;
|
||||||
begin
|
begin
|
||||||
Result:= false;
|
Result:= false;
|
||||||
|
Loading…
Reference in New Issue
Block a user