1642 lines
No EOL
61 KiB
HolyC
1642 lines
No EOL
61 KiB
HolyC
Context2D* umami_min_max_close =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Window/min_max_close.png");
|
|
Context2D* umami_min_max_close_pressed = Image.FileToContext2D(
|
|
"M:/Media/Themes/Umami/Window/min_max_close_pressed.png");
|
|
Context2D* umami_title_bar_button = NewContext2D(16, 14);
|
|
Context2D* umami_default_icon =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Icon/default.png");
|
|
Context2D* umami_corner_resize =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Window/corner_resize.png");
|
|
|
|
Context2D* umami_widget_checkbox =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/checkbox.png");
|
|
Context2D* umami_widget_checkbox_active =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/checkbox_active.png");
|
|
Context2D* umami_widget_checkbox_checked =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/checkbox_checked.png");
|
|
Context2D* umami_widget_checkbox_checked_active = @image_file_to_context2d(
|
|
"M:/Media/Themes/Umami/Widget/checkbox_checked_active.png");
|
|
|
|
Context2D* umami_widget_radio =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/radio.png");
|
|
Context2D* umami_widget_radio_active =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/radio_active.png");
|
|
Context2D* umami_widget_radio_selected =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/radio_selected.png");
|
|
|
|
Context2D* umami_widget_horz_slider =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/horz_slider.png");
|
|
Context2D* umami_widget_vert_slider =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/vert_slider.png");
|
|
|
|
Context2D* umami_widget_sb_up_button =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/sb_up_button.png");
|
|
Context2D* umami_widget_sb_down_button =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/sb_down_button.png");
|
|
Context2D* umami_widget_sb_left_button =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/sb_left_button.png");
|
|
Context2D* umami_widget_sb_right_button =
|
|
@image_file_to_context2d("M:/Media/Themes/Umami/Widget/sb_right_button.png");
|
|
|
|
U0 @umami_button_repaint(Window* win, ButtonWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
I64 text_offset;
|
|
I64 text_width;
|
|
if (!widget->color)
|
|
widget->color = Color(0, 0, 0);
|
|
if (!widget->font)
|
|
widget->font = Compositor.theme.font.sans;
|
|
if (widget->image) {
|
|
widget->width = Max(widget->image->width + 8, widget->width);
|
|
widget->height = Max(widget->image->height + 8, widget->height);
|
|
}
|
|
ctx->fill_rect(x + 1, y + 1, widget->width - 2, widget->height - 2,
|
|
Color(232, 232, 232));
|
|
Line2D(win->render_ctx, x + 1, y, x + widget->width - 1, y,
|
|
Color(96, 96, 96));
|
|
Line2D(win->render_ctx, x + 1, y + widget->height - 1, x + widget->width - 1,
|
|
y + widget->height - 1, Color(96, 96, 96));
|
|
Line2D(win->render_ctx, x, y + 1, x, y + widget->height - 2,
|
|
Color(96, 96, 96));
|
|
Line2D(win->render_ctx, x + widget->width - 1, y + 1, x + widget->width - 1,
|
|
y + widget->height - 2, Color(96, 96, 96));
|
|
if (widget == win->mouse_down_widget && Mouse.left &&
|
|
@widget_is_hovered(win->x + x, win->y + y, widget)) {
|
|
|
|
if (widget->image) {
|
|
ctx->blot(x + 5, y + 5, widget->image);
|
|
}
|
|
|
|
Line2D(win->render_ctx, x + 1, y + 1, x + widget->width - 2, y + 1,
|
|
Color(152, 152, 152));
|
|
Line2D(win->render_ctx, x + 1, y + 1, x + 1, y + widget->height - 3,
|
|
Color(152, 152, 152));
|
|
Line2D(win->render_ctx, x + 2, y + 2, x + widget->width - 3, y + 2,
|
|
Color(216, 216, 216));
|
|
Line2D(win->render_ctx, x + 2, y + 2, x + 2, y + widget->height - 4,
|
|
Color(216, 216, 216));
|
|
Line2D(win->render_ctx, x + 2, y + widget->height - 3,
|
|
x + widget->width - 2, y + widget->height - 3, Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + 3, y + widget->height - 4,
|
|
x + widget->width - 2, y + widget->height - 4, Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + widget->width - 3, y + 2, x + widget->width - 3,
|
|
y + widget->height - 3, Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + widget->width - 4, y + 3, x + widget->width - 4,
|
|
y + widget->height - 3, Color(255, 255, 255));
|
|
} else {
|
|
|
|
if (widget->image) {
|
|
ctx->blot(x + 4, y + 4, widget->image);
|
|
}
|
|
|
|
Line2D(win->render_ctx, x + 2, y + 2, x + widget->width - 2, y + 2,
|
|
Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + 2, y + 3, x + widget->width - 3, y + 3,
|
|
Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + 2, y + 2, x + 2, y + widget->height - 3,
|
|
Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + 3, y + 2, x + 3, y + widget->height - 4,
|
|
Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + 3, y + widget->height - 3,
|
|
x + widget->width - 3, y + widget->height - 3, Color(216, 216, 216));
|
|
Line2D(win->render_ctx, x + widget->width - 3, y + 3, x + widget->width - 3,
|
|
y + widget->height - 3, Color(216, 216, 216));
|
|
Line2D(win->render_ctx, x + 2, y + widget->height - 2,
|
|
x + widget->width - 2, y + widget->height - 2, Color(152, 152, 152));
|
|
Line2D(win->render_ctx, x + widget->width - 2, y + 2, x + widget->width - 2,
|
|
y + widget->height - 2, Color(152, 152, 152));
|
|
}
|
|
if (StrLen(&widget->text)) {
|
|
text_offset = T(widget == win->mouse_down_widget && Mouse.left &&
|
|
@widget_is_hovered(win->x + x, win->y + y, widget),
|
|
1, 0);
|
|
text_width = PutS2D(NULL, widget->font, 0, 0, Color(0, 0, 0), , &widget->text);
|
|
PutS2D(win->render_ctx, widget->font,
|
|
x + text_offset + (widget->width / 2) - (text_width / 2),
|
|
y + text_offset + (widget->height / 2) - (widget->font->line_height / 2),
|
|
widget->color, , &widget->text);
|
|
}
|
|
}
|
|
|
|
U0 @umami_checkbox_repaint(Window* win, CheckBoxWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
if (widget == win->mouse_down_widget &&
|
|
@widget_is_hovered(win->x + x, win->y + y, widget)) {
|
|
ctx->blot(x, y,
|
|
T(widget->checked, umami_widget_checkbox_checked_active,
|
|
umami_widget_checkbox_active));
|
|
return;
|
|
}
|
|
if (widget == win->mouse_down_widget->echo && widget != win->mouse_down_widget &&
|
|
@widget_is_hovered(win->x + x, win->y + y, win->mouse_down_widget)) {
|
|
ctx->blot(x, y,
|
|
T(widget->checked, umami_widget_checkbox_checked_active,
|
|
umami_widget_checkbox_active));
|
|
return;
|
|
}
|
|
ctx->blot(x, y,
|
|
T(widget->checked, umami_widget_checkbox_checked, umami_widget_checkbox));
|
|
}
|
|
|
|
U0 @umami_terminal_calculate_size(Window* win, TerminalWidget* widget)
|
|
{
|
|
widget->size.cols = RoundI64(win->width, 8) / 8;
|
|
widget->size.rows = (RoundI64(win->height, 16) / 16) - 2;
|
|
}
|
|
|
|
U32 @umami_terminal_256_color_lookup(I64 index)
|
|
{
|
|
U32* color_table = TERMINAL_COLOR_TABLE;
|
|
return color_table[index];
|
|
}
|
|
|
|
U0 @umami_terminal_set_256_color_foreground(Window* win, TerminalWidget* widget,
|
|
I64 argc, U8** argv)
|
|
{
|
|
if (argc != 3 && !StrCmp(argv[1], "5"))
|
|
return;
|
|
widget->color.foreground = @umami_terminal_256_color_lookup(Str2I64(argv[2]));
|
|
}
|
|
|
|
U0 @umami_terminal_set_256_color_background(Window* win, TerminalWidget* widget,
|
|
I64 argc, U8** argv)
|
|
{
|
|
if (argc != 3 && !StrCmp(argv[1], "5"))
|
|
return;
|
|
widget->color.background = @umami_terminal_256_color_lookup(Str2I64(argv[2]));
|
|
widget->color.background.u8[3] = win->opacity;
|
|
}
|
|
|
|
U0 @umami_terminal_cleanup_strings(I64 argc, U8** argv)
|
|
{
|
|
I64 i;
|
|
for (i = 0; i < argc - 1; i++)
|
|
Free(argv[i]);
|
|
}
|
|
|
|
I64 @umami_ansi_16_color_table[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
|
|
|
U0 @umami_terminal_set_16_color_fg_value(TerminalWidget* widget)
|
|
{
|
|
I64 val = widget->last_fg_color_set;
|
|
if (val > 15)
|
|
return;
|
|
widget->color.foreground = Color(T(widget->attr.bold,
|
|
gr_palette_std[8 + @umami_ansi_16_color_table[val]].r & 0xFF,
|
|
gr_palette_std[@umami_ansi_16_color_table[val]].r & 0xFF),
|
|
T(widget->attr.bold,
|
|
gr_palette_std[8 + @umami_ansi_16_color_table[val]].g & 0xFF,
|
|
gr_palette_std[@umami_ansi_16_color_table[val]].g & 0xFF),
|
|
T(widget->attr.bold,
|
|
gr_palette_std[8 + @umami_ansi_16_color_table[val]].b & 0xFF,
|
|
gr_palette_std[@umami_ansi_16_color_table[val]].b & 0xFF));
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_sgr(Window* win, TerminalWidget* widget)
|
|
{
|
|
I64 argc;
|
|
I64 i;
|
|
I64 val;
|
|
U8** argv = String.Split(&widget->consumed_chars, ';', &argc);
|
|
if (!argc && StrLen(&widget->consumed_chars)) {
|
|
argc = 1;
|
|
argv[0] = &widget->consumed_chars;
|
|
}
|
|
if (!argc && !StrLen(&widget->consumed_chars)) {
|
|
widget->color.background = Color(0, 0, 0);
|
|
widget->color.foreground = Color(217, 217, 217);
|
|
return;
|
|
}
|
|
for (i = 0; i < argc; i++) {
|
|
val = Str2I64(argv[i]);
|
|
switch (val) {
|
|
case 0:
|
|
widget->color.background = Color(0, 0, 0);
|
|
widget->color.foreground = Color(217, 217, 217);
|
|
break;
|
|
case 1:
|
|
widget->attr.bold = TRUE;
|
|
if (widget->last_fg_color_set < 16)
|
|
@umami_terminal_set_16_color_fg_value(widget);
|
|
break;
|
|
case 2:
|
|
widget->attr.bold = FALSE;
|
|
if (widget->last_fg_color_set < 16)
|
|
@umami_terminal_set_16_color_fg_value(widget);
|
|
break;
|
|
// 16 colors
|
|
case 30...37:
|
|
widget->last_fg_color_set = val - 30;
|
|
@umami_terminal_set_16_color_fg_value(widget);
|
|
break;
|
|
case 40...47:
|
|
widget->color.background = Color(gr_palette_std[@umami_ansi_16_color_table[(val - 40)]].r & 0xFF,
|
|
gr_palette_std[@umami_ansi_16_color_table[(val - 40)]].g & 0xFF,
|
|
gr_palette_std[@umami_ansi_16_color_table[(val - 40)]].b & 0xFF,
|
|
win->opacity);
|
|
break;
|
|
// 256 colors
|
|
case 38:
|
|
widget->last_fg_color_set = 256;
|
|
@umami_terminal_set_256_color_foreground(win, widget, argc, argv);
|
|
i += 2;
|
|
break;
|
|
case 48:
|
|
@umami_terminal_set_256_color_background(win, widget, argc, argv);
|
|
i += 2;
|
|
break;
|
|
case 39:
|
|
// FIXME: Set default foreground color
|
|
widget->color.foreground = Color(217, 217, 217);
|
|
break;
|
|
case 49:
|
|
// FIXME: Set default background color
|
|
widget->color.background = Color(0, 0, 0);
|
|
break;
|
|
default:
|
|
System.Log("Unrecognized attribute in ctrl_seq_sgr: %d", val);
|
|
break;
|
|
}
|
|
}
|
|
// if (argc)
|
|
// @umami_terminal_cleanup_strings(argc, argv);
|
|
}
|
|
|
|
U0 @umami_terminal_set_col(Window* win, TerminalWidget* widget, I64 row,
|
|
I64 col, U8 char)
|
|
{
|
|
widget->row[row + widget->scroll.y].col[col + widget->scroll.x].foreground = widget->color.foreground;
|
|
widget->row[row + widget->scroll.y].col[col + widget->scroll.x].background = widget->color.background;
|
|
widget->row[row + widget->scroll.y].col[col + widget->scroll.x].char = char;
|
|
}
|
|
|
|
U0 @umami_terminal_set_row(Window* win, TerminalWidget* widget, I64 row,
|
|
U8 char)
|
|
{
|
|
I64 col;
|
|
for (col = 0; col < TERMINAL_MAX_COLS - 1; col++)
|
|
@umami_terminal_set_col(win, widget, row, col, char);
|
|
}
|
|
|
|
U0 @umami_terminal_set_rows(Window* win, TerminalWidget* widget, U8 char)
|
|
{
|
|
I64 row;
|
|
for (row = 0; row < widget->size.rows - 1; row++)
|
|
@umami_terminal_set_row(win, widget, row, char);
|
|
}
|
|
|
|
U0 @umami_terminal_repaint_col(Window* win, TerminalWidget* widget, I64 row,
|
|
I64 col)
|
|
{
|
|
U8 char[2];
|
|
char[1] = NULL;
|
|
U32 col_bg_color;
|
|
char[0] = widget->row[row + widget->scroll.y].col[col + widget->scroll.x].char;
|
|
col_bg_color = widget->row[row + widget->scroll.y]
|
|
.col[col + widget->scroll.x]
|
|
.background;
|
|
col_bg_color.u8[3] = win->opacity;
|
|
widget->backing_store->fill_rect(2 + (col * 8), 2 + (row * 16), 8, 16,
|
|
col_bg_color);
|
|
PutS2D(widget->backing_store, Compositor.theme.font.monospace, 2 + (col * 8),
|
|
2 + (row * 16),
|
|
widget->row[row + widget->scroll.y]
|
|
.col[col + widget->scroll.x]
|
|
.foreground,
|
|
, &char);
|
|
}
|
|
|
|
U0 @umami_terminal_repaint_row(Window* win, TerminalWidget* widget, I64 row)
|
|
{
|
|
I64 col;
|
|
for (col = 0; col < TERMINAL_MAX_COLS - 1; col++)
|
|
@umami_terminal_repaint_col(win, widget, row, col);
|
|
}
|
|
|
|
U0 @umami_terminal_repaint_rows(Window* win, TerminalWidget* widget)
|
|
{
|
|
I64 row;
|
|
for (row = 0; row < widget->size.rows - 1; row++)
|
|
@umami_terminal_repaint_row(win, widget, row);
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_cursor_move(Window* win, TerminalWidget* widget,
|
|
I64 dir)
|
|
{
|
|
I64 pos = Str2I64(&widget->consumed_chars);
|
|
I64 prev_row = widget->cursor.y;
|
|
switch (dir) {
|
|
case 'A':
|
|
widget->cursor.y = Max(0, widget->cursor.y - pos);
|
|
break;
|
|
case 'B':
|
|
widget->cursor.y = Min(widget->cursor.y + pos, widget->size.rows - 1);
|
|
break;
|
|
case 'C':
|
|
widget->cursor.x = Min(widget->cursor.x + pos, widget->size.cols - 1);
|
|
break;
|
|
case 'D':
|
|
widget->cursor.x = Max(0, widget->cursor.x - pos);
|
|
break;
|
|
};
|
|
@umami_terminal_repaint_row(win, widget, prev_row);
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_cursor_pos(Window* win, TerminalWidget* widget)
|
|
{
|
|
I64 argc;
|
|
I64 i;
|
|
I64 val;
|
|
U8** argv = String.Split(&widget->consumed_chars, ';', &argc);
|
|
if (!argc) {
|
|
@umami_terminal_repaint_col(win, widget, widget->cursor.y,
|
|
widget->cursor.x);
|
|
widget->cursor.x = 0;
|
|
widget->cursor.y = 0;
|
|
return;
|
|
}
|
|
if (argc == 2) {
|
|
@umami_terminal_repaint_col(win, widget, widget->cursor.y,
|
|
widget->cursor.x);
|
|
widget->cursor.y = Str2I64(argv[0]) - 1;
|
|
widget->cursor.x = Str2I64(argv[1]) - 1;
|
|
widget->cursor.y = Min(widget->size.rows - 2, widget->cursor.y);
|
|
widget->cursor.x = Min(widget->size.cols - 2, widget->cursor.x);
|
|
widget->cursor.y = Max(0, widget->cursor.y);
|
|
widget->cursor.x = Max(0, widget->cursor.x);
|
|
//@umami_terminal_cleanup_strings(argc, argv);
|
|
return;
|
|
}
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_erase_screen(Window* win, TerminalWidget* widget)
|
|
{
|
|
I64 i;
|
|
if (!StrLen(&widget->consumed_chars)) {
|
|
// TODO: clear from cursor to end of the screen
|
|
return;
|
|
}
|
|
I64 val = Str2I64(&widget->consumed_chars);
|
|
switch (val) {
|
|
case 0:
|
|
// TODO: clear from cursor to end of the screen
|
|
break;
|
|
case 1:
|
|
// TODO: clear from cursor to beginning of the screen
|
|
break;
|
|
case 2:
|
|
widget->scroll.x = 0;
|
|
widget->scroll.y = 0;
|
|
widget->max.x = 0;
|
|
widget->max.y = 0;
|
|
for (i = 0; i < 2000; i++)
|
|
@umami_terminal_set_row(win, widget, i, NULL);
|
|
@umami_terminal_repaint_rows(win, widget);
|
|
break;
|
|
default:
|
|
System.Log("Unrecognized attribute in ctrl_seq_erase_screen: %d", val);
|
|
break;
|
|
};
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_erase_line(Window* win, TerminalWidget* widget)
|
|
{
|
|
if (!StrLen(&widget->consumed_chars)) {
|
|
// TODO: clear from cursor to end of the line
|
|
return;
|
|
}
|
|
I64 val = Str2I64(&widget->consumed_chars);
|
|
switch (val) {
|
|
case 0:
|
|
// TODO: clear from cursor to end of the line
|
|
break;
|
|
case 1:
|
|
// TODO: clear from cursor to beginning of the line
|
|
break;
|
|
case 2:
|
|
@umami_terminal_set_row(win, widget, widget->cursor.y, ' ');
|
|
@umami_terminal_repaint_rows(win, widget);
|
|
break;
|
|
default:
|
|
System.Log("Unrecognized attribute in ctrl_seq_erase_line: %d", val);
|
|
break;
|
|
};
|
|
}
|
|
|
|
U0 @umami_terminal_send_response_string(Window* win, TerminalWidget* widget,
|
|
U8* string)
|
|
{
|
|
if (!string || !widget->output)
|
|
return;
|
|
I64 i;
|
|
for (i = 0; i < StrLen(string); i++)
|
|
FifoU8Ins(widget->output, string[i]);
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_set_func(Window* win, TerminalWidget* widget,
|
|
Bool bool)
|
|
{
|
|
if (!StrCmp(&widget->consumed_chars, "?25")) {
|
|
@umami_terminal_repaint_col(win, widget, widget->cursor.y,
|
|
widget->cursor.x);
|
|
widget->cursor.hidden = T(bool, FALSE, TRUE);
|
|
}
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_dev_attr_report(Window* win,
|
|
TerminalWidget* widget)
|
|
{
|
|
if (!widget->output)
|
|
return;
|
|
if (StrFind("=", &widget->consumed_chars)) {
|
|
// Tertiary device attributes
|
|
@umami_terminal_send_response_string(win, widget, "\x1bP!|7E565445\x1b\\");
|
|
return;
|
|
}
|
|
if (StrFind(">", &widget->consumed_chars)) {
|
|
// Secondary device attributes
|
|
@umami_terminal_send_response_string(win, widget, "\x1b[>65;6201;1c");
|
|
return;
|
|
}
|
|
// Primary device attributes
|
|
@umami_terminal_send_response_string(win, widget, "\x1b[?65;1;9c");
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_ecp_report(Window* win, TerminalWidget* widget)
|
|
{
|
|
if (!widget->output)
|
|
return;
|
|
U8 resp_str[32];
|
|
StrPrint(&resp_str, "\x1b[%d;%dR", widget->cursor.y + 1,
|
|
widget->cursor.x + 1);
|
|
if (!StrCmp(&widget->consumed_chars, "5"))
|
|
@umami_terminal_send_response_string(win, widget, "\x1b[0n");
|
|
if (!StrCmp(&widget->consumed_chars, "6"))
|
|
@umami_terminal_send_response_string(win, widget, &resp_str);
|
|
}
|
|
|
|
U0 @umami_terminal_ctrl_seq_req_tparm(Window* win, TerminalWidget* widget)
|
|
{
|
|
// FIXME: allow unsolicited DECREPTPARMs
|
|
if (!StrCmp(&widget->consumed_chars, "1")) {
|
|
@umami_terminal_send_response_string(win, widget,
|
|
"\x1b[3;1;1;120;120;1;0x");
|
|
return;
|
|
}
|
|
@umami_terminal_send_response_string(win, widget, "\x1b[2;1;1;120;120;1;0x");
|
|
}
|
|
|
|
U0 @umami_terminal_os_cmd(Window* win, TerminalWidget* widget)
|
|
{
|
|
I64 argc;
|
|
I64 i;
|
|
I64 val;
|
|
U8** argv = String.Split(&widget->consumed_chars, ';', &argc);
|
|
if (!argc)
|
|
return;
|
|
val = Str2I64(argv[0]);
|
|
switch (val) {
|
|
case 0:
|
|
// Test set window title
|
|
StrPrint(win->title, "Terminal - %s", argv[1]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//@umami_terminal_cleanup_strings(argc, argv);
|
|
}
|
|
|
|
U0 @umami_terminal_consume_char(Window* win, TerminalWidget* widget)
|
|
{
|
|
U8 char[2];
|
|
char[1] = NULL;
|
|
FifoU8Rem(widget->input, &char);
|
|
|
|
switch (widget->state) {
|
|
case TERMINAL_STATE_CONSUME_BEGIN:
|
|
StrCpy(&widget->consumed_chars, "");
|
|
switch (char[0]) {
|
|
case '7': // DEC Save Cursor
|
|
MemCpy(&widget->stored.attr, &widget->attr,
|
|
sizeof(@terminal_widget_attr));
|
|
MemCpy(&widget->stored.color, &widget->color,
|
|
sizeof(@terminal_widget_color));
|
|
MemCpy(&widget->stored.cursor, &widget->cursor,
|
|
sizeof(@terminal_widget_cursor));
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case '8': // Dec Restore Cursor
|
|
MemCpy(&widget->attr, &widget->stored.attr,
|
|
sizeof(@terminal_widget_attr));
|
|
MemCpy(&widget->color, &widget->stored.color,
|
|
sizeof(@terminal_widget_color));
|
|
MemCpy(&widget->cursor, &widget->stored.cursor,
|
|
sizeof(@terminal_widget_cursor));
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case '[':
|
|
widget->state = TERMINAL_STATE_CONSUME_CTRL_SEQ;
|
|
break;
|
|
case ']':
|
|
widget->state = TERMINAL_STATE_CONSUME_OS_CMD;
|
|
break;
|
|
default:
|
|
System.Log(Fs, "Undefined C1 control code: %c", char[0]);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
};
|
|
break;
|
|
case TERMINAL_STATE_CONSUME_CTRL_SEQ:
|
|
switch (char[0]) {
|
|
case '0' ... '9':
|
|
case ';':
|
|
case '?':
|
|
case '>':
|
|
case '=':
|
|
String.Append(&widget->consumed_chars, &char);
|
|
break;
|
|
case 'A' ... 'D':
|
|
@umami_terminal_ctrl_seq_cursor_move(win, widget, char[0]);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'H':
|
|
@umami_terminal_ctrl_seq_cursor_pos(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'J':
|
|
@umami_terminal_ctrl_seq_erase_screen(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'K':
|
|
@umami_terminal_ctrl_seq_erase_line(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'c':
|
|
@umami_terminal_ctrl_seq_dev_attr_report(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'h':
|
|
@umami_terminal_ctrl_seq_set_func(win, widget, 1);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'l':
|
|
@umami_terminal_ctrl_seq_set_func(win, widget, 0);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'm':
|
|
@umami_terminal_ctrl_seq_sgr(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'n':
|
|
@umami_terminal_ctrl_seq_ecp_report(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 't':
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
case 'x':
|
|
@umami_terminal_ctrl_seq_req_tparm(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
default:
|
|
System.Log(Fs,
|
|
"Invalid or unimplemented character in control sequence: '%c'",
|
|
char[0]);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
}
|
|
break;
|
|
case TERMINAL_STATE_CONSUME_OS_CMD:
|
|
switch (char[0]) {
|
|
case 7:
|
|
case '\\':
|
|
@umami_terminal_os_cmd(win, widget);
|
|
widget->state = TERMINAL_STATE_CONSUME_END;
|
|
break;
|
|
default:
|
|
String.Append(&widget->consumed_chars, &char);
|
|
break;
|
|
};
|
|
break;
|
|
};
|
|
}
|
|
|
|
U0 @umami_terminal_output_char(Window* win, TerminalWidget* widget)
|
|
{
|
|
if (widget->scroll.y != widget->max.y) {
|
|
widget->scroll.y = widget->max.y;
|
|
@umami_terminal_repaint_rows(win, widget);
|
|
} else {
|
|
widget->scroll.y = widget->max.y;
|
|
}
|
|
U8 char[2];
|
|
char[1] = NULL;
|
|
FifoU8Rem(widget->input, &char);
|
|
switch (char[0]) {
|
|
case 27:
|
|
StrCpy(&widget->consumed_chars, "");
|
|
widget->state = TERMINAL_STATE_CONSUME_BEGIN;
|
|
return;
|
|
break;
|
|
case 7:
|
|
// Audio.Beep();
|
|
break;
|
|
case 8:
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.char
|
|
= ' ';
|
|
widget->cursor.x--;
|
|
if (widget->cursor.x < 0) {
|
|
widget->cursor.y--;
|
|
widget->cursor.x = widget->size.cols - 2;
|
|
}
|
|
break;
|
|
case 10:
|
|
widget->cursor.y++;
|
|
widget->cursor.x = 0;
|
|
break;
|
|
case 13:
|
|
widget->cursor.x = 0;
|
|
break;
|
|
case 32...127:
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.foreground
|
|
= widget->color.foreground;
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.background
|
|
= widget->color.background;
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.char
|
|
= char[0];
|
|
widget->cursor.x++;
|
|
break;
|
|
default:
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.foreground
|
|
= widget->color.foreground;
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.background
|
|
= widget->color.background;
|
|
widget->row[widget->cursor.y + widget->scroll.y]
|
|
.col[widget->cursor.x + widget->scroll.x]
|
|
.char
|
|
= '?';
|
|
widget->cursor.x++;
|
|
break;
|
|
};
|
|
if (widget->cursor.x >= widget->size.cols - 1) {
|
|
widget->cursor.y++;
|
|
widget->cursor.x = 0;
|
|
}
|
|
if (widget->cursor.y >= widget->size.rows - 1) {
|
|
widget->cursor.y--;
|
|
widget->max.y++;
|
|
widget->scroll.y = widget->max.y;
|
|
@umami_terminal_set_row(win, widget, widget->cursor.y, NULL);
|
|
@umami_terminal_repaint_rows(win, widget);
|
|
}
|
|
@umami_terminal_set_col(win, widget, widget->cursor.y, widget->cursor.x, ' ');
|
|
}
|
|
|
|
U0 @umami_terminal_repaint(Window* win, TerminalWidget* widget, I64 x, I64 y)
|
|
{
|
|
|
|
I64 current_col = NULL;
|
|
I64 current_row = NULL;
|
|
|
|
@umami_terminal_calculate_size(win, widget);
|
|
|
|
if (widget->refresh) {
|
|
@umami_terminal_repaint_rows(win, widget);
|
|
widget->refresh = FALSE;
|
|
}
|
|
|
|
while (FifoU8Cnt(widget->input)) {
|
|
current_col = widget->cursor.x;
|
|
current_row = widget->cursor.y;
|
|
switch (widget->state) {
|
|
case TERMINAL_STATE_OUTPUT:
|
|
@umami_terminal_output_char(win, widget);
|
|
break;
|
|
case TERMINAL_STATE_CONSUME_BEGIN:
|
|
case TERMINAL_STATE_CONSUME_CTRL_SEQ:
|
|
case TERMINAL_STATE_CONSUME_OS_CMD:
|
|
@umami_terminal_consume_char(win, widget);
|
|
break;
|
|
}
|
|
if (widget->state == TERMINAL_STATE_OUTPUT)
|
|
@umami_terminal_repaint_col(win, widget, current_row, current_col);
|
|
if (widget->state == TERMINAL_STATE_CONSUME_END)
|
|
widget->state = TERMINAL_STATE_OUTPUT;
|
|
}
|
|
if (widget->state == TERMINAL_STATE_OUTPUT && !widget->cursor.hidden && widget->scroll.y == widget->max.y)
|
|
widget->backing_store->fill_rect(2 + (widget->cursor.x * 8),
|
|
2 + (widget->cursor.y * 16), 8, 16, widget->color.cursor);
|
|
}
|
|
|
|
I64 @umami_input_get_text_width(BitmapFontTextInputWidget* widget)
|
|
{
|
|
I64 x;
|
|
I64 y;
|
|
I64 text_width = PutS2D(NULL, widget->font, 0, 0, Color(0, 0, 0), -1, &widget->text);
|
|
|
|
Context2D* ctx = NewContext2D(text_width, widget->font->line_height);
|
|
ctx->fill(0);
|
|
PutS2D(ctx, widget->font, 0, 0, Color(128, 255, 255), -1, &widget->text);
|
|
|
|
for (x = ctx->width - 1; x > -1; x--) {
|
|
for (y = 0; y < ctx->height - 1; y++) {
|
|
if (ctx->fb[(ctx->width * y) + x]) {
|
|
DelContext2D(ctx);
|
|
return x + 2;
|
|
}
|
|
}
|
|
}
|
|
DelContext2D(ctx);
|
|
return x;
|
|
}
|
|
|
|
U0 @umami_input_draw_cursor(Window* win, BitmapFontTextInputWidget* widget,
|
|
I64 index, I64 x, I64 y, I64 pos)
|
|
{
|
|
if (widget->selected_region_start != -1 && widget->selected_region_end != -1)
|
|
return;
|
|
if (widget == win->focused_widget) {
|
|
if (Blink && index == widget->cursor_index) {
|
|
VLine2D(win->render_ctx, x + 2 + pos, y + 2,
|
|
y + 2 + widget->font->line_height, Color(0, 0, 0));
|
|
}
|
|
}
|
|
}
|
|
|
|
U0 @umami_input_repaint(Window* win, I64 event,
|
|
BitmapFontTextInputWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
if (!widget->font)
|
|
widget->font = Compositor.theme.font.sans;
|
|
U8* text;
|
|
U8 ch[2];
|
|
I64 index;
|
|
I64 text_width;
|
|
I64 text_x_pos;
|
|
ch[1] = NULL;
|
|
widget->height = widget->font->line_height + 6;
|
|
|
|
HLine2D(win->render_ctx, x, y, x + widget->width, Color(156, 156, 156));
|
|
VLine2D(win->render_ctx, x, y, y + widget->height, Color(156, 156, 156));
|
|
HLine2D(win->render_ctx, x + 1, y + widget->height, x + widget->width,
|
|
Color(190, 190, 190));
|
|
VLine2D(win->render_ctx, x + widget->width, y + 1, y + widget->height,
|
|
Color(190, 190, 190));
|
|
ctx->fill_rect(x + 1, y + 1, widget->width - 1, widget->height - 1,
|
|
Color(255, 255, 255));
|
|
|
|
if (widget == win->focused_widget) {
|
|
HLine2D(win->render_ctx, x + 1, y + 1, x + widget->width - 1,
|
|
Color(0, 0, 0));
|
|
VLine2D(win->render_ctx, x + 1, y + 1, y + widget->height - 2,
|
|
Color(0, 0, 0));
|
|
HLine2D(win->render_ctx, x + 1, y + widget->height - 1,
|
|
x + widget->width - 1, Color(0, 0, 0));
|
|
VLine2D(win->render_ctx, x + widget->width - 1, y + 1,
|
|
y + widget->height - 1, Color(0, 0, 0));
|
|
} else {
|
|
widget->in_drag = FALSE;
|
|
}
|
|
|
|
if (!Mouse.left) {
|
|
widget->in_drag = FALSE;
|
|
widget->mouse_drag_index = -1;
|
|
}
|
|
|
|
Context2D* text_input_ctx = NewContext2D(widget->width - 4, widget->height);
|
|
|
|
if (widget->is_password) {
|
|
StrCpy(widget->password, widget->text);
|
|
for (text_x_pos = 0; text_x_pos < StrLen(widget->password); text_x_pos++)
|
|
widget->password[text_x_pos] = '*';
|
|
}
|
|
text = T(widget->is_password, &widget->password, &widget->text);
|
|
index = 0;
|
|
text_width;
|
|
text_x_pos = 0;
|
|
while (*text) {
|
|
ch[0] = *text;
|
|
text_width = PutS2D(NULL, widget->font, 0, 0, Color(0, 0, 0), -1, &ch) + 2;
|
|
|
|
if (event == CPZ_MSG_WIN_LEFT_BTN_DOWN && !widget->in_drag && Mouse.x >= win->x + widget->x + -widget->x_offset + text_x_pos && Mouse.x <= win->x + widget->x + -widget->x_offset + text_x_pos + text_width) {
|
|
widget->cursor_index = index;
|
|
widget->mouse_drag_index = widget->cursor_index - 1;
|
|
widget->mouse_drag_origin_x = Mouse.x - win->x - widget->x + widget->x_offset;
|
|
}
|
|
|
|
if (widget->in_drag) {
|
|
if (Mouse.x - win->x - widget->x < widget->mouse_drag_origin_x && Mouse.x >= win->x + widget->x + -widget->x_offset + text_x_pos && Mouse.x <= win->x + widget->x + -widget->x_offset + text_x_pos + text_width) {
|
|
widget->selected_region_start = index;
|
|
widget->selected_region_end = widget->mouse_drag_index;
|
|
}
|
|
if (Mouse.x - win->x - widget->x >= widget->mouse_drag_origin_x && Mouse.x >= win->x + widget->x + -widget->x_offset + text_x_pos + text_width) {
|
|
widget->selected_region_start = widget->mouse_drag_index + 1;
|
|
widget->selected_region_end = index;
|
|
}
|
|
}
|
|
|
|
if (index >= widget->selected_region_start && index <= widget->selected_region_end) {
|
|
text_input_ctx->fill_rect(-widget->x_offset + text_x_pos, 0, text_width,
|
|
widget->font->line_height + 3, Compositor.theme.color.hilight);
|
|
}
|
|
if (index >= widget->selected_region_start && index <= widget->selected_region_end)
|
|
PutS2D(text_input_ctx, widget->font, -widget->x_offset + text_x_pos, 2,
|
|
Color(255, 255, 255), -1, &ch);
|
|
else
|
|
PutS2D(text_input_ctx, widget->font, -widget->x_offset + text_x_pos, 2,
|
|
widget->color, -1, &ch);
|
|
|
|
@umami_input_draw_cursor(win, widget, index, x, y,
|
|
-widget->x_offset + text_x_pos);
|
|
text_x_pos += text_width;
|
|
|
|
text++;
|
|
index++;
|
|
}
|
|
|
|
if (event == CPZ_MSG_WIN_LEFT_BTN_DOWN && !widget->in_drag && Mouse.x > win->x + widget->x + -widget->x_offset + text_x_pos && widget == win->focused_widget) {
|
|
widget->cursor_index = StrLen(&widget->text);
|
|
widget->mouse_drag_index = widget->cursor_index;
|
|
widget->mouse_drag_origin_x = Mouse.x - win->x - widget->x;
|
|
}
|
|
|
|
if (event == CPZ_MSG_WIN_LEFT_BTN_DOWN && widget == win->focused_widget) {
|
|
@widget_input_clear_selected_region(widget);
|
|
widget->in_drag = TRUE;
|
|
}
|
|
|
|
if (-widget->x_offset + text_x_pos < text_input_ctx->width)
|
|
@umami_input_draw_cursor(win, widget, index, x, y,
|
|
-widget->x_offset + text_x_pos);
|
|
|
|
ctx->blot(x + 3, y + 2, text_input_ctx);
|
|
DelContext2D(text_input_ctx);
|
|
}
|
|
|
|
U0 @umami_label_repaint(Window* win, BitmapFontTextLabelWidget* widget, I64 x,
|
|
I64 y)
|
|
{
|
|
if (!widget->font)
|
|
widget->font = Compositor.theme.font.sans;
|
|
if (widget->text)
|
|
PutS2D(win->render_ctx, widget->font, x, y, widget->color, -1,
|
|
widget->text);
|
|
}
|
|
|
|
U0 @umami_list_view_repaint(Window* win, ListViewWidget* widget, I64 x, I64 y)
|
|
{
|
|
}
|
|
|
|
U0 @umami_menu_item_repaint(Window* win, MenuItemWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
U32 text_color = Color(0, 0, 0);
|
|
I64 text_x = 8;
|
|
I64 text_y = 4 + (widget->height / 2) - (16 / 2);
|
|
I64 icon_x = 4;
|
|
I64 icon_y = 0;
|
|
if (widget->icon) {
|
|
icon_y = 4 + (widget->height / 2) - (widget->icon->height / 2) - 3;
|
|
}
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget)) {
|
|
ctx->fill_rect(x, y, widget->width, widget->height,
|
|
Compositor.theme.color.hilight);
|
|
text_color = Color(255, 255, 255);
|
|
if (widget->submenu) {
|
|
Gui.Window.Show(widget->submenu);
|
|
Gui.Window.Refresh(widget->submenu);
|
|
if (Compositor.GetWindowByZIndex(Compositor.max_z_index - 3) != widget->submenu) {
|
|
Gui.Window.SetZIndex(widget->submenu, Compositor.max_z_index - 3);
|
|
}
|
|
}
|
|
}
|
|
if (!(@widget_is_hovered(win->x + x, win->y + y, widget))) {
|
|
if (widget->submenu) {
|
|
Gui.Window.Hide(widget->submenu);
|
|
}
|
|
}
|
|
if (!widget->font)
|
|
widget->font = Compositor.theme.font.menu;
|
|
if (widget->icon) {
|
|
ctx->blot(x + icon_x, y + icon_y, widget->icon);
|
|
text_x += 20;
|
|
}
|
|
if (widget->text)
|
|
PutS2D(win->render_ctx, widget->font, x + text_x, y + text_y,
|
|
T(widget->color, widget->color, text_color), -1, widget->text);
|
|
}
|
|
|
|
U0 @umami_radio_repaint(Window* win, RadioButtonWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
if (widget == win->mouse_down_widget &&
|
|
@widget_is_hovered(win->x + x, win->y + y, widget)) {
|
|
ctx->blot(x, y,
|
|
T(widget->selected, umami_widget_radio_selected,
|
|
umami_widget_radio_active));
|
|
return;
|
|
}
|
|
if (widget == win->mouse_down_widget->echo && widget != win->mouse_down_widget && !widget->selected &&
|
|
@widget_is_hovered(win->x + x, win->y + y, win->mouse_down_widget)) {
|
|
ctx->blot(x, y,
|
|
T(win->mouse_down_widget(RadioButtonWidget*)->selected,
|
|
umami_widget_radio_selected, umami_widget_radio_active));
|
|
return;
|
|
}
|
|
ctx->blot(x, y,
|
|
T(widget->selected, umami_widget_radio_selected, umami_widget_radio));
|
|
}
|
|
|
|
U0 @umami_radio_select(Window* win, RadioButtonWidget* widget)
|
|
{
|
|
@window_widgets_list* widgets_list;
|
|
widgets_list = win->widget;
|
|
while (widgets_list) {
|
|
if (widgets_list->widget && widgets_list->widget->type == WIDGET_TYPE_RADIO)
|
|
if (widgets_list->widget(RadioButtonWidget*)->group == widget->group)
|
|
widgets_list->widget(RadioButtonWidget*)->selected = T(widgets_list->widget == widget, TRUE, FALSE);
|
|
widgets_list = widgets_list->next;
|
|
}
|
|
}
|
|
|
|
Bool @umami_horz_slider_bar_is_hovered(I64 x, I64 y, Widget* widget)
|
|
{
|
|
no_warn y;
|
|
if (Mouse.x > x - 7 && Mouse.x < x + widget->width + 7)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
Bool @umami_horz_slider_is_hovered(Window* win, HorizontalSliderWidget* widget,
|
|
I64 x, I64 y, I64 scroll_pos)
|
|
{
|
|
if (@widget_is_hovered(win->x + x, win->y + y - 24, widget) && Mouse.x > -4 + (win->x + widget->x - 7) + scroll_pos && Mouse.x < (win->x + widget->x - 7) + scroll_pos + 16)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
U0 @umami_horz_slider_repaint(Window* win, I64 event,
|
|
HorizontalSliderWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
I64 scroll = widget->scroll;
|
|
widget->height = 12;
|
|
if (widget->in_drag &&
|
|
@umami_horz_slider_bar_is_hovered(win->x + x, win->y + y - 24, widget)) {
|
|
if (widget->origin.mouse_x != Mouse.x) {
|
|
widget->scroll += (Mouse.x - widget->origin.mouse_x);
|
|
widget->origin.mouse_x = Mouse.x;
|
|
}
|
|
}
|
|
|
|
ctx->fill_rect(x, y + 5, widget->width, 4, Color(156, 156, 156));
|
|
if (@umami_horz_slider_is_hovered(win, widget, x, y, widget->scroll) && event == CPZ_MSG_WIN_LEFT_BTN_DOWN) {
|
|
win->mouse_down_widget = widget;
|
|
widget->origin.mouse_x = Mouse.x;
|
|
widget->in_drag = TRUE;
|
|
} else {
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget) && event == CPZ_MSG_WIN_LEFT_BTN_DOWN) {
|
|
widget->scroll = (Mouse.x - win->x - x + 2);
|
|
widget->origin.mouse_x = Mouse.x;
|
|
widget->in_drag = TRUE;
|
|
}
|
|
}
|
|
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget) && event == CPZ_MSG_WIN_MOUSE_WHEEL) {
|
|
widget->scroll -= Compositor.mouse.z;
|
|
}
|
|
|
|
widget->scroll = Max(0, widget->scroll);
|
|
widget->scroll = Min(widget->width - 1, widget->scroll);
|
|
widget->value = ToI64((widget->max * 1.0) / (widget->width * 1.0) * (widget->scroll * 1.0));
|
|
|
|
if (!Mouse.left)
|
|
widget->in_drag = FALSE;
|
|
|
|
HLine2D(win->render_ctx, x, y + 1, x + widget->width, Color(190, 190, 190));
|
|
HLine2D(win->render_ctx, x + 1, y + 4, x + widget->width, Color(0, 0, 0));
|
|
VLine2D(win->render_ctx, x + 1, y + 4, y + 8, Color(0, 0, 0));
|
|
VLine2D(win->render_ctx, x, y + 4, y + 9, Color(190, 190, 190));
|
|
HLine2D(win->render_ctx, x, y + 9, x + widget->width, Color(255, 255, 255));
|
|
VLine2D(win->render_ctx, x + widget->width, y + 4, y + 9,
|
|
Color(255, 255, 255));
|
|
|
|
VLine2D(win->render_ctx, x, y + 11, y + 16, Color(190, 190, 190));
|
|
VLine2D(win->render_ctx, x + 1, y + 11, y + 16, Color(255, 255, 255));
|
|
|
|
VLine2D(win->render_ctx, x + (widget->width / 2) - 1, y + 11, y + 16,
|
|
Color(190, 190, 190));
|
|
VLine2D(win->render_ctx, x + (widget->width / 2), y + 11, y + 16,
|
|
Color(255, 255, 255));
|
|
|
|
VLine2D(win->render_ctx, x + widget->width - 1, y + 11, y + 16,
|
|
Color(190, 190, 190));
|
|
VLine2D(win->render_ctx, x + widget->width, y + 11, y + 16,
|
|
Color(255, 255, 255));
|
|
|
|
ctx->blot((x - 7) + widget->scroll, y,
|
|
umami_widget_horz_slider);
|
|
|
|
if (widget->scroll != scroll)
|
|
widget->change = TRUE;
|
|
}
|
|
|
|
Bool @umami_vert_slider_bar_is_hovered(I64 x, I64 y, Widget* widget)
|
|
{
|
|
no_warn x;
|
|
if (Mouse.y > y - 7 && Mouse.y < y + widget->height + 7)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
Bool @umami_vert_slider_is_hovered(Window* win, VerticalSliderWidget* widget,
|
|
I64 x, I64 y, I64 scroll_pos)
|
|
{
|
|
if (@widget_is_hovered(win->x + x - 24, win->y + y, widget) && Mouse.y > -4 + (win->y + widget->y - 7) + scroll_pos && Mouse.y < (win->y + widget->y - 7) + scroll_pos + 16)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
U0 @umami_vert_slider_repaint(Window* win, I64 event,
|
|
VerticalSliderWidget* widget, I64 x, I64 y)
|
|
{
|
|
Context2D* ctx = win->render_ctx;
|
|
I64 scroll = widget->scroll;
|
|
widget->width = 12;
|
|
if (widget->in_drag &&
|
|
@umami_vert_slider_bar_is_hovered(win->x + x, win->y + y, widget)) {
|
|
if (widget->origin.mouse_y != Mouse.y) {
|
|
widget->scroll += (Mouse.y - widget->origin.mouse_y);
|
|
widget->origin.mouse_y = Mouse.y;
|
|
}
|
|
}
|
|
ctx->fill_rect(x + 5, y, 4, widget->height, Color(156, 156, 156));
|
|
if (@umami_horz_slider_is_hovered(win, widget, x, y, widget->scroll) && event == CPZ_MSG_WIN_LEFT_BTN_DOWN) {
|
|
win->mouse_down_widget = widget;
|
|
widget->origin.mouse_y = Mouse.y;
|
|
widget->in_drag = TRUE;
|
|
} else {
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget) && event == CPZ_MSG_WIN_LEFT_BTN_DOWN) {
|
|
widget->scroll = (Mouse.y - win->y - y + 1);
|
|
widget->origin.mouse_y = Mouse.y;
|
|
widget->in_drag = TRUE;
|
|
}
|
|
}
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget) && event == CPZ_MSG_WIN_MOUSE_WHEEL) {
|
|
widget->scroll += Compositor.mouse.z;
|
|
}
|
|
widget->scroll = Max(0, widget->scroll);
|
|
widget->scroll = Min(widget->height - 1, widget->scroll);
|
|
widget->value = ToI64((widget->max * 1.0) / (widget->height * 1.0) * (widget->scroll * 1.0));
|
|
if (!Mouse.left)
|
|
widget->in_drag = FALSE;
|
|
VLine2D(win->render_ctx, x + 1, y, y + widget->height, Color(190, 190, 190));
|
|
VLine2D(win->render_ctx, x + 4, y + 1, y + widget->height, Color(0, 0, 0));
|
|
HLine2D(win->render_ctx, x + 4, y, x + 9, Color(0, 0, 0));
|
|
VLine2D(win->render_ctx, x + 9, y, y + widget->height, Color(255, 255, 255));
|
|
HLine2D(win->render_ctx, x + 4, y + widget->height, x + 9,
|
|
Color(255, 255, 255));
|
|
HLine2D(win->render_ctx, x + 11, y, x + 16, Color(190, 190, 190));
|
|
HLine2D(win->render_ctx, x + 11, y + 1, x + 16, Color(255, 255, 255));
|
|
HLine2D(win->render_ctx, x + 11, y + (widget->height / 2) - 1, x + 16,
|
|
Color(190, 190, 190));
|
|
HLine2D(win->render_ctx, x + 11, y + (widget->height / 2), x + 16,
|
|
Color(255, 255, 255));
|
|
HLine2D(win->render_ctx, x + 11, y + widget->height - 1, x + 16,
|
|
Color(190, 190, 190));
|
|
HLine2D(win->render_ctx, x + 11, y + widget->height, x + 16,
|
|
Color(255, 255, 255));
|
|
ctx->blot(x, (y - 7) + widget->scroll,
|
|
umami_widget_vert_slider);
|
|
|
|
if (widget->scroll != scroll)
|
|
widget->change = TRUE;
|
|
}
|
|
|
|
U0 @umami_vert_scroll_button_repaint(Window* win, I64 x, I64 y, I64 width,
|
|
I64 height)
|
|
{
|
|
I64 i;
|
|
Context2D* ctx = win->render_ctx;
|
|
|
|
ctx->fill_rect(x, y, width, height, Color(192, 192, 192));
|
|
for (i = 0; i < height; i++) {
|
|
Line2D(win->render_ctx, x, y, x, y + height - 1, Color(192, 192, 192));
|
|
Line2D(win->render_ctx, x + 1, y, x + 1, y + height - 1,
|
|
Color(255, 255, 255));
|
|
Line2D(win->render_ctx, x + 14, y, x + width - 2, y + height - 1,
|
|
Color(128, 128, 128));
|
|
Line2D(win->render_ctx, x + 15, y, x + width - 1, y + height - 1,
|
|
Color(64, 64, 64));
|
|
}
|
|
|
|
ctx->plot(x + 1, y, Color(192, 192, 192));
|
|
ctx->plot(x + 14, y, Color(192, 192, 192));
|
|
ctx->plot(x + 15, y, Color(64, 64, 64));
|
|
|
|
Line2D(win->render_ctx, x + 1, y + 1, x + width - 2, y + 1,
|
|
Color(255, 255, 255));
|
|
ctx->plot(x + 14, y + 1, Color(128, 128, 128));
|
|
ctx->plot(x + 15, y + 1, Color(64, 64, 64));
|
|
|
|
Line2D(win->render_ctx, x + 1, y + height - 2, x + width - 2, y + height - 2,
|
|
Color(128, 128, 128));
|
|
|
|
Line2D(win->render_ctx, x, y + height - 1, x + width - 1, y + height - 1,
|
|
Color(64, 64, 64));
|
|
}
|
|
|
|
U0 @umami_vert_scrollbar_repaint(Window* win, I64 event,
|
|
VerticalScrollBarWidget* widget, I64 x,
|
|
I64 y)
|
|
{
|
|
I64 scroll = widget->scroll;
|
|
I64 segment_length = widget->length;
|
|
I64 i, j;
|
|
Bool fill = TRUE;
|
|
Context2D* ctx = win->render_ctx;
|
|
|
|
if (widget->in_drag && Mouse.y > win->y + widget->y && Mouse.y < win->y + widget->y + widget->height) {
|
|
if (widget->origin.mouse_y != Mouse.y) {
|
|
widget->scroll += (Mouse.y - widget->origin.mouse_y);
|
|
widget->origin.mouse_y = Mouse.y;
|
|
}
|
|
}
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget) && event == CPZ_MSG_WIN_LEFT_BTN_DOWN) {
|
|
if (Mouse.y > win->y + y + 16 && Mouse.y < win->y + y + widget->height - 16) {
|
|
widget->scroll = (Mouse.y - win->y - y - (widget->length / 2));
|
|
widget->origin.mouse_y = Mouse.y;
|
|
widget->in_drag = TRUE;
|
|
}
|
|
}
|
|
if (@widget_is_hovered(win->x + x, win->y + y, widget) && event == CPZ_MSG_WIN_MOUSE_WHEEL) {
|
|
widget->scroll += Compositor.mouse.z;
|
|
}
|
|
widget->scroll = Max(16, widget->scroll);
|
|
widget->scroll = Min(widget->height - 1, widget->scroll);
|
|
while (widget->scroll + segment_length > widget->height - 16)
|
|
widget->scroll--;
|
|
widget->value = ToI64((widget->max * 1.0) / (widget->height * 1.0) * (widget->scroll * 1.0));
|
|
if (!Mouse.left)
|
|
widget->in_drag = FALSE;
|
|
|
|
ctx->fill_rect(x, y, widget->width, widget->height,
|
|
Color(127, 127, 127));
|
|
|
|
for (i = 0; i < widget->width; i++) {
|
|
for (j = 16; j < widget->height - 16; j++) {
|
|
if (fill)
|
|
ctx->plot(i + x, j + y, Color(255, 255, 255));
|
|
fill = !fill;
|
|
}
|
|
fill = !fill;
|
|
}
|
|
|
|
@umami_vert_scroll_button_repaint(win, x, y, widget->width, 16);
|
|
@umami_vert_scroll_button_repaint(win, x, y + widget->height - 16,
|
|
widget->width, 16);
|
|
|
|
ctx->blot(x, y, umami_widget_sb_up_button);
|
|
ctx->blot(x, y + widget->height - 16,
|
|
umami_widget_sb_down_button);
|
|
|
|
@umami_vert_scroll_button_repaint(win, x, y + widget->scroll, widget->width,
|
|
segment_length);
|
|
|
|
if (widget->scroll != scroll)
|
|
widget->change = TRUE;
|
|
}
|
|
|
|
U0 @umami_widgets_repaint(Window* win, I64 event, I64 origin_x, I64 origin_y)
|
|
{
|
|
@window_widgets_list* widgets_list;
|
|
Widget* widget;
|
|
Context2D* ctx;
|
|
Bool widget_is_hovered;
|
|
I64 x, y;
|
|
F64 ttf_point_to_size;
|
|
no_warn ctx;
|
|
no_warn ttf_point_to_size;
|
|
|
|
if (event == CPZ_MSG_WIN_LEFT_BTN_DOWN)
|
|
win->focused_widget = NULL;
|
|
|
|
widget_is_hovered = FALSE;
|
|
widgets_list = win->widget;
|
|
while (widgets_list) {
|
|
if (widgets_list->widget) {
|
|
widget = widgets_list->widget;
|
|
x = win->x + origin_x + widget->x;
|
|
y = win->y + origin_y + widget->y;
|
|
|
|
if (@gui_window_is_hovered(win) && @widget_is_hovered(x, y, widget)) {
|
|
win->hovered_widget = widget;
|
|
widget_is_hovered = TRUE;
|
|
}
|
|
|
|
if (@widget_is_hovered(x, y, widget) && event == CPZ_MSG_WIN_LEFT_BTN_DOWN) {
|
|
win->focused_widget = widget;
|
|
win->mouse_down_widget = widget;
|
|
break;
|
|
}
|
|
}
|
|
widgets_list = widgets_list->next;
|
|
}
|
|
|
|
if (!widget_is_hovered)
|
|
win->hovered_widget = NULL;
|
|
|
|
if (!Mouse.left && win->mouse_down_widget) {
|
|
widget = win->mouse_down_widget;
|
|
x = win->x + origin_x + widget->x;
|
|
y = win->y + origin_y + widget->y;
|
|
if (@widget_is_hovered(x, y, widget) && widget->callback.clicked)
|
|
widget->callback.clicked(widget);
|
|
if (@widget_is_hovered(x, y, widget) && widget->echo) {
|
|
if (widget->echo->callback.clicked)
|
|
widget->echo->callback.clicked(widget->echo);
|
|
}
|
|
if (@widget_is_hovered(x, y, widget)) {
|
|
switch (widget->type) {
|
|
case WIDGET_TYPE_CHECKBOX:
|
|
widget(CheckBoxWidget*)->checked = !widget(CheckBoxWidget*)->checked;
|
|
break;
|
|
case WIDGET_TYPE_RADIO:
|
|
@umami_radio_select(win, widget);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (@widget_is_hovered(x, y, widget) && widget->echo) {
|
|
switch (widget->echo->type) {
|
|
case WIDGET_TYPE_CHECKBOX:
|
|
widget->echo(CheckBoxWidget*)->checked = !widget->echo(CheckBoxWidget*)->checked;
|
|
break;
|
|
case WIDGET_TYPE_RADIO:
|
|
@umami_radio_select(win, widget->echo);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
win->mouse_down_widget = NULL;
|
|
}
|
|
|
|
widgets_list = win->widget;
|
|
while (widgets_list) {
|
|
if (widgets_list->widget) {
|
|
widget = widgets_list->widget;
|
|
x = origin_x + widget->x;
|
|
y = origin_y + widget->y;
|
|
if (x > win->width - 12 || y > win->height - 12)
|
|
goto @umami_skip_widget_repaint;
|
|
switch (widget->type) {
|
|
case NULL:
|
|
break;
|
|
case WIDGET_TYPE_BUTTON:
|
|
@umami_button_repaint(win, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_CHECKBOX:
|
|
@umami_checkbox_repaint(win, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_TERMINAL:
|
|
@umami_terminal_repaint(win, widget, x, y);
|
|
if (widget->backing_store)
|
|
CopyRect2D(win->render_ctx, x, y, widget->backing_store);
|
|
break;
|
|
case WIDGET_TYPE_CONTEXT2D:
|
|
if (widget(Context2DWidget*)->ctx)
|
|
if (widget(Context2DWidget*)->fast_copy)
|
|
CopyRect2D(win->render_ctx, x, y, widget(Context2DWidget*)->ctx);
|
|
else
|
|
win->render_ctx->blot(x, y, widget(Context2DWidget*)->ctx);
|
|
break;
|
|
case WIDGET_TYPE_RADIO:
|
|
@umami_radio_repaint(win, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_INPUT:
|
|
@umami_input_repaint(win, event, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_LABEL:
|
|
@umami_label_repaint(win, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_LISTVIEW:
|
|
@umami_list_view_repaint(win, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_MENU_ITEM:
|
|
@umami_menu_item_repaint(win, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_HORZ_SLIDER:
|
|
@umami_horz_slider_repaint(win, event, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_VERT_SLIDER:
|
|
@umami_vert_slider_repaint(win, event, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_HORZ_SCROLLBAR:
|
|
//@umami_horz_scrollbar_repaint(win, event, widget, x, y);
|
|
break;
|
|
case WIDGET_TYPE_VERT_SCROLLBAR:
|
|
@umami_vert_scrollbar_repaint(win, event, widget, x, y);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (widget->change) {
|
|
if (widget->callback.change)
|
|
widget->callback.change(widget);
|
|
if (widget->echo) {
|
|
if (widget->echo->callback.change)
|
|
widget->echo->callback.change(widget);
|
|
}
|
|
widget->change = FALSE;
|
|
}
|
|
}
|
|
@umami_skip_widget_repaint : widgets_list = widgets_list->next;
|
|
}
|
|
}
|
|
|
|
U0 @umami_window_repaint(Window* win, I64 event)
|
|
{
|
|
if (!win)
|
|
return;
|
|
|
|
win->repainting = TRUE;
|
|
Context2D* ctx = win->render_ctx;
|
|
|
|
win->render_ctx->width = win->width;
|
|
win->render_ctx->height = win->height;
|
|
if (!@gui_window_flag_is_set(win, WIN_FLAGS_NOFILL))
|
|
MemSetU32(win->render_ctx->fb, Color(204, 204, 204, win->opacity),
|
|
win->width * win->height);
|
|
|
|
I64 title_bar_x;
|
|
I64 title_bar_y;
|
|
I64 title_bar_width;
|
|
I64 title_bar_height = 0;
|
|
I64 window_button_x;
|
|
I64 origin_title_width;
|
|
I64 pass;
|
|
Bool repaint;
|
|
U8 window_title[1024];
|
|
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_TITLE_BAR)) {
|
|
title_bar_height = 17;
|
|
}
|
|
|
|
I64 widget_origin_x = 4;
|
|
I64 widget_origin_y = 4;
|
|
if (title_bar_height)
|
|
widget_origin_y = 7 + title_bar_height;
|
|
|
|
@umami_widgets_repaint(win, event, widget_origin_x, widget_origin_y);
|
|
|
|
// Draw window margins
|
|
if (!@gui_window_flag_is_set(win, WIN_FLAGS_NOFILL)) {
|
|
ctx->fill_rect(0, 0, win->width, 4,
|
|
Color(204, 204, 204, win->opacity));
|
|
ctx->fill_rect(0, win->height - 4, win->width, 4,
|
|
Color(204, 204, 204, win->opacity));
|
|
ctx->fill_rect(0, 0, 4, win->height,
|
|
Color(204, 204, 204, win->opacity));
|
|
ctx->fill_rect(win->width - 5, 0, 4, win->height,
|
|
Color(204, 204, 204, win->opacity));
|
|
}
|
|
|
|
// Draw window border
|
|
Line2D(win->render_ctx, 0, 0, win->width - 1, 0,
|
|
Color(255, 255, 255, win->opacity));
|
|
Line2D(win->render_ctx, 0, 0, 0, win->height - 2,
|
|
Color(255, 255, 255, win->opacity));
|
|
Line2D(win->render_ctx, 1, win->height - 1, win->width - 1, win->height - 1,
|
|
Color(156, 156, 156, win->opacity));
|
|
Line2D(win->render_ctx, win->width - 1, 1, win->width - 1, win->height - 1,
|
|
Color(156, 156, 156, win->opacity));
|
|
|
|
title_bar_width = 0;
|
|
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_TITLE_BAR)) {
|
|
title_bar_x = 4;
|
|
title_bar_y = 4;
|
|
title_bar_width = win->width - 8;
|
|
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_ICON)) {
|
|
if (win->icon)
|
|
ctx->blot(4, 4, win->icon);
|
|
else
|
|
ctx->blot(4, 4, umami_default_icon);
|
|
title_bar_x = 24;
|
|
title_bar_width -= 20;
|
|
}
|
|
|
|
origin_title_width = title_bar_width;
|
|
|
|
repaint = FALSE;
|
|
|
|
for (pass = 0; pass < 2; pass++) {
|
|
title_bar_width = origin_title_width;
|
|
window_button_x = win->width - 20;
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_CLOSE_BUTTON)) {
|
|
if (pass) {
|
|
if (win->mouse.x > window_button_x && win->mouse.x < window_button_x + 16 && win->mouse.y > 5 && win->mouse.y < 21 && win->button.close) {
|
|
CopyRect2D(umami_title_bar_button, -32, -1,
|
|
umami_min_max_close_pressed);
|
|
if (!Mouse.left && win->callback.close)
|
|
win->callback.close(win);
|
|
} else
|
|
CopyRect2D(umami_title_bar_button, -32, -1, umami_min_max_close);
|
|
CopyRect2D(win->render_ctx, window_button_x, 5,
|
|
umami_title_bar_button);
|
|
}
|
|
if (win->left_btn_down.x > window_button_x && win->left_btn_down.x < window_button_x + 16 && win->left_btn_down.y > 5 && win->left_btn_down.y < 21 && Mouse.left && !win->button.close) {
|
|
win->button.close = TRUE;
|
|
repaint = TRUE;
|
|
}
|
|
window_button_x -= 16;
|
|
title_bar_width -= 17;
|
|
}
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_MAX_BUTTON)) {
|
|
if (pass) {
|
|
if (win->mouse.x > window_button_x && win->mouse.x < window_button_x + 16 && win->mouse.y > 5 && win->mouse.y < 21 && win->button.maximize) {
|
|
CopyRect2D(umami_title_bar_button, -16, -1,
|
|
umami_min_max_close_pressed);
|
|
if (!Mouse.left && win->callback.maximize)
|
|
win->callback.maximize(win);
|
|
}
|
|
|
|
else
|
|
CopyRect2D(umami_title_bar_button, -16, -1, umami_min_max_close);
|
|
CopyRect2D(win->render_ctx, window_button_x, 5,
|
|
umami_title_bar_button);
|
|
}
|
|
if (win->left_btn_down.x > window_button_x && win->left_btn_down.x < window_button_x + 16 && win->left_btn_down.y > 5 && win->left_btn_down.y < 21 && Mouse.left && !win->button.maximize) {
|
|
win->button.maximize = TRUE;
|
|
repaint = TRUE;
|
|
}
|
|
window_button_x -= 16;
|
|
title_bar_width -= 17;
|
|
}
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_MIN_BUTTON)) {
|
|
if (pass) {
|
|
if (win->mouse.x > window_button_x && win->mouse.x < window_button_x + 16 && win->mouse.y > 5 && win->mouse.y < 21 && win->button.minimize) {
|
|
CopyRect2D(umami_title_bar_button, 0, -1,
|
|
umami_min_max_close_pressed);
|
|
if (!Mouse.left && win->callback.minimize)
|
|
win->callback.minimize(win);
|
|
} else
|
|
CopyRect2D(umami_title_bar_button, 0, -1, umami_min_max_close);
|
|
CopyRect2D(win->render_ctx, window_button_x, 5,
|
|
umami_title_bar_button);
|
|
}
|
|
if (win->left_btn_down.x > window_button_x && win->left_btn_down.x < window_button_x + 16 && win->left_btn_down.y > 5 && win->left_btn_down.y < 21 && Mouse.left && !win->button.minimize) {
|
|
win->button.minimize = TRUE;
|
|
repaint = TRUE;
|
|
}
|
|
window_button_x -= 16;
|
|
title_bar_width -= 17;
|
|
}
|
|
}
|
|
|
|
if (!Mouse.left) {
|
|
if (win->button.close)
|
|
repaint = TRUE;
|
|
if (win->button.maximize)
|
|
repaint = TRUE;
|
|
if (win->button.minimize)
|
|
repaint = TRUE;
|
|
win->button.close = FALSE;
|
|
win->button.maximize = FALSE;
|
|
win->button.minimize = FALSE;
|
|
}
|
|
|
|
if (repaint) {
|
|
@umami_window_repaint(win, event);
|
|
return;
|
|
}
|
|
|
|
if (title_bar_width) {
|
|
win->title_bar_x = title_bar_x;
|
|
win->title_bar_width = title_bar_width;
|
|
}
|
|
|
|
StrCpy(&window_title, &win->title);
|
|
if (win == Compositor.active_win) {
|
|
HGradientRect2D(win->render_ctx, title_bar_x, title_bar_y,
|
|
title_bar_width, title_bar_height,
|
|
Color(10, 36, 106, win->opacity),
|
|
Color(165, 201, 239, win->opacity));
|
|
// Color(85, 18, 132, win->opacity),
|
|
// Color(233, 15, 240, win->opacity));
|
|
PutS2D(win->render_ctx, Compositor.theme.font.menu, title_bar_x + 4,
|
|
title_bar_y + 4, Color(255, 255, 255, win->opacity),
|
|
title_bar_width, &window_title);
|
|
} else {
|
|
ctx->fill_rect(title_bar_x, title_bar_y, title_bar_width,
|
|
title_bar_height, Color(235, 235, 235, win->opacity));
|
|
PutS2D(win->render_ctx, Compositor.theme.font.menu, title_bar_x + 4,
|
|
title_bar_y + 4, Color(156, 156, 156, win->opacity),
|
|
title_bar_width, &window_title);
|
|
}
|
|
|
|
Line2D(win->render_ctx, title_bar_x, title_bar_y,
|
|
title_bar_x + title_bar_width - 1, title_bar_y,
|
|
Color(156, 156, 156, win->opacity));
|
|
Line2D(win->render_ctx, title_bar_x, title_bar_y, title_bar_x,
|
|
title_bar_y + title_bar_height - 2,
|
|
Color(156, 156, 156, win->opacity));
|
|
|
|
Line2D(win->render_ctx, title_bar_x + title_bar_width - 1, title_bar_y,
|
|
title_bar_x + title_bar_width - 1,
|
|
title_bar_y + title_bar_height - 1,
|
|
Color(255, 255, 255, win->opacity));
|
|
Line2D(win->render_ctx, title_bar_x, title_bar_y + title_bar_height - 1,
|
|
title_bar_x + title_bar_width - 1,
|
|
title_bar_y + title_bar_height - 1,
|
|
Color(255, 255, 255, win->opacity));
|
|
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_RESIZABLE))
|
|
ctx->blot(win->width - 16, win->height - 16,
|
|
umami_corner_resize);
|
|
}
|
|
|
|
win->backing_store->width = win->render_ctx->width;
|
|
win->backing_store->height = win->render_ctx->height;
|
|
if (!@gui_window_flag_is_set(win, WIN_FLAGS_NOFILL))
|
|
MemCpyU32(win->backing_store->fb, win->render_ctx->fb,
|
|
win->render_ctx->width * win->render_ctx->height);
|
|
if (@gui_window_flag_is_set(win, WIN_FLAGS_NOFILL))
|
|
MemCpyU32(win->backing_store->fb, win->render_ctx->fb, (win->width) * 20);
|
|
|
|
win->repainting = FALSE;
|
|
}
|
|
|
|
Compositor.theme.color.active_border = Color(0, 0, 0);
|
|
Compositor.theme.color.hilight = Color(8, 33, 107);
|
|
|
|
BitmapFont* @umami_theme_bitmapfont_001 = @bitmapfont_new_from_context2d(
|
|
Image.FileToContext2D("M:/Media/Themes/Umami/BitmapFont/menu.png"),
|
|
"Eight Bit Dragon",
|
|
"`1234567890-=[]\;',./"
|
|
"~!@#\d%^&*()_+{}|:\"<>?"
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
|
@umami_theme_bitmapfont_001->line_height = 12;
|
|
BitmapFonts.Add(@umami_theme_bitmapfont_001);
|
|
|
|
BitmapFont* @umami_theme_bitmapfont_002 = @bitmapfont_new_from_context2d(
|
|
Image.FileToContext2D("M:/Media/Themes/Umami/BitmapFont/sans.png"),
|
|
"Nineteen Ninety Three",
|
|
"`1234567890-=[]\;',./"
|
|
"~!@#\d%^&*()_+{}|:\"<>?"
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
|
@umami_theme_bitmapfont_002->line_height = 10;
|
|
BitmapFonts.Add(@umami_theme_bitmapfont_002);
|
|
|
|
BitmapFont* @umami_theme_bitmapfont_003 = @bitmapfont_new_from_context2d(
|
|
Image.FileToContext2D("M:/Media/Themes/Umami/BitmapFont/monospace.png"),
|
|
"Spleen",
|
|
" !\"#\d%&'()*+,-./"
|
|
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
|
|
"abcdefghijklmnopqrstuvwxyz{|}~",
|
|
7);
|
|
@umami_theme_bitmapfont_003->line_height = 16;
|
|
BitmapFonts.Add(@umami_theme_bitmapfont_003);
|
|
|
|
Compositor.theme.font.menu = BitmapFonts.GetByName("Eight Bit Dragon");
|
|
Compositor.theme.font.sans = BitmapFonts.GetByName("Nineteen Ninety Three");
|
|
Compositor.theme.font.monospace = BitmapFonts.GetByName("Spleen");
|
|
|
|
Compositor.theme.window.min_width = 128;
|
|
Compositor.theme.window.min_height = 128;
|
|
|
|
Compositor.theme.window_repaint = &@umami_window_repaint;
|
|
|
|
Context2D** umami_pointer_wait_frames = CAlloc(sizeof(Context2D*) * 18);
|
|
Context2D* umami_pointer_wait_anim = Image.FileToContext2D("M:/Media/Themes/Umami/Pointer/wait.png");
|
|
|
|
U0 @umami_pointer_wait_anim_init()
|
|
{
|
|
I64 i;
|
|
for (i = 0; i < 18; i++) {
|
|
umami_pointer_wait_frames[i] = NewContext2D(24, 24);
|
|
umami_pointer_wait_frames[i]->blot(0, -(24 * i), umami_pointer_wait_anim);
|
|
}
|
|
DelContext2D(umami_pointer_wait_anim);
|
|
}
|
|
|
|
@umami_pointer_wait_anim_init;
|
|
Compositor.theme.pointer.wait = Animation2D.NewFromFrames(umami_pointer_wait_frames, 18, 50); |