- Fixed Window to no longer use derwin() -- subwindows share data with

their parent, in a sometimes buggy and unpredictable ways. always use
  newwin() and ensure redraws happen from the bottom up.

- Optimized redraw to not immediately call doupdate(), but rather wait
  until the end of the runloop and call it once. This may cause buggy
  behavior, but seems fine now...
This commit is contained in:
casey 2016-05-15 12:18:29 -07:00
parent 1a0d297b30
commit 132bc25d43
12 changed files with 89 additions and 36 deletions

View File

@ -50,6 +50,5 @@ IScrollAdapter::EntryPtr CategoryListView::Adapter::GetEntry(size_t index) {
int64 attrs = (index == parent.GetSelectedIndex()) ? COLOR_PAIR(BOX_COLOR_BLACK_ON_GREEN) : -1;
IScrollAdapter::EntryPtr entry(new SingleLineEntry(parent.metadata->at(index)));
entry->SetAttrs(attrs);
return entry;
}

View File

@ -38,6 +38,7 @@ CommandWindow::CommandWindow(
LibraryPtr library,
OutputWindow& output)
: Window(parent) {
this->SetContentColor(BOX_COLOR_WHITE_ON_BLACK);
this->transport = &transport;
this->library = library;
this->buffer = new char[BUFFER_SIZE];

View File

@ -5,5 +5,4 @@
class IInput {
public:
virtual void WriteChar(int64 ch) = 0;
virtual void Focus() = 0;
};

View File

@ -12,8 +12,11 @@ class IWindow : public IDisplayable {
virtual void Show() = 0;
virtual void Hide() = 0;
virtual void SetContentColor(int color) = 0;
virtual void SetFrameColor(int color) = 0;
virtual void Focus() = 0;
virtual void Blur() = 0;
virtual void SetContentColor(int64 color) = 0;
virtual void SetFrameColor(int64 color) = 0;
virtual void SetSize(int width, int height) = 0;
virtual void SetPosition(int x, int y) = 0;

View File

@ -28,10 +28,12 @@ bool sortByFocusOrder(IWindowPtr a, IWindowPtr b) {
static inline IWindow* adjustFocus(IWindow* oldFocus, IWindow* newFocus) {
if (oldFocus) {
oldFocus->SetFrameColor(BOX_COLOR_WHITE_ON_BLACK);
oldFocus->Blur();
}
if (newFocus) {
newFocus->SetFrameColor(BOX_COLOR_RED_ON_BLACK);
newFocus->Focus();
}
return newFocus;
@ -66,6 +68,17 @@ void LayoutBase::Hide() {
Window::Hide();
}
void LayoutBase::Repaint() {
/* repaint bottom up. start with ourselves, then our children,
recursively. */
Window::Repaint();
for (size_t i = 0; i < this->children.size(); i++) {
this->children.at(i)->Repaint();
}
}
bool LayoutBase::AddWindow(IWindowPtr window) {
if (find(this->children, window) >= 0) {
return true;

View File

@ -13,6 +13,7 @@ class LayoutBase : public Window, public ILayout {
/* IWindow */
virtual void Show();
virtual void Hide();
virtual void Repaint();
/* ILayout */
virtual IWindow* FocusNext();

View File

@ -25,6 +25,13 @@ void ListWindow::ScrollToBottom() {
this->Repaint();
}
void ListWindow::Focus() {
GetScrollAdapter().DrawPage(
this->GetContent(),
this->scrollPosition.firstVisibleEntryIndex,
&this->scrollPosition);
}
void ListWindow::ScrollUp(int delta) {
ScrollPos spos = this->GetScrollPosition();
IScrollAdapter& adapter = this->GetScrollAdapter();

View File

@ -15,6 +15,7 @@ class ListWindow : public ScrollableWindow {
virtual void ScrollDown(int delta = 1);
virtual void PageUp();
virtual void PageDown();
virtual void Focus();
virtual size_t GetSelectedIndex();

View File

@ -88,7 +88,6 @@ void changeLayout(WindowState& current, ILayout* newLayout) {
if (current.input) {
curs_set(1);
current.input->Focus();
wtimeout(current.focused->GetContent(), IDLE_TIMEOUT_MS);
}
else {
@ -107,7 +106,6 @@ void focusNextInLayout(WindowState& current) {
if (current.input != NULL) {
curs_set(1);
current.input->Focus();
if (current.focused) {
wtimeout(current.focused->GetContent(), IDLE_TIMEOUT_MS);
@ -188,7 +186,6 @@ int main(int argc, char* argv[])
else {
ch = getch();
}
if (ch == -1) { /* timeout */
state.layout->OnIdle();
}
@ -236,6 +233,8 @@ int main(int argc, char* argv[])
else if (state.input) {
state.input->WriteChar(ch);
}
Window::WriteToScreen();
}
}

View File

@ -32,13 +32,13 @@ TransportWindow::~TransportWindow() {
}
void TransportWindow::Repaint() {
this->Clear();
WINDOW *c = this->GetContent();
//this->Clear();
//WINDOW *c = this->GetContent();
double volume = (this->transport->Volume() * 100.0);
//double volume = (this->transport->Volume() * 100.0);
wprintw(c, "volume %.1f%%\n", volume);
wprintw(c, "filename: ");
//wprintw(c, "volume %.1f%%\n", volume);
//wprintw(c, "filename: ");
Window::Repaint();
}

View File

@ -5,6 +5,14 @@
#include "IWindowGroup.h"
static int NEXT_ID = 0;
static bool drawPending = false;
void Window::WriteToScreen() {
if (drawPending) {
drawPending = false;
doupdate();
}
}
Window::Window(IWindow *parent) {
this->frame = this->content = 0;
@ -87,20 +95,30 @@ int Window::GetY() const {
return this->y;
}
void Window::SetContentColor(int color) {
void Window::SetContentColor(int64 color) {
this->contentColor = color;
if (this->contentColor != -1 && this->content) {
wbkgd(this->frame, COLOR_PAIR(this->frameColor));
if (this->content != this->frame) {
wbkgd(this->content, COLOR_PAIR(this->contentColor));
}
this->Repaint();
}
}
void Window::SetFrameColor(int color) {
void Window::SetFrameColor(int64 color) {
this->frameColor = color;
if (this->drawFrame && this->frameColor != -1 && this->frame) {
wbkgd(this->frame, COLOR_PAIR(this->frameColor));
if (this->content != this->frame) {
wbkgd(this->content, COLOR_PAIR(this->contentColor));
}
this->Repaint();
}
}
@ -124,18 +142,18 @@ void Window::SetFocusOrder(int order) {
void Window::Show() {
this->Hide();
/* if we have a parent, place the new window relative to the parent. */
this->frame = (this->parent == NULL)
? newwin(
this->height,
this->width,
this->y,
this->x)
: derwin(
this->parent->GetFrame(),
: newwin(
this->height,
this->width,
this->y,
this->x);
this->parent->GetY() + this->y,
this->parent->GetX() + this->x);
/* if we were asked not to draw a frame, we'll set the frame equal to
the content view, and use the content views colors*/
@ -146,8 +164,6 @@ void Window::Show() {
if (this->contentColor != -1) {
wbkgd(this->frame, COLOR_PAIR(this->contentColor));
}
wnoutrefresh(this->content);
}
/* otherwise we'll draw a box around the frame, and create a content
@ -156,12 +172,11 @@ void Window::Show() {
else {
box(this->frame, 0, 0);
this->content = derwin(
this->frame,
this->content = newwin(
this->height - 2,
this->width - 2,
1,
1);
this->GetY() + 1,
this->GetX() + 1);
if (this->frameColor != -1) {
wbkgd(this->frame, COLOR_PAIR(this->frameColor));
@ -170,12 +185,9 @@ void Window::Show() {
if (this->contentColor != -1) {
wbkgd(this->content, COLOR_PAIR(this->contentColor));
}
wnoutrefresh(this->frame);
touchwin(this->content);
wnoutrefresh(this->content);
doupdate();
}
this->Repaint();
}
void Window::SetFrameVisible(bool enabled) {
@ -204,9 +216,21 @@ void Window::Clear() {
void Window::Repaint() {
if (this->frame && this->content) {
wnoutrefresh(this->frame);
if (this->frame != this->content) {
wnoutrefresh(this->content);
doupdate();
}
drawPending = true;
}
}
void Window::Focus() {
}
void Window::Blur() {
}
void Window::Hide() {

View File

@ -18,8 +18,11 @@ class Window : public IWindow, public std::enable_shared_from_this<IWindow> {
void SetFrameVisible(bool enabled);
bool IsFrameVisible();
virtual void SetContentColor(int color);
virtual void SetFrameColor(int color);
virtual void Focus();
virtual void Blur();
virtual void SetContentColor(int64 color);
virtual void SetFrameColor(int64 color);
virtual void SetSize(int width, int height);
virtual void SetPosition(int x, int y);
@ -37,6 +40,8 @@ class Window : public IWindow, public std::enable_shared_from_this<IWindow> {
virtual int GetFocusOrder();
virtual void SetFocusOrder(int order = -1);
static void WriteToScreen();
protected:
IWindow* GetParent() const;
@ -49,5 +54,6 @@ class Window : public IWindow, public std::enable_shared_from_this<IWindow> {
bool drawFrame;
int focusOrder;
int id;
int width, height, x, y, contentColor, frameColor;
int64 contentColor, frameColor;
int width, height, x, y;
};