using Beefy.widgets; using Beefy.gfx; using Beefy.theme.dark; using System; using System.IO; using Beefy.utils; using System.Threading; using System.Collections; using System.Diagnostics; namespace LogViewer { class Board : Widget { public struct Match { public int32 mFilterIdx; public int32 mTextIdx; } public DarkEditWidget mDocEdit; public DarkEditWidget mFilterEdit; public String mContent ~ delete _; public StatusBar mStatusBar; public String mFilter = new String() ~ delete _; public List mFilterLengths = new List() ~ delete _; public int mFilterDirtyCountdown = 1; public String mNewContent ~ delete _; public List mNewMatches ~ delete _; public bool mRefreshing; public uint32[] mColors = new .( 0xFFFFFFFF, 0xFFFC5858, 0xFF00FF00, 0xFF6E67FF, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF, 0XFFFFBD67 ) ~ delete _; public this() { mStatusBar = new StatusBar(); AddWidget(mStatusBar); mDocEdit = new DarkEditWidget(); var ewc = (DarkEditWidgetContent)mDocEdit.mEditWidgetContent; ewc.mIsMultiline = true; ewc.mFont = gApp.mFont; ewc.mWordWrap = false; ewc.mTextColors = mColors; mDocEdit.InitScrollbars(true, true); AddWidget(mDocEdit); mFilterEdit = new DarkEditWidget(); ewc = (DarkEditWidgetContent)mFilterEdit.mEditWidgetContent; ewc.mIsMultiline = true; ewc.mFont = gApp.mFont; ewc.mWordWrap = false; ewc.mTextColors = mColors; mFilterEdit.InitScrollbars(true, true); AddWidget(mFilterEdit); } int GetColorIdx(int idx) { return (idx % (mColors.Count - 1)) + 1; } uint32 GetColor(int idx) { return mColors[(idx % (mColors.Count - 1)) + 1]; } public void Load(StringView filePath) { scope AutoBeefPerf("Board.Load"); delete mContent; mContent = new String(); let result = File.ReadAllText(filePath, mContent, false); if (result case .Err) { gApp.Fail("Failed to open file '{0}'", filePath); } //mDocEdit.SetText(mContent); } void Refresh() { scope AutoBeefPerf("Board.Refresh"); //let profileId = Profiler.StartSampling(Thread.CurrentThread).GetValueOrDefault(); delete mNewContent; mNewContent = new String(); delete mNewMatches; mNewMatches = new List(); let filters = mFilter.Split!('\n'); for (var line in mContent.Split('\n')) { bool hadMatch = false; bool hadFilter = false; for (var filter in filters) { if (filter.Length == 0) continue; hadFilter = true; int lastIdx = -1; while (true) { int findIdx = line.IndexOf(filter, lastIdx + 1); if (findIdx == -1) break; hadMatch = true; lastIdx = findIdx + filter.Length - 1; Match match; match.mFilterIdx = (.)@filter; match.mTextIdx = (.)(mNewContent.Length + findIdx); mNewMatches.Add(match); } } if ((hadMatch) || (!hadFilter)) { mNewContent.Append(line); mNewContent.Append('\n'); } } mRefreshing = false; /*if (profileId != 0) profileId.Dispose();*/ } public override void Draw(Graphics g) { base.Draw(g); //using (g.PushColor(0xFFE02040)) //g.FillRect(0, 0, mWidth, mHeight); g.DrawBox(DarkTheme.sDarkTheme.GetImage(.Bkg), 0, 0, mWidth, mHeight); } public override void DrawAll(Graphics g) { base.DrawAll(g); /*g.SetFont(gApp.mFont); g.DrawString(scope String()..AppendF("FPS: {0}", gApp.mLastFPS), 0, 0);*/ } void ResizeComponents() { float statusBarHeight = 20; float findHeight = 140; mDocEdit.Resize(0, 0, mWidth, mHeight - findHeight - statusBarHeight); mFilterEdit.Resize(0, mHeight - findHeight - statusBarHeight, mWidth, findHeight); mStatusBar.Resize(0, mHeight - statusBarHeight, mWidth, statusBarHeight); } public override void Resize(float x, float y, float width, float height) { base.Resize(x, y, width, height); ResizeComponents(); } public override void Update() { base.Update(); if (mRefreshing) { // Just wait... } else { if (mNewContent != null) { var ewc = (DarkEditWidgetContent)mFilterEdit.mEditWidgetContent; for (int lineIdx < ewc.GetLineCount()) { int colorIdx = GetColorIdx(lineIdx); ewc.GetLinePosition(lineIdx, let lineStart, let lineEnd); for (int i = lineStart; i < lineEnd; i++) { ewc.mData.mText[i].mDisplayTypeId = (.)colorIdx; } } ewc = (DarkEditWidgetContent)mDocEdit.mEditWidgetContent; mDocEdit.SetText(mNewContent); for (let match in mNewMatches) { int colorIdx = GetColorIdx(match.mFilterIdx); int matchLength = mFilterLengths[match.mFilterIdx]; for (int i = match.mTextIdx; i < match.mTextIdx + matchLength; i++) { ewc.mData.mText[i].mDisplayTypeId = (.)colorIdx; } } DeleteAndNullify!(mNewContent); DeleteAndNullify!(mNewMatches); } var filter = scope String(); mFilterEdit.GetText(filter); if (filter != mFilter) { mFilter.Set(filter); mFilterDirtyCountdown = 5; } mFilterLengths.Clear(); for (let filterLine in mFilter.Split('\n')) { mFilterLengths.Add((int32)filterLine.Length); } if ((mFilterDirtyCountdown > 0) && (gApp.mIsUpdateBatchStart)) { if (--mFilterDirtyCountdown == 0) { ThreadPool.QueueUserWorkItem(new => Refresh); mRefreshing = true; } } } } } }