From d595a9d154ceaa2ade92b41ba835aef08c74ec92 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 4 Sep 2018 15:26:18 +1000 Subject: [PATCH] [Developer] Support drag and drop into monaco editor --- .../developer/TIKE/child/UfrmKeymanWizard.pas | 2 +- .../developer/TIKE/main/CharMapDropTool.pas | 37 ++++++++++++- .../developer/TIKE/main/UframeTextEditor.pas | 52 +++++++++++++++++++ .../developer/TIKE/xml/app/editor/editor.js | 42 +++++++++++++++ .../delphi/charmap/CharacterDragObject.pas | 2 + 5 files changed, 133 insertions(+), 2 deletions(-) diff --git a/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas b/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas index 9dc38a1d5b..3edf601b97 100644 --- a/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas +++ b/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas @@ -650,8 +650,8 @@ begin SetupDebugForm; GetCharMapDropTool.Handle(Self, cmimText); -//TODO: GetCharMapDropTool.Handle(frameSource.memo, cmimDefault); GetCharMapDropTool.Handle(editKeyOutputCode, cmimCode); + frameSource.SetupCharMapDrop; FillFeatureGrid; diff --git a/windows/src/developer/TIKE/main/CharMapDropTool.pas b/windows/src/developer/TIKE/main/CharMapDropTool.pas index cc9040c0e6..d5b9fae955 100644 --- a/windows/src/developer/TIKE/main/CharMapDropTool.pas +++ b/windows/src/developer/TIKE/main/CharMapDropTool.pas @@ -49,6 +49,13 @@ type property InsertMode: TCharMapInsertMode read FInsertMode; end; + TCharMapDropToolControlDefault = class(TCharMapDropToolControl) + public + class function Handles: TControlClass; override; + procedure Drag(AObject: TCharacterDragObject; X, Y: Integer; var Accept: Boolean); override; + procedure Drop(AInsertType: TCharMapInsertMode; AObject: TCharacterDragObject; X, Y: Integer); override; + end; + TCharMapDropToolControlClass = class of TCharMapDropToolControl; TCharMapDropToolControls = class(TObjectList) @@ -180,8 +187,11 @@ begin if Control is TCharMapDropToolControlClass(FControlClasses[i]).Handles then begin FControls.Add(TCharMapDropToolControlClass(FControlClasses[i]).Create(Self, Control, AInsertMode, AOnDragOver, AOnDragDrop)); - Break; + Exit; end; + + if Assigned(AOnDragOver) and Assigned(AOnDragDrop) then + FControls.Add(TCharMapDropToolControlDefault.Create(Self, Control, cmimCustom, AOnDragOver, AOnDragDrop)); end; end; @@ -369,6 +379,31 @@ begin end; end; +{ TCharMapDropToolControlDefault } + +procedure TCharMapDropToolControlDefault.Drag(AObject: TCharacterDragObject; X, + Y: Integer; var Accept: Boolean); +begin + if Assigned(FOnDragOver) + then FOnDragOver(Self, AObject, X, Y, dsDragMove, Accept) + else Accept := False; +end; + +procedure TCharMapDropToolControlDefault.Drop(AInsertType: TCharMapInsertMode; + AObject: TCharacterDragObject; X, Y: Integer); +begin + if Assigned(FOnDragDrop) then + begin + AObject.InsertType := AInsertType; + FOnDragDrop(Self, AObject, X, Y); + end; +end; + +class function TCharMapDropToolControlDefault.Handles: TControlClass; +begin + Result := TWinControl; +end; + initialization finalization FreeAndNil(FCharMapDropTool); diff --git a/windows/src/developer/TIKE/main/UframeTextEditor.pas b/windows/src/developer/TIKE/main/UframeTextEditor.pas index 232745fe59..4ee6f241ce 100644 --- a/windows/src/developer/TIKE/main/UframeTextEditor.pas +++ b/windows/src/developer/TIKE/main/UframeTextEditor.pas @@ -98,6 +98,9 @@ type procedure cefLoadEnd(Sender: TObject); procedure DoBreakpointClicked(const line: string); procedure UpdateEditorFonts; + procedure CharMapDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure CharMapDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); protected function GetHelpTopic: string; override; @@ -146,6 +149,7 @@ type property OnBreakpointClicked: TEditorBreakpointClickedEvent read FOnBreakpointClicked write FOnBreakpointClicked; procedure SetFocus; override; + procedure SetupCharMapDrop; procedure FindError(ln: Integer); procedure FindErrorByOffset(offset: Integer); // I4083 @@ -184,8 +188,10 @@ uses dmActionsMain, dmActionsTextEditor, + CharacterDragObject, CharacterInfo, CharMapDropTool, + CharMapInsertMode, keyboardparser, KeymanDeveloperOptions, kwhelp, @@ -310,6 +316,12 @@ begin cef.cef.OnBeforeContextMenu := cefBeforeContextMenu; cef.cef.OnContextMenuCommand := cefContextMenuCommand; cef.OnPreKeyEvent := cefPreKeyEvent; + SetupCharMapDrop; +end; + +procedure TframeTextEditor.SetupCharMapDrop; +begin + GetCharMapDropTool.Handle(cef.cefwp, cmimDefault, CharMapDragOver, CharMapDragDrop); end; procedure TframeTextEditor.cefLoadEnd(Sender: TObject); @@ -1049,4 +1061,44 @@ begin FreeAndNil(FCodeFont); end; +procedure TframeTextEditor.CharMapDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); +var + j: TJSONObject; +begin + cef.cefwp.SetFocus; + j := TJSONObject.Create; + try + j.AddPair('x', TJSONNumber.Create(X)); + j.AddPair('y', TJSONNumber.Create(Y)); + j.AddPair('state', GetEnumName(TypeInfo(TDragState), Ord(State))); + ExecuteCommand('charmapDragOver', j); + finally + j.Free; + end; + + // We cannot test acceptance via event because it is asynchronous + // So we will just assume we can accept and throw it away if it is outside bounds + // during drop. + Accept := True; +end; + +procedure TframeTextEditor.CharMapDragDrop(Sender, Source: TObject; X, Y: Integer); +var + j: TJSONObject; + cdo: TCharacterDragObject; +begin + cef.cefwp.SetFocus; + cdo := Source as TCharacterDragObject; + j := TJSONObject.Create; + try + j.AddPair('x', TJSONNumber.Create(X)); + j.AddPair('y', TJSONNumber.Create(Y)); + j.AddPair('text', cdo.Text[cdo.InsertType]); + ExecuteCommand('charmapDragDrop', j); + finally + j.Free; + end; +end; + end. diff --git a/windows/src/developer/TIKE/xml/app/editor/editor.js b/windows/src/developer/TIKE/xml/app/editor/editor.js index 480de73c5d..f378a57a8f 100644 --- a/windows/src/developer/TIKE/xml/app/editor/editor.js +++ b/windows/src/developer/TIKE/xml/app/editor/editor.js @@ -172,6 +172,48 @@ window.editorGlobalContext = { ); context.moveCursor({ row: row, column: 0 }); }; + + // + // Character map drag+drop and double-click insertion + // + + context.charmapDragOver = function(o) { + + // Convert X, Y to document coordinates + + let target = editor.getTargetAtClientPoint(o.x, o.y); + + if(target === null || target.type !== monaco.editor.MouseTargetType.CONTENT_TEXT) { + return false; + } + + // Move insertion point accordingly + + let position = editor.getPosition(); + + if(!position.equals(target.position)) { + editor.setPosition(target.position); + } + + return true; + }; + + context.charmapDragDrop = function(o) { + + // Convert X, Y to document coordinates + + if(o.x >= 0 && o.y >= 0) { + let target = editor.getTargetAtClientPoint(o.x, o.y); + + if(target === null || target.type !== monaco.editor.MouseTargetType.CONTENT_TEXT) { + return false; + } + + editor.setPosition(target.position); + } + + editor.trigger('keyboard', 'type', {text: o.text}); + }; // // Error highlighting diff --git a/windows/src/global/delphi/charmap/CharacterDragObject.pas b/windows/src/global/delphi/charmap/CharacterDragObject.pas index 56bb341a50..4363a1b72d 100644 --- a/windows/src/global/delphi/charmap/CharacterDragObject.pas +++ b/windows/src/global/delphi/charmap/CharacterDragObject.pas @@ -30,6 +30,7 @@ type FFontName: WideString; FText: array[TCharMapInsertMode] of WideString; FDragImages: TDragImageList; + FInsertType: TCharMapInsertMode; function GetText(Index: TCharMapInsertMode): WideString; procedure SetText(Index: TCharMapInsertMode; Value: WideString); procedure CreateDragCursor; @@ -44,6 +45,7 @@ type function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; override; procedure SetDragCursorOptions(ADefaultInsertMode: TCharMapInsertMode; AFontName: WideString); property Text[Index: TCharMapInsertMode]: WideString read GetText write SetText; + property InsertType: TCharMapInsertMode read FInsertType write FInsertType; // used for custom insertion only end; implementation