mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-04-21 19:24:00 +00:00
增加更多UILib控件
This commit is contained in:
@@ -1 +1 @@
|
|||||||
2026-03-25 20:24:01
|
2026-03-25 21:37:54
|
||||||
@@ -1 +1 @@
|
|||||||
a8ac938
|
d009660
|
||||||
@@ -145,6 +145,47 @@ namespace CMLeonOS.Gui.Apps
|
|||||||
AddDemo(info);
|
AddDemo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ShowTabsDemo()
|
||||||
|
{
|
||||||
|
ClearPreview();
|
||||||
|
SetHeader("Tabs", "Tab strip control for switching between sections.");
|
||||||
|
|
||||||
|
Tabs tabs = new Tabs(previewHost, 20, 24, 360, 28);
|
||||||
|
tabs.Items.Add("General");
|
||||||
|
tabs.Items.Add("Appearance");
|
||||||
|
tabs.Items.Add("Advanced");
|
||||||
|
tabs.RefreshItems();
|
||||||
|
tabs.SelectionChanged = (index, text) => SetHeader("Tabs", "Selected tab: " + text);
|
||||||
|
AddDemo(tabs);
|
||||||
|
|
||||||
|
TextBlock block = new TextBlock(previewHost, 20, 70, 360, 48);
|
||||||
|
block.Text = "Tabs are ideal for settings and editors.";
|
||||||
|
block.Background = UITheme.AccentLight;
|
||||||
|
block.Foreground = UITheme.TextPrimary;
|
||||||
|
block.HorizontalAlignment = Alignment.Middle;
|
||||||
|
block.VerticalAlignment = Alignment.Middle;
|
||||||
|
AddDemo(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowNumericDemo()
|
||||||
|
{
|
||||||
|
ClearPreview();
|
||||||
|
SetHeader("NumericUpDown", "Increment and decrement integer values without typing.");
|
||||||
|
|
||||||
|
NumericUpDown numeric = new NumericUpDown(previewHost, 20, 24, 120, 32);
|
||||||
|
numeric.Minimum = 0;
|
||||||
|
numeric.Maximum = 256;
|
||||||
|
numeric.Step = 8;
|
||||||
|
numeric.Value = 64;
|
||||||
|
numeric.Changed = (value) => SetHeader("NumericUpDown", "Value changed to " + value.ToString());
|
||||||
|
AddDemo(numeric);
|
||||||
|
|
||||||
|
TextBlock hint = new TextBlock(previewHost, 160, 28, 320, 24);
|
||||||
|
hint.Text = "Click + / - to change the value.";
|
||||||
|
hint.Foreground = UITheme.TextSecondary;
|
||||||
|
AddDemo(hint);
|
||||||
|
}
|
||||||
|
|
||||||
private void ShowTableDemo()
|
private void ShowTableDemo()
|
||||||
{
|
{
|
||||||
ClearPreview();
|
ClearPreview();
|
||||||
@@ -193,6 +234,11 @@ namespace CMLeonOS.Gui.Apps
|
|||||||
image.Image = AppManager.DefaultAppIcon.Resize(48, 48);
|
image.Image = AppManager.DefaultAppIcon.Resize(48, 48);
|
||||||
image.Alpha = true;
|
image.Alpha = true;
|
||||||
AddDemo(image);
|
AddDemo(image);
|
||||||
|
|
||||||
|
StatusBar statusBar = new StatusBar(previewHost, 20, 132, 360, 24);
|
||||||
|
statusBar.Text = "Ready";
|
||||||
|
statusBar.DetailText = "UILib Demo";
|
||||||
|
AddDemo(statusBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowDialogsDemo()
|
private void ShowDialogsDemo()
|
||||||
@@ -231,6 +277,15 @@ namespace CMLeonOS.Gui.Apps
|
|||||||
fileBrowser.Show();
|
fileBrowser.Show();
|
||||||
};
|
};
|
||||||
AddDemo(fileBrowserButton);
|
AddDemo(fileBrowserButton);
|
||||||
|
|
||||||
|
Button notificationButton = new Button(previewHost, 20, 68, 140, 28);
|
||||||
|
notificationButton.Text = "Notification";
|
||||||
|
notificationButton.OnClick = (_, _) =>
|
||||||
|
{
|
||||||
|
Notification notification = new Notification(this, "UILib Gallery", "This is a toast notification.");
|
||||||
|
notification.Show();
|
||||||
|
};
|
||||||
|
AddDemo(notificationButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CategorySelected(int index)
|
private void CategorySelected(int index)
|
||||||
@@ -247,12 +302,18 @@ namespace CMLeonOS.Gui.Apps
|
|||||||
ShowDropdownDemo();
|
ShowDropdownDemo();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
ShowTableDemo();
|
ShowTabsDemo();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
ShowBarsDemo();
|
ShowNumericDemo();
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
ShowTableDemo();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
ShowBarsDemo();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
ShowDialogsDemo();
|
ShowDialogsDemo();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -300,6 +361,8 @@ namespace CMLeonOS.Gui.Apps
|
|||||||
categoryTable.Cells.Add(new TableCell("Buttons"));
|
categoryTable.Cells.Add(new TableCell("Buttons"));
|
||||||
categoryTable.Cells.Add(new TableCell("Inputs"));
|
categoryTable.Cells.Add(new TableCell("Inputs"));
|
||||||
categoryTable.Cells.Add(new TableCell("Dropdown"));
|
categoryTable.Cells.Add(new TableCell("Dropdown"));
|
||||||
|
categoryTable.Cells.Add(new TableCell("Tabs"));
|
||||||
|
categoryTable.Cells.Add(new TableCell("Numeric"));
|
||||||
categoryTable.Cells.Add(new TableCell("Table"));
|
categoryTable.Cells.Add(new TableCell("Table"));
|
||||||
categoryTable.Cells.Add(new TableCell("Bars && Blocks"));
|
categoryTable.Cells.Add(new TableCell("Bars && Blocks"));
|
||||||
categoryTable.Cells.Add(new TableCell("Dialogs"));
|
categoryTable.Cells.Add(new TableCell("Dialogs"));
|
||||||
|
|||||||
131
Gui/UILib/Notification.cs
Normal file
131
Gui/UILib/Notification.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using CMLeonOS;
|
||||||
|
using CMLeonOS.UILib.Animations;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace CMLeonOS.Gui.UILib
|
||||||
|
{
|
||||||
|
internal class Notification
|
||||||
|
{
|
||||||
|
internal Notification(Process process, string title, string message)
|
||||||
|
{
|
||||||
|
owner = process;
|
||||||
|
Title = title;
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Process owner;
|
||||||
|
internal string Title { get; }
|
||||||
|
internal string Message { get; }
|
||||||
|
internal void Show()
|
||||||
|
{
|
||||||
|
ProcessManager.AddProcess(owner, new NotificationProcess(owner, Title, Message)).Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NotificationProcess : Process
|
||||||
|
{
|
||||||
|
internal NotificationProcess(Process parent, string title, string message) : base("Notification", ProcessType.Background, parent)
|
||||||
|
{
|
||||||
|
this.title = title;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly string title;
|
||||||
|
private readonly string message;
|
||||||
|
|
||||||
|
private Window window;
|
||||||
|
private Button closeButton;
|
||||||
|
private readonly WindowManager wm = ProcessManager.GetProcess<WindowManager>();
|
||||||
|
private bool closeAnimationRunning = false;
|
||||||
|
private int targetX;
|
||||||
|
private int targetY;
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
|
||||||
|
int width = 280;
|
||||||
|
int height = 84;
|
||||||
|
targetX = (int)wm.ScreenWidth - width - 16;
|
||||||
|
targetY = (int)wm.ScreenHeight - height - 44;
|
||||||
|
int startX = (int)wm.ScreenWidth + 12;
|
||||||
|
|
||||||
|
window = new Window(this, startX, targetY, width, height);
|
||||||
|
window.Clear(UITheme.WindowTitleBackground);
|
||||||
|
window.DrawFilledRectangle(0, 0, window.Width, window.Height, UITheme.WindowTitleBackground);
|
||||||
|
window.DrawRectangle(0, 0, window.Width, window.Height, UITheme.SurfaceBorder);
|
||||||
|
window.DrawFilledRectangle(0, 0, window.Width, 22, UITheme.Accent);
|
||||||
|
window.DrawString(title, UITheme.WindowTitleText, 10, 4);
|
||||||
|
window.DrawString(message, Color.White, 10, 30);
|
||||||
|
wm.AddWindow(window);
|
||||||
|
|
||||||
|
closeButton = new Button(window, window.Width - 54, window.Height - 28, 44, 20);
|
||||||
|
closeButton.Text = "Close";
|
||||||
|
closeButton.OnClick = (_, _) => BeginCloseAnimation();
|
||||||
|
wm.AddWindow(closeButton);
|
||||||
|
|
||||||
|
wm.Update(window);
|
||||||
|
StartOpenAnimation(startX, targetY, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartOpenAnimation(int startX, int startY, int width, int height)
|
||||||
|
{
|
||||||
|
MovementAnimation animation = new MovementAnimation(window)
|
||||||
|
{
|
||||||
|
From = new Rectangle(startX, startY, width, height),
|
||||||
|
To = new Rectangle(targetX, targetY, width, height),
|
||||||
|
Duration = 10,
|
||||||
|
EasingType = EasingType.Sine,
|
||||||
|
EasingDirection = EasingDirection.Out
|
||||||
|
};
|
||||||
|
animation.Completed = () =>
|
||||||
|
{
|
||||||
|
wm.Update(window);
|
||||||
|
closeButton.Render();
|
||||||
|
};
|
||||||
|
animation.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginCloseAnimation()
|
||||||
|
{
|
||||||
|
if (closeAnimationRunning || window == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAnimationRunning = true;
|
||||||
|
|
||||||
|
int endX = (int)wm.ScreenWidth + 12;
|
||||||
|
int width = window.Width;
|
||||||
|
int height = window.Height;
|
||||||
|
|
||||||
|
MovementAnimation animation = new MovementAnimation(window)
|
||||||
|
{
|
||||||
|
From = new Rectangle(window.X, window.Y, width, height),
|
||||||
|
To = new Rectangle(endX, targetY, width, height),
|
||||||
|
Duration = 9,
|
||||||
|
EasingType = EasingType.Sine,
|
||||||
|
EasingDirection = EasingDirection.In
|
||||||
|
};
|
||||||
|
animation.Completed = TryStop;
|
||||||
|
animation.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
base.Stop();
|
||||||
|
if (closeButton != null)
|
||||||
|
{
|
||||||
|
wm.RemoveWindow(closeButton);
|
||||||
|
}
|
||||||
|
if (window != null)
|
||||||
|
{
|
||||||
|
wm.RemoveWindow(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
110
Gui/UILib/NumericUpDown.cs
Normal file
110
Gui/UILib/NumericUpDown.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace CMLeonOS.Gui.UILib
|
||||||
|
{
|
||||||
|
internal class NumericUpDown : Control
|
||||||
|
{
|
||||||
|
public NumericUpDown(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
|
||||||
|
{
|
||||||
|
OnClick = NumericUpDownClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Action<int> Changed;
|
||||||
|
|
||||||
|
private Color _background = UITheme.Surface;
|
||||||
|
internal Color Background
|
||||||
|
{
|
||||||
|
get { return _background; }
|
||||||
|
set { _background = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _foreground = UITheme.TextPrimary;
|
||||||
|
internal Color Foreground
|
||||||
|
{
|
||||||
|
get { return _foreground; }
|
||||||
|
set { _foreground = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _border = UITheme.SurfaceBorder;
|
||||||
|
internal Color Border
|
||||||
|
{
|
||||||
|
get { return _border; }
|
||||||
|
set { _border = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _minimum = 0;
|
||||||
|
internal int Minimum
|
||||||
|
{
|
||||||
|
get { return _minimum; }
|
||||||
|
set { _minimum = value; if (_value < _minimum) { _value = _minimum; } Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _maximum = 100;
|
||||||
|
internal int Maximum
|
||||||
|
{
|
||||||
|
get { return _maximum; }
|
||||||
|
set { _maximum = value; if (_value > _maximum) { _value = _maximum; } Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _step = 1;
|
||||||
|
internal int Step
|
||||||
|
{
|
||||||
|
get { return _step; }
|
||||||
|
set { _step = Math.Max(1, value); Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _value = 0;
|
||||||
|
internal int Value
|
||||||
|
{
|
||||||
|
get { return _value; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int newValue = Math.Clamp(value, _minimum, _maximum);
|
||||||
|
if (_value != newValue)
|
||||||
|
{
|
||||||
|
_value = newValue;
|
||||||
|
Render();
|
||||||
|
Changed?.Invoke(_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NumericUpDownClicked(int x, int y)
|
||||||
|
{
|
||||||
|
int buttonWidth = 22;
|
||||||
|
if (x >= Width - buttonWidth)
|
||||||
|
{
|
||||||
|
if (y < Height / 2)
|
||||||
|
{
|
||||||
|
Value += _step;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Value -= _step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Render()
|
||||||
|
{
|
||||||
|
int buttonWidth = 22;
|
||||||
|
|
||||||
|
Clear(Background);
|
||||||
|
DrawFilledRectangle(0, 0, Width, Height, Background);
|
||||||
|
DrawRectangle(0, 0, Width, Height, Border);
|
||||||
|
|
||||||
|
DrawFilledRectangle(Width - buttonWidth, 0, buttonWidth, Height, UITheme.SurfaceMuted);
|
||||||
|
DrawRectangle(Width - buttonWidth, 0, buttonWidth, Height, Border);
|
||||||
|
DrawHorizontalLine(buttonWidth, Width - buttonWidth, Height / 2, Border);
|
||||||
|
|
||||||
|
string text = _value.ToString();
|
||||||
|
DrawString(text, Foreground, 6, (Height / 2) - 8);
|
||||||
|
|
||||||
|
DrawString("+", Foreground, Width - buttonWidth + 7, 2);
|
||||||
|
DrawString("-", Foreground, Width - buttonWidth + 7, (Height / 2) - 2);
|
||||||
|
|
||||||
|
WM.Update(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Gui/UILib/StatusBar.cs
Normal file
62
Gui/UILib/StatusBar.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace CMLeonOS.Gui.UILib
|
||||||
|
{
|
||||||
|
internal class StatusBar : Control
|
||||||
|
{
|
||||||
|
public StatusBar(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _text = "Ready";
|
||||||
|
internal string Text
|
||||||
|
{
|
||||||
|
get { return _text; }
|
||||||
|
set { _text = value ?? string.Empty; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _detailText = string.Empty;
|
||||||
|
internal string DetailText
|
||||||
|
{
|
||||||
|
get { return _detailText; }
|
||||||
|
set { _detailText = value ?? string.Empty; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _background = UITheme.SurfaceMuted;
|
||||||
|
internal Color Background
|
||||||
|
{
|
||||||
|
get { return _background; }
|
||||||
|
set { _background = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _foreground = UITheme.TextPrimary;
|
||||||
|
internal Color Foreground
|
||||||
|
{
|
||||||
|
get { return _foreground; }
|
||||||
|
set { _foreground = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _border = UITheme.SurfaceBorder;
|
||||||
|
internal Color Border
|
||||||
|
{
|
||||||
|
get { return _border; }
|
||||||
|
set { _border = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Render()
|
||||||
|
{
|
||||||
|
Clear(Background);
|
||||||
|
DrawFilledRectangle(0, 0, Width, Height, Background);
|
||||||
|
DrawHorizontalLine(Width, 0, 0, Border);
|
||||||
|
|
||||||
|
DrawString(Text, Foreground, 6, (Height / 2) - 8);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(DetailText))
|
||||||
|
{
|
||||||
|
DrawString(DetailText, Foreground, Width - (DetailText.Length * 8) - 6, (Height / 2) - 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
WM.Update(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
127
Gui/UILib/Tabs.cs
Normal file
127
Gui/UILib/Tabs.cs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace CMLeonOS.Gui.UILib
|
||||||
|
{
|
||||||
|
internal class Tabs : Control
|
||||||
|
{
|
||||||
|
public Tabs(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
|
||||||
|
{
|
||||||
|
OnClick = TabsClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Action<int, string> SelectionChanged;
|
||||||
|
|
||||||
|
internal List<string> Items { get; } = new List<string>();
|
||||||
|
|
||||||
|
private Color _background = UITheme.Surface;
|
||||||
|
internal Color Background
|
||||||
|
{
|
||||||
|
get { return _background; }
|
||||||
|
set { _background = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _foreground = UITheme.TextPrimary;
|
||||||
|
internal Color Foreground
|
||||||
|
{
|
||||||
|
get { return _foreground; }
|
||||||
|
set { _foreground = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _border = UITheme.SurfaceBorder;
|
||||||
|
internal Color Border
|
||||||
|
{
|
||||||
|
get { return _border; }
|
||||||
|
set { _border = value; Render(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _selectedIndex = 0;
|
||||||
|
internal int SelectedIndex
|
||||||
|
{
|
||||||
|
get { return _selectedIndex; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int newIndex = Math.Clamp(value, 0, Math.Max(0, Items.Count - 1));
|
||||||
|
if (_selectedIndex != newIndex)
|
||||||
|
{
|
||||||
|
_selectedIndex = newIndex;
|
||||||
|
Render();
|
||||||
|
if (Items.Count > 0)
|
||||||
|
{
|
||||||
|
SelectionChanged?.Invoke(_selectedIndex, Items[_selectedIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string SelectedText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Items.Count == 0 || _selectedIndex < 0 || _selectedIndex >= Items.Count)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Items[_selectedIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RefreshItems()
|
||||||
|
{
|
||||||
|
if (_selectedIndex >= Items.Count)
|
||||||
|
{
|
||||||
|
_selectedIndex = Math.Max(0, Items.Count - 1);
|
||||||
|
}
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TabsClicked(int x, int y)
|
||||||
|
{
|
||||||
|
if (Items.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tabWidth = Math.Max(1, Width / Items.Count);
|
||||||
|
int index = Math.Min(Items.Count - 1, Math.Max(0, x / tabWidth));
|
||||||
|
SelectedIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Render()
|
||||||
|
{
|
||||||
|
Clear(Background);
|
||||||
|
DrawFilledRectangle(0, 0, Width, Height, Background);
|
||||||
|
DrawRectangle(0, 0, Width, Height, Border);
|
||||||
|
|
||||||
|
if (Items.Count == 0)
|
||||||
|
{
|
||||||
|
WM.Update(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tabWidth = Math.Max(1, Width / Items.Count);
|
||||||
|
for (int i = 0; i < Items.Count; i++)
|
||||||
|
{
|
||||||
|
int tabX = i * tabWidth;
|
||||||
|
int actualWidth = i == Items.Count - 1 ? Width - tabX : tabWidth;
|
||||||
|
bool selected = i == _selectedIndex;
|
||||||
|
|
||||||
|
DrawFilledRectangle(tabX, 0, actualWidth, Height, selected ? UITheme.AccentLight : UITheme.SurfaceMuted);
|
||||||
|
DrawRectangle(tabX, 0, actualWidth, Height, selected ? UITheme.Accent : Border);
|
||||||
|
|
||||||
|
string text = Items[i];
|
||||||
|
int maxChars = Math.Max(1, (actualWidth - 8) / 8);
|
||||||
|
if (text.Length > maxChars)
|
||||||
|
{
|
||||||
|
text = text.Substring(0, Math.Max(1, maxChars - 1)) + "~";
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawString(text, Foreground, tabX + (actualWidth / 2) - (text.Length * 4), (Height / 2) - 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
WM.Update(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user