From 57c658d98b9459ee3c0a2872ac7fa92fc85c2a92 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 30 Aug 2018 08:57:05 +1000 Subject: [PATCH] [Developer] Re-implement Convert-to-character command in web text editor --- .../TIKE/actions/KMDActionInterfaces.pas | 8 ++ .../TIKE/actions/dmActionsTextEditor.pas | 98 +++++++++---------- .../developer/TIKE/main/UframeTextEditor.pas | 58 ++++++++--- .../developer/TIKE/xml/app/editor/editor.js | 16 ++- 4 files changed, 112 insertions(+), 68 deletions(-) diff --git a/windows/src/developer/TIKE/actions/KMDActionInterfaces.pas b/windows/src/developer/TIKE/actions/KMDActionInterfaces.pas index 724275d2b9..6c58fca2dc 100644 --- a/windows/src/developer/TIKE/actions/KMDActionInterfaces.pas +++ b/windows/src/developer/TIKE/actions/KMDActionInterfaces.pas @@ -22,6 +22,8 @@ unit KMDActionInterfaces; interface uses + System.Types, + TextFileFormat; type @@ -74,9 +76,15 @@ type function GetText: string; procedure SetText(const Value: string); function GetSelectedRow: Integer; + function GetSelectedCol: Integer; + function GetSelectedRange: TRect; function GetEditorFormat: TEditorFormat; + procedure ReplaceSelection(ARange: TRect; const ANewText: string); + property EditorFormat: TEditorFormat read GetEditorFormat; property SelectedRow: Integer read GetSelectedRow; + property SelectedCol: Integer read GetSelectedCol; + property SelectedRange: TRect read GetSelectedRange; property Text: string read GetText write SetText; end; diff --git a/windows/src/developer/TIKE/actions/dmActionsTextEditor.pas b/windows/src/developer/TIKE/actions/dmActionsTextEditor.pas index 68abe10fa7..e83073f702 100644 --- a/windows/src/developer/TIKE/actions/dmActionsTextEditor.pas +++ b/windows/src/developer/TIKE/actions/dmActionsTextEditor.pas @@ -1,18 +1,18 @@ (* Name: dmActionsTextEditor Copyright: Copyright (C) SIL International. - Documentation: - Description: + Documentation: + Description: Create Date: 23 Aug 2006 Modified Date: 24 Jul 2015 Authors: mcdurdin - Related Files: - Dependencies: + Related Files: + Dependencies: - Bugs: - Todo: - Notes: + Bugs: + Todo: + Notes: History: 23 Aug 2006 - mcdurdin - Initial version 30 Aug 2006 - mcdurdin - Add Reformat XML action 04 Dec 2006 - mcdurdin - Localize @@ -32,8 +32,10 @@ interface uses System.Actions, + System.Character, System.Classes, System.SysUtils, + System.Types, Vcl.ActnList, Vcl.Menus, @@ -74,57 +76,51 @@ uses {$R *.dfm} procedure TmodActionsTextEditor.actTextEditor_ConvertToCharactersExecute(Sender: TObject); -{var - ws: WideString; - x, len: Integer; - memo: TframeTextEditor; - line, seltext: WideString; - i: Integer; - FToCodes: Boolean; - FError: Boolean; - res: string; - FInQuotes: Boolean;} +var + a: IKMDTextEditorActions; + FRange: TRect; + i, len: Integer; + res, ws, FText, newtext, seltext: string; + FError, FInQuotes, FToCodes: Boolean; begin -{TODO: reimplement in JS probably better - memo := Screen.ActiveControl as TKeymanDeveloperMemo; - line := memo.LinesArray[memo.SelLine]; - seltext := memo.SelText; - x := memo.SelCol+1; - len := 0; + a := KMDActions.GetTextEditorController(Screen.ActiveControl); - if memo.SelLength = 0 then // I4797 - begin - // Select the token under the cursor - seltext := GetTokenFromCaret(line, x, len); - memo.SelCol := x-1; - memo.SelLength := len; - end; + FText := a.Text; + FRange := a.SelectedRange; - if memo.SelLength < 0 then // I4797 - begin - len := -memo.SelLength; - memo.SelStart := memo.SelStart - len; - memo.SelLength := len; - end; + with TStringList.Create do + try + Text := FText; + if (FRange.Left = FRange.Right) and (FRange.Bottom = FRange.Top) then + begin + // No selection + Inc(FRange.Left); // 1-offset instead of 0-offset + seltext := GetTokenFromCaret(Strings[FRange.Top], FRange.Left, len); + FRange.Right := FRange.Left + len; + end + else if FRange.Top = FRange.Bottom then + begin + // Single line selection + seltext := Copy(Strings[FRange.Top], FRange.Left + 1, FRange.Right - FRange.Left); - while (seltext <> '') and (Copy(seltext, 1, 1) = ' ') do - begin - memo.SelStart := memo.SelStart + 1; - memo.SelLength := Length(seltext); - Delete(seltext, 1, 1); - end; - - while (seltext <> '') and (Copy(seltext, Length(seltext), 1) = ' ') do - begin - memo.SelLength := memo.SelLength - 1; - Delete(seltext, Length(seltext), 1); + // Adjust selection to remove whitespace + newtext := seltext.TrimLeft; + Inc(FRange.Left, seltext.Length - newtext.Length); + seltext := newtext.TrimRight; + Dec(FRange.Right, newtext.Length - seltext.Length); + end + else + // Cannot convert multi-line selections at this time + Exit; + finally + Free; end; if seltext = '' then Exit; ws := ExtStringToString(seltext, FError); - if FError then + if FError then Exit; FToCodes := (Pos('"', seltext) > 0) or (Pos('''', seltext) > 0); @@ -155,14 +151,12 @@ begin res := Trim(res); end; - memo.SelText := res; - memo.SelStart := memo.SelStart - Length(res); - memo.SelLength := Length(res);} + a.ReplaceSelection(FRange, res); end; procedure TmodActionsTextEditor.actTextEditor_ConvertToCharactersUpdate(Sender: TObject); begin - actTextEditor_ConvertToCharacters.Enabled := KMDActions.IsTextEditor(Sender); + actTextEditor_ConvertToCharacters.Enabled := KMDActions.IsTextEditor(Screen.ActiveControl); end; procedure TmodActionsTextEditor.actTextEditor_ReformatXMLExecute(Sender: TObject); diff --git a/windows/src/developer/TIKE/main/UframeTextEditor.pas b/windows/src/developer/TIKE/main/UframeTextEditor.pas index c1f8c58c74..fb59b42a27 100644 --- a/windows/src/developer/TIKE/main/UframeTextEditor.pas +++ b/windows/src/developer/TIKE/main/UframeTextEditor.pas @@ -46,8 +46,8 @@ type class var FInitialFilenameIndex: Integer; private - FSelectedRow: Integer; - FSelectedCol: Integer; + FSelectedRange: TRect; + FSelectedRangeIsBackwards: Boolean; FCanUndo: Boolean; FCanRedo: Boolean; FHasSelection: Boolean; @@ -128,6 +128,9 @@ type { IKMDTextEditorActions } function GetEditorFormat: TEditorFormat; function GetSelectedRow: Integer; + function GetSelectedCol: Integer; + function GetSelectedRange: TRect; + procedure ReplaceSelection(ARange: TRect; const ANewText: string); public { Public declarations } @@ -192,6 +195,24 @@ begin //TODO: memo.TabStops := FKeymanDeveloperOptions.IndentSize; end; +procedure TframeTextEditor.ReplaceSelection(ARange: TRect; + const ANewText: string); +var + j: TJSONObject; +begin + j := TJSONObject.Create; + try + j.AddPair('top', TJSONNumber.Create(ARange.Top)); + j.AddPair('left', TJSONNumber.Create(ARange.Left)); + j.AddPair('bottom', TJSONNumber.Create(ARange.Bottom)); + j.AddPair('right', TJSONNumber.Create(ARange.Right)); + j.AddPair('newText', ANewText); + ExecuteCommand('replaceSelection', j); + finally + j.Free; + end; +end; + procedure TframeTextEditor.cefBeforeBrowse(Sender: TObject; const Url: string; out Result: Boolean); var params: TStringList; @@ -225,6 +246,7 @@ begin model.AddItem(TEXTEDITOR_CONTEXTMENU_SHOWCHARACTER, 'S&how Character'); model.SetEnabled(TEXTEDITOR_CONTEXTMENU_SHOWCHARACTER, modActionsTextEditor.actTextEditor_ShowCharacter.Enabled); model.AddItem(TEXTEDITOR_CONTEXTMENU_CONVERTTOCHARACTERS, 'C&onvert to Characters'); + model.SetAccelerator(TEXTEDITOR_CONTEXTMENU_CONVERTTOCHARACTERS, Ord('U'), True, True, False); model.SetEnabled(TEXTEDITOR_CONTEXTMENU_CONVERTTOCHARACTERS, modActionsTextEditor.actTextEditor_ConvertToCharacters.Enabled); end; @@ -572,18 +594,25 @@ begin finally j.Free; end; -{TODO: - if (ALine >= EditorMemo.LineCount) or (ALine < 0) then Exit; - EditorMemo.SelLine := ALine; - EditorMemo.SelCol := 0; - EditorMemo.SelLength := Length(EditorMemo.LinesArray[ALine]); - EditorMemo.ScrollInView; -} +end; + +function TframeTextEditor.GetSelectedCol: Integer; +begin + if FSelectedRangeIsBackwards + then Result := FSelectedRange.Left + else Result := FSelectedRange.Right; +end; + +function TframeTextEditor.GetSelectedRange: TRect; +begin + Result := FSelectedRange; end; function TframeTextEditor.GetSelectedRow: Integer; begin - Result := FSelectedRow; + if FSelectedRangeIsBackwards + then Result := FSelectedRange.Top + else Result := FSelectedRange.Bottom; end; procedure TframeTextEditor.SetText(Value: WideString); @@ -624,9 +653,12 @@ begin begin if ALocation <> '' then begin - FSelectedRow := StrToIntDef(StrToken(ALocation, ','),0); - FSelectedCol := StrToIntDef(ALocation,0); - frmKeymanDeveloper.barStatus.Panels[0].Text := Format('Line %d, Col %d', [FSelectedRow+1,FSelectedCol+1]); + FSelectedRange.Top := StrToIntDef(StrToken(ALocation, ','),0); + FSelectedRange.Left := StrToIntDef(StrToken(ALocation, ','),0); + FSelectedRange.Bottom := StrToIntDef(StrToken(ALocation, ','),0); + FSelectedRange.Right := StrToIntDef(StrToken(ALocation, ','),0); + FSelectedRangeIsBackwards := StrToIntDef(StrToken(ALocation, ','),0) > 0; + frmKeymanDeveloper.barStatus.Panels[0].Text := Format('Line %d, Col %d', [FSelectedRange.Top+1,FSelectedRange.Left+1]); 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 e7c39f877c..cca26a1e36 100644 --- a/windows/src/developer/TIKE/xml/app/editor/editor.js +++ b/windows/src/developer/TIKE/xml/app/editor/editor.js @@ -82,6 +82,14 @@ window.editorGlobalContext = { } }; + context.replaceSelection = function (o) { + let originalRange = new ace.Range(o.top, o.left, o.bottom, o.right); + let end = editor.session.doc.replace(originalRange, o.newText); + + let newRange = new ace.Range(o.top, o.left, end.row, end.column); + editor.selection.setSelectionRange(newRange, false); + }; + /* Printing */ context.print = function () { @@ -142,9 +150,11 @@ window.editorGlobalContext = { command(editor.getSelectedText() == '' ? 'no-selection' : 'has-selection'); command(editor.session.getUndoManager().hasUndo() ? 'undo-enable' : 'undo-disable'); command(editor.session.getUndoManager().hasRedo() ? 'redo-enable' : 'redo-disable'); - let c = editor.selection.getCursor(); - command('location,'+c.row+','+c.column); - command('insert-mode,'+(editor.session.getOption('overwrite') ? 'Overwrite' : 'Insert')); + let r = editor.selection.getRange(); + var n = editor.session.doc.getTextRange(editor.selection.getRange()).length; + if (!editor.selection.isBackwards()) n = -n; + command('location,' + r.start.row + ',' + r.start.column + ',' + r.end.row + ',' + r.end.column + ',' + n); + command('insert-mode,' + (editor.session.getOption('overwrite') ? 'Overwrite' : 'Insert')); // command(editor.session.getUndoManager().isClean() ? 'modified' : 'not-modified'); var s = getTokenAtCursor(); if(s) {