1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Merge pull request #2136 from MineBill/line-spacing

Add a 'Line Height' options that allows changing the the line height of the text editor.
This commit is contained in:
Brian Fiete 2025-02-16 11:43:14 -08:00 committed by GitHub
commit 4ada557f64
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 49 additions and 23 deletions

View file

@ -50,6 +50,7 @@ namespace Beefy.theme.dark
} }
public Font mFont; public Font mFont;
public float mLineHeight = 1.0f;
public uint32[] mTextColors = sDefaultColors; public uint32[] mTextColors = sDefaultColors;
public uint32 mHiliteColor = 0xFF2f5c88; public uint32 mHiliteColor = 0xFF2f5c88;
public uint32 mUnfocusedHiliteColor = 0x00000000; public uint32 mUnfocusedHiliteColor = 0x00000000;
@ -104,7 +105,7 @@ namespace Beefy.theme.dark
mLineCoords.GrowUninitialized(mData.mLineStarts.Count); mLineCoords.GrowUninitialized(mData.mLineStarts.Count);
mLineCoordJumpTable.Clear(); mLineCoordJumpTable.Clear();
float fontHeight = mFont.GetLineSpacing(); float fontHeight = Math.Round(mFont.GetLineSpacing() * mLineHeight);
int prevJumpIdx = -1; int prevJumpIdx = -1;
float jumpCoordSpacing = GetJumpCoordSpacing(); float jumpCoordSpacing = GetJumpCoordSpacing();
@ -214,6 +215,13 @@ namespace Beefy.theme.dark
return defaultVal; 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) public int FindUncollapsedLine(int line)
{ {
var line; var line;
@ -509,7 +517,7 @@ namespace Beefy.theme.dark
((embed.mKind == .HideLine) && (!hideLine))) ((embed.mKind == .HideLine) && (!hideLine)))
selStartX += GS!(4); 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) if (rect.mY < 0)
rect.mY = 0; rect.mY = 0;
return rect; return rect;
@ -526,7 +534,9 @@ namespace Beefy.theme.dark
#unwarn #unwarn
int lineCount = GetLineCount(); 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; float offsetY = mTextInsets.mTop;
if (mHeight < lineSpacing) if (mHeight < lineSpacing)
@ -565,7 +575,7 @@ namespace Beefy.theme.dark
{ {
if (mHiliteCurrentLine && selStartIdx == selEndIdx) 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 // 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. // to properly highlight the whole line without getting cut off - this works well for now.
float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness; float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness;
@ -596,18 +606,18 @@ namespace Beefy.theme.dark
if (mCharWidth <= 2) if (mCharWidth <= 2)
{ {
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.75f)))) 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 else
{ {
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.30f)))) 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 else
{ {
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness)))) 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; drewCursor = true;
} }
@ -701,7 +711,7 @@ namespace Beefy.theme.dark
} }
float nextX = curX; 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); DrawSectionFlagsOver(g, curX, curY, nextX - curX, flags);
//int32 lineDrawStartColumn = lineDrawStart - lineStart; //int32 lineDrawStartColumn = lineDrawStart - lineStart;

View file

@ -698,6 +698,7 @@ namespace IDE
public List<String> mFonts = new .() ~ DeleteContainerAndItems!(_); public List<String> mFonts = new .() ~ DeleteContainerAndItems!(_);
public float mFontSize = 12; public float mFontSize = 12;
public float mLineHeight = 1.0f;
public AutoCompleteShowKind mAutoCompleteShowKind = .PanelIfVisible; public AutoCompleteShowKind mAutoCompleteShowKind = .PanelIfVisible;
public bool mAutoCompleteRequireControl = true; public bool mAutoCompleteRequireControl = true;
public bool mAutoCompleteRequireTab = false; public bool mAutoCompleteRequireTab = false;
@ -732,6 +733,7 @@ namespace IDE
sd.Add(str); sd.Add(str);
} }
sd.Add("FontSize", mFontSize); sd.Add("FontSize", mFontSize);
sd.Add("LineHeight", mLineHeight);
sd.Add("AutoCompleteShowKind", mAutoCompleteShowKind); sd.Add("AutoCompleteShowKind", mAutoCompleteShowKind);
sd.Add("AutoCompleteRequireControl", mAutoCompleteRequireControl); sd.Add("AutoCompleteRequireControl", mAutoCompleteRequireControl);
sd.Add("AutoCompleteRequireTab", mAutoCompleteRequireTab); sd.Add("AutoCompleteRequireTab", mAutoCompleteRequireTab);
@ -769,6 +771,7 @@ namespace IDE
} }
sd.Get("UIScale", ref gApp.mSettings.mUISettings.mScale); // Legacy sd.Get("UIScale", ref gApp.mSettings.mUISettings.mScale); // Legacy
sd.Get("FontSize", ref mFontSize); sd.Get("FontSize", ref mFontSize);
sd.Get("LineHeight", ref mLineHeight);
sd.Get("AutoCompleteShowKind", ref mAutoCompleteShowKind); sd.Get("AutoCompleteShowKind", ref mAutoCompleteShowKind);
sd.Get("AutoCompleteRequireControl", ref mAutoCompleteRequireControl); sd.Get("AutoCompleteRequireControl", ref mAutoCompleteRequireControl);
sd.Get("AutoCompleteRequireTab", ref mAutoCompleteRequireTab); 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.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.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(); mUISettings.Apply();
mEditorSettings.Apply(); mEditorSettings.Apply();
@ -1387,7 +1391,12 @@ namespace IDE
for (let value in gApp.mFileEditData.Values) for (let value in gApp.mFileEditData.Values)
if (value.mEditWidget != null) 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) if (!mWakaTimeKey.IsEmpty)
{ {

View file

@ -98,6 +98,7 @@ namespace IDE.ui
category.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, cHeaderColor); category.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, cHeaderColor);
AddPropertiesItem(category, "Font", "mFonts"); AddPropertiesItem(category, "Font", "mFonts");
AddPropertiesItem(category, "Font Size", "mFontSize"); AddPropertiesItem(category, "Font Size", "mFontSize");
AddPropertiesItem(category, "Line Height", "mLineHeight");
AddPropertiesItem(category, "Autocomplete", "mAutoCompleteShowKind"); AddPropertiesItem(category, "Autocomplete", "mAutoCompleteShowKind");
AddPropertiesItem(category, "Autocomplete Require Control", "mAutoCompleteRequireControl"); AddPropertiesItem(category, "Autocomplete Require Control", "mAutoCompleteRequireControl");
AddPropertiesItem(category, "Autocomplete Require Tab", "mAutoCompleteRequireTab"); AddPropertiesItem(category, "Autocomplete Require Tab", "mAutoCompleteRequireTab");

View file

@ -858,6 +858,7 @@ namespace IDE.ui
SetFont(IDEApp.sApp.mCodeFont, true, true); SetFont(IDEApp.sApp.mCodeFont, true, true);
//SetFont(DarkTheme.sDarkTheme.mSmallFont, false, false); //SetFont(DarkTheme.sDarkTheme.mSmallFont, false, false);
mLineHeight = Math.Clamp(gApp.mSettings.mEditorSettings.mLineHeight, 0.125f, 10.0f);
mWantsTabsAsSpaces = gApp.mSettings.mEditorSettings.mTabsOrSpaces == .Spaces; mWantsTabsAsSpaces = gApp.mSettings.mEditorSettings.mTabsOrSpaces == .Spaces;
mTabLength = gApp.mSettings.mEditorSettings.mTabSize; mTabLength = gApp.mSettings.mEditorSettings.mTabSize;
mTabSize = mFont.GetWidth(scope String(' ', 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) if ((flags & ~(uint8)SourceElementFlags.Skipped) == 0)
return; return;
let lineSpacing = Math.Round(mFont.GetLineSpacing() * mLineHeight);
if ((flags & (uint8)SourceElementFlags.SymbolReference) != 0) if ((flags & (uint8)SourceElementFlags.SymbolReference) != 0)
{ {
bool isRenameSymbol = (IDEApp.sApp.mSymbolReferenceHelper != null) && (IDEApp.sApp.mSymbolReferenceHelper.mKind == SymbolReferenceHelper.Kind.Rename); bool isRenameSymbol = (IDEApp.sApp.mSymbolReferenceHelper != null) && (IDEApp.sApp.mSymbolReferenceHelper.mKind == SymbolReferenceHelper.Kind.Rename);
using (g.PushColor(isRenameSymbol ? (uint32)0x28FFFFFF : (uint32)0x18FFFFFF)) 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)); DrawSectionFlagsOver(g, x, y, width, (uint8)(flags & ~(uint8)SourceElementFlags.SymbolReference));
return; return;
@ -1224,7 +1226,7 @@ namespace IDE.ui
if ((flags & (uint8)SourceElementFlags.Find_CurrentSelection) != 0) if ((flags & (uint8)SourceElementFlags.Find_CurrentSelection) != 0)
{ {
using (g.PushColor(0x504C575C)) 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))); DrawSectionFlagsOver(g, x, y, width, (uint8)(flags & ~(uint8)(SourceElementFlags.Find_CurrentSelection | .Find_Matches)));
return; return;
@ -1233,7 +1235,7 @@ namespace IDE.ui
if ((flags & (uint8)SourceElementFlags.Find_Matches) != 0) if ((flags & (uint8)SourceElementFlags.Find_Matches) != 0)
{ {
using (g.PushColor(0x50D0C090)) 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)); DrawSectionFlagsOver(g, x, y, width, (uint8)(flags & ~(uint8)SourceElementFlags.Find_Matches));
return; return;
@ -1277,7 +1279,7 @@ namespace IDE.ui
if (underlineColor != 0) if (underlineColor != 0)
{ {
using (g.PushColor(underlineColor)) 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); orderedEmitEmbeds.Sort(scope (lhs, rhs) => lhs.line <=> rhs.line);
float fontHeight = mFont.GetLineSpacing(); float fontHeight = Math.Round(mFont.GetLineSpacing() * mLineHeight);
int prevJumpIdx = -1; int prevJumpIdx = -1;
float jumpCoordSpacing = GetJumpCoordSpacing(); float jumpCoordSpacing = GetJumpCoordSpacing();
@ -6432,8 +6434,10 @@ namespace IDE.ui
let height = mFont.GetHeight() + GS!(2); let height = mFont.GetHeight() + GS!(2);
using (g.PushColor(DarkTheme.COLOR_CHAR_PAIR_HILITE)) using (g.PushColor(DarkTheme.COLOR_CHAR_PAIR_HILITE))
{ {
g.FillRect(x1, y1, charWidth, height); float offset = GetTextOffset();
g.FillRect(x2, y2, charWidth, height);
g.FillRect(x1, y1 + offset, charWidth, height);
g.FillRect(x2, y2 + offset, charWidth, height);
} }
} }
} }

View file

@ -4550,7 +4550,7 @@ namespace IDE.ui
{ {
float editX = GetEditX(); float editX = GetEditX();
float lineSpacing = ewc.mFont.GetLineSpacing(); float lineSpacing = Math.Round(ewc.mFont.GetLineSpacing() * ewc.mLineHeight);
int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine; int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine;
bool hiliteCurrentLine = mEditWidget.mHasFocus; bool hiliteCurrentLine = mEditWidget.mHasFocus;
@ -4719,6 +4719,8 @@ namespace IDE.ui
}*/ }*/
} }
float offset = ewc.GetTextOffset();
if ((gApp.mSettings.mEditorSettings.mShowLineNumbers) && (mEmbedKind == .None)) if ((gApp.mSettings.mEditorSettings.mShowLineNumbers) && (mEmbedKind == .None))
{ {
String lineStr = scope String(16); String lineStr = scope String(16);
@ -4748,7 +4750,7 @@ namespace IDE.ui
default: lineStr.AppendF("{0}", lineIdx + 1); default: lineStr.AppendF("{0}", lineIdx + 1);
} }
using (g.PushColor(DarkTheme.COLOR_TEXT)) 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)) 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)); 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.mUpdateCnt = gApp.mUpdateCnt;
mLinePointerDrawData.mDebuggerContinueIdx = gApp.mDebuggerContinueIdx; mLinePointerDrawData.mDebuggerContinueIdx = gApp.mDebuggerContinueIdx;
g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust, g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust,
0 + ewc.GetLineY(lineNum, 0)); 0 + ewc.GetLineY(lineNum, 0) + ewc.GetTextOffset());
} }
if (mMousePos != null && mIsDraggingLinePointer) if (mMousePos != null && mIsDraggingLinePointer)
@ -4869,7 +4871,7 @@ namespace IDE.ui
{ {
using (g.PushColor(0x7FFFFFFF)) using (g.PushColor(0x7FFFFFFF))
g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust, 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; SourceEditWidgetContent ewc = (.)mEditWidget.Content;
Rect linePointerRect = .( Rect linePointerRect = .(
mEditWidget.mX - GS!(20) - sDrawLeftAdjust, mEditWidget.mX - GS!(20) - sDrawLeftAdjust,
0 + ewc.GetLineY(mLinePointerDrawData.mLine, 0), 0 + ewc.GetLineY(mLinePointerDrawData.mLine, 0) + ewc.GetTextOffset(),
GS!(15), GS!(15),
GS!(15) GS!(15)
); );
@ -7573,7 +7575,7 @@ namespace IDE.ui
else if (mIsDraggingLinePointer) else if (mIsDraggingLinePointer)
{ {
SourceEditWidgetContent ewc = (.)mEditWidget.Content; 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(); Rect visibleRange = mEditWidget.GetVisibleContentRange();
if (visibleRange.Top > linePos) if (visibleRange.Top > linePos)