aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/style.css29
m---------depends/dchat_core0
-rw-r--r--images/add_button.pngbin0 -> 1568 bytes
-rw-r--r--images/add_button_small.pngbin0 -> 1122 bytes
-rw-r--r--include/ChatWindow.hpp15
-rw-r--r--include/ImageButton.hpp12
-rw-r--r--include/InputDialog.hpp16
-rw-r--r--src/ChatWindow.cpp156
-rw-r--r--src/ImageButton.cpp14
-rw-r--r--src/InputDialog.cpp32
-rw-r--r--src/Window.cpp13
-rw-r--r--src/main.cpp1
12 files changed, 232 insertions, 56 deletions
diff --git a/css/style.css b/css/style.css
index 65cc83d..7b82820 100644
--- a/css/style.css
+++ b/css/style.css
@@ -6,13 +6,17 @@ window {
background-color: #2f3136;
}
+dialog {
+ background-color: #2f3136;
+}
+
entry {
caret-color: #f7f7f7;
background-color: #444444;
border-color: #444444;
border-radius: 10px;
color: #f7f7f7;
- box-shadow: 0px 0px 0px 0px;
+ box-shadow: none;
}
label {
@@ -39,12 +43,12 @@ scrollbar {
button {
background-image: none;
- background-color: #2f3136;
+ background-color: #36393e;
color: #f7f7f7;
border-style: none;
outline-style: none;
- box-shadow: 0px 0px 0px transparent;
- text-shadow: 0px 0px 0px transparent;
+ box-shadow: none;
+ text-shadow: none;
}
.confirm-button {
@@ -96,7 +100,7 @@ separator {
padding: 10px 10px 10px 10px;
}
-#current-channel-title {
+#current-room-title {
color: #f7f7f7;
font-size: 20px;
font-weight: bold;
@@ -123,11 +127,11 @@ separator {
font-size: 16px;
}
-.channel-button {
- background-color: transparent;
+.room-button {
+ background: none;
}
-#users-title {
+.users-title {
color: #f7f7f7;
font-weight: bold;
font-size: 16px;
@@ -175,6 +179,15 @@ textview text {
padding: 2em;
}
+.image-button {
+ background-image: none;
+ background: none;
+ border-style: none;
+ outline-style: none;
+ box-shadow: none;
+ text-shadow: none;
+}
+
/*
#chat-input {
border-style: none;
diff --git a/depends/dchat_core b/depends/dchat_core
-Subproject 391e0cb6a667fa384d61a9ef7909482d2e1bbb5
+Subproject c5b916157ae111da514481899d53f3e2bf5be98
diff --git a/images/add_button.png b/images/add_button.png
new file mode 100644
index 0000000..2efa8a0
--- /dev/null
+++ b/images/add_button.png
Binary files differ
diff --git a/images/add_button_small.png b/images/add_button_small.png
new file mode 100644
index 0000000..d6c0a6c
--- /dev/null
+++ b/images/add_button_small.png
Binary files differ
diff --git a/include/ChatWindow.hpp b/include/ChatWindow.hpp
index 988b225..7a61d91 100644
--- a/include/ChatWindow.hpp
+++ b/include/ChatWindow.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "ImageButton.hpp"
#include <dchat/Room.hpp>
#include <gtkmm/label.h>
#include <gtkmm/togglebutton.h>
@@ -20,35 +21,43 @@ namespace dchat
{
public:
ChatWindow();
+ ~ChatWindow();
void addRoom(std::shared_ptr<Room> room);
void addMessage(const RoomAddMessageRequest &request);
void addUser(std::shared_ptr<Room> room, std::shared_ptr<User> user);
void setUserNickname(const UserChangeNicknameRequest &request);
+ void changeRoomName(const RoomChangeNameRequest &request);
void scrollToBottom();
private:
void setupTopBar();
void setupLeftPanel(Gtk::Paned *sidePanels);
void setupMessageArea(Gtk::Grid *rightPanel);
void setupChatInput(Gtk::Grid *rightPanel);
+
+ void setCurrentRoom(std::shared_ptr<Room> room);
private:
Gtk::Grid topbar;
Gtk::Entry topbarSearchBar;
Gtk::Grid leftPanelChannels;
- Gtk::Grid leftPanelUsers;
+ Gtk::Stack leftPanelUsersStack;
+ ImageButton addRoomButton;
Gtk::Label currentChannelTitle;
Gtk::ScrolledWindow messageArea;
- Gtk::Grid messageAreaLayout;
+ Gtk::Stack messageAreaStack;
Gtk::TextView chatInput;
struct RoomData
{
+ Gtk::Grid *leftPanelUsersLayout;
+ Gtk::Grid *messageAreaLayout;
Gtk::ToggleButton *button;
};
- odhtdb::MapHash<RoomData> roomDataById;
+ odhtdb::MapHash<RoomData*> roomDataById;
odhtdb::MapHash<ChatMessage*> messageById;
int chatPrevNumLines;
int roomCount;
+ RoomData *currentRoomData;
std::shared_ptr<Room> currentRoom;
};
} \ No newline at end of file
diff --git a/include/ImageButton.hpp b/include/ImageButton.hpp
new file mode 100644
index 0000000..16b0840
--- /dev/null
+++ b/include/ImageButton.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <gtkmm/button.h>
+
+namespace dchat
+{
+ class ImageButton : public Gtk::Button
+ {
+ public:
+ ImageButton(const char *filepath, const char *text);
+ };
+} \ No newline at end of file
diff --git a/include/InputDialog.hpp b/include/InputDialog.hpp
new file mode 100644
index 0000000..4b2b02a
--- /dev/null
+++ b/include/InputDialog.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+
+namespace dchat
+{
+ class InputDialog : public Gtk::Dialog
+ {
+ public:
+ InputDialog(const char *title, const char *text, const char *acceptText = "Create", const char *cancelText = "Cancel");
+ Glib::ustring getInput() const;
+
+ Gtk::Entry entry;
+ };
+} \ No newline at end of file
diff --git a/src/ChatWindow.cpp b/src/ChatWindow.cpp
index c82e7fa..273f0e0 100644
--- a/src/ChatWindow.cpp
+++ b/src/ChatWindow.cpp
@@ -1,5 +1,6 @@
#include "../include/ChatWindow.hpp"
#include "../include/ChatMessage.hpp"
+#include "../include/InputDialog.hpp"
#include <gtkmm/alignment.h>
#include <gtkmm/viewport.h>
#include <gtkmm/scrollbar.h>
@@ -12,8 +13,12 @@ namespace dchat
const int MERGE_MESSAGE_TIMESTAMP_DIFF_SEC = 60;
ChatWindow::ChatWindow() :
- roomCount(0)
+ addRoomButton("images/add_button_small.png", " Add room"),
+ roomCount(0),
+ currentRoomData(nullptr)
{
+ leftPanelUsersStack.set_homogeneous(false);
+ messageAreaStack.set_homogeneous(false);
setupTopBar();
Gtk::Paned *sidePanels = Gtk::manage(new Gtk::Paned());
@@ -24,6 +29,7 @@ namespace dchat
setupLeftPanel(sidePanels);
Gtk::Grid *rightPanel = Gtk::manage(new Gtk::Grid());
+ rightPanel->set_vexpand(true);
rightPanel->set_hexpand(true);
sidePanels->add2(*rightPanel);
@@ -34,6 +40,17 @@ namespace dchat
set_hexpand(true);
}
+ ChatWindow::~ChatWindow()
+ {
+ for(auto &it : roomDataById)
+ {
+ delete it.second->leftPanelUsersLayout;
+ delete it.second->messageAreaLayout;
+ delete it.second->button;
+ delete it.second;
+ }
+ }
+
void ChatWindow::setupTopBar()
{
topbar.set_name("top-bar");
@@ -49,18 +66,21 @@ namespace dchat
topbarSpacer->set_size_request(50);
topbar.attach_next_to(*topbarSpacer, topbarSearchBar, Gtk::POS_RIGHT, 1, 1);
- currentChannelTitle.set_text("Linux");
- currentChannelTitle.set_name("current-channel-title");
+ currentChannelTitle.set_name("current-room-title");
topbar.attach_next_to(currentChannelTitle, *topbarSpacer, Gtk::POS_RIGHT, 1, 1);
}
void ChatWindow::setupLeftPanel(Gtk::Paned *sidePanels)
{
+ Gtk::Grid *leftPanelLayout = Gtk::manage(new Gtk::Grid());
+ leftPanelLayout->set_vexpand(true);
+ leftPanelLayout->set_size_request(200);
+ leftPanelLayout->set_name("left-panel");
+ sidePanels->add1(*leftPanelLayout);
+
Gtk::Paned *leftPanel = Gtk::manage(new Gtk::Paned(Gtk::ORIENTATION_VERTICAL));
- leftPanel->set_size_request(200);
- leftPanel->set_name("left-panel");
leftPanel->set_vexpand(true);
- sidePanels->add1(*leftPanel);
+ leftPanelLayout->attach(*leftPanel, 0, 0, 1, 2);
leftPanelChannels.set_vexpand(true);
leftPanel->add1(leftPanelChannels);
@@ -72,14 +92,26 @@ namespace dchat
leftPanelChannels.attach(*channelsTitle, 0, 0, 1, 1);
////
- leftPanelUsers.set_vexpand(true);
- leftPanel->add2(leftPanelUsers);
+ leftPanelUsersStack.set_vexpand(true);
+ leftPanel->add2(leftPanelUsersStack);
- Gtk::Label *usersTitle = Gtk::manage(new Gtk::Label());
- usersTitle->set_name("users-title");
- usersTitle->set_text("Users");
- usersTitle->set_halign(Gtk::ALIGN_START);
- leftPanelUsers.attach(*usersTitle, 0, 0, 1, 1);
+ addRoomButton.set_halign(Gtk::ALIGN_START);
+ leftPanelLayout->attach_next_to(addRoomButton, *leftPanel, Gtk::POS_BOTTOM, 1, 1);
+ addRoomButton.signal_clicked().connect([this]()
+ {
+ InputDialog createRoomDialog("Create a new room", "Room name");
+ switch(createRoomDialog.run())
+ {
+ case Gtk::RESPONSE_ACCEPT:
+ {
+ // TODO: Do not allow if room name size is == 0 or > 32
+ currentRoom->rooms->createRoom(createRoomDialog.getInput());
+ break;
+ }
+ default:
+ break;
+ }
+ });
}
void ChatWindow::setupMessageArea(Gtk::Grid *rightPanel)
@@ -89,8 +121,8 @@ namespace dchat
messageArea.set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC);
rightPanel->attach(messageArea, 0, 0, 1, 2);
- messageAreaLayout.set_name("chat-area-layout");
- messageArea.add(messageAreaLayout);
+ messageAreaStack.set_name("chat-area-layout");
+ messageArea.add(messageAreaStack);
}
void ChatWindow::setupChatInput(Gtk::Grid *rightPanel)
@@ -159,17 +191,57 @@ namespace dchat
void ChatWindow::addRoom(std::shared_ptr<Room> room)
{
+ std::string roomIdStr = room->id->toString();
+ Gtk::Grid *leftPanelUsersLayout = new Gtk::Grid();
+ leftPanelUsersLayout->set_vexpand(true);
+ leftPanelUsersLayout->show();
+ leftPanelUsersStack.add(*leftPanelUsersLayout, roomIdStr);
+
+ Gtk::Label *usersTitle = Gtk::manage(new Gtk::Label());
+ usersTitle->get_style_context()->add_class("users-title");
+ usersTitle->set_text("Users");
+ usersTitle->set_halign(Gtk::ALIGN_START);
+ usersTitle->show();
+ leftPanelUsersLayout->attach(*usersTitle, 0, 0, 1, 1);
+
+ Gtk::Grid *messageAreaLayout = new Gtk::Grid();
+ messageAreaLayout->show();
+ messageAreaStack.add(*messageAreaLayout, roomIdStr);
+
fprintf(stderr, "Added channel %s\n", room->id->toString().c_str());
- Gtk::ToggleButton *channelButton = Gtk::manage(new Gtk::ToggleButton("Channel name"));
- channelButton->set_active(true);
- channelButton->get_style_context()->add_class("channel-button");
- channelButton->set_hexpand(true);
- channelButton->get_child()->set_halign(Gtk::ALIGN_START);
- channelButton->show();
- leftPanelChannels.attach(*channelButton, 0, 1 + roomCount, 1, 1);
+ Gtk::ToggleButton *roomButton = new Gtk::ToggleButton("Room name");
+ roomButton->set_active(true);
+ roomButton->get_style_context()->add_class("room-button");
+ roomButton->set_hexpand(true);
+ roomButton->set_halign(Gtk::ALIGN_START);
+ roomButton->get_child()->set_halign(Gtk::ALIGN_START);
+ roomButton->show();
+ roomButton->signal_clicked().connect([this, room]
+ {
+ setCurrentRoom(room);
+ });
+ leftPanelChannels.attach(*roomButton, 0, 1 + roomCount, 1, 1);
++roomCount;
- roomDataById[*room->id] = { channelButton };
+ currentRoomData = new RoomData { leftPanelUsersLayout, messageAreaLayout, roomButton };
+ roomDataById[*room->id] = currentRoomData;
+ currentRoom = room;
+
+ leftPanelUsersStack.set_visible_child(roomIdStr);
+ messageAreaStack.set_visible_child(roomIdStr);
+ }
+
+ void ChatWindow::setCurrentRoom(std::shared_ptr<Room> room)
+ {
+ std::string roomIdStr = room->id->toString();
+ leftPanelUsersStack.set_visible_child(roomIdStr);
+ messageAreaStack.set_visible_child(roomIdStr);
+ currentChannelTitle.set_text(room->name);
currentRoom = room;
+ currentRoomData = roomDataById[*room->id];
+
+ // TODO: Instead of scrolling to bottom, remember scroll position (even after restarting application).
+ // We want to show oldest unread message first
+ scrollToBottom();
}
void ChatWindow::addMessage(const RoomAddMessageRequest &request)
@@ -190,42 +262,41 @@ namespace dchat
messageById[request.message.id] = message;
if(!request.loadedFromCache && *request.room->id == *currentRoom->id)
{
- auto adj = messageArea.get_vadjustment();
- adj->set_value(adj->get_upper());
- messageAreaLayout.queue_draw();
- while(gtk_events_pending())
- gtk_main_iteration_do(FALSE);
+ currentRoomData->messageAreaLayout->queue_draw();
+ scrollToBottom();
}
return;
}
}
- ChatMessage *message = Gtk::manage(new ChatMessage(request.message.creator->nickname, request.message.text, request.message.timestampSeconds));
+ std::string userNickname = request.message.creator->nickname;
+ if(userNickname.empty())
+ userNickname = "Anonymous";
+ ChatMessage *message = Gtk::manage(new ChatMessage(userNickname, request.message.text, request.message.timestampSeconds));
message->set_valign(Gtk::Align::ALIGN_START);
message->set_hexpand(true);
message->show_all();
messageById[request.message.id] = message;
- messageAreaLayout.attach(*message, 0, roomMessages.size(), 1, 1);
+ RoomData *roomData = roomDataById[*request.room->id];
+ roomData->messageAreaLayout->attach(*message, 0, roomMessages.size(), 1, 1);
// TODO: When we get a message in the current room we scroll to the bottom, but this should only be done if we are not manually scrolling to view old messages
if(!request.loadedFromCache && *request.room->id == *currentRoom->id)
{
- auto adj = messageArea.get_vadjustment();
- adj->set_value(adj->get_upper());
- messageAreaLayout.queue_draw();
- while(gtk_events_pending())
- gtk_main_iteration_do(FALSE);
+ roomData->messageAreaLayout->queue_draw();
+ scrollToBottom();
}
}
void ChatWindow::addUser(std::shared_ptr<Room> room, std::shared_ptr<User> user)
{
- Gtk::Label *username = Gtk::manage(new Gtk::Label("NoName"));
+ Gtk::Label *username = Gtk::manage(new Gtk::Label("Anonymous"));
username->set_halign(Gtk::ALIGN_START);
username->show();
username->get_style_context()->add_class("username-list-username");
user->userdata = username;
- leftPanelUsers.attach(*username, 0, room->userByPublicKey.size(), 1, 1);
+ RoomData *roomData = roomDataById[*room->id];
+ roomData->leftPanelUsersLayout->attach(*username, 0, room->userByPublicKey.size(), 1, 1);
fprintf(stderr, "Added user %s\n", user->publicKey.toString().c_str());
}
@@ -236,8 +307,19 @@ namespace dchat
fprintf(stderr, "Set nickname for user %s to %s\n", request.user->publicKey.toString().c_str(), request.newNickname.c_str());
}
+ void ChatWindow::changeRoomName(const RoomChangeNameRequest &request)
+ {
+ Gtk::Button *button = roomDataById[*request.room->id]->button;
+ static_cast<Gtk::Label*>(button->get_child())->set_text(request.newName);
+ if(*request.room->id == *currentRoom->id)
+ currentChannelTitle.set_text(request.newName);
+ fprintf(stderr, "Changed room %s name to %s\n", request.room->id->toString().c_str(), request.newName.c_str());
+ }
+
void ChatWindow::scrollToBottom()
{
+ while(gtk_events_pending())
+ gtk_main_iteration_do(FALSE);
auto adj = messageArea.get_vadjustment();
adj->set_value(adj->get_upper());
}
diff --git a/src/ImageButton.cpp b/src/ImageButton.cpp
new file mode 100644
index 0000000..17939f7
--- /dev/null
+++ b/src/ImageButton.cpp
@@ -0,0 +1,14 @@
+#include "../include/ImageButton.hpp"
+#include <gtkmm/image.h>
+
+namespace dchat
+{
+ ImageButton::ImageButton(const char *filepath, const char *text) :
+ Gtk::Button(text)
+ {
+ Gtk::Image *image = Gtk::manage(new Gtk::Image(filepath));
+ set_always_show_image(true);
+ set_image(*image);
+ get_style_context()->add_class("image-button");
+ }
+} \ No newline at end of file
diff --git a/src/InputDialog.cpp b/src/InputDialog.cpp
new file mode 100644
index 0000000..520bfa2
--- /dev/null
+++ b/src/InputDialog.cpp
@@ -0,0 +1,32 @@
+#include "../include/InputDialog.hpp"
+#include <gtkmm/label.h>
+
+namespace dchat
+{
+ InputDialog::InputDialog(const char *title, const char *text, const char *acceptText, const char *cancelText)
+ {
+ set_title(title);
+
+ Gtk::Box *box = get_content_area();
+ Gtk::Label *label = Gtk::manage(new Gtk::Label(text));
+ label->set_valign(Gtk::ALIGN_END);
+ label->set_halign(Gtk::ALIGN_CENTER);
+ box->pack_start(*label, true, true);
+
+ entry.set_valign(Gtk::ALIGN_CENTER);
+ entry.set_halign(Gtk::ALIGN_CENTER);
+ entry.set_hexpand(true);
+ box->pack_end(entry, true, true);
+
+ add_button(acceptText, Gtk::RESPONSE_ACCEPT);
+ add_button(cancelText, Gtk::RESPONSE_CANCEL);
+ show_all();
+
+ set_size_request(300, 150);
+ }
+
+ Glib::ustring InputDialog::getInput() const
+ {
+ return entry.get_text();
+ }
+} \ No newline at end of file
diff --git a/src/Window.cpp b/src/Window.cpp
index b9e1490..e8129f0 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -5,7 +5,6 @@
#include <sibs/SafeDeserializer.hpp>
#include <math.h>
#include <chrono>
-#include <gtkmm.h>
namespace dchat
{
@@ -48,13 +47,7 @@ namespace dchat
drawBackgroundConnection.disconnect();
chatWindow.show_all();
stack.set_visible_child(chatWindow);
-
- Glib::signal_timeout().connect([this]
- {
- printf("scroll to bottom!\n");
- chatWindow.scrollToBottom();
- return false;
- }, 100);
+ chatWindow.scrollToBottom();
}
catch(std::exception &e)
{
@@ -130,6 +123,10 @@ namespace dchat
{
chatWindow.setUserNickname(request);
};
+ roomCallbackFuncs.changeRoomNameCallbackFunc = [this](const RoomChangeNameRequest &request)
+ {
+ chatWindow.changeRoomName(request);
+ };
windowNotification->show("Connecting to 83.252.53.188:27130");
Rooms::connect("83.252.53.188", 27130, roomCallbackFuncs);
diff --git a/src/main.cpp b/src/main.cpp
index 6c7dec6..71e54d3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,7 @@
#include "../include/Window.hpp"
#include <gtkmm/application.h>
#include <gtkmm/cssprovider.h>
+#include <gtkmm/settings.h>
int main (int argc, char *argv[])
{