kNCurses/VerticalTilingWindowManager.cpp

105 lines
2.9 KiB
C++

/**
* @author Christian Burger (christian@krikkel.de)
*/
#include <kNCurses/VerticalTilingWindowManager.hpp>
#include <kNCurses/Window.hpp>
#include <ncursesw/ncurses.h>
#include <algorithm>
namespace krikkel::NCurses
{
using std::list;
using std::recursive_mutex;
using std::scoped_lock;
using std::find;
VerticalTilingWindowManager::VerticalTilingWindowManager(NCursesWindow *rootWindow, recursive_mutex *ncursesMutex)
: rootWindow(new Window(*rootWindow)), ncursesMutex(ncursesMutex)
{}
void VerticalTilingWindowManager::addWindow(Window *window)
{
stack.push_back(window);
visibleStack.push_back(window);
}
void VerticalTilingWindowManager::hideWindow(Window *window)
{
visibleStack.remove(window);
window->hidden = true;
}
void VerticalTilingWindowManager::showWindow(Window *window)
{
if(!window->hidden)
return;
list<Window *>::iterator currentVisibleWindow = visibleStack.begin();
for(Window *currentWindow : stack)
{
if(currentWindow == window)
{
visibleStack.insert(currentVisibleWindow, window);
window->hidden = false;
break;
}
if(currentWindow != (*currentVisibleWindow))
continue;
++currentVisibleWindow;
}
}
void VerticalTilingWindowManager::refresh()
{
scoped_lock lock(*ncursesMutex);
rootWindow->refresh();
for(Window *window : visibleStack)
window->refresh();
}
SingleUserInput VerticalTilingWindowManager::readSingleUserInput()
{
return rootWindow->readSingleUserInput();
}
void VerticalTilingWindowManager::updateLayout()
{
size_t stackSize = visibleStack.size();
if(stackSize == 0)
{
rootWindow->clear();
return;
}
scoped_lock lock(*ncursesMutex);
int availableWidth = rootWindow->width();
int availableHeight = rootWindow->height();
int windowHeight = availableHeight / stackSize - 1;
if((windowHeight + 1) * stackSize < availableHeight)
++windowHeight;
uint16_t y = 0;
list<Window *>::iterator it = visibleStack.begin();
for(size_t index = 0
; index < visibleStack.size() - 1
; ++index)
{
resizeWindowInStack(*it++, y, windowHeight, availableWidth);
y += windowHeight;
{
rootWindow->move(y++, 0);
rootWindow->hline(availableWidth);
}
}
resizeWindowInStack(*it, y, availableHeight - y, availableWidth);
}
void VerticalTilingWindowManager::resizeWindowInStack(Window *window, uint16_t y, uint16_t height, uint16_t width)
{
window->resize(height, width);
window->mvwin(y, 0);
}
}