From c61cbf4234cbfe76fc2db04600f17b07c4f4d2a3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 11 Oct 2018 02:50:08 +0200 Subject: [PATCH] Start poking at a TerminalWidget. --- Widgets/Makefile | 1 + Widgets/TerminalWidget.cpp | 69 ++++++++++++++++++++++++++++++++++++++ Widgets/TerminalWidget.h | 33 ++++++++++++++++++ Widgets/test.cpp | 7 ++-- 4 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 Widgets/TerminalWidget.cpp create mode 100644 Widgets/TerminalWidget.h diff --git a/Widgets/Makefile b/Widgets/Makefile index 0ddb811396..11ed7e6b51 100644 --- a/Widgets/Makefile +++ b/Widgets/Makefile @@ -18,6 +18,7 @@ VFS_OBJS = \ Painter.o \ Label.o \ Button.o \ + TerminalWidget.o \ test.o OBJS = $(AK_OBJS) $(VFS_OBJS) diff --git a/Widgets/TerminalWidget.cpp b/Widgets/TerminalWidget.cpp new file mode 100644 index 0000000000..9de00cd9c8 --- /dev/null +++ b/Widgets/TerminalWidget.cpp @@ -0,0 +1,69 @@ +#include "TerminalWidget.h" +#include "Painter.h" + +TerminalWidget::TerminalWidget(Widget* parent) + : Widget(parent) +{ + setRect({ 100, 300, columns() * 8, rows() * 8 }); + m_screen = new CharacterWithAttributes[rows() * columns() * 2]; + 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; + } + } + onReceive(String("Serenity/OS").toByteBuffer()); +} + +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::onPaint(PaintEvent&) +{ + Painter painter(*this); + + painter.fillRect({ 0, 0, width(), height() }, Color(0, 0, 0)); + + char buf[2] = { 0, 0 }; + for (unsigned row = 0; row < m_rows; ++row) { + int y = row * 8; + for (unsigned column = 0; column < m_columns; ++column) { + int x = column * 8; + buf[0] = at(row, column).character; + painter.drawText({ x, y, width(), 8 }, buf, Painter::TextAlignment::TopLeft, Color(0xa0, 0xa0, 0xa0)); + } + } +} + +void TerminalWidget::onReceive(const ByteBuffer& buffer) +{ + for (unsigned i = 0; i < buffer.size(); ++i) { + onReceive(buffer[i]); + } +} + +void TerminalWidget::onReceive(byte ch) +{ + at(m_cursorRow, m_cursorColumn).character = ch; + printf("%2u,%2u -> ", m_cursorRow, m_cursorColumn); + if (++m_cursorColumn > m_columns) { + m_cursorColumn = 0; + if (m_cursorRow < (m_rows - 1)) { + ++m_cursorRow; + } else { + // FIXME: Scroll it! + ASSERT_NOT_REACHED(); + } + } + printf("%2u,%2u\n", m_cursorRow, m_cursorColumn); +} + diff --git a/Widgets/TerminalWidget.h b/Widgets/TerminalWidget.h new file mode 100644 index 0000000000..ba77c5d10a --- /dev/null +++ b/Widgets/TerminalWidget.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Widget.h" +#include + +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; } + +private: + CharacterWithAttributes& at(unsigned row, unsigned column); + + virtual void onPaint(PaintEvent&) override; + void onReceive(const ByteBuffer&); + void onReceive(byte); + + unsigned m_columns { 80 }; + unsigned m_rows { 25 }; + + unsigned m_cursorRow { 0 }; + unsigned m_cursorColumn { 0 }; + + CharacterWithAttributes* m_screen { nullptr }; +}; diff --git a/Widgets/test.cpp b/Widgets/test.cpp index b6d437041a..60426f7268 100644 --- a/Widgets/test.cpp +++ b/Widgets/test.cpp @@ -3,6 +3,7 @@ #include "RootWidget.h" #include "Label.h" #include "Button.h" +#include "TerminalWidget.h" #include int main(int c, char** v) @@ -31,13 +32,11 @@ int main(int c, char** v) l4->setRect(Rect(100, 160, 300, 20)); l4->setText("!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~"); - 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!"); + auto* t = new TerminalWidget(&w); + return loop.exec(); }