diff --git a/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf b/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf index 8c1bd49e..962339c5 100644 --- a/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf +++ b/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf @@ -50,6 +50,7 @@ namespace Beefy.theme.dark } public Font mFont; + public float mLineHeight = 1.0f; public uint32[] mTextColors = sDefaultColors; public uint32 mHiliteColor = 0xFF2f5c88; public uint32 mUnfocusedHiliteColor = 0x00000000; @@ -104,7 +105,7 @@ namespace Beefy.theme.dark mLineCoords.GrowUninitialized(mData.mLineStarts.Count); mLineCoordJumpTable.Clear(); - float fontHeight = mFont.GetLineSpacing(); + float fontHeight = Math.Round(mFont.GetLineSpacing() * mLineHeight); int prevJumpIdx = -1; float jumpCoordSpacing = GetJumpCoordSpacing(); @@ -214,6 +215,13 @@ namespace Beefy.theme.dark return defaultVal; } + public float GetTextOffset() + { + float baseLineSpacing = mFont.GetLineSpacing(); + float lineSpacing = Math.Round(mFont.GetLineSpacing() * mLineHeight); + return lineSpacing / 2.0f - baseLineSpacing / 2.0f; + } + public int FindUncollapsedLine(int line) { var line; @@ -509,7 +517,7 @@ namespace Beefy.theme.dark ((embed.mKind == .HideLine) && (!hideLine))) selStartX += GS!(4); - Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(1), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(3)); + Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(1) + GetTextOffset(), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(3)); if (rect.mY < 0) rect.mY = 0; return rect; @@ -526,7 +534,9 @@ namespace Beefy.theme.dark #unwarn int lineCount = GetLineCount(); - float lineSpacing = mFont.GetLineSpacing(); + float lineSpacing = Math.Round(mFont.GetLineSpacing() * mLineHeight); + float fontLineSpacing = mFont.GetLineSpacing(); + float textYOffset = GetTextOffset(); float offsetY = mTextInsets.mTop; if (mHeight < lineSpacing) @@ -565,7 +575,7 @@ namespace Beefy.theme.dark { if (mHiliteCurrentLine && selStartIdx == selEndIdx) { - float thickness = 2 * (lineSpacing / 18); + float thickness = Math.Ceiling(2 * (Math.Floor(fontLineSpacing) / 18)); // This isn't quite the right value, but I'm not sure how to get this // to properly highlight the whole line without getting cut off - this works well for now. float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness; @@ -596,18 +606,18 @@ namespace Beefy.theme.dark if (mCharWidth <= 2) { using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.75f)))) - g.FillRect(x, y, GS!(2), lineSpacing); + g.FillRect(x, y + textYOffset, GS!(2), fontLineSpacing); } else { using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.30f)))) - g.FillRect(x, y, mCharWidth, lineSpacing); + g.FillRect(x, y + textYOffset, mCharWidth, fontLineSpacing); } } else { using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness)))) - g.FillRect(x, y, Math.Max(1.0f, GS!(1)), lineSpacing); + g.FillRect(x, y + textYOffset, Math.Max(1.0f, GS!(1)), fontLineSpacing); } drewCursor = true; } @@ -701,7 +711,7 @@ namespace Beefy.theme.dark } float nextX = curX; - nextX = DrawText(g, sectionText, curX, curY, curTypeIdAndFlags); + nextX = DrawText(g, sectionText, curX, curY + textYOffset, curTypeIdAndFlags); DrawSectionFlagsOver(g, curX, curY, nextX - curX, flags); //int32 lineDrawStartColumn = lineDrawStart - lineStart; diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index 6b988f4a..dc83d8e1 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -698,6 +698,7 @@ namespace IDE public List mFonts = new .() ~ DeleteContainerAndItems!(_); public float mFontSize = 12; + public float mLineHeight = 1.0f; public AutoCompleteShowKind mAutoCompleteShowKind = .PanelIfVisible; public bool mAutoCompleteRequireControl = true; public bool mAutoCompleteRequireTab = false; @@ -732,6 +733,7 @@ namespace IDE sd.Add(str); } sd.Add("FontSize", mFontSize); + sd.Add("LineHeight", mLineHeight); sd.Add("AutoCompleteShowKind", mAutoCompleteShowKind); sd.Add("AutoCompleteRequireControl", mAutoCompleteRequireControl); sd.Add("AutoCompleteRequireTab", mAutoCompleteRequireTab); @@ -769,6 +771,7 @@ namespace IDE } sd.Get("UIScale", ref gApp.mSettings.mUISettings.mScale); // Legacy sd.Get("FontSize", ref mFontSize); + sd.Get("LineHeight", ref mLineHeight); sd.Get("AutoCompleteShowKind", ref mAutoCompleteShowKind); sd.Get("AutoCompleteRequireControl", ref mAutoCompleteRequireControl); sd.Get("AutoCompleteRequireTab", ref mAutoCompleteRequireTab); @@ -1365,6 +1368,7 @@ namespace IDE { gApp.mSettings.mUISettings.mScale = Math.Clamp(gApp.mSettings.mUISettings.mScale, 50, 400); gApp.mSettings.mEditorSettings.mFontSize = Math.Clamp(gApp.mSettings.mEditorSettings.mFontSize, 6.0f, 72.0f); + gApp.mSettings.mEditorSettings.mLineHeight = Math.Clamp(gApp.mSettings.mEditorSettings.mLineHeight, 0.125f, 10.0f); mUISettings.Apply(); mEditorSettings.Apply(); @@ -1387,7 +1391,12 @@ namespace IDE for (let value in gApp.mFileEditData.Values) if (value.mEditWidget != null) - ((SourceEditWidgetContent)value.mEditWidget.Content).mHiliteCurrentLine = gApp.mSettings.mEditorSettings.mHiliteCurrentLine; + { + var ewc = (SourceEditWidgetContent)value.mEditWidget.Content; + ewc.mHiliteCurrentLine = gApp.mSettings.mEditorSettings.mHiliteCurrentLine; + ewc.mLineHeight = gApp.mSettings.mEditorSettings.mLineHeight; + ewc.RehupLineCoords(); + } if (!mWakaTimeKey.IsEmpty) { diff --git a/IDE/src/ui/SettingsDialog.bf b/IDE/src/ui/SettingsDialog.bf index aee5fc3b..fda2d33a 100644 --- a/IDE/src/ui/SettingsDialog.bf +++ b/IDE/src/ui/SettingsDialog.bf @@ -98,6 +98,7 @@ namespace IDE.ui category.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, cHeaderColor); AddPropertiesItem(category, "Font", "mFonts"); AddPropertiesItem(category, "Font Size", "mFontSize"); + AddPropertiesItem(category, "Line Height", "mLineHeight"); AddPropertiesItem(category, "Autocomplete", "mAutoCompleteShowKind"); AddPropertiesItem(category, "Autocomplete Require Control", "mAutoCompleteRequireControl"); AddPropertiesItem(category, "Autocomplete Require Tab", "mAutoCompleteRequireTab"); diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index 04a684cd..0343e8db 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -858,6 +858,7 @@ namespace IDE.ui SetFont(IDEApp.sApp.mCodeFont, true, true); //SetFont(DarkTheme.sDarkTheme.mSmallFont, false, false); + mLineHeight = Math.Clamp(gApp.mSettings.mEditorSettings.mLineHeight, 0.125f, 10.0f); mWantsTabsAsSpaces = gApp.mSettings.mEditorSettings.mTabsOrSpaces == .Spaces; mTabLength = gApp.mSettings.mEditorSettings.mTabSize; mTabSize = mFont.GetWidth(scope String(' ', gApp.mSettings.mEditorSettings.mTabSize)); @@ -1211,11 +1212,12 @@ namespace IDE.ui if ((flags & ~(uint8)SourceElementFlags.Skipped) == 0) return; + let lineSpacing = Math.Round(mFont.GetLineSpacing() * mLineHeight); if ((flags & (uint8)SourceElementFlags.SymbolReference) != 0) { bool isRenameSymbol = (IDEApp.sApp.mSymbolReferenceHelper != null) && (IDEApp.sApp.mSymbolReferenceHelper.mKind == SymbolReferenceHelper.Kind.Rename); using (g.PushColor(isRenameSymbol ? (uint32)0x28FFFFFF : (uint32)0x18FFFFFF)) - g.FillRect(x, y, width, mFont.GetLineSpacing()); + g.FillRect(x, y, width, lineSpacing); DrawSectionFlagsOver(g, x, y, width, (uint8)(flags & ~(uint8)SourceElementFlags.SymbolReference)); return; @@ -1224,7 +1226,7 @@ namespace IDE.ui if ((flags & (uint8)SourceElementFlags.Find_CurrentSelection) != 0) { using (g.PushColor(0x504C575C)) - g.FillRect(x, y, width, mFont.GetLineSpacing()); + g.FillRect(x, y, width, lineSpacing); DrawSectionFlagsOver(g, x, y, width, (uint8)(flags & ~(uint8)(SourceElementFlags.Find_CurrentSelection | .Find_Matches))); return; @@ -1233,7 +1235,7 @@ namespace IDE.ui if ((flags & (uint8)SourceElementFlags.Find_Matches) != 0) { using (g.PushColor(0x50D0C090)) - g.FillRect(x, y, width, mFont.GetLineSpacing()); + g.FillRect(x, y, width, lineSpacing); DrawSectionFlagsOver(g, x, y, width, (uint8)(flags & ~(uint8)SourceElementFlags.Find_Matches)); return; @@ -1277,7 +1279,7 @@ namespace IDE.ui if (underlineColor != 0) { using (g.PushColor(underlineColor)) - gApp.DrawSquiggle(g, x, y, width); + gApp.DrawSquiggle(g, x, y + GetTextOffset(), width); } } } @@ -5853,7 +5855,7 @@ namespace IDE.ui } orderedEmitEmbeds.Sort(scope (lhs, rhs) => lhs.line <=> rhs.line); - float fontHeight = mFont.GetLineSpacing(); + float fontHeight = Math.Round(mFont.GetLineSpacing() * mLineHeight); int prevJumpIdx = -1; float jumpCoordSpacing = GetJumpCoordSpacing(); @@ -6432,8 +6434,10 @@ namespace IDE.ui let height = mFont.GetHeight() + GS!(2); using (g.PushColor(DarkTheme.COLOR_CHAR_PAIR_HILITE)) { - g.FillRect(x1, y1, charWidth, height); - g.FillRect(x2, y2, charWidth, height); + float offset = GetTextOffset(); + + g.FillRect(x1, y1 + offset, charWidth, height); + g.FillRect(x2, y2 + offset, charWidth, height); } } } diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index b41134f0..948802a9 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -4550,7 +4550,7 @@ namespace IDE.ui { float editX = GetEditX(); - float lineSpacing = ewc.mFont.GetLineSpacing(); + float lineSpacing = Math.Round(ewc.mFont.GetLineSpacing() * ewc.mLineHeight); int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine; bool hiliteCurrentLine = mEditWidget.mHasFocus; @@ -4719,6 +4719,8 @@ namespace IDE.ui }*/ } + float offset = ewc.GetTextOffset(); + if ((gApp.mSettings.mEditorSettings.mShowLineNumbers) && (mEmbedKind == .None)) { String lineStr = scope String(16); @@ -4748,7 +4750,7 @@ namespace IDE.ui default: lineStr.AppendF("{0}", lineIdx + 1); } using (g.PushColor(DarkTheme.COLOR_TEXT)) - g.DrawString(lineStr, 0, GS!(2) + ewc.mLineCoords[lineIdx], FontAlign.Right, editX - GS!(14)); + g.DrawString(lineStr, 0, GS!(2) + ewc.mLineCoords[lineIdx] + offset, FontAlign.Right, editX - GS!(14)); } } } @@ -4787,7 +4789,7 @@ namespace IDE.ui { using (g.PushColor(0xFFA5A5A5)) { - g.FillRect(editX - (int)GS!(7.5f), ewc.mLineCoords[lineIdx] - (int)GS!(0.5f), (int)GS!(1.5f), lineSpacing); + g.FillRect(editX - (int)GS!(7.5f), ewc.mLineCoords[lineIdx] - offset - (int)GS!(0.5f), (int)GS!(1.5f), lineSpacing + offset); g.FillRect(editX - (int)GS!(7.5f), ewc.mLineCoords[lineIdx] + lineSpacing - (int)GS!(1.5f), GS!(5), (int)GS!(1.5f)); } } @@ -4859,7 +4861,7 @@ namespace IDE.ui mLinePointerDrawData.mUpdateCnt = gApp.mUpdateCnt; mLinePointerDrawData.mDebuggerContinueIdx = gApp.mDebuggerContinueIdx; g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust, - 0 + ewc.GetLineY(lineNum, 0)); + 0 + ewc.GetLineY(lineNum, 0) + ewc.GetTextOffset()); } if (mMousePos != null && mIsDraggingLinePointer) @@ -4869,7 +4871,7 @@ namespace IDE.ui { using (g.PushColor(0x7FFFFFFF)) g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust, - 0 + ewc.GetLineY(dragLineNum, 0)); + 0 + ewc.GetLineY(dragLineNum, 0) + ewc.GetTextOffset()); } } } @@ -7556,7 +7558,7 @@ namespace IDE.ui SourceEditWidgetContent ewc = (.)mEditWidget.Content; Rect linePointerRect = .( mEditWidget.mX - GS!(20) - sDrawLeftAdjust, - 0 + ewc.GetLineY(mLinePointerDrawData.mLine, 0), + 0 + ewc.GetLineY(mLinePointerDrawData.mLine, 0) + ewc.GetTextOffset(), GS!(15), GS!(15) ); @@ -7573,7 +7575,7 @@ namespace IDE.ui else if (mIsDraggingLinePointer) { SourceEditWidgetContent ewc = (.)mEditWidget.Content; - float linePos = ewc.GetLineY(GetLineAt(0, mMousePos.Value.y), 0); + float linePos = ewc.GetLineY(GetLineAt(0, mMousePos.Value.y), 0) + ewc.GetTextOffset(); Rect visibleRange = mEditWidget.GetVisibleContentRange(); if (visibleRange.Top > linePos)