diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eea780c..16bacca3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ add_library (${PROJECT_NAME} "src/app/aura.cpp" "src/app/configurationbase.cpp" "src/app/interprocesscommunicator.cpp" + "src/app/windowgeometry.cpp" "src/database/sqlcontext.cpp" "src/database/sqldatabase.cpp" "src/database/sqlite3.c" diff --git a/docs/app.md b/docs/app.md index 9b409b92..cd55421d 100644 --- a/docs/app.md +++ b/docs/app.md @@ -7,11 +7,12 @@ This module contains types and functions for creating Nickvision applications. - [Aura](#aura) - [ConfigurationBase](#configurationbase) - [InterProcessCommunicator](#interprocesscommunicator) +- [WindowGeometry](#windowgeometry) ## AppInfo Description: A model for the information about an application. -Interface: [appinfo.h](/include/aura/appinfo.h) +Interface: [appinfo.h](/include/app/appinfo.h) Type: `class` @@ -127,7 +128,7 @@ Path: `Nickvision::App::AppInfo` ## Aura Description: An application base. -Interface: [aura.h](/include/aura/aura.h) +Interface: [aura.h](/include/app/aura.h) Type: `class` @@ -233,7 +234,7 @@ Path: `Nickvision::App::Aura` ## ConfigurationBase Description: A base class for configuration files. -Interface: [configurationbase.h](/include/aura/configurationbase.h) +Interface: [configurationbase.h](/include/app/configurationbase.h) Type: `class` @@ -337,7 +338,7 @@ Type: `file` ## InterProcessCommunicator Description: An inter process communicator (server/client). -Interface: [interprocesscommunicator.h](/include/aura/interprocesscommunicator.h) +Interface: [interprocesscommunicator.h](/include/app/interprocesscommunicator.h) Type: `class` @@ -414,3 +415,49 @@ If this program is ran for the first time, ipc will be the server instance. `han If this program is ran not for the first time, its arguments will be sent to the first instance and this instance itself will close. The first instance's `handleArguments` function will be called as a result of `CommandReceived` being invoked by the ipc server receiving the command. +## WindowGeometry +Description: A model of a window's geometry. + +Interface: [windowgeometry.h](/include/app/windowgeometry.h) + +Type: `class` + +Path: `Nickvision::App::WindowGeometry` + +### Member Variables +- ``` + long Width: get, set + ``` + - The window's width. +- ``` + long Height: get, set + ``` + - The window's height. +- ``` + bool IsMaximized: get, set + ``` + - Whether or not the window is maximized. + +### Methods +- ```cpp + WindowGeometry() + ``` + - Constructs a WindowGeometry. + - Note: Uses default values: 800 width, 600 height, not maximized. +- ```cpp + WindowGeometry(long width, long height, bool isMaximized) + ``` + - Constructs a WindowGeometry. + - Accepts: The window's width, width, the window's height, height, and whether or not the window is maximized, isMaximized. +- ```cpp + WindowGeometry(HWND hwnd) + ``` + - Constructs a WindowGeometry. + - Accepts: The window handle to get the geometry from, hwnd. + - Note: This function is only available on Windows. +- ```cpp + bool apply(HWND hwnd) + ``` + - Accepts: The window handle to apply the geometry to, hwnd. + - Returns: True if successful. + - Returns: False if unsuccessful. \ No newline at end of file diff --git a/include/app/windowgeometry.h b/include/app/windowgeometry.h new file mode 100644 index 00000000..0d459f3f --- /dev/null +++ b/include/app/windowgeometry.h @@ -0,0 +1,80 @@ +#ifndef WINDOWGEOMETRY_H +#define WINDOWGEOMETRY_H + +#ifdef _WIN32 +#include +#endif + +namespace Nickvision::App +{ + /** + * @brief A model of a window's geometry. + */ + class WindowGeometry + { + public: + /** + * @brief Construct a WindowGeometry. + */ + WindowGeometry(); + /** + * @brief Construct a WindowGeometry. + * @param width The width of the window + * @param height The height of the window + * @param isMaximized Whether or not the window is maximized + */ + WindowGeometry(long width, long height, bool isMaximized); +#ifdef _WIN32 + /** + * @brief Construct a WindowGeometry. + * @param hwnd The window handle to get the geometry from + */ + WindowGeometry(HWND hwnd); +#endif + /** + * @brief Gets the width of the window. + * @return The width of the window + */ + long getWidth() const; + /** + * @brief Sets the width of the window. + * @param width The new width of the window + */ + void setWidth(long width); + /** + * @brief Gets the height of the window. + * @return The height of the window + */ + long getHeight() const; + /** + * @brief Sets the height of the window. + * @param height The new height of the window + */ + void setHeight(long height); + /** + * @brief Gets whether or not the window is maximized. + * @return True if maximized, else false + */ + bool isMaximized() const; + /** + * @brief Sets whether or not the window is maximized. + * @param isMaximized True if maximized, else false + */ + void setIsMaximized(bool isMaximized); +#ifdef _WIN32 + /** + * @brief Applies the geometry to a window. + * @param hwnd The window handle to apply the geometry to + * @return True if successful, else false + */ + bool apply(HWND hwnd) const; +#endif + + private: + long m_width; + long m_height; + bool m_isMaximized; + }; +} + +#endif //WINDOWGEOMETRY_H \ No newline at end of file diff --git a/src/app/windowgeometry.cpp b/src/app/windowgeometry.cpp new file mode 100644 index 00000000..0ca015de --- /dev/null +++ b/src/app/windowgeometry.cpp @@ -0,0 +1,73 @@ +#include "app/windowgeometry.h" + +namespace Nickvision::App +{ + WindowGeometry::WindowGeometry() + : m_width{ 800 }, + m_height{ 600 }, + m_isMaximized{ false } + { + + } + + WindowGeometry::WindowGeometry(long width, long height, bool isMaximized) + : m_width{ width }, + m_height{ height }, + m_isMaximized{ isMaximized } + { + + } + +#ifdef _WIN32 + WindowGeometry::WindowGeometry(HWND hwnd) + { + WINDOWPLACEMENT placement; + GetWindowPlacement(hwnd, &placement); + m_width = placement.rcNormalPosition.right - placement.rcNormalPosition.left; + m_height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top; + m_isMaximized = placement.showCmd == SW_SHOWMAXIMIZED; + } +#endif + + long WindowGeometry::getWidth() const + { + return m_width; + } + + void WindowGeometry::setWidth(long width) + { + m_width = width; + } + + long WindowGeometry::getHeight() const + { + return m_height; + } + + void WindowGeometry::setHeight(long height) + { + m_height = height; + } + + bool WindowGeometry::isMaximized() const + { + return m_isMaximized; + } + + void WindowGeometry::setIsMaximized(bool isMaximized) + { + m_isMaximized = isMaximized; + } + +#ifdef _WIN32 + bool WindowGeometry::apply(HWND hwnd) const + { + WINDOWPLACEMENT placement; + GetWindowPlacement(hwnd, &placement); + placement.rcNormalPosition.right = placement.rcNormalPosition.left + m_width; + placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + m_height; + placement.showCmd = m_isMaximized ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL; + return SetWindowPlacement(hwnd, &placement); + } +#endif +} \ No newline at end of file diff --git a/tests/auratests.cpp b/tests/auratests.cpp index 9cd683c6..d29bf739 100644 --- a/tests/auratests.cpp +++ b/tests/auratests.cpp @@ -1,5 +1,6 @@ #include #include "app/aura.h" +#include "app/windowgeometry.h" #include "filesystem/userdirectories.h" #include "notifications/shellnotification.h" @@ -25,12 +26,29 @@ class AppConfig : public ConfigurationBase Theme getTheme() const { - return (Theme)m_json.get("Theme", (int)Theme::System).asInt(); + return static_cast(m_json.get("Theme", (int)Theme::System).asInt()); } void setTheme(Theme theme) { - m_json["Theme"] = (int)theme; + m_json["Theme"] = static_cast(theme); + } + + WindowGeometry getWindowGeometry() + { + WindowGeometry geometry; + const Json::Value json{ m_json["WindowGeometry"] }; + geometry.setWidth(json.get("Width", 800).asInt64()); + geometry.setHeight(json.get("Height", 600).asInt64()); + geometry.setIsMaximized(json.get("IsMaximized", false).asBool()); + return geometry; + } + + void setWindowGeometry(const WindowGeometry& geometry) + { + m_json["WindowGeometry"]["Width"] = static_cast(geometry.getWidth()); + m_json["WindowGeometry"]["Height"] = static_cast(geometry.getHeight()); + m_json["WindowGeometry"]["IsMaximized"] = geometry.isMaximized(); } }; @@ -57,21 +75,29 @@ TEST_F(AuraTest, SetAppInfo) TEST_F(AuraTest, EnsureDefaultAppConfig) { AppConfig& config{ Aura::getActive().getConfig("config") }; + WindowGeometry geometry{ config.getWindowGeometry() }; ASSERT_EQ(config.getTheme(), Theme::System); + ASSERT_EQ(geometry.getWidth(), 800); + ASSERT_EQ(geometry.getHeight(), 600); + ASSERT_EQ(geometry.isMaximized(), false); } TEST_F(AuraTest, ChangeAppConfig) { AppConfig& config{ Aura::getActive().getConfig("config") }; config.setTheme(Theme::Light); + config.setWindowGeometry(WindowGeometry{ 1920, 1080, true }); ASSERT_TRUE(config.save()); - ASSERT_EQ(config.getTheme(), Theme::Light); } TEST_F(AuraTest, EnsureChangeInAppConfig) { AppConfig& config{ Aura::getActive().getConfig("config") }; ASSERT_EQ(config.getTheme(), Theme::Light); + WindowGeometry geometry{ config.getWindowGeometry() }; + ASSERT_EQ(geometry.getWidth(), 1920); + ASSERT_EQ(geometry.getHeight(), 1080); + ASSERT_EQ(geometry.isMaximized(), true); } TEST_F(AuraTest, ResetAppConfig)