From d0b26a8bb68028b4329a0b95e99250204aa9bc22 Mon Sep 17 00:00:00 2001 From: John Lewin Date: Fri, 14 Oct 2022 10:11:22 -0700 Subject: [PATCH 1/2] Add missing Markdig project --- MatterControl.sln | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/MatterControl.sln b/MatterControl.sln index 5a215e2d4..c038ecd44 100644 --- a/MatterControl.sln +++ b/MatterControl.sln @@ -106,13 +106,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "geometry3Sharp", "Submodule EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestInvoker", "Submodules\agg-sharp\Tests\TestInvoker\TestInvoker.csproj", "{A1F2F1DA-2B86-461E-9602-EAB2BD899A8F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkdigAgg", "Submodules\agg-sharp\MarkdigAgg\MarkdigAgg.csproj", "{C0E747D6-53CA-4747-B581-D175DCDD085F}" +EndProject Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - Submodules\agg-sharp\Typography\Typography.OpenFont\Typography.OpenFont.projitems*{235a071b-8d06-40ae-a5c5-b1ce59715ee9}*SharedItemsImports = 13 - Submodules\agg-sharp\Typography\Typography.GlyphLayout\Typography.GlyphLayout.projitems*{b112455b-e42e-4718-821f-862884b9c07c}*SharedItemsImports = 5 - Submodules\agg-sharp\Typography\Typography.OpenFont\Typography.OpenFont.projitems*{b112455b-e42e-4718-821f-862884b9c07c}*SharedItemsImports = 5 - Submodules\agg-sharp\Typography\Typography.GlyphLayout\Typography.GlyphLayout.projitems*{d8861cf8-c506-472b-8a57-632bd6ca6496}*SharedItemsImports = 13 - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -286,6 +282,10 @@ Global {A1F2F1DA-2B86-461E-9602-EAB2BD899A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {A1F2F1DA-2B86-461E-9602-EAB2BD899A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU {A1F2F1DA-2B86-461E-9602-EAB2BD899A8F}.Release|Any CPU.Build.0 = Release|Any CPU + {C0E747D6-53CA-4747-B581-D175DCDD085F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0E747D6-53CA-4747-B581-D175DCDD085F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0E747D6-53CA-4747-B581-D175DCDD085F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0E747D6-53CA-4747-B581-D175DCDD085F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -334,10 +334,17 @@ Global {34383A75-1831-4816-A38A-AB06B969D7C7} = {FED00F38-E911-45E1-A788-26980E84C3D6} {3A25C796-F676-4422-8F30-01D4FDB240F1} = {2AB9B589-5C98-4C05-BBEA-F97DAE168EAB} {A1F2F1DA-2B86-461E-9602-EAB2BD899A8F} = {FBE6DF29-85A9-4A8B-B739-35BE4CA0A9B7} + {C0E747D6-53CA-4747-B581-D175DCDD085F} = {2AB9B589-5C98-4C05-BBEA-F97DAE168EAB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {42D74E06-00EA-43D2-A05B-9BEAD4A2C8A0} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Submodules\agg-sharp\Typography\Typography.OpenFont\Typography.OpenFont.projitems*{235a071b-8d06-40ae-a5c5-b1ce59715ee9}*SharedItemsImports = 13 + Submodules\agg-sharp\Typography\Typography.GlyphLayout\Typography.GlyphLayout.projitems*{b112455b-e42e-4718-821f-862884b9c07c}*SharedItemsImports = 5 + Submodules\agg-sharp\Typography\Typography.OpenFont\Typography.OpenFont.projitems*{b112455b-e42e-4718-821f-862884b9c07c}*SharedItemsImports = 5 + Submodules\agg-sharp\Typography\Typography.GlyphLayout\Typography.GlyphLayout.projitems*{d8861cf8-c506-472b-8a57-632bd6ca6496}*SharedItemsImports = 13 + EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = MatterControl.csproj EndGlobalSection From 3a4ab087b5ab691aea776b70a8cecce78d04c3d1 Mon Sep 17 00:00:00 2001 From: John Lewin Date: Fri, 14 Oct 2022 10:13:24 -0700 Subject: [PATCH 2/2] Add initial support for terminal text selection - Issue #4880 --- .../TerminalWindow/TextScrollWidget.cs | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs b/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs index 6f9d647a1..87d1482b3 100644 --- a/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs +++ b/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs @@ -52,6 +52,12 @@ namespace MatterHackers.MatterControl /// private int forceStartLine = -1; + // Text selection + private bool dragActive = false; + private int selectionStartLine; + private int selectionEndLine = -1; + private double selectionMouseDown; + private Func _lineFilterFunction; public TextScrollWidget(PrinterConfig printer, TerminalLog terminalLog) @@ -67,6 +73,8 @@ namespace MatterHackers.MatterControl printer.Connection.TerminalLog.LogCleared += this.TerminalLog_LogCleared; } + private double documentHeight => visibleLines.Count * typeFacePrinter.TypeFaceStyle.EmSizeInPixels; + public double Position0To1 { get @@ -89,6 +97,7 @@ namespace MatterHackers.MatterControl // If the start would be less than one screen worth of content, allow // the whole screen to have content and scroll with new material. + // Note: alternatively, if scrolled and sticking to bottom if (forceStartLine > visibleLines.Count - NumVisibleLines) { forceStartLine = -1; @@ -173,6 +182,9 @@ namespace MatterHackers.MatterControl int numLinesToDraw = NumVisibleLines; + int selectionStart = Math.Min(selectionStartLine, selectionEndLine); + int selectionEnd = Math.Max(selectionStartLine, selectionEndLine); + double y = LocalBounds.Bottom + typeFacePrinter.TypeFaceStyle.EmSizeInPixels * numLinesToDraw; lock (locker) { @@ -201,7 +213,13 @@ namespace MatterHackers.MatterControl { typeFacePrinter.Text = visibleLines[lineIndex]; typeFacePrinter.Origin = new Vector2(bounds.Left + 2, y); - typeFacePrinter.Render(graphics2D, TextColor); + + // Account for text selection + var textSelected = selectionEndLine != -1 + && lineIndex >= selectionStart + && lineIndex <= selectionEnd; + + typeFacePrinter.Render(graphics2D, textSelected ? AppContext.Theme.PrimaryAccentColor : TextColor); } } @@ -216,6 +234,57 @@ namespace MatterHackers.MatterControl base.OnDraw(graphics2D); } + private int GetLineIndexFromMouse(Vector2 mousePosition) + { + var yPosFromTop = LocalBounds.Height - mousePosition.Y; + var lineIndex = (int)Math.Ceiling(yPosFromTop / typeFacePrinter.TypeFaceStyle.EmSizeInPixels); + + // After the view fills up and/or when not pinned bottom, scroll offset is simply forceStartLine + // Otherwise it's the offset from the bottom + int scrollOffset = forceStartLine >= 0 ? forceStartLine : visibleLines.Count - NumVisibleLines; + + // Account for scroll + return lineIndex + scrollOffset; + } + + public override void OnMouseDown(MouseEventArgs mouseEvent) + { + dragActive = mouseEvent.Button == MouseButtons.Left; + selectionMouseDown = mouseEvent.Y; + + if (dragActive) + { + // Account for scroll + selectionStartLine = GetLineIndexFromMouse(mouseEvent.Position); + + // Reset end index on start drag + selectionEndLine = -1; + + this.Invalidate(); + } + + base.OnMouseDown(mouseEvent); + } + + public override void OnMouseUp(MouseEventArgs mouseEvent) + { + dragActive = false; + base.OnMouseUp(mouseEvent); + } + + public override void OnMouseMove(MouseEventArgs mouseEvent) + { + if (dragActive) + { + // Recompute line index from mouse position into doc, rather than the more + // typical start/current delta, to ensure range stay in sync with scrolling text + selectionEndLine = GetLineIndexFromMouse(mouseEvent.Position); + this.Invalidate(); + } + + base.OnMouseMove(mouseEvent); + } + public override void OnMouseWheel(MouseEventArgs mouseEvent) { base.OnMouseWheel(mouseEvent); @@ -294,5 +363,30 @@ namespace MatterHackers.MatterControl } } } + + public override void OnKeyUp(KeyEventArgs keyEvent) + { + if (keyEvent.KeyCode == Keys.C + && keyEvent.Control + && Math.Abs(selectionStartLine - selectionEndLine) > 0) + { + int selectionStart = Math.Min(selectionStartLine, selectionEndLine); + int selectionEnd = Math.Max(selectionStartLine, selectionEndLine); + + // Filter visiblelines to selection range + var filteredLines = visibleLines.Where((l, i) => i >= selectionStart && i <= selectionEnd); + + if (UserSettings.Instance.Fields.GetBool(UserSettingsKey.TerminalShowInputOutputMarks, true)) + { + // Drop leading communication/direction indicators + filteredLines = filteredLines.Select(l => l.Substring(l.IndexOf(' ') + 1)); + } + + // Push selected text to clipboard + Clipboard.Instance.SetText(string.Join("\r\n", filteredLines)); + } + + base.OnKeyUp(keyEvent); + } } } \ No newline at end of file