/** * @author Christian Burger (christian@krikkel.de) */ #include #include #include #include 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::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::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); } }