Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Code/Examples/1-SimpleExample/EntryPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CustomForm {

void OnCreated(maxGUI::FormConcept* form) noexcept {
// Add controls inside the Form's OnCreated().
multiline_textbox_ = form->AddControl<maxGUI::MultilineTextBox>(max::Containers::MakeRectangle(0, 0, 100, 100), "Multi-line" MAXGUI_PLATFORM_NEWLINE "test");
multiline_textbox_ = form->AddControl<maxGUI::MultilineTextBox<>>(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 {
Expand All @@ -24,7 +24,7 @@ class CustomForm {
maxGUI::PostExitMessage(0);
}

maxGUI::MultilineTextBox* multiline_textbox_ = nullptr;
maxGUI::MultilineTextBox<>* multiline_textbox_ = nullptr;
};


Expand Down
8 changes: 4 additions & 4 deletions Code/Examples/2-StylingExample/EntryPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ class LoginForm {
void OnCreated(maxGUI::FormConcept* form) noexcept {
form->AddControl<maxGUI::Label>(max::Containers::MakeRectangle(50, 50, 300, 500), "Login");

username_textbox_ = form->AddControl<maxGUI::TextBox>(max::Containers::MakeRectangle(50, 100, 300, 50), "");
username_textbox_ = form->AddControl<maxGUI::TextBox<>>(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<maxGUI::TextBox>(max::Containers::MakeRectangle(50, 150, 300, 50), "", maxGUI::TextBoxStyles::Password);
password_textbox_ = form->AddControl<maxGUI::TextBox<>>(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<maxGUI::Button<LoginButtonBehavior>>(max::Containers::MakeRectangle(50, 250, 100, 100), "Login", maxGUI::ButtonStyles::Default | maxGUI::ButtonStyles::Disabled);
Expand All @@ -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;

};

Expand Down
17 changes: 8 additions & 9 deletions Code/Examples/3-ControlGalleryExample/EntryPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

#include <maxGUI/maxGUI.hpp>

class CustomButtonBehavior
{
class CustomButtonBehavior {
public:

static void OnPressed() noexcept {
Expand All @@ -26,28 +25,28 @@ class ControlGalleryForm {
form->AddControl<maxGUI::Button<CustomButtonBehavior>>(max::Containers::MakeRectangle(25, 25, 150, 50), "Custom Button");

std::vector<std::string> dropdown_options{"Option 1", "Option 2", "Option 3"};
form->AddControl<maxGUI::DropDownBox>(max::Containers::MakeRectangle(25, 100, 300, 250), std::move(dropdown_options));
form->AddControl<maxGUI::DropDownBox<>>(max::Containers::MakeRectangle(25, 100, 300, 250), std::move(dropdown_options));

// TODO: Add the radio buttons inside the frame
form->AddControl<maxGUI::Frame>(max::Containers::MakeRectangle(25, 150, 300, 50), "Frame");

form->AddControl<maxGUI::Label>(max::Containers::MakeRectangle(25, 225, 300, 25), "Label");

std::vector<std::string> listbox_options{"Item 1", "Item 2", "Item 3"};
form->AddControl<maxGUI::ListBox>(max::Containers::MakeRectangle(25, 275, 300, 150), std::move(listbox_options));
form->AddControl<maxGUI::ListBox<>>(max::Containers::MakeRectangle(25, 275, 300, 150), std::move(listbox_options));

form->AddControl<maxGUI::MultilineTextBox>(max::Containers::MakeRectangle(25, 450, 300, 150), "Multiline\r\ntextbox");
form->AddControl<maxGUI::MultilineTextBox<>>(max::Containers::MakeRectangle(25, 450, 300, 150), "Multiline\r\ntextbox");

form->AddControl<maxGUI::ProgressBar>(max::Containers::MakeRectangle(25, 625, 300, 25), 0, 100, 50);

form->AddControl<maxGUI::CheckBox>(max::Containers::MakeRectangle(25, 675, 300, 25), "Check 1");
form->AddControl<maxGUI::CheckBox<>>(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<maxGUI::RadioButton>(max::Containers::MakeRectangle(25, 725, 300, 25), "Option 1", maxGUI::RadioButtonStyles::FirstInGroup);
form->AddControl<maxGUI::RadioButton<>>(max::Containers::MakeRectangle(25, 725, 300, 25), "Option 1", maxGUI::RadioButtonStyles::FirstInGroup);

form->AddControl<maxGUI::RadioButton>(max::Containers::MakeRectangle(25, 750, 300, 25), "Option 2");
form->AddControl<maxGUI::RadioButton<>>(max::Containers::MakeRectangle(25, 750, 300, 25), "Option 2");

form->AddControl<maxGUI::TextBox>(max::Containers::MakeRectangle(25, 800, 300, 25), "Textbox");
form->AddControl<maxGUI::TextBox<>>(max::Containers::MakeRectangle(25, 800, 300, 25), "Textbox");
}

void OnClosed(maxGUI::FormConcept* /*form*/) noexcept {
Expand Down
23 changes: 5 additions & 18 deletions Code/maxGUI/Button.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,23 @@
#define MAXGUI_BUTTON_HPP

#include <max/Compiling/Configuration.hpp>
#include <max/Compiling/Bitmask.hpp>
#include <max/Containers/Rectangle.hpp>
#include <maxGUI/ButtonImplementation.hpp>
#include <maxGUI/ControlWithText.hpp>
#include <string>
#include <utility>

#if defined(MAX_PLATFORM_WINDOWS)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <Windows.h>
#endif

#ifndef MAX_CONCEPTS_SUPPORTED
#include <max/Compiling/Exists.hpp>
#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
{

Expand Down Expand Up @@ -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<int, int> rectangle, std::string text, ButtonStyles styles = ButtonStyles::None) noexcept;
Expand All @@ -81,6 +67,7 @@ namespace maxGUI
#endif

Behavior behavior_;
ButtonImplementation implementation_;

};

Expand Down
54 changes: 28 additions & 26 deletions Code/maxGUI/Button.inl
Original file line number Diff line number Diff line change
Expand Up @@ -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 <utility>

#if defined(MAX_PLATFORM_WINDOWS)
#include <maxGUI/Win32String.hpp>
#endif
Expand All @@ -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

Expand All @@ -27,27 +30,17 @@ namespace maxGUI
#else
template< class Behavior >
#endif
HWND Button< Behavior >::Create(HWND parent_window_handle, max::Containers::Rectangle<int, int> 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<HINSTANCE>(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<int, int> 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

Expand All @@ -58,12 +51,21 @@ namespace maxGUI
template< class Behavior >
#endif
void Button< Behavior >::OnCommand(WORD notification) noexcept {
//if constexpr (Exists<Behavior, OnPressedTest>::value) {
//if constexpr (Exists2<Behavior::OnPressed()>::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

Expand Down
58 changes: 58 additions & 0 deletions Code/maxGUI/ButtonImplementation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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 <maxGUI/ButtonImplementation.hpp>

#if defined(MAX_PLATFORM_WINDOWS)
#include <maxGUI/Win32String.hpp>
#endif

namespace maxGUI
{

#if defined(MAX_PLATFORM_WINDOWS)
ButtonImplementation::ButtonImplementation(HWND window_handle) noexcept
: ControlWithTextImplementation(std::move(window_handle))
{}
#endif

ButtonImplementation::~ButtonImplementation() noexcept = default;

#if defined(MAX_PLATFORM_WINDOWS)
HWND ButtonImplementation::Create(HWND parent_window_handle, max::Containers::Rectangle<int, int> 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<HINSTANCE>(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<HINSTANCE>(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<WPARAM>(font), TRUE);

return window_handle;
}
#endif

} // namespace maxGUI
59 changes: 59 additions & 0 deletions Code/maxGUI/ButtonImplementation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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 <string>

#include <max/Compiling/Bitmask.hpp>
#include <max/Containers/Rectangle.hpp>
#include <max/Compiling/Configuration.hpp>

#if defined(MAX_PLATFORM_WINDOWS)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <Windows.h>
#endif

#include <maxGUI/ControlWithTextImplementation.hpp>

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:

#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<int, int> rectangle, std::string text, ButtonStyles styles) noexcept;
#endif

};

} // namespace maxGUI

#endif // #ifndef MAXGUI_BUTTONIMPLEMENTATION_HPP
Loading