mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Move Widget & friends into LibGUI.
This commit is contained in:
parent
7e5b81fe48
commit
a026da47e7
Notes:
sideshowbarker
2024-07-19 16:00:07 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/a026da47e7a
29 changed files with 73 additions and 551 deletions
|
@ -4,6 +4,8 @@ sudo id
|
|||
|
||||
make -C ../LibC clean && \
|
||||
make -C ../LibC && \
|
||||
make -C ../LibGUI clean && \
|
||||
make -C ../LibGUI && \
|
||||
make -C ../Userland clean && \
|
||||
make -C ../Userland && \
|
||||
make -C ../Terminal clean && \
|
||||
|
|
0
Widgets/.gitignore → LibGUI/.gitignore
vendored
0
Widgets/.gitignore → LibGUI/.gitignore
vendored
|
@ -1,5 +1,5 @@
|
|||
#include "Button.h"
|
||||
#include "Painter.h"
|
||||
#include <SharedGraphics/Painter.h>
|
||||
|
||||
Button::Button(Widget* parent)
|
||||
: Widget(parent)
|
||||
|
@ -66,7 +66,7 @@ void Button::paintEvent(PaintEvent&)
|
|||
|
||||
void Button::mouseDownEvent(MouseEvent& event)
|
||||
{
|
||||
printf("Button::mouseDownEvent: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||
dbgprintf("Button::mouseDownEvent: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||
|
||||
m_beingPressed = true;
|
||||
|
||||
|
@ -76,7 +76,7 @@ void Button::mouseDownEvent(MouseEvent& event)
|
|||
|
||||
void Button::mouseUpEvent(MouseEvent& event)
|
||||
{
|
||||
printf("Button::mouseUpEvent: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||
dbgprintf("Button::mouseUpEvent: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||
|
||||
m_beingPressed = false;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "CheckBox.h"
|
||||
#include "Painter.h"
|
||||
#include "CharacterBitmap.h"
|
||||
#include <SharedGraphics/Painter.h>
|
||||
#include <SharedGraphics/CharacterBitmap.h>
|
||||
|
||||
CheckBox::CheckBox(Widget* parent)
|
||||
: Widget(parent)
|
||||
|
@ -95,7 +95,7 @@ void CheckBox::paintEvent(PaintEvent&)
|
|||
|
||||
void CheckBox::mouseDownEvent(MouseEvent& event)
|
||||
{
|
||||
printf("CheckBox::mouseDownEvent: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||
dbgprintf("CheckBox::mouseDownEvent: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||
|
||||
setIsChecked(!isChecked());
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Point.h"
|
||||
#include "Rect.h"
|
||||
#include <SharedGraphics/Point.h>
|
||||
#include <SharedGraphics/Rect.h>
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/Types.h>
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
#include "EventLoop.h"
|
||||
#include "Event.h"
|
||||
#include "Object.h"
|
||||
#include "WindowManager.h"
|
||||
#include "AbstractScreen.h"
|
||||
#include "PS2MouseDevice.h"
|
||||
#include "Scheduler.h"
|
||||
|
||||
static EventLoop* s_mainEventLoop;
|
||||
|
||||
|
@ -31,14 +27,12 @@ EventLoop& EventLoop::main()
|
|||
|
||||
int EventLoop::exec()
|
||||
{
|
||||
m_server_process = current;
|
||||
m_running = true;
|
||||
for (;;) {
|
||||
if (m_queuedEvents.is_empty())
|
||||
waitForEvent();
|
||||
Vector<QueuedEvent> events;
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
events = move(m_queuedEvents);
|
||||
}
|
||||
for (auto& queuedEvent : events) {
|
||||
|
@ -51,7 +45,7 @@ int EventLoop::exec()
|
|||
ASSERT_NOT_REACHED();
|
||||
return 0;
|
||||
default:
|
||||
printf("event type %u with no receiver :(\n", event.type());
|
||||
dbgprintf("event type %u with no receiver :(\n", event.type());
|
||||
ASSERT_NOT_REACHED();
|
||||
return 1;
|
||||
}
|
||||
|
@ -70,26 +64,4 @@ void EventLoop::postEvent(Object* receiver, OwnPtr<Event>&& event)
|
|||
|
||||
void EventLoop::waitForEvent()
|
||||
{
|
||||
auto& mouse = PS2MouseDevice::the();
|
||||
auto& screen = AbstractScreen::the();
|
||||
bool prev_left_button = screen.left_mouse_button_pressed();
|
||||
bool prev_right_button = screen.right_mouse_button_pressed();
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
while (mouse.can_read(*m_server_process)) {
|
||||
signed_byte data[3];
|
||||
ssize_t nread = mouse.read(*m_server_process, (byte*)data, 3);
|
||||
ASSERT(nread == 3);
|
||||
bool left_button = data[0] & 1;
|
||||
bool right_button = data[0] & 2;
|
||||
dx += data[1];
|
||||
dy += -data[2];
|
||||
if (left_button != prev_left_button || right_button != prev_right_button || !mouse.can_read(*m_server_process)) {
|
||||
prev_left_button = left_button;
|
||||
prev_right_button = right_button;
|
||||
screen.on_receive_mouse_data(dx, dy, left_button, right_button);
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#include "Label.h"
|
||||
#include "Painter.h"
|
||||
#include <SharedGraphics/Painter.h>
|
||||
|
||||
Label::Label(Widget* parent)
|
||||
: Widget(parent)
|
||||
|
@ -29,7 +29,7 @@ void Label::paintEvent(PaintEvent&)
|
|||
|
||||
void Label::mouseMoveEvent(MouseEvent& event)
|
||||
{
|
||||
printf("Label::mouseMoveEvent: x=%d, y=%d\n", event.x(), event.y());
|
||||
dbgprintf("Label::mouseMoveEvent: x=%d, y=%d\n", event.x(), event.y());
|
||||
Widget::mouseMoveEvent(event);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#include "ListBox.h"
|
||||
#include "Painter.h"
|
||||
#include "Font.h"
|
||||
#include "Window.h"
|
||||
#include <SharedGraphics/Font.h>
|
||||
#include <SharedGraphics/Painter.h>
|
||||
|
||||
ListBox::ListBox(Widget* parent)
|
||||
: Widget(parent)
|
||||
|
@ -47,12 +47,12 @@ void ListBox::paintEvent(PaintEvent&)
|
|||
|
||||
void ListBox::mouseDownEvent(MouseEvent& event)
|
||||
{
|
||||
printf("ListBox::mouseDownEvent %d,%d\n", event.x(), event.y());
|
||||
dbgprintf("ListBox::mouseDownEvent %d,%d\n", event.x(), event.y());
|
||||
for (int i = m_scrollOffset; i < static_cast<int>(m_items.size()); ++i) {
|
||||
auto itemRect = item_rect(i);
|
||||
if (itemRect.contains(event.position())) {
|
||||
m_selectedIndex = i;
|
||||
printf("ListBox: selected item %u (\"%s\")\n", i, m_items[i].characters());
|
||||
dbgprintf("ListBox: selected item %u (\"%s\")\n", i, m_items[i].characters());
|
||||
update();
|
||||
return;
|
||||
}
|
|
@ -57,7 +57,7 @@ void Object::timerEvent(TimerEvent&)
|
|||
void Object::startTimer(int ms)
|
||||
{
|
||||
if (m_timerID) {
|
||||
printf("Object{%p} already has a timer!\n", this);
|
||||
dbgprintf("Object{%p} already has a timer!\n", this);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#include "TextBox.h"
|
||||
#include "Painter.h"
|
||||
#include "Font.h"
|
||||
#include "CharacterBitmap.h"
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <SharedGraphics/CharacterBitmap.h>
|
||||
#include <SharedGraphics/Font.h>
|
||||
#include <SharedGraphics/Painter.h>
|
||||
|
||||
TextBox::TextBox(Widget* parent)
|
||||
: Widget(parent)
|
||||
|
@ -48,7 +48,7 @@ void TextBox::paintEvent(PaintEvent&)
|
|||
int x = innerRect.x() + (i * font().glyph_width());
|
||||
auto* bitmap = font().glyph_bitmap(ch);
|
||||
if (!bitmap) {
|
||||
printf("TextBox: glyph missing: %02x\n", ch);
|
||||
dbgprintf("TextBox: glyph missing: %02x\n", ch);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
painter.draw_bitmap({x, y}, *bitmap, Color::Black);
|
|
@ -1,11 +1,10 @@
|
|||
#include "Widget.h"
|
||||
#include "Event.h"
|
||||
#include "EventLoop.h"
|
||||
#include "GraphicsBitmap.h"
|
||||
#include "WindowManager.h"
|
||||
#include "Window.h"
|
||||
#include "Painter.h"
|
||||
#include <AK/Assertions.h>
|
||||
#include <SharedGraphics/GraphicsBitmap.h>
|
||||
#include <SharedGraphics/Painter.h>
|
||||
|
||||
Widget::Widget(Widget* parent)
|
||||
: Object(parent)
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "Event.h"
|
||||
#include "Object.h"
|
||||
#include "Rect.h"
|
||||
#include "Color.h"
|
||||
#include "Font.h"
|
||||
#include <SharedGraphics/Rect.h>
|
||||
#include <SharedGraphics/Color.h>
|
||||
#include <SharedGraphics/Font.h>
|
||||
#include <AK/AKString.h>
|
||||
|
||||
class GraphicsBitmap;
|
42
LibGUI/Window.cpp
Normal file
42
LibGUI/Window.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "Window.h"
|
||||
#include "Event.h"
|
||||
#include "EventLoop.h"
|
||||
#include <SharedGraphics/GraphicsBitmap.h>
|
||||
|
||||
Window::Window(int window_id)
|
||||
: m_window_id(window_id)
|
||||
{
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
}
|
||||
|
||||
void Window::set_title(String&& title)
|
||||
{
|
||||
if (m_title == title)
|
||||
return;
|
||||
|
||||
m_title = move(title);
|
||||
}
|
||||
void Window::set_rect(const Rect& rect)
|
||||
{
|
||||
if (m_rect == rect)
|
||||
return;
|
||||
m_rect = rect;
|
||||
dbgprintf("Window::setRect %d,%d %dx%d\n", m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height());
|
||||
}
|
||||
|
||||
void Window::event(Event& event)
|
||||
{
|
||||
}
|
||||
|
||||
bool Window::is_visible() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window::close()
|
||||
{
|
||||
}
|
||||
|
|
@ -1,16 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "Object.h"
|
||||
#include "Rect.h"
|
||||
#include "GraphicsBitmap.h"
|
||||
#include <SharedGraphics/Rect.h>
|
||||
#include <SharedGraphics/GraphicsBitmap.h>
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/InlineLinkedList.h>
|
||||
|
||||
class Process;
|
||||
|
||||
class Window final : public Object, public InlineLinkedListNode<Window> {
|
||||
class Window final : public Object {
|
||||
public:
|
||||
Window(Process&, int window_id);
|
||||
explicit Window(int window_id);
|
||||
virtual ~Window() override;
|
||||
|
||||
int window_id() const { return m_window_id; }
|
||||
|
@ -41,18 +38,12 @@ public:
|
|||
|
||||
GraphicsBitmap* backing() { return m_backing.ptr(); }
|
||||
|
||||
// For InlineLinkedList.
|
||||
// FIXME: Maybe make a ListHashSet and then WindowManager can just use that.
|
||||
Window* m_next { nullptr };
|
||||
Window* m_prev { nullptr };
|
||||
|
||||
private:
|
||||
String m_title;
|
||||
Rect m_rect;
|
||||
bool m_is_being_dragged { false };
|
||||
|
||||
RetainPtr<GraphicsBitmap> m_backing;
|
||||
Process& m_process;
|
||||
int m_window_id { -1 };
|
||||
};
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
#include "MsgBox.h"
|
||||
#include "Font.h"
|
||||
#include "AbstractScreen.h"
|
||||
#include "Window.h"
|
||||
#include "Label.h"
|
||||
#include "Button.h"
|
||||
#include "Process.h"
|
||||
|
||||
#if 0
|
||||
void MsgBox(Window* owner, String&& text)
|
||||
{
|
||||
Font& font = Font::defaultFont();
|
||||
auto screenRect = AbstractScreen::the().rect();
|
||||
|
||||
int textWidth = text.length() * font.glyphWidth() + 8;
|
||||
int textHeight = font.glyphHeight() + 8;
|
||||
int horizontalPadding = 16;
|
||||
int verticalPadding = 16;
|
||||
int buttonWidth = 60;
|
||||
int buttonHeight = 20;
|
||||
int windowWidth = textWidth + horizontalPadding * 2;
|
||||
int windowHeight = textHeight + buttonHeight + verticalPadding * 3;
|
||||
|
||||
Rect windowRect(
|
||||
screenRect.center().x() - windowWidth / 2,
|
||||
screenRect.center().y() - windowHeight / 2,
|
||||
windowWidth,
|
||||
windowHeight
|
||||
);
|
||||
|
||||
Rect buttonRect(
|
||||
windowWidth / 2 - buttonWidth / 2,
|
||||
windowHeight - verticalPadding - buttonHeight,
|
||||
buttonWidth,
|
||||
buttonHeight
|
||||
);
|
||||
|
||||
auto* window = new Window(*current, current->make_window_id());
|
||||
window->setTitle("MsgBox");
|
||||
window->setRect(windowRect);
|
||||
auto* widget = new Widget;
|
||||
widget->setWindowRelativeRect({ 0, 0, windowWidth, windowHeight });
|
||||
widget->setFillWithBackgroundColor(true);
|
||||
window->setMainWidget(widget);
|
||||
auto* label = new Label(widget);
|
||||
label->setWindowRelativeRect({
|
||||
horizontalPadding,
|
||||
verticalPadding,
|
||||
textWidth,
|
||||
textHeight
|
||||
});
|
||||
label->setText(move(text));
|
||||
auto* button = new Button(widget);
|
||||
button->setCaption("OK");
|
||||
button->setWindowRelativeRect(buttonRect);
|
||||
button->onClick = [] (Button& button) {
|
||||
printf("MsgBox button pressed, closing MsgBox :)\n");
|
||||
button.window()->close();
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/AKString.h>
|
||||
|
||||
class Window;
|
||||
|
||||
void MsgBox(Window* owner, String&&);
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
#include "TerminalWidget.h"
|
||||
#include "Font.h"
|
||||
#include "Painter.h"
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
extern int g_fd;
|
||||
TerminalWidget* g_tw;
|
||||
|
||||
TerminalWidget::TerminalWidget(Widget* parent)
|
||||
: Widget(parent)
|
||||
{
|
||||
g_tw = this;
|
||||
|
||||
setWindowRelativeRect({ 0, 0, int(columns() * font().glyph_width()) + 4, int(rows() * font().glyph_height()) + 4 });
|
||||
|
||||
printf("rekt: %d x %d\n", width(), height());
|
||||
m_screen = new CharacterWithAttributes[rows() * columns()];
|
||||
for (unsigned row = 0; row < m_rows; ++row) {
|
||||
for (unsigned column = 0; column < m_columns; ++column) {
|
||||
at(row, column).character = ' ';
|
||||
at(row, column).attribute = 0x07;
|
||||
}
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
g_fd = posix_openpt(O_RDWR);
|
||||
#else
|
||||
g_fd = getpt();
|
||||
#endif
|
||||
|
||||
grantpt(g_fd);
|
||||
unlockpt(g_fd);
|
||||
char buf[1024];
|
||||
ptsname_r(g_fd, buf, sizeof(buf));
|
||||
|
||||
if (fork() == 0) {
|
||||
close(g_fd);
|
||||
setsid();
|
||||
int fd = open(buf, O_RDWR);
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
signal(SIGWINCH, SIG_IGN);
|
||||
ioctl(fd, TIOCSCTTY);
|
||||
execl("/bin/bash", "bash", nullptr);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
}
|
||||
|
||||
TerminalWidget::~TerminalWidget()
|
||||
{
|
||||
}
|
||||
|
||||
CharacterWithAttributes& TerminalWidget::at(unsigned row, unsigned column)
|
||||
{
|
||||
ASSERT(m_screen);
|
||||
ASSERT(row < m_rows);
|
||||
ASSERT(column < m_columns);
|
||||
return m_screen[row * columns() + column];
|
||||
}
|
||||
|
||||
void TerminalWidget::paintEvent(PaintEvent&)
|
||||
{
|
||||
Painter painter(*this);
|
||||
painter.fill_rect(rect(), Color::Black);
|
||||
|
||||
char buf[2] = { 0, 0 };
|
||||
for (unsigned row = 0; row < m_rows; ++row) {
|
||||
int y = row * font().glyph_height();
|
||||
for (unsigned column = 0; column < m_columns; ++column) {
|
||||
int x = column * font().glyph_width();
|
||||
buf[0] = at(row, column).character;
|
||||
painter.draw_text({ x + 2, y + 2, width(), font().glyph_height() }, buf, Painter::TextAlignment::TopLeft, Color(0xa0, 0xa0, 0xa0));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_belling)
|
||||
painter.draw_rect(rect(), Color::Red);
|
||||
}
|
||||
|
||||
void TerminalWidget::onReceive(const ByteBuffer& buffer)
|
||||
{
|
||||
for (unsigned i = 0; i < buffer.size(); ++i) {
|
||||
onReceive(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalWidget::onReceive(byte ch)
|
||||
{
|
||||
//printf("receive %02x\n", ch);
|
||||
auto scrollScreen = [&] () {
|
||||
memmove(m_screen, m_screen + columns(), (m_rows - 1) * columns() * sizeof(CharacterWithAttributes));
|
||||
memset(m_screen + (m_rows - 1) * columns(), ' ', columns() * sizeof(CharacterWithAttributes));
|
||||
};
|
||||
|
||||
auto addChar = [&] (byte ch) {
|
||||
at(m_cursorRow, m_cursorColumn).character = ch;
|
||||
if (++m_cursorColumn >= m_columns) {
|
||||
m_cursorColumn = 0;
|
||||
if (m_cursorRow < (m_rows - 1)) {
|
||||
++m_cursorRow;
|
||||
} else {
|
||||
scrollScreen();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
if (m_cursorRow < (m_rows - 1)) {
|
||||
++m_cursorRow;
|
||||
} else {
|
||||
scrollScreen();
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
m_cursorColumn = 0;
|
||||
break;
|
||||
case '\t':
|
||||
// FIXME: Respect terminal tab stops.
|
||||
while ((m_cursorColumn % 8) != 0 && m_cursorColumn < m_columns) {
|
||||
addChar(' ');
|
||||
break;
|
||||
case '\a':
|
||||
bell();
|
||||
break;
|
||||
case 8:
|
||||
if (m_cursorColumn > 0) {
|
||||
--m_cursorColumn;
|
||||
at(m_cursorRow, m_cursorColumn).character = ' ';
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
printf("TerminalWidget: got escape!\n");
|
||||
break;
|
||||
default:
|
||||
addChar(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void TerminalWidget::keyDownEvent(KeyEvent& event)
|
||||
{
|
||||
if (event.text().is_empty())
|
||||
return;
|
||||
write(g_fd, event.text().characters(), event.text().length());
|
||||
}
|
||||
|
||||
void TerminalWidget::keyUpEvent(KeyEvent& event)
|
||||
{
|
||||
return Widget::keyUpEvent(event);
|
||||
}
|
||||
|
||||
void TerminalWidget::bell()
|
||||
{
|
||||
if (m_belling)
|
||||
stopTimer();
|
||||
startTimer(250);
|
||||
m_belling = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void TerminalWidget::timerEvent(TimerEvent&)
|
||||
{
|
||||
m_belling = false;
|
||||
stopTimer();
|
||||
update();
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Widget.h"
|
||||
#include <AK/ByteBuffer.h>
|
||||
|
||||
struct CharacterWithAttributes {
|
||||
byte character;
|
||||
byte attribute;
|
||||
};
|
||||
|
||||
class TerminalWidget final : public Widget {
|
||||
public:
|
||||
explicit TerminalWidget(Widget* parent);
|
||||
virtual ~TerminalWidget() override;
|
||||
|
||||
unsigned rows() const { return m_rows; }
|
||||
unsigned columns() const { return m_columns; }
|
||||
|
||||
void onReceive(const ByteBuffer&);
|
||||
void onReceive(byte);
|
||||
|
||||
private:
|
||||
CharacterWithAttributes& at(unsigned row, unsigned column);
|
||||
|
||||
virtual void paintEvent(PaintEvent&) override;
|
||||
virtual void keyDownEvent(KeyEvent&) override;
|
||||
virtual void keyUpEvent(KeyEvent&) override;
|
||||
virtual void timerEvent(TimerEvent&) override;
|
||||
|
||||
void bell();
|
||||
|
||||
unsigned m_columns { 80 };
|
||||
unsigned m_rows { 25 };
|
||||
|
||||
unsigned m_cursorRow { 0 };
|
||||
unsigned m_cursorColumn { 0 };
|
||||
|
||||
CharacterWithAttributes* m_screen { nullptr };
|
||||
|
||||
bool m_belling { false };
|
||||
};
|
|
@ -1,99 +0,0 @@
|
|||
#include "Window.h"
|
||||
#include "WindowManager.h"
|
||||
#include "Event.h"
|
||||
#include "EventLoop.h"
|
||||
#include "Process.h"
|
||||
|
||||
Window::Window(Process& process, int window_id)
|
||||
: m_process(process)
|
||||
, m_window_id(window_id)
|
||||
{
|
||||
WindowManager::the().addWindow(*this);
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
WindowManager::the().removeWindow(*this);
|
||||
}
|
||||
|
||||
void Window::set_title(String&& title)
|
||||
{
|
||||
if (m_title == title)
|
||||
return;
|
||||
|
||||
m_title = move(title);
|
||||
WindowManager::the().notifyTitleChanged(*this);
|
||||
}
|
||||
|
||||
void Window::set_rect(const Rect& rect)
|
||||
{
|
||||
if (m_rect == rect)
|
||||
return;
|
||||
auto oldRect = m_rect;
|
||||
m_rect = rect;
|
||||
dbgprintf("Window::setRect %d,%d %dx%d\n", m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height());
|
||||
m_backing = GraphicsBitmap::create(m_process, m_rect.size());
|
||||
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
|
||||
}
|
||||
|
||||
// FIXME: Just use the same types.
|
||||
static GUI_MouseButton to_api(MouseButton button)
|
||||
{
|
||||
switch (button) {
|
||||
case MouseButton::None: return GUI_MouseButton::NoButton;
|
||||
case MouseButton::Left: return GUI_MouseButton::Left;
|
||||
case MouseButton::Right: return GUI_MouseButton::Right;
|
||||
case MouseButton::Middle: return GUI_MouseButton::Middle;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::event(Event& event)
|
||||
{
|
||||
GUI_Event gui_event;
|
||||
gui_event.window_id = window_id();
|
||||
|
||||
switch (event.type()) {
|
||||
case Event::Paint:
|
||||
gui_event.type = GUI_Event::Type::Paint;
|
||||
gui_event.paint.rect = static_cast<PaintEvent&>(event).rect();
|
||||
break;
|
||||
case Event::MouseMove:
|
||||
gui_event.type = GUI_Event::Type::MouseMove;
|
||||
gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
|
||||
break;
|
||||
case Event::MouseDown:
|
||||
gui_event.type = GUI_Event::Type::MouseDown;
|
||||
gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
|
||||
gui_event.mouse.button = to_api(static_cast<MouseEvent&>(event).button());
|
||||
break;
|
||||
case Event::MouseUp:
|
||||
gui_event.type = GUI_Event::Type::MouseUp;
|
||||
gui_event.mouse.position = static_cast<MouseEvent&>(event).position();
|
||||
gui_event.mouse.button = to_api(static_cast<MouseEvent&>(event).button());
|
||||
break;
|
||||
case Event::KeyDown:
|
||||
gui_event.type = GUI_Event::Type::KeyDown;
|
||||
gui_event.key.character = static_cast<KeyEvent&>(event).text()[0];
|
||||
break;
|
||||
}
|
||||
|
||||
if (gui_event.type == GUI_Event::Type::Invalid)
|
||||
return;
|
||||
|
||||
{
|
||||
LOCKER(m_process.gui_events_lock());
|
||||
m_process.gui_events().append(move(gui_event));
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::is_visible() const
|
||||
{
|
||||
return WindowManager::the().isVisible(const_cast<Window&>(*this));
|
||||
}
|
||||
|
||||
void Window::close()
|
||||
{
|
||||
WindowManager::the().removeWindow(*this);
|
||||
deleteLater();
|
||||
}
|
||||
|
100
Widgets/test.cpp
100
Widgets/test.cpp
|
@ -1,100 +0,0 @@
|
|||
#include "FrameBuffer.h"
|
||||
#include "EventLoop.h"
|
||||
#include "Label.h"
|
||||
#include "Button.h"
|
||||
#include "WindowManager.h"
|
||||
#include "Window.h"
|
||||
#include "ClockWidget.h"
|
||||
#include "CheckBox.h"
|
||||
#include "ListBox.h"
|
||||
#include "TextBox.h"
|
||||
#include "MsgBox.h"
|
||||
#include <cstdio>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FrameBuffer fb(800, 600);
|
||||
fb.show();
|
||||
|
||||
EventLoop loop;
|
||||
|
||||
auto* fontTestWindow = new Window;
|
||||
fontTestWindow->set_title("Font test");
|
||||
fontTestWindow->set_rect({ 140, 100, 300, 80 });
|
||||
|
||||
auto* fontTestWindowWidget = new Widget;
|
||||
fontTestWindow->setMainWidget(fontTestWindowWidget);
|
||||
fontTestWindowWidget->setWindowRelativeRect({ 0, 0, 300, 80 });
|
||||
|
||||
auto* l1 = new Label(fontTestWindowWidget);
|
||||
l1->setWindowRelativeRect({ 0, 0, 300, 20 });
|
||||
l1->setText("0123456789");
|
||||
|
||||
auto* l2 = new Label(fontTestWindowWidget);
|
||||
l2->setWindowRelativeRect({ 0, 20, 300, 20 });
|
||||
l2->setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
auto* l3 = new Label(fontTestWindowWidget);
|
||||
l3->setWindowRelativeRect({ 0, 40, 300, 20 });
|
||||
l3->setText("abcdefghijklmnopqrstuvwxyz");
|
||||
|
||||
auto* l4 = new Label(fontTestWindowWidget);
|
||||
l4->setWindowRelativeRect({ 0, 60, 300, 20 });
|
||||
l4->setText("!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~");
|
||||
|
||||
{
|
||||
auto* widgetTestWindow = new Window;
|
||||
widgetTestWindow->set_title("Widget test");
|
||||
widgetTestWindow->set_rect({ 20, 40, 100, 180 });
|
||||
|
||||
auto* widgetTestWindowWidget = new Widget;
|
||||
widgetTestWindowWidget->setWindowRelativeRect({ 0, 0, 100, 100 });
|
||||
widgetTestWindow->setMainWidget(widgetTestWindowWidget);
|
||||
|
||||
auto* l = new Label(widgetTestWindowWidget);
|
||||
l->setWindowRelativeRect({ 0, 0, 100, 20 });
|
||||
l->setText("Label");
|
||||
|
||||
auto* b = new Button(widgetTestWindowWidget);
|
||||
b->setWindowRelativeRect({ 0, 20, 100, 20 });
|
||||
b->setCaption("Button");
|
||||
|
||||
b->onClick = [] (Button& button) {
|
||||
printf("Button %p clicked!\n", &button);
|
||||
};
|
||||
|
||||
auto* c = new CheckBox(widgetTestWindowWidget);
|
||||
c->setWindowRelativeRect({ 0, 40, 100, 20 });
|
||||
c->setCaption("CheckBox");
|
||||
|
||||
auto *lb = new ListBox(widgetTestWindowWidget);
|
||||
lb->setWindowRelativeRect({ 0, 60, 100, 100 });
|
||||
lb->addItem("This");
|
||||
lb->addItem("is");
|
||||
lb->addItem("a");
|
||||
lb->addItem("ListBox");
|
||||
|
||||
auto *tb = new TextBox(widgetTestWindowWidget);
|
||||
tb->setWindowRelativeRect({ 0, 160, 100, 20 });
|
||||
tb->setText("Hello!");
|
||||
tb->setFocus(true);
|
||||
|
||||
tb->onReturnPressed = [] (TextBox& textBox) {
|
||||
printf("TextBox %p return pressed: '%s'\n", &textBox, textBox.text().characters());
|
||||
MsgBox(nullptr, textBox.text());
|
||||
};
|
||||
|
||||
WindowManager::the().setActiveWindow(widgetTestWindow);
|
||||
}
|
||||
|
||||
#if 0
|
||||
auto* clockWin = new Window;
|
||||
clockWin->setTitle("Clock");
|
||||
clockWin->setRect({ 500, 50, 100, 40 });
|
||||
clockWin->setMainWidget(new ClockWidget);
|
||||
#endif
|
||||
|
||||
MsgBox(nullptr, "This is a message box!");
|
||||
|
||||
return loop.exec();
|
||||
}
|
Loading…
Reference in a new issue