LibGUI: More work on GInputBox.
- If the GInputBox has a parent and the parent is a GWindow, center the input box window within the parent window. This looks quite nice. - Stop processing events in a nested event loop immediately after it's been asked to quit. - Fix GWidget::parent_widget() behavior for non-widget parents.
This commit is contained in:
parent
a6538feed1
commit
f88e550998
Notes:
sideshowbarker
2024-07-19 15:00:33 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/f88e5509984
9 changed files with 74 additions and 34 deletions
|
@ -50,7 +50,7 @@ void IRCAppWindow::setup_client()
|
|||
void IRCAppWindow::setup_actions()
|
||||
{
|
||||
m_join_action = GAction::create("Join channel", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-join.rgb", { 16, 16 }), [&] (auto&) {
|
||||
GInputBox input_box("Enter nickname:", "Join channel");
|
||||
GInputBox input_box("Enter nickname:", "Join channel", this);
|
||||
if (input_box.exec() == GInputBox::ExecOK)
|
||||
m_client.handle_join_action(input_box.text_value());
|
||||
});
|
||||
|
@ -60,13 +60,13 @@ void IRCAppWindow::setup_actions()
|
|||
});
|
||||
|
||||
m_whois_action = GAction::create("Whois user", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-whois.rgb", { 16, 16 }), [&] (auto&) {
|
||||
GInputBox input_box("Enter nickname:", "IRC WHOIS lookup");
|
||||
GInputBox input_box("Enter nickname:", "IRC WHOIS lookup", this);
|
||||
if (input_box.exec() == GInputBox::ExecOK)
|
||||
m_client.handle_whois_action(input_box.text_value());
|
||||
});
|
||||
|
||||
m_open_query_action = GAction::create("Open query", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-open-query.rgb", { 16, 16 }), [&] (auto&) {
|
||||
GInputBox input_box("Enter nickname:", "Open IRC query with...");
|
||||
GInputBox input_box("Enter nickname:", "Open IRC query with...", this);
|
||||
if (input_box.exec() == GInputBox::ExecOK)
|
||||
m_client.handle_open_query_action(input_box.text_value());
|
||||
});
|
||||
|
|
|
@ -14,13 +14,25 @@ GDialog::~GDialog()
|
|||
|
||||
int GDialog::exec()
|
||||
{
|
||||
GEventLoop loop;
|
||||
ASSERT(!m_event_loop);
|
||||
m_event_loop = make<GEventLoop>();
|
||||
if (parent() && parent()->is_window()) {
|
||||
auto& parent_window = *static_cast<GWindow*>(parent());
|
||||
auto new_rect = rect();
|
||||
new_rect.center_within(parent_window.rect());
|
||||
set_rect(new_rect);
|
||||
}
|
||||
show();
|
||||
return loop.exec();
|
||||
auto result = m_event_loop->exec();
|
||||
m_event_loop = nullptr;
|
||||
dbgprintf("event loop returned with result %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void GDialog::done(int result)
|
||||
{
|
||||
ASSERT(m_event_loop);
|
||||
m_result = result;
|
||||
GEventLoop::current().quit(result);
|
||||
dbgprintf("quit event loop with result %d\n", result);
|
||||
m_event_loop->quit(result);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibGUI/GWindow.h>
|
||||
#include <LibGUI/GEventLoop.h>
|
||||
|
||||
class GDialog : public GWindow {
|
||||
public:
|
||||
enum ExecResult { ExecOK = 0, ExecCancel = 1, ExecAborted = 2 };
|
||||
|
||||
virtual ~GDialog() override;
|
||||
|
||||
int exec();
|
||||
|
@ -15,5 +18,6 @@ protected:
|
|||
explicit GDialog(GObject* parent);
|
||||
|
||||
private:
|
||||
int m_result { 0 };
|
||||
OwnPtr<GEventLoop> m_event_loop;
|
||||
int m_result { ExecAborted };
|
||||
};
|
||||
|
|
|
@ -158,6 +158,13 @@ int GEventLoop::exec()
|
|||
} else {
|
||||
receiver->event(event);
|
||||
}
|
||||
|
||||
if (m_exit_requested) {
|
||||
auto rejigged_event_queue = move(events);
|
||||
rejigged_event_queue.append(move(m_queued_events));
|
||||
m_queued_events = move(rejigged_event_queue);
|
||||
return m_exit_code;
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
|
|
|
@ -36,9 +36,9 @@ void GInputBox::build()
|
|||
label->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
|
||||
label->set_preferred_size({ text_width, 16 });
|
||||
|
||||
auto* text_editor = new GTextEditor(GTextEditor::SingleLine, widget);
|
||||
text_editor->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||
text_editor->set_preferred_size({ 0, 16 });
|
||||
m_text_editor = new GTextEditor(GTextEditor::SingleLine, widget);
|
||||
m_text_editor->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||
m_text_editor->set_preferred_size({ 0, 16 });
|
||||
|
||||
auto* button_container_outer = new GWidget(widget);
|
||||
button_container_outer->set_layout(make<GBoxLayout>(Orientation::Vertical));
|
||||
|
@ -47,30 +47,30 @@ void GInputBox::build()
|
|||
button_container_inner->set_layout(make<GBoxLayout>(Orientation::Horizontal));
|
||||
button_container_inner->layout()->set_spacing(8);
|
||||
|
||||
auto* cancel_button = new GButton(button_container_inner);
|
||||
cancel_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||
cancel_button->set_preferred_size({ 0, 16 });
|
||||
cancel_button->set_caption("Cancel");
|
||||
cancel_button->on_click = [&] (auto&) {
|
||||
fprintf(stderr, "GInputBox: Cancel button clicked\n");
|
||||
done(1);
|
||||
m_cancel_button = new GButton(button_container_inner);
|
||||
m_cancel_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||
m_cancel_button->set_preferred_size({ 0, 16 });
|
||||
m_cancel_button->set_caption("Cancel");
|
||||
m_cancel_button->on_click = [this] (auto&) {
|
||||
dbgprintf("GInputBox: Cancel button clicked\n");
|
||||
done(ExecCancel);
|
||||
};
|
||||
|
||||
auto* ok_button = new GButton(button_container_inner);
|
||||
ok_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||
ok_button->set_preferred_size({ 0, 16 });
|
||||
ok_button->set_caption("OK");
|
||||
ok_button->on_click = [&] (auto&) {
|
||||
fprintf(stderr, "GInputBox: OK button clicked\n");
|
||||
m_text_value = text_editor->text();
|
||||
done(0);
|
||||
m_ok_button = new GButton(button_container_inner);
|
||||
m_ok_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||
m_ok_button->set_preferred_size({ 0, 16 });
|
||||
m_ok_button->set_caption("OK");
|
||||
m_ok_button->on_click = [this] (auto&) {
|
||||
dbgprintf("GInputBox: OK button clicked\n");
|
||||
m_text_value = m_text_editor->text();
|
||||
done(ExecOK);
|
||||
};
|
||||
|
||||
text_editor->on_return_pressed = [&] (auto&) {
|
||||
ok_button->click();
|
||||
m_text_editor->on_return_pressed = [this] (auto&) {
|
||||
m_ok_button->click();
|
||||
};
|
||||
text_editor->on_escape_pressed = [&] (auto&) {
|
||||
cancel_button->click();
|
||||
m_text_editor->on_escape_pressed = [this] (auto&) {
|
||||
m_cancel_button->click();
|
||||
};
|
||||
text_editor->set_focus(true);
|
||||
m_text_editor->set_focus(true);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
#include <LibGUI/GDialog.h>
|
||||
|
||||
class GButton;
|
||||
class GTextEditor;
|
||||
|
||||
class GInputBox : public GDialog {
|
||||
public:
|
||||
enum ExecResult { ExecOK = 0, ExecCancel = 1 };
|
||||
|
||||
explicit GInputBox(const String& prompt, const String& title, GObject* parent = nullptr);
|
||||
virtual ~GInputBox() override;
|
||||
|
||||
|
@ -15,4 +16,8 @@ private:
|
|||
void build();
|
||||
String m_prompt;
|
||||
String m_text_value;
|
||||
|
||||
GButton* m_ok_button { nullptr };
|
||||
GButton* m_cancel_button { nullptr };
|
||||
GTextEditor* m_text_editor { nullptr };
|
||||
};
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
void dump_tree(int indent = 0);
|
||||
|
||||
virtual bool is_widget() const { return false; }
|
||||
virtual bool is_window() const { return false; }
|
||||
|
||||
protected:
|
||||
virtual void timer_event(GTimerEvent&);
|
||||
|
|
|
@ -109,8 +109,18 @@ public:
|
|||
|
||||
void set_window(GWindow*);
|
||||
|
||||
GWidget* parent_widget() { return static_cast<GWidget*>(parent()); }
|
||||
const GWidget* parent_widget() const { return static_cast<const GWidget*>(parent()); }
|
||||
GWidget* parent_widget()
|
||||
{
|
||||
if (parent() && parent()->is_widget())
|
||||
return static_cast<GWidget*>(parent());
|
||||
return nullptr;
|
||||
}
|
||||
const GWidget* parent_widget() const
|
||||
{
|
||||
if (parent() && parent()->is_widget())
|
||||
return static_cast<const GWidget*>(parent());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void set_fill_with_background_color(bool b) { m_fill_with_background_color = b; }
|
||||
bool fill_with_background_color() const { return m_fill_with_background_color; }
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "GWindow"; }
|
||||
virtual bool is_window() const override final { return true; }
|
||||
|
||||
Retained<GraphicsBitmap> create_backing_bitmap(const Size&);
|
||||
void set_current_backing_bitmap(GraphicsBitmap&, bool flush_immediately = false);
|
||||
|
|
Loading…
Add table
Reference in a new issue