1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 12:58:12 +00:00

LibGUI: Flesh out focus implementation and more GTextBox work.

This commit is contained in:
Andreas Kling 2019-01-26 11:24:16 +01:00
parent d72575d196
commit de2423de5f
10 changed files with 54 additions and 27 deletions

View file

@ -19,6 +19,7 @@ private:
virtual void mousedown_event(GMouseEvent&) override; virtual void mousedown_event(GMouseEvent&) override;
virtual const char* class_name() const override { return "GCheckBox"; } virtual const char* class_name() const override { return "GCheckBox"; }
virtual bool accepts_focus() const override { return true; }
String m_caption; String m_caption;
bool m_checked { false }; bool m_checked { false };

View file

@ -5,21 +5,6 @@
#include <AK/AKString.h> #include <AK/AKString.h>
#include <AK/Types.h> #include <AK/Types.h>
static const char* eventNames[] = {
"Invalid",
"Quit",
"Show",
"Hide",
"Paint",
"MouseMove",
"MouseDown",
"MouseUp",
"KeyDown",
"KeyUp",
"Timer",
"DeferredDestroy",
};
class GEvent { class GEvent {
public: public:
enum Type { enum Type {
@ -37,6 +22,8 @@ public:
DeferredDestroy, DeferredDestroy,
WindowBecameInactive, WindowBecameInactive,
WindowBecameActive, WindowBecameActive,
FocusIn,
FocusOut,
}; };
GEvent() { } GEvent() { }
@ -45,8 +32,6 @@ public:
Type type() const { return m_type; } Type type() const { return m_type; }
const char* name() const { return eventNames[(unsigned)m_type]; }
bool is_mouse_event() const { return m_type == MouseMove || m_type == MouseDown || m_type == MouseUp; } bool is_mouse_event() const { return m_type == MouseMove || m_type == MouseDown || m_type == MouseUp; }
bool is_key_event() const { return m_type == KeyUp || m_type == KeyDown; } bool is_key_event() const { return m_type == KeyUp || m_type == KeyDown; }
bool is_paint_event() const { return m_type == Paint; } bool is_paint_event() const { return m_type == Paint; }

View file

@ -14,6 +14,7 @@ private:
virtual void paint_event(GPaintEvent&) override; virtual void paint_event(GPaintEvent&) override;
virtual void mousedown_event(GMouseEvent&) override; virtual void mousedown_event(GMouseEvent&) override;
virtual const char* class_name() const override { return "GListBox"; } virtual const char* class_name() const override { return "GListBox"; }
virtual bool accepts_focus() const override { return true; }
Rect item_rect(int index) const; Rect item_rect(int index) const;

View file

@ -107,8 +107,8 @@ void GTextBox::keydown_event(GKeyEvent& event)
case KeyCode::Key_Backspace: case KeyCode::Key_Backspace:
return handle_backspace(); return handle_backspace();
case KeyCode::Key_Return: case KeyCode::Key_Return:
if (onReturnPressed) if (on_return_pressed)
onReturnPressed(*this); on_return_pressed(*this);
return; return;
} }

View file

@ -11,7 +11,7 @@ public:
String text() const { return m_text; } String text() const { return m_text; }
void set_text(String&&); void set_text(String&&);
Function<void(GTextBox&)> onReturnPressed; Function<void(GTextBox&)> on_return_pressed;
private: private:
virtual const char* class_name() const override { return "GTextBox"; } virtual const char* class_name() const override { return "GTextBox"; }
@ -19,6 +19,7 @@ private:
virtual void mousedown_event(GMouseEvent&) override; virtual void mousedown_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override; virtual void keydown_event(GKeyEvent&) override;
virtual void timerEvent(GTimerEvent&) override; virtual void timerEvent(GTimerEvent&) override;
virtual bool accepts_focus() const override { return true; }
void handle_backspace(); void handle_backspace();

View file

@ -38,6 +38,9 @@ void GWidget::event(GEvent& event)
case GEvent::Paint: case GEvent::Paint:
m_has_pending_paint_event = false; m_has_pending_paint_event = false;
return paint_event(static_cast<GPaintEvent&>(event)); return paint_event(static_cast<GPaintEvent&>(event));
case GEvent::FocusIn:
case GEvent::FocusOut:
return focusin_event(event);
case GEvent::Show: case GEvent::Show:
return show_event(static_cast<GShowEvent&>(event)); return show_event(static_cast<GShowEvent&>(event));
case GEvent::Hide: case GEvent::Hide:
@ -49,7 +52,8 @@ void GWidget::event(GEvent& event)
case GEvent::MouseMove: case GEvent::MouseMove:
return mousemove_event(static_cast<GMouseEvent&>(event)); return mousemove_event(static_cast<GMouseEvent&>(event));
case GEvent::MouseDown: case GEvent::MouseDown:
// FIXME: Focus self if needed. if (accepts_focus())
set_focus(true);
return mousedown_event(static_cast<GMouseEvent&>(event)); return mousedown_event(static_cast<GMouseEvent&>(event));
case GEvent::MouseUp: case GEvent::MouseUp:
return mouseup_event(static_cast<GMouseEvent&>(event)); return mouseup_event(static_cast<GMouseEvent&>(event));
@ -98,6 +102,14 @@ void GWidget::mousemove_event(GMouseEvent&)
{ {
} }
void GWidget::focusin_event(GEvent&)
{
}
void GWidget::focusout_event(GEvent&)
{
}
void GWidget::update() void GWidget::update()
{ {
auto* w = window(); auto* w = window();
@ -130,15 +142,23 @@ void GWidget::set_window(GWindow* window)
bool GWidget::is_focused() const bool GWidget::is_focused() const
{ {
// FIXME: Implement. auto* win = window();
return false; if (!win)
return false;
return win->focused_widget() == this;
} }
void GWidget::set_focus(bool focus) void GWidget::set_focus(bool focus)
{ {
if (focus == is_focused()) auto* win = window();
if (!win)
return; return;
// FIXME: Implement. if (focus) {
win->set_focused_widget(this);
} else {
if (win->focused_widget() == this)
win->set_focused_widget(nullptr);
}
} }
void GWidget::set_font(RetainPtr<Font>&& font) void GWidget::set_font(RetainPtr<Font>&& font)

View file

@ -24,6 +24,8 @@ public:
virtual void mousemove_event(GMouseEvent&); virtual void mousemove_event(GMouseEvent&);
virtual void mousedown_event(GMouseEvent&); virtual void mousedown_event(GMouseEvent&);
virtual void mouseup_event(GMouseEvent&); virtual void mouseup_event(GMouseEvent&);
virtual void focusin_event(GEvent&);
virtual void focusout_event(GEvent&);
Rect relative_rect() const { return m_relative_rect; } Rect relative_rect() const { return m_relative_rect; }
Point relative_position() const { return m_relative_rect.location(); } Point relative_position() const { return m_relative_rect.location(); }
@ -39,6 +41,8 @@ public:
void update(); void update();
void repaint(const Rect&); void repaint(const Rect&);
virtual bool accepts_focus() const { return false; }
bool is_focused() const; bool is_focused() const;
void set_focus(bool); void set_focus(bool);

View file

@ -139,8 +139,13 @@ void GWindow::set_focused_widget(GWidget* widget)
{ {
if (m_focused_widget == widget) if (m_focused_widget == widget)
return; return;
if (m_focused_widget) if (m_focused_widget) {
GEventLoop::main().post_event(m_focused_widget, make<GEvent>(GEvent::FocusOut));
m_focused_widget->update(); m_focused_widget->update();
}
m_focused_widget = widget; m_focused_widget = widget;
m_focused_widget->update(); if (m_focused_widget) {
GEventLoop::main().post_event(m_focused_widget, make<GEvent>(GEvent::FocusIn));
m_focused_widget->update();
}
} }

View file

@ -38,6 +38,10 @@ public:
GWidget* main_widget() { return m_main_widget; } GWidget* main_widget() { return m_main_widget; }
const GWidget* main_widget() const { return m_main_widget; } const GWidget* main_widget() const { return m_main_widget; }
void set_main_widget(GWidget*); void set_main_widget(GWidget*);
GWidget* focused_widget() { return m_focused_widget; }
const GWidget* focused_widget() const { return m_focused_widget; }
void set_focused_widget(GWidget*); void set_focused_widget(GWidget*);
void show(); void show();

View file

@ -110,6 +110,12 @@ GWindow* make_launcher_window()
auto* textbox = new GTextBox(widget); auto* textbox = new GTextBox(widget);
textbox->set_relative_rect({ 5, 110, 90, 20 }); textbox->set_relative_rect({ 5, 110, 90, 20 });
textbox->on_return_pressed = [window] (GTextBox& textbox) {
window->set_title(textbox.text());
};
auto* other_textbox = new GTextBox(widget);
other_textbox->set_relative_rect({ 5, 140, 90, 20 });
window->set_focused_widget(textbox); window->set_focused_widget(textbox);