forked from OpenGamers/abaddon
pull out chat input into its own component, rename some stuff
This commit is contained in:
53
components/chatinput.cpp
Normal file
53
components/chatinput.cpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include "chatinput.hpp"
|
||||||
|
|
||||||
|
ChatInput::ChatInput() {
|
||||||
|
get_style_context()->add_class("message-input");
|
||||||
|
set_propagate_natural_height(true);
|
||||||
|
set_min_content_height(20);
|
||||||
|
set_max_content_height(250);
|
||||||
|
set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||||
|
|
||||||
|
// hack
|
||||||
|
auto cb = [this](GdkEventKey *e) -> bool {
|
||||||
|
return event(reinterpret_cast<GdkEvent *>(e));
|
||||||
|
};
|
||||||
|
m_textview.signal_key_press_event().connect(cb, false);
|
||||||
|
m_textview.set_hexpand(false);
|
||||||
|
m_textview.set_halign(Gtk::ALIGN_FILL);
|
||||||
|
m_textview.set_valign(Gtk::ALIGN_CENTER);
|
||||||
|
m_textview.set_wrap_mode(Gtk::WRAP_WORD_CHAR);
|
||||||
|
m_textview.show();
|
||||||
|
add(m_textview);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatInput::InsertText(const Glib::ustring &text) {
|
||||||
|
GetBuffer()->insert_at_cursor(text);
|
||||||
|
m_textview.grab_focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> ChatInput::GetBuffer() {
|
||||||
|
return m_textview.get_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// this isnt connected directly so that the chat window can handle stuff like the completer first
|
||||||
|
bool ChatInput::ProcessKeyPress(GdkEventKey *event) {
|
||||||
|
if (event->keyval == GDK_KEY_Return) {
|
||||||
|
if (event->state & GDK_SHIFT_MASK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto buf = GetBuffer();
|
||||||
|
auto text = buf->get_text();
|
||||||
|
// sometimes a message thats just newlines can sneak in if you hold down enter
|
||||||
|
if (text.size() > 0 && !std::all_of(text.begin(), text.end(), [](gunichar c) -> bool { return c == gunichar('\n'); })) {
|
||||||
|
buf->set_text("");
|
||||||
|
m_signal_submit.emit(text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatInput::type_signal_submit ChatInput::signal_submit() {
|
||||||
|
return m_signal_submit;
|
||||||
|
}
|
||||||
23
components/chatinput.hpp
Normal file
23
components/chatinput.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <gtkmm.h>
|
||||||
|
|
||||||
|
class ChatInput : public Gtk::ScrolledWindow {
|
||||||
|
public:
|
||||||
|
ChatInput();
|
||||||
|
|
||||||
|
void InsertText(const Glib::ustring &text);
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> GetBuffer();
|
||||||
|
bool ProcessKeyPress(GdkEventKey *event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Gtk::TextView m_textview;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef sigc::signal<void, Glib::ustring> type_signal_submit;
|
||||||
|
|
||||||
|
type_signal_submit signal_submit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
type_signal_submit m_signal_submit;
|
||||||
|
};
|
||||||
@@ -2,13 +2,13 @@
|
|||||||
#include "chatmessage.hpp"
|
#include "chatmessage.hpp"
|
||||||
#include "../abaddon.hpp"
|
#include "../abaddon.hpp"
|
||||||
#include "typingindicator.hpp"
|
#include "typingindicator.hpp"
|
||||||
|
#include "chatinput.hpp"
|
||||||
|
|
||||||
ChatWindow::ChatWindow() {
|
ChatWindow::ChatWindow() {
|
||||||
m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||||
m_list = Gtk::manage(new Gtk::ListBox);
|
m_list = Gtk::manage(new Gtk::ListBox);
|
||||||
m_scroll = Gtk::manage(new Gtk::ScrolledWindow);
|
m_scroll = Gtk::manage(new Gtk::ScrolledWindow);
|
||||||
m_input = Gtk::manage(new Gtk::TextView);
|
m_input = Gtk::manage(new ChatInput);
|
||||||
m_input_scroll = Gtk::manage(new Gtk::ScrolledWindow);
|
|
||||||
m_typing_indicator = Gtk::manage(new TypingIndicator);
|
m_typing_indicator = Gtk::manage(new TypingIndicator);
|
||||||
|
|
||||||
m_typing_indicator->set_valign(Gtk::ALIGN_END);
|
m_typing_indicator->set_valign(Gtk::ALIGN_END);
|
||||||
@@ -16,12 +16,11 @@ ChatWindow::ChatWindow() {
|
|||||||
|
|
||||||
m_main->get_style_context()->add_class("messages");
|
m_main->get_style_context()->add_class("messages");
|
||||||
m_list->get_style_context()->add_class("messages");
|
m_list->get_style_context()->add_class("messages");
|
||||||
m_input_scroll->get_style_context()->add_class("message-input");
|
|
||||||
|
|
||||||
m_main->set_hexpand(true);
|
m_main->set_hexpand(true);
|
||||||
m_main->set_vexpand(true);
|
m_main->set_vexpand(true);
|
||||||
|
|
||||||
m_scroll->signal_edge_reached().connect(sigc::mem_fun(*this, &ChatWindow::on_scroll_edge_overshot));
|
m_scroll->signal_edge_reached().connect(sigc::mem_fun(*this, &ChatWindow::OnScrollEdgeOvershot));
|
||||||
|
|
||||||
auto v = m_scroll->get_vadjustment();
|
auto v = m_scroll->get_vadjustment();
|
||||||
v->signal_value_changed().connect([this, v] {
|
v->signal_value_changed().connect([this, v] {
|
||||||
@@ -44,20 +43,14 @@ ChatWindow::ChatWindow() {
|
|||||||
m_list->set_focus_vadjustment(m_scroll->get_vadjustment());
|
m_list->set_focus_vadjustment(m_scroll->get_vadjustment());
|
||||||
m_list->show();
|
m_list->show();
|
||||||
|
|
||||||
m_input->set_hexpand(false);
|
m_input->signal_submit().connect([this](const Glib::ustring &text) {
|
||||||
m_input->set_halign(Gtk::ALIGN_FILL);
|
if (m_active_channel.IsValid())
|
||||||
m_input->set_valign(Gtk::ALIGN_CENTER);
|
m_signal_action_chat_submit.emit(text, m_active_channel);
|
||||||
m_input->set_wrap_mode(Gtk::WRAP_WORD_CHAR);
|
});
|
||||||
m_input->signal_key_press_event().connect(sigc::mem_fun(*this, &ChatWindow::on_key_press_event), false);
|
m_input->signal_key_press_event().connect(sigc::mem_fun(*this, &ChatWindow::OnKeyPressEvent), false);
|
||||||
m_input->show();
|
m_input->show();
|
||||||
|
|
||||||
m_input_scroll->set_propagate_natural_height(true);
|
m_completer.SetBuffer(m_input->GetBuffer());
|
||||||
m_input_scroll->set_min_content_height(20);
|
|
||||||
m_input_scroll->set_max_content_height(250);
|
|
||||||
m_input_scroll->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
|
||||||
m_input_scroll->show();
|
|
||||||
|
|
||||||
m_completer.SetBuffer(m_input->get_buffer());
|
|
||||||
m_completer.SetGetChannelID([this]() -> auto {
|
m_completer.SetGetChannelID([this]() -> auto {
|
||||||
return m_active_channel;
|
return m_active_channel;
|
||||||
});
|
});
|
||||||
@@ -90,11 +83,10 @@ ChatWindow::ChatWindow() {
|
|||||||
|
|
||||||
m_completer.show();
|
m_completer.show();
|
||||||
|
|
||||||
m_input_scroll->add(*m_input);
|
|
||||||
m_scroll->add(*m_list);
|
m_scroll->add(*m_list);
|
||||||
m_main->add(*m_scroll);
|
m_main->add(*m_scroll);
|
||||||
m_main->add(m_completer);
|
m_main->add(m_completer);
|
||||||
m_main->add(*m_input_scroll);
|
m_main->add(*m_input);
|
||||||
m_main->add(*m_typing_indicator);
|
m_main->add(*m_typing_indicator);
|
||||||
m_main->show();
|
m_main->show();
|
||||||
}
|
}
|
||||||
@@ -160,9 +152,7 @@ void ChatWindow::AddNewHistory(const std::vector<Snowflake> &id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatWindow::InsertChatInput(std::string text) {
|
void ChatWindow::InsertChatInput(std::string text) {
|
||||||
// shouldn't need a mutex cuz called from gui action
|
m_input->InsertText(text);
|
||||||
m_input->get_buffer()->insert_at_cursor(text);
|
|
||||||
m_input->grab_focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Snowflake ChatWindow::GetOldestListedMessage() {
|
Snowflake ChatWindow::GetOldestListedMessage() {
|
||||||
@@ -188,23 +178,12 @@ Snowflake ChatWindow::GetActiveChannel() const {
|
|||||||
return m_active_channel;
|
return m_active_channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatWindow::on_key_press_event(GdkEventKey *e) {
|
bool ChatWindow::OnKeyPressEvent(GdkEventKey *e) {
|
||||||
if (m_completer.ProcessKeyPress(e))
|
if (m_completer.ProcessKeyPress(e))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (e->keyval == GDK_KEY_Return) {
|
if (m_input->ProcessKeyPress(e))
|
||||||
if (e->state & GDK_SHIFT_MASK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto buf = m_input->get_buffer();
|
|
||||||
auto text = buf->get_text();
|
|
||||||
if (text.size() == 0) return true;
|
|
||||||
buf->set_text("");
|
|
||||||
|
|
||||||
m_signal_action_chat_submit.emit(text, m_active_channel);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -297,7 +276,7 @@ void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWindow::on_scroll_edge_overshot(Gtk::PositionType pos) {
|
void ChatWindow::OnScrollEdgeOvershot(Gtk::PositionType pos) {
|
||||||
if (pos == Gtk::POS_TOP)
|
if (pos == Gtk::POS_TOP)
|
||||||
m_signal_action_chat_load_history.emit(m_active_channel);
|
m_signal_action_chat_load_history.emit(m_active_channel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "chatmessage.hpp"
|
#include "chatmessage.hpp"
|
||||||
#include "completer.hpp"
|
#include "completer.hpp"
|
||||||
|
|
||||||
|
class ChatInput;
|
||||||
class TypingIndicator;
|
class TypingIndicator;
|
||||||
class ChatWindow {
|
class ChatWindow {
|
||||||
public:
|
public:
|
||||||
@@ -34,8 +35,8 @@ protected:
|
|||||||
|
|
||||||
Snowflake m_active_channel;
|
Snowflake m_active_channel;
|
||||||
|
|
||||||
bool on_key_press_event(GdkEventKey *e);
|
bool OnKeyPressEvent(GdkEventKey *e);
|
||||||
void on_scroll_edge_overshot(Gtk::PositionType pos);
|
void OnScrollEdgeOvershot(Gtk::PositionType pos);
|
||||||
|
|
||||||
void ScrollToBottom();
|
void ScrollToBottom();
|
||||||
bool m_should_scroll_to_bottom = true;
|
bool m_should_scroll_to_bottom = true;
|
||||||
@@ -44,8 +45,7 @@ protected:
|
|||||||
Gtk::ListBox *m_list;
|
Gtk::ListBox *m_list;
|
||||||
Gtk::ScrolledWindow *m_scroll;
|
Gtk::ScrolledWindow *m_scroll;
|
||||||
|
|
||||||
Gtk::TextView *m_input;
|
ChatInput *m_input;
|
||||||
Gtk::ScrolledWindow *m_input_scroll;
|
|
||||||
|
|
||||||
Completer m_completer;
|
Completer m_completer;
|
||||||
TypingIndicator *m_typing_indicator;
|
TypingIndicator *m_typing_indicator;
|
||||||
|
|||||||
Reference in New Issue
Block a user