From ce778bf8d4b54aa771fe45d58e36902bc88cf7fa Mon Sep 17 00:00:00 2001 From: Mehmet Ali Date: Fri, 10 Feb 2023 13:31:01 +0300 Subject: [PATCH] Implement basic native things --- events.v | 7 +++++-- examples/all_widgets.v | 2 +- mui.v | 10 +++++++++- native/windows_popup_helper.h | 25 +++++++++++++++++++++++++ native/windows_shared_helper.h | 19 +++++++++++++++++++ native_windows.c.v | 25 +++++++++++++++++++++++++ selectbox.v | 16 +++++++++++++++- themes.v | 3 ++- types.v | 4 ++++ types_windows.c.v | 12 ++++++++++-- widgets.v | 8 ++++---- 11 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 native/windows_popup_helper.h create mode 100644 native/windows_shared_helper.h create mode 100644 native_windows.c.v diff --git a/events.v b/events.v index 8b19d79..c1d6cef 100644 --- a/events.v +++ b/events.v @@ -7,12 +7,14 @@ import sokol.sapp [unsafe] fn click_fn(x f32, y f32, mb gg.MouseButton, mut app &Window) { + app.native_focus = false unsafe{ if app.focus!="" && app.active_dialog=="" { if get_object_by_id(app, app.focus)["type"].str=="selectbox" { mut old_focused_object:=get_object_by_id(app, app.focus) app.focus="" - total_items:=old_focused_object["list"].str.split("\0").len + the_list := old_focused_object["list"].str.split("\0") + total_items:=the_list.len list_x:=old_focused_object["x"].num list_y:=old_focused_object["y"].num+old_focused_object["h"].num list_height:=total_items*old_focused_object["h"].num @@ -20,7 +22,7 @@ fn click_fn(x f32, y f32, mb gg.MouseButton, mut app &Window) { if list_xx { if list_yy { old_focused_object["s"]=WindowData{num:int((y-list_y)/(list_height/total_items))} - old_focused_object["text"]=WindowData{str:old_focused_object["list"].str.split("\0")[old_focused_object["s"].num]} + old_focused_object["text"]=WindowData{str:the_list[old_focused_object["s"].num]} old_focused_object["fnchg"].fun(EventDetails{event:"value_change",trigger:"mouse_left",value:old_focused_object["text"].str,target_type:old_focused_object["type"].str,target_id:old_focused_object["id"].str},mut app, mut app.app_data) return } @@ -590,6 +592,7 @@ fn keydown_fn(c gg.KeyCode, m gg.Modifier, mut app &Window){ match c{ .tab { unsafe { + app.native_focus = false if app.active_dialog!=""{ if shift { app.focus=app.get_previous_dialog_object_by_id(app.focus)[0]["id"].str diff --git a/examples/all_widgets.v b/examples/all_widgets.v index 321b496..ed0ce1c 100644 --- a/examples/all_widgets.v +++ b/examples/all_widgets.v @@ -1,6 +1,6 @@ import malisipi.mui as m -mut app:=m.create(m.WindowConfig{ title:"MUI", scrollbar:true, width:800, height: 600 view_area:[1000,1000], ask_quit:true }) +mut app:=m.create(m.WindowConfig{ title:"MUI", scrollbar:true, width:800, height: 600 view_area:[1000,1000], ask_quit:true, prefer_native:false }) app.rect(m.Widget{ id:"rect", x:0, y:0, width:170, height:420 }) app.label(m.Widget{ id:"label", x: 20, y:20, text:"This is a label" }) diff --git a/mui.v b/mui.v index 4aa6aa7..2839c05 100644 --- a/mui.v +++ b/mui.v @@ -7,7 +7,14 @@ import math import sokol.sapp pub fn create(args &WindowConfig) &Window { - color_scheme, light_mode := if args.color!=[-1,-1,-1] { create_gx_color_from_manuel_color(args.color) } else { create_gx_color_from_color_scheme() } + prefer_native := $if windows { args.prefer_native } $else { false } + color_scheme, light_mode := if args.color!=[-1,-1,-1] { create_gx_color_from_manuel_color(args.color) } else { + if !prefer_native { + create_gx_color_from_color_scheme() + } else { + [gx.Color{r:240,g:240,b:240}, gx.Color{r:253,g:253,b:253}, gx.Color{r:0,g:120,b:212}, gx.Color{r:0,g:0,b:0}], true + } + } mut app := &Window{ objects: [] focus: "" @@ -28,6 +35,7 @@ pub fn create(args &WindowConfig) &Window { quit_fn: args.quit_fn resized_fn: args.resized_fn menubar_config: args.menubar_config + prefer_native: prefer_native } mut emoji_font:=args.font diff --git a/native/windows_popup_helper.h b/native/windows_popup_helper.h new file mode 100644 index 0000000..3ff41c9 --- /dev/null +++ b/native/windows_popup_helper.h @@ -0,0 +1,25 @@ +#define UNICODE + +#include +#include +#include + +static MENUITEMINFO mui_popup_menu_MENUITEMINFO (int id, bool def, bool disabled, bool checked, wchar_t* text) { + MENUITEMINFO item; + item.cbSize = sizeof(MENUITEMINFO); + item.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; + item.fType = 0; + item.fState = 0; + if (def){ + item.fState |= MFS_DEFAULT; + } + if (disabled) { + item.fState |= MFS_DISABLED; + } + if (checked) { + item.fState |= MFS_CHECKED; + } + item.wID = id; + item.dwTypeData = text; + return item; +} diff --git a/native/windows_shared_helper.h b/native/windows_shared_helper.h new file mode 100644 index 0000000..263dd59 --- /dev/null +++ b/native/windows_shared_helper.h @@ -0,0 +1,19 @@ +#define UNICODE + +#include +#include +#include + +int mui_window_top = 0; +int mui_window_left = 0; +int mui_window_bottom = 0; +int mui_window_right = 0; + +static void mui_update_window_pos (HWND hwnd) { + RECT pos; + GetWindowRect(hwnd, &pos); + mui_window_top = pos.top; + mui_window_bottom = pos.bottom; + mui_window_right = pos.right; + mui_window_left = pos.left; +} diff --git a/native_windows.c.v b/native_windows.c.v new file mode 100644 index 0000000..80ad7ca --- /dev/null +++ b/native_windows.c.v @@ -0,0 +1,25 @@ +module mui + +#include "@VMODROOT/native/windows_shared_helper.h" +#include "@VMODROOT/native/windows_popup_helper.h" + +fn C.CreatePopupMenu() voidptr +fn C.InsertMenuItem(hmenu C.HMENU, id int, idk_wtd bool, item &C.MENUITEMINFO) +fn C.TrackPopupMenu(hmenu C.HMENU, int, int, int, int, voidptr, int) int +fn C.mui_popup_menu_MENUITEMINFO(id int, def bool, disabled bool, checked bool, text &u16) C.MENUITEMINFO +fn C.DestroyMenu(hmenu C.HMENU) +fn C.mui_update_window_pos(hwnd voidptr) + +fn (mut app Window) create_popup_menu(the_list []string, x int, y int) int { + unsafe { + mut hmenu := C.CreatePopupMenu() + for id,w in the_list{ + mut item := C.mui_popup_menu_MENUITEMINFO(id+1, false, false, false, w.to_wide()) + C.InsertMenuItem(hmenu, id+1, true, &item) + } + C.mui_update_window_pos(app.window_handle()) + output := C.TrackPopupMenu(hmenu, C.TPM_LEFTALIGN | C.TPM_RIGHTBUTTON | C.TPM_RETURNCMD | C.TPM_NONOTIFY, C.mui_window_left+x, C.mui_window_top+y, 0, app.window_handle(), C.NULL) + C.DestroyMenu(hmenu) + return output-1 + } +} diff --git a/selectbox.v b/selectbox.v index 50b36b4..453f129 100644 --- a/selectbox.v +++ b/selectbox.v @@ -24,7 +24,7 @@ pub fn add_selectbox(mut app &Window, text string, list []string, selected int, "list": WindowData{str:list.join("\0")}, "s": WindowData{num:if text==""{ selected } else { -1 }}, "hi": WindowData{bol:hi}, - "fnchg":WindowData{fun:fnchg} + "fnchg":WindowData{fun:fnchg}, } } @@ -48,6 +48,20 @@ fn draw_selectbox(app &Window, object map[string]WindowData){ }) if app.focus==object["id"].str { + if app.prefer_native { + if !app.native_focus { + the_list := object["list"].str.split("\0") + selected := app.create_popup_menu(the_list, object["x"].num, window_titlebar_height+object["y"].num+object["h"].num) + if selected != -1 { + object["s"]=WindowData{num:selected} + object["text"]=WindowData{str:the_list[object["s"].num]} + object["fnchg"].fun(EventDetails{event:"value_change",trigger:"mouse_left",value:object["text"].str,target_type:object["type"].str,target_id:object["id"].str},mut app, mut app.app_data) + } + app.native_focus = true + } + return + } + $if !dont_clip ? { app.gg.scissor_rect(object["x"].num,object["y"].num+object["h"].num,object["w"].num,object["h"].num*object["list"].str.split("\0").len) } diff --git a/themes.v b/themes.v index 9e6c366..dbff4d7 100755 --- a/themes.v +++ b/themes.v @@ -8,6 +8,7 @@ import math pub const ( theme_dark=[40,40,40] theme_light=[225,225,225] + user_light_theme=is_light_theme() ) fn hex_to_rgb(clr string) []int { @@ -94,7 +95,7 @@ fn create_color_scheme() ([][]int, bool) { return create_color_scheme_from_accent_color(accent_color) } - color_scheme:=is_light_theme() + color_scheme:=user_light_theme if color_scheme { // if light theme return create_color_scheme_from_accent_color(theme_light) } diff --git a/types.v b/types.v index 83d3dc0..83258ff 100644 --- a/types.v +++ b/types.v @@ -5,6 +5,7 @@ import gx pub const ( null_object={"id":WindowData{str:""}} + window_titlebar_height = 30 ) pub type IntOrString=int|string @@ -67,6 +68,7 @@ pub mut: menubar_config MenubarConfig toolbar int //= 0 statusbar int //= 0 + prefer_native bool //= true } pub struct EventDetails{ @@ -109,6 +111,8 @@ pub mut: menubar_config MenubarConfig redraw_required bool = true force_redraw bool //= false + prefer_native bool + native_focus bool //=false } pub struct MenubarConfig { diff --git a/types_windows.c.v b/types_windows.c.v index cdaf4bc..34ffa90 100644 --- a/types_windows.c.v +++ b/types_windows.c.v @@ -1,8 +1,16 @@ module mui +import os import os.font const ( - text_cursor="│" - os_font=font.default() + text_cursor="|" + os_font=get_os_font() ) + +fn get_os_font()string{ + if os.exists("C:/Windows/Fonts/segoeui.ttf"){ + return "C:/Windows/Fonts/segoeui.ttf" + } + return font.default() +} \ No newline at end of file diff --git a/widgets.v b/widgets.v index 8c30fde..c190489 100644 --- a/widgets.v +++ b/widgets.v @@ -65,15 +65,15 @@ pub fn (mut app Window) password ( args Widget ){ } pub fn (mut app Window) checkbox ( args Widget ){ //dialog support not done - add_checkbox(mut app, args.text, args.id, args.x, args.y, args.width, args.height, args.checked , args.hidden, app.color_scheme[1], app.color_scheme[3], app.color_scheme[3], args.onchange, args.frame, args.z_index, args.text_size) + add_checkbox(mut app, args.text, args.id, args.x, args.y, args.width, args.height, args.checked , args.hidden, app.color_scheme[1], app.color_scheme[2], app.color_scheme[3], args.onchange, args.frame, args.z_index, args.text_size) } pub fn (mut app Window) switch ( args Widget ){ //dialog support not done - add_switch(mut app, args.text, args.id, args.x, args.y, args.width, args.height, args.checked , args.hidden, app.color_scheme[1], app.color_scheme[3], app.color_scheme[3], args.onchange, args.frame, args.z_index, args.text_size) + add_switch(mut app, args.text, args.id, args.x, args.y, args.width, args.height, args.checked , args.hidden, app.color_scheme[1], app.color_scheme[2], app.color_scheme[3], args.onchange, args.frame, args.z_index, args.text_size) } pub fn (mut app Window) radio ( args Widget ){ //dialog support not done - add_radio(mut app, args.list, args.id, args.x, args.y, args.height, args.selected , args.hidden, app.color_scheme[1], app.color_scheme[3], app.color_scheme[3], args.onchange, args.frame, args.z_index, args.text_size) + add_radio(mut app, args.list, args.id, args.x, args.y, args.height, args.selected , args.hidden, app.color_scheme[1], app.color_scheme[2], app.color_scheme[3], args.onchange, args.frame, args.z_index, args.text_size) } pub fn (mut app Window) selectbox ( args Widget ){ //dialog support not done @@ -89,7 +89,7 @@ pub fn (mut app Window) scrollbar ( args Widget ){ //dialog support not done } pub fn (mut app Window) link ( args Widget ){ //dialog support not done - add_link (mut app, args.text, args.id, args.x, args.y, args.width, args.height, args.hidden, args.link_underline, args.link, app.color_scheme[3], args.onclick, args.frame, args.z_index) + add_link (mut app, args.text, args.id, args.x, args.y, args.width, args.height, args.hidden, args.link_underline, args.link, app.color_scheme[2], args.onclick, args.frame, args.z_index) } pub fn (mut app Window) tab_view ( args Widget ){