#include "../include/Window.hpp" #include #include #include #include #include namespace dchat { const int nodesPerColumn = 10; const int nodesPerRow = 10; Window::Window() : chatWindow(this) { set_border_width(0); windowNotification = Gtk::manage(new WindowNotification()); overlay.add_overlay(*windowNotification); overlay.set_overlay_pass_through(*windowNotification); overlay.add(stack); add(overlay); stack.set_homogeneous(false); stack.set_transition_type(Gtk::StackTransitionType::STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT); stack.set_transition_duration(250); stack.add(loginWindow, "login"); stack.add(chatWindow, "chat"); overlay.show(); windowNotification->show_all(); stack.set_visible_child("login"); stack.show(); //chatWindow.show_all(); //loginWindow.show(); loginWindow.setLoginHandler([this](const Glib::ustring &username, const Glib::ustring &password) { if(!rooms || !rooms->database) { windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); return; } try { fprintf(stderr, "Trying to login with username %s\n", username.raw().c_str()); rooms->loginUser(username.raw(), password.raw()); //windowNotification->show(Glib::ustring("Successfully logged in as ") + username); drawBackgroundConnection.disconnect(); chatWindow.show(); stack.set_visible_child(chatWindow); chatWindow.scrollToBottom(); } catch(std::exception &e) { Glib::ustring errMsg = "Failed to login, reason: "; errMsg += e.what(); windowNotification->show(errMsg); } }); loginWindow.setRegisterHandler([this](const Glib::ustring &username, const Glib::ustring &password) { if(!rooms || !rooms->database) { windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); return; } try { fprintf(stderr, "Trying to register username %s\n", username.raw().c_str()); rooms->registerUser(username.raw(), password.raw()); windowNotification->show(Glib::ustring("Successfully registered user ") + username); drawBackgroundConnection.disconnect(); chatWindow.show(); stack.set_visible_child(chatWindow); } catch(std::exception &e) { Glib::ustring errMsg = "Failed to register username "; errMsg += username.raw(); errMsg += ", reason: "; errMsg += e.what(); windowNotification->show(errMsg); } }); loginWindow.setRegisterPasswordMismatch([this] { windowNotification->show("Passwords do not match"); }); RoomCallbackFuncs roomCallbackFuncs; roomCallbackFuncs.connectCallbackFunc = [this](std::shared_ptr rooms, const char *errMsg) { this->rooms = rooms; if(rooms) { loginWindow.show(); stack.set_visible_child(loginWindow); windowNotification->show("Connected to 83.252.53.188:27130"); loginWindow.loginUsernameInput.grab_focus(); } else { std::string errMsgToShow = "Failed to connect to boostrap node, reason: "; errMsgToShow += errMsg; windowNotification->show(errMsgToShow); } }; roomCallbackFuncs.createRoomCallbackFunc = [this](std::shared_ptr room) { chatWindow.addRoom(room); }; roomCallbackFuncs.addUserCallbackFunc = [this](const RoomAddUserRequest &request) { chatWindow.addUser(request); }; roomCallbackFuncs.addMessageCallbackFunc = [this](const RoomAddMessageRequest &request) { chatWindow.addMessage(request); }; roomCallbackFuncs.userChangeNicknameCallbackFunc = [this](const UserChangeNicknameRequest &request) { chatWindow.setUserNickname(request); }; roomCallbackFuncs.userChangeAvatarCallbackFunc = [this](const UserChangeAvatarRequest &request) { chatWindow.setUserAvatar(request); }; roomCallbackFuncs.changeRoomNameCallbackFunc = [this](const RoomChangeNameRequest &request) { chatWindow.changeRoomName(request); }; roomCallbackFuncs.receiveInviteUserCallbackFunc = [this](const InviteUserRequest &request) { chatWindow.addInviteRequest(request); }; windowNotification->show("Connecting to 83.252.53.188:27130"); Rooms::connect("83.252.53.188", 27130, roomCallbackFuncs); backgroundRng.seed(std::random_device()()); std::uniform_int_distribution sizeDeviationRand(0, 5); std::uniform_int_distribution posDeviationRand(0, 100); const double spaceBetweenNodesColumn = 1.0 / (double)(nodesPerColumn - 1); const double spaceBetweenNodesRow = 1.0 / (double)(nodesPerRow - 1); for(int y = 0; y < nodesPerRow; ++y) { for(int x = 0; x < nodesPerColumn; ++x) { int sizeDeviation = sizeDeviationRand(backgroundRng); //int xDeviation = posDeviationRand(backgroundRng) - 50; //int yDeviation = posDeviationRand(backgroundRng) - 50; int xDeviation = 0; int yDeviation = 0; Node node; node.radius = 5.0 + sizeDeviation; node.originalPosX = /*spaceBetweenNodesColumn * 0.5 + */x * spaceBetweenNodesColumn + xDeviation * 0.001; node.originalPosY = /*spaceBetweenNodesRow * 0.5 + */y * spaceBetweenNodesRow + yDeviation * 0.001; node.currentPosX = node.originalPosX; node.currentPosY = node.originalPosY; node.targetPosX = node.currentPosX; node.targetPosY = node.currentPosY; backgroundNodes.push_back(node); } } prevTimeMillis = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() - 5000; drawBackgroundConnection = signal_draw().connect(sigc::mem_fun(*this, &Window::drawBackground)); //set_size_request(640, 480); //set_app_paintable(true); } Window::~Window() { } static void drawNode(const Cairo::RefPtr &cairo, double x, double y, double radius) { cairo->arc(x, y, radius, 0.0, 2.0 * M_PI); cairo->fill(); cairo->arc(x, y, radius + (radius * 0.8), 0.0, 2.0 * M_PI); cairo->set_line_width(radius * 0.1); cairo->stroke(); } bool Window::drawBackground(const Cairo::RefPtr &cairo) { int windowWidth, windowHeight; get_size(windowWidth, windowHeight); //cairo->set_source_rgb(0.1843137254901961, 0.19215686274509805, 0.21176470588235294); //cairo->rectangle(0.0, 0.0, windowWidth, windowHeight); //cairo->fill(); cairo->set_source_rgb(0.5, 0.5, 0.5); int currentTimeMillis = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); int deltaTimeMillis = currentTimeMillis - prevTimeMillis; bool updateTarget = false; if(deltaTimeMillis > 3000) { prevTimeMillis = currentTimeMillis; updateTarget = true; } std::uniform_int_distribution posDeviationRand(0, 100); const double moveSpeed = 0.0001; for(Node &node : backgroundNodes) { if(updateTarget) { int xDeviation = posDeviationRand(backgroundRng) - 50; int yDeviation = posDeviationRand(backgroundRng) - 50; node.targetPosX = node.originalPosX + xDeviation * 0.001; node.targetPosY = node.originalPosY + yDeviation * 0.001; } double diffX = node.targetPosX - node.currentPosX; double diffY = node.targetPosY - node.currentPosY; double diffDist = std::max(0.01, std::sqrt(diffX*diffX + diffY*diffY)); diffX /= diffDist; diffY /= diffDist; node.currentPosX += (diffX * moveSpeed); node.currentPosY += (diffY * moveSpeed); drawNode(cairo, node.currentPosX * windowWidth, node.currentPosY * windowHeight, node.radius); } cairo->set_line_width(2.0); for(int y = 0; y < nodesPerRow; ++y) { for(int x = 0; x < nodesPerColumn; ++x) { Node *currentNode = &backgroundNodes[x + y * nodesPerRow]; if(x > 0) { Node *prevNode = &backgroundNodes[x - 1 + y * nodesPerRow]; int currentNodeRadius = currentNode->radius + (currentNode->radius * 0.8); int prevNodeRadius = prevNode->radius + (prevNode->radius * 0.8); cairo->move_to(prevNode->currentPosX * windowWidth + prevNodeRadius, prevNode->currentPosY * windowHeight); cairo->line_to(currentNode->currentPosX * windowWidth - currentNodeRadius, currentNode->currentPosY * windowHeight); } if(y > 0) { Node *prevNode = &backgroundNodes[x + (y - 1) * nodesPerRow]; int currentNodeRadius = currentNode->radius + (currentNode->radius * 0.8); int prevNodeRadius = prevNode->radius + (prevNode->radius * 0.8); cairo->move_to(prevNode->currentPosX * windowWidth, prevNode->currentPosY * windowHeight + prevNodeRadius); cairo->line_to(currentNode->currentPosX * windowWidth, currentNode->currentPosY * windowHeight - currentNodeRadius); } } } cairo->stroke(); /* int windowMax = std::max(windowWidth/2, windowHeight/2); auto backgroundGradient = Cairo::RadialGradient::create(windowWidth/2, windowHeight/2, 0.0, windowWidth/2, windowHeight/2, windowMax*1.35); backgroundGradient->add_color_stop_rgba(0.0, 0.0, 0.0, 0.0, 0.0); backgroundGradient->add_color_stop_rgba(1.0, 0.1843137254901961, 0.19215686274509805, 0.21176470588235294, 1.0); cairo->set_source(backgroundGradient); cairo->mask(backgroundGradient); //cairo->paint(); */ Gtk::Allocation alloc = overlay.get_allocation(); // For some reason gtk sometimes needs time to allocate the overlay, and it freezes the application if you do not wait for it if(!alloc.has_zero_area()) overlay.draw(cairo); queue_draw(); return true; } }