|
|
|
|
#include "guecs/sfml/components.hpp"
|
|
|
|
|
#include "guecs/ui.hpp"
|
|
|
|
|
#include <fmt/xchar.h>
|
|
|
|
|
#include <deque>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
|
#include "dbc.hpp"
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include "constants.hpp"
|
|
|
|
|
#include "control_ui.hpp"
|
|
|
|
|
#include <optional>
|
|
|
|
|
|
|
|
|
|
ControlUI::ControlUI(sf::RenderWindow& presenter, sf::RenderWindow& controller, unsigned short port) :
|
|
|
|
|
$presenter{presenter},
|
|
|
|
|
$controller{controller},
|
|
|
|
|
$window_size{$presenter.getSize()},
|
|
|
|
|
$ctrl_sock{port}
|
|
|
|
|
{
|
|
|
|
|
$gui.position(0, 0, CONTROL_WIDTH, CONTROL_HEIGHT);
|
|
|
|
|
$gui.layout(
|
|
|
|
|
"[status|*%(200,400)current|_]"
|
|
|
|
|
"[title0|_|_]"
|
|
|
|
|
"[title1|_|_]"
|
|
|
|
|
"[title2|_|_]"
|
|
|
|
|
"[title3|*%(200,400)preview|_]"
|
|
|
|
|
"[title4|_|_]"
|
|
|
|
|
"[title5|_|_]"
|
|
|
|
|
"[help|_|_]"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlUI::init() {
|
|
|
|
|
$ctrl_sock.listen();
|
|
|
|
|
|
|
|
|
|
auto status_id = $gui.entity("status");
|
|
|
|
|
$gui.set<guecs::Text>(status_id, {L""});
|
|
|
|
|
|
|
|
|
|
auto docs_id = $gui.entity("help");
|
|
|
|
|
$gui.set<guecs::Text>(docs_id, {
|
|
|
|
|
.content=L"F: fullscreen\nA: win left\nD: win right\nQ: quit",
|
|
|
|
|
.size=20});
|
|
|
|
|
|
|
|
|
|
auto current = $gui.entity("current");
|
|
|
|
|
$gui.set<guecs::Rectangle>(current, {});
|
|
|
|
|
$gui.set<guecs::Text>(current, {.content=L"CURRENT", .size=40});
|
|
|
|
|
|
|
|
|
|
auto preview = $gui.entity("preview");
|
|
|
|
|
$gui.set<guecs::Rectangle>(preview, {.color=guecs::THEME.DARK_DARK});
|
|
|
|
|
$gui.set<guecs::Text>(preview, {
|
|
|
|
|
.content=L"PREVIEW",
|
|
|
|
|
.size=40,
|
|
|
|
|
.color={180, 180, 180, 255}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 6; i++) {
|
|
|
|
|
auto id = $gui.entity("title", i);
|
|
|
|
|
$gui.set<guecs::Rectangle>(id, {.color=guecs::THEME.TRANSPARENT});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$gui.init();
|
|
|
|
|
|
|
|
|
|
// warning! must come after init so the thing is there
|
|
|
|
|
$status = $gui.get_if<guecs::Text>(status_id);
|
|
|
|
|
dbc::check($status != nullptr, "failed to setup the status text");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlUI::render_slide(const std::string& name, Slide& slide) {
|
|
|
|
|
$gui.show_text(name, slide.preview);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlUI::render(sf::RenderWindow& window, SlideDeck& deck) {
|
|
|
|
|
dbc::check($status != nullptr, "called render before init?");
|
|
|
|
|
|
|
|
|
|
auto pos = $presenter.getPosition();
|
|
|
|
|
auto size = $presenter.getSize();
|
|
|
|
|
|
|
|
|
|
$status->update(fmt::format(L"Slide: {}\nOf: {}",
|
|
|
|
|
deck.current + 1, deck.slides.size()));
|
|
|
|
|
|
|
|
|
|
window.clear();
|
|
|
|
|
$gui.render(window);
|
|
|
|
|
|
|
|
|
|
render_slide("current", deck.current_slide());
|
|
|
|
|
|
|
|
|
|
size_t preview = std::min(deck.slides.size() - 1, deck.current + 1);
|
|
|
|
|
render_slide("preview", deck.slide_at(preview));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ControlUI::full_screen(bool do_it) {
|
|
|
|
|
if(do_it) {
|
|
|
|
|
$presenter.setSize($window_size);
|
|
|
|
|
$controller.requestFocus();
|
|
|
|
|
} else {
|
|
|
|
|
$presenter.setSize({$window_size.x/2, $window_size.y/2});
|
|
|
|
|
$controller.requestFocus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$full_screen = do_it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlUI::process_commands(std::shared_ptr<SlidesUI> slides) {
|
|
|
|
|
using enum CtrlCommand;
|
|
|
|
|
|
|
|
|
|
switch($ctrl_sock.receive()) {
|
|
|
|
|
case FOCUS:
|
|
|
|
|
sf::Mouse::setPosition({WINDOW_WIDTH - 100, WINDOW_HEIGHT - 100}, $presenter);
|
|
|
|
|
break;
|
|
|
|
|
case FULL_SCREEN:
|
|
|
|
|
full_screen(!$full_screen);
|
|
|
|
|
break;
|
|
|
|
|
case MOVE_LEFT:
|
|
|
|
|
move(-1);
|
|
|
|
|
break;
|
|
|
|
|
case MOVE_RIGHT:
|
|
|
|
|
move(1);
|
|
|
|
|
break;
|
|
|
|
|
case NEXT_SLIDE:
|
|
|
|
|
slides->next_slide();
|
|
|
|
|
break;
|
|
|
|
|
case PREV_SLIDE:
|
|
|
|
|
slides->prev_slide();
|
|
|
|
|
break;
|
|
|
|
|
case QUIT:
|
|
|
|
|
$controller.close();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlUI::move(int dir) {
|
|
|
|
|
auto pos = $presenter.getPosition();
|
|
|
|
|
pos.x += dir * $window_size.x;
|
|
|
|
|
$presenter.setPosition(pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlUI::update(std::shared_ptr<SlidesUI> slides) {
|
|
|
|
|
dbc::check($status != nullptr, "handle_events called before init?!");
|
|
|
|
|
|
|
|
|
|
process_commands(slides);
|
|
|
|
|
|
|
|
|
|
while (const auto event = $controller.pollEvent()) {
|
|
|
|
|
if(event->is<sf::Event::Closed>()) {
|
|
|
|
|
$controller.close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(const auto* key = event->getIf<sf::Event::KeyPressed>()) {
|
|
|
|
|
|
|
|
|
|
using KEY = sf::Keyboard::Scan;
|
|
|
|
|
switch(key->scancode) {
|
|
|
|
|
case KEY::A:
|
|
|
|
|
move(-1);
|
|
|
|
|
break;
|
|
|
|
|
case KEY::D:
|
|
|
|
|
move(1);
|
|
|
|
|
break;
|
|
|
|
|
case KEY::Q:
|
|
|
|
|
$controller.close();
|
|
|
|
|
break;
|
|
|
|
|
case KEY::F:
|
|
|
|
|
full_screen(!$full_screen);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
slides->handle_events($controller, *event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|