aboutsummaryrefslogtreecommitdiff
path: root/ShiftOS.Frontend/GUI
diff options
context:
space:
mode:
Diffstat (limited to 'ShiftOS.Frontend/GUI')
-rw-r--r--ShiftOS.Frontend/GUI/ListBox.cs162
1 files changed, 162 insertions, 0 deletions
diff --git a/ShiftOS.Frontend/GUI/ListBox.cs b/ShiftOS.Frontend/GUI/ListBox.cs
new file mode 100644
index 0000000..f9354e0
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ListBox.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework;
+using ShiftOS.Frontend.GraphicsSubsystem;
+using static ShiftOS.Engine.SkinEngine;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class ListBox : GUI.Control
+ {
+ private int fontheight = 0;
+ private List<object> items = new List<object>();
+ private int selectedIndex = -1;
+ private int itemOffset = 0;
+ private int itemsPerPage = 1;
+
+ public int SelectedIndex
+ {
+ get
+ {
+ return MathHelper.Clamp(selectedIndex, 0, items.Count - 1);
+ }
+ set
+ {
+ selectedIndex = MathHelper.Clamp(value, 0, items.Count - 1);
+ RecalculateItemsPerPage();
+ SelectedIndexChanged?.Invoke();
+ }
+ }
+
+ public object SelectedItem
+ {
+ get
+ {
+ try
+ {
+ return items[SelectedIndex];
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ }
+
+ public void ClearItems()
+ {
+ selectedIndex = -1;
+ items.Clear();
+ SelectedIndexChanged?.Invoke();
+ Invalidate();
+ }
+
+ public void AddItem(object item)
+ {
+ items.Add(item);
+ RecalculateItemsPerPage();
+ Invalidate();
+ }
+
+ public void RemoveItem(object item)
+ {
+ items.Remove(item);
+ selectedIndex = -1;
+ RecalculateItemsPerPage();
+ SelectedIndexChanged?.Invoke();
+ Invalidate();
+ }
+
+ public void RecalculateItemsPerPage()
+ {
+ itemsPerPage = 0;
+ while(itemsPerPage * fontheight < Height && itemsPerPage < items.Count - 1)
+ {
+ itemsPerPage++;
+ }
+ //We have the amount of items we can fit on screen.
+ //Now let's calculate the offset based on this, as well
+ //as the currently selected item.
+ //of course, if there IS one.
+ if(selectedIndex > -1)
+ {
+ if(selectedIndex >= items.Count)
+ {
+ selectedIndex = items.Count - 1;
+ }
+ while(this.itemOffset > selectedIndex)
+ {
+ itemOffset--;
+ }
+ while(this.itemOffset + itemsPerPage < selectedIndex)
+ {
+ itemOffset++;
+ }
+ }
+ }
+
+ protected override void OnKeyEvent(KeyEvent e)
+ {
+ if(e.Key== Microsoft.Xna.Framework.Input.Keys.Down)
+ {
+ if(selectedIndex < items.Count - 2)
+ {
+ selectedIndex++;
+ RecalculateItemsPerPage();
+ SelectedIndexChanged?.Invoke();
+ Invalidate();
+ }
+ }
+ else if(e.Key == Microsoft.Xna.Framework.Input.Keys.Up)
+ {
+ if(selectedIndex > 0)
+ {
+ selectedIndex--;
+ RecalculateItemsPerPage();
+ SelectedIndexChanged?.Invoke();
+ Invalidate();
+ }
+ }
+ }
+
+ protected override void OnPaint(GraphicsContext gfx)
+ {
+ gfx.Clear(LoadedSkin.ControlTextColor.ToMonoColor());
+ gfx.DrawRectangle(1, 1, Width - 2, Height - 2, UIManager.SkinTextures["ControlColor"]);
+ for(int i = itemOffset; i < items.Count - 1 && i < itemsPerPage; i++)
+ {
+ int x = 1;
+ int y = fontheight * (i - itemOffset);
+ int width = Width - 2;
+ int height = fontheight;
+ if(i == selectedIndex)
+ {
+ //draw the string as selected
+ gfx.DrawRectangle(x, y, width, height, UIManager.SkinTextures["ControlTextColor"]);
+ gfx.DrawString(items[i].ToString(), x, y, LoadedSkin.ControlColor.ToMonoColor(), LoadedSkin.MainFont);
+ }
+ else
+ {
+ gfx.DrawRectangle(x, y, width, height, UIManager.SkinTextures["ControlColor"]);
+ gfx.DrawString(items[i].ToString(), x, y, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.MainFont);
+
+ }
+ }
+ }
+
+ protected override void OnLayout()
+ {
+ if(fontheight != LoadedSkin.MainFont.Height)
+ {
+ fontheight = LoadedSkin.MainFont.Height;
+ Invalidate();
+ }
+ base.OnLayout();
+ }
+
+ public event Action SelectedIndexChanged;
+ }
+}