moved all sources into src directory
This commit is contained in:
157
src/Window.cpp
Normal file
157
src/Window.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
//
|
||||
// Window.cpp
|
||||
// gui
|
||||
//
|
||||
// Created by Bob Polis at 2020-10-14
|
||||
// Copyright (c) 2020 SwiftCoder. All rights reserved.
|
||||
//
|
||||
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "Window.hpp"
|
||||
#include "Image.hpp"
|
||||
|
||||
using namespace sc::gui;
|
||||
|
||||
std::vector<Window> Window::_windows;
|
||||
std::map<SDL_WindowEventID, std::vector<WindowEventHandler>> Window::_global_event_handlers;
|
||||
|
||||
Window& Window::new_window(const std::string& title) {
|
||||
_windows.emplace_back(title);
|
||||
return _windows.back();
|
||||
}
|
||||
|
||||
Window* Window::from_sdl(Uint32 window_id) {
|
||||
SDL_Window* w {SDL_GetWindowFromID(window_id)};
|
||||
if (w) {
|
||||
auto it = std::find_if(_windows.begin(), _windows.end(), [w](Window& win) {
|
||||
return win.window() == w;
|
||||
});
|
||||
if (it != _windows.end()) {
|
||||
return &*it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Window::handle_window_event(const SDL_Event& event) {
|
||||
bool quit {false};
|
||||
Window* w {from_sdl(event.window.windowID)};
|
||||
if (w) {
|
||||
quit = w->handle_event(event, quit);
|
||||
}
|
||||
return quit | handle_global_event(event);
|
||||
}
|
||||
|
||||
bool Window::handle_global_event(const SDL_Event& event) {
|
||||
bool quit {false};
|
||||
auto iter = _global_event_handlers.find(static_cast<SDL_WindowEventID>(event.window.event));
|
||||
if (iter != _global_event_handlers.end()) {
|
||||
for (WindowEventHandler handler : iter->second) {
|
||||
quit = handler(event, quit);
|
||||
}
|
||||
}
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE: {
|
||||
// remove window from window list
|
||||
SDL_Window* w {SDL_GetWindowFromID(event.window.windowID)};
|
||||
auto it = std::remove_if(_windows.begin(), _windows.end(), [w](Window& win) {
|
||||
return win.window() == w;
|
||||
});
|
||||
_windows.erase(it, _windows.end());
|
||||
if (_windows.size() == 0) {
|
||||
quit = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return quit;
|
||||
}
|
||||
|
||||
void Window::add_global_event_handler(WindowEventHandler handler, SDL_WindowEventID type) {
|
||||
auto it = _global_event_handlers.find(type);
|
||||
if (it != _global_event_handlers.end()) {
|
||||
it->second.push_back(handler);
|
||||
} else {
|
||||
std::vector<WindowEventHandler> handlers {handler};
|
||||
_global_event_handlers.emplace(type, handlers);
|
||||
}
|
||||
}
|
||||
|
||||
Window::Window(const std::string& title) : _title {title} {
|
||||
SDL_Window* win = SDL_CreateWindow(title.c_str(),
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
1600, 900,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
_w.reset(win);
|
||||
_r.reset(SDL_CreateRenderer(win, -1, 0));
|
||||
}
|
||||
|
||||
void Window::set_size(int w, int h) {
|
||||
SDL_SetWindowSize(_w.get(), w, h);
|
||||
}
|
||||
|
||||
void Window::update() const {
|
||||
SDL_RenderClear(_r.get());
|
||||
SDL_RenderCopy(_r.get(), _t.get(), nullptr, nullptr);
|
||||
SDL_RenderPresent(_r.get());
|
||||
}
|
||||
|
||||
void Window::show_image(const Image& image) {
|
||||
// create texture from surface
|
||||
_t.reset(SDL_CreateTextureFromSurface(_r.get(), image.surface()));
|
||||
|
||||
// get screen size, to scale down if image is too big
|
||||
int w {image.width()};
|
||||
int h {image.height()};
|
||||
SDL_DisplayMode dm;
|
||||
SDL_GetCurrentDisplayMode(0, &dm);
|
||||
if (dm.w < w || dm.h < h) {
|
||||
double screen_ratio {static_cast<double>(dm.w) / dm.h};
|
||||
double image_ratio {static_cast<double>(w) / h};
|
||||
const int safety {100}; // room for window and desktop adornments
|
||||
if (screen_ratio > image_ratio) { // screen relatively less high than image
|
||||
h = dm.h - safety;
|
||||
w = static_cast<int>(round(image_ratio * h));
|
||||
} else { // screen relatively less wide than image
|
||||
w = dm.w - safety;
|
||||
h = static_cast<int>(round(w / image_ratio));
|
||||
}
|
||||
}
|
||||
set_size(w, h);
|
||||
}
|
||||
|
||||
void Window::add_event_handler(WindowEventHandler handler, SDL_WindowEventID type) {
|
||||
auto it = _event_handlers.find(type);
|
||||
if (it != _event_handlers.end()) {
|
||||
it->second.push_back(handler);
|
||||
} else {
|
||||
std::vector<WindowEventHandler> handlers {handler};
|
||||
_event_handlers.emplace(type, handlers);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::handle_event(const SDL_Event& event, bool quit) {
|
||||
auto it = _event_handlers.find(static_cast<SDL_WindowEventID>(event.window.event));
|
||||
if (it != _event_handlers.end()) {
|
||||
for (WindowEventHandler handler : it->second) {
|
||||
quit = handler(event, quit);
|
||||
}
|
||||
}
|
||||
return quit;
|
||||
}
|
||||
|
||||
int Window::width() const {
|
||||
int w, h;
|
||||
SDL_GetWindowSize(_w.get(), &w, &h);
|
||||
return w;
|
||||
}
|
||||
|
||||
int Window::height() const {
|
||||
int w, h;
|
||||
SDL_GetWindowSize(_w.get(), &w, &h);
|
||||
return h;
|
||||
}
|
Reference in New Issue
Block a user