From d46553baecd6d7e786677737915969865bc3f84b Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 15:41:59 -0400 Subject: [PATCH 01/13] Add focus events This commit updates interactive controls (not controls which only display information) to handle OnGainedFocus() and OnLostFocus() events. These interactive controls are given a behavior template parameter, which can implement these functions if they want to handle them. --- Code/Examples/1-SimpleExample/EntryPoint.cpp | 4 +- Code/Examples/2-StylingExample/EntryPoint.cpp | 8 +- .../3-ControlGalleryExample/EntryPoint.cpp | 17 ++- Code/maxGUI/Button.hpp | 23 +--- Code/maxGUI/Button.inl | 54 +++++---- Code/maxGUI/ButtonImplementation.cpp | 43 +++++++ Code/maxGUI/ButtonImplementation.hpp | 55 +++++++++ Code/maxGUI/CheckBox.hpp | 32 +++-- Code/maxGUI/CheckBox.inl | 67 ++++++++++ ...heckBox.cpp => CheckBoxImplementation.cpp} | 114 ++++++++---------- Code/maxGUI/CheckBoxImplementation.hpp | 57 +++++++++ Code/maxGUI/Control.hpp | 33 +++++ Code/maxGUI/ControlImplementation.cpp | 20 +++ Code/maxGUI/ControlImplementation.hpp | 39 ++++++ Code/maxGUI/ControlWithTextImplementation.cpp | 41 +++++++ Code/maxGUI/ControlWithTextImplementation.hpp | 42 +++++++ Code/maxGUI/DropDownBox.hpp | 32 ++--- Code/maxGUI/DropDownBox.inl | 46 +++++++ ...nBox.cpp => DropDownBoxImplementation.cpp} | 96 +++++++-------- Code/maxGUI/DropDownBoxImplementation.hpp | 53 ++++++++ Code/maxGUI/ListBox.hpp | 33 +++-- Code/maxGUI/ListBox.inl | 44 +++++++ ...{ListBox.cpp => ListBoxImplementation.cpp} | 99 ++++++++------- Code/maxGUI/ListBoxImplementation.hpp | 55 +++++++++ Code/maxGUI/MultilineTextBox.hpp | 33 ++--- Code/maxGUI/MultilineTextBox.inl | 64 ++++++++++ ...cpp => MultilineTextBoxImplementation.cpp} | 96 +++++++-------- .../maxGUI/MultilineTextBoxImplementation.hpp | 52 ++++++++ Code/maxGUI/RadioButton.hpp | 34 +++--- Code/maxGUI/RadioButton.inl | 48 ++++++++ ...tton.cpp => RadioButtonImplementation.cpp} | 87 +++++++------ Code/maxGUI/RadioButtonImplementation.hpp | 54 +++++++++ Code/maxGUI/TextBox.hpp | 39 +++--- Code/maxGUI/TextBox.inl | 44 +++++++ ...{TextBox.cpp => TextBoxImplementation.cpp} | 112 ++++++++--------- Code/maxGUI/TextBoxImplementation.hpp | 55 +++++++++ Projects/VisualStudio/maxGUI/maxGUI.vcxproj | 34 +++++- .../maxGUI/maxGUI.vcxproj.filters | 88 +++++++++++--- 38 files changed, 1441 insertions(+), 506 deletions(-) create mode 100644 Code/maxGUI/ButtonImplementation.cpp create mode 100644 Code/maxGUI/ButtonImplementation.hpp create mode 100644 Code/maxGUI/CheckBox.inl rename Code/maxGUI/{CheckBox.cpp => CheckBoxImplementation.cpp} (59%) create mode 100644 Code/maxGUI/CheckBoxImplementation.hpp create mode 100644 Code/maxGUI/ControlImplementation.cpp create mode 100644 Code/maxGUI/ControlImplementation.hpp create mode 100644 Code/maxGUI/ControlWithTextImplementation.cpp create mode 100644 Code/maxGUI/ControlWithTextImplementation.hpp create mode 100644 Code/maxGUI/DropDownBox.inl rename Code/maxGUI/{DropDownBox.cpp => DropDownBoxImplementation.cpp} (65%) create mode 100644 Code/maxGUI/DropDownBoxImplementation.hpp create mode 100644 Code/maxGUI/ListBox.inl rename Code/maxGUI/{ListBox.cpp => ListBoxImplementation.cpp} (68%) create mode 100644 Code/maxGUI/ListBoxImplementation.hpp create mode 100644 Code/maxGUI/MultilineTextBox.inl rename Code/maxGUI/{MultilineTextBox.cpp => MultilineTextBoxImplementation.cpp} (71%) create mode 100644 Code/maxGUI/MultilineTextBoxImplementation.hpp create mode 100644 Code/maxGUI/RadioButton.inl rename Code/maxGUI/{RadioButton.cpp => RadioButtonImplementation.cpp} (64%) create mode 100644 Code/maxGUI/RadioButtonImplementation.hpp create mode 100644 Code/maxGUI/TextBox.inl rename Code/maxGUI/{TextBox.cpp => TextBoxImplementation.cpp} (63%) create mode 100644 Code/maxGUI/TextBoxImplementation.hpp diff --git a/Code/Examples/1-SimpleExample/EntryPoint.cpp b/Code/Examples/1-SimpleExample/EntryPoint.cpp index 3831227..075aa87 100644 --- a/Code/Examples/1-SimpleExample/EntryPoint.cpp +++ b/Code/Examples/1-SimpleExample/EntryPoint.cpp @@ -11,7 +11,7 @@ class CustomForm { void OnCreated(maxGUI::FormConcept* form) noexcept { // Add controls inside the Form's OnCreated(). - multiline_textbox_ = form->AddControl(max::Containers::MakeRectangle(0, 0, 100, 100), "Multi-line" MAXGUI_PLATFORM_NEWLINE "test"); + multiline_textbox_ = form->AddControl>(max::Containers::MakeRectangle(0, 0, 100, 100), "Multi-line" MAXGUI_PLATFORM_NEWLINE "test"); } void OnResized(maxGUI::FormConcept* /*form*/, int new_width, int new_height) noexcept { @@ -24,7 +24,7 @@ class CustomForm { maxGUI::PostExitMessage(0); } - maxGUI::MultilineTextBox* multiline_textbox_ = nullptr; + maxGUI::MultilineTextBox<>* multiline_textbox_ = nullptr; }; diff --git a/Code/Examples/2-StylingExample/EntryPoint.cpp b/Code/Examples/2-StylingExample/EntryPoint.cpp index 6fbcc84..9a6ad09 100644 --- a/Code/Examples/2-StylingExample/EntryPoint.cpp +++ b/Code/Examples/2-StylingExample/EntryPoint.cpp @@ -26,12 +26,12 @@ class LoginForm { void OnCreated(maxGUI::FormConcept* form) noexcept { form->AddControl(max::Containers::MakeRectangle(50, 50, 300, 500), "Login"); - username_textbox_ = form->AddControl(max::Containers::MakeRectangle(50, 100, 300, 50), ""); + username_textbox_ = form->AddControl>(max::Containers::MakeRectangle(50, 100, 300, 50), ""); // The extra optional parameter at the end is a bitmask of styles. // Different controls have different optional styles available. // For example, a TextBox can have the Password style which hides the character typed by the user. - password_textbox_ = form->AddControl(max::Containers::MakeRectangle(50, 150, 300, 50), "", maxGUI::TextBoxStyles::Password); + password_textbox_ = form->AddControl>(max::Containers::MakeRectangle(50, 150, 300, 50), "", maxGUI::TextBoxStyles::Password); // A Button can have the Default style, which allows the user to press Enter at any time to press the button. form->AddControl>(max::Containers::MakeRectangle(50, 250, 100, 100), "Login", maxGUI::ButtonStyles::Default | maxGUI::ButtonStyles::Disabled); @@ -41,8 +41,8 @@ class LoginForm { maxGUI::PostExitMessage(0); } - maxGUI::TextBox* username_textbox_ = nullptr; - maxGUI::TextBox* password_textbox_ = nullptr; + maxGUI::TextBox<>* username_textbox_ = nullptr; + maxGUI::TextBox<>* password_textbox_ = nullptr; }; diff --git a/Code/Examples/3-ControlGalleryExample/EntryPoint.cpp b/Code/Examples/3-ControlGalleryExample/EntryPoint.cpp index 7f8f576..75b6f1e 100644 --- a/Code/Examples/3-ControlGalleryExample/EntryPoint.cpp +++ b/Code/Examples/3-ControlGalleryExample/EntryPoint.cpp @@ -9,8 +9,7 @@ #include -class CustomButtonBehavior -{ +class CustomButtonBehavior { public: static void OnPressed() noexcept { @@ -26,7 +25,7 @@ class ControlGalleryForm { form->AddControl>(max::Containers::MakeRectangle(25, 25, 150, 50), "Custom Button"); std::vector dropdown_options{"Option 1", "Option 2", "Option 3"}; - form->AddControl(max::Containers::MakeRectangle(25, 100, 300, 250), std::move(dropdown_options)); + form->AddControl>(max::Containers::MakeRectangle(25, 100, 300, 250), std::move(dropdown_options)); // TODO: Add the radio buttons inside the frame form->AddControl(max::Containers::MakeRectangle(25, 150, 300, 50), "Frame"); @@ -34,20 +33,20 @@ class ControlGalleryForm { form->AddControl(max::Containers::MakeRectangle(25, 225, 300, 25), "Label"); std::vector listbox_options{"Item 1", "Item 2", "Item 3"}; - form->AddControl(max::Containers::MakeRectangle(25, 275, 300, 150), std::move(listbox_options)); + form->AddControl>(max::Containers::MakeRectangle(25, 275, 300, 150), std::move(listbox_options)); - form->AddControl(max::Containers::MakeRectangle(25, 450, 300, 150), "Multiline\r\ntextbox"); + form->AddControl>(max::Containers::MakeRectangle(25, 450, 300, 150), "Multiline\r\ntextbox"); form->AddControl(max::Containers::MakeRectangle(25, 625, 300, 25), 0, 100, 50); - form->AddControl(max::Containers::MakeRectangle(25, 675, 300, 25), "Check 1"); + form->AddControl>(max::Containers::MakeRectangle(25, 675, 300, 25), "Check 1"); // When using multiple RadioButtons that belong to one group, be sure to add the FirstInGroup style to the first option. - form->AddControl(max::Containers::MakeRectangle(25, 725, 300, 25), "Option 1", maxGUI::RadioButtonStyles::FirstInGroup); + form->AddControl>(max::Containers::MakeRectangle(25, 725, 300, 25), "Option 1", maxGUI::RadioButtonStyles::FirstInGroup); - form->AddControl(max::Containers::MakeRectangle(25, 750, 300, 25), "Option 2"); + form->AddControl>(max::Containers::MakeRectangle(25, 750, 300, 25), "Option 2"); - form->AddControl(max::Containers::MakeRectangle(25, 800, 300, 25), "Textbox"); + form->AddControl>(max::Containers::MakeRectangle(25, 800, 300, 25), "Textbox"); } void OnClosed(maxGUI::FormConcept* /*form*/) noexcept { diff --git a/Code/maxGUI/Button.hpp b/Code/maxGUI/Button.hpp index ad445d9..b60e013 100644 --- a/Code/maxGUI/Button.hpp +++ b/Code/maxGUI/Button.hpp @@ -6,16 +6,16 @@ #define MAXGUI_BUTTON_HPP #include -#include #include +#include #include #include -#include #if defined(MAX_PLATFORM_WINDOWS) #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN #endif + #include #endif @@ -23,20 +23,6 @@ #include #endif -namespace maxGUI -{ - - enum class ButtonStyles : uint8_t { - None = 0, - Disabled = 1, - Default = 2, - Flat = 4, - }; - -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::ButtonStyles); - namespace maxGUI { @@ -68,7 +54,7 @@ namespace maxGUI explicit Button(HWND window_handle) noexcept; #endif - ~Button() noexcept override = default; + ~Button() noexcept override; #if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, ButtonStyles styles = ButtonStyles::None) noexcept; @@ -81,6 +67,7 @@ namespace maxGUI #endif Behavior behavior_; + ButtonImplementation implementation_; }; diff --git a/Code/maxGUI/Button.inl b/Code/maxGUI/Button.inl index 38dd891..6ed3ebc 100644 --- a/Code/maxGUI/Button.inl +++ b/Code/maxGUI/Button.inl @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #if defined(MAX_PLATFORM_WINDOWS) #include #endif @@ -16,8 +18,9 @@ namespace maxGUI template< class Behavior > #endif Button< Behavior >::Button(HWND window_handle) noexcept - : ControlWithText(std::move(window_handle)) + : ControlWithText(window_handle) , behavior_() + , implementation_(window_handle) {} #endif @@ -27,27 +30,17 @@ namespace maxGUI #else template< class Behavior > #endif - HWND Button< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, ButtonStyles styles) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 -#pragma warning(push) -#pragma warning(disable: 26813) - if ((styles & ButtonStyles::Disabled) == ButtonStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - if ((styles & ButtonStyles::Default) == ButtonStyles::Default) { - win32_styles |= BS_DEFPUSHBUTTON; - } - if ((styles & ButtonStyles::Flat) == ButtonStyles::Flat) { - win32_styles |= BS_FLAT; - } -#pragma warning(pop) - - Win32String win32_text = Utf8ToWin32String(std::move(text)); + Button< Behavior >::~Button() noexcept = default; +#endif - return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); +#if defined(MAX_PLATFORM_WINDOWS) +#if defined(MAX_CONCEPTS_SUPPORTED) + template< ButtonRequirements Behavior > +#else + template< class Behavior > +#endif + HWND Button< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, ButtonStyles styles) noexcept { + return ButtonImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(text), std::move(styles)); } #endif @@ -58,12 +51,21 @@ namespace maxGUI template< class Behavior > #endif void Button< Behavior >::OnCommand(WORD notification) noexcept { - //if constexpr (Exists::value) { - //if constexpr (Exists2::value) { - if (notification == BN_CLICKED) { - behavior_.OnPressed(); + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == BN_SETFOCUS ) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == BN_KILLFOCUS ) { + behavior_.OnLostFocus(&implementation_); } - //} + } + + if (notification == BN_CLICKED) { + behavior_.OnPressed(); + } } #endif diff --git a/Code/maxGUI/ButtonImplementation.cpp b/Code/maxGUI/ButtonImplementation.cpp new file mode 100644 index 0000000..c59f0e2 --- /dev/null +++ b/Code/maxGUI/ButtonImplementation.cpp @@ -0,0 +1,43 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +namespace maxGUI +{ + + ButtonImplementation::ButtonImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + ButtonImplementation::~ButtonImplementation() noexcept = default; + +#if defined(MAX_PLATFORM_WINDOWS) + HWND ButtonImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, ButtonStyles styles) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_NOTIFY; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 +#pragma warning(push) +#pragma warning(disable: 26813) + if ((styles & ButtonStyles::Disabled) == ButtonStyles::Disabled) { + win32_styles |= WS_DISABLED; + } + if ((styles & ButtonStyles::Default) == ButtonStyles::Default) { + win32_styles |= BS_DEFPUSHBUTTON; + } + if ((styles & ButtonStyles::Flat) == ButtonStyles::Flat) { + win32_styles |= BS_FLAT; + } +#pragma warning(pop) + + Win32String win32_text = Utf8ToWin32String(std::move(text)); + + return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + } +#endif + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/ButtonImplementation.hpp b/Code/maxGUI/ButtonImplementation.hpp new file mode 100644 index 0000000..2ca6180 --- /dev/null +++ b/Code/maxGUI/ButtonImplementation.hpp @@ -0,0 +1,55 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_BUTTONIMPLEMENTATION_HPP +#define MAXGUI_BUTTONIMPLEMENTATION_HPP + +#include + +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + +#include + +namespace maxGUI +{ + + enum class ButtonStyles : uint8_t { + None = 0, + Disabled = 1, + Default = 2, + Flat = 4, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::ButtonStyles); + +namespace maxGUI +{ + + class ButtonImplementation : public ControlWithTextImplementation + { + public: + + explicit ButtonImplementation(HWND window_handle) noexcept; + + ~ButtonImplementation() noexcept; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, ButtonStyles styles) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_BUTTONIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/CheckBox.hpp b/Code/maxGUI/CheckBox.hpp index 7972cf3..86ec1dc 100644 --- a/Code/maxGUI/CheckBox.hpp +++ b/Code/maxGUI/CheckBox.hpp @@ -5,39 +5,30 @@ #ifndef MAXGUI_CHECKBOX_HPP #define MAXGUI_CHECKBOX_HPP +#include + #include #include +#include +#include -#if defined(MAX_PLATFORM_WINDOWS) -#include -#include -#include -#include +#if defined(MAX_PLATFORM_WINDOWS) namespace maxGUI { - enum class CheckBoxStyles : uint8_t { - None = 0, - Disabled = 1, - Flat = 2, + class DefaultCheckBoxBehavior { }; -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::CheckBoxStyles); - -namespace maxGUI -{ - + template< class Behavior = DefaultCheckBoxBehavior > class CheckBox : public ControlWithText { public: explicit CheckBox(HWND window_handle) noexcept; - ~CheckBox() noexcept override = default; + ~CheckBox() noexcept override; static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, CheckBoxStyles styles = CheckBoxStyles::None) noexcept; @@ -51,10 +42,17 @@ namespace maxGUI void OnCommand(WORD notification) noexcept override; + private: + + Behavior behavior_; + CheckBoxImplementation implementation_; + }; } // namespace maxGUI #endif // #if defined(MAX_PLATFORM_WINDOWS) +#include + #endif // #ifndef MAXGUI_BUTTON_HPP \ No newline at end of file diff --git a/Code/maxGUI/CheckBox.inl b/Code/maxGUI/CheckBox.inl new file mode 100644 index 0000000..8b78f89 --- /dev/null +++ b/Code/maxGUI/CheckBox.inl @@ -0,0 +1,67 @@ +// Copyright 2020, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +namespace maxGUI +{ + + template< class Behavior > + CheckBox< Behavior >::CheckBox(HWND window_handle) noexcept + : ControlWithText(window_handle) + , behavior_() + , implementation_(window_handle) + {} + + template< class Behavior > + CheckBox< Behavior >::~CheckBox() noexcept = default; + + template< class Behavior > + HWND CheckBox< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, CheckBoxStyles styles) noexcept { + return CheckBoxImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(text), std::move(styles)); + } + + template< class Behavior > + void CheckBox< Behavior >::OnPressed() noexcept { + if (IsChecked()) { + Uncheck(); + } else { + Check(); + } + } + + template< class Behavior > + void CheckBox< Behavior >::OnCommand(WORD notification) noexcept { + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == BN_SETFOCUS) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == BN_KILLFOCUS) { + behavior_.OnLostFocus(&implementation_); + } + } + + if (notification == BN_CLICKED) + { + OnPressed(); + } + } + + template< class Behavior > + bool CheckBox< Behavior >::IsChecked() const noexcept { + return implementation_.IsChecked(); + } + + template< class Behavior > + void CheckBox< Behavior >::Check() noexcept { + return implementation_.Check(); + } + + template< class Behavior > + void CheckBox< Behavior >::Uncheck() noexcept { + return implementation_.Uncheck(); + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/CheckBox.cpp b/Code/maxGUI/CheckBoxImplementation.cpp similarity index 59% rename from Code/maxGUI/CheckBox.cpp rename to Code/maxGUI/CheckBoxImplementation.cpp index e177ae5..2ffeadb 100644 --- a/Code/maxGUI/CheckBox.cpp +++ b/Code/maxGUI/CheckBoxImplementation.cpp @@ -1,61 +1,53 @@ -// Copyright 2020, The maxGUI Contributors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include - -namespace maxGUI -{ - - CheckBox::CheckBox(HWND window_handle) noexcept - : ControlWithText(std::move(window_handle)) - {} - - HWND CheckBox::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, CheckBoxStyles styles) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 - #pragma warning(push) - #pragma warning(disable: 26813) - if ((styles & CheckBoxStyles::Disabled) == CheckBoxStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - if ((styles & CheckBoxStyles::Flat) == CheckBoxStyles::Flat) { - win32_styles |= BS_FLAT; - } - #pragma warning(pop) - Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); - } - - void CheckBox::OnPressed() noexcept { - if (IsChecked()) { - Uncheck(); - } else { - Check(); - } - } - - void CheckBox::OnCommand(WORD notification) noexcept { - if (notification == BN_CLICKED) - { - OnPressed(); - } - } - - bool CheckBox::IsChecked() const noexcept { - return SendMessage(window_handle_, BM_GETCHECK, 0, 0) == BST_CHECKED; - } - - void CheckBox::Check() noexcept { - SendMessage(window_handle_, BM_SETCHECK, BST_CHECKED, 0); - } - - void CheckBox::Uncheck() noexcept { - SendMessage(window_handle_, BM_SETCHECK, BST_UNCHECKED, 0); - } - -} // namespace maxGUI \ No newline at end of file +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include + +namespace maxGUI +{ + + CheckBoxImplementation::CheckBoxImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + CheckBoxImplementation::~CheckBoxImplementation() noexcept = default; + +#if defined(MAX_PLATFORM_WINDOWS) + HWND CheckBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, CheckBoxStyles styles) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX | BS_NOTIFY; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 +#pragma warning(push) +#pragma warning(disable: 26813) + if ((styles & CheckBoxStyles::Disabled) == CheckBoxStyles::Disabled) { + win32_styles |= WS_DISABLED; + } + if ((styles & CheckBoxStyles::Flat) == CheckBoxStyles::Flat) { + win32_styles |= BS_FLAT; + } +#pragma warning(pop) + Win32String win32_text = Utf8ToWin32String(std::move(text)); + return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + } + + bool CheckBoxImplementation::IsChecked() const noexcept { + return SendMessage(window_handle_, BM_GETCHECK, 0, 0) == BST_CHECKED; + } + + void CheckBoxImplementation::Check() noexcept { + SendMessage(window_handle_, BM_SETCHECK, BST_CHECKED, 0); + } + + void CheckBoxImplementation::Uncheck() noexcept { + SendMessage(window_handle_, BM_SETCHECK, BST_UNCHECKED, 0); + } + +#endif + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/CheckBoxImplementation.hpp b/Code/maxGUI/CheckBoxImplementation.hpp new file mode 100644 index 0000000..da0ab6d --- /dev/null +++ b/Code/maxGUI/CheckBoxImplementation.hpp @@ -0,0 +1,57 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_CHECKBOXIMPLEMENTATION_HPP +#define MAXGUI_CHECKBOXIMPLEMENTATION_HPP + +#include + +#include +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + +namespace maxGUI +{ + + enum class CheckBoxStyles : uint8_t { + None = 0, + Disabled = 1, + Flat = 2, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::CheckBoxStyles); + +namespace maxGUI +{ + + class CheckBoxImplementation : public ControlWithTextImplementation + { + public: + + explicit CheckBoxImplementation(HWND window_handle) noexcept; + + ~CheckBoxImplementation() noexcept; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, CheckBoxStyles styles) noexcept; + + bool IsChecked() const noexcept; + void Check() noexcept; + void Uncheck() noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_CHECKBOXIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/Control.hpp b/Code/maxGUI/Control.hpp index d49763c..7a963b6 100644 --- a/Code/maxGUI/Control.hpp +++ b/Code/maxGUI/Control.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #if defined(MAX_PLATFORM_WINDOWS) #ifndef WIN32_LEAN_AND_MEAN @@ -18,6 +19,37 @@ #include #endif +namespace { + + // TODO: Use max's Exists here + template< typename T > + struct HasOnGainedFocus { + typedef char yes[1]; + typedef char no[2]; + + // If you want only non-static member functions: + //template static yes& test(typename std::enable_if, bool>::type = 0); + // If you want static and non-static member functions: + template static yes& test(typename std::enable_if, bool>::type = 0); + template static no& test(...); + static bool const value = sizeof(test::type>(0)) == sizeof(yes&); + }; + + template< typename T > + struct HasOnLostFocus { + typedef char yes[1]; + typedef char no[2]; + + // If you want only non-static member functions: + //template static yes& test(typename std::enable_if, bool>::type = 0); + // If you want static and non-static member functions: + template static yes& test(typename std::enable_if, bool>::type = 0); + template static no& test(...); + static bool const value = sizeof(test::type>(0)) == sizeof(yes&); + }; + +} // anonymous namespace + namespace maxGUI { @@ -29,6 +61,7 @@ namespace maxGUI explicit Control(HWND window_handle) noexcept; #endif + // TODO: Do we really need this to be virtual? virtual ~Control() noexcept = default; void Move(max::Containers::Rectangle rectangle) noexcept; diff --git a/Code/maxGUI/ControlImplementation.cpp b/Code/maxGUI/ControlImplementation.cpp new file mode 100644 index 0000000..fdccf5c --- /dev/null +++ b/Code/maxGUI/ControlImplementation.cpp @@ -0,0 +1,20 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +namespace maxGUI +{ + +#if defined(MAX_PLATFORM_WINDOWS) + ControlImplementation::ControlImplementation(HWND window_handle) noexcept + : window_handle_(std::move(window_handle)) + {} +#endif + + ControlImplementation::~ControlImplementation() noexcept = default; + +} // namespace maxGUI diff --git a/Code/maxGUI/ControlImplementation.hpp b/Code/maxGUI/ControlImplementation.hpp new file mode 100644 index 0000000..6b03407 --- /dev/null +++ b/Code/maxGUI/ControlImplementation.hpp @@ -0,0 +1,39 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_CONTROLIMPLEMENTATION_HPP +#define MAXGUI_CONTROLIMPLEMENTATION_HPP + +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAD_AND_MEAN + #endif + + #include +#endif + +namespace maxGUI +{ + + class ControlImplementation + { + public: + +#if defined(MAX_PLATFORM_WINDOWS) + ControlImplementation(HWND window_handle) noexcept; +#endif + + virtual ~ControlImplementation() noexcept; + + //private: + + HWND window_handle_; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_CONTROLIMPLEMENTATION_HPP diff --git a/Code/maxGUI/ControlWithTextImplementation.cpp b/Code/maxGUI/ControlWithTextImplementation.cpp new file mode 100644 index 0000000..66ac797 --- /dev/null +++ b/Code/maxGUI/ControlWithTextImplementation.cpp @@ -0,0 +1,41 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +namespace maxGUI +{ + + ControlWithTextImplementation::ControlWithTextImplementation(HWND window_handle) noexcept + : ControlImplementation(std::move(window_handle)) + {} + + ControlWithTextImplementation::~ControlWithTextImplementation() noexcept = default; + + std::string ControlWithTextImplementation::GetText() const noexcept { +#if defined(MAX_PLATFORM_WINDOWS) + size_t length_in_chars = static_cast(SendMessage(window_handle_, WM_GETTEXTLENGTH, 0, 0)) + 1; // +1 for the null terminator + TCHAR* buffer = new wchar_t[length_in_chars]; + SendMessage(window_handle_, WM_GETTEXT, length_in_chars, reinterpret_cast(buffer)); + Win32String win32_string(std::move(buffer), length_in_chars - 1); + return Win32StringToUtf8(std::move(win32_string)); +#endif +#if defined(MAX_PLATFORM_LINUX) + return std::string(); +#endif + } + + void ControlWithTextImplementation::SetText(std::string text) noexcept { +#if defined(MAX_PLATFORM_WINDOWS) + Win32String win32_text = Utf8ToWin32String(std::move(text)); + SendMessage(window_handle_, WM_SETTEXT, 0, reinterpret_cast(win32_text.text_)); +#endif +#if defined(MAX_PLATFORM_LINUX) + (void)text; +#endif + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/ControlWithTextImplementation.hpp b/Code/maxGUI/ControlWithTextImplementation.hpp new file mode 100644 index 0000000..2061eea --- /dev/null +++ b/Code/maxGUI/ControlWithTextImplementation.hpp @@ -0,0 +1,42 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_CONTROLWITHTEXTIMPLEMENTATION_HPP +#define MAXGUI_CONTROLWITHTEXTIMPLEMENTATION_HPP + +#include + +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + + +namespace maxGUI +{ + + class ControlWithTextImplementation : public ControlImplementation + { + public: + +#if defined(MAX_PLATFORM_WINDOWS) + ControlWithTextImplementation(HWND window_handle) noexcept; +#endif + + ~ControlWithTextImplementation() noexcept override; + + std::string GetText() const noexcept; + void SetText(std::string text) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_CONTROLWITHTEXTIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/DropDownBox.hpp b/Code/maxGUI/DropDownBox.hpp index f6d7c72..4f4001b 100644 --- a/Code/maxGUI/DropDownBox.hpp +++ b/Code/maxGUI/DropDownBox.hpp @@ -5,38 +5,31 @@ #ifndef MAXGUI_DROPDOWNBOX_HPP #define MAXGUI_DROPDOWNBOX_HPP +#include +#include + #include +#include #include +#include +#include #if defined(MAX_PLATFORM_WINDOWS) -#include -#include -#include -#include -#include - namespace maxGUI { - enum class DropDownBoxStyles : uint8_t { - None = 0, - Disabled = 1, + class DefaultDropDownBoxBehavior { }; -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::DropDownBoxStyles); - -namespace maxGUI -{ + template< class Behavior = DefaultDropDownBoxBehavior > class DropDownBox : public ControlWithList { public: explicit DropDownBox(HWND window_handle) noexcept; - ~DropDownBox() noexcept override = default; + ~DropDownBox() noexcept override; static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles = DropDownBoxStyles::None) noexcept; @@ -44,10 +37,17 @@ namespace maxGUI void OnCommand(WORD notification) noexcept override; + private: + + Behavior behavior_; + DropDownBoxImplementation implementation_; + }; } // namespace maxGUI #endif // #if defined(MAX_PLATFORM_WINDOWS) +#include + #endif // #ifndef MAXGUI_DROPDOWNBOX_HPP \ No newline at end of file diff --git a/Code/maxGUI/DropDownBox.inl b/Code/maxGUI/DropDownBox.inl new file mode 100644 index 0000000..f25fbb5 --- /dev/null +++ b/Code/maxGUI/DropDownBox.inl @@ -0,0 +1,46 @@ +// Copyright 2020, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +namespace maxGUI +{ + + template< class Behavior > + DropDownBox< Behavior >::DropDownBox(HWND window_handle) noexcept + : ControlWithList(window_handle) + , behavior_() + , implementation_(window_handle) + {} + + template< class Behavior > + DropDownBox< Behavior >::~DropDownBox() noexcept = default; + + template< class Behavior > + void DropDownBox< Behavior >::OnCommand(WORD notification) noexcept { + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == CBN_SETFOCUS ) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == CBN_KILLFOCUS ) { + behavior_.OnLostFocus(&implementation_); + } + } + + if (notification == CBN_SELCHANGE) + { + int index = static_cast(SendMessage(window_handle_, CB_GETCURSEL, 0, 0)); + OnSelectionChanged(index); + } + } + + template< class Behavior > + HWND DropDownBox< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles) noexcept { + return DropDownBoxImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(list), std::move(styles)); + }; + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/DropDownBox.cpp b/Code/maxGUI/DropDownBoxImplementation.cpp similarity index 65% rename from Code/maxGUI/DropDownBox.cpp rename to Code/maxGUI/DropDownBoxImplementation.cpp index 1701b6d..5be92fe 100644 --- a/Code/maxGUI/DropDownBox.cpp +++ b/Code/maxGUI/DropDownBoxImplementation.cpp @@ -1,50 +1,46 @@ -// Copyright 2020, The maxGUI Contributors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include - -namespace maxGUI -{ - - DropDownBox::DropDownBox(HWND window_handle) noexcept - : ControlWithList(std::move(window_handle)) - {} - - void DropDownBox::OnCommand(WORD notification) noexcept { - if (notification == CBN_SELCHANGE) - { - int index = static_cast(SendMessage(window_handle_, CB_GETCURSEL, 0, 0)); - OnSelectionChanged(index); - } - } - - HWND DropDownBox::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS /*| CBS_DROPDOWNLIST*/; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 - #pragma warning(push) - #pragma warning(disable: 26813) - if ((styles & DropDownBoxStyles::Disabled) == DropDownBoxStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - #pragma warning(pop) - HWND window_handle = CreateWindowEx(0, TEXT("COMBOBOX"), TEXT(""), win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); - - for (const auto& text : list) { - Win32String win32_text = Utf8ToWin32String(text); - SendMessage(window_handle, CB_ADDSTRING, 0, reinterpret_cast(win32_text.text_)); - } - - // Default select the first item - if (list.size() != 0) { - SendMessage(window_handle, CB_SETCURSEL, 0, 0); - } - - return window_handle; - }; - -} // namespace maxGUI \ No newline at end of file +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include + +namespace maxGUI +{ + + DropDownBoxImplementation::DropDownBoxImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + DropDownBoxImplementation::~DropDownBoxImplementation() noexcept = default; + + HWND DropDownBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS /*| CBS_DROPDOWNLIST*/; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 +#pragma warning(push) +#pragma warning(disable: 26813) + if ((styles & DropDownBoxStyles::Disabled) == DropDownBoxStyles::Disabled) { + win32_styles |= WS_DISABLED; + } +#pragma warning(pop) + HWND window_handle = CreateWindowEx(0, TEXT("COMBOBOX"), TEXT(""), win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + + for (const auto& text : list) { + Win32String win32_text = Utf8ToWin32String(text); + SendMessage(window_handle, CB_ADDSTRING, 0, reinterpret_cast(win32_text.text_)); + } + + // Default select the first item + if (list.size() != 0) { + SendMessage(window_handle, CB_SETCURSEL, 0, 0); + } + + return window_handle; + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/DropDownBoxImplementation.hpp b/Code/maxGUI/DropDownBoxImplementation.hpp new file mode 100644 index 0000000..cba254b --- /dev/null +++ b/Code/maxGUI/DropDownBoxImplementation.hpp @@ -0,0 +1,53 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_DROPDOWNBOXIMPLEMENTATION_HPP +#define MAXGUI_DROPDOWNBOXIMPLEMENTATION_HPP + +#include +#include + +#include +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + +namespace maxGUI +{ + + enum class DropDownBoxStyles : uint8_t { + None = 0, + Disabled = 1, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::DropDownBoxStyles); + +namespace maxGUI +{ + + class DropDownBoxImplementation : public ControlWithTextImplementation + { + public: + + explicit DropDownBoxImplementation(HWND window_handle) noexcept; + + ~DropDownBoxImplementation() noexcept; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_DROPDOWNBOXIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/ListBox.hpp b/Code/maxGUI/ListBox.hpp index bf65c72..c3a3cca 100644 --- a/Code/maxGUI/ListBox.hpp +++ b/Code/maxGUI/ListBox.hpp @@ -5,41 +5,31 @@ #ifndef MAXGUI_LISTBOX_HPP #define MAXGUI_LISTBOX_HPP -#include - -#if defined(MAX_PLATFORM_WINDOWS) +#include +#include #include +#include #include #include -#include -#include -#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) namespace maxGUI { - enum class ListBoxStyles : uint8_t { - None = 0, - Disabled = 1, - SingleClickMultipleSelection = 2, - KeyboardAndClickMultipleSelection = 4, + class DefaultListBoxBehavior { }; -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::ListBoxStyles); - -namespace maxGUI -{ - + template< class Behavior = DefaultListBoxBehavior > class ListBox : public ControlWithList { public: explicit ListBox(HWND window_handle) noexcept; - ~ListBox() noexcept override = default; + ~ListBox() noexcept override; static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles = ListBoxStyles::None) noexcept; @@ -47,10 +37,15 @@ namespace maxGUI void OnCommand(WORD notification) noexcept override; + Behavior behavior_; + ListBoxImplementation implementation_; + }; } // namespace maxGUI #endif // #if defined(MAX_PLATFORM_WINDOWS) +#include + #endif // #ifndef MAXGUI_LISTBOX_HPP \ No newline at end of file diff --git a/Code/maxGUI/ListBox.inl b/Code/maxGUI/ListBox.inl new file mode 100644 index 0000000..98e0ff5 --- /dev/null +++ b/Code/maxGUI/ListBox.inl @@ -0,0 +1,44 @@ +// Copyright 2020, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +namespace maxGUI +{ + + template< class Behavior > + ListBox< Behavior >::ListBox(HWND window_handle) noexcept + : ControlWithList(window_handle) + , behavior_() + , implementation_(window_handle) + {} + + template< class Behavior > + ListBox< Behavior >::~ListBox() noexcept = default; + + template< class Behavior > + HWND ListBox< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles) noexcept { + return ListBoxImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(list), std::move(styles)); + } + + template< class Behavior > + void ListBox< Behavior >::OnCommand(WORD notification) noexcept { + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == LBN_SETFOCUS ) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == LBN_KILLFOCUS ) { + behavior_.OnLostFocus(&implementation_); + } + } + + if (notification == LBN_SELCHANGE) + { + int index = static_cast(SendMessage(window_handle_, LB_GETCURSEL, 0, 0)); + OnSelectionChanged(index); + } + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/ListBox.cpp b/Code/maxGUI/ListBoxImplementation.cpp similarity index 68% rename from Code/maxGUI/ListBox.cpp rename to Code/maxGUI/ListBoxImplementation.cpp index 606f740..b0b08da 100644 --- a/Code/maxGUI/ListBox.cpp +++ b/Code/maxGUI/ListBoxImplementation.cpp @@ -1,52 +1,47 @@ -// Copyright 2020, The maxGUI Contributors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include -#include - -namespace maxGUI -{ - - ListBox::ListBox(HWND window_handle) noexcept - : ControlWithList(std::move(window_handle)) - {} - - HWND ListBox::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_STANDARD; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 - #pragma warning(push) - #pragma warning(disable: 26813) - if ((styles & ListBoxStyles::Disabled) == ListBoxStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - if ((styles & ListBoxStyles::SingleClickMultipleSelection) == ListBoxStyles::SingleClickMultipleSelection) { - win32_styles |= LBS_MULTIPLESEL; - } - if ((styles & ListBoxStyles::KeyboardAndClickMultipleSelection) == ListBoxStyles::KeyboardAndClickMultipleSelection) { - win32_styles |= LBS_EXTENDEDSEL; - } - #pragma warning(pop) - HWND window_handle = CreateWindowEx(0, TEXT("LISTBOX"), TEXT(""), win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); - - for (const auto& text : list) { - Win32String win32_text = Utf8ToWin32String(text); - SendMessage(window_handle, LB_ADDSTRING, 0, reinterpret_cast(win32_text.text_)); - } - - return window_handle; - } - - void ListBox::OnCommand(WORD notification) noexcept { - if (notification == LBN_SELCHANGE) - { - int index = static_cast(SendMessage(window_handle_, LB_GETCURSEL, 0, 0)); - OnSelectionChanged(index); - } - } - -} // namespace maxGUI \ No newline at end of file +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include + +namespace maxGUI +{ + + ListBoxImplementation::ListBoxImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + ListBoxImplementation::~ListBoxImplementation() noexcept = default; + + HWND ListBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_STANDARD; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 +#pragma warning(push) +#pragma warning(disable: 26813) + if ((styles & ListBoxStyles::Disabled) == ListBoxStyles::Disabled) { + win32_styles |= WS_DISABLED; + } + if ((styles & ListBoxStyles::SingleClickMultipleSelection) == ListBoxStyles::SingleClickMultipleSelection) { + win32_styles |= LBS_MULTIPLESEL; + } + if ((styles & ListBoxStyles::KeyboardAndClickMultipleSelection) == ListBoxStyles::KeyboardAndClickMultipleSelection) { + win32_styles |= LBS_EXTENDEDSEL; + } +#pragma warning(pop) + HWND window_handle = CreateWindowEx(0, TEXT("LISTBOX"), TEXT(""), win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + + for (const auto& text : list) { + Win32String win32_text = Utf8ToWin32String(text); + SendMessage(window_handle, LB_ADDSTRING, 0, reinterpret_cast(win32_text.text_)); + } + + return window_handle; + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/ListBoxImplementation.hpp b/Code/maxGUI/ListBoxImplementation.hpp new file mode 100644 index 0000000..4b6f44b --- /dev/null +++ b/Code/maxGUI/ListBoxImplementation.hpp @@ -0,0 +1,55 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_LISTBOXIMPLEMENTATION_HPP +#define MAXGUI_LISTBOXIMPLEMENTATION_HPP + +#include +#include + +#include +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + +namespace maxGUI +{ + + enum class ListBoxStyles : uint8_t { + None = 0, + Disabled = 1, + SingleClickMultipleSelection = 2, + KeyboardAndClickMultipleSelection = 4, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::ListBoxStyles); + +namespace maxGUI +{ + + class ListBoxImplementation : public ControlWithTextImplementation + { + public: + + explicit ListBoxImplementation(HWND window_handle) noexcept; + + ~ListBoxImplementation() noexcept; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_LISTBOXIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/MultilineTextBox.hpp b/Code/maxGUI/MultilineTextBox.hpp index e9bb168..9a2ffc5 100644 --- a/Code/maxGUI/MultilineTextBox.hpp +++ b/Code/maxGUI/MultilineTextBox.hpp @@ -5,12 +5,12 @@ #ifndef MAXGUI_MULTILINETEXTBOX_HPP #define MAXGUI_MULTILINETEXTBOX_HPP +#include + #include -#include #include #include -#include -#include +#include #if defined(MAX_PLATFORM_LINUX) #include @@ -19,18 +19,10 @@ namespace maxGUI { - enum class MultilineTextBoxStyles : uint8_t { - None = 0, - Disabled = 1, + class DefaultMultilineTextBoxBehavior { }; - -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::MultilineTextBoxStyles); - -namespace maxGUI -{ + template< class Behavior = DefaultMultilineTextBoxBehavior > class MultilineTextBox : public ControlWithText { public: @@ -40,7 +32,8 @@ namespace maxGUI #elif defined(MAX_PLATFORM_LINUX) explicit MultilineTextBox(QTextEdit* widget) noexcept; #endif - ~MultilineTextBox() noexcept override = default; + + ~MultilineTextBox() noexcept; #if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles = MultilineTextBoxStyles::None) noexcept; @@ -48,8 +41,20 @@ namespace maxGUI static QTextEdit* Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles = MultilineTextBoxStyles::None) noexcept; #endif + //protected: +#if defined(MAX_PLATFORM_WINDOWS) + void OnCommand(WORD notification) noexcept override; +#endif + + private: + + Behavior behavior_; + MultilineTextBoxImplementation implementation_; + }; } // namespace maxGUI +#include + #endif // #ifndef MAXGUI_MULTILINETEXTBOX_HPP diff --git a/Code/maxGUI/MultilineTextBox.inl b/Code/maxGUI/MultilineTextBox.inl new file mode 100644 index 0000000..a4bec18 --- /dev/null +++ b/Code/maxGUI/MultilineTextBox.inl @@ -0,0 +1,64 @@ +// Copyright 2020, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif + +namespace maxGUI +{ + +#if defined(MAX_PLATFORM_WINDOWS) + template< class Behavior > + MultilineTextBox< Behavior >::MultilineTextBox(HWND window_handle) noexcept + : ControlWithText(window_handle) + , behavior_() + , implementation_(window_handle) + {} +#elif defined(MAX_PLATFORM_LINUX) + template< class Behavior > + MultilineTextBox< Behavior >::MultilineTextBox(QTextEdit* widget) noexcept + : ControlWithText() + , behavior_() + , implementation_() + { + (void)widget; + } +#endif + + template< class Behavior > + MultilineTextBox< Behavior >::~MultilineTextBox() noexcept = default; + +#if defined(MAX_PLATFORM_WINDOWS) + template< class Behavior > + HWND MultilineTextBox< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { + return MultilineTextBoxImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(text), std::move(styles)); + } +#elif defined(MAX_PLATFORM_LINUX) + template< class Behavior > + QTextEdit* MultilineTextBox< Behavior >::Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { + return MultilineTextBoxImplementation::Create(std::move(parent_window), std::move(rectangle), std::move(text), std::move(styles)); + } +#endif + +#if defined(MAX_PLATFORM_WINDOWS) + template< class Behavior > + void MultilineTextBox< Behavior >::OnCommand(WORD notification) noexcept { + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == EN_SETFOCUS ) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == EN_KILLFOCUS ) { + behavior_.OnLostFocus(&implementation_); + } + } + } +#endif + +} // namespace maxGUI diff --git a/Code/maxGUI/MultilineTextBox.cpp b/Code/maxGUI/MultilineTextBoxImplementation.cpp similarity index 71% rename from Code/maxGUI/MultilineTextBox.cpp rename to Code/maxGUI/MultilineTextBoxImplementation.cpp index 33ce0ac..7026811 100644 --- a/Code/maxGUI/MultilineTextBox.cpp +++ b/Code/maxGUI/MultilineTextBoxImplementation.cpp @@ -1,52 +1,44 @@ -// Copyright 2020, The maxGUI Contributors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#if defined(MAX_PLATFORM_WINDOWS) - #include -#endif - -#include - -namespace maxGUI -{ - -#if defined(MAX_PLATFORM_WINDOWS) - MultilineTextBox::MultilineTextBox(HWND window_handle) noexcept - : ControlWithText(std::move(window_handle)) - {} -#elif defined(MAX_PLATFORM_LINUX) - MultilineTextBox::MultilineTextBox(QTextEdit* widget) noexcept - : ControlWithText() - { - (void)widget; - } -#endif - -#if defined(MAX_PLATFORM_WINDOWS) - HWND MultilineTextBox::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 - #pragma warning(push) - #pragma warning(disable: 26813) - if ((styles & MultilineTextBoxStyles::Disabled) == MultilineTextBoxStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - #pragma warning(pop) - Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); - } -#elif defined(MAX_PLATFORM_LINUX) - QTextEdit* MultilineTextBox::Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { - QTextEdit* multiline_textbox = new QTextEdit(text.c_str(), parent_window); - multiline_textbox->setGeometry(rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height); - // TODO: Handle MultilineTextBoxStyles styles - return multiline_textbox; - } -#endif - -} // namespace maxGUI +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include + +namespace maxGUI +{ + + MultilineTextBoxImplementation::MultilineTextBoxImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + MultilineTextBoxImplementation::~MultilineTextBoxImplementation() noexcept = default; + +#if defined(MAX_PLATFORM_WINDOWS) + HWND MultilineTextBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 + #pragma warning(push) + #pragma warning(disable: 26813) + if ((styles & MultilineTextBoxStyles::Disabled) == MultilineTextBoxStyles::Disabled) { + win32_styles |= WS_DISABLED; + } + #pragma warning(pop) + Win32String win32_text = Utf8ToWin32String(std::move(text)); + return CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + } +#elif defined(MAX_PLATFORM_LINUX) + QTextEdit* MultilineTextBox::Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { + QTextEdit* multiline_textbox = new QTextEdit(text.c_str(), parent_window); + multiline_textbox->setGeometry(rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height); + // TODO: Handle MultilineTextBoxStyles styles + return multiline_textbox; + } +#endif + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/MultilineTextBoxImplementation.hpp b/Code/maxGUI/MultilineTextBoxImplementation.hpp new file mode 100644 index 0000000..57e6ae0 --- /dev/null +++ b/Code/maxGUI/MultilineTextBoxImplementation.hpp @@ -0,0 +1,52 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_MULTILINETEXTBOXIMPLEMENTATION_HPP +#define MAXGUI_MULTILINETEXTBOXIMPLEMENTATION_HPP + +#include + +#include +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + +namespace maxGUI +{ + + enum class MultilineTextBoxStyles : uint8_t { + None = 0, + Disabled = 1, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::MultilineTextBoxStyles); + +namespace maxGUI +{ + + class MultilineTextBoxImplementation : public ControlWithTextImplementation + { + public: + + explicit MultilineTextBoxImplementation(HWND window_handle) noexcept; + + ~MultilineTextBoxImplementation() noexcept; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles = MultilineTextBoxStyles::None) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_MULTILINETEXTBOXIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/RadioButton.hpp b/Code/maxGUI/RadioButton.hpp index cc94ba8..895f222 100644 --- a/Code/maxGUI/RadioButton.hpp +++ b/Code/maxGUI/RadioButton.hpp @@ -5,41 +5,30 @@ #ifndef MAXGUI_RADIOBUTTON_HPP #define MAXGUI_RADIOBUTTON_HPP - -#include - -#if defined(MAX_PLATFORM_WINDOWS) +#include #include +#include #include #include -#include -#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) namespace maxGUI { - enum class RadioButtonStyles : uint8_t { - None = 0, - Disabled = 1, - FirstInGroup = 2, - Flat = 4, + class DefaultRadioButtonBehavior { }; -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::RadioButtonStyles); - -namespace maxGUI -{ - + template< class Behavior = DefaultRadioButtonBehavior > class RadioButton : public ControlWithText { public: explicit RadioButton(HWND window_handle) noexcept; - ~RadioButton() noexcept override = default; + ~RadioButton() noexcept override; static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles styles = RadioButtonStyles::None) noexcept; @@ -49,10 +38,17 @@ namespace maxGUI void OnCommand(WORD notification) noexcept override; + private: + + Behavior behavior_; + RadioButtonImplementation implementation_; + }; } // namespace maxGUI #endif // #if defined(MAX_PLATFORM_WINDOWS) +#include + #endif // #ifndef MAXGUI_RADIOBUTTON_HPP \ No newline at end of file diff --git a/Code/maxGUI/RadioButton.inl b/Code/maxGUI/RadioButton.inl new file mode 100644 index 0000000..4942a75 --- /dev/null +++ b/Code/maxGUI/RadioButton.inl @@ -0,0 +1,48 @@ +// Copyright 2020, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +namespace maxGUI +{ + + template< class Behavior > + RadioButton< Behavior >::RadioButton(HWND window_handle) noexcept + : ControlWithText(window_handle) + , behavior_() + , implementation_(window_handle) + {} + + template< class Behavior > + RadioButton< Behavior >::~RadioButton() noexcept = default; + + template< class Behavior > + HWND RadioButton< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles style) noexcept { + return RadioButtonImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(text), std::move(style)); + } + + template< class Behavior > + void RadioButton< Behavior >::OnPressed() noexcept + {} + + template< class Behavior > + void RadioButton< Behavior >::OnCommand(WORD notification) noexcept { + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == BN_SETFOCUS ) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == BN_KILLFOCUS ) { + behavior_.OnLostFocus(&implementation_); + } + } + + if (notification == BN_CLICKED) { + OnPressed(); + } + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/RadioButton.cpp b/Code/maxGUI/RadioButtonImplementation.cpp similarity index 64% rename from Code/maxGUI/RadioButton.cpp rename to Code/maxGUI/RadioButtonImplementation.cpp index 1bad710..c64af78 100644 --- a/Code/maxGUI/RadioButton.cpp +++ b/Code/maxGUI/RadioButtonImplementation.cpp @@ -1,46 +1,41 @@ -// Copyright 2020, The maxGUI Contributors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include - -namespace maxGUI -{ - - RadioButton::RadioButton(HWND window_handle) noexcept - : ControlWithText(std::move(window_handle)) - {} - - HWND RadioButton::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles style) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 - #pragma warning(push) - #pragma warning(disable: 26813) - if ((style & RadioButtonStyles::Disabled) == RadioButtonStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - if ((style & RadioButtonStyles::FirstInGroup) == RadioButtonStyles::FirstInGroup) { - win32_styles |= WS_GROUP | WS_TABSTOP; - } - if ((style & RadioButtonStyles::Flat) == RadioButtonStyles::Flat) { - win32_styles |= BS_FLAT; - } - #pragma warning(pop) - Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); - } - - void RadioButton::OnPressed() noexcept - {} - - void RadioButton::OnCommand(WORD notification) noexcept { - if (notification == BN_CLICKED) { - OnPressed(); - } - } - -} // namespace maxGUI \ No newline at end of file +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include + +namespace maxGUI +{ + + RadioButtonImplementation::RadioButtonImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + RadioButtonImplementation::~RadioButtonImplementation() noexcept = default; + + HWND RadioButtonImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles style) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | BS_NOTIFY; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 +#pragma warning(push) +#pragma warning(disable: 26813) + if ((style & RadioButtonStyles::Disabled) == RadioButtonStyles::Disabled) { + win32_styles |= WS_DISABLED; + } + if ((style & RadioButtonStyles::FirstInGroup) == RadioButtonStyles::FirstInGroup) { + win32_styles |= WS_GROUP | WS_TABSTOP; + } + if ((style & RadioButtonStyles::Flat) == RadioButtonStyles::Flat) { + win32_styles |= BS_FLAT; + } +#pragma warning(pop) + Win32String win32_text = Utf8ToWin32String(std::move(text)); + return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/RadioButtonImplementation.hpp b/Code/maxGUI/RadioButtonImplementation.hpp new file mode 100644 index 0000000..0d3bb85 --- /dev/null +++ b/Code/maxGUI/RadioButtonImplementation.hpp @@ -0,0 +1,54 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_RADIOBUTTONIMPLEMENTATION_HPP +#define MAXGUI_RADIOBUTTONIMPLEMENTATION_HPP + +#include + +#include +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + +namespace maxGUI +{ + + enum class RadioButtonStyles : uint8_t { + None = 0, + Disabled = 1, + FirstInGroup = 2, + Flat = 4, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::RadioButtonStyles); + +namespace maxGUI +{ + + class RadioButtonImplementation : public ControlWithTextImplementation + { + public: + + explicit RadioButtonImplementation(HWND window_handle) noexcept; + + ~RadioButtonImplementation() noexcept; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles style) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_RADIOBUTTONIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Code/maxGUI/TextBox.hpp b/Code/maxGUI/TextBox.hpp index 5b0a74a..bb57235 100644 --- a/Code/maxGUI/TextBox.hpp +++ b/Code/maxGUI/TextBox.hpp @@ -5,50 +5,43 @@ #ifndef MAXGUI_TEXTBOX_HPP #define MAXGUI_TEXTBOX_HPP -#include -#include -#include #include -#include - #include - -// TODO: Add Linux version of TextBox -#if defined(MAX_PLATFORM_WINDOWS) +#include +#include +#include namespace maxGUI { - enum class TextBoxStyles : uint8_t { - None = 0, - Disabled = 1, - Password = 2, - ReadOnly = 4, + class DefaultTextBoxBehavior { }; -} // namespace maxGUI - -MAX_BITMASKABLE_ENUM_CLASS(maxGUI::TextBoxStyles); - -namespace maxGUI -{ - + template< class Behavior = DefaultTextBoxBehavior > class TextBox : public ControlWithText { public: explicit TextBox(HWND window_handle) noexcept; - ~TextBox() noexcept override = default; + ~TextBox() noexcept override; static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles = TextBoxStyles::None) noexcept; + //protected: + +#if defined(MAX_PLATFORM_WINDOWS) + void OnCommand(WORD notification) noexcept override; +#endif + + Behavior behavior_; + TextBoxImplementation implementation_; + }; } // namespace maxGUI - -#endif // #if defined(MAX_PLATFORM_WINDOWS) +#include #endif // #ifndef MAXGUI_TEXTBOX_HPP \ No newline at end of file diff --git a/Code/maxGUI/TextBox.inl b/Code/maxGUI/TextBox.inl new file mode 100644 index 0000000..d56865f --- /dev/null +++ b/Code/maxGUI/TextBox.inl @@ -0,0 +1,44 @@ +// Copyright 2020, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +namespace maxGUI +{ + + template< class Behavior > + TextBox< Behavior >::TextBox(HWND window_handle) noexcept + : ControlWithText(window_handle) + , behavior_() + , implementation_(window_handle) + {} + + template< class Behavior > + TextBox< Behavior >::~TextBox() noexcept = default; + + template< class Behavior > + HWND TextBox< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles) noexcept { + return TextBoxImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(text), std::move(styles)); + } + +#if defined(MAX_PLATFORM_WINDOWS) + template< class Behavior > + void TextBox< Behavior >::OnCommand(WORD notification) noexcept { + if constexpr (HasOnGainedFocus< Behavior >::value) { + if (notification == EN_SETFOCUS ) { + behavior_.OnGainedFocus(&implementation_); + } + } + + if constexpr (HasOnLostFocus< Behavior >::value) { + if (notification == EN_KILLFOCUS ) { + behavior_.OnLostFocus(&implementation_); + } + } + } +#endif + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/TextBox.cpp b/Code/maxGUI/TextBoxImplementation.cpp similarity index 63% rename from Code/maxGUI/TextBox.cpp rename to Code/maxGUI/TextBoxImplementation.cpp index 30a9450..aca9286 100644 --- a/Code/maxGUI/TextBox.cpp +++ b/Code/maxGUI/TextBoxImplementation.cpp @@ -1,55 +1,57 @@ -// Copyright 2020, The maxGUI Contributors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include -#include -#include - -namespace maxGUI -{ - - TextBox::TextBox(HWND window_handle) noexcept - : ControlWithText(std::move(window_handle)) - {} - - HWND TextBox::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles) noexcept { - DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL; - // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" - // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. - // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 - #pragma warning(push) - #pragma warning(disable: 26813) - if ((styles & TextBoxStyles::Disabled) == TextBoxStyles::Disabled) { - win32_styles |= WS_DISABLED; - } - if ((styles & TextBoxStyles::Password) == TextBoxStyles::Password) { - win32_styles |= ES_PASSWORD; - } - if ((styles & TextBoxStyles::ReadOnly) == TextBoxStyles::ReadOnly) { - win32_styles |= ES_READONLY; - } - #pragma warning(pop) - - //EM_GETSEL - Gets the starting (low-order word) and ending (first nonselected char, high-order word) character positions of the current selection. - //EM_LIMITTEXT - wParam holds max number of chars. If this is zero, the text length is set to the maximum number of bytes possible. - //EM_REPLACESEL - pointer to the text in the lParam parameter. The new text must be null-terminated. - //EM_SETPASSWORDCHAR - new password character in the wParam parameter. Doesn't work on multi-line - //EM_SETSEL - lParam specifies the starting (low-order word) and ending (high-order word) character for the selection. - //To select the 10th through 20th characters in an edit control: - //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(9,19) ); - //To deselect a selection: - //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(0xffff, 0) ); - //To set the caret at the end of the edit control: - //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(0xffff, 0xffff) ); - //To set the caret after the position of the Nth character: - //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(N, N) ); - //EN_UPDATE - text changed - - Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); - } - -} // namespace maxGUI \ No newline at end of file +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include + +namespace maxGUI +{ + + TextBoxImplementation::TextBoxImplementation(HWND window_handle) noexcept + : ControlWithTextImplementation(std::move(window_handle)) + {} + + TextBoxImplementation::~TextBoxImplementation() noexcept = default; + + HWND TextBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles) noexcept { + DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL; + // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" + // But this doesn't play nicely with enum classes because ultimately it needs to convert to bool. + // See https://developercommunity.visualstudio.com/t/C26813-incompatible-with-enum-class/10145182 +#pragma warning(push) +#pragma warning(disable: 26813) + if ((styles & TextBoxStyles::Disabled) == TextBoxStyles::Disabled) { + win32_styles |= WS_DISABLED; + } + if ((styles & TextBoxStyles::Password) == TextBoxStyles::Password) { + win32_styles |= ES_PASSWORD; + } + if ((styles & TextBoxStyles::ReadOnly) == TextBoxStyles::ReadOnly) { + win32_styles |= ES_READONLY; + } +#pragma warning(pop) + + //EM_GETSEL - Gets the starting (low-order word) and ending (first nonselected char, high-order word) character positions of the current selection. + //EM_LIMITTEXT - wParam holds max number of chars. If this is zero, the text length is set to the maximum number of bytes possible. + //EM_REPLACESEL - pointer to the text in the lParam parameter. The new text must be null-terminated. + //EM_SETPASSWORDCHAR - new password character in the wParam parameter. Doesn't work on multi-line + //EM_SETSEL - lParam specifies the starting (low-order word) and ending (high-order word) character for the selection. + //To select the 10th through 20th characters in an edit control: + //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(9,19) ); + //To deselect a selection: + //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(0xffff, 0) ); + //To set the caret at the end of the edit control: + //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(0xffff, 0xffff) ); + //To set the caret after the position of the Nth character: + //SendMessage(hEditWnd, EM_SETSEL, 0, MAKELONG(N, N) ); + //EN_UPDATE - text changed + + Win32String win32_text = Utf8ToWin32String(std::move(text)); + return CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + } + +} // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/TextBoxImplementation.hpp b/Code/maxGUI/TextBoxImplementation.hpp new file mode 100644 index 0000000..3978782 --- /dev/null +++ b/Code/maxGUI/TextBoxImplementation.hpp @@ -0,0 +1,55 @@ +// Copyright 2023, The maxGUI Contributors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MAXGUI_TEXTBOXIMPLEMENTATION_HPP +#define MAXGUI_TEXTBOXIMPLEMENTATION_HPP + +#include + +#include +#include +#include +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include +#endif + + +namespace maxGUI +{ + + enum class TextBoxStyles : uint8_t { + None = 0, + Disabled = 1, + Password = 2, + ReadOnly = 4, + }; + +} // namespace maxGUI + +MAX_BITMASKABLE_ENUM_CLASS(maxGUI::TextBoxStyles); + +namespace maxGUI +{ + + class TextBoxImplementation : public ControlWithTextImplementation + { + public: + + explicit TextBoxImplementation(HWND window_handle) noexcept; + + ~TextBoxImplementation() noexcept override; + + static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles) noexcept; + + }; + +} // namespace maxGUI + +#endif // #ifndef MAXGUI_TEXTBOXIMPLEMENTATION_HPP \ No newline at end of file diff --git a/Projects/VisualStudio/maxGUI/maxGUI.vcxproj b/Projects/VisualStudio/maxGUI/maxGUI.vcxproj index 1f9bd05..8fe63e1 100644 --- a/Projects/VisualStudio/maxGUI/maxGUI.vcxproj +++ b/Projects/VisualStudio/maxGUI/maxGUI.vcxproj @@ -24,9 +24,15 @@ + + + + + + @@ -43,30 +49,38 @@ - + + + - + + - - + + - - + + + + + + + @@ -78,11 +92,15 @@ + + + + @@ -193,6 +211,7 @@ true stdcpplatest + true Windows @@ -211,6 +230,7 @@ true stdcpplatest + true Windows @@ -231,6 +251,7 @@ true stdcpplatest + true Windows @@ -253,6 +274,7 @@ true stdcpplatest + true Windows diff --git a/Projects/VisualStudio/maxGUI/maxGUI.vcxproj.filters b/Projects/VisualStudio/maxGUI/maxGUI.vcxproj.filters index 2902d3f..c0aa93c 100644 --- a/Projects/VisualStudio/maxGUI/maxGUI.vcxproj.filters +++ b/Projects/VisualStudio/maxGUI/maxGUI.vcxproj.filters @@ -101,6 +101,24 @@ Dependencies\max\Containers + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + @@ -114,55 +132,64 @@ Code - - Code - Code Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code - + + Code + + + Code + + + Code + + + Code + + Code @@ -293,5 +320,32 @@ Dependencies\max\Compiling + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + \ No newline at end of file From 23562d3732d2ac8de3feb263e2a957be8a11a731 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:10:26 -0400 Subject: [PATCH 02/13] Fix Linux builds --- Code/maxGUI/ButtonImplementation.cpp | 15 ++++++++++++++- Code/maxGUI/ButtonImplementation.hpp | 4 ++++ Code/maxGUI/ControlWithTextImplementation.cpp | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Code/maxGUI/ButtonImplementation.cpp b/Code/maxGUI/ButtonImplementation.cpp index c59f0e2..00404a7 100644 --- a/Code/maxGUI/ButtonImplementation.cpp +++ b/Code/maxGUI/ButtonImplementation.cpp @@ -9,9 +9,11 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) ButtonImplementation::ButtonImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif ButtonImplementation::~ButtonImplementation() noexcept = default; @@ -36,7 +38,18 @@ namespace maxGUI Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + //return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + HWND window_handle = CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + + const int font_height_in_points = 10; + HDC screen_device_context = GetDC(NULL); + const int font_height_in_logical_units = -MulDiv(font_height_in_points, GetDeviceCaps(screen_device_context, LOGPIXELSY), 72); + //const int font_height_in_logical_units = -12; + HFONT font = CreateFont(font_height_in_logical_units, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, TEXT("Segoe UI")); + + SendMessage(window_handle, WM_SETFONT, reinterpret_cast(font), TRUE); + + return window_handle; } #endif diff --git a/Code/maxGUI/ButtonImplementation.hpp b/Code/maxGUI/ButtonImplementation.hpp index 2ca6180..14f1277 100644 --- a/Code/maxGUI/ButtonImplementation.hpp +++ b/Code/maxGUI/ButtonImplementation.hpp @@ -42,11 +42,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit ButtonImplementation(HWND window_handle) noexcept; +#endif ~ButtonImplementation() noexcept; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, ButtonStyles styles) noexcept; +#endif }; diff --git a/Code/maxGUI/ControlWithTextImplementation.cpp b/Code/maxGUI/ControlWithTextImplementation.cpp index 66ac797..6c6a8a0 100644 --- a/Code/maxGUI/ControlWithTextImplementation.cpp +++ b/Code/maxGUI/ControlWithTextImplementation.cpp @@ -9,9 +9,11 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) ControlWithTextImplementation::ControlWithTextImplementation(HWND window_handle) noexcept : ControlImplementation(std::move(window_handle)) {} +#endif ControlWithTextImplementation::~ControlWithTextImplementation() noexcept = default; From c0440cd69fcaa7019bfcafa0dc93e486bf71fa15 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:17:50 -0400 Subject: [PATCH 03/13] Remove HWND from Linux build --- Code/maxGUI/ControlImplementation.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/maxGUI/ControlImplementation.hpp b/Code/maxGUI/ControlImplementation.hpp index 6b03407..dcb6687 100644 --- a/Code/maxGUI/ControlImplementation.hpp +++ b/Code/maxGUI/ControlImplementation.hpp @@ -30,7 +30,9 @@ namespace maxGUI //private: +#if defined(MAX_PLATFORM_WINDOWS) HWND window_handle_; +#endif }; From f81f0f3223dee504e0044c2dc29c9db8456ef95d Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:28:52 -0400 Subject: [PATCH 04/13] Update Makefiles --- Projects/Clang X86 Make/Makefile | 16 +++++++++------- Projects/Clang X86-64 Make/Makefile | 16 +++++++++------- Projects/GCC X86 Make/Makefile | 18 ++++++++++-------- Projects/GCC X86-64 Make/Makefile | 16 +++++++++------- 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/Projects/Clang X86 Make/Makefile b/Projects/Clang X86 Make/Makefile index 5b8e421..048539d 100644 --- a/Projects/Clang X86 Make/Makefile +++ b/Projects/Clang X86 Make/Makefile @@ -1,22 +1,24 @@ PROGRAM_NAME = maxGUI CXX_SRCS = \ - ../../Code/maxGUI/Button.cpp \ + ../../Code/maxGUI/ButtonImplementation.cpp \ ../../Code/maxGUI/Control.cpp \ + ../../Code/maxGUI/ControlImplementation.cpp \ ../../Code/maxGUI/ControlWithText.cpp \ + ../../Code/maxGUI/ControlWithTextImplementation.cpp \ ../../Code/maxGUI/EntryPoint.cpp \ ../../Code/maxGUI/FormAllocatorConcept.cpp \ ../../Code/maxGUI/FormConcept.cpp \ ../../Code/maxGUI/FormContainer.cpp \ - ../../Code/maxGUI/MultilineTextBox.cpp - #../../Code/maxGUI/CheckBox.cpp \ + ../../Code/maxGUI/MultilineTextBoxImplementation.cpp + #../../Code/maxGUI/CheckBoxImplementation.cpp \ #../../Code/maxGUI/ControlWithList.cpp \ - #../../Code/maxGUI/DropDownBox.cpp \ + #../../Code/maxGUI/DropDownBoxImplementation.cpp \ #../../Code/maxGUI/Frame.cpp \ #../../Code/maxGUI/Label.cpp \ - #../../Code/maxGUI/ListBox.cpp \ + #../../Code/maxGUI/ListBoxImplementation.cpp \ #../../Code/maxGUI/ProgressBar.cpp \ - #../../Code/maxGUI/RadioButton.cpp \ - #../../Code/maxGUI/TextBox.cpp + #../../Code/maxGUI/RadioButtonImplementation.cpp \ + #../../Code/maxGUI/TextBoxImplementation.cpp CXX_OBJS = $(CXX_SRCS:.cpp=.o) INCLUDE_PATHS = \ diff --git a/Projects/Clang X86-64 Make/Makefile b/Projects/Clang X86-64 Make/Makefile index 32c29ad..efb7ba8 100644 --- a/Projects/Clang X86-64 Make/Makefile +++ b/Projects/Clang X86-64 Make/Makefile @@ -1,22 +1,24 @@ PROGRAM_NAME = maxGUI CXX_SRCS = \ - ../../Code/maxGUI/Button.cpp \ + ../../Code/maxGUI/ButtonImplementation.cpp \ ../../Code/maxGUI/Control.cpp \ + ../../Code/maxGUI/ControlImplementation.cpp \ ../../Code/maxGUI/ControlWithText.cpp \ + ../../Code/maxGUI/ControlWithTextImplementation.cpp \ ../../Code/maxGUI/EntryPoint.cpp \ ../../Code/maxGUI/FormAllocatorConcept.cpp \ ../../Code/maxGUI/FormConcept.cpp \ ../../Code/maxGUI/FormContainer.cpp \ - ../../Code/maxGUI/MultilineTextBox.cpp - #../../Code/maxGUI/CheckBox.cpp \ + ../../Code/maxGUI/MultilineTextBoxImplementation.cpp + #../../Code/maxGUI/CheckBoxImplementation.cpp \ #../../Code/maxGUI/ControlWithList.cpp \ - #../../Code/maxGUI/DropDownBox.cpp \ + #../../Code/maxGUI/DropDownBoxImplementation.cpp \ #../../Code/maxGUI/Frame.cpp \ #../../Code/maxGUI/Label.cpp \ - #../../Code/maxGUI/ListBox.cpp \ + #../../Code/maxGUI/ListBoxImplementation.cpp \ #../../Code/maxGUI/ProgressBar.cpp \ - #../../Code/maxGUI/RadioButton.cpp \ - #../../Code/maxGUI/TextBox.cpp + #../../Code/maxGUI/RadioButtonImplementation.cpp \ + #../../Code/maxGUI/TextBoxImplementation.cpp CXX_OBJS = $(CXX_SRCS:.cpp=.o) INCLUDE_PATHS = \ diff --git a/Projects/GCC X86 Make/Makefile b/Projects/GCC X86 Make/Makefile index e6a9702..e3446ca 100644 --- a/Projects/GCC X86 Make/Makefile +++ b/Projects/GCC X86 Make/Makefile @@ -1,22 +1,24 @@ PROGRAM_NAME = maxGUI CXX_SRCS = \ - ../../Code/maxGUI/Button.cpp \ + ../../Code/maxGUI/ButtonImplementation.cpp \ ../../Code/maxGUI/Control.cpp \ + ../../Code/maxGUI/ControlImplementation.cpp \ ../../Code/maxGUI/ControlWithText.cpp \ + ../../Code/maxGUI/ControlWithTextImplementation.cpp \ ../../Code/maxGUI/EntryPoint.cpp \ - ../../Code/maxGUI/FormAllocatorConcept.cpp \ + ../../Code/maxGUI/FormAllocatorConcept.cpp \ ../../Code/maxGUI/FormConcept.cpp \ ../../Code/maxGUI/FormContainer.cpp \ - ../../Code/maxGUI/MultilineTextBox.cpp - #../../Code/maxGUI/CheckBox.cpp \ + ../../Code/maxGUI/MultilineTextBoxImplementation.cpp + #../../Code/maxGUI/CheckBoxImplementation.cpp \ #../../Code/maxGUI/ControlWithList.cpp \ - #../../Code/maxGUI/DropDownBox.cpp \ + #../../Code/maxGUI/DropDownBoxImplementation.cpp \ #../../Code/maxGUI/Frame.cpp \ #../../Code/maxGUI/Label.cpp \ - #../../Code/maxGUI/ListBox.cpp \ + #../../Code/maxGUI/ListBoxImplementation.cpp \ #../../Code/maxGUI/ProgressBar.cpp \ - #../../Code/maxGUI/RadioButton.cpp \ - #../../Code/maxGUI/TextBox.cpp + #../../Code/maxGUI/RadioButtonImplementation.cpp \ + #../../Code/maxGUI/TextBoxImplementation.cpp CXX_OBJS = $(CXX_SRCS:.cpp=.o) INCLUDE_PATHS = \ diff --git a/Projects/GCC X86-64 Make/Makefile b/Projects/GCC X86-64 Make/Makefile index d9f8ce9..e2c68fa 100644 --- a/Projects/GCC X86-64 Make/Makefile +++ b/Projects/GCC X86-64 Make/Makefile @@ -1,22 +1,24 @@ PROGRAM_NAME = maxGUI CXX_SRCS = \ - ../../Code/maxGUI/Button.cpp \ + ../../Code/maxGUI/ButtonImplementation.cpp \ ../../Code/maxGUI/Control.cpp \ + ../../Code/maxGUI/ControlImplementation.cpp \ ../../Code/maxGUI/ControlWithText.cpp \ + ../../Code/maxGUI/ControlWithTextImplementation.cpp \ ../../Code/maxGUI/EntryPoint.cpp \ ../../Code/maxGUI/FormAllocatorConcept.cpp \ ../../Code/maxGUI/FormConcept.cpp \ ../../Code/maxGUI/FormContainer.cpp \ - ../../Code/maxGUI/MultilineTextBox.cpp - #../../Code/maxGUI/CheckBox.cpp \ + ../../Code/maxGUI/MultilineTextBoxImplementation.cpp + #../../Code/maxGUI/CheckBoxImplementation.cpp \ #../../Code/maxGUI/ControlWithList.cpp \ - #../../Code/maxGUI/DropDownBox.cpp \ + #../../Code/maxGUI/DropDownBoxImplementation.cpp \ #../../Code/maxGUI/Frame.cpp \ #../../Code/maxGUI/Label.cpp \ - #../../Code/maxGUI/ListBox.cpp \ + #../../Code/maxGUI/ListBoxImplementation.cpp \ #../../Code/maxGUI/ProgressBar.cpp \ - #../../Code/maxGUI/RadioButton.cpp \ - #../../Code/maxGUI/TextBox.cpp + #../../Code/maxGUI/RadioButtonImplementation.cpp \ + #../../Code/maxGUI/TextBoxImplementation.cpp CXX_OBJS = $(CXX_SRCS:.cpp=.o) INCLUDE_PATHS = \ From 51aa568ebcaa10ab5a45ab9ce734d7fcdebf15de Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:36:33 -0400 Subject: [PATCH 05/13] Only include Win32String.hpp on Windows builds --- Code/maxGUI/ButtonImplementation.cpp | 4 ++- Code/maxGUI/CheckBoxImplementation.cpp | 23 +++++++++++++++-- Code/maxGUI/ControlWithTextImplementation.cpp | 4 ++- Code/maxGUI/DropDownBoxImplementation.cpp | 4 ++- Code/maxGUI/ListBoxImplementation.cpp | 4 ++- .../maxGUI/MultilineTextBoxImplementation.cpp | 4 ++- Code/maxGUI/RadioButtonImplementation.cpp | 25 +++++++++++++++++-- Code/maxGUI/TextBoxImplementation.cpp | 4 ++- 8 files changed, 62 insertions(+), 10 deletions(-) diff --git a/Code/maxGUI/ButtonImplementation.cpp b/Code/maxGUI/ButtonImplementation.cpp index 00404a7..23a42fd 100644 --- a/Code/maxGUI/ButtonImplementation.cpp +++ b/Code/maxGUI/ButtonImplementation.cpp @@ -4,7 +4,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { diff --git a/Code/maxGUI/CheckBoxImplementation.cpp b/Code/maxGUI/CheckBoxImplementation.cpp index 2ffeadb..1e89bf3 100644 --- a/Code/maxGUI/CheckBoxImplementation.cpp +++ b/Code/maxGUI/CheckBoxImplementation.cpp @@ -6,7 +6,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { @@ -33,7 +35,24 @@ namespace maxGUI } #pragma warning(pop) Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + //return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + HWND window_handle = CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + + /* + LOGFONT lf; + SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); + HFONT font = CreateFontIndirect(&lf); + */ + + const int font_height_in_points = 10; + HDC screen_device_context = GetDC(NULL); + const int font_height_in_logical_units = -MulDiv(font_height_in_points, GetDeviceCaps(screen_device_context, LOGPIXELSY), 72); + //const int font_height_in_logical_units = -12; + HFONT font = CreateFont(font_height_in_logical_units, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, TEXT("Segoe UI")); + + SendMessage(window_handle, WM_SETFONT, reinterpret_cast(font), TRUE); + + return window_handle; } bool CheckBoxImplementation::IsChecked() const noexcept { diff --git a/Code/maxGUI/ControlWithTextImplementation.cpp b/Code/maxGUI/ControlWithTextImplementation.cpp index 6c6a8a0..0bec91f 100644 --- a/Code/maxGUI/ControlWithTextImplementation.cpp +++ b/Code/maxGUI/ControlWithTextImplementation.cpp @@ -4,7 +4,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { diff --git a/Code/maxGUI/DropDownBoxImplementation.cpp b/Code/maxGUI/DropDownBoxImplementation.cpp index 5be92fe..c0de1d5 100644 --- a/Code/maxGUI/DropDownBoxImplementation.cpp +++ b/Code/maxGUI/DropDownBoxImplementation.cpp @@ -6,7 +6,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { diff --git a/Code/maxGUI/ListBoxImplementation.cpp b/Code/maxGUI/ListBoxImplementation.cpp index b0b08da..de26865 100644 --- a/Code/maxGUI/ListBoxImplementation.cpp +++ b/Code/maxGUI/ListBoxImplementation.cpp @@ -6,7 +6,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { diff --git a/Code/maxGUI/MultilineTextBoxImplementation.cpp b/Code/maxGUI/MultilineTextBoxImplementation.cpp index 7026811..acefd46 100644 --- a/Code/maxGUI/MultilineTextBoxImplementation.cpp +++ b/Code/maxGUI/MultilineTextBoxImplementation.cpp @@ -6,7 +6,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { diff --git a/Code/maxGUI/RadioButtonImplementation.cpp b/Code/maxGUI/RadioButtonImplementation.cpp index c64af78..1bea08f 100644 --- a/Code/maxGUI/RadioButtonImplementation.cpp +++ b/Code/maxGUI/RadioButtonImplementation.cpp @@ -6,7 +6,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { @@ -35,7 +37,26 @@ namespace maxGUI } #pragma warning(pop) Win32String win32_text = Utf8ToWin32String(std::move(text)); - return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + //return CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + HWND window_handle = CreateWindowEx(0, TEXT("BUTTON"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); + + static int count = 0; + if (count == 0) { + LOGFONT lf = {0}; + SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); + HFONT font = CreateFontIndirect(&lf); + SendMessage(window_handle, WM_SETFONT, reinterpret_cast(font), TRUE); + } else { + //const int font_height_in_points = 14; + //HDC screen_device_context = GetDC(NULL); + //const int font_height_in_logical_units = -MulDiv(font_height_in_points, GetDeviceCaps(screen_device_context, LOGPIXELSY), 72); + const int font_height_in_logical_units = -14; + HFONT font = CreateFont(font_height_in_logical_units, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, TEXT("Segoe UI Variable")); + SendMessage(window_handle, WM_SETFONT, reinterpret_cast(font), TRUE); } + count++; + + return window_handle; + } } // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/TextBoxImplementation.cpp b/Code/maxGUI/TextBoxImplementation.cpp index aca9286..41fca49 100644 --- a/Code/maxGUI/TextBoxImplementation.cpp +++ b/Code/maxGUI/TextBoxImplementation.cpp @@ -6,7 +6,9 @@ #include -#include +#if defined(MAX_PLATFORM_WINDOWS) + #include +#endif namespace maxGUI { From 347de4298ab0b6ca18b27a671f22b6c4475a2f38 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:44:32 -0400 Subject: [PATCH 06/13] Block HWND-using functions on Linux builds --- Code/maxGUI/CheckBoxImplementation.cpp | 2 ++ Code/maxGUI/CheckBoxImplementation.hpp | 4 ++++ Code/maxGUI/DropDownBoxImplementation.cpp | 4 ++++ Code/maxGUI/DropDownBoxImplementation.hpp | 4 ++++ Code/maxGUI/ListBoxImplementation.cpp | 4 ++++ Code/maxGUI/ListBoxImplementation.hpp | 4 ++++ Code/maxGUI/MultilineTextBoxImplementation.cpp | 2 ++ Code/maxGUI/MultilineTextBoxImplementation.hpp | 4 ++++ Code/maxGUI/RadioButtonImplementation.cpp | 4 ++++ Code/maxGUI/RadioButtonImplementation.hpp | 4 ++++ Code/maxGUI/TextBoxImplementation.cpp | 4 ++++ Code/maxGUI/TextBoxImplementation.hpp | 4 ++++ 12 files changed, 44 insertions(+) diff --git a/Code/maxGUI/CheckBoxImplementation.cpp b/Code/maxGUI/CheckBoxImplementation.cpp index 1e89bf3..b65a02d 100644 --- a/Code/maxGUI/CheckBoxImplementation.cpp +++ b/Code/maxGUI/CheckBoxImplementation.cpp @@ -13,9 +13,11 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) CheckBoxImplementation::CheckBoxImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif CheckBoxImplementation::~CheckBoxImplementation() noexcept = default; diff --git a/Code/maxGUI/CheckBoxImplementation.hpp b/Code/maxGUI/CheckBoxImplementation.hpp index da0ab6d..04fec73 100644 --- a/Code/maxGUI/CheckBoxImplementation.hpp +++ b/Code/maxGUI/CheckBoxImplementation.hpp @@ -40,11 +40,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit CheckBoxImplementation(HWND window_handle) noexcept; +#endif ~CheckBoxImplementation() noexcept; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, CheckBoxStyles styles) noexcept; +#endif bool IsChecked() const noexcept; void Check() noexcept; diff --git a/Code/maxGUI/DropDownBoxImplementation.cpp b/Code/maxGUI/DropDownBoxImplementation.cpp index c0de1d5..b42a190 100644 --- a/Code/maxGUI/DropDownBoxImplementation.cpp +++ b/Code/maxGUI/DropDownBoxImplementation.cpp @@ -13,12 +13,15 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) DropDownBoxImplementation::DropDownBoxImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif DropDownBoxImplementation::~DropDownBoxImplementation() noexcept = default; +#if defined(MAX_PLATFORM_WINDOWS) HWND DropDownBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles) noexcept { DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS /*| CBS_DROPDOWNLIST*/; // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" @@ -44,5 +47,6 @@ namespace maxGUI return window_handle; } +#endif } // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/DropDownBoxImplementation.hpp b/Code/maxGUI/DropDownBoxImplementation.hpp index cba254b..7b0fa91 100644 --- a/Code/maxGUI/DropDownBoxImplementation.hpp +++ b/Code/maxGUI/DropDownBoxImplementation.hpp @@ -40,11 +40,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit DropDownBoxImplementation(HWND window_handle) noexcept; +#endif ~DropDownBoxImplementation() noexcept; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, DropDownBoxStyles styles) noexcept; +#endif }; diff --git a/Code/maxGUI/ListBoxImplementation.cpp b/Code/maxGUI/ListBoxImplementation.cpp index de26865..369ad69 100644 --- a/Code/maxGUI/ListBoxImplementation.cpp +++ b/Code/maxGUI/ListBoxImplementation.cpp @@ -13,12 +13,15 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) ListBoxImplementation::ListBoxImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif ListBoxImplementation::~ListBoxImplementation() noexcept = default; +#if defined(MAX_PLATFORM_WINDOWS) HWND ListBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles) noexcept { DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_STANDARD; // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" @@ -45,5 +48,6 @@ namespace maxGUI return window_handle; } +#endif } // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/ListBoxImplementation.hpp b/Code/maxGUI/ListBoxImplementation.hpp index 4b6f44b..d57335a 100644 --- a/Code/maxGUI/ListBoxImplementation.hpp +++ b/Code/maxGUI/ListBoxImplementation.hpp @@ -42,11 +42,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit ListBoxImplementation(HWND window_handle) noexcept; +#endif ~ListBoxImplementation() noexcept; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::vector list, ListBoxStyles styles) noexcept; +#endif }; diff --git a/Code/maxGUI/MultilineTextBoxImplementation.cpp b/Code/maxGUI/MultilineTextBoxImplementation.cpp index acefd46..a188c5e 100644 --- a/Code/maxGUI/MultilineTextBoxImplementation.cpp +++ b/Code/maxGUI/MultilineTextBoxImplementation.cpp @@ -13,9 +13,11 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) MultilineTextBoxImplementation::MultilineTextBoxImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif MultilineTextBoxImplementation::~MultilineTextBoxImplementation() noexcept = default; diff --git a/Code/maxGUI/MultilineTextBoxImplementation.hpp b/Code/maxGUI/MultilineTextBoxImplementation.hpp index 57e6ae0..94be3f2 100644 --- a/Code/maxGUI/MultilineTextBoxImplementation.hpp +++ b/Code/maxGUI/MultilineTextBoxImplementation.hpp @@ -39,11 +39,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit MultilineTextBoxImplementation(HWND window_handle) noexcept; +#endif ~MultilineTextBoxImplementation() noexcept; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles = MultilineTextBoxStyles::None) noexcept; +#endif }; diff --git a/Code/maxGUI/RadioButtonImplementation.cpp b/Code/maxGUI/RadioButtonImplementation.cpp index 1bea08f..d00acc4 100644 --- a/Code/maxGUI/RadioButtonImplementation.cpp +++ b/Code/maxGUI/RadioButtonImplementation.cpp @@ -13,12 +13,15 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) RadioButtonImplementation::RadioButtonImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif RadioButtonImplementation::~RadioButtonImplementation() noexcept = default; +#if defined(MAX_PLATFORM_WINDOWS) HWND RadioButtonImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles style) noexcept { DWORD win32_styles = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | BS_NOTIFY; // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" @@ -58,5 +61,6 @@ namespace maxGUI return window_handle; } +#endif } // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/RadioButtonImplementation.hpp b/Code/maxGUI/RadioButtonImplementation.hpp index 0d3bb85..de5f465 100644 --- a/Code/maxGUI/RadioButtonImplementation.hpp +++ b/Code/maxGUI/RadioButtonImplementation.hpp @@ -41,11 +41,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit RadioButtonImplementation(HWND window_handle) noexcept; +#endif ~RadioButtonImplementation() noexcept; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, RadioButtonStyles style) noexcept; +#endif }; diff --git a/Code/maxGUI/TextBoxImplementation.cpp b/Code/maxGUI/TextBoxImplementation.cpp index 41fca49..3bd00bd 100644 --- a/Code/maxGUI/TextBoxImplementation.cpp +++ b/Code/maxGUI/TextBoxImplementation.cpp @@ -13,12 +13,15 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) TextBoxImplementation::TextBoxImplementation(HWND window_handle) noexcept : ControlWithTextImplementation(std::move(window_handle)) {} +#endif TextBoxImplementation::~TextBoxImplementation() noexcept = default; +#if defined(MAX_PLATFORM_WINDOWS) HWND TextBoxImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles) noexcept { DWORD win32_styles = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL; // MSVC at warning level 4 issues C26813 because it wants "if (styles & ButtonStyles::Default) {" @@ -55,5 +58,6 @@ namespace maxGUI Win32String win32_text = Utf8ToWin32String(std::move(text)); return CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); } +#endif } // namespace maxGUI \ No newline at end of file diff --git a/Code/maxGUI/TextBoxImplementation.hpp b/Code/maxGUI/TextBoxImplementation.hpp index 3978782..eed1ff0 100644 --- a/Code/maxGUI/TextBoxImplementation.hpp +++ b/Code/maxGUI/TextBoxImplementation.hpp @@ -42,11 +42,15 @@ namespace maxGUI { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit TextBoxImplementation(HWND window_handle) noexcept; +#endif ~TextBoxImplementation() noexcept override; +#if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, TextBoxStyles styles) noexcept; +#endif }; From 6d0c499de0923d74a0bab40d528b74528289a211 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:49:00 -0400 Subject: [PATCH 07/13] Include Linux MultilineTextBox::Create() --- Code/maxGUI/MultilineTextBoxImplementation.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/maxGUI/MultilineTextBoxImplementation.hpp b/Code/maxGUI/MultilineTextBoxImplementation.hpp index 94be3f2..0643200 100644 --- a/Code/maxGUI/MultilineTextBoxImplementation.hpp +++ b/Code/maxGUI/MultilineTextBoxImplementation.hpp @@ -18,6 +18,8 @@ #endif #include +#elif defined(MAX_PLATFORM_LINUX) + #include #endif namespace maxGUI @@ -47,6 +49,8 @@ namespace maxGUI #if defined(MAX_PLATFORM_WINDOWS) static HWND Create(HWND parent_window_handle, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles = MultilineTextBoxStyles::None) noexcept; +#elif defined(MAX_PLATFORM_LINUX) + static QTextEdit* Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles = MultilineTextBoxStyles::None) noexcept; #endif }; From c2fba3da0e5def830231d7d0631e0746233dd1f0 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 16:53:40 -0400 Subject: [PATCH 08/13] Fix misattributed function --- Code/maxGUI/MultilineTextBoxImplementation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/maxGUI/MultilineTextBoxImplementation.cpp b/Code/maxGUI/MultilineTextBoxImplementation.cpp index a188c5e..6b87dde 100644 --- a/Code/maxGUI/MultilineTextBoxImplementation.cpp +++ b/Code/maxGUI/MultilineTextBoxImplementation.cpp @@ -37,7 +37,7 @@ namespace maxGUI return CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), win32_text.text_, win32_styles, rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height, parent_window_handle, NULL, reinterpret_cast(GetWindowLongPtr(parent_window_handle, GWLP_HINSTANCE)), NULL); } #elif defined(MAX_PLATFORM_LINUX) - QTextEdit* MultilineTextBox::Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { + QTextEdit* MultilineTextBoxImplementation::Create(QWidget* parent_window, max::Containers::Rectangle rectangle, std::string text, MultilineTextBoxStyles styles) noexcept { QTextEdit* multiline_textbox = new QTextEdit(text.c_str(), parent_window); multiline_textbox->setGeometry(rectangle.TopLeft.X(), rectangle.TopLeft.Y(), rectangle.Width, rectangle.Height); // TODO: Handle MultilineTextBoxStyles styles From adffc45afa9d6b73129eca791190ce90af1d397c Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 19:47:28 -0400 Subject: [PATCH 09/13] Hide Windows-only functions from Linux --- Code/maxGUI/CheckBox.inl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/maxGUI/CheckBox.inl b/Code/maxGUI/CheckBox.inl index 8b78f89..ef81278 100644 --- a/Code/maxGUI/CheckBox.inl +++ b/Code/maxGUI/CheckBox.inl @@ -5,6 +5,8 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) + template< class Behavior > CheckBox< Behavior >::CheckBox(HWND window_handle) noexcept : ControlWithText(window_handle) @@ -64,4 +66,6 @@ namespace maxGUI return implementation_.Uncheck(); } +#endif + } // namespace maxGUI \ No newline at end of file From 7f2899527d036cbf697d00f5f4ec3a2f1d2b8b37 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 20:16:49 -0400 Subject: [PATCH 10/13] Block HWND-using ControlWithList from Linux builds --- Code/maxGUI/Control.hpp | 3 ++- Code/maxGUI/ControlWithList.cpp | 2 ++ Code/maxGUI/ControlWithList.hpp | 17 +++++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Code/maxGUI/Control.hpp b/Code/maxGUI/Control.hpp index 7a963b6..c2716e6 100644 --- a/Code/maxGUI/Control.hpp +++ b/Code/maxGUI/Control.hpp @@ -12,8 +12,9 @@ #if defined(MAX_PLATFORM_WINDOWS) #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN #endif + #include #elif defined(MAX_PLATFORM_LINUX) #include diff --git a/Code/maxGUI/ControlWithList.cpp b/Code/maxGUI/ControlWithList.cpp index b4da330..e6b09ba 100644 --- a/Code/maxGUI/ControlWithList.cpp +++ b/Code/maxGUI/ControlWithList.cpp @@ -9,9 +9,11 @@ namespace maxGUI { +#if defined(MAX_PLATFORM_WINDOWS) ControlWithList::ControlWithList(HWND window_handle) noexcept : Control(std::move(window_handle)) {} +#endif void ControlWithList::OnSelectionChanged(int /*newly_selected_index*/) noexcept {} diff --git a/Code/maxGUI/ControlWithList.hpp b/Code/maxGUI/ControlWithList.hpp index ceed6e4..b3992db 100644 --- a/Code/maxGUI/ControlWithList.hpp +++ b/Code/maxGUI/ControlWithList.hpp @@ -5,13 +5,20 @@ #ifndef MAXGUI_CONTROLWITHLIST_HPP #define MAXGUI_CONTROLWITHLIST_HPP -#include #include #include -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN + +#include + +#include + +#if defined(MAX_PLATFORM_WINDOWS) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #include #endif -#include namespace maxGUI { @@ -19,7 +26,9 @@ namespace maxGUI class ControlWithList : public Control { public: +#if defined(MAX_PLATFORM_WINDOWS) explicit ControlWithList(HWND window_handle) noexcept; +#endif ~ControlWithList() noexcept override = default; From dddb2b6f270737e09f30b0203e24af40eab75883 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 20:21:15 -0400 Subject: [PATCH 11/13] Guard DropDownBox.inl to be Windows-only --- Code/maxGUI/DropDownBox.inl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/maxGUI/DropDownBox.inl b/Code/maxGUI/DropDownBox.inl index f25fbb5..95d85f3 100644 --- a/Code/maxGUI/DropDownBox.inl +++ b/Code/maxGUI/DropDownBox.inl @@ -4,6 +4,8 @@ #include +#if defined(MAX_PLATFORM_WINDOWS) + namespace maxGUI { @@ -43,4 +45,6 @@ namespace maxGUI return DropDownBoxImplementation::Create(std::move(parent_window_handle), std::move(rectangle), std::move(list), std::move(styles)); }; -} // namespace maxGUI \ No newline at end of file +} // namespace maxGUI + +#endif \ No newline at end of file From 7b2fbfa1106255cc15297c0b77cdb2fc061dbe1c Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 20:24:27 -0400 Subject: [PATCH 12/13] Block more template functions when their class is unavailable on Linux --- Code/maxGUI/ListBox.inl | 6 +++++- Code/maxGUI/RadioButton.inl | 6 +++++- Code/maxGUI/TextBox.hpp | 4 ++++ Code/maxGUI/TextBox.inl | 6 +++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Code/maxGUI/ListBox.inl b/Code/maxGUI/ListBox.inl index 98e0ff5..fe27c8c 100644 --- a/Code/maxGUI/ListBox.inl +++ b/Code/maxGUI/ListBox.inl @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#if defined(MAX_PLATFORM_WINDOWS) + namespace maxGUI { @@ -41,4 +43,6 @@ namespace maxGUI } } -} // namespace maxGUI \ No newline at end of file +} // namespace maxGUI + +#endif \ No newline at end of file diff --git a/Code/maxGUI/RadioButton.inl b/Code/maxGUI/RadioButton.inl index 4942a75..5afe7f7 100644 --- a/Code/maxGUI/RadioButton.inl +++ b/Code/maxGUI/RadioButton.inl @@ -4,6 +4,8 @@ #include +#if defined(MAX_PLATFORM_WINDOWS) + namespace maxGUI { @@ -45,4 +47,6 @@ namespace maxGUI } } -} // namespace maxGUI \ No newline at end of file +} // namespace maxGUI + +#endif \ No newline at end of file diff --git a/Code/maxGUI/TextBox.hpp b/Code/maxGUI/TextBox.hpp index bb57235..bb96be4 100644 --- a/Code/maxGUI/TextBox.hpp +++ b/Code/maxGUI/TextBox.hpp @@ -12,6 +12,8 @@ #include #include +#if defined(MAX_PLATFORM_WINDOWS) + namespace maxGUI { @@ -42,6 +44,8 @@ namespace maxGUI } // namespace maxGUI +#endif + #include #endif // #ifndef MAXGUI_TEXTBOX_HPP \ No newline at end of file diff --git a/Code/maxGUI/TextBox.inl b/Code/maxGUI/TextBox.inl index d56865f..5b6662a 100644 --- a/Code/maxGUI/TextBox.inl +++ b/Code/maxGUI/TextBox.inl @@ -6,6 +6,8 @@ #include +#if defined(MAX_PLATFORM_WINDOWS) + namespace maxGUI { @@ -41,4 +43,6 @@ namespace maxGUI } #endif -} // namespace maxGUI \ No newline at end of file +} // namespace maxGUI + +#endif \ No newline at end of file From ec9af1b3a209533c54e4ceb666b99a04969339e7 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Wed, 10 May 2023 20:27:52 -0400 Subject: [PATCH 13/13] Don't include Win32String on Linux --- Code/maxGUI/RadioButton.inl | 4 ++-- Code/maxGUI/TextBox.inl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/maxGUI/RadioButton.inl b/Code/maxGUI/RadioButton.inl index 5afe7f7..52b0e1e 100644 --- a/Code/maxGUI/RadioButton.inl +++ b/Code/maxGUI/RadioButton.inl @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include - #if defined(MAX_PLATFORM_WINDOWS) +#include + namespace maxGUI { diff --git a/Code/maxGUI/TextBox.inl b/Code/maxGUI/TextBox.inl index 5b6662a..7df49fc 100644 --- a/Code/maxGUI/TextBox.inl +++ b/Code/maxGUI/TextBox.inl @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include - #include #if defined(MAX_PLATFORM_WINDOWS) +#include + namespace maxGUI {