From 64a23ceb9abc1c6b7685c7865a5c309bf99d2a96 Mon Sep 17 00:00:00 2001 From: Fusioon Date: Sun, 4 Jun 2023 13:41:44 +0200 Subject: [PATCH] Add startup panel --- IDE/src/IDEApp.bf | 13 ++ IDE/src/Settings.bf | 4 + IDE/src/ui/SettingsDialog.bf | 1 + IDE/src/ui/StartupPanel.bf | 335 +++++++++++++++++++++++++++++++++++ 4 files changed, 353 insertions(+) create mode 100644 IDE/src/ui/StartupPanel.bf diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 77cdb203..93321252 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -1744,6 +1744,8 @@ namespace IDE continue; if (tabWidget.mContent is WelcomePanel) continue; + if (tabWidget.mContent is StartupPanel) + continue; } using (data.CreateObject()) @@ -12382,6 +12384,9 @@ namespace IDE if ((mIsFirstRun) && (!mWorkspace.IsInitialized)) ShowWelcome(); + + if ((mSettings.mUISettings.mShowStartupPanel) && (!mIsFirstRun) && (!mWorkspace.IsInitialized)) + ShowStartup(); } #endif void ShowWelcome() @@ -12392,6 +12397,14 @@ namespace IDE tabButton.Activate(); } + void ShowStartup() + { + StartupPanel startupPanel = new .(); + TabbedView tabbedView = GetDefaultDocumentTabbedView(); + let tabButton = SetupTab(tabbedView, "Startup", 0, startupPanel, true); + tabButton.Activate(); + } + public void CheckLoadConfig() { if (mBeefConfig.mLibsChanged) diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index 1bd1d217..5d9937e1 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -449,6 +449,7 @@ namespace IDE public float mScale = 100; public InsertNewTabsKind mInsertNewTabs = .LeftOfExistingTabs; public List mTheme = new .() ~ DeleteContainerAndItems!(_); + public bool mShowStartupPanel = true; public void SetDefaults() { @@ -457,6 +458,7 @@ namespace IDE mScale = 100; mInsertNewTabs = .LeftOfExistingTabs; ClearAndDeleteItems(mTheme); + mShowStartupPanel = true; } public void Apply() @@ -596,6 +598,7 @@ namespace IDE sd.Add(str); } sd.Add("InsertNewTabs", mInsertNewTabs); + sd.Add("ShowStartupPanel", mShowStartupPanel); } public void Deserialize(StructuredData sd) @@ -609,6 +612,7 @@ namespace IDE mTheme.Add(str); } sd.Get("InsertNewTabs", ref mInsertNewTabs); + sd.Get("ShowStartupPanel", ref mShowStartupPanel); } } diff --git a/IDE/src/ui/SettingsDialog.bf b/IDE/src/ui/SettingsDialog.bf index e7e1da9a..52b58a4c 100644 --- a/IDE/src/ui/SettingsDialog.bf +++ b/IDE/src/ui/SettingsDialog.bf @@ -81,6 +81,7 @@ namespace IDE.ui AddPropertiesItem(category, "Scale", "mScale"); AddPropertiesItem(category, "Theme", "mTheme"); AddPropertiesItem(category, "Insert New Tabs", "mInsertNewTabs"); + AddPropertiesItem(category, "Show Startup Panel", "mShowStartupPanel"); category.Open(true, true); } diff --git a/IDE/src/ui/StartupPanel.bf b/IDE/src/ui/StartupPanel.bf new file mode 100644 index 00000000..84e8e65f --- /dev/null +++ b/IDE/src/ui/StartupPanel.bf @@ -0,0 +1,335 @@ +using System; +using System.IO; +using System.Collections; +using Beefy.gfx; +using Beefy.theme.dark; +using Beefy.widgets; + +using IDE.util; +using Beefy.events; +using Beefy.theme; +using System.Diagnostics; + +namespace IDE.ui +{ + class StartupPanel : Panel + { + class RecentWorkspacesScrollWidget : ScrollableWidget + { + public Font mTitleFont; + + public this() + { + mScrollContent = new Widget(); + mScrollContentContainer.AddWidget(mScrollContent); + } + + public void AddContentWidget(Widget widget) + { + mScrollContent.AddWidget(widget); + } + + public override void Resize(float x, float y, float width, float height) + { + const float MARGIN = 3; + float currentY = 0; + + float fillWidth = width - mVertScrollbar.Width; + + if (mScrollContent.mChildWidgets != null && fillWidth >= 0) + { + for (let widget in mScrollContent.mChildWidgets) + { + widget.Resize(0, currentY, fillWidth, GS!(30)); + currentY += widget.Height + MARGIN; + } + } + + base.Resize(x, y, width, Math.Min(currentY, height)); + mScrollContent.Resize(0, 0, fillWidth, currentY); + + UpdateScrollbars(); + } + + public override void Draw(Graphics g) + { + using (g.PushColor(0x40000000)) + g.FillRect(0, -30, mWidth, mHeight + 30); + + g.SetFont(mTitleFont); + + using (g.PushColor(0xFFFFFFFF)) + g.DrawString("Recent Workspaces", 0, -30, .Centered, mWidth); + + base.Draw(g); + } + } + + class RecentWorkspaceItem : Widget + { + public static Font s_Font; + append String mPath; + + public bool mPinned; + public RecentWorkspacesScrollWidget mRecentsParent; + + public String Path + { + get => mPath; + set => mPath.Set(value); + } + + public override void Draw(Graphics g) + { + if (mMouseOver) + { + using (g.PushColor(0x80000000)) + g.FillRect(0, 0, mWidth, mHeight); + } + + g.SetFont(s_Font); + g.DrawString(mPath, 10, 0, .Left, mWidth - 10); + } + + public override void MouseEnter() + { + base.MouseEnter(); + gApp.SetCursor(.Hand); + } + + public override void MouseLeave() + { + base.MouseLeave(); + gApp.SetCursor(.Pointer); + } + + public override void Update() + { + base.Update(); + + if (DarkTooltipManager.CheckMouseover(this, 20, let mousePoint)) + { + DarkTooltipManager.ShowTooltip(mPath, this, mousePoint.x, mousePoint.y); + } + } + + public override void MouseClicked(float x, float y, float origX, float origY, int32 btn) + { + base.MouseClicked(x, y, origX, origY, btn); + + if (btn == 0) + { + TryOpenWorkspace(); + } + else if (btn == 1) + { + Menu menu = new .(); + menu.AddItem("Open").mOnMenuItemSelected.Add(new (menu) => { TryOpenWorkspace(); }); + menu.AddItem(); + menu.AddItem("Open Containing Folder").mOnMenuItemSelected.Add(new (menu) => { OpenContainingFolder(); }); + menu.AddItem("Copy Path").mOnMenuItemSelected.Add(new (menu) => { + gApp.SetClipboardData("text", mPath.CStr(), (int32)mPath.Length + 1, true); + }); + menu.AddItem(); + menu.AddItem("Remove").mOnMenuItemSelected.Add(new (menu) => { RemoveFromRecent(); }); + MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu); + menuWidget.Init(this, x, y); + } + } + + void ShowNotFoundDialog() + { + IDEApp.Beep(.Error); + + let aDialog = ThemeFactory.mDefault.CreateDialog( + "Beef IDE", + "Workspace couldn't be found. Do you want to remove the reference from recent list?", + DarkTheme.sDarkTheme.mImages[(int)DarkTheme.ImageIdx.IconError]); + + aDialog.AddYesNoButtons(new (theEvent) => { + RemoveFromRecent(); + }, null, 0, 1); + aDialog.PopupWindow(gApp.GetActiveWindow()); + } + + void OpenContainingFolder() + { + if (!Directory.Exists(mPath)) + { + ShowNotFoundDialog(); + return; + } + + ProcessStartInfo psi = scope ProcessStartInfo(); + psi.SetFileName(mPath); + psi.UseShellExecute = true; + psi.SetVerb("Open"); + + var process = scope SpawnedProcess(); + process.Start(psi).IgnoreError(); + } + + void TryOpenWorkspace() + { + const String WORKSPACE_FILENAME = "BeefSpace.toml"; + String path = scope .(mPath.Length + WORKSPACE_FILENAME.Length + 2); + System.IO.Path.InternalCombine(path, mPath, WORKSPACE_FILENAME); + if (!File.Exists(path)) + { + ShowNotFoundDialog(); + return; + } + + gApp.[Friend]mDeferredOpen = .Workspace; + String.NewOrSet!(gApp.[Friend]mDeferredOpenFileName, path); + } + + void RemoveFromRecent() + { + let recentWorkspaces = gApp.mSettings.mRecentFiles.mRecents[(int)RecentFiles.RecentKind.OpenedWorkspace]; + + var index = recentWorkspaces.mList.IndexOf(mPath); + if (index == -1) + return; + + delete recentWorkspaces.mList[index]; + recentWorkspaces.mList.RemoveAt(index); + recentWorkspaces.mMenuItems[index].Dispose(); + recentWorkspaces.mMenuItems.RemoveAt(index); + + RemoveSelf(); + mRecentsParent.RehupSize(); + delete this; + } + } + + DarkButton mCreateBtn; + DarkButton mOpenWorkspaceBtn; + DarkButton mOpenProjectBtn; + DarkButton mWelcomeBtn; + DarkButton mOpenDocBtn; + + RecentWorkspacesScrollWidget mRecentsScrollWidget; + public Font mMedFont ~ delete _; + public Font mSmallFont ~ delete _; + + public this() + { + mCreateBtn = new .() + { + Label = "New Project or Workspace" + }; + mCreateBtn.mOnMouseClick.Add(new (event) => { + gApp.[Friend]mDeferredOpen = .NewWorkspaceOrProject; + }); + AddWidget(mCreateBtn); + + mOpenWorkspaceBtn = new .() + { + Label = "Open Workspace" + }; + mOpenWorkspaceBtn.mOnMouseClick.Add(new (event) => { + gApp.DoOpenWorkspace(false); + }); + AddWidget(mOpenWorkspaceBtn); + + mOpenProjectBtn = new .() + { + Label = "Open Project" + }; + mOpenProjectBtn.mOnMouseClick.Add(new (event) => { + gApp.Cmd_OpenProject(); + }); + AddWidget(mOpenProjectBtn); + + mWelcomeBtn = new .() + { + Label = "Show Welcome Panel" + }; + mWelcomeBtn.mOnMouseClick.Add(new (event) => { gApp.[Friend]ShowWelcome(); }); + AddWidget(mWelcomeBtn); + + mOpenDocBtn = new .() + { + Label = "Open Documentation", + }; + mOpenDocBtn.mOnMouseClick.Add(new (event) => { OpenDocumentation(); }); + AddWidget(mOpenDocBtn); + + mRecentsScrollWidget = new .(); + mRecentsScrollWidget.InitScrollbars(false, true); + let recentList = gApp.mSettings.mRecentFiles.mRecents[(int)RecentFiles.RecentKind.OpenedWorkspace].mList; + for (let recent in recentList) + { + var workspaceItem = new RecentWorkspaceItem() + { + Path = recent, + mRecentsParent = mRecentsScrollWidget + }; + mRecentsScrollWidget.AddContentWidget(workspaceItem); + } + + AddWidget(mRecentsScrollWidget); + } + + public override bool WantsSerialization => false; + + public override void RehupScale(float oldScale, float newScale) + { + base.RehupScale(oldScale, newScale); + + DeleteAndNullify!(mMedFont); + DeleteAndNullify!(mSmallFont); + } + + public override void DrawAll(Graphics g) + { + if (mMedFont == null) + mMedFont = new Font()..Load("Segoe UI Bold", 20.0f * DarkTheme.sScale); + + if (mSmallFont == null) + mSmallFont = new Font()..Load("Segoe UI Bold", 16.0f * DarkTheme.sScale); + + + this.mRecentsScrollWidget.mTitleFont = mMedFont; + RecentWorkspaceItem.s_Font = mSmallFont; + + base.DrawAll(g); + } + + + public override void Resize(float x, float y, float width, float height) + { + base.Resize(x, y, width, height); + + let autoPos = DarkButton[](mCreateBtn, mOpenWorkspaceBtn, mOpenProjectBtn, mWelcomeBtn, mOpenDocBtn); + + int32 startX = 20; + int32 currentY = 20; + int32 buttonWidth = GS!(250); + int32 buttonheight = GS!(35); + + for (let button in autoPos) + { + button.Resize(startX, currentY, buttonWidth, buttonheight); + currentY += buttonheight + 10; + } + + float offsetX = buttonWidth + GS!(35); + float offsetY = 50; + + mRecentsScrollWidget.Resize(offsetX, offsetY, Math.Clamp(mWidth - offsetX, 0, 700), Math.Clamp(mHeight - offsetY, 0, 700)); + } + + void OpenDocumentation() + { + ProcessStartInfo psi = scope ProcessStartInfo(); + psi.SetFileName("https://www.beeflang.org/docs/"); + psi.UseShellExecute = true; + psi.SetVerb("Open"); + + var process = scope SpawnedProcess(); + process.Start(psi).IgnoreError(); + } + } +} \ No newline at end of file