Files
ViperOS/VKernel/Kernel/drivers/video/ui/ui.py
2026-07-19 12:38:20 +08:00

153 lines
4.8 KiB
Python

from stdint import *
import drivers.video.vesafb.gfx as gfx
import drivers.video.ui.sheet as sheet
import string
import t, c
UI_LABEL: t.CDefine = 0
UI_BUTTON: t.CDefine = 1
UI_PANEL: t.CDefine = 2
UI_PROGRESS: t.CDefine = 3
@t.Object
class UIComponent:
id: t.CInt
ctype: t.CInt
x: t.CInt
y: t.CInt
w: t.CInt
h: t.CInt
visible: t.CInt
sheet: sheet.Sheet | t.CPtr
fg_color: t.CUInt32T
bg_color: t.CUInt32T
text: t.CArray[t.CChar, 128]
text_len: t.CInt
value: t.CInt
def __init__(self, ctype: t.CInt, sh: sheet.Sheet | t.CPtr, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt):
global _next_component_id
self.id = _next_component_id
_next_component_id += 1
self.ctype = ctype
self.x = x
self.y = y
self.w = w
self.h = h
self.visible = 1
self.sheet = sh
self.fg_color = gfx.COLOR_RGB(255, 255, 255)
self.bg_color = gfx.COLOR_RGB(40, 40, 60)
string.memset(c.Addr(self.text), 0, 128)
self.text_len = 0
self.value = 0
def SetText(self, s: str):
i: t.CInt = 0
for ch in s:
if i >= 127: break
self.text[i] = ch
i += 1
self.text[i] = 0
self.text_len = i
def SetValue(self, v: t.CInt):
self.value = v
def Render(self):
if self.visible == 0: return
sh: sheet.Sheet = c.Deref(self.sheet)
match self.ctype:
case 0:
self._RenderLabel(sh)
case 1:
self._RenderButton(sh)
case 2:
self._RenderPanel(sh)
case 3:
self._RenderProgress(sh)
def _RenderLabel(self, sh: sheet.Sheet):
sh.DrawFilledRect(self.x, self.y, self.w, self.h, 0)
def _RenderButton(self, sh: sheet.Sheet):
sh.DrawFilledRect(self.x, self.y, self.w, self.h, self.bg_color)
sh.DrawRect(self.x, self.y, self.w, self.h, self.fg_color)
def _RenderPanel(self, sh: sheet.Sheet):
sh.DrawFilledRect(self.x, self.y, self.w, self.h, self.bg_color)
sh.DrawRect(self.x, self.y, self.w, self.h, gfx.COLOR_RGB(80, 80, 120))
def _RenderProgress(self, sh: sheet.Sheet):
sh.DrawFilledRect(self.x, self.y, self.w, self.h, gfx.COLOR_RGB(30, 30, 40))
fill_w: t.CInt = self.w * self.value / 100
if fill_w > 0:
sh.DrawFilledRect(self.x, self.y, fill_w, self.h, gfx.COLOR_RGB(0, 180, 255))
sh.DrawRect(self.x, self.y, self.w, self.h, gfx.COLOR_RGB(80, 80, 100))
def Contains(self, px: t.CInt, py: t.CInt) -> t.CInt:
if px >= self.x and px < self.x + self.w and py >= self.y and py < self.y + self.h:
return 1
return 0
@t.Object
class UIManager:
sheets: t.CArray[sheet.Sheet | t.CPtr, 64]
sheet_count: t.CInt
components: t.CArray[UIComponent | t.CPtr, 256]
component_count: t.CInt
screen_w: t.CInt
screen_h: t.CInt
def __init__(self, w: t.CInt, h: t.CInt):
self.sheet_count = 0
self.component_count = 0
self.screen_w = w
self.screen_h = h
i: t.CInt
for i in range(64):
self.sheets[i] = None
for i in range(256):
self.components[i] = None
def AddSheet(self, sh: sheet.Sheet | t.CPtr) -> t.CInt:
if self.sheet_count >= 64: return -1
self.sheets[self.sheet_count] = sh
self.sheet_count += 1
return 0
def AddComponent(self, comp: UIComponent | t.CPtr) -> t.CInt:
if self.component_count >= 256: return -1
self.components[self.component_count] = comp
self.component_count += 1
return 0
def FindComponent(self, cid: t.CInt) -> UIComponent | t.CPtr:
i: t.CInt
for i in range(self.component_count):
p: UIComponent | t.CPtr = self.components[i]
if p is not None:
comp: UIComponent = c.Deref(p)
if comp.id == cid: return p
return None
def RenderAll(self):
i: t.CInt
for i in range(self.component_count):
p: UIComponent | t.CPtr = self.components[i]
if p is not None:
comp: UIComponent = c.Deref(p)
comp.Render()
def HitTest(self, px: t.CInt, py: t.CInt) -> UIComponent | t.CPtr:
i: t.CInt = self.component_count - 1
while i >= 0:
p: UIComponent | t.CPtr = self.components[i]
if p is not None:
comp: UIComponent = c.Deref(p)
if comp.visible == 1 and comp.Contains(px, py) == 1:
return p
i -= 1
return None