diff --git a/Applications/IRCClient/IRCAppWindow.h b/Applications/IRCClient/IRCAppWindow.h index d990aae6f8..3cbebc135c 100644 --- a/Applications/IRCClient/IRCAppWindow.h +++ b/Applications/IRCClient/IRCAppWindow.h @@ -7,6 +7,7 @@ class GAction; class GStackWidget; +class GTableView; class IRCAppWindow : public GWindow { public: diff --git a/Applications/IRCClient/IRCLogBuffer.cpp b/Applications/IRCClient/IRCLogBuffer.cpp index fb5934b071..a56443b145 100644 --- a/Applications/IRCClient/IRCLogBuffer.cpp +++ b/Applications/IRCClient/IRCLogBuffer.cpp @@ -1,5 +1,10 @@ #include "IRCLogBuffer.h" -#include "IRCLogBufferModel.h" +#include +#include +#include +#include +#include +#include #include #include @@ -9,8 +14,19 @@ NonnullRefPtr IRCLogBuffer::create() } IRCLogBuffer::IRCLogBuffer() - : m_model(IRCLogBufferModel::create(*this)) { + m_document = adopt(*new Document); + m_document->append_child(adopt(*new DocumentType(document()))); + auto html_element = create_element(document(), "html"); + m_document->append_child(html_element); + auto head_element = create_element(document(), "head"); + html_element->append_child(head_element); + auto style_element = create_element(document(), "style"); + style_element->append_child(adopt(*new Text(document(), "div { font-family: Csilla; font-weight: lighter; }"))); + head_element->append_child(style_element); + auto body_element = create_element(document(), "body"); + html_element->append_child(body_element); + m_container_element = body_element; } IRCLogBuffer::~IRCLogBuffer() @@ -19,19 +35,44 @@ IRCLogBuffer::~IRCLogBuffer() void IRCLogBuffer::add_message(char prefix, const String& name, const String& text, Color color) { - m_messages.enqueue({ time(nullptr), prefix, name, text, color }); - m_model->update(); + auto message_element = create_element(document(), "div"); + message_element->set_attribute("style", String::format("color: %s;", color.to_string().characters())); + auto timestamp_element = create_element(document(), "span"); + auto now = time(nullptr); + auto* tm = localtime(&now); + auto timestamp_string = String::format("%02u:%02u:%02u ", tm->tm_hour, tm->tm_min, tm->tm_sec); + timestamp_element->append_child(adopt(*new Text(document(), timestamp_string))); + auto nick_element = create_element(document(), "b"); + nick_element->append_child(*new Text(document(), String::format("<%c%s> ", prefix ? prefix : ' ', name.characters()))); + auto text_element = create_element(document(), "span"); + text_element->append_child(*new Text(document(), text)); + message_element->append_child(timestamp_element); + message_element->append_child(nick_element); + message_element->append_child(text_element); + m_container_element->append_child(message_element); + + m_document->force_layout(); } void IRCLogBuffer::add_message(const String& text, Color color) { - m_messages.enqueue({ time(nullptr), '\0', String(), text, color }); - m_model->update(); + auto message_element = create_element(document(), "div"); + message_element->set_attribute("style", String::format("color: %s;", color.to_string().characters())); + auto timestamp_element = create_element(document(), "span"); + auto now = time(nullptr); + auto* tm = localtime(&now); + auto timestamp_string = String::format("%02u:%02u:%02u ", tm->tm_hour, tm->tm_min, tm->tm_sec); + timestamp_element->append_child(adopt(*new Text(document(), timestamp_string))); + auto text_element = create_element(document(), "span"); + text_element->append_child(*new Text(document(), text)); + message_element->append_child(timestamp_element); + message_element->append_child(text_element); + m_container_element->append_child(message_element); + + m_document->force_layout(); } void IRCLogBuffer::dump() const { - for (auto& message : m_messages) { - printf("%u <%c%8s> %s\n", message.timestamp, message.prefix, message.sender.characters(), message.text.characters()); - } + // FIXME: Remove me? } diff --git a/Applications/IRCClient/IRCLogBuffer.h b/Applications/IRCClient/IRCLogBuffer.h index 6cf7469698..82b31737f3 100644 --- a/Applications/IRCClient/IRCLogBuffer.h +++ b/Applications/IRCClient/IRCLogBuffer.h @@ -1,12 +1,10 @@ #pragma once -#include -#include -#include #include +#include +#include #include - -class IRCLogBufferModel; +#include class IRCLogBuffer : public RefCounted { public: @@ -21,17 +19,15 @@ public: Color color { Color::Black }; }; - int count() const { return m_messages.size(); } - const Message& at(int index) const { return m_messages.at(index); } void add_message(char prefix, const String& name, const String& text, Color = Color::Black); void add_message(const String& text, Color = Color::Black); void dump() const; - const IRCLogBufferModel* model() const { return m_model.ptr(); } - IRCLogBufferModel* model() { return m_model.ptr(); } + const Document& document() const { return *m_document; } + Document& document() { return *m_document; } private: IRCLogBuffer(); - NonnullRefPtr m_model; - CircularQueue m_messages; + RefPtr m_document; + RefPtr m_container_element; }; diff --git a/Applications/IRCClient/IRCLogBufferModel.cpp b/Applications/IRCClient/IRCLogBufferModel.cpp deleted file mode 100644 index db14ba49cd..0000000000 --- a/Applications/IRCClient/IRCLogBufferModel.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "IRCLogBufferModel.h" -#include "IRCLogBuffer.h" -#include -#include -#include - -IRCLogBufferModel::IRCLogBufferModel(NonnullRefPtr&& log_buffer) - : m_log_buffer(move(log_buffer)) -{ -} - -IRCLogBufferModel::~IRCLogBufferModel() -{ -} - -int IRCLogBufferModel::row_count(const GModelIndex&) const -{ - return m_log_buffer->count(); -} - -int IRCLogBufferModel::column_count(const GModelIndex&) const -{ - return Column::__Count; -} - -String IRCLogBufferModel::column_name(int column) const -{ - switch (column) { - case Column::Timestamp: - return "Time"; - case Column::Name: - return "Name"; - case Column::Text: - return "Text"; - } - ASSERT_NOT_REACHED(); -} - -GModel::ColumnMetadata IRCLogBufferModel::column_metadata(int column) const -{ - switch (column) { - case Column::Timestamp: - return { 60, TextAlignment::CenterLeft }; - case Column::Name: - return { 70, TextAlignment::CenterRight, &Font::default_bold_font() }; - case Column::Text: - return { 800, TextAlignment::CenterLeft }; - } - ASSERT_NOT_REACHED(); -} - -GVariant IRCLogBufferModel::data(const GModelIndex& index, Role role) const -{ - if (role == Role::Display) { - auto& entry = m_log_buffer->at(index.row()); - switch (index.column()) { - case Column::Timestamp: { - auto* tm = localtime(&entry.timestamp); - return String::format("%02u:%02u:%02u", tm->tm_hour, tm->tm_min, tm->tm_sec); - } - case Column::Name: - if (entry.sender.is_empty()) - return String::empty(); - return String::format("<%c%s>", entry.prefix ? entry.prefix : ' ', entry.sender.characters()); - case Column::Text: - return entry.text; - } - } - if (role == Role::ForegroundColor) { - if (index.column() == Column::Timestamp) - return Color(Color::MidGray); - if (index.column() == Column::Text) - return m_log_buffer->at(index.row()).color; - } - return {}; -} - -void IRCLogBufferModel::update() -{ - did_update(); -} diff --git a/Applications/IRCClient/IRCLogBufferModel.h b/Applications/IRCClient/IRCLogBufferModel.h deleted file mode 100644 index d0685f4637..0000000000 --- a/Applications/IRCClient/IRCLogBufferModel.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -class IRCLogBuffer; - -class IRCLogBufferModel final : public GModel { -public: - enum Column { - Timestamp = 0, - Name, - Text, - __Count, - }; - - static NonnullRefPtr create(NonnullRefPtr&& log_buffer) { return adopt(*new IRCLogBufferModel(move(log_buffer))); } - virtual ~IRCLogBufferModel() override; - - virtual int row_count(const GModelIndex&) const override; - virtual int column_count(const GModelIndex&) const override; - virtual String column_name(int column) const override; - virtual ColumnMetadata column_metadata(int column) const override; - virtual GVariant data(const GModelIndex&, Role = Role::Display) const override; - virtual void update() override; - -private: - explicit IRCLogBufferModel(NonnullRefPtr&&); - - NonnullRefPtr m_log_buffer; -}; diff --git a/Applications/IRCClient/IRCWindow.cpp b/Applications/IRCClient/IRCWindow.cpp index 0c08206e54..7f0acbac5d 100644 --- a/Applications/IRCClient/IRCWindow.cpp +++ b/Applications/IRCClient/IRCWindow.cpp @@ -2,12 +2,12 @@ #include "IRCChannel.h" #include "IRCChannelMemberListModel.h" #include "IRCClient.h" -#include "IRCLogBufferModel.h" #include #include #include #include #include +#include IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& name, GWidget* parent) : GWidget(parent) @@ -21,15 +21,7 @@ IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& na // Make a container for the log buffer view + (optional) member list. auto container = GSplitter::construct(Orientation::Horizontal, this); - m_table_view = GTableView::construct(container); - m_table_view->set_size_columns_to_fit_content(true); - m_table_view->set_headers_visible(false); - m_table_view->set_font(Font::default_fixed_width_font()); - m_table_view->set_alternating_row_colors(false); - - if (m_type == Server) { - m_table_view->set_column_hidden(IRCLogBufferModel::Column::Name, true); - } + m_html_view = HtmlView::construct(container); if (m_type == Channel) { auto member_view = GTableView::construct(container); @@ -65,7 +57,7 @@ IRCWindow::~IRCWindow() void IRCWindow::set_log_buffer(const IRCLogBuffer& log_buffer) { m_log_buffer = &log_buffer; - m_table_view->set_model(log_buffer.model()); + m_html_view->set_document(const_cast(&log_buffer.document())); } bool IRCWindow::is_active() const @@ -80,7 +72,7 @@ void IRCWindow::did_add_message() m_client.aid_update_window_list(); return; } - m_table_view->scroll_to_bottom(); + m_html_view->scroll_to_bottom(); } void IRCWindow::clear_unread_count() diff --git a/Applications/IRCClient/IRCWindow.h b/Applications/IRCClient/IRCWindow.h index 62c26fd681..2239e01b26 100644 --- a/Applications/IRCClient/IRCWindow.h +++ b/Applications/IRCClient/IRCWindow.h @@ -6,8 +6,8 @@ class IRCChannel; class IRCClient; class IRCQuery; class IRCLogBuffer; -class GTableView; class GTextEditor; +class HtmlView; class IRCWindow : public GWidget { C_OBJECT(IRCWindow) @@ -46,7 +46,7 @@ private: void* m_owner { nullptr }; Type m_type; String m_name; - RefPtr m_table_view; + RefPtr m_html_view; RefPtr m_text_editor; RefPtr m_log_buffer; int m_unread_count { 0 }; diff --git a/Applications/IRCClient/Makefile b/Applications/IRCClient/Makefile index fef4865cca..6fe6656832 100644 --- a/Applications/IRCClient/Makefile +++ b/Applications/IRCClient/Makefile @@ -5,7 +5,6 @@ OBJS = \ IRCChannel.o \ IRCQuery.o \ IRCLogBuffer.o \ - IRCLogBufferModel.o \ IRCAppWindow.o \ IRCWindow.o \ IRCWindowListModel.o \