Skip to content

Commit

Permalink
IRCClient: Switch to using an HtmlView for the IRC window contents :^)
Browse files Browse the repository at this point in the history
This seemed like a perfect fit for LibHTML. We can now style the IRC
channels and queries however we like with the power of HTML and CSS.

This patch doesn't do much in the way of styling, it just gets the
basic mechanism into place.
  • Loading branch information
awesomekling committed Oct 28, 2019
1 parent 98ff8ef commit fa69b9f
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 146 deletions.
1 change: 1 addition & 0 deletions Applications/IRCClient/IRCAppWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class GAction;
class GStackWidget;
class GTableView;

class IRCAppWindow : public GWindow {
public:
Expand Down
59 changes: 50 additions & 9 deletions Applications/IRCClient/IRCLogBuffer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include "IRCLogBuffer.h"
#include "IRCLogBufferModel.h"
#include <LibHTML/DOM/DocumentType.h>
#include <LibHTML/DOM/ElementFactory.h>
#include <LibHTML/DOM/HTMLBodyElement.h>
#include <LibHTML/DOM/Text.h>
#include <LibHTML/Dump.h>
#include <LibHTML/Parser/HTMLParser.h>
#include <stdio.h>
#include <time.h>

Expand All @@ -9,8 +14,19 @@ NonnullRefPtr<IRCLogBuffer> 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()
Expand All @@ -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?
}
18 changes: 7 additions & 11 deletions Applications/IRCClient/IRCLogBuffer.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#pragma once

#include <AK/String.h>
#include <AK/CircularQueue.h>
#include <AK/RefPtr.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <AK/String.h>
#include <LibDraw/Color.h>

class IRCLogBufferModel;
#include <LibHTML/DOM/Document.h>

class IRCLogBuffer : public RefCounted<IRCLogBuffer> {
public:
Expand All @@ -21,17 +19,15 @@ class IRCLogBuffer : public RefCounted<IRCLogBuffer> {
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<IRCLogBufferModel> m_model;
CircularQueue<Message, 1000> m_messages;
RefPtr<Document> m_document;
RefPtr<Element> m_container_element;
};
81 changes: 0 additions & 81 deletions Applications/IRCClient/IRCLogBufferModel.cpp

This file was deleted.

30 changes: 0 additions & 30 deletions Applications/IRCClient/IRCLogBufferModel.h

This file was deleted.

16 changes: 4 additions & 12 deletions Applications/IRCClient/IRCWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
#include "IRCChannel.h"
#include "IRCChannelMemberListModel.h"
#include "IRCClient.h"
#include "IRCLogBufferModel.h"
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GSplitter.h>
#include <LibGUI/GTableView.h>
#include <LibGUI/GTextBox.h>
#include <LibGUI/GTextEditor.h>
#include <LibHTML/HtmlView.h>

IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& name, GWidget* parent)
: GWidget(parent)
Expand All @@ -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);
Expand Down Expand Up @@ -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<Document*>(&log_buffer.document()));
}

bool IRCWindow::is_active() const
Expand All @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions Applications/IRCClient/IRCWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -46,7 +46,7 @@ class IRCWindow : public GWidget {
void* m_owner { nullptr };
Type m_type;
String m_name;
RefPtr<GTableView> m_table_view;
RefPtr<HtmlView> m_html_view;
RefPtr<GTextEditor> m_text_editor;
RefPtr<IRCLogBuffer> m_log_buffer;
int m_unread_count { 0 };
Expand Down
1 change: 0 additions & 1 deletion Applications/IRCClient/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ OBJS = \
IRCChannel.o \
IRCQuery.o \
IRCLogBuffer.o \
IRCLogBufferModel.o \
IRCAppWindow.o \
IRCWindow.o \
IRCWindowListModel.o \
Expand Down

0 comments on commit fa69b9f

Please sign in to comment.