feat: message box dynamic sizing, documentation page updates

This commit is contained in:
2026-04-22 20:27:55 +02:00
parent 15a092d0b4
commit 867d56b342
6 changed files with 101 additions and 25 deletions
+4 -9
View File
@@ -87,11 +87,6 @@
<hr>
<ul>
<li><a href="introduction.html">Introduction</a></li>
<li><a href="#">Kernel</a></li>
<li><a href="#">Userspace</a></li>
<li><a href="#">Applications</a></li>
<li><a href="#">Building</a></li>
<li><a href="#">Contributing</a></li>
</ul>
</div>
@@ -114,6 +109,10 @@ operating system, its components, and how to use and develop for it.
<a href="introduction.html">Introduction</a>
<p>Installation, running on emulator, and your first steps with MontaukOS.</p>
</li>
<li>
<a href="dtinternals/dialogslib.html">Dialogs Library</a>
<p>Desktop internals: file, print, and message box dialogs exposed through the shared dialogs library.</p>
</li>
<li>
<a href="#">Kernel Architecture</a>
<p>Overview of the preemptive multitasking kernel and its subsystems.</p>
@@ -130,10 +129,6 @@ operating system, its components, and how to use and develop for it.
<a href="#">Building from Source</a>
<p>How to compile and build MontaukOS yourself.</p>
</li>
<li>
<a href="#">Contributing</a>
<p>Guidelines for contributing to the project.</p>
</li>
</ul>
<hr>
-5
View File
@@ -73,11 +73,6 @@
<hr>
<ul>
<li><a href="introduction.html" class="current">Introduction</a></li>
<li><a href="#">Kernel</a></li>
<li><a href="#">Userspace</a></li>
<li><a href="#">Applications</a></li>
<li><a href="#">Building</a></li>
<li><a href="#">Contributing</a></li>
</ul>
</div>
+5 -1
View File
@@ -166,7 +166,11 @@ extern "C" uint8_t dialogs_message_box(const char* title,
const char* window_title = title && title[0] ? title : "Message";
messagebox::init(message ? message : "", buttons);
if (!g_app.win.create(window_title, messagebox::MESSAGE_INIT_W, messagebox::MESSAGE_INIT_H)) {
int init_w = 0;
int init_h = 0;
messagebox::preferred_size(window_title, &init_w, &init_h);
if (!g_app.win.create(window_title, init_w, init_h)) {
cleanup();
return dlg::MESSAGE_BOX_RESULT_NONE;
}
+75 -5
View File
@@ -210,6 +210,48 @@ bool is_space(char ch) {
return ch == ' ' || ch == '\t' || ch == '\r';
}
int clamp_int(int value, int min_value, int max_value) {
if (value < min_value) return min_value;
if (value > max_value) return max_value;
return value;
}
int button_row_width(const MessageBoxState* st) {
if (!st || st->button_count <= 0) return 0;
int total_w = st->button_count * messagebox::BUTTON_W;
if (st->button_count > 1)
total_w += (st->button_count - 1) * messagebox::BUTTON_GAP;
return total_w;
}
int widest_explicit_message_line(const MessageBoxState* st, int max_px) {
if (!st || !st->text[0]) return 0;
char line[messagebox::MAX_LINE_LEN] = {};
int line_len = 0;
int widest = 0;
for (const char* p = st->text; ; p++) {
char ch = *p;
bool at_end = ch == '\0';
if (at_end || ch == '\n') {
line[line_len] = '\0';
int width = text_width(line);
if (width > widest) widest = width;
line_len = 0;
line[0] = '\0';
if (at_end) break;
continue;
}
if (line_len >= messagebox::MAX_LINE_LEN - 1)
return max_px;
line[line_len++] = ch;
}
return widest > max_px ? max_px : widest;
}
void wrap_message(MessageBoxState* st, int max_px) {
if (!st) return;
if (max_px < 40) max_px = 40;
@@ -267,11 +309,12 @@ MessageBoxLayout message_layout(const MessageBoxState* st) {
lo.button_count = st ? st->button_count : 0;
lo.footer_rect = {0, g_app.win.height - messagebox::FOOTER_H, g_app.win.width, messagebox::FOOTER_H};
lo.text_rect = {20, 24, g_app.win.width - 40, lo.footer_rect.y - 32};
lo.text_rect = {messagebox::TEXT_X, messagebox::TEXT_Y,
g_app.win.width - messagebox::TEXT_X * 2,
lo.footer_rect.y - messagebox::TEXT_Y - messagebox::TEXT_BOTTOM_GAP};
int total_w = lo.button_count * messagebox::BUTTON_W;
if (lo.button_count > 1) total_w += (lo.button_count - 1) * messagebox::BUTTON_GAP;
int x = g_app.win.width - 16 - total_w;
int total_w = button_row_width(st);
int x = g_app.win.width - messagebox::BUTTON_RIGHT_PAD - total_w;
int y = lo.footer_rect.y + (messagebox::FOOTER_H - messagebox::BUTTON_H) / 2;
for (int i = 0; i < lo.button_count && i < messagebox::MAX_BUTTONS; i++) {
lo.buttons[i] = {x, y, messagebox::BUTTON_W, messagebox::BUTTON_H};
@@ -387,7 +430,34 @@ void init(const char* message, uint8_t buttons, uint8_t default_choice) {
configure_buttons(st);
if (!has_choice(st, st->default_choice))
st->default_choice = default_choice_for(st->buttons);
wrap_message(st, MESSAGE_INIT_W - 40);
wrap_message(st, messagebox::MESSAGE_MIN_W - messagebox::TEXT_X * 2);
}
void preferred_size(const char* title, int* out_w, int* out_h) {
MessageBoxState* st = &g_message;
int max_text_w = messagebox::MESSAGE_MAX_W - messagebox::TEXT_X * 2;
int desired_text_w = widest_explicit_message_line(st, max_text_w);
if (title && title[0]) {
int title_w = text_width(title) + 120;
if (title_w > desired_text_w) desired_text_w = title_w;
}
int desired_w = desired_text_w + messagebox::TEXT_X * 2;
int buttons_w = button_row_width(st) + messagebox::BUTTON_RIGHT_PAD * 2;
if (buttons_w > desired_w) desired_w = buttons_w;
desired_w = clamp_int(desired_w, messagebox::MESSAGE_MIN_W, messagebox::MESSAGE_MAX_W);
wrap_message(st, desired_w - messagebox::TEXT_X * 2);
int line_h = system_font_height() + 5;
int text_h = st->line_count > 0 ? st->line_count * line_h : line_h;
int desired_h = messagebox::TEXT_Y + text_h + messagebox::TEXT_BOTTOM_GAP +
messagebox::FOOTER_H;
desired_h = clamp_int(desired_h, messagebox::MESSAGE_MIN_H, messagebox::MESSAGE_MAX_H);
if (out_w) *out_w = desired_w;
if (out_h) *out_h = desired_h;
}
void draw() {
+9 -2
View File
@@ -19,9 +19,15 @@ struct MessageBoxLayout {
namespace messagebox {
constexpr int MESSAGE_INIT_W = 460;
constexpr int MESSAGE_INIT_H = 220;
constexpr int MESSAGE_MIN_W = 300;
constexpr int MESSAGE_MAX_W = 560;
constexpr int MESSAGE_MIN_H = 124;
constexpr int MESSAGE_MAX_H = 280;
constexpr int FOOTER_H = 56;
constexpr int TEXT_X = 20;
constexpr int TEXT_Y = 24;
constexpr int TEXT_BOTTOM_GAP = 24;
constexpr int BUTTON_RIGHT_PAD = 16;
constexpr int BUTTON_W = 88;
constexpr int BUTTON_H = 30;
constexpr int BUTTON_GAP = 8;
@@ -30,6 +36,7 @@ constexpr int MAX_LINES = 7;
constexpr int MAX_LINE_LEN = 128;
void init(const char* message, uint8_t buttons, uint8_t default_choice = 0);
void preferred_size(const char* title, int* out_w, int* out_h);
void draw();
void handle_mouse(const Montauk::WinEvent& ev);
void handle_key(const Montauk::KeyEvent& key);
+8 -3
View File
@@ -8,8 +8,13 @@
#include <gui/dialogs.hpp>
extern "C" void _start() {
gui::dialogs::message_box("Test Dialogs",
"Hello from libdialogs::message_box.",
gui::dialogs::MESSAGE_BOX_OK);
auto result = gui::dialogs::message_box(
"Close Document",
"Discard unsaved changes?",
gui::dialogs::MESSAGE_BOX_YES_NO_CANCEL);
if (result == gui::dialogs::MESSAGE_BOX_RESULT_YES) {
/* discard and close */
}
montauk::exit(0);
}