diff --git a/windows/src/developer/TIKE/child/UfrmDebug.pas b/windows/src/developer/TIKE/child/UfrmDebug.pas index 25cf44da90..10819d5015 100644 --- a/windows/src/developer/TIKE/child/UfrmDebug.pas +++ b/windows/src/developer/TIKE/child/UfrmDebug.pas @@ -57,20 +57,40 @@ unit UfrmDebug; // I3323 // I3306 interface uses - Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - ExtCtrls, Grids, ComCtrls, CaptionPanel, Buttons, - StdCtrls, debugging, debugkeyboard, UfrmMDIEditor, PaintPanel, Menus, - HintLabel, debugdeadkeys, UserMessages, - UframeTextEditor, + System.Classes, + System.Generics.Collections, + System.SysUtils, Vcl.AppEvnts, + Vcl.Buttons, + Vcl.ComCtrls, + Vcl.Controls, + Vcl.Dialogs, + Vcl.ExtCtrls, + Vcl.Forms, + Vcl.Graphics, + Vcl.Grids, + Vcl.Menus, + Vcl.StdCtrls, + Winapi.Messages, + Winapi.Windows, + + CaptionPanel, + debugdeadkeys, + debugging, + debugkeyboard, DebugUtils, - keymanapi_TLB, msctf, UfrmTike, - KeymanDeveloperDebuggerMemo; + HintLabel, + PaintPanel, + keymanapi_TLB, + KeymanDeveloperDebuggerMemo, + msctf, + UframeTextEditor, + UfrmMDIEditor, + UfrmTike, + UserMessages; type - TUpdateParColourEvent = procedure(Sender: TObject; ALine: Integer; ALineType: TParColourLineType) of object; - - TBreakpointRange = 0..99; + TDebugLineEvent = procedure(Sender: TObject; ALine: Integer) of object; TDebugUIStatus = (duiInvalid, duiPaused, duiFocusedForInput, duiReadyForInput, duiReceivingEvents, duiDebugging, duiClosing, duiDebuggingOutput, duiTest); @@ -87,6 +107,8 @@ type property TrueLineNumber: Integer read GetTrueLineNumber write SetTrueLineNumber; end; + TDebugBreakpoints = class(TObjectList); + TfrmDebug = class(TTikeForm) memo: TKeymanDeveloperDebuggerMemo; mnuPopup: TPopupMenu; // I4796 @@ -115,7 +137,7 @@ type private FDebugVisible: Boolean; - FBreakpoint: array[TBreakpointRange] of TDebugBreakpoint; + FBreakpoints: TDebugBreakpoints; FRunning, FFoundBreakpoint, FForceKeyboard: Boolean; FFileName: string; //FEditor: TfrmTikeEditor; @@ -163,8 +185,6 @@ type procedure KeymanGetContext(var Message: TMessage); - procedure UpdateParColour(Line: Integer; LineType: TParColourLineType); - procedure AddDebug(s: WideString); { Debug panel functions } @@ -174,10 +194,13 @@ type private FANSITest: Boolean; FEditorMemo: TframeTextEditor; - FOnUpdateParColour: TUpdateParColourEvent; + FDebugFileName: WideString; FSingleStepMode: Boolean; FCanDebug: Boolean; + FOnUpdateExecutionPoint: TDebugLineEvent; + FOnClearBreakpoint: TDebugLineEvent; + FOnSetBreakpoint: TDebugLineEvent; procedure SetANSITest(const Value: Boolean); procedure UpdateANSITest; procedure ClearDeadkeys; @@ -216,13 +239,14 @@ type procedure SetBreakpoint(ALine: Integer); procedure ClearBreakpoint(ALine: Integer); + procedure ToggleBreakpoint(ALine: Integer); function IsBreakPointLine(ALine: Integer): Boolean; function IsExecutionPointLine(ALine: Integer): Boolean; function GetDebugKeyboard: TDebugKeyboard; - property CanDebug: Boolean read FCanDebug write FCanDebug; + property CanDebug: Boolean read FCanDebug write FCanDebug; property UIStatus: TDebugUIStatus read FUIStatus write SetUIStatus; property SingleStepMode: Boolean read FSingleStepMode write SetSingleStepMode; @@ -250,7 +274,9 @@ type property CurrentEvent: TDebugEvent read GetCurrentEvent; - property OnUpdateParColour: TUpdateParColourEvent read FOnUpdateParColour write FOnUpdateParColour; + property OnSetBreakpoint: TDebugLineEvent read FOnSetBreakpoint write FOnSetBreakpoint; + property OnClearBreakpoint: TDebugLineEvent read FOnClearBreakpoint write FOnClearBreakpoint; + property OnUpdateExecutionPoint: TDebugLineEvent read FOnUpdateExecutionPoint write FOnUpdateExecutionPoint; end; implementation @@ -317,6 +343,7 @@ begin // InitMSCTF; // I3655 TDebugUtils.GetActiveTSFProfile(FLastActiveProfile); // I4331 + FBreakpoints := TDebugBreakpoints.Create; FExecutionPointLine := -1; //InitControlCaptions; @@ -331,11 +358,9 @@ begin end; procedure TfrmDebug.FormDestroy(Sender: TObject); -var - i: TBreakpointRange; begin ResetDebug; - for i := Low(TBreakpointRange) to High(TBreakpointRange) do FBreakpoint[i].Free; + FBreakpoints.Free; FEvents.Free; //UninitControlCaptions; //UninitSystemKeyboard; @@ -722,7 +747,7 @@ end; procedure TfrmDebug.WMUSERUpdateForceKeyboard(var Message: TMessage); // I4767 procedure FailTidyUp; begin - Windows.SetFocus(0); + Winapi.Windows.SetFocus(0); HideDebugForm; FForceKeyboard := False; end; @@ -763,8 +788,8 @@ begin if FWasStarted then // I3283 // I3503 begin // Give Keyman Engine a chance to correctly attach focus after it starts - Windows.SetFocus(0); - Windows.SetFocus(memo.Handle); + Winapi.Windows.SetFocus(0); + Winapi.Windows.SetFocus(memo.Handle); Exit; end; @@ -784,7 +809,7 @@ begin {Keyman_Exit; I3283 // I3503 if not Keyman_Initialise(Application.MainForm.Handle, True) or not Keyman_ForceKeyboard(FFileName) then begin} - Windows.SetFocus(0); + Winapi.Windows.SetFocus(0); HideDebugForm; ShowMessage('Unable to start debugger - please make sure that Keyman Developer is correctly installed (the error code was '+IntToHex(FLastError, 8)+').'); // I3173 // I3504 //(Editor as TfrmEditor).HideDebugForm; @@ -1017,59 +1042,49 @@ end; procedure TfrmDebug.SetBreakpoint(ALine: Integer); var - i: TBreakpointRange; - j: Integer; + b: TDebugBreakpoint; begin - j := -1; - for i := Low(TBreakpointRange) to High(TBreakpointRange) do - begin - if Assigned(FBreakpoint[i]) then - begin - if (FBreakpoint[i].TrueLineNumber = ALine) then Exit; - end - else if j = -1 then j := i; - end; + for b in FBreakpoints do + if b.TrueLineNumber = ALine then + Exit; - if j = -1 then - begin - ShowMessage('You can only have a maximum of '+ - IntToStr(High(TBreakpointRange)-Low(TBreakpointRange))+' breakpoints.'); - Exit; - end; + b := TDebugBreakpoint.Create(EditorMemo); + b.TrueLineNumber := ALine; + FBreakpoints.Add(b); - FBreakpoint[j] := TDebugBreakpoint.Create(EditorMemo); - FBreakpoint[j].TrueLineNumber := ALine; - UpdateParColour(ALine, pcltBreakpoint); + if Assigned(FOnSetBreakpoint) then + FOnSetBreakpoint(Self, ALine); end; procedure TfrmDebug.ClearBreakpoint(ALine: Integer); var - i: TBreakpointRange; + b: TDebugBreakpoint; begin - for i := Low(TBreakpointRange) to High(TBreakpointRange) do - if Assigned(FBreakpoint[i]) and (FBreakpoint[i].TrueLineNumber = ALine) then + for b in FBreakpoints do + if b.TrueLineNumber = ALine then begin - FBreakpoint[i].Free; - FBreakpoint[i] := nil; - if IsExecutionPointLine(ALine) - then UpdateParColour(ALine, pcltExecutionPoint) - else UpdateParColour(ALine, pcltNone); + FBreakpoints.Remove(b); + if Assigned(FOnClearBreakpoint) then + FOnClearBreakpoint(Self, ALine); Exit; end; end; +procedure TfrmDebug.ToggleBreakpoint(ALine: Integer); +begin + if IsBreakpointLine(ALine) + then ClearBreakpoint(ALine) + else SetBreakpoint(ALine) +end; + function TfrmDebug.IsBreakPointLine(ALine: Integer): Boolean; var - i: Integer; + b: TDebugBreakpoint; begin - Result := True; - for i := Low(TBreakpointRange) to High(TBreakpointRange) do - begin - if FBreakpoint[i] <> nil then - if FBreakpoint[i].TrueLineNumber = ALine then - Exit; - end; - Result := False; + for b in FBreakpoints do + if b.TrueLineNumber = ALine then + Exit(True); + Exit(False); end; {------------------------------------------------------------------------------- @@ -1082,28 +1097,21 @@ begin end; procedure TfrmDebug.SetExecutionPointLine(ALine: Integer); -var - oldline: Integer; begin - oldline := FExecutionPointLine; FExecutionPointLine := ALine; - if IsBreakPointLine(oldline) - then UpdateParColour(oldline, pcltBreakpoint) - else UpdateParColour(oldline, pcltNone); - if FRunning then Exit; - if FExecutionPointLine >= 0 then - UpdateParColour(FExecutionPointLine, pcltExecutionPoint); + if FRunning and (FExecutionPointLine >= 0) then Exit; + if Assigned(FOnUpdateExecutionPoint) then + FOnUpdateExecutionPoint(Self, ALine); end; procedure TfrmDebug.ListBreakpoints; var - i: Integer; + b: TDebugBreakpoint; begin memo.Clear; - //frmDebugStatus.DeadKeys.ClearDeadkeys; I1699 - for i := 0 to 99 do - if Assigned(FBreakPoint[i]) and (FBreakpoint[i].TrueLineNumber >= 0) then - UpdateParColour(FBreakpoint[i].TrueLineNumber, pcltBreakpoint); + for b in FBreakpoints do + if Assigned(FOnSetBreakpoint) then + FOnSetBreakpoint(Self, b.TrueLineNumber); end; @@ -1178,12 +1186,6 @@ begin (frmDebugStatus as TfrmDebugStatus).DisplayFont := FFont; end; -procedure TfrmDebug.UpdateParColour(Line: Integer; LineType: TParColourLineType); -begin - if Assigned(FOnUpdateParColour) then - FOnUpdateParColour(Self, Line, LineType); -end; - procedure TfrmDebug.Pause; begin if UIStatus = duiTest then Exit; diff --git a/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas b/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas index c8e4d2789e..73911bb0fa 100644 --- a/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas +++ b/windows/src/developer/TIKE/child/UfrmKeymanWizard.pas @@ -437,6 +437,8 @@ type procedure TouchLayoutModified(Sender: TObject); procedure FocusTabTouchLayout; + procedure EditorBreakpointClicked(Sender: TObject; ALine: Integer); + procedure FillFeatureGrid; procedure CheckParserSourceMove(Changed: Boolean); procedure ToggleWinLanguagesRow(Y: Integer); @@ -488,7 +490,9 @@ type procedure StopDebugging; function PrepareForBuild(var DebugReset: Boolean): Boolean; // I4504 - procedure UpdateParColour(Sender: TObject; ALine: Integer; ALineType: TParColourLineType); + procedure DebugSetBreakpoint(Sender: TObject; ALine: Integer); + procedure DebugClearBreakpoint(Sender: TObject; ALine: Integer); + procedure DebugUpdateExecutionPoint(Sender: TObject; ALine: Integer); function HasSubfilename(const Filename: string): Boolean; override; // I4081 @@ -626,6 +630,7 @@ begin frameSource.EditorFormat := efKMN; frameSource.Visible := True; frameSource.OnChanged := SourceChanged; + frameSource.OnBreakpointClicked := EditorBreakpointClicked; frameSource.TextFileFormat := FTextFileFormat; pages.ActivePage := pageDetails; @@ -702,6 +707,13 @@ end; { General Functions } {-----------------------------------------------------------------------------} +procedure TfrmKeymanWizard.EditorBreakpointClicked(Sender: TObject; + ALine: Integer); +begin + if Assigned(FDebugForm) then + FDebugForm.ToggleBreakpoint(ALine); +end; + procedure TfrmKeymanWizard.EnableControls; begin BitmapEnableControls; @@ -1478,11 +1490,6 @@ begin tmrUpdateCharacterMap.Enabled := True; end; -procedure TfrmKeymanWizard.UpdateParColour(Sender: TObject; ALine: Integer; ALineType: TParColourLineType); -begin - frameSource.UpdateParColour(ALine, ALineType); -end; - procedure TfrmKeymanWizard.SelectVKey(VKey: Integer); begin kbdLayout.SelectedKey := kbdLayout.Keys.ItemsByUSVK[VKey]; @@ -1942,6 +1949,22 @@ begin frmKeymanDeveloper.cbTextFileFormat.ItemIndex := Ord(TextFileFormat); end; +procedure TfrmKeymanWizard.DebugClearBreakpoint(Sender: TObject; + ALine: Integer); +begin + frameSource.DebugClearBreakpoint(ALine); +end; + +procedure TfrmKeymanWizard.DebugSetBreakpoint(Sender: TObject; ALine: Integer); +begin + frameSource.DebugSetBreakpoint(ALine); +end; + +procedure TfrmKeymanWizard.DebugUpdateExecutionPoint(Sender: TObject; ALine: Integer); +begin + frameSource.DebugUpdateExecutionPoint(ALine); +end; + procedure TfrmKeymanWizard.DoFocus(control: TWinControl); begin if control.Enabled and control.Visible and control.Showing and control.CanFocus then @@ -2835,7 +2858,9 @@ begin FDebugForm.BorderStyle := bsNone; FDebugForm.Parent := panDebugWindowHost; FDebugForm.Align := alClient; - FDebugForm.OnUpdateParColour := UpdateParColour; + FDebugForm.OnSetBreakpoint := DebugSetBreakpoint; + FDebugForm.OnClearBreakpoint := DebugClearBreakpoint; + FDebugForm.OnUpdateExecutionPoint := DebugUpdateExecutionPoint; FDebugForm.Visible := True; diff --git a/windows/src/developer/TIKE/main/UframeTextEditor.pas b/windows/src/developer/TIKE/main/UframeTextEditor.pas index c875a3fd32..6517f4d004 100644 --- a/windows/src/developer/TIKE/main/UframeTextEditor.pas +++ b/windows/src/developer/TIKE/main/UframeTextEditor.pas @@ -32,7 +32,7 @@ uses UserMessages; type - TParColourLineType = (pcltNone, pcltBreakpoint, pcltExecutionPoint, pcltError); + TEditorBreakpointClickedEvent = procedure(Sender: TObject; ALine: Integer) of object; TframeTextEditor = class(TTIKEForm, IKMDEditActions, IKMDSearchActions, IKMDTextEditorActions) lstImages: TMenuImgList; @@ -59,6 +59,7 @@ type cef: TframeCEFHost; FFilename: string; + FOnBreakpointClicked: TEditorBreakpointClickedEvent; procedure RefreshOptions; function GetText: WideString; @@ -91,9 +92,11 @@ type procedure LoadFileInBrowser(const AData: string); procedure UpdateInsertState(const AMode: string); procedure ExecuteCommand(const command: string; const parameters: TJSONValue = nil); + procedure ExecuteLineCommand(ALine: Integer; const command: string); procedure UpdateToken(command: string); procedure SetCursorPosition(AColumn, ARow: Integer); procedure cefLoadEnd(Sender: TObject); + procedure DoBreakpointClicked(const line: string); protected function GetHelpTopic: string; override; @@ -136,7 +139,11 @@ type public { Public declarations } - procedure UpdateParColour(par: Integer; LineType: TParColourLineType); + procedure DebugSetBreakpoint(ALine: Integer); + procedure DebugClearBreakpoint(ALine: Integer); + procedure DebugUpdateExecutionPoint(ALine: Integer); + property OnBreakpointClicked: TEditorBreakpointClickedEvent read FOnBreakpointClicked write FOnBreakpointClicked; + procedure SetFocus; override; procedure FindError(ln: Integer); @@ -170,6 +177,7 @@ implementation uses System.TypInfo, Vcl.Clipbrd, + Keyman.Developer.System.HelpTopics, dmActionsMain, @@ -785,6 +793,21 @@ begin cef.cef.ClipboardCut; end; +procedure TframeTextEditor.DebugClearBreakpoint(ALine: Integer); +begin + ExecuteLineCommand(ALine, 'clearBreakpoint'); +end; + +procedure TframeTextEditor.DebugSetBreakpoint(ALine: Integer); +begin + ExecuteLineCommand(ALine, 'setBreakpoint'); +end; + +procedure TframeTextEditor.DebugUpdateExecutionPoint(ALine: Integer); +begin + ExecuteLineCommand(ALine, 'updateExecutionPoint'); +end; + procedure TframeTextEditor.PasteFromClipboard; begin cef.cef.ClipboardPaste; @@ -832,28 +855,32 @@ begin end; end; -procedure TframeTextEditor.FindError(ln: Integer); +procedure TframeTextEditor.ExecuteLineCommand(ALine: Integer; + const command: string); var v: TJSONNumber; +begin + v := TJSONNumber.Create(ALine); + try + ExecuteCommand(command, v); + finally + v.Free; + end; +end; + +procedure TframeTextEditor.FindError(ln: Integer); begin ClearError; if (ln <= 0) then Exit; - v := TJSONNumber.Create(ln); - try - ExecuteCommand('highlightError', v); - SetSelectedRow(ln); - finally - v.Free; - end; + ExecuteLineCommand(ln, 'highlightError'); + SetSelectedRow(ln); end; function TframeTextEditor.OffsetToLine(Offset: Integer): Integer; // I4083 var line: Integer; begin - Result := 0; - with TStringList.Create do try Text := Self.GetText; @@ -879,40 +906,49 @@ end; procedure TframeTextEditor.FireCommand(const commands: TStringList); var i: Integer; - command: string; + command0, command: string; + commandParams: TArray; begin i := 0; while i < commands.Count do begin - command := commands[i]; + command0 := commands[i]; + commandParams := command0.Split([',']); + command := commandParams[0]; if command = 'modified' then Changed // I3948 - else if command = 'undo-disable' then FCanUndo := False else if command = 'undo-enable' then FCanUndo := True else if command = 'redo-disable' then FCanRedo := False else if command = 'redo-enable' then FCanRedo := True else if command = 'has-selection' then FHasSelection := True else if command = 'no-selection' then FHasSelection := False - else if command.StartsWith('insert-mode,') then + else if command = 'breakpoint-clicked' then DoBreakpointClicked(commandParams[1]) + else if command0.StartsWith('insert-mode,') then begin - UpdateInsertState(command.Substring('insert-mode,'.Length)); + UpdateInsertState(command0.Substring('insert-mode,'.Length)); end - else if command.StartsWith('location,') then + else if command0.StartsWith('location,') then begin - UpdateState(command.Substring('location,'.Length)); + UpdateState(command0.Substring('location,'.Length)); end - else if command.StartsWith('token,') then + else if command0.StartsWith('token,') then begin - UpdateToken(command.Substring('token,'.Length)); + UpdateToken(command0.Substring('token,'.Length)); end else ShowMessage('keyman:'+commands.Text); Inc(i); end; end; +procedure TframeTextEditor.DoBreakpointClicked(const line: string); +begin + if Assigned(FOnBreakpointClicked) then + FOnBreakpointClicked(Self, StrToInt(line)); +end; + procedure TframeTextEditor.UpdateToken(command: string); var - n, col: Integer; + col: Integer; line: string; x, tx: Integer; token, prevtoken: WideString; @@ -968,23 +1004,6 @@ begin end; end; -procedure TframeTextEditor.UpdateParColour(par: Integer; LineType: TParColourLineType); -var - j: TJSONObject; -begin - if par < 0 then Exit; - j := TJSONObject.Create; - try - j.AddPair('row', TJSONNumber.Create(par)); - if LineType <> pcltNone then - j.AddPair('style', TJSONString.Create(GetEnumName(TypeInfo(TParColourLineType), Ord(LineType)))); - ExecuteCommand('setRowColor', j); - finally - j.Free; - end; -end; - - function TframeTextEditor.GetHelpTopic: string; begin if FEditorFormat <> efKMN then diff --git a/windows/src/developer/TIKE/xml/app/editor/editor.css b/windows/src/developer/TIKE/xml/app/editor/editor.css index 75e91847a3..0b5916b2dc 100644 --- a/windows/src/developer/TIKE/xml/app/editor/editor.css +++ b/windows/src/developer/TIKE/xml/app/editor/editor.css @@ -11,27 +11,14 @@ html, body { left: 0; } -.ace_marker-layer .km_error, -.ace_marker-layer .km_pcltBreakpoint, -.ace_marker-layer .km_pcltExecutionPoint, -.ace_marker-layer .km_pcltError { - position: absolute; - z-index: 3; -} - -/*.ace-chrome*/ .ace_marker-layer .km_error { +.km_error { background: rgb(255, 128, 128); } -/*.ace-chrome*/ .ace_marker-layer .km_pcltBreakpoint { - background-color: forestgreen; +.km_breakpoint { + background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cdefs%3E%3Cstyle%3E.icon-canvas-transparent,.icon-vs-out{fill:%23f6f6f6}.icon-canvas-transparent{opacity:0}.icon-vs-red{fill:%23e51400}%3C/style%3E%3C/defs%3E%3Ctitle%3Ebreakpoint%3C/title%3E%3Cpath class='icon-canvas-transparent' d='M16 0v16H0V0z' id='canvas'/%3E%3Cpath class='icon-vs-red' d='M11.789 8A3.789 3.789 0 1 1 8 4.211 3.788 3.788 0 0 1 11.789 8z' id='iconBg'/%3E%3C/svg%3E") 50% no-repeat } -/*.ace-chrome*/ .ace_marker-layer .km_pcltExecutionPoint { +.km_executionPoint { background-color: deepskyblue; } - -/*.ace-chrome*/ .ace_marker-layer .km_pcltError { - background: rgb(255, 128, 128); -} - \ No newline at end of file diff --git a/windows/src/developer/TIKE/xml/app/editor/editor.js b/windows/src/developer/TIKE/xml/app/editor/editor.js index 56164ff22a..52a5efdb01 100644 --- a/windows/src/developer/TIKE/xml/app/editor/editor.js +++ b/windows/src/developer/TIKE/xml/app/editor/editor.js @@ -1,3 +1,11 @@ +/* + * Editor using monaco + * + * Helpful references: + * https://microsoft.github.io/monaco-editor/api/index.html + * https://blog.expo.io/building-a-code-editor-with-monaco-f84b3a06deaf + */ + window.editorGlobalContext = { loading: false }; @@ -5,7 +13,8 @@ window.editorGlobalContext = { (function(context) { var editor = null; var errorRange = null; - var ranges = []; + var executionPoint = []; + var breakpoints = []; let params = (new URL(location)).searchParams; let filename = params.get('filename'); let mode = params.get('mode'); @@ -13,103 +22,153 @@ window.editorGlobalContext = { if(!mode) { mode = 'keyman'; } - + + + /** + Initialize the editor + */ + + require.config({ paths: { 'vs': '../lib/monaco/min/vs' } }); + require(['vs/editor/editor.main'], function () { + editor = monaco.editor.create(document.getElementById('editor'), { + language: mode, + minimap: { + enabled: false + }, + glyphMargin: true, + disableMonospaceOptimizations: true + }); + + $.get("/app/source/file", + { + Filename: filename + }, + function (response) { + context.loading = true; + editor.setValue(response); + context.loading = false; + }, + "text" + ); + + const model = editor.getModel(); + model.onDidChangeContent(() => { + // Even when loading, we post back the data to the backend so we have an original version + $.post("/app/source/file", { + Filename: filename, + Data: model.getValue() + // delta.start, delta.end, delta.lines, delta.action + }); + if (!context.loading) { + context.highlightError(); // clear the selected error + command('modified'); + updateState(); + } + }); + + editor.onDidChangeCursorPosition(updateState); + editor.onDidChangeCursorSelection(updateState); + editor.onMouseDown(e => { + if (e.target.type !== monaco.editor.MouseTargetType.GUTTER_GLYPH_MARGIN) { + return; + } + command('breakpoint-clicked,'+(e.target.position.lineNumber-1)); + }); + }); + /* Search and replace interfaces */ - context.searchFind = function() { - editor.commands.byName.find.exec(editor); + context.searchFind = function () { + editor.trigger('', 'actions.find'); }; context.searchFindNext = function() { - editor.commands.byName.selectOrFindNext.exec(editor); + editor.trigger('', 'editor.action.nextMatchFindAction'); }; context.searchReplace = function() { - editor.commands.byName.replace.exec(editor); + editor.trigger('', 'editor.action.startFindReplaceAction'); }; /* Edit command interfaces */ context.editUndo = function() { - editor.undo(); + editor.model.undo(); }; context.editRedo = function() { - editor.redo(); + editor.model.redo(); }; context.editSelectAll = function() { - editor.selectAll(); + editor.setSelection(editor.model.getFullModelRange()); }; /* Row selection */ context.moveCursor = function (o) { - editor.moveCursorTo(o.row, o.column); - editor.selection.clearSelection(); - editor.renderer.scrollCursorIntoView(); + editor.setPosition({ column: o.column + 1, lineNumber: o.row + 1 }); + editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), monaco.editor.ScrollType.Smooth); }; + /* Debug interactions */ + + context.setBreakpoint = function (row) { + if (!breakpoints[row]) { + breakpoints[row] = editor.deltaDecorations( + [], + [{ range: new monaco.Range(row + 1, 1, row + 1, 1), options: { isWholeLine: true, glyphMarginClassName: 'km_breakpoint' } }] + ); + } + }; + + context.clearBreakpoint = function (row) { + if (breakpoints[row]) { + editor.deltaDecorations(breakpoints[row], []); + breakpoints[row] = null; + } + }; + + context.updateExecutionPoint = function (row) { + executionPoint = editor.deltaDecorations( + executionPoint, + row >= 0 ? [{ range: new monaco.Range(row + 1, 1, row + 1, 1), options: { isWholeLine: true, linesDecorationsClassName: 'km_executionPoint' } }] : [] + ); + context.moveCursor({ row: row, column: 0 }); + }; + /* Error highlighting */ - - context.setRowColor = function(o) { - if (o.style) { - var r = new ace.Range(o.row, 0, o.row, Infinity); - r.row = o.row; - r.id = editor.session.addMarker(r, 'km_'+o.style, "fullLine", false); - ranges.push(r); - } else { - ranges = ranges.filter(function (v) { - if (v.row !== o.row) { - return true; - } - editor.session.removeMarker(v.id); - return false; - }); + + context.highlightError = function (row) { + if (errorRange) { + editor.deltaDecorations(errorRange, []); + errorRange = null; } - editor.moveCursorTo(o.row, 0); - editor.selection.clearSelection(); - editor.renderer.scrollCursorIntoView(); - }; - - context.highlightError = function(row) { - if(errorRange) { - editor.session.removeMarker(errorRange.id); - } - if(typeof row == 'number') { - errorRange = new ace.Range(row, 0, row, Infinity); - errorRange.id = editor.session.addMarker(errorRange, 'km_error', "fullLine", false); + if (typeof row == 'number') { + errorRange = editor.deltaDecorations([], [{ range: new monaco.Range(row + 1, 1, row + 1, 1), options: { isWholeLine: true, linesDecorationsClassName: 'km_error', className: 'km_error' } }]); } }; 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); + let r = new monaco.Range(o.top + 1, o.left + 1, o.bottom + 1, o.right + 1); + editor.setSelection(r); + editor.executeEdits("", [ + { range: r, text: o.newText } + ]); }; context.setText = function (text) { - let range = editor.session.selection.getRange(); + let range = editor.getSelection(); context.loading = true; - editor.session.setValue(text); - editor.session.selection.setSelectionRange(range); - context.loading = false; - }; - - context.setText = function (text) { - let range = editor.session.selection.getRange(); - context.loading = true; - editor.session.setValue(text); - editor.session.selection.setSelectionRange(range); + editor.setValue(text); + editor.setSelection(range); context.loading = false; }; /* Printing */ context.print = function () { - require("ace/config").loadModule("ace/ext/static_highlight", function (m) { + /****require("ace/config").loadModule("ace/ext/static_highlight", function (m) { var result = m.renderSync( editor.getValue(), editor.session.getMode(), editor.renderer.theme ); @@ -129,7 +188,7 @@ window.editorGlobalContext = { }, 10); }; document.body.appendChild(iframe); - }); + });*/ }; /** @@ -162,84 +221,38 @@ window.editorGlobalContext = { /** */ - var updateState = function() { - 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 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) { - command('token,'+s.column+','+encodeURIComponent(s.text)); + var updateState = function () { + let s = editor.getSelection(); + command(s.isEmpty() ? 'no-selection' : 'has-selection'); + command(editor.model.canUndo() ? 'undo-enable' : 'undo-disable'); + command(editor.model.canRedo() ? 'redo-enable' : 'redo-disable'); + + var n = editor.model.getValueInRange(s).length; + if (editor.getSelection().getDirection() == monaco.SelectionDirection.LTR) n = -n; + command('location,' + (s.startLineNumber-1) + ',' + (s.startColumn-1) + ',' + (s.endLineNumber-1) + ',' + (s.endColumn-1) + ',' + n); + //command('insert-mode,' + (editor.session.getOption('overwrite') ? 'Overwrite' : 'Insert')); + var token = getTokenAtCursor(); + if (token) { + command('token,' + token.column + ',' + encodeURIComponent(token.text)); } }; - - var getTokenAtCursor = function() { - var txt = editor.getSelectedText(); - if(txt != '') { + + var getTokenAtCursor = function () { + var txt = editor.model.getValueInRange(editor.getSelection()); + if (txt != '') { // We'll always return the first 100 characters of the selection and not // do any manipulation here. - return {column:null,text:txt.substr(0, 99)}; + return { column: null, text: txt.substr(0, 99) }; } - - if(mode == 'keyman') { + + if (mode == 'keyman') { // Get the token under the cursor - var c = editor.session.selection.getCursor(); - var line = editor.session.getLine(c.row); - return {column:c.column, text:line}; + var c = editor.getSelection(); + var line = editor.model.getLineContent(c.positionLineNumber); + return { column: c.positionColumn-1, text: line }; } else { // Get the character under the cursor return null; } }; - - /** - Initialize the editor - */ - $(function initialize() { - editor = ace.edit("editor"); - - // Remove Alt+ key bindings which may conflict with environment shortcuts, e.g. Alt+E, function keys - - var reAltKeyBindings = /(^alt-[a-z0-9]|f[0-9]+)$/; - for (var key in editor.keyBinding.$defaultHandler.commandKeyBinding) { - if (key.match(reAltKeyBindings)) { - delete editor.keyBinding.$defaultHandler.commandKeyBinding[key]; - } - } - - editor.setTheme("ace/theme/xcode"); - - editor.session.selection.on('changeCursor', updateState); - editor.session.on('changeOverwrite', updateState); - editor.session.selection.on('changeSelection', updateState); - - editor.session.on('change', function (delta) { - // Even when loading, we post back the data to the backend so we have an original version - $.post("/app/source/file", { - Filename: filename, - Data: editor.session.getValue() - // delta.start, delta.end, delta.lines, delta.action - }); - if (!context.loading) { - context.highlightError(); // clear the selected error - command('modified'); - updateState(); - } - }); - // Start reading the source file - $.get("/app/source/file", { - Filename: filename - }, function (response) { - context.loading = true; - editor.session.setValue(response); - editor.session.setMode("ace/mode/"+mode); - context.loading = false; - }, - "text"); - }); })(window.editorGlobalContext); \ No newline at end of file diff --git a/windows/src/developer/TIKE/xml/app/editor/index.html b/windows/src/developer/TIKE/xml/app/editor/index.html index eb4ae31a05..939e578d1b 100644 --- a/windows/src/developer/TIKE/xml/app/editor/index.html +++ b/windows/src/developer/TIKE/xml/app/editor/index.html @@ -1,4 +1,4 @@ - + @@ -15,11 +15,12 @@ - -
+ + +