123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922 |
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- using Beefy.widgets;
- using Beefy.gfx;
- using Beefy.utils;
- namespace Beefy.theme.dark
- {
- public class DarkEditWidgetContent : EditWidgetContent
- {
- public Font mFont;
- public uint32[] mTextColors = sDefaultColors;
- public uint32 mHiliteColor = 0xFF2f5c88;
- public uint32 mUnfocusedHiliteColor = 0x00000000;
- public int32 mRecalcSizeLineNum = -1;
- public float mRecalcSizeCurMaxWidth = 0;
- public bool mHasQueuedRecalcSize;
- public int32 mTopCharId = -1;
- public double mTopCharIdVertPos = -1;
- public bool mWantsCheckScrollPosition;
- public uint32 mViewWhiteSpaceColor;
- public bool mScrollToStartOnLostFocus;
- protected static uint32[] sDefaultColors = new uint32[] { Color.White } ~ delete _;
- public this(EditWidgetContent refContent = null) : base(refContent)
- {
- //mTextInsets.Set(-3, 2, 0, 2);
- //mTextInsets.Set(GS!(-3), GS!(2), 0, GS!(2));
- mTextInsets.Set(GS!(0), GS!(2), 0, GS!(2));
- mWidth = GS!(100);
- mHeight = GS!(24);
- mHorzJumpSize = GS!(40);
- mFont = DarkTheme.sDarkTheme.mSmallFont;
- }
- public override void GetTextData()
- {
- // Generate text flags if we need to...
- if ((mData.mTextFlags == null) && (mWordWrap))
- {
- scope AutoBeefPerf("DEWC.GetTextData");
- mData.mTextFlags = new uint8[mData.mTextLength + 1];
- int32 lineIdx = 0;
- int32 lineStartIdx = 0;
- String lineCheck = scope String();
- for (int32 i = 0; i < mData.mTextLength; i++)
- {
- char8 c = (char8)mData.mText[i].mChar;
-
- lineCheck.Clear();
- if (c == '\n')
- ExtractString(lineStartIdx, i - lineStartIdx, lineCheck);
- else if (i == mData.mTextLength - 1)
- ExtractString(lineStartIdx, i - lineStartIdx + 1, lineCheck);
- if (lineCheck.Length > 0)
- {
- String lineCheckLeft = scope String();
- lineCheckLeft.Reference(lineCheck);
- while (true)
- {
- int32 maxChars = GetTabbedCharCountToLength(lineCheckLeft, mEditWidget.mScrollContentContainer.mWidth - mTextInsets.mLeft - mTextInsets.mRight);
- if (maxChars == 0)
- maxChars = 1;
- if (maxChars >= lineCheckLeft.Length)
- break;
-
- int32 checkIdx = maxChars;
- while ((checkIdx > 0) && (!lineCheckLeft[checkIdx].IsWhiteSpace))
- checkIdx--;
-
- if (checkIdx == 0)
- checkIdx = maxChars - 1;
-
- mData.mTextFlags[lineStartIdx + checkIdx + 1] |= (int32)TextFlags.Wrap;
- lineStartIdx += checkIdx + 1;
-
- //lineCheck.Remove(0, checkIdx + 1);
- lineCheckLeft.AdjustPtr(checkIdx + 1);
- }
- }
- if (c == '\n')
- {
- lineStartIdx = i + 1;
- lineIdx++;
- }
- }
- }
- base.GetTextData();
- }
- protected override void AdjustCursorsAfterExternalEdit(int index, int ofs)
- {
- base.AdjustCursorsAfterExternalEdit(index, ofs);
- mWantsCheckScrollPosition = true;
- }
- public float GetTabbedPos(float startX)
- {
- float spaceWidth = mFont.GetWidth((char32)' ');
- if (mTabSize == 0)
- return startX + spaceWidth;
- return (float)Math.Truncate((startX + spaceWidth) / mTabSize + 0.999f) * mTabSize;
- }
- static mixin GetTabSection(var origString, var stringLeft, var subStr)
- {
- int32 tabIdx = (int32)stringLeft.IndexOf('\t');
- if (tabIdx == -1)
- break;
- if (subStr == null)
- {
- subStr = scope:: String(stringLeft, 0, tabIdx);
- stringLeft = scope:: String(origString, tabIdx + 1);
- }
- else
- {
- subStr.Clear();
- subStr.Append(stringLeft, 0, tabIdx);
- stringLeft.Remove(0, tabIdx + 1);
- }
- tabIdx
- }
- public float DoDrawText(Graphics g, String origString, float x, float y)
- {
- String stringLeft = origString;
- float aX = x;
- float aY = y;
- void DrawString(String str, float x, float y)
- {
- if (str.Length == 0)
- return;
- g.DrawString(str, x, y);
- if (mViewWhiteSpaceColor != 0)
- {
- let prevColor = g.mColor;
- g.PopColor();
- g.PushColor(mViewWhiteSpaceColor);
- float curX = x;
- int lastNonSpace = 0;
- for (int i < str.Length)
- {
- char8 c = str[i];
- if (c == ' ')
- {
- // Flush length
- if (lastNonSpace < i)
- {
- var contentStr = scope String();
- contentStr.Reference(str.Ptr + lastNonSpace, i - lastNonSpace);
- curX += mFont.GetWidth(contentStr);
- }
- g.DrawString("·", curX, y);
- curX += mFont.GetWidth(' ');
- lastNonSpace = i + 1;
- }
- }
- g.PopColor();
- g.PushColorOverride(prevColor);
- }
- }
- String subStr = null;
- while (true)
- {
- GetTabSection!(origString, stringLeft, subStr);
- if (g != null)
- DrawString(subStr, aX, aY);
-
- aX += mFont.GetWidth(subStr);
- if ((mViewWhiteSpaceColor != 0) && (g != null))
- {
- let prevColor = g.mColor;
- g.PopColor();
- g.PushColor(mViewWhiteSpaceColor);
- g.DrawString("→", aX, y);
- g.PopColor();
- g.PushColorOverride(prevColor);
- }
- aX = GetTabbedPos(aX);
- }
-
- if (g != null)
- DrawString(stringLeft, aX, aY);
- //TODO: This is just an "emergency dropout", remove when we optimize more?
- /*if ((mX + x >= 0) && (stringLeft.Length > 1000))
- {
- return aX + 10000;
- }*/
- aX += mFont.GetWidth(stringLeft);
- return aX;
- }
- /*public int GetTabbedCharCountToLength(String origString, float len)
- {
- String stringLeft = origString;
- float aX = 0;
- int idx = 0;
- String subStr = null;
- while (true)
- {
- int tabIdx = GetTabSection!(origString, stringLeft, subStr);
-
- int char8Count = mFont.GetCharCountToLength(subStr, len - aX);
- if (char8Count < subStr.Length)
- return idx + char8Count;
- idx += tabIdx + 1;
- aX += mFont.GetWidth(subStr);
- float prevX = aX;
- aX = GetTabbedPos(aX);
- if (len < aX)
- return idx - 1;
- }
- return idx + mFont.GetCharCountToLength(stringLeft, len - aX);
- }*/
- public int32 GetTabbedCharCountToLength(String origString, float len)
- {
- float aX = 0;
- int32 idx = 0;
- String subStr = scope String();
- subStr.Reference(origString);
- while (true)
- {
- bool hitTabStop = false;
- int32 char8Count = (int32)mFont.GetCharCountToLength(subStr, len - aX, &hitTabStop);
- if (!hitTabStop)
- return idx + char8Count;
- aX += mFont.GetWidth(StringView(subStr, 0, char8Count));
- aX = GetTabbedPos(aX);
- if (aX > len + 0.001f)
- return idx + char8Count;
- idx += char8Count + 1;
- subStr.AdjustPtr(char8Count + 1);
- }
- }
- public virtual void DrawSectionFlagsOver(Graphics g, float x, float y, float width, uint8 flags)
- {
- }
- public float GetTabbedWidth(String origString, float x, bool forceAccurate = false)
- {
- String stringLeft = origString;
- float aX = x;
- String subStr = null;
- while (true)
- {
- #unwarn
- int32 tabIdx = GetTabSection!(origString, stringLeft, subStr);
- aX += mFont.GetWidth(subStr);
- aX = GetTabbedPos(aX);
- }
- //TODO: This is just an "emergency dropout", remove when we optimize more?
- /*if ((!forceAccurate) && (mX + x >= 0) && (stringLeft.Length > 1000))
- {
- return aX + 10000;
- }*/
- return aX + mFont.GetWidth(stringLeft);
- }
- public void SetFont(Font font, bool isMonospace, bool virtualCursor)
- {
- mFont = font;
- if (isMonospace)
- {
- mCharWidth = mFont.GetWidth((char32)' ');
- //Debug.Assert(mFont.GetWidth((char32)'W') == mCharWidth);
- if (mTabSize == 0)
- mTabSize = mTabLength * mCharWidth;
- else
- mTabSize = (float)Math.Round(mTabSize / mCharWidth) * mCharWidth;
- }
- else
- mCharWidth = -1;
- if (virtualCursor)
- Debug.Assert(isMonospace);
- mAllowVirtualCursor = virtualCursor;
- }
- public override void RehupScale(float oldScale, float newScale)
- {
- base.RehupScale(oldScale, newScale);
- Utils.RoundScale(ref mTabSize, newScale / oldScale);
- SetFont(mFont, mCharWidth != -1, mAllowVirtualCursor);
- mContentChanged = true; // Defer calling of RecalcSize
- }
- public virtual float DrawText(Graphics g, String str, float x, float y, uint16 typeIdAndFlags)
- {
- using (g.PushColor(mTextColors[typeIdAndFlags & 0xFF]))
- return DoDrawText(g, str, x, y);
- }
- public virtual uint32 GetSelectionColor(uint8 flags)
- {
- return mEditWidget.mHasFocus ? mHiliteColor : mUnfocusedHiliteColor;
- }
- public override void Draw(Graphics g)
- {
- base.Draw(g);
-
- #unwarn
- int lineCount = GetLineCount();
- float lineSpacing = GetLineHeight(0);
- g.SetFont(mFont);
- float offsetY = mTextInsets.mTop;
- if (mHeight < lineSpacing)
- offsetY = (mHeight - lineSpacing) * 0.75f;
- g.PushTranslate(mTextInsets.mLeft, offsetY);
- int selStartLine = -1;
- int selStartCharIdx = -1;
- int selEndLine = -1;
- int selEndCharIdx = -1;
- int selStartIdx = -1;
- int selEndIdx = -1;
- if (mSelection != null)
- {
- mSelection.Value.GetAsForwardSelect(out selStartIdx, out selEndIdx);
- GetLineCharAtIdx(selStartIdx, out selStartLine, out selStartCharIdx);
- GetLineCharAtIdx(selEndIdx, out selEndLine, out selEndCharIdx);
- }
- int firstLine;
- int firstCharIdx;
- float overflowX;
- GetLineCharAtCoord(0, -mY, out firstLine, out firstCharIdx, out overflowX);
- int lastLine;
- int lastCharIdx;
- float lastOverflowX;
- GetLineCharAtCoord(0, -mY + mEditWidget.mScrollContentContainer.mHeight, out lastLine, out lastCharIdx, out lastOverflowX);
- bool drewCursor = false;
- String sectionText = scope String(256);
- for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
- {
- //string lineText = GetLineText(lineIdx);
- int lineStart;
- int lineEnd;
- GetLinePosition(lineIdx, out lineStart, out lineEnd);
- int lineDrawStart = lineStart;
- float curX = 0;
- float curY = lineIdx * lineSpacing;
- while (true)
- {
- int lineDrawEnd = lineDrawStart;
- uint16 curTypeIdAndFlags = *(uint16*)&mData.mText[lineDrawStart].mDisplayTypeId;
- // Check for transition of curTypeIdAndFlags - colors ignore whitespace, but if flags are set then we need
- // to be exact
- /*while ((lineDrawEnd < lineEnd) && ((*(uint16*)&mData.mText[lineDrawEnd].mDisplayTypeId == curTypeIdAndFlags) ||
- ((curTypeIdAndFlags < 0x100) && (((char8)mData.mText[lineDrawEnd].mChar).IsWhiteSpace))))
- lineDrawEnd++;*/
- while (true)
- {
- var checkEnd = ref mData.mText[lineDrawEnd];
- if ((lineDrawEnd < lineEnd) && ((*(uint16*)&checkEnd.mDisplayTypeId == curTypeIdAndFlags) ||
- ((curTypeIdAndFlags < 0x100) && (checkEnd.mChar.IsWhiteSpace) && (checkEnd.mDisplayFlags == 0))))
- lineDrawEnd++;
- else
- break;
- }
- sectionText.Clear();
- ExtractString(lineDrawStart, lineDrawEnd - lineDrawStart, sectionText);
-
- int selStart = Math.Max(0, selStartIdx - lineDrawStart);
- int selEnd = Math.Min(lineDrawEnd - lineDrawStart, selEndIdx - lineDrawStart);
- uint8 flags = (uint8)(curTypeIdAndFlags >> 8);
- if ((lineDrawStart >= selStartIdx) && (lineDrawEnd < selEndIdx) && (lineDrawEnd == lineDrawStart))
- {
- // Blank line selected
- using (g.PushColor(GetSelectionColor(flags)))
- g.FillRect(curX, curY, 4, lineSpacing);
- }
- if (selEnd > selStart)
- {
- String selPrevString = scope String(selStart);
- selPrevString.Append(sectionText, 0, selStart);
- String selIncludeString = scope String(selEnd);
- selIncludeString.Append(sectionText, 0, selEnd);
- float selStartX = GetTabbedWidth(selPrevString, curX);
- float selEndX = GetTabbedWidth(selIncludeString, curX);
- if (lineIdx != selEndLine)
- selEndX += mFont.GetWidth((char32)' ');
- using (g.PushColor(GetSelectionColor(flags)))
- g.FillRect(selStartX, curY, selEndX - selStartX, lineSpacing);
- }
- float nextX = curX;
- nextX = DrawText(g, sectionText, curX, curY, curTypeIdAndFlags);
- DrawSectionFlagsOver(g, curX, curY, nextX - curX, flags);
- //int32 lineDrawStartColumn = lineDrawStart - lineStart;
- //int32 lineDrawEndColumn = lineDrawEnd - lineStart;
- if ((mEditWidget.mHasFocus) && (!drewCursor))
- {
- float aX = -1;
- if (mVirtualCursorPos != null)
- {
- if ((lineIdx == mVirtualCursorPos.Value.mLine) && (lineDrawEnd == lineEnd))
- {
- aX = mVirtualCursorPos.Value.mColumn * mCharWidth;
- }
- }
- else if (mCursorTextPos >= lineDrawStart)
- {
- bool isInside = mCursorTextPos < lineDrawEnd;
- if ((mCursorTextPos == lineDrawEnd) && (lineDrawEnd == lineEnd))
- {
- if (lineDrawEnd == mData.mTextLength)
- isInside = true;
- if (mWordWrap)
- {
- if ((mShowCursorAtLineEnd) || (lineEnd >= mData.mTextFlags.Count) || (mData.mTextFlags[lineEnd] & (int32)TextFlags.Wrap) == 0)
- isInside = true;
- }
- else
- isInside = true;
- }
- if (isInside)
- {
- String subText = scope String(mCursorTextPos - lineDrawStart);
- subText.Append(sectionText, 0, mCursorTextPos - lineDrawStart);
- aX = GetTabbedWidth(subText, curX);
- }
- }
- if (aX != -1)
- {
- float brightness = (float)Math.Cos(Math.Max(0.0f, mCursorBlinkTicks - 20) / 9.0f);
- brightness = Math.Max(0, Math.Min(1.0f, brightness * 2.0f + 1.6f));
- if (mEditWidget.mVertPos.IsMoving)
- brightness = 0; // When we animate a pgup or pgdn, it's weird seeing the cursor scrolling around
- if (mOverTypeMode)
- {
- if (mCharWidth <= 2)
- {
- using (g.PushColor(Color.Get(brightness * 0.75f)))
- g.FillRect(aX, curY, GS!(2), lineSpacing);
- }
- else
- {
- using (g.PushColor(Color.Get(brightness * 0.30f)))
- g.FillRect(aX, curY, mCharWidth, lineSpacing);
- }
- }
- else
- {
- using (g.PushColor(Color.Get(brightness)))
- g.FillRect(aX, curY, Math.Max(1.0f, GS!(1)), lineSpacing);
- }
- drewCursor = true;
- }
- }
- lineDrawStart = lineDrawEnd;
- curX = nextX;
- if (lineDrawStart >= lineEnd)
- break;
- }
- }
- g.PopMatrix();
- /*using (g.PushColor(0x4000FF00))
- g.FillRect(-8, -8, mWidth + 16, mHeight + 16);*/
- /*if (mDbgX != -1)
- g.FillRect(mDbgX - 1, mDbgY - 1, 3, 3);*/
- }
- public override void AddWidget(Widget widget)
- {
- base.AddWidget(widget);
- }
- public override bool AllowChar(char32 theChar)
- {
- if ((int)theChar < 32)
- return (theChar == '\n') || (mIsMultiline && (theChar == '\t'));
- return mFont.HasChar(theChar);
- }
- public override void InsertAtCursor(String theString, InsertFlags insertFlags)
- {
- scope AutoBeefPerf("DarkEditWidgetContent.InsertAtCursor");
- base.InsertAtCursor(theString, insertFlags);
- }
- public override void GetTextCoordAtLineChar(int line, int lineChar, out float x, out float y)
- {
- String lineText = scope String(256);
- GetLineText(line, lineText);
- if (lineChar > lineText.Length)
- x = GetTabbedWidth(lineText, 0) + (mFont.GetWidth((char32)' ') * (lineChar - (int32)lineText.Length)) + mTextInsets.mLeft;
- else
- {
- String subText = scope String(Math.Min(lineChar, 256));
- subText.Append(lineText, 0, lineChar);
- x = GetTabbedWidth(subText, 0, true) + mTextInsets.mLeft;
- }
- y = mTextInsets.mTop + line * mFont.GetLineSpacing();
- }
- public override void GetTextCoordAtLineAndColumn(int line, int column, out float x, out float y)
- {
- Debug.Assert((mCharWidth != -1) || (column == 0));
- String lineText = scope String(256);
- GetLineText(line, lineText);
- x = mTextInsets.mLeft + column * mCharWidth;
- y = mTextInsets.mTop + line * mFont.GetLineSpacing();
- }
- public override bool GetLineCharAtCoord(float x, float y, out int line, out int char8Idx, out float overflowX)
- {
- line = (int) ((y - mTextInsets.mTop) / mFont.GetLineSpacing() + 0.001f);
- int lineCount = GetLineCount();
- if (line < 0)
- line = 0;
- if (line >= lineCount)
- line = lineCount - 1;
- String lineText = scope String(256);
- GetLineText(line, lineText);
- int32 char8Count = GetTabbedCharCountToLength(lineText, x - mTextInsets.mLeft);
- char8Idx = char8Count;
- if (char8Count < lineText.Length)
- {
- String subString = scope String(char8Count);
- subString.Append(lineText, 0, char8Count);
- float subWidth = GetTabbedWidth(subString, 0);
- var utf8enumerator = lineText.DecodedChars(char8Count);
- if (utf8enumerator.MoveNext())
- {
- char32 c = utf8enumerator.Current;
- float checkCharWidth = 0;
- if (c == '\t')
- checkCharWidth = mTabSize * 0.5f;
- else
- {
- checkCharWidth = mFont.GetWidth(c) * 0.5f;
- }
- if (x >= subWidth + mTextInsets.mLeft + checkCharWidth)
- char8Idx = (int32)utf8enumerator.NextIndex;
- }
- }
- else
- {
- overflowX = (x - mTextInsets.mLeft) - (GetTabbedWidth(lineText, 0) + 0.001f);
- return overflowX <= 0;
- }
- overflowX = 0;
- return true;
- }
- public override bool GetLineAndColumnAtCoord(float x, float y, out int line, out int column)
- {
- line = (int32)((y - mTextInsets.mTop) / mFont.GetLineSpacing() + 0.001f);
- if (line >= GetLineCount())
- line = GetLineCount() - 1;
- line = Math.Max(0, line);
- column = Math.Max(0, (int32)((x - mTextInsets.mLeft + 1) / mCharWidth + 0.6f));
- return mCharWidth != -1;
- }
- void RecalcSize(int32 startLineNum, int32 endLineNum, bool forceAccurate = false)
- {
- scope AutoBeefPerf("DEWC.RecalcSize");
- String line = scope String();
- for (int32 lineIdx = startLineNum; lineIdx < endLineNum; lineIdx++)
- {
- line.Clear();
- GetLineText(lineIdx, line);
- mRecalcSizeCurMaxWidth = Math.Max(mRecalcSizeCurMaxWidth, GetTabbedWidth(line, 0, forceAccurate) + mHorzJumpSize);
- Debug.Assert(!mRecalcSizeCurMaxWidth.IsNaN);
- }
- }
- public override void CursorToLineEnd()
- {
- //int32 line;
- //int32 lineChar;
- //GetCursorLineChar(out line, out lineChar);
- /*RecalcSize(line, line + 1, true);
- if (mRecalcSizeCurMaxWidth > mWidth)
- {
- mRecalcSizeLineNum = -1;
- }*/
- mRecalcSizeLineNum = -1;
- RecalcSize(true);
- base.CursorToLineEnd();
- }
- public void RecalcSize(bool forceAccurate = false)
- {
- mMaximalScrollAddedHeight = 0;
- if (mRecalcSizeLineNum == -1)
- {
- mRecalcSizeCurMaxWidth = 0;
- mHasQueuedRecalcSize = false;
- }
- else // We need to recalc again after our current pass
- mHasQueuedRecalcSize = true;
- if (!mIsReadOnly)
- {
- float cursorX;
- float cursorY;
- GetTextCoordAtCursor(out cursorX, out cursorY);
- mRecalcSizeCurMaxWidth = Math.Max(mRecalcSizeCurMaxWidth, cursorX + mHorzJumpSize);
- }
- if (mUpdateCnt == 0)
- {
- RecalcSize(0, GetLineCount());
- mWidth = mRecalcSizeCurMaxWidth + mTextInsets.mLeft + mTextInsets.mRight;
- Debug.Assert(!mWidth.IsNaN);
- }
- else if (mRecalcSizeLineNum == -1)
- {
- mRecalcSizeLineNum = 0;
- // The actual recalculation will take 16 ticks so just make sure we have enough width for
- // the current line for now
- var lineAndCol = CursorLineAndColumn;
- RecalcSize(lineAndCol.mLine, lineAndCol.mLine + 1, forceAccurate);
- mWidth = Math.Max(mWidth, mRecalcSizeCurMaxWidth + mTextInsets.mLeft + mTextInsets.mRight);
- Debug.Assert(!mWidth.IsNaN);
- }
- mHeight = GetLineCount() * mFont.GetLineSpacing() + mTextInsets.mTop + mTextInsets.mBottom;
- UpdateMaximalScroll();
- base.RecalcSize();
- }
- public override void RecalcSize()
- {
- RecalcSize(false);
- }
- public override void ContentChanged()
- {
- base.ContentChanged();
- mRecalcSizeLineNum = -1;
- }
- public override void TextAppended(String str)
- {
- if ((mData.mLineStarts != null) && (mIsReadOnly))
- {
- int32 recalcSizeLineNum = Math.Max((int32)mData.mLineStarts.Count - 2, 0);
- if ((mRecalcSizeLineNum == -1) || (recalcSizeLineNum < mRecalcSizeLineNum))
- mRecalcSizeLineNum = recalcSizeLineNum;
- }
- base.TextAppended(str);
- }
- void UpdateMaximalScroll()
- {
- if (mAllowMaximalScroll)
- {
- let prevHeight = mHeight;
- mHeight -= mMaximalScrollAddedHeight;
- mMaximalScrollAddedHeight = mEditWidget.mScrollContentContainer.mHeight - mFont.GetLineSpacing();
- mHeight += mMaximalScrollAddedHeight;
- if (mHeight != prevHeight)
- mEditWidget.UpdateScrollbars();
- }
- }
- public override void Resize(float x, float y, float width, float height)
- {
- base.Resize(x, y, width, height);
- UpdateMaximalScroll();
- }
- public override float GetLineHeight(int line)
- {
- return mFont.GetLineSpacing();
- }
- public override float GetPageScrollTextHeight()
- {
- float numLinesVisible = mEditWidget.mScrollContentContainer.mHeight / mFont.GetLineSpacing();
- if (numLinesVisible - (int32)numLinesVisible < 0.90f)
- numLinesVisible = (int32) numLinesVisible;
- float val = numLinesVisible * mFont.GetLineSpacing();
- if (val <= 0)
- return base.GetPageScrollTextHeight();
- return val;
- }
- public void CheckRecordScrollTop()
- {
- if (mWantsCheckScrollPosition)
- {
- if (mTopCharId != -1)
- {
- int textIdx = mData.mTextIdData.GetPrepared().GetIndexFromId(mTopCharId);
- if (textIdx != -1)
- {
- int line;
- int lineChar;
- GetLineCharAtIdx(textIdx, out line, out lineChar);
- var vertPos = mEditWidget.mVertPos.mDest;
- var offset = vertPos % mFont.GetLineSpacing();
- mEditWidget.mVertScrollbar.ScrollTo(line * mFont.GetLineSpacing() + offset);
- }
- else
- {
- mTopCharId = -1;
- }
- }
- mWantsCheckScrollPosition = false;
- }
- if (mEditWidget.mHasFocus)
- {
- mTopCharId = -1;
- }
- else
- {
- var vertPos = mEditWidget.mVertPos.mDest;
- if ((mTopCharId == -1) || (mTopCharIdVertPos != vertPos))
- {
- float lineNum = (float)(vertPos / mFont.GetLineSpacing());
- int lineStart;
- int lineEnd;
- GetLinePosition((int32)lineNum, out lineStart, out lineEnd);
- int idAtStart = mData.mTextIdData.GetIdAtIndex((int32)lineStart);
- if (idAtStart == -1)
- idAtStart = 0;
- mTopCharId = (int32)idAtStart;
- mTopCharIdVertPos = vertPos;
- }
- }
- }
- public override void Update()
- {
- base.Update();
- if ((mRecalcSizeLineNum != -1) && (BFApp.sApp.mIsUpdateBatchStart))
- {
- int32 lineCount = GetLineCount();
- int32 toLine = Math.Min(lineCount, mRecalcSizeLineNum + Math.Max(1, lineCount / 16) + 80);
- RecalcSize(mRecalcSizeLineNum, toLine);
- if (toLine == lineCount)
- {
- mRecalcSizeLineNum = -1;
- mWidth = mRecalcSizeCurMaxWidth + mTextInsets.mLeft + mTextInsets.mRight;
- base.RecalcSize();
- }
- else
- mRecalcSizeLineNum = toLine;
- }
- if ((mRecalcSizeLineNum == -1) && (mHasQueuedRecalcSize))
- RecalcSize();
- CheckRecordScrollTop();
- }
- }
- public class DarkEditWidget : EditWidget
- {
- public bool mDrawBox = true;
- public this(DarkEditWidgetContent content = null)
- {
- mEditWidgetContent = content;
- if (mEditWidgetContent == null)
- mEditWidgetContent = new DarkEditWidgetContent();
- mEditWidgetContent.mEditWidget = this;
- mScrollContent = mEditWidgetContent;
- mScrollContentContainer.AddWidget(mEditWidgetContent);
- SetupInsets();
- //mScrollbarInsets.Set(18, 1, 0, 0);
- mHorzPos.mSpeed = 0.2f;
- mVertPos.mSpeed = 0.2f;
- mScrollbarBaseContentSizeOffset = GS!(3);
- }
- protected virtual void SetupInsets()
- {
- mScrollContentInsets.Set(GS!(3), GS!(3), GS!(3), GS!(3));
- }
- protected override void HandleWindowMouseDown(Beefy.events.MouseEvent event)
- {
- base.HandleWindowMouseDown(event);
- // If we got closed as part of this click, don't propagate the click through
- if (mParent == null)
- {
- event.mHandled = true;
- }
- }
- public override void RehupScale(float oldScale, float newScale)
- {
- base.RehupScale(oldScale, newScale);
- SetupInsets();
- }
- public override void DefaultDesignInit()
- {
- base.DefaultDesignInit();
- mWidth = GS!(80);
- mHeight = GS!(20);
- SetText("Edit Text");
- }
- public override void InitScrollbars(bool wantHorz, bool wantVert)
- {
- SetupInsets();
- base.InitScrollbars(wantHorz, wantVert);
- float scrollIncrement = ((DarkEditWidgetContent) mEditWidgetContent).mFont.GetLineSpacing() * GS!(3);
- if (mHorzScrollbar != null)
- mHorzScrollbar.mScrollIncrement = scrollIncrement;
- if (mVertScrollbar != null)
- mVertScrollbar.mScrollIncrement = scrollIncrement;
- }
- public override void Draw(Graphics g)
- {
- base.Draw(g);
- if (mDrawBox)
- {
- g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.EditBox), 0, 0, mWidth, mHeight);
- if (mHasFocus)
- {
- using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
- g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Outline), 0, 0, mWidth, mHeight);
- }
- }
- /*using (g.PushColor(0x40FF0000))
- g.FillRect(0, 0, mWidth, mHeight);*/
- }
- public override void LostFocus()
- {
- base.LostFocus();
- var darkEditWidgetContent = (DarkEditWidgetContent)mEditWidgetContent;
- darkEditWidgetContent.CheckRecordScrollTop();
- if (darkEditWidgetContent.mScrollToStartOnLostFocus)
- HorzScrollTo(0);
- }
- }
- }
|