/* by korenkonder GitHub/GitLab: korenkonder */ #include "dw.hpp" #include "print_work.hpp" class PrintWorkDebug : public PrintWork { public: PrintWorkDebug(); }; namespace dw { struct Print { p_Font* font; PrintWorkDebug* print_work; color4u8 field_10; color4u8 field_14; rectangle field_18; rectangle clip_data; float_t field_38; Print(float_t width, float_t height); ~Print(); void FillRectangle(rectangle rect); vec2 GetTextSize(prj::string& str); vec2 GetTextSize(prj::wstring& str); vec2 GetTextSize(const wchar_t* str, size_t length); void PrintText(prj::string& str, float_t pos_x, float_t pos_y); void PrintText(prj::wstring& str, float_t pos_x, float_t pos_y); void SetClipData(rectangle rect); void SetFillColor(color4u8 value); void SetFont(p_Font* value); void SetColor(color4u8 value); void sub_140301390(rectangle rect, float_t a3); void sub_140302800(); inline vec2 GetTextSize(prj::string&& str) { return GetTextSize(str); } inline vec2 GetTextSize(prj::wstring&& str) { return GetTextSize(str); } inline void PrintText(prj::string&& str, float_t pos_x, float_t pos_y) { PrintText(str, pos_x, pos_y); } inline void PrintText(prj::wstring&& str, float_t pos_x, float_t pos_y) { PrintText(str, pos_x, pos_y); } }; struct Colors { color4u8 background; color4u8 foreground; color4u8 selection_background; color4u8 selection_foreground; color4u8 selection_inactive_background; color4u8 selection_inactive_foreground; color4u8 disable_background; color4u8 disable_foreground; color4u8 title_background; color4u8 title_foreground; color4u8 title_inactive_background; color4u8 title_inactive_foreground; color4u8 active_border_color; color4u8 inactive_border_color; color4u8 focus_border_color; color4u8 border_color; color4u8 border_light_color; color4u8 border_dark_color; color4u8 popup_background; color4u8 popup_foreground; color4u8 popup_selection_background; color4u8 popup_selection_foreground; color4u8 menu_background; color4u8 menu_foreground; color4u8 menu_selection_background; color4u8 menu_selection_foreground; color4u8 button_background; color4u8 button_foreground; color4u8 button_disable_background; color4u8 button_disable_foreground; }; } struct struc_751 { vec2 mouse_pos; vec2 mouse_delta; int32_t mouse_input; int32_t modifier; int32_t field_18; int8_t field_1C; int8_t field_1D; int64_t field_20; uint8_t field_28; int32_t key_input[2]; }; namespace dw_gui_detail { struct Display { class RootKeySelection : public dw::KeyAdapter { public: }; void* __vftable; dw::Shell* selected_shell; dw::Menu* opened_menu; dw::Widget* howered_shell; dw::Widget* move_resize_shell; dw::Widget* howered_widget; dw::Widget* selected_widget; dw::Shell* focused_shell; bool set_focus; bool find_focus; prj::vector shells; prj::vector menus; dw::Widget::MouseCallbackData mouse_callback_data; dw::Widget::KeyCallbackData key_callback_data; prj::vector free_widgets; struc_751 field_C0; dw::init_data init_data; int64_t field_118; vec2 field_120; float_t field_128; struct DragBoundsControl* drag_bounds_control; prj::wstring name; RootKeySelection root_key_selection; dw::Shell* GetHoveredShell(); void MakeShellFirst(dw::Shell* value); void MakeShellLast(dw::Shell* value); void RemoveShell(dw::Shell* value); }; } static_assert(sizeof(dw_gui_detail::Display) == 0x160, "\"dw_gui_detail::Display\" struct should have a size of 0x160"); dw_gui_detail::Display*& dw_gui_detail_display = *(dw_gui_detail::Display**)0x0000000141190108; int32_t& dword_140EDA6B8 = *(int32_t*)0x0000000140EDA6B8; static void dw_gui_detail_display_set_selected_widget(dw::Widget* widget, bool set); static void sub_1402EE3C0(rectangle rect, float_t border, int32_t type, color4u8* fill_color); namespace dw { const dw::Colors& colors_default = *(dw::Colors*)0x000000141190130; static RowLayout* row_layout_vertical = new RowLayout(VERTICAL); DropDownListScrollBarSelectionListener& drop_down_list_scroll_bar_selection_listener = *(DropDownListScrollBarSelectionListener*)0x0000000140C987E8; ScrollBarTestSelectionListener& scroll_bar_test_Selection_listener = *(ScrollBarTestSelectionListener*)0x0000000140C987F0; Print*& print = *(Print**)0x00000001411900C8; dw::Colors& colors_current = *(dw::Colors*)0x00000001411901B0; p_Font& current_font = *(p_Font*)0x00000141190128; Font*& font_type_6x12 = *(Font**)0x00000001411902A0; Font*& font_type_8x12 = *(Font**)0x00000001411902A8; Font*& font_type_8x16 = *(Font**)0x00000001411902B0; Font*& font_type_10x16 = *(Font**)0x00000001411902B8; Font*& font_type_10x20 = *(Font**)0x00000001411902C0; Font*& font_type_12x24 = *(Font**)0x00000001411902C8; Font*& font_type_scroll_bar = *(Font**)0x00000001411902D0; p_Font& p_font_type_6x12 = *(p_Font*)0x00000001411901A8; p_Font& p_font_type_8x12 = *(p_Font*)0x0000000141190238; p_Font& p_font_type_8x16 = *(p_Font*)0x0000000141190240; p_Font& p_font_type_10x16 = *(p_Font*)0x0000000141190248; p_Font& p_font_type_10x20 = *(p_Font*)0x0000000141190250; p_Font& p_font_type_12x24 = *(p_Font*)0x0000000141190258; p_Font& p_font_type_scroll_bar = *(p_Font*)0x0000000141190260; prj::map& font_collection = *(prj::map*)0x00000001403024BE; Font::Font(int32_t font_handler_index, prj::string& name, bool half_width) { font = font_info(font_handler_index); this->name.assign(name); this->half_width = half_width; } Font::Font(int32_t font_handler_index, prj::string& name) { font = font_info(font_handler_index); this->name.assign(name); this->half_width = 0; } Font::~Font() { } float_t Font::GetFontGlyphHeight() { return font.glyph.y; } vec2 Font::GetFontGlyphSize() { vec2 size; size.x = GetFontGlyphWidth(); size.y = GetFontGlyphHeight(); return size; } float_t Font::GetFontGlyphWidth() { float_t glyph_height = font.glyph.x; if (half_width) return glyph_height * 0.5f; return glyph_height; } prj::string Font::GetName() { return name; } void Font::SetGlyphSize(float_t glyph_width, float_t glyph_height) { if (half_width) glyph_width *= 2.0f; font.set_glyph_size(glyph_width, glyph_height); } p_Font::p_Font() : ptr() { } p_Font::~p_Font() { } float_t p_Font::GetFontGlyphHeight() { return ptr->GetFontGlyphHeight(); } vec2 p_Font::GetFontGlyphSize() { return ptr->GetFontGlyphSize(); } float_t p_Font::GetFontGlyphWidth() { return ptr->GetFontGlyphWidth(); } prj::string p_Font::GetName() { return ptr->GetName(); } void p_Font::SetGlyphSize(float_t glyph_width, float_t glyph_height) { ptr->SetGlyphSize(glyph_width, glyph_height); } SelectionListener::SelectionListener() { } SelectionListener::~SelectionListener() { } SelectionAdapter::SelectionAdapter() { } SelectionAdapter::~SelectionAdapter() { } void SelectionAdapter::Callback(SelectionListener::CallbackData* data) { } void SelectionAdapter::Field_10(SelectionListener::CallbackData* data) { } SelectionListenerOnHook::SelectionListenerOnHook() : callback() { } SelectionListenerOnHook::SelectionListenerOnHook(SelectionListenerOnHook::CallbackFunc callback) { this->callback = callback; } SelectionListenerOnHook::~SelectionListenerOnHook() { } void SelectionListenerOnHook::Callback(SelectionListener::CallbackData* data) { callback(data->widget); } Widget::KeyCallbackData::KeyCallbackData() : widget(), modifier(), field_C(), field_D(), input() { } Widget::MouseCallbackData::MouseCallbackData() : widget(), input(), modifier() { } Widget::Widget(Widget* parent, Flags flags) : freed(), callback_data(), free_callback(), parent() { text.assign(L"NO_NAME"); this->flags = flags; font = current_font; } Widget::~Widget() { Free(); } void Widget::Draw() { } void Widget::Reset() { text.clear(); } prj::wstring Widget::GetText() { return text; } void Widget::SetText(prj::wstring& str) { text.assign(str); } int32_t Widget::KeyCallback(const Widget::KeyCallbackData& data) { return 0; } int32_t Widget::MouseCallback(const Widget::MouseCallbackData& data) { return 0; } void Widget::SetSize(const vec2& value) { rect.size = value; } vec2 Widget::GetPos() { return rect.pos; } bool Widget::CheckHitPos(const vec2& hit_pos) { rectangle rect = GetRectangle(); return rect.pos.x <= hit_pos.x && hit_pos.x < rect.pos.x + rect.size.x && rect.pos.y <= hit_pos.y && hit_pos.y < rect.size.y + rect.pos.y; } void Widget::Free() { if (freed) return; Reset(); if (free_callback) free_callback(this); freed = true; if (dw_gui_detail_display) dw_gui_detail_display->free_widgets.push_back(this); } float_t Widget::GetFontGlyphHeight() { return font.GetFontGlyphHeight(); } rectangle Widget::GetRectangle() { return { GetPos(), rect.size }; } void Widget::SetText(prj::string& str) { std::string temp_utf8(str.data(), str.size()); std::wstring temp_utf16(utf8_to_utf16(temp_utf8)); SetText(prj::wstring(temp_utf16.data(), temp_utf16.size())); } void Widget::UpdateDraw() { print->sub_140302800(); Draw(); } void Widget::sub_1402F3770(Widget* widget) { if (!widget) return; rectangle v10 = widget->GetRectangle(); rectangle v11 = dw_gui_detail_display->init_data.field_0; if (v11.pos.x > v10.pos.x || v10.pos.x + v10.size.x > v11.pos.x + v11.size.x || v11.pos.y > v10.pos.y || v10.pos.y + v10.size.y > v11.pos.y + v11.size.y) { vec2 v7 = v10.pos; if (v10.pos.x + v10.size.x >= v11.pos.x + v11.size.x) v7.x = v11.pos.x + v11.size.x - widget->rect.size.x; if (v10.pos.x < v11.pos.x || v7.x < 0.0f) v7.x = 0.0f; if (v10.pos.y + v10.size.y >= v11.pos.y + v11.size.y) v7.y = v11.pos.y + v11.size.y - widget->rect.size.y; if (v10.pos.y < v11.pos.y || v7.y < 0.0f) v7.y = 0.0f; widget->rect.pos = v7; } } Control::Control(Composite* parent, Flags flags) : Widget(parent, flags), field_68(), parent_comp(), parent_shell(), parent_menu() { parent_comp = parent; foreground_color = colors_current.foreground; background_color = colors_current.background; if (parent) { parent->controls.push_back(this); parent_shell = parent->parent_shell; } } Control::~Control() { } void Control::Draw() { } void Control::Reset() { parent_comp = 0; Widget::Reset(); } int32_t Control::KeyCallback(const Widget::KeyCallbackData& data) { if (!Field_A0()) return 0; /*if ((data.field_8 & 0x20000) && data.field_10 == 0x1000013) if (parent_menu) parent_menu->sub_1402F35E0();*/ if (data.input[0] || (data.input[1] & 0x40000000)) { Widget::KeyCallbackData v8 = data; v8.widget = parent; for (KeyListener*& i : key_listener) i->Field_8(v8); } return 0; } int32_t Control::MouseCallback(const Widget::MouseCallbackData& data) { if (!Field_A0()) return 0; /*if (dw_gui_detail_display->field_C0.field_18 == 9 && (data.field_10 & 0x40) && !data.field_14) if (parent_menu) parent_menu->sub_1402F35E0();*/ if (!data.input) return 0; if (data.input & 0xF0) { Widget::MouseCallbackData v19 = data; v19.widget = parent; v19.input = data.input & 0xF0; for (MouseListener* i : mouse_listener) i->Field_10(v19); } if (data.input & 0xF000000) { Widget::MouseCallbackData v19 = data; v19.widget = parent; v19.input = data.input & 0xF000000; for (MouseListener* i : mouse_listener) i->Field_18(v19); } if (data.input & 0xF000) { Widget::MouseCallbackData v19 = data; v19.widget = parent; v19.input = data.input & 0xF000; for (MouseListener* i : mouse_listener) i->Field_8(v19); } if (data.input & 0xF00) { Widget::MouseCallbackData v19 = data; v19.widget = parent; v19.input = data.input & 0xF00; for (MouseListener* i : mouse_listener) i->Field_20(v19); } if (data.input & 0x40000000) { Widget::MouseCallbackData v19 = data; v19.widget = parent; for (MouseMoveListener* i : mouse_move_listener) i->Field_8(v19); } return 0; } vec2 Control::GetPos() { vec2 pos = rect.pos; if (parent_comp) { rectangle parent_comp_bb = parent_comp->GetBoundingBox(); pos += parent_comp->GetPos() + parent_comp_bb.pos; if (parent_comp->v_bar) pos.y -= parent_comp->v_bar->value; } return pos; } void Control::UpdateLayout() { SetSize(GetSize()); } vec2 Control::GetSize() { return rect.size; } bool Control::Field_58() { return parent_comp->SetCurrentControl(this); } bool Control::Field_60() { return parent_comp->sub_1402F1E60(this); } void Control::SetFont(p_Font& value) { font = value; } p_Font& Control::GetFont() { return font; } void Control::SetForegroundColor(color4u8 value) { foreground_color = value; } void Control::SetBackgroundColor(color4u8 value) { background_color = value; } color4u8 Control::GetForegroundColor() { return foreground_color; } color4u8 Control::GetBackgroundColor() { return background_color; } bool Control::Field_98() { return !field_68; } bool Control::Field_A0() { if (parent_comp) return parent_comp->Field_A0() && Field_98(); return Field_98(); } void Control::Field_A8(bool value) { field_68 = !value; } Widget* Control::GetHitWidget(const vec2& hit_pos) { if (CheckHitPos(hit_pos)) return this; return 0; } void Control::SetParentMenu(Menu* menu) { if (menu) { //menu->Field_60(); parent_menu = menu; } else parent_menu = 0; } Scrollable::Scrollable(Composite* parent, Flags flags) : Control(parent, flags), h_bar(), v_bar() { if (flags & HORIZONTAL) { h_bar = new ScrollBar(this, HORIZONTAL); h_bar->SetText(L"h_bar"); } if (flags & VERTICAL) { v_bar = new ScrollBar(this, VERTICAL); v_bar->SetText(L"v_bar"); } } Scrollable::~Scrollable() { } void Scrollable::Draw() { if (v_bar) v_bar->UpdateDraw(); } void Scrollable::Reset() { if (h_bar) { h_bar->Free(); h_bar = 0; } if (v_bar) { v_bar->Free(); v_bar = 0; } Control::Reset(); } int32_t Scrollable::MouseCallback(const Widget::MouseCallbackData& data) { if (!v_bar) return Control::MouseCallback(data); bool v4 = v_bar->field_A6; int32_t ret = v_bar->MouseCallback(data); if (v4 != v_bar->field_A6) dw_gui_detail_display_set_selected_widget(v_bar, v_bar->field_A6); return ret; } void Scrollable::SetSize(const vec2& value) { Widget::SetSize(value); vec2 size = value; if (flags & FLAG_800) size -= 2.0f * 2.0f; if (v_bar) { v_bar->rect.pos.x = size.x - v_bar->rect.size.x; v_bar->rect.pos.y = 0.0f; v_bar->SetWidth(size.y); } } void Scrollable::SetFont(p_Font& value) { font = value; if (h_bar) h_bar->SetFont(value); if (v_bar) v_bar->SetFont(value); } Widget* Scrollable::GetHitWidget(const vec2& hit_pos) { if (!CheckHitPos(hit_pos)) return 0; if (v_bar && v_bar->CheckHitPos(hit_pos)) return v_bar; return this; } rectangle Scrollable::GetBoundingBox() { rectangle rect; rect.size = this->rect.size; if (flags & FLAG_800) { rect.pos = 2.0f; rect.size -= 2.0f * 2.0f; } if (v_bar) rect.size.x -= v_bar->rect.size.x; return rect; } rectangle Scrollable::GetScrollableRectangle() { vec2 pos = GetPos(); rectangle rect = GetBoundingBox(); rect.pos += pos; return rect; } Composite::Composite(Composite* parent, Flags flags) : Scrollable(parent, flags) { layout = row_layout_vertical; current_control = -1; } Composite::~Composite() { } void Composite::Draw() { rectangle rect = GetBoundingBox(); rect.pos = 0.0f; if (v_bar) rect.pos.y = v_bar->value; for (Control*& i : controls) if ((i->rect.pos.x + i->rect.size.x) > rect.pos.x && (rect.pos.x + rect.size.x) > i->rect.pos.x && (i->rect.pos.y + i->rect.size.y) > rect.pos.y && (rect.pos.y + rect.size.y) > i->rect.pos.y) i->UpdateDraw(); Scrollable::Draw(); } void Composite::Reset() { for (Control*& i : controls) i->Free(); controls.clear(); Scrollable::Reset(); } int32_t Composite::KeyCallback(const Widget::KeyCallbackData& data) { if (current_control != -1 && current_control < controls.size()) return controls[current_control]->KeyCallback(data); else return 0; } int32_t Composite::MouseCallback(const Widget::MouseCallbackData& data) { for (Control*& i : controls) if (i->CheckHitPos(data.pos)) return i->MouseCallback(data); return Scrollable::MouseCallback(data); } void Composite::SetSize(const vec2& size) { Scrollable::SetSize(size); layout->SetSize(this); } void Composite::UpdateLayout() { SetSize(GetSize()); } vec2 Composite::GetSize() { return layout->GetSize(this); } bool Composite::Field_58() { current_control = -1; return Control::Field_58(); } bool Composite::Field_60() { return current_control == -1 && Field_C0(); } Widget* Composite::GetHitWidget(const vec2& hit_pos) { if (!CheckHitPos(hit_pos)) return Scrollable::GetHitWidget(hit_pos); for (Control*& i : controls) { Widget* widget = i->GetHitWidget(hit_pos); if (widget) return widget; } return this; } bool Composite::Field_C0() { return parent_comp->sub_1402F1E60(this); } bool Composite::SetCurrentControl(Control* control) { current_control = GetControlIndex(control); return parent_comp->SetCurrentControl(this); } size_t Composite::GetControlIndex(Control* control) { for (Control*& i : controls) if (i == control) return &i - controls.data(); return -1; } void Composite::SetLayout(Layout* value) { layout = value; } bool Composite::sub_1402F1E60(Control* control) { return GetControlIndex(control) == current_control && Field_C0(); } Shell::Shell(Shell* parent, Flags flags) : Composite(parent, flags), disp(), disp_callback(), hide_callback(), field_128(), destroy(), close_button(), field_170(), field_178() { parent_shell = this; if (flags & CLOSE_BUTTON) { close_button = new ShellCloseButton(this); if (controls.size()) controls.pop_back(); } if (parent) { parent_comp = parent; parent->children.push_back(this); } dw_gui_detail_display->shells.push_back(this); } Shell::~Shell() { } void Shell::Draw() { if (!GetDisp()) return; rectangle v12 = GetRectangle(); bool active = dw_gui_detail_display->selected_shell == this; print->SetColor(active ? colors_current.active_border_color : colors_current.inactive_border_color); print->sub_140301390(v12, 2.0f); if (flags & CHECKBOX) { rectangle v11 = v12; v11.size.y = current_font.GetFontGlyphHeight() + 2.0f + 2.0f; print->sub_140301390(v11, 2.0f); rectangle v10; v10.pos = v11.pos + 2.0f; v10.size = v11.size - 2.0f * 2.0f; print->SetFillColor(active ? colors_current.title_background : colors_current.title_inactive_background); print->FillRectangle(v10); print->SetColor(active ? colors_current.title_foreground : colors_current.title_inactive_foreground); print->SetFont(¤t_font); print->SetClipData(v10); print->PrintText(GetText(), v10.pos.x, v10.pos.y); print->sub_140302800(); if (close_button) close_button->UpdateDraw(); } print->SetFillColor(colors_current.background); print->FillRectangle(GetScrollableRectangle()); print->SetColor(colors_current.foreground); Composite::Draw(); if (field_178) { field_170 = true; field_178->UpdateDraw(); field_170 = false; } } void Shell::Reset() { prj::vector vec; vec.assign(children.begin(), children.end()); children.clear(); for (Widget* i : vec) i->Free(); for (Menu* i : menus) ;//i->Free(); menus.clear(); if (close_button) { close_button->Free(); close_button = 0; } if (parent_comp) { Shell* parent_shell = dynamic_cast(parent_comp); if (parent_shell) { auto i = parent_shell->children.begin(); auto i_end = parent_shell->children.end(); while (i != i_end) if (*i == this) { parent_shell->children.erase(i); break; } } } dw_gui_detail_display->RemoveShell(this); Composite::Reset(); } int32_t Shell::KeyCallback(const Widget::KeyCallbackData& data) { if (!GetDisp()) return 0; if ((data.modifier & 0x10000) && data.input[0] == 0x100000D || (data.input[0] & 0x2000)) { Hide(); return 0; } return Composite::KeyCallback(data); } int32_t Shell::MouseCallback(const Widget::MouseCallbackData& data) { if (!GetDisp()) return 0; bool (FASTCALL * sub_140192D00)() = (bool (FASTCALL*)())0x0000000140192D00; if (data.input & 0xF0) { if (!sub_140192D00()) return 0; dw_gui_detail_display->MakeShellFirst(this); } if ((uint16_t)dw_gui_detail_display->field_C0.field_18 >= 1 && (uint16_t)dw_gui_detail_display->field_C0.field_18 <= 8) { if (data.input & 0x10) { if (sub_140192D00()) { dw_gui_detail_display->field_C0.field_18 |= 0x20000000; dw_gui_detail_display->move_resize_shell = dw_gui_detail_display->selected_shell; } return 0; } } else if ((uint16_t)dw_gui_detail_display->field_C0.field_18 == 10) { if (close_button && close_button->CheckHitPos(data.pos)) return close_button->MouseCallback(data); if (data.input & 0x10) { if (sub_140192D00()) { dw_gui_detail_display->field_C0.field_18 |= 0x40000000; dw_gui_detail_display->move_resize_shell = dw_gui_detail_display->selected_shell; } return 0; } } return Composite::MouseCallback(data); } void Shell::SetSize(const vec2& size) { Widget::SetSize(size); if (flags & CHECKBOX) { if (close_button) { vec2 size = close_button->GetSize(); close_button->rect.pos.x = rect.size.x - (size.x + 2.0f); close_button->rect.pos.y = 2.0f; } } rectangle bounding_box = GetBoundingBox(); if (v_bar) { v_bar->rect.pos.x = bounding_box.pos.x + bounding_box.size.x - v_bar->rect.size.x; v_bar->rect.pos.y = bounding_box.pos.y; v_bar->SetWidth(bounding_box.size.y); } layout->SetSize(this); } vec2 Shell::GetPos() { return rect.pos; } vec2 Shell::GetSize() { vec2 size = Composite::GetSize() + 2.0f * 2.0f; if (flags & CHECKBOX) size.y += current_font.GetFontGlyphHeight() + 2.0f; return size; } bool Shell::Field_58() { return this == dw_gui_detail_display->selected_shell && GetDisp(); } Widget* Shell::GetHitWidget(const vec2& hit_pos) { rectangle rect = GetRectangle(); if (rect.pos.x > hit_pos.x || hit_pos.x >= rect.pos.x + rect.size.x || rect.pos.y > hit_pos.y || hit_pos.y >= rect.size.y + rect.pos.y) return 0; if (close_button && close_button->CheckHitPos(hit_pos)) return close_button; Widget* widget = Composite::GetHitWidget(hit_pos); if (widget) return widget; return this; } rectangle Shell::GetBoundingBox() { rectangle rect; rect.pos = 2.0f; rect.size = this->rect.size - 2.0f * 2.0f; if (flags & CHECKBOX) { rect.size.y -= current_font.GetFontGlyphHeight() + 2.0f; rect.pos.y += current_font.GetFontGlyphHeight() + 2.0f; } if (v_bar) rect.size.x -= v_bar->rect.size.x; return rect; } bool Shell::Field_C0() { return Field_58(); } bool Shell::SetCurrentControl(Control* control) { current_control = GetControlIndex(control); return Field_58(); } void Shell::Hide() { destroy = true; } void Shell::Disp() { SetDisp(true); dw_gui_detail_display->MakeShellFirst(this); dw_gui_detail_display->focused_shell = this; dw_gui_detail_display->set_focus = true; } bool Shell::GetDisp() { return disp; } void Shell::SetDisp(bool value) { if (disp == value) return; disp = value; if (disp) { dw_gui_detail_display->MakeShellFirst(this); dw_gui_detail_display->focused_shell = this; dw_gui_detail_display->set_focus = true; if (disp_callback) disp_callback(this); } else { dw_gui_detail_display->find_focus = true; if (hide_callback) hide_callback(this); } } void Shell::sub_1402E43C0(Widget* widget) { if (!field_178) field_178 = widget; } void Shell::sub_1402E61F0(Widget* widget) { if (field_178 && field_178 == widget) field_178 = 0; } void Shell::sub_1402F38B0() { sub_1402F3770(this); Disp(); } KeyListener::KeyListener() { } KeyListener::~KeyListener() { } KeyAdapter::KeyAdapter() { } KeyAdapter::~KeyAdapter() { } void KeyAdapter::Field_8(const Widget::KeyCallbackData& data) { } void KeyAdapter::Field_10(const Widget::KeyCallbackData& data) { } void KeyAdapter::Field_18(const Widget::KeyCallbackData& data) { } MouseListener::MouseListener() { } MouseListener::~MouseListener() { } MouseAdapter::MouseAdapter() { } MouseAdapter::~MouseAdapter() { } void MouseAdapter::Field_8(const Widget::MouseCallbackData& data) { } void MouseAdapter::Field_10(const Widget::MouseCallbackData& data) { } void MouseAdapter::Field_18(const Widget::MouseCallbackData& data) { } void MouseAdapter::Field_20(const Widget::MouseCallbackData& data) { } MouseMoveListener::MouseMoveListener() { } MouseMoveListener::~MouseMoveListener() { } Layout::Layout() { } Layout::~Layout() { } FillLayout::FillLayout(Flags flags) { this->flags = flags; } FillLayout::~FillLayout() { } vec2 FillLayout::GetSize(Composite* comp) { if (!comp->controls.size()) { vec2 size = comp->rect.size; if (comp->v_bar) size.x += comp->v_bar->rect.size.x; return size; } vec2 size = 0.0f; if (flags == VERTICAL) for (Control* i : comp->controls) { vec2 _size = i->GetSize(); size.x = max_def(_size.x, size.x); } else for (Control* i : comp->controls) { vec2 _size = i->GetSize(); size.y = max_def(_size.y, size.y); } if (comp->v_bar) size.x += comp->v_bar->rect.size.x; return size; } void FillLayout::SetSize(Composite* comp) { rectangle comp_bb = comp->GetBoundingBox(); if (!comp->controls.size()) return; float_t size = (float_t)(int64_t)comp->controls.size(); if (size < 0.0f) size += (float_t)UINT64_MAX; if (flags == VERTICAL) { float_t pos = 0.0f; size = comp_bb.size.y / size; for (Control* i : comp->controls) { i->rect.pos = { 0.0f, pos }; i->SetSize({ comp_bb.size.x, size }); pos += size; } } else { float_t pos = 0.0f; size = comp_bb.size.x / size; for (Control* i : comp->controls) { i->rect.pos = { pos, 0.0f }; i->SetSize({ size, comp_bb.size.y }); pos += size; } } } GraphLayout::GraphLayout(Flags flags) { this->flags = flags; } GraphLayout::~GraphLayout() { } vec2 GraphLayout::GetSize(Composite* comp) { return comp->rect.size; } void GraphLayout::SetSize(Composite* comp) { const rectangle rect = comp->rect; for (Control* i : comp->controls) { i->rect.pos = rect.pos; i->SetSize(rect.size); } } GridLayout::GridLayout(size_t columns) : rows() { this->columns = columns; spacing = 2.0f; } GridLayout::~GridLayout() { } vec2 GridLayout::GetSize(Composite* comp) { prj::vector& controls = comp->controls; size_t controls_count = controls.size(); if (!controls_count) { vec2 size = comp->rect.size; if (comp->v_bar) size.x += comp->v_bar->rect.size.x; return size; } rows = (controls_count + columns - 1) / columns; rows = rows ? rows : 1; column_size.resize(columns); row_size.resize(rows); size_t control = 0; for (size_t row = 0; row < rows && control < controls_count; row++) for (size_t column = 0; column < columns && control < controls_count; column++, control++) { vec2 size = controls.data()[control]->GetSize(); column_size.data()[column] = max_def(size.x, column_size.data()[column]); row_size.data()[row] = max_def(size.y, row_size.data()[row]); } vec2 size; size.x = (float_t)(int64_t)(columns - 1); if (size.x < 0.0f) size.x += (float_t)UINT64_MAX; size.y = (float_t)(int64_t)(rows - 1); if (size.y < 0.0f) size.y += (float_t)UINT64_MAX; size *= spacing; float_t size_x = size.x; for (float_t i : column_size) size_x += i; size.x = size_x; float_t size_y = size.y; for (float_t i : row_size) size_y += i; size.y = size_y; if (comp->v_bar) size.x += comp->v_bar->rect.size.x; return size; } void GridLayout::SetSize(Composite* comp) { prj::vector& controls = comp->controls; size_t controls_count = controls.size(); rectangle comp_bb = comp->GetBoundingBox(); if (!controls_count) return; if (controls_count == 1) { Scrollable* scrollable = dynamic_cast(comp->controls.front()); if (scrollable) { scrollable->rect.pos = 0.0f; scrollable->SetSize(comp_bb.size); return; } } size_t control = 0; vec2 pos = 0.0f; for (size_t row = 0; row < rows && control < controls_count; row++) { vec2 _pos = pos; for (size_t column = 0; column < columns && control < controls_count; column++, control++) { comp->controls.data()[control]->rect.pos = _pos; comp->controls.data()[control]->SetSize({ column_size.data()[column], row_size.data()[row] }); _pos.x += column_size.data()[column] + spacing.x; } pos.y += row_size.data()[row] + spacing.y; } } RowLayout::RowLayout(Flags flags) { this->flags = flags; spacing = 2.0f; } RowLayout::~RowLayout() { } vec2 RowLayout::GetSize(Composite* comp) { if (!comp->controls.size()) { vec2 size = comp->rect.size; if (comp->v_bar) size.x += comp->v_bar->rect.size.x; return size; } vec2 size = 0.0f; if (flags == VERTICAL) { for (Control* i : comp->controls) { vec2 _size = i->GetSize(); size.x = max_def(_size.x, size.x); size.y += _size.y + spacing; } size.y -= spacing; } else { for (Control* i : comp->controls) { vec2 _size = i->GetSize(); size.x += _size.x + spacing; size.y = max_def(_size.y, size.y); } size.x -= spacing; } if (comp->v_bar) size.x += comp->v_bar->rect.size.x; return size; } void RowLayout::SetSize(Composite* comp) { rectangle comp_bb = comp->GetBoundingBox(); if (!comp->controls.size()) return; if (comp->controls.size() == 1) { Scrollable* scrollable = dynamic_cast(comp->controls.front()); if (scrollable) { scrollable->rect.pos = 0.0f; scrollable->SetSize(comp_bb.size); return; } } float_t pos = 0.0f; if (flags == VERTICAL) for (Control*& i : comp->controls) { i->rect.pos = { 0.0f, pos }; float_t size_y = i->GetSize().y; i->SetSize({ comp_bb.size.x, size_y }); pos += size_y + spacing; } else for (Control*& i : comp->controls) { i->rect.pos = { pos, 0.0f }; float_t size_x = i->GetSize().x; i->SetSize({ size_x, comp_bb.size.y }); pos += size_x + spacing; } } Group::Group(Composite* parent, Flags flag) : Composite(parent, (Flags)(flags & ~(VERTICAL | HORIZONTAL))) { } Group::~Group() { } void Group::Draw() { print->SetFont(&font); rectangle rect = GetRectangle(); float_t half_glyph_height = prj::floorf(font.GetFontGlyphHeight() * 0.5f); rect.pos.y += half_glyph_height; rect.size.y -= half_glyph_height; print->SetColor(colors_current.border_color); print->sub_140301390(rect, 2.0f); rect.size += -1.0f; print->SetColor(color_black); print->sub_140301390(rect, 1.0f); if (GetText().size()) { rectangle rect = GetRectangle(); rect.pos.x += 2.0f; rect.pos.y = rect.pos.y; rect.size.x += 2.0f * -2.0f; rect.size.y = font.GetFontGlyphHeight(); vec2 text_size = print->GetTextSize(GetText()); rect.size.x = min_def(text_size.x, rect.size.x); print->SetFillColor(colors_current.background); print->FillRectangle(rect); print->SetColor(colors_current.foreground); print->SetClipData(rect); print->PrintText(GetText(), rect.pos.x, rect.pos.y); } Composite::Draw(); } vec2 Group::GetSize() { vec2 size = Composite::GetSize(); size.x += 2.0f * 2.0f; size.y += font.GetFontGlyphHeight() + 2.0f; return size; } rectangle Group::GetBoundingBox() { float_t glyph_height = font.GetFontGlyphHeight(); rectangle rect = Scrollable::GetBoundingBox(); rect.pos.x += 2.0f; rect.pos.y += glyph_height; rect.size.x -= 2.0f * 2.0f; rect.size.y -= glyph_height + 2.0f; return rect; } Label::Label(Composite* parent, Flags flags) : Control(parent, flags) { } Label::~Label() { } void Label::Draw() { rectangle rect = GetRectangle(); print->SetFont(&font); vec2 text_size = print->GetTextSize(GetText()); float_t pos_x; if (flags & FLAG_4000) pos_x = rect.pos.x; else if (flags & FLAG_20000) pos_x = rect.pos.x + rect.size.x - text_size.x; else pos_x = rect.pos.x + (rect.size.x - text_size.x) * 0.5f; float_t pos_y = rect.pos.y + (rect.size.y - text_size.y) * 0.5f; print->SetColor(Field_A0() ? colors_current.foreground : colors_current.disable_foreground); print->SetClipData(rect); print->SetFont(&font); print->PrintText(GetText(), pos_x, pos_y); } vec2 Label::GetSize() { print->SetFont(&font); return print->GetTextSize(text) + 2.0f * 2.0f; } Button::Button(Composite* parent, Flags flags) : Control(parent, flags), value(), callback(), field_100() { field_104 = 1; SetSize(GetSize()); } Button::~Button() { } void Button::Draw() { print->SetFont(&this->font); vec2 checkbox_size = print->GetTextSize(L"[X]"); rectangle v6 = GetRectangle(); rectangle v8 = v6; if (flags & (FLAG_8 | MULTISELECT)) { int32_t v3; if ((field_100 & 0x01) && (field_100 & 0x02)) { v3 = 4; v8.pos.x += 2.0f; v8.size.x += -2.0f; } else v3 = 2; sub_1402EE3C0(v6, 2.0f, v3, &colors_current.button_background); v8.pos += 2.0f; v8.size -= 2.0f * 2.0f; } else if (flags & CHECKBOX) { print->SetColor(colors_current.button_foreground); print->SetClipData(v8); print->PrintText(value ? L"[X]" : L"[ ]", v8.pos.x, v8.pos.y); v8.size.x -= checkbox_size.x; v8.pos.x += checkbox_size.x; } else if (flags & RADIOBUTTON) { print->SetColor(colors_current.button_foreground); print->SetClipData(v8); print->PrintText(value ? L"(*)" : L"( )", v8.pos.x, v8.pos.y); v8.size.x -= checkbox_size.x; v8.pos.x += checkbox_size.x; } prj::wstring text = GetText(); print->SetFont(&font); vec2 text_size = print->GetTextSize(text); if (!(flags & (CHECKBOX | RADIOBUTTON))) { float_t v5 = (v8.size.x - text_size.x) * 0.5f; v8.pos.x = v8.pos.x + v5; v8.size.x = v8.size.x + (v5 * -2.0f); } if (Field_A0()) { print->SetColor(colors_current.button_foreground); print->SetClipData(v8); print->PrintText(text, v8.pos.x, v8.pos.y); if (Field_60()) { print->SetColor(colors_current.focus_border_color); print->sub_140301390(v8, 1.0); } } else { print->SetColor(colors_current.button_disable_foreground); print->SetClipData(v8); print->PrintText(text, v8.pos.x, v8.pos.y); } } int32_t Button::KeyCallback(const Widget::KeyCallbackData& data) { if (!Field_A0()) return 0; if (data.input[0] != 0x0D && data.input[0] != 0x20) return Control::KeyCallback(data); if (flags & CHECKBOX) SetValue(!value); else if (flags & RADIOBUTTON) SetValue(true); if (callback) callback(this); SelectionListener::CallbackData callback_data = this; for (SelectionListener*& i : selection_listeners) i->Callback(&callback_data); field_100 &= ~0x102; return Control::KeyCallback(data); } int32_t Button::MouseCallback(const Widget::MouseCallbackData& data) { if (!Field_A0()) return 0; field_100 &= ~0x01; if (CheckHitPos(data.pos)) field_100 |= 0x01; if (field_100 & 0x01) { if ((data.input & 0xF0) && !Field_60()) Field_58(); if (data.input & 0x100) { if (field_100 & 0x02) field_100 = (field_100 & ~0x02) | 0x100; } else if (data.input & 0x10) field_100 |= 0x2; } if (field_100 & 0x100) { field_104--; if (flags & CHECKBOX) SetValue(!value); else if (flags & RADIOBUTTON) SetValue(true); if (callback) callback(this); SelectionListener::CallbackData callback_data = this; for (SelectionListener*& i : selection_listeners) i->Callback(&callback_data); field_100 &= ~0x102; field_104 = 1; } return Control::MouseCallback(data); } vec2 Button::GetSize() { print->SetFont(&font); vec2 size = print->GetTextSize(text); if (flags & FLAG_8) { size.x += 2.0f; size.x += 2.0f * 2.0f; size.y += 2.0f * 2.0f; } else if (flags & RADIOBUTTON) { print->SetFont(&font); size.x += print->GetTextSize("(X)").x; } else if (flags & CHECKBOX) { print->SetFont(&font); size.x += print->GetTextSize("[X]").x; } return size; } void Button::AddSelectionListener(SelectionListener* value) { selection_listeners.push_back(value); } void Button::SetValue(bool value) { this->value = value; if (!(flags & RADIOBUTTON)) return; for (Control* i : parent_comp->controls) { Button* button = (Button*)dynamic_cast(i); if (button && button != this && button->flags & RADIOBUTTON) button->value = false; } } List::List(Composite* parent, Flags flags) : Scrollable(parent, flags), field_148() { hovered_item = -1; selected_item = -1; max_items = -1; if (flags & VERTICAL) max_items = 10; } List::~List() { } void List::Draw() { if (flags & FLAG_800) { rectangle rect; color4u8* v3; if (Field_A0()) { rect = GetRectangle(); v3 = 0; } else { rect = GetRectangle(); v3 = &colors_current.disable_background; } sub_1402EE3C0(rect, 2.0f, 2, v3); } Scrollable::Draw(); float_t glyph_height = GetFontGlyphHeight(); float_t pos_y = 0.0f; if (v_bar) pos_y = prj::floorf(v_bar->value); print->SetFont(&font); rectangle v21 = GetScrollableRectangle(); pos_y = -pos_y; print->SetClipData(v21); size_t items_count = items.size(); for (size_t i = 0; i < items_count; i++, pos_y += glyph_height) { rectangle v22; v22.pos.x = v21.pos.x; v22.pos.y = v21.pos.y + pos_y; v22.size.x = v21.size.x; v22.size.y = glyph_height; if (v21.pos.x + v21.size.x <= v21.pos.x || v21.pos.y + pos_y + glyph_height <= v21.pos.y || v21.size.y + v21.pos.y <= v21.pos.y + pos_y) continue; bool selected = false; bool hovered = false; color4u8 color; if (!field_148) { if ((flags & MULTISELECT) && selected_item == i || (flags & FLAG_2) && selections[i]) selected = true; if (Field_60()) hovered = hovered_item == i; if (selected) { print->SetFillColor(colors_current.selection_background); print->FillRectangle(v22); color = colors_current.selection_foreground; } else if (Field_A0()) color = colors_current.foreground; else color = colors_current.disable_foreground; } else { if (hovered_item == i) { print->SetFillColor(colors_current.popup_selection_background); print->FillRectangle(v22); color = colors_current.popup_selection_foreground; } else if (field_148) color = colors_current.popup_foreground; else if (Field_A0()) color = colors_current.foreground; else color = colors_current.disable_foreground; } print->SetColor(color); print->SetFont(&font); print->PrintText(items[i], v21.pos.x, pos_y + v21.pos.y); if (hovered) { print->SetColor(colors_current.focus_border_color); print->sub_140301390(v22, 1.0f); } } } void List::Reset() { items.clear(); items.shrink_to_fit(); selections.clear(); Scrollable::Reset(); } int32_t List::KeyCallback(const Widget::KeyCallbackData& data) { size_t items_count = items.size(); if (!data.input[0] || !items_count) return Control::KeyCallback(data); size_t hovered_item = this->hovered_item; SelectionListener::CallbackData v12 = v_bar; size_t max_items_visible = GetMaxItemsVisible(); switch (data.input[0]) { case 0x1000001: if (hovered_item == -1) hovered_item = 0; else if (hovered_item) hovered_item--; if (sub_1402F1F20(hovered_item) && !sub_1402F1F20(hovered_item)) v12.field_8 = data.input[0]; break; case 0x1000002: if (hovered_item == -1) hovered_item = 0; else if (hovered_item < items_count - 1) hovered_item++; if (sub_1402F1F20(hovered_item) && !sub_1402F1F20(hovered_item)) v12.field_8 = data.input[0]; break; case 0x1000005: if (hovered_item == -1 || hovered_item < max_items_visible) hovered_item = 0; else hovered_item -= max_items_visible; v12.field_8 = data.input[0]; break; case 0x1000006: if (hovered_item == -1) hovered_item = 0; else if (max_items_visible >= items_count || hovered_item > items_count - max_items_visible - 1) hovered_item = items_count - 1; else hovered_item += max_items_visible; v12.field_8 = data.input[0]; break; case 0x1000007: hovered_item = 0; v12.field_8 = data.input[0]; break; case 0x1000008: hovered_item = items_count - 1; v12.field_8 = data.input[0]; break; } if (hovered_item < items_count && hovered_item != -1 && this->hovered_item != hovered_item) { SetItemIndex(hovered_item); SelectionListener::CallbackData callback_data = parent; for (SelectionListener*& i : selection_listeners) i->Callback(&callback_data); if (v12.field_8 && v_bar) ScrollBar::sub_1402E6CC0(v12); sub_1402F9C90(hovered_item); } return Control::KeyCallback(data); } int32_t List::MouseCallback(const Widget::MouseCallbackData& data) { if (!Field_A0() || !CheckHitPos(data.pos)) return 0; if (!field_148 && (data.input & 0xF0) && !Field_60()) Field_58(); rectangle v27 = GetScrollableRectangle(); if (v27.pos.x > data.pos.x || data.pos.x >= v27.size.x + v27.pos.x || v27.pos.y > data.pos.y || data.pos.y >= v27.size.y + v27.pos.y) return Scrollable::MouseCallback(data); size_t hovered_item = this->hovered_item; if (field_148 && (data.input & 0x40000000) || (data.input & 0x10)) { float_t glyph_height = GetFontGlyphHeight(); float_t v10 = (float_t)sub_1402EF570(); if (v10 < 0.0f) v10 += (float_t)UINT64_MAX; size_t v11 = 0; float_t v12 = (data.pos.y - (v27.pos.y - v10 * glyph_height)) / glyph_height; if (v12 >= (float_t)INT64_MAX) { v12 -= (float_t)INT64_MAX; if (v12 < (float_t)INT64_MAX) v11 = 0x8000000000000000u; } size_t hovered_item = v11 + (int64_t)v12; if (hovered_item < items.size()) this->hovered_item = hovered_item; } if (hovered_item < this->items.size()) { if (data.input & 0x10) { if (data.modifier & 0x20000) { ResetSelectedItem(); size_t end = this->hovered_item; size_t begin = hovered_item; if (end < begin) { begin = this->hovered_item; end = hovered_item; } SetSelectedItems(begin, end); } else if (data.modifier & 0x40000) { if (CheckItemSelected(hovered_item)) UnsetSelectedItem(hovered_item); else SetSelectedItem(hovered_item); } else { ResetSelectedItem(); SetSelectedItem(this->hovered_item); } SelectionListener::CallbackData v26 = parent; for (SelectionListener*& i : selection_listeners) i->Callback(&v26); } if (data.input & 0x1000) { SelectionListener::CallbackData v26 = parent; for (SelectionListener*& i : selection_listeners) i->Field_10(&v26); } } if ((data.input & 0x100000) || (data.input & 0x200000)) return Scrollable::MouseCallback(data); return 0; } void List::SetSize(const vec2& size) { Scrollable::SetSize(size); SetScrollBarParams(); } vec2 List::GetSize() { print->SetFont(&font); float_t max_text_size = 0.0f; for (prj::wstring& i : items) { vec2 text_size = print->GetTextSize(i); max_text_size = max_def(text_size.x, max_text_size); } size_t max_items_visible = GetMaxItemsVisible(); size_t items_count = items.size(); float_t glyph_height = font.GetFontGlyphHeight(); float_t v14 = (float_t)(int64_t)min_def(max_items_visible, items_count); if (v14 < 0.0f) v14 += (float_t)UINT64_MAX; vec2 size = { max_text_size, glyph_height * v14 }; if (v_bar) size.x += v_bar->rect.size.x; if (flags & FLAG_800) size += 2.0f * 2.0f; return size; } void List::AddItem(const prj::string& str) { std::string temp_utf8(str.data(), str.size()); std::wstring temp_utf16(utf8_to_utf16(temp_utf8)); items.push_back(prj::wstring(temp_utf16.data(), temp_utf16.size())); } void List::AddItem(const prj::wstring& str) { items.push_back(str); } void List::AddSelectionListener(SelectionListener* value) { selection_listeners.push_back(value); } void List::Callback(SelectionListener::CallbackData* data) { if (data->widget) for (SelectionListener*& i : selection_listeners) i->Callback(data); } bool List::CheckItemSelected(size_t index) { if (index >= items.size()) return false; else if (flags & MULTISELECT) return index == selected_item; return selections[index] != 0; } void List::ClearItems() { items.clear(); selections.clear(); hovered_item = -1; selected_item = -1; } prj::string List::GetItemStr(size_t index) const { std::wstring temp_utf16(items[index].data(), items[index].size()); std::string temp_utf8(utf16_to_utf8(temp_utf16)); return prj::string(temp_utf8.data(), temp_utf8.size()); } prj::wstring List::GetItem(size_t index) const { return items[index]; } size_t List::GetItemCount() { return items.size(); } size_t List::GetMaxItemsVisible() { if (!v_bar) return items.size(); else if (max_items >= items.size()) return items.size(); return max_items; } void List::ResetSelectedItem() { if (flags & MULTISELECT) selected_item = -1; else for (int32_t& i : selections) i = 0; } void List::SetMaxItems(size_t value) { max_items = value; } void List::SetScrollBarParams() { rectangle bb = GetBoundingBox(); if (v_bar) v_bar->SetParams(bb.size.y, font.GetFontGlyphHeight(), items.size()); } void List::SetSelectedItem(size_t index) { if (index < items.size()) if (flags & MULTISELECT) selected_item = index; else selections[index] = 1; } void List::SetSelectedItems(size_t begin, size_t end) { if (end < begin || end >= items.size()) return; if (flags & MULTISELECT) { if (begin == end) selected_item = begin; } else for (size_t i = begin; i <= end; i++) selections[i] = 1; } void List::UnsetSelectedItem(size_t index) { if (index < items.size()) if (flags & MULTISELECT) selected_item = -1; else selections[index] = 0; } int64_t List::sub_1402EF570() { float_t glyph_height = GetFontGlyphHeight(); float_t v4 = 0.0f; if (v_bar) v4 = prj::floorf(v_bar->value / glyph_height); int64_t v6 = 0; if (v4 >= (float_t)INT64_MAX) { v4 -= (float_t)INT64_MAX; if (v4 < (float_t)INT64_MAX) v6 = 0x8000000000000000u; } return v6 + (int64_t)v4; } bool List::sub_1402F1F20(size_t index) { size_t max_items_visible = GetMaxItemsVisible(); size_t v5 = sub_1402EF570(); return max_items_visible >= items.size() || v5 <= index && index < max_items_visible + v5; } void List::sub_1402F9680(int64_t index) { if (!v_bar) return; float_t glyph_height = GetFontGlyphHeight(); size_t max_items_visible = GetMaxItemsVisible(); size_t items_count = items.size(); if (items_count <= max_items_visible) return; float_t value = 0.0f; if (index != -1) { if (items_count - index >= max_items_visible) value = (float_t)index; else value = (float_t)(items_count - max_items_visible); if (value < 0.0f) value += (float_t)UINT64_MAX; value *= glyph_height; } v_bar->SetValue(value); } void List::sub_1402F9C90(size_t index) { if (!sub_1402F1F20(index)) sub_1402F9680(index); } ListBox::ListBox(Composite* parent, Flags flags) : Composite(parent, flags), list(), field_118() { list = new List(this, flags); list->field_148 = true; list->SetText(L"ddl"); list->parent = this; if (list->v_bar) { list->v_bar->parent = this; list->v_bar->AddSelectionListener(&drop_down_list_scroll_bar_selection_listener); } } ListBox::~ListBox() { } void ListBox::Draw() { if (!parent_shell->field_170) { rectangle v13 = GetRectangle(); sub_1402EE3C0(v13, 2.0, 4, Field_A0() ? &colors_current.background : &colors_current.disable_background); v13.pos = v13.pos + 2.0f; v13.size = v13.size - 2.0f * 2.0f; rectangle v14 = v13; vec2 glyph_size = font.GetFontGlyphSize(); rectangle v15; v15.pos = v13.pos + v13.size - glyph_size; v15.size = glyph_size; print->SetFont(&font); print->SetColor(colors_current.foreground); print->sub_140301390(v15, 1.0f); print->SetClipData(v15); print->PrintText(L"v", v15.pos.x, v15.pos.y); v14.size.x -= glyph_size.x; if (Field_60()) { print->SetColor(colors_current.focus_border_color); print->sub_140301390(v14, 1.0f); } if (list->selected_item < list->items.size()) { print->SetFont(&font); print->SetColor(Field_A0() ? colors_current.foreground : colors_current.disable_foreground); print->SetClipData(v14); print->PrintText(GetItem(list->selected_item), v14.pos.x, v14.pos.y); } } if (parent_shell->field_170 && field_118) { rectangle rect = GetListRectangle(); print->SetFillColor(colors_current.popup_background); print->FillRectangle(rect); list->UpdateDraw(); print->SetColor(color_black); print->sub_140301390(rect, 1.0f); } } void ListBox::Reset() { Composite::Reset(); } int32_t ListBox::KeyCallback(const Widget::KeyCallbackData& data) { if (!Field_A0()) return 0; list->KeyCallback(data); if (field_118 && data.input[0] == 0x0D) sub_1402E4F40(); return 0; } int32_t ListBox::MouseCallback(const Widget::MouseCallbackData& data) { if (!Field_A0()) return 0; if ((data.input & 0xF0) && !Field_60()) Field_58(); if (field_118) { list->MouseCallback(data); if ((data.input & 0x10) && (!list->CheckHitPos(data.pos) || ListBox::sub_1402EC8C0(list->GetScrollableRectangle(), data.pos))) { sub_1402E4F40(); return 0; } } else if (CheckHitPos(data.pos) && (data.input & 0x10)) sub_1402E4F90(); return 0; } vec2 ListBox::GetSize() { vec2 size = list->GetSize(); size.x += font.GetFontGlyphWidth(); size.y = font.GetFontGlyphHeight(); return size + 2.0f * 2.0f; } void ListBox::SetFont(p_Font& value) { Scrollable::SetFont(value); if (list) list->SetFont(value); } rectangle ListBox::GetListRectangle() { return list->GetRectangle(); } void ListBox::sub_1402E4440() { rectangle rect = GetRectangle(); vec2 size = list->GetSize(); vec2 pos; if (dw_gui_detail_display->init_data.field_0.pos.y + dw_gui_detail_display->init_data.field_0.size.y > rect.pos.y + rect.size.y + size.y) pos.y = rect.size.y; else pos.y = -size.y; list->rect.pos = pos; list->SetSize({ max_def(rect.size.x, size.x), size.y }); } void ListBox::sub_1402E4F40() { parent_shell->sub_1402E61F0(this); dw_gui_detail_display_set_selected_widget(this, false); list->hovered_item = list->selected_item; field_118 = false; } void ListBox::sub_1402E4F90() { field_118 = true; sub_1402E4440(); list->hovered_item = list->selected_item; list->sub_1402F9C90(list->selected_item); dw_gui_detail_display_set_selected_widget(this, true); parent_shell->sub_1402E43C0(this); } bool ListBox::sub_1402EC8C0(rectangle rect, vec2 pos) { return (rect.pos.x <= pos.x && pos.x < rect.pos.x + rect.size.x) && (rect.pos.y <= pos.y && pos.y < rect.pos.y + rect.size.y); } ScrollBar::ScrollBar(Control* parent, Flags flags) : Widget(parent, flags), value(), min(), field_A0(), field_A5(), field_A6() { parent_control = parent; max = 100.0f; grab = 10.0f; step = 1.0f; step_fast = 10.0f; round = true; font = p_font_type_scroll_bar; SetSize({ 8.0f, 8.0f }); } ScrollBar::~ScrollBar() { } void ScrollBar::Draw() { rectangle v14 = GetRectangle(); print->SetColor(colors_current.border_color); print->sub_140301390(v14, 1.0f); print->SetClipData(v14); print->SetColor(Field_60() ? colors_current.foreground : colors_current.disable_foreground); print->SetFont(&font); vec2 glyph_size = font.GetFontGlyphSize(); rectangle v16; v16.pos = v14.pos; v16.size = glyph_size; if (flags & HORIZONTAL) { print->sub_140301390(v16, 1.0f); print->PrintText(L"<", v14.pos.x, v14.pos.y); v16.pos.x = v14.size.x + v14.pos.x - glyph_size.x; print->sub_140301390(v16, 1.0f); print->PrintText(L">", v14.size.x + v14.pos.x - v16.size.x, v14.pos.y); rectangle v18 = v14; v18.pos.x = v14.pos.x + glyph_size.x; v18.size.x = v14.size.x - v16.size.x * 2.0f; print->SetFillColor(color_grey); print->FillRectangle(v18); vec2 v11 = sub_1402E4790(); rectangle v17 = v18; v17.pos.x = v11.x + v18.pos.x; v17.size.x = v11.y; print->SetFillColor(colors_current.background); print->FillRectangle(v17); print->sub_140301390(v17, 1.0f); print->PrintText(L"#", v17.size.x * 0.5f + v17.pos.x - glyph_size.x * 0.5f, v17.pos.y); } else { print->sub_140301390(v16, 1.0f); print->PrintText(L"A", v14.pos.x, v14.pos.y); v16.pos.y = v14.size.y + v14.pos.y - glyph_size.y; print->sub_140301390(v16, 1.0f); print->PrintText(L"V", v14.pos.x, v14.size.y + v14.pos.y - v16.size.y); rectangle v18 = v14; v18.pos.y = v14.pos.y + glyph_size.y; v18.size.y = v14.size.y - v16.size.y * 2.0f; print->SetFillColor(color_grey); print->FillRectangle(v18); vec2 v11 = sub_1402E4790(); rectangle v17 = v18; v17.pos.y = v11.x + v18.pos.y; v17.size.y = v11.y; print->SetFillColor(colors_current.background); print->FillRectangle(v17); print->sub_140301390(v17, 1.0f); print->PrintText(L"#", v17.pos.x, v17.size.y * 0.5f + v17.pos.y - glyph_size.y * 0.5f); } } int32_t ScrollBar::KeyCallback(const Widget::KeyCallbackData& data) { if (!Field_60()) return 0; SelectionListener::CallbackData v6 = sub_1402E5140(data); if (v6.widget) for (SelectionListener*& i : selection_listeners) i->Callback(&v6); return 0; } int32_t ScrollBar::MouseCallback(const Widget::MouseCallbackData& data) { if (!Field_60()) return 0; bool v4 = field_A6; SelectionListener::CallbackData v8 = sub_1402E5380(data); if (v4 != field_A6) dw_gui_detail_display_set_selected_widget(this, field_A6); if (v8.widget) for (SelectionListener*& i : selection_listeners) i->Callback(&v8); return 0; } void ScrollBar::SetSize(const vec2& size) { if (flags & HORIZONTAL) { rect.size.x = size.x; rect.size.y = font.GetFontGlyphHeight(); } else { rect.size.x = font.GetFontGlyphWidth(); rect.size.y = size.y; } } vec2 ScrollBar::GetPos() { vec2 pos = rect.pos; Control* control = GetParentControl(); if (control) { pos += control->GetPos(); Scrollable* scrollable = dynamic_cast(control); if (scrollable && scrollable->flags & FLAG_800) pos += 2.0f; } return pos; } Control* ScrollBar::GetParentControl() { return parent_control; } void ScrollBar::SetFont(p_Font& value) { font = value; } bool ScrollBar::Field_58() { return !field_A5; } bool ScrollBar::Field_60() { return GetParentControl()->Field_A0() && Field_58(); } void ScrollBar::Field_68(bool value) { field_A5 = !value; } void ScrollBar::SetGrab(float_t value) { grab = value; } void ScrollBar::SetMax(float_t value) { max = value; } void ScrollBar::SetMin(float_t value) { min = value; } void ScrollBar::SetParams(float_t value, float_t min, float_t max, float_t grab, float_t step, float_t step_fast) { this->value = value; this->grab = grab; this->min = min; this->step_fast = step_fast; this->max = max; this->step = step; } void ScrollBar::SetParams(float_t size, float_t step, size_t items_count) { if (!items_count) return; float_t v5 = (float_t)(int64_t)items_count; if (v5 < 0.0f) v5 += (float_t)UINT64_MAX; float_t v6 = v5 * step; if (v6 > size) { min = 0.0f; max = v6 - size; grab = (size / v6) * (v6 - size); ScrollBar::SetValue(value); this->step = step; size_t v8 = 0; float_t v9 = size / step; if (v9 >= (float_t)INT64_MAX) { v9 -= (float_t)INT64_MAX; if (v9 < (float_t)INT64_MAX) v8 = INT64_MIN; } float_t v11 = (float_t)(int64_t)(v8 + (int64_t)v9); if (v11 < 0.0f) v11 += (float_t)UINT64_MAX; step_fast = v11 * step; } else { min = 0.0f; max = 0.0f; grab = v6; SetValue(value); this->step = step; step_fast = v6; } } void ScrollBar::SetRound(bool value) { round = value; } void ScrollBar::SetValue(float_t value) { value = clamp_def(value, min, max); if (round) this->value = prj::roundf(value / step) * step; else this->value = value; } void ScrollBar::SetWidth(float_t value) { vec2 glyph_size = font.GetFontGlyphSize(); if (flags & HORIZONTAL) { rect.size.x = value; rect.size.y = glyph_size.y; } else { rect.size.x = glyph_size.x; rect.size.y = value; } } void ScrollBar::AddSelectionListener(SelectionListener* value) { selection_listeners.push_back(value); } vec2 ScrollBar::sub_1402E4790() { vec2 glyph_size = font.GetFontGlyphSize(); float_t _glyph_size; float_t size; if (flags & HORIZONTAL) { _glyph_size = glyph_size.x; size = rect.size.x; } else { _glyph_size = glyph_size.y; size = rect.size.y; } size -= _glyph_size * 2.0f; float_t range = max - min; if (range > 0.0) { float_t v10 = max_def((grab * (1.0f / range)) * size, 20.0f); float_t v11 = ((value - min) * (1.0f / range)) * (size - v10); return { v11, v10 }; } return { 0.0f, size }; } SelectionListener::CallbackData ScrollBar::sub_1402E5140(const Widget::KeyCallbackData& key_callback_data) { SelectionListener::CallbackData callback_data; switch (key_callback_data.input[0]) { case 0x1000001: case 0x1000002: case 0x1000005: case 0x1000006: case 0x1000007: case 0x1000008: callback_data.field_8 = key_callback_data.input[0]; break; case 0x1000003: callback_data.field_8 = 0x1000001; break; case 0x1000004: callback_data.field_8 = 0x1000002; break; default: break; } if (callback_data.field_8 != -1) { callback_data.widget = this; ScrollBar::sub_1402E6CC0(callback_data); callback_data.widget = parent; } return callback_data; } SelectionListener::CallbackData ScrollBar::sub_1402E5380(const Widget::MouseCallbackData& mouse_callback_data) { if (field_A6) { SelectionListener::CallbackData callback_data; if ((mouse_callback_data.input & 1) != 0) { callback_data.field_8 = 1; callback_data.mouse_pos = mouse_callback_data.pos; } else { callback_data.field_8 = 0; field_A6 = false; } if (callback_data.field_8 != -1) { callback_data.widget = this; ScrollBar::sub_1402E6CC0(callback_data); callback_data.widget = this->parent; } return callback_data; } SelectionListener::CallbackData callback_data; if (mouse_callback_data.input & 0x100000) callback_data.field_8 = 0x1000071; else if (mouse_callback_data.input & 0x200000) callback_data.field_8 = 0x1000072; if (callback_data.field_8 == -1 && !CheckHitPos(mouse_callback_data.pos)) return callback_data; vec2 glyph_size = font.GetFontGlyphSize(); rectangle rect = GetRectangle(); float_t v8; float_t v9; float_t v10; float_t v11; if (flags & HORIZONTAL) { v8 = glyph_size.x; v9 = mouse_callback_data.pos.x; v10 = glyph_size.x + rect.pos.x; v11 = rect.size.x + rect.pos.x; } else { v8 = glyph_size.y; v9 = mouse_callback_data.pos.y; v10 = glyph_size.y + rect.pos.y; v11 = rect.size.y + rect.pos.y; } if (mouse_callback_data.input & 0x1000000) { if (v9 < v10) callback_data.field_8 = 0x1000001; else if (v11 - v8 < v9) callback_data.field_8 = 0x1000002; else { vec2 v23 = sub_1402E4790(); if (v23.x + v10 > v9) callback_data.field_8 = 0x1000005; else if (v9 > v23.x + v10 + v23.y) callback_data.field_8 = 0x1000006; } } if (callback_data.field_8 == -1 && (mouse_callback_data.input & 0x01) && (mouse_callback_data.input & 0x40000000)) { vec2 v23 = sub_1402E4790(); rectangle rect = GetRectangle(); float_t v14; float_t v15; float_t v17; float_t v18; if (flags & HORIZONTAL) { v14 = rect.pos.x + glyph_size.x + v23.x; v15 = rect.pos.y; v17 = v23.y; v18 = rect.size.y; } else { v14 = rect.pos.x; v15 = rect.pos.y + glyph_size.y + v23.x; v17 = rect.size.x; v18 = v23.y; } if (v14 <= mouse_callback_data.pos.x && mouse_callback_data.pos.x < v17 + v14 && v15 <= mouse_callback_data.pos.y && mouse_callback_data.pos.y < v18 + v15) { field_A6 = true; if (flags & HORIZONTAL) field_A0 = mouse_callback_data.pos.x - (v17 * 0.5f + v14); else field_A0 = mouse_callback_data.pos.y - (v18 * 0.5f + v15); callback_data.field_8 = 1; callback_data.mouse_pos = mouse_callback_data.pos; } } if (callback_data.field_8 != -1) { callback_data.widget = this; ScrollBar::sub_1402E6CC0(callback_data); callback_data.widget = parent; } return callback_data; } void ScrollBar::sub_1402E6CC0(SelectionListener::CallbackData data) { if (!data.field_8) return; ScrollBar* scroll_bar = dynamic_cast(data.widget); if (!scroll_bar) return; float_t value = scroll_bar->value; switch (data.field_8) { case 1: { vec2 glyph_size = scroll_bar->font.GetFontGlyphSize(); rectangle v14 = scroll_bar->GetRectangle(); float_t v6; float_t v7; float_t v8; float_t v9; if (scroll_bar->flags & HORIZONTAL) { v6 = glyph_size.x; v7 = data.mouse_pos.x; v8 = v14.pos.x + glyph_size.x; v9 = v14.pos.x + v14.size.x; } else { v6 = glyph_size.y; v7 = data.mouse_pos.y; v8 = v14.pos.y + glyph_size.y; v9 = v14.pos.y + v14.size.y; } float_t v10 = v7 - scroll_bar->field_A0; vec2 size = scroll_bar->sub_1402E4790(); float_t v11 = v9 - v6 - v8 - size.y; float_t v12 = v8 + size.y * 0.5f; if (v12 >= v10) value = scroll_bar->min; else if (v10 >= v12 + v11) value = scroll_bar->max; else value = scroll_bar->min + (v10 - v8 - size.y * 0.5f) / v11 * (scroll_bar->max - scroll_bar->min); } break; case 0x1000001: value -= scroll_bar->step; break; case 0x1000002: value += scroll_bar->step; break; case 0x1000005: value -= scroll_bar->step_fast; break; case 0x1000006: value += scroll_bar->step_fast; break; case 0x1000007: value = scroll_bar->min; break; case 0x1000008: value = scroll_bar->max; break; case 0x1000071: if (scroll_bar->flags & VERTICAL) value += scroll_bar->step * -3.0f; break; case 0x1000072: if (scroll_bar->flags & VERTICAL) value += scroll_bar->step * 3.0f; break; } scroll_bar->SetValue(value); } ShellCloseButton::ShellCloseButton(Shell* parent) : Button(parent) { SetSize({ 14.0f, 14.0f }); SetText(L"Close Box"); callback = Callback; field_100 = 0; field_104 = 4; } ShellCloseButton::~ShellCloseButton() { } void ShellCloseButton::Draw() { print->SetFont(¤t_font); vec2 pos = GetPos(); print->PrintText(!(field_100 & 2) || !(field_100 & 1) ? "x" : "*", pos.x, pos.y); } vec2 ShellCloseButton::GetPos() { return parent_comp->GetPos() + rect.pos; } vec2 ShellCloseButton::GetSize() { return current_font.GetFontGlyphSize(); } void ShellCloseButton::Callback(Widget* data) { ShellCloseButton* close_button = dynamic_cast(data); if (close_button) close_button->parent_shell->Hide(); } Slider::Slider(Composite* parent, Flags flags) : Control(parent, flags) { format = "%f"; scroll_bar = new ScrollBar(this, (Flags)(flags & (HORIZONTAL | VERTICAL))); scroll_bar->parent = this; } Slider::~Slider() { } void Slider::Draw() { rectangle rect = GetRectangle(); print->SetClipData(rect); float_t pos_x = 0.0f; if (GetText().size()) { print->SetFont(&font); print->SetColor(Field_A0() ? colors_current.foreground : colors_current.disable_foreground); print->PrintText(GetText(), rect.pos.x, rect.pos.y); pos_x = font.GetFontGlyphWidth() + print->GetTextSize(GetText()).x; } print->SetFont(&font); print->SetColor(Field_A0() ? colors_current.foreground : colors_current.disable_foreground); char buf[256]; sprintf_s(buf, sizeof(buf), format, scroll_bar->value); print->PrintText(buf, rect.pos.x + pos_x, rect.pos.y); scroll_bar->UpdateDraw(); if (Field_A0() && Field_60()) { print->SetColor(colors_current.focus_border_color); print->sub_140301390(GetRectangle(), 1.0f); } } void Slider::Reset() { if (scroll_bar) { scroll_bar->Free(); scroll_bar = 0; } Control::Reset(); } int32_t Slider::KeyCallback(const Widget::KeyCallbackData& data) { if (!Field_A0()) return 0; SelectionListener::CallbackData v6 = scroll_bar->sub_1402E5140(data); if (v6.widget) for (SelectionListener*& i : selection_listeners) i->Callback(&v6); return 0; } int32_t Slider::MouseCallback(const Widget::MouseCallbackData& data) { if (!Field_A0()) return 0; if ((data.input & 0xF0) && !Field_60()) Field_58(); bool v5 = scroll_bar->field_A6; SelectionListener::CallbackData v9 = scroll_bar->sub_1402E5380(data); if (v5 != scroll_bar->field_A6) dw_gui_detail_display_set_selected_widget(this, scroll_bar->field_A6); if (v9.widget) for (SelectionListener*& i : selection_listeners) i->Callback(&v9); return 0; } void Slider::SetSize(const vec2& value) { Widget::SetSize(value); scroll_bar->rect.pos.x = value.x - scroll_bar->rect.size.x; scroll_bar->rect.pos.y = 0.0f; } void Slider::UpdateLayout() { scroll_bar->rect.pos = { GetTextSize().x, 0.0f }; SetSize(GetSize()); } vec2 Slider::GetSize() { vec2 v10 = Slider::GetTextSize(); vec2 v11 = scroll_bar->rect.size; vec2 size; size.x = v11.x + v10.x; size.y = max_def(v11.y, v10.y); return size; } void Slider::AddSelectionListener(SelectionListener* value) { selection_listeners.push_back(value); } vec2 Slider::GetTextSize() { vec2 size; if (GetText().size()) { print->SetFont(&font); size.x += font.GetFontGlyphWidth() + print->GetTextSize(GetText()).x; } char buf[0x100]; sprintf_s(buf, sizeof(buf), format, scroll_bar->value); size.x += font.GetFontGlyphWidth() + print->GetTextSize(buf).x; return size; } Slider* Slider::Create(Composite* parent, Flags flags, const char* name, const char* format, float_t width) { Slider* slider = new Slider(parent, flags); slider->scroll_bar->SetText(L"slider's bar"); slider->SetText(name); slider->format = format; slider->scroll_bar->SetWidth(width); return slider; } Slider* Slider::Create(Composite* parent, Flags flags, float_t pos_x, float_t pos_y, float_t width, float_t height, const char* text) { Slider* slider = new Slider(parent, flags); ScrollBar* scroll_bar = slider->scroll_bar; slider->SetText(text); scroll_bar->SetText(L"slider's bar"); scroll_bar->SetSize({ width, height }); print->SetFont(&slider->font); vec2 size; if (flags & HORIZONTAL) { vec2 v21 = print->GetTextSize(slider->text); vec2 v22 = print->GetTextSize(L"0000"); scroll_bar->rect.pos.x = v21.x + v22.x; scroll_bar->rect.pos.y = 0.0f; size.x = v21.x + v22.x + scroll_bar->rect.size.x; size.y = slider->font.GetFontGlyphHeight(); } else { vec2 v21 = print->GetTextSize(slider->text); vec2 v22 = print->GetTextSize(L"0000"); size.x = slider->font.GetFontGlyphWidth(); size.y = v21.x + v22.x + scroll_bar->rect.size.y; } slider->rect.pos = { pos_x, pos_y }; slider->SetSize(size); return slider; } init_data::init_data() { } int32_t font_get_index(prj::string& name) { for (auto& i : font_collection) if (!i.second->GetName().compare(name)) { current_font = *i.second; return i.first; } return -1; } } PrintWorkDebug::PrintWorkDebug() { prio = spr::SPR_PRIO_29; SetResolutionMode(RESOLUTION_MODE_MAX); } namespace dw { Print::Print(float_t width, float_t height) { font = ¤t_font; print_work = new PrintWorkDebug; field_10 = color_black; field_14 = color_white; field_18 = { 0.0f, 0.0f, width, height }; clip_data = field_18; field_38 = 1.0f; } Print::~Print() { delete print_work; } void Print::FillRectangle(rectangle rect) { if (rect.size.x > 0.0f && rect.size.y > 0.0f) print_work->FillRectangle(rect); } vec2 Print::GetTextSize(prj::string& str) { std::string temp_utf8(str.data(), str.size()); std::wstring temp_utf16(utf8_to_utf16(temp_utf8)); return GetTextSize(prj::wstring(temp_utf16.data(), temp_utf16.size())); } vec2 Print::GetTextSize(prj::wstring& str) { return print_work->GetTextSize(str.c_str(), str.c_str() + str.size()); } vec2 Print::GetTextSize(const wchar_t* str, size_t length) { return print_work->GetTextSize(str, str + length); } void Print::PrintText(prj::string& str, float_t pos_x, float_t pos_y) { std::string temp_utf8(str.data(), str.size()); std::wstring temp_utf16(utf8_to_utf16(temp_utf8)); PrintText(prj::wstring(temp_utf16.data(), temp_utf16.size()), pos_x, pos_y); } void Print::PrintText(prj::wstring& str, float_t pos_x, float_t pos_y) { PrintWorkDebug* print_work = this->print_work; print_work->line_origin_loc = { pos_x, pos_y }; print_work->text_current_loc = print_work->line_origin_loc; print_work->PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, str.c_str(), str.c_str() + str.size()); } void Print::SetColor(color4u8 value) { print_work->color = value; } void Print::SetFillColor(color4u8 value) { print_work->fill_color = value; } void Print::SetClipData(rectangle rect) { clip_data = rect; print_work->clip = true; print_work->clip_data = clip_data; } void Print::SetFont(p_Font* value) { this->font = value; print_work->SetFont(&value->ptr->font); } void Print::sub_140301390(rectangle rect, float_t a3) { color4u8 v3 = field_14; print_work->fill_color = print_work->color; rectangle v10; v10.pos.x = rect.pos.x; v10.pos.y = rect.pos.y; v10.size.x = a3; v10.size.y = rect.size.y; FillRectangle(v10); v10.pos.x = rect.size.x + rect.pos.x - a3; FillRectangle(v10); v10.pos.x = a3 + rect.pos.x; v10.pos.y = rect.pos.y; v10.size.x = rect.size.x - a3 - a3; v10.size.y = a3; FillRectangle(v10); v10.pos.y = rect.size.y + rect.pos.y - a3; FillRectangle(v10); print_work->fill_color = v3; } void Print::sub_140302800() { SetClipData(field_18); } } dw::Shell* dw_gui_detail::Display::GetHoveredShell() { auto i_begin = shells.end(); auto i_end = shells.begin(); for (auto i = i_begin; i != i_end;) { i--; if (!(*i)->freed && (*i)->GetDisp()) { rectangle rect = (*i)->GetRectangle(); if (rect.pos.x <= mouse_callback_data.pos.x && mouse_callback_data.pos.x < rect.pos.x + rect.size.x && rect.pos.y <= mouse_callback_data.pos.y && mouse_callback_data.pos.y < rect.pos.y + rect.size.y) return *i; } } return 0; } void dw_gui_detail::Display::MakeShellFirst(dw::Shell* value) { if (!value) return; auto i = shells.begin(); auto i_end = shells.end(); while (i != i_end) if (*i == value) { shells.erase(i); shells.push_back(value); break; } else i++; } void dw_gui_detail::Display::MakeShellLast(dw::Shell* value) { if (!value) return; auto i = shells.begin(); auto i_end = shells.end(); while (i != i_end) if (*i == value) { shells.erase(i); shells.insert(shells.begin(), value); break; } else i++; } void dw_gui_detail::Display::RemoveShell(dw::Shell* value) { auto i = shells.begin(); auto i_end = shells.end(); while (i != i_end) if (*i == value) { shells.erase(i); break; } else i++; if (selected_shell == value) { selected_shell = 0; find_focus = true; } if (howered_shell == value) howered_shell = 0; if (move_resize_shell == value) move_resize_shell = 0; } static void dw_gui_detail_display_set_selected_widget(dw::Widget* widget, bool set) { dw_gui_detail_display->selected_widget = set ? widget : 0; } static void sub_1402EE3C0(rectangle rect, float_t border, int32_t type, color4u8* fill_color) { if (type != 2 && type != 4) return; color4u8 v26 = type == 2 ? dw::colors_current.border_light_color : dw::colors_current.border_dark_color; color4u8 v25 = type == 2 ? dw::colors_current.border_dark_color : dw::colors_current.border_light_color; rectangle v24a; v24a.pos.x = rect.pos.x; v24a.pos.y = rect.pos.y; v24a.size.x = rect.size.x; v24a.size.y = border; dw::print->SetFillColor(v26); dw::print->FillRectangle(v24a); rectangle v24b; v24b.pos.x = rect.pos.x; v24b.pos.y = rect.pos.y + border; v24b.size.x = border; v24b.size.y = rect.size.y - border; dw::print->SetFillColor(v26); dw::print->FillRectangle(v24b); rectangle v24c; v24c.pos.x = rect.pos.x + rect.size.x - border; v24c.pos.y = rect.pos.y + border; v24c.size.x = border; v24c.size.y = rect.size.y - border; dw::print->SetFillColor(v25); dw::print->FillRectangle(v24c); rectangle v24d; v24d.pos.x = rect.pos.x + border; v24d.pos.y = rect.pos.y + rect.size.y - border; v24d.size.x = rect.size.x - border; v24d.size.y = border; dw::print->SetFillColor(v25); dw::print->FillRectangle(v24d); if (fill_color) { rectangle v24; v24.pos.x = border + rect.pos.x; v24.pos.y = border + rect.pos.y; v24.size.x = rect.size.x - border - border; v24.size.y = rect.size.y - border - border; dw::print->SetFillColor(*fill_color); dw::print->FillRectangle(v24); } }