2022-05-08 20:57:48 +02:00
|
|
|
/**
|
|
|
|
* @author Christian Burger (christian@krikkel.de)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <kNCurses/TilingWindowManager.hpp>
|
|
|
|
#include <kNCurses/Window.hpp>
|
2022-05-18 21:15:13 +02:00
|
|
|
#include "Debug.hpp"
|
|
|
|
|
2022-05-08 20:57:48 +02:00
|
|
|
#include <ncursesw/ncurses.h>
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
namespace krikkel::NCurses
|
|
|
|
{
|
|
|
|
using std::list;
|
2022-05-18 21:15:13 +02:00
|
|
|
using std::pair;
|
2022-05-08 20:57:48 +02:00
|
|
|
using std::recursive_mutex;
|
|
|
|
using std::scoped_lock;
|
|
|
|
|
|
|
|
TilingWindowManager::TilingWindowManager(NCursesWindow *rootWindow, recursive_mutex *ncursesMutex)
|
2022-05-08 22:52:23 +02:00
|
|
|
: Window(*rootWindow), ncursesMutex(ncursesMutex)
|
2022-05-08 20:57:48 +02:00
|
|
|
{}
|
|
|
|
|
2022-05-18 21:15:13 +02:00
|
|
|
void TilingWindowManager::addWindow(Window *window, windowDimension size)
|
2022-05-08 20:57:48 +02:00
|
|
|
{
|
2022-05-18 21:15:13 +02:00
|
|
|
WindowStackElement stackElement(window, size);
|
|
|
|
stack.push_back(stackElement);
|
|
|
|
visibleStack.push_back(stackElement);
|
2022-05-08 20:57:48 +02:00
|
|
|
}
|
|
|
|
|
2022-05-19 14:45:50 +02:00
|
|
|
std::recursive_mutex *TilingWindowManager::getNCursesMutex()
|
|
|
|
{
|
|
|
|
return ncursesMutex;
|
|
|
|
}
|
|
|
|
|
2022-05-08 20:57:48 +02:00
|
|
|
void TilingWindowManager::hideWindow(Window *window)
|
|
|
|
{
|
2022-05-18 21:15:13 +02:00
|
|
|
if(window->hidden)
|
|
|
|
return;
|
|
|
|
|
|
|
|
visibleStack.remove_if(
|
|
|
|
[window](WindowStackElement element)
|
|
|
|
{
|
|
|
|
return element.first == window;
|
|
|
|
});
|
2022-05-08 20:57:48 +02:00
|
|
|
window->hidden = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TilingWindowManager::showWindow(Window *window)
|
|
|
|
{
|
|
|
|
if(!window->hidden)
|
|
|
|
return;
|
|
|
|
|
2022-05-18 21:15:13 +02:00
|
|
|
list<WindowStackElement>::iterator currentVisibleWindowElement = visibleStack.begin();
|
|
|
|
for(WindowStackElement currentWindowElement : stack)
|
2022-05-08 20:57:48 +02:00
|
|
|
{
|
2022-05-18 21:15:13 +02:00
|
|
|
if(currentWindowElement.first == window)
|
2022-05-08 20:57:48 +02:00
|
|
|
{
|
2022-05-18 21:15:13 +02:00
|
|
|
visibleStack.insert(currentVisibleWindowElement, currentWindowElement);
|
2022-05-08 20:57:48 +02:00
|
|
|
window->hidden = false;
|
|
|
|
break;
|
|
|
|
}
|
2022-05-18 21:15:13 +02:00
|
|
|
if(currentWindowElement != (*currentVisibleWindowElement))
|
2022-05-08 20:57:48 +02:00
|
|
|
continue;
|
2022-05-18 21:15:13 +02:00
|
|
|
++currentVisibleWindowElement;
|
2022-05-08 20:57:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-20 20:41:45 +02:00
|
|
|
void TilingWindowManager::invertWindowsVisibility()
|
|
|
|
{
|
|
|
|
list<WindowStackElement> originallyVisibleStack(visibleStack);
|
|
|
|
list<WindowStackElement>::iterator originallyVisibleStackIterator = originallyVisibleStack.begin();
|
|
|
|
visibleStack.clear();
|
|
|
|
|
|
|
|
for(WindowStackElement currentWindowElement : stack)
|
|
|
|
if(originallyVisibleStackIterator != originallyVisibleStack.end()
|
|
|
|
&& currentWindowElement == *originallyVisibleStackIterator)
|
|
|
|
{
|
|
|
|
currentWindowElement.first->hidden = true;
|
|
|
|
++originallyVisibleStackIterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentWindowElement.first->hidden = false;
|
|
|
|
visibleStack.push_back(currentWindowElement);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-08 22:52:23 +02:00
|
|
|
int TilingWindowManager::resize(int rows, int cols)
|
|
|
|
{
|
|
|
|
int result = Window::resize(rows, cols);
|
|
|
|
updateLayout();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TilingWindowManager::refresh()
|
2022-05-08 20:57:48 +02:00
|
|
|
{
|
|
|
|
scoped_lock lock(*ncursesMutex);
|
|
|
|
|
2022-05-08 22:52:23 +02:00
|
|
|
int result = Window::refresh();
|
|
|
|
|
2022-05-18 21:15:13 +02:00
|
|
|
for(WindowStackElement stackElement : visibleStack)
|
2022-05-08 22:52:23 +02:00
|
|
|
// @todo there are return values; compound them?
|
2022-05-18 21:15:13 +02:00
|
|
|
stackElement.first->refresh();
|
2022-05-08 22:52:23 +02:00
|
|
|
|
|
|
|
return result;
|
2022-05-08 20:57:48 +02:00
|
|
|
}
|
|
|
|
|
2022-05-18 21:15:13 +02:00
|
|
|
void TilingWindowManager::updateLayout()
|
2022-05-08 20:57:48 +02:00
|
|
|
{
|
2022-05-18 21:15:13 +02:00
|
|
|
scoped_lock lock(*ncursesMutex);
|
|
|
|
|
|
|
|
size_t stackSize = visibleStack.size();
|
|
|
|
if(stackSize == 0)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int unitSize = getRelativeUnitSizeForVisibleWindows(getAvailableSpace()) - 1;
|
|
|
|
windowPosition position = 0;
|
|
|
|
auto lastButNotLeast = prev(visibleStack.end());
|
|
|
|
for(auto stackElementIterator = visibleStack.begin()
|
|
|
|
; stackElementIterator != lastButNotLeast
|
|
|
|
; ++stackElementIterator)
|
|
|
|
{
|
|
|
|
WindowStackElement stackElement = *stackElementIterator;
|
|
|
|
Window *window = stackElement.first;
|
|
|
|
if(!window->isHidden())
|
|
|
|
{
|
|
|
|
int windowShift;
|
|
|
|
int windowSize = stackElement.second;
|
|
|
|
if(windowSize < 0)
|
|
|
|
windowShift = unitSize * (-windowSize);
|
|
|
|
else
|
|
|
|
windowShift = windowSize;
|
|
|
|
|
|
|
|
resizeAndMoveWindow(window, windowShift, position);
|
|
|
|
position += windowShift;
|
|
|
|
__debug_log("drawing line at " + std::to_string(position));
|
|
|
|
moveCursor(position++);
|
|
|
|
windowBorder();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
resizeAndMoveWindow((*lastButNotLeast).first, getAvailableSpace() - position, position);
|
2022-05-08 20:57:48 +02:00
|
|
|
}
|
|
|
|
|
2022-05-18 21:15:13 +02:00
|
|
|
|
|
|
|
TilingWindowManager::windowDimension TilingWindowManager::getRelativeUnitSizeForVisibleWindows(windowDimension spaceAvailable)
|
2022-05-08 20:57:48 +02:00
|
|
|
{
|
2022-05-18 21:15:13 +02:00
|
|
|
uint16_t numberOfRelativeUnits = 0;
|
|
|
|
windowDimension absoluteSum = 0;
|
|
|
|
list<WindowStackElement>::iterator windowIterator = stack.begin();
|
|
|
|
|
|
|
|
for(WindowStackElement stackElement : visibleStack)
|
|
|
|
{
|
|
|
|
windowDimension size = stackElement.second;
|
|
|
|
if(size < 0)
|
|
|
|
numberOfRelativeUnits -= size;
|
|
|
|
else
|
|
|
|
absoluteSum += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowDimension relativeUnitSize = (spaceAvailable - absoluteSum) / numberOfRelativeUnits;
|
|
|
|
windowDimension remainder = (spaceAvailable - absoluteSum - relativeUnitSize * numberOfRelativeUnits);
|
|
|
|
if(remainder > 0 && remainder * 2 < numberOfRelativeUnits)
|
|
|
|
++relativeUnitSize;
|
|
|
|
|
|
|
|
return relativeUnitSize;
|
2022-05-08 20:57:48 +02:00
|
|
|
}
|
|
|
|
}
|