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:
Andreas Kling 2019-03-19 02:20:00 +01:00
parent a6538feed1
commit f88e550998
Notes: sideshowbarker 2024-07-19 15:00:33 +09:00
9 changed files with 74 additions and 34 deletions

View file

@ -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());
});

View file

@ -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);
}

View file

@ -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 };
};

View file

@ -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();

View file

@ -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);
}

View file

@ -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 };
};

View file

@ -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&);

View file

@ -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; }

View file

@ -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);