Skip to content

Commit 3001a9a

Browse files
committed
Add MessageDialog class and macOS implementation
Introduces a new MessageDialog class for displaying informational, warning, and custom dialogs, including modality support. Adds base Dialog class, updates nativeapi.h includes, and provides a macOS-specific implementation using NSAlert. Also adds a message_dialog_example demonstrating usage and integration in CMake.
1 parent d1d6731 commit 3001a9a

File tree

8 files changed

+592
-0
lines changed

8 files changed

+592
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_subdirectory(examples/id_allocator_example)
1414
add_subdirectory(examples/keyboard_example)
1515
add_subdirectory(examples/menu_example)
1616
add_subdirectory(examples/menu_c_example)
17+
add_subdirectory(examples/message_dialog_example)
1718
add_subdirectory(examples/storage_example)
1819
add_subdirectory(examples/storage_c_example)
1920
add_subdirectory(examples/tray_icon_example)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(message_dialog_example VERSION 0.0.1 LANGUAGES CXX)
4+
5+
# Set C++ standard
6+
set(CMAKE_CXX_STANDARD 17)
7+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
8+
9+
# Add example program
10+
add_executable(message_dialog_example
11+
"main.cpp"
12+
)
13+
14+
# Link main library
15+
target_link_libraries(message_dialog_example PRIVATE nativeapi)
16+
17+
# Set example program properties
18+
set_target_properties(message_dialog_example PROPERTIES
19+
OUTPUT_NAME "message_dialog_example"
20+
)
21+
22+
# Set example program compile options (macOS only)
23+
if(APPLE)
24+
set_source_files_properties("main.cpp"
25+
PROPERTIES
26+
COMPILE_FLAGS "-x objective-c++"
27+
)
28+
endif()
29+
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <iostream>
2+
#include <memory>
3+
#include "nativeapi.h"
4+
5+
using namespace nativeapi;
6+
7+
int main() {
8+
std::cout << "=== MessageDialog Example ===" << std::endl;
9+
10+
// Get the Application instance to initialize platform
11+
Application& app = Application::GetInstance();
12+
13+
try {
14+
std::cout << "\n1. Creating a simple informational dialog..." << std::endl;
15+
16+
// Create a simple informational message dialog
17+
auto info_dialog = std::make_shared<MessageDialog>(
18+
"Information",
19+
"This is an informational message dialog.\n\n"
20+
"MessageDialog can be used to display various types of messages to users.");
21+
22+
info_dialog->SetModality(DialogModality::Application);
23+
24+
std::cout << "Dialog title: " << info_dialog->GetTitle() << std::endl;
25+
std::cout << "Dialog message: " << info_dialog->GetMessage() << std::endl;
26+
std::cout << "Opening dialog..." << std::endl;
27+
28+
// Open the dialog (this will block until user dismisses it)
29+
if (info_dialog->Open()) {
30+
std::cout << "Dialog was opened successfully" << std::endl;
31+
} else {
32+
std::cout << "Failed to open dialog" << std::endl;
33+
}
34+
35+
std::cout << "\n2. Creating a warning dialog..." << std::endl;
36+
37+
// Create a warning dialog
38+
auto warning_dialog = std::make_shared<MessageDialog>(
39+
"Warning",
40+
"This is a warning message.\n\n"
41+
"Warning dialogs are used to alert users about potential issues.");
42+
43+
warning_dialog->SetModality(DialogModality::Application);
44+
warning_dialog->Open();
45+
46+
std::cout << "\n3. Creating a dialog with updated content..." << std::endl;
47+
48+
// Create a dialog and update its content
49+
auto dynamic_dialog = std::make_shared<MessageDialog>(
50+
"Update Available",
51+
"Initial message");
52+
53+
// Update the title and message before opening
54+
dynamic_dialog->SetTitle("System Update");
55+
dynamic_dialog->SetMessage(
56+
"A new version of the application is available.\n\n"
57+
"Version 2.0 includes:\n"
58+
"• Improved performance\n"
59+
"• New features\n"
60+
"• Bug fixes\n\n"
61+
"Would you like to update now?");
62+
63+
dynamic_dialog->SetModality(DialogModality::Application);
64+
65+
std::cout << "Updated title: " << dynamic_dialog->GetTitle() << std::endl;
66+
std::cout << "Opening updated dialog..." << std::endl;
67+
dynamic_dialog->Open();
68+
69+
std::cout << "\n4. Demonstrating different modality types..." << std::endl;
70+
71+
// Non-modal dialog (default)
72+
auto non_modal_dialog = std::make_shared<MessageDialog>(
73+
"Non-Modal Dialog",
74+
"This dialog does not block interaction.\n\n"
75+
"The application continues running and users can interact with other windows.");
76+
non_modal_dialog->SetModality(DialogModality::None);
77+
std::cout << "Modality: None (non-modal)" << std::endl;
78+
non_modal_dialog->Open();
79+
80+
// Application modal dialog
81+
auto app_modal_dialog = std::make_shared<MessageDialog>(
82+
"Application Modal",
83+
"This dialog blocks interaction with all windows in the current application.");
84+
app_modal_dialog->SetModality(DialogModality::Application);
85+
std::cout << "Modality: Application" << std::endl;
86+
app_modal_dialog->Open();
87+
88+
// Window modal dialog (behaves as Application on macOS)
89+
auto window_modal_dialog = std::make_shared<MessageDialog>(
90+
"Window Modal",
91+
"This dialog blocks interaction with a specific parent window.\n\n"
92+
"Note: On macOS, this behaves as Application.");
93+
window_modal_dialog->SetModality(DialogModality::Window);
94+
std::cout << "Modality: Window" << std::endl;
95+
window_modal_dialog->Open();
96+
97+
std::cout << "\n=== MessageDialog Example Complete ===" << std::endl;
98+
std::cout << "This example demonstrated:" << std::endl;
99+
std::cout << "1. Creating MessageDialog instances" << std::endl;
100+
std::cout << "2. Setting title and message" << std::endl;
101+
std::cout << "3. Updating dialog content programmatically" << std::endl;
102+
std::cout << "4. Opening dialogs with different modality types (None, Application, Window)" << std::endl;
103+
std::cout << "5. Modal vs non-modal dialog behavior" << std::endl;
104+
105+
std::cout << "\nExiting MessageDialog Example..." << std::endl;
106+
return 0;
107+
108+
} catch (const std::exception& e) {
109+
std::cerr << "Error: " << e.what() << std::endl;
110+
return 1;
111+
}
112+
}
113+

include/nativeapi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "../src/display.h"
99
#include "../src/display_event.h"
1010
#include "../src/display_manager.h"
11+
#include "../src/dialog.h"
1112
#include "../src/foundation/event.h"
1213
#include "../src/foundation/event_emitter.h"
1314
#include "../src/foundation/geometry.h"
@@ -16,6 +17,7 @@
1617
#include "../src/keyboard_event.h"
1718
#include "../src/keyboard_monitor.h"
1819
#include "../src/menu.h"
20+
#include "../src/message_dialog.h"
1921
#include "../src/preferences.h"
2022
#include "../src/secure_storage.h"
2123
#include "../src/storage.h"

src/dialog.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "dialog.h"
2+
3+
namespace nativeapi {
4+
5+
Dialog::~Dialog() = default;
6+
7+
DialogModality Dialog::GetModality() const {
8+
return modality_;
9+
}
10+
11+
void Dialog::SetModality(DialogModality modality) {
12+
modality_ = modality;
13+
}
14+
15+
bool Dialog::Open() {
16+
return false; // Base class implementation - should be overridden
17+
}
18+
19+
bool Dialog::Close() {
20+
return false; // Base class implementation - should be overridden
21+
}
22+
23+
} // namespace nativeapi
24+

src/dialog.h

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#pragma once
2+
3+
#include <string>
4+
5+
namespace nativeapi {
6+
7+
/**
8+
* @enum DialogModality
9+
* @brief Dialog modality types.
10+
*
11+
* Defines how the dialog blocks user interaction.
12+
*/
13+
enum class DialogModality {
14+
/**
15+
* @brief None - Non-modal dialog.
16+
*
17+
* The dialog does not block user interaction. The application continues
18+
* to run and users can interact with other windows while the dialog is open.
19+
*/
20+
None,
21+
22+
/**
23+
* @brief Application - Blocks the current application.
24+
*
25+
* Blocks interaction with all windows in the current application,
26+
* but allows interaction with other applications.
27+
*/
28+
Application,
29+
30+
/**
31+
* @brief Window - Blocks the parent window (requires parent window handle).
32+
*
33+
* Blocks interaction with a specific parent window.
34+
* Requires a parent window handle to be provided.
35+
*/
36+
Window
37+
};
38+
39+
/**
40+
* @class Dialog
41+
* @brief Base class for all dialog types.
42+
*
43+
* This abstract class provides the common interface for all dialog types
44+
* in the system. Specific dialog types (MessageDialog, FileDialog, etc.)
45+
* inherit from this class and implement their specific behavior.
46+
*
47+
* The Dialog class provides:
48+
* - Modal and non-modal display modes
49+
* - Modal state management
50+
*
51+
* @note This is an abstract base class. Use specific dialog types like
52+
* MessageDialog, FileDialog, etc., to create actual dialogs.
53+
*
54+
* @example
55+
* ```cpp
56+
* // Create a message dialog (see MessageDialog for details)
57+
* auto message_dialog = std::make_shared<MessageDialog>(
58+
* "Title", "Message", MessageDialogType::Info);
59+
*
60+
* // Set modal mode and open
61+
* message_dialog->SetModality(DialogModality::Application);
62+
* message_dialog->Open();
63+
* ```
64+
*/
65+
class Dialog {
66+
public:
67+
/**
68+
* @brief Virtual destructor.
69+
*
70+
* Ensures proper cleanup of derived classes and platform-specific resources.
71+
*/
72+
virtual ~Dialog();
73+
74+
/**
75+
* @brief Get the current modality setting of the dialog.
76+
*
77+
* @return The current DialogModality setting
78+
*/
79+
virtual DialogModality GetModality() const;
80+
81+
/**
82+
* @brief Set the modality of the dialog.
83+
*
84+
* The modality determines how the dialog blocks user interaction:
85+
* - None: Non-modal dialog, does not block user interaction
86+
* - Application: Blocks interaction with all windows in the current application
87+
* - Window: Blocks interaction with a specific parent window (requires parent handle)
88+
*
89+
* @param modality The modality type to set
90+
*
91+
* @note This setting affects the behavior when Open() is called.
92+
* The modality should be set before opening the dialog.
93+
*
94+
* @example
95+
* ```cpp
96+
* dialog->SetModality(DialogModality::Application); // Make it application modal
97+
* dialog->Open(); // Open as modal dialog
98+
* ```
99+
*/
100+
virtual void SetModality(DialogModality modality);
101+
102+
/**
103+
* @brief Open the dialog according to its modality setting.
104+
*
105+
* The dialog behavior depends on the current modality:
106+
* - None: Opens non-modally, does not block the calling thread
107+
* - Application/Window: Opens modally, blocks until the user dismisses the dialog
108+
*
109+
* @return true if the dialog was successfully opened, false otherwise
110+
*
111+
* @example
112+
* ```cpp
113+
* // Non-modal dialog
114+
* dialog->SetModality(DialogModality::None);
115+
* dialog->Open();
116+
* // Application continues running...
117+
*
118+
* // Modal dialog
119+
* dialog->SetModality(DialogModality::Application);
120+
* dialog->Open();
121+
* // Blocks until user dismisses dialog
122+
* ```
123+
*/
124+
virtual bool Open();
125+
126+
/**
127+
* @brief Close the dialog programmatically.
128+
*
129+
* Dismisses the dialog as if the user had closed it.
130+
*
131+
* @return true if the dialog was successfully closed, false otherwise
132+
*/
133+
virtual bool Close();
134+
135+
protected:
136+
/**
137+
* @brief Current modality setting.
138+
*/
139+
DialogModality modality_ = DialogModality::None;
140+
};
141+
142+
} // namespace nativeapi

0 commit comments

Comments
 (0)