toaruos/apps/krk_yutani_test.krk
2023-02-22 10:44:37 +09:00

176 lines
5.6 KiB
Plaintext

#!/bin/kuroko
from _yutani2 import (YutaniCtx, Font, rgb, rgb, MenuBar, decor_get_bounds, decor_render,
MenuList, MenuEntry, MenuEntrySeparator, Message, decor_handle_event, decor_show_default_menu,
MenuEntryCustom)
from yutani_mainloop import Window, yctx as y, AsyncMainloop, Task, sleep
import math
import random
let mainloop = AsyncMainloop()
def close_enough(me):
return me.command == 2 and math.sqrt((me.new_x - me.old_x) ** 2 + (me.new_y - me.old_y) **2) < 10
class Button:
''' Basic button widget based on draw_button '''
def __init__(self, window, x, y, width, height, title, callback):
self.ctx = window
self.x = x
self.y = y
self.width = width
self.height = height
self.title = title
self.state = 0
self.callback = asyncCallback
def __contains__(self, coord):
if not isinstance(cord, tuple):
return False
def focus_enter(self):
self.state = 1
return True
def focus_leave(self):
self.state = 0
return True
def mouse_down(self, msg):
self.state = 2
return True
def mouse_up(self, msg):
# TODO check if old_x, old_y is in button
self.callback(self)
self.state = 0
return True
def draw(self):
draw_button(self.ctx, self.x, self.y, self.width, self.height, self.title, self.state)
class MyMenuWidget(MenuEntryCustom):
def __init__(self):
super().__init__()
self.height = 30
self.rwidth = 148
self.dejavu = Font("sans-serif", 13)
self.x = 0
self.y = 0
def render(self, ctx, offset):
self.offset = offset
if self.hilight:
ctx.rect(1,offset,self.width-2,self.height,rgb(100,int(255 * self.x / self.width),int(255 * (self.y-offset) / self.height)),radius=4)
self.dejavu.draw_string(ctx, f"{self.x=},{self.y=}", 2, offset + 13)
else:
self.dejavu.draw_string(ctx, f"{offset=}", 2, offset + 13)
def activate(self, flags):
print("Activated by keyboard!")
def click_within(self, evt):
if evt.command == 0: return True
if evt.command == 2:
if \
evt.new_x >= 0 and evt.new_x < self.width and \
evt.new_y >= self.offset and evt.new_y < self.offset + self.height and \
evt.old_x >= 0 and evt.old_x < self.width and \
evt.old_y >= self.offset and evt.old_y < self.offset + self.height:
return True
else:
print(f'{evt.old_x=} {evt.old_y=} {evt.new_x=} {evt.old_y=} {self.offset=} {self.width=} {self.height=}')
async def async_thingy(self):
print("Schedule async callback")
await sleep(2)
print("Finish async callback")
def mouse_event(self, evt):
self.x = evt.new_x
self.y = evt.new_y
if self.click_within(evt):
Task(self.async_thingy())
print("Clicked!")
return True
class MyWindow(Window):
def __init__(self):
super().__init__(640, 480, title="Hello", doublebuffer=True)
self.bgc = rgb(255,255,255)
self.dejavu = Font("sans-serif", 13)
self.mb = MenuBar((("File",'file'),("Help",'help')))
let _menu_File = MenuList()
_menu_File.insert(MenuEntry("Test", lambda menu: print("hello, world")))
_menu_File.insert(MenuEntrySeparator())
_menu_File.insert(MenuEntry("Quit", lambda menu: self.close()))
self.mb.insert('file', _menu_File)
let _menu_Help = MenuList()
let _menu_Help_help = MenuEntry("Help",lambda menu: print("oh no!"))
_menu_Help.insert(_menu_Help_help)
_menu_Help.insert(MyMenuWidget())
_menu_Help.insert(MyMenuWidget())
self.mb.insert('help', _menu_Help)
self.mb.callback = lambda x: self.draw()
def draw(self):
self.fill(self.bgc)
decor_render(self)
let bounds = decor_get_bounds(self)
self.mb.place(bounds['left_width'],bounds['top_height'],self.width-bounds['width'],self)
self.mb.render(self)
self.dejavu.draw_string(self,"Hello, world.",20,120)
self.dejavu.draw_string(self,f"{self.x}, {self.y}",20,140)
self.flip()
def mouse_event(self, msg):
let decResponse = decor_handle_event(msg)
if decResponse == 2:
print("Close me?")
self.close()
return True
else if decResponse == 5:
decor_show_default_menu(self, self.x + msg.new_x, self.y + msg.new_y)
self.mb.mouse_event(self, msg)
def interp(a,b,p):
return a * (1.0 - p) + b * p
def interp_color(a,b,p):
return rgb(*(int(self.interp(l,r,p)) for l,r in zip(a,b)))
async def animate(self):
let mySentinel = object()
self.animator = mySentinel
let start = (255 * random.random(),255 * random.random(),255 * random.random())
let end = (255,255,255)
for i in range(31):
await sleep(0.033)
if self.animator is not mySentinel:
break
self.bgc = self.interp_color(start,end,i/30)
self.draw()
def keyboard_event(self, msg):
print(msg.keycode)
if msg.keycode == 102 and msg.action == 1:
Task(self.animate())
def close(self):
super().close()
mainloop.exit()
def window_moved(self, msg):
self.draw()
def menu_close(self):
self.draw()
let w = MyWindow()
w.move(200,200)
w.draw()
mainloop.menu_closed_callback = w.menu_close
mainloop.run()