mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-04 23:19:27 +00:00
More hacking on Widgets.
This commit is contained in:
parent
aee66e0119
commit
f337616741
|
@ -27,12 +27,15 @@ AbstractScreen::~AbstractScreen()
|
||||||
|
|
||||||
void AbstractScreen::event(Event& event)
|
void AbstractScreen::event(Event& event)
|
||||||
{
|
{
|
||||||
if (event.type() == Event::MouseMove) {
|
if (event.type() == Event::MouseMove
|
||||||
|
|| event.type() == Event::MouseDown
|
||||||
|
|| event.type() == Event::MouseUp) {
|
||||||
auto& me = static_cast<MouseEvent&>(event);
|
auto& me = static_cast<MouseEvent&>(event);
|
||||||
printf("AbstractScreen::onMouseMove: %d, %d\n", me.x(), me.y());
|
//printf("AbstractScreen::onMouseMove: %d, %d\n", me.x(), me.y());
|
||||||
|
|
||||||
auto result = m_rootWidget->hitTest(me.x(), me.y());
|
auto result = m_rootWidget->hitTest(me.x(), me.y());
|
||||||
printf("hit test for %d,%d found: %s{%p} %d,%d\n", me.x(), me.y(), result.widget->className(), result.widget, result.localX, result.localY);
|
//printf("hit test for %d,%d found: %s{%p} %d,%d\n", me.x(), me.y(), result.widget->className(), result.widget, result.localX, result.localY);
|
||||||
|
auto localEvent = make<MouseEvent>(event.type(), result.localX, result.localY, me.button());
|
||||||
|
result.widget->event(*localEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
Widgets/Button.cpp
Normal file
39
Widgets/Button.cpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include "Button.h"
|
||||||
|
#include "Painter.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
Button::Button(Widget* parent)
|
||||||
|
: Widget(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Button::~Button()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::setCaption(String&& caption)
|
||||||
|
{
|
||||||
|
if (caption == m_caption)
|
||||||
|
return;
|
||||||
|
m_caption = std::move(caption);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::onPaint(PaintEvent&)
|
||||||
|
{
|
||||||
|
Painter painter(*this);
|
||||||
|
painter.fillRect({ 0, 0, width(), height() }, backgroundColor());
|
||||||
|
if (!caption().isEmpty()) {
|
||||||
|
painter.drawText({ 0, 0, width(), height() }, caption(), Painter::TextAlignment::Center, Color(0, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::onMouseDown(MouseEvent& event)
|
||||||
|
{
|
||||||
|
printf("Button::onMouseDown: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
|
||||||
|
|
||||||
|
setBackgroundColor(Color(0xff, 0xc0, 0xc0));
|
||||||
|
update();
|
||||||
|
Widget::onMouseDown(event);
|
||||||
|
}
|
||||||
|
|
22
Widgets/Button.h
Normal file
22
Widgets/Button.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
#include <AK/String.h>
|
||||||
|
|
||||||
|
class Button final : public Widget {
|
||||||
|
public:
|
||||||
|
explicit Button(Widget* parent);
|
||||||
|
virtual ~Button() override;
|
||||||
|
|
||||||
|
String caption() const { return m_caption; }
|
||||||
|
void setCaption(String&&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void onPaint(PaintEvent&) override;
|
||||||
|
virtual void onMouseDown(MouseEvent&) override;
|
||||||
|
|
||||||
|
virtual const char* className() const override { return "Button"; }
|
||||||
|
|
||||||
|
String m_caption;
|
||||||
|
};
|
||||||
|
|
|
@ -79,6 +79,7 @@ public:
|
||||||
enum class MouseButton : byte {
|
enum class MouseButton : byte {
|
||||||
None = 0,
|
None = 0,
|
||||||
Left,
|
Left,
|
||||||
|
Middle,
|
||||||
Right,
|
Right,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,19 @@ EventLoopSDL::~EventLoopSDL()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline MouseButton toMouseButton(byte sdlButton)
|
||||||
|
{
|
||||||
|
printf("sdlbutton = %u\n", sdlButton);
|
||||||
|
if (sdlButton == 1)
|
||||||
|
return MouseButton::Left;
|
||||||
|
if (sdlButton == 2)
|
||||||
|
return MouseButton::Middle;
|
||||||
|
if (sdlButton == 3)
|
||||||
|
return MouseButton::Right;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
return MouseButton::None;
|
||||||
|
}
|
||||||
|
|
||||||
void EventLoopSDL::waitForEvent()
|
void EventLoopSDL::waitForEvent()
|
||||||
{
|
{
|
||||||
SDL_Event sdlEvent;
|
SDL_Event sdlEvent;
|
||||||
|
@ -30,6 +43,9 @@ void EventLoopSDL::waitForEvent()
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
postEvent(&AbstractScreen::the(), make<MouseEvent>(Event::MouseMove, sdlEvent.motion.x, sdlEvent.motion.y));
|
postEvent(&AbstractScreen::the(), make<MouseEvent>(Event::MouseMove, sdlEvent.motion.x, sdlEvent.motion.y));
|
||||||
return;
|
return;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
postEvent(&AbstractScreen::the(), make<MouseEvent>(Event::MouseDown, sdlEvent.button.x, sdlEvent.button.y, toMouseButton(sdlEvent.button.button)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ void Label::onPaint(PaintEvent&)
|
||||||
Painter painter(*this);
|
Painter painter(*this);
|
||||||
painter.fillRect({ 0, 0, width(), height() }, Color(0x0, 0x0, 0x0));
|
painter.fillRect({ 0, 0, width(), height() }, Color(0x0, 0x0, 0x0));
|
||||||
if (!text().isEmpty())
|
if (!text().isEmpty())
|
||||||
painter.drawText({ 4, 4 }, text(), Color(0xff, 0xff, 0xff));
|
painter.drawText({ 4, 4, width(), height() }, text(), Painter::TextAlignment::TopLeft, Color(0xff, 0xff, 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::onMouseMove(MouseEvent& event)
|
void Label::onMouseMove(MouseEvent& event)
|
||||||
|
|
|
@ -17,6 +17,7 @@ VFS_OBJS = \
|
||||||
ColorSDL.o \
|
ColorSDL.o \
|
||||||
Painter.o \
|
Painter.o \
|
||||||
Label.o \
|
Label.o \
|
||||||
|
Button.o \
|
||||||
test.o
|
test.o
|
||||||
|
|
||||||
OBJS = $(AK_OBJS) $(VFS_OBJS)
|
OBJS = $(AK_OBJS) $(VFS_OBJS)
|
||||||
|
|
|
@ -35,24 +35,32 @@ void Painter::fillRect(const Rect& rect, Color color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::drawText(const Point& point, const String& text, const Color& color)
|
void Painter::drawText(const Rect& rect, const String& text, TextAlignment alignment, const Color& color)
|
||||||
{
|
{
|
||||||
Point p = point;
|
Point point;
|
||||||
p.moveBy(m_widget.x(), m_widget.y());
|
|
||||||
|
if (alignment == TextAlignment::TopLeft) {
|
||||||
|
point = rect.location();
|
||||||
|
point.moveBy(m_widget.x(), m_widget.y());;
|
||||||
|
} else if (alignment == TextAlignment::Center) {
|
||||||
|
int textWidth = text.length() * Peanut8x8::fontWidth;
|
||||||
|
point = rect.center();
|
||||||
|
point.moveBy(-(textWidth / 2), -(Peanut8x8::fontWidth / 2));
|
||||||
|
point.moveBy(m_widget.x(), m_widget.y());
|
||||||
|
} else {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
byte fontWidth = 8;
|
for (int row = 0; row < Peanut8x8::fontHeight; ++row) {
|
||||||
byte fontHeight = 8;
|
int y = point.y() + row;
|
||||||
|
|
||||||
for (int row = 0; row < fontHeight; ++row) {
|
|
||||||
int y = p.y() + row;
|
|
||||||
dword* bits = scanline(y);
|
dword* bits = scanline(y);
|
||||||
for (unsigned i = 0; i < text.length(); ++i) {
|
for (unsigned i = 0; i < text.length(); ++i) {
|
||||||
if (text[i] == ' ')
|
if (text[i] == ' ')
|
||||||
continue;
|
continue;
|
||||||
const char* fontCharacter = Peanut8x8::font[text[i] - Peanut8x8::firstCharacter];
|
const char* fontCharacter = Peanut8x8::font[text[i] - Peanut8x8::firstCharacter];
|
||||||
int x = p.x() + i * fontWidth;
|
int x = point.x() + i * Peanut8x8::fontWidth;
|
||||||
for (unsigned j = 0; j < fontWidth; ++j) {
|
for (unsigned j = 0; j < Peanut8x8::fontWidth; ++j) {
|
||||||
char fc = fontCharacter[row * fontWidth + j];
|
char fc = fontCharacter[row * Peanut8x8::fontWidth + j];
|
||||||
if (fc == '#')
|
if (fc == '#')
|
||||||
bits[x + j] = color.value();
|
bits[x + j] = color.value();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,11 @@ class Widget;
|
||||||
|
|
||||||
class Painter {
|
class Painter {
|
||||||
public:
|
public:
|
||||||
|
enum class TextAlignment { TopLeft, Center };
|
||||||
explicit Painter(Widget&);
|
explicit Painter(Widget&);
|
||||||
~Painter();
|
~Painter();
|
||||||
void fillRect(const Rect&, Color);
|
void fillRect(const Rect&, Color);
|
||||||
void drawText(const Point&, const String&, const Color& = Color());
|
void drawText(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, const Color& = Color());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Widget& m_widget;
|
Widget& m_widget;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
namespace Peanut8x8 {
|
namespace Peanut8x8 {
|
||||||
|
|
||||||
static constexpr char firstCharacter = '!';
|
static constexpr char firstCharacter = '!';
|
||||||
|
static constexpr byte fontWidth = 8;
|
||||||
|
static constexpr byte fontHeight = 8;
|
||||||
|
|
||||||
static constexpr const char* font[] {
|
static constexpr const char* font[] {
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@ public:
|
||||||
m_location.moveBy(dx, dy);
|
m_location.moveBy(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point center() const
|
||||||
|
{
|
||||||
|
return { x() + width() / 2, y() + height() / 2 };
|
||||||
|
}
|
||||||
|
|
||||||
bool contains(int x, int y) const
|
bool contains(int x, int y) const
|
||||||
{
|
{
|
||||||
return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom();
|
return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom();
|
||||||
|
|
|
@ -14,7 +14,7 @@ void RootWidget::onPaint(PaintEvent& event)
|
||||||
{
|
{
|
||||||
printf("RootWidget::onPaint\n");
|
printf("RootWidget::onPaint\n");
|
||||||
Painter painter(*this);
|
Painter painter(*this);
|
||||||
painter.fillRect(Rect(0, 0, 800, 600), Color(0x80, 0x80, 0x80));
|
painter.fillRect(Rect(0, 0, 800, 600), Color(0x40, 0x40, 0x40));
|
||||||
Widget::onPaint(event);
|
Widget::onPaint(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
Widget::Widget(Widget* parent)
|
Widget::Widget(Widget* parent)
|
||||||
: Object(parent)
|
: Object(parent)
|
||||||
{
|
{
|
||||||
|
m_backgroundColor = Color(255, 255, 255);
|
||||||
|
m_foregroundColor = Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget::~Widget()
|
Widget::~Widget()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Rect.h"
|
#include "Rect.h"
|
||||||
|
#include "Color.h"
|
||||||
|
|
||||||
class Widget : public Object {
|
class Widget : public Object {
|
||||||
public:
|
public:
|
||||||
|
@ -38,6 +39,14 @@ public:
|
||||||
|
|
||||||
void setRect(const Rect&);
|
void setRect(const Rect&);
|
||||||
|
|
||||||
|
Color backgroundColor() const { return m_backgroundColor; }
|
||||||
|
Color foregroundColor() const { return m_foregroundColor; }
|
||||||
|
|
||||||
|
void setBackgroundColor(Color color) { m_backgroundColor = color; }
|
||||||
|
void setForegroundColor(Color color) { m_foregroundColor = color; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
|
Color m_backgroundColor;
|
||||||
|
Color m_foregroundColor;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "EventLoopSDL.h"
|
#include "EventLoopSDL.h"
|
||||||
#include "RootWidget.h"
|
#include "RootWidget.h"
|
||||||
#include "Label.h"
|
#include "Label.h"
|
||||||
|
#include "Button.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
int main(int c, char** v)
|
int main(int c, char** v)
|
||||||
|
@ -30,7 +31,13 @@ int main(int c, char** v)
|
||||||
l4->setRect(Rect(100, 160, 300, 20));
|
l4->setRect(Rect(100, 160, 300, 20));
|
||||||
l4->setText("!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~");
|
l4->setText("!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~");
|
||||||
|
|
||||||
//l5->setText("Welcome to the Serenity Operating System");
|
auto* l5 = new Label(&w);
|
||||||
|
l5->setRect(Rect(200, 200, 400, 50));
|
||||||
|
l5->setText("Welcome to the Serenity Operating System");
|
||||||
|
|
||||||
|
auto* b = new Button(&w);
|
||||||
|
b->setRect(Rect(10, 10, 100, 30));
|
||||||
|
b->setCaption("Button!");
|
||||||
|
|
||||||
return loop.exec();
|
return loop.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue