Preliminary work on ScrollableWindow.

This commit is contained in:
casey 2016-05-07 19:01:15 -07:00
parent 9126c6ca6a
commit 2407547325
18 changed files with 413 additions and 40 deletions

View File

@ -63,3 +63,7 @@ inline std::string u16to8(const std::wstring& u16) {
utf8::utf16to8(u16.begin(), u16.end(), std::back_inserter(result));
return result;
}
inline size_t u8len(const std::string& u8) {
return utf8::distance(u8.begin(), u8.end());
}

View File

@ -35,6 +35,14 @@ int BorderedWindow::GetHeight() const {
return this->height;
}
int BorderedWindow::GetContentHeight() const {
return this->height - 2;
}
int BorderedWindow::GetContentWidth() const {
return this->width - 2;
}
int BorderedWindow::GetX() const {
return this->x;
}

View File

@ -20,6 +20,8 @@ class BorderedWindow {
void Clear();
int GetWidth() const;
int GetHeight() const;
int GetContentHeight() const;
int GetContentWidth() const;
int GetX() const;
int GetY() const;
bool GetScrollable() const;

View File

@ -12,4 +12,5 @@ void Colors::Init() {
init_pair(BOX_COLOR_RED_ON_BLUE, COLOR_RED, COLOR_BLUE);
init_pair(BOX_COLOR_YELLOW_ON_BLUE, COLOR_YELLOW, COLOR_BLUE);
init_pair(BOX_COLOR_BLACK_ON_GREY, COLOR_BLACK, COLOR_WHITE);
init_pair(BOX_COLOR_BLACK_ON_GREEN, COLOR_BLACK, COLOR_GREEN);
}

View File

@ -6,6 +6,7 @@
#define BOX_COLOR_RED_ON_BLUE 2
#define BOX_COLOR_YELLOW_ON_BLUE 3
#define BOX_COLOR_BLACK_ON_GREY 4
#define BOX_COLOR_BLACK_ON_GREEN 5
class Colors {
private:

View File

@ -64,15 +64,14 @@ void CommandWindow::WriteChar(int ch) {
this->buffer[bufferPosition] = 0;
std::string cmd(buffer);
if (this->ProcessCommand(cmd)) {
wclear(this->GetContents());
this->bufferPosition = 0;
}
else {
if (!this->ProcessCommand(cmd)) {
if (cmd.size()) {
output->WriteLine("illegal command: '" + cmd + "'");
}
}
wclear(this->GetContents());
this->bufferPosition = 0;
}
else {
this->buffer[bufferPosition++] = ch;

18
src/square/IScrollAdapter.h Executable file
View File

@ -0,0 +1,18 @@
#pragma once
#include "stdafx.h"
#include <curses.h>
class IScrollAdapter {
public:
virtual void SetDisplaySize(size_t width, size_t height) = 0;
virtual size_t GetLineCount(size_t width) = 0;
virtual size_t GetEntryCount() = 0;
virtual void DrawPage(WINDOW* window, size_t index) = 0;
class IEntry {
public:
virtual size_t GetLineCount(size_t width) = 0;
virtual std::string GetValue() = 0;
};
};

View File

@ -95,12 +95,28 @@ int main(int argc, char* argv[])
CommandWindow command(tp, output);
TransportWindow transport(tp);
int f1 = KEY_F(2);
int ch;
timeout(500);
while (ch = getch()) {
if (ch == -1) { /* timeout */
logs.Update();
}
else if (ch >= KEY_F(0) && ch <= KEY_F(12)) {
}
else if (ch == KEY_NPAGE) {
output.PageDown();
}
else if (ch == KEY_PPAGE) {
output.PageUp();
}
else if (ch == KEY_DOWN) {
output.ScrollDown();
}
else if (ch == KEY_UP) {
output.ScrollUp();
}
else {
command.WriteChar(ch);
}
@ -115,3 +131,4 @@ int main(int argc, char* argv[])
return 0;
}

View File

@ -5,11 +5,16 @@
#include "Screen.h"
#include "Colors.h"
OutputWindow::OutputWindow() {
OutputWindow::OutputWindow()
: ScrollableWindow()
{
this->SetSize(Screen::GetWidth() / 2, Screen::GetHeight() - 3 - 4);
this->SetPosition(0, 4);
this->SetColor(BOX_COLOR_BLACK_ON_GREY);
this->SetScrollable(true);
this->adapter = new SimpleScrollAdapter();
this->adapter->SetDisplaySize(this->GetContentWidth(), this->GetContentHeight());
this->Create();
}
@ -17,12 +22,11 @@ OutputWindow::~OutputWindow() {
}
void OutputWindow::Write(const std::string& text) {
wprintw(this->GetContents(), "%s", text.c_str());
this->Repaint();
IScrollAdapter& OutputWindow::GetScrollAdapter() {
return (IScrollAdapter&) *this->adapter;
}
void OutputWindow::WriteLine(const std::string& line) {
this->Write(line + "\n");
void OutputWindow::WriteLine(const std::string& text) {
this->adapter->AddLine(text);
this->OnAdapterChanged();
}

View File

@ -1,13 +1,17 @@
#pragma once
#include "stdafx.h"
#include "BorderedWindow.h"
#include "ScrollableWindow.h"
#include "SimpleScrollAdapter.h"
class OutputWindow : public BorderedWindow {
class OutputWindow : public ScrollableWindow {
public:
OutputWindow();
~OutputWindow();
void Write(const std::string& text);
void WriteLine(const std::string& line);
virtual IScrollAdapter& GetScrollAdapter();
private:
SimpleScrollAdapter* adapter;
};

101
src/square/ScrollableWindow.cpp Executable file
View File

@ -0,0 +1,101 @@
#pragma once
#include "stdafx.h"
#include "ScrollableWindow.h"
#include "Screen.h"
#include "Colors.h"
#include <core/debug.h>
ScrollableWindow::ScrollableWindow()
: BorderedWindow() {
scrollPosition = 0;
scrolledToBottom = true;
}
ScrollableWindow::~ScrollableWindow() {
}
void ScrollableWindow::OnAdapterChanged() {
IScrollAdapter *adapter = &GetScrollAdapter();
if (scrolledToBottom) {
this->ScrollToBottom();
}
else {
GetScrollAdapter().DrawPage(this->GetContents(), this->scrollPosition);
this->Repaint();
}
}
size_t ScrollableWindow::GetFirstVisible() {
return scrollPosition;
}
size_t ScrollableWindow::GetLastVisible() {
int total = GetScrollAdapter().GetLineCount(this->GetContentWidth());
return min(scrollPosition + this->GetContentHeight(), total);
}
void ScrollableWindow::ScrollToTop() {
GetScrollAdapter().DrawPage(this->GetContents(), 0);
this->scrollPosition = 0;
this->Repaint();
this->CheckScrolledToBottom();
}
void ScrollableWindow::ScrollToBottom() {
IScrollAdapter *adapter = &GetScrollAdapter();
int total = (int) adapter->GetLineCount(this->GetWidth());
int height = this->GetContentHeight();
int actual = total - height + 1;
actual = (actual < 0) ? 0 : actual;
adapter->DrawPage(this->GetContents(), actual);
this->scrollPosition = actual;
this->Repaint();
this->CheckScrolledToBottom();
}
void ScrollableWindow::ScrollUp(int delta) {
int actual = (int) this->scrollPosition - delta;
actual = (actual < 0) ? 0 : actual;
GetScrollAdapter().DrawPage(this->GetContents(), actual);
this->scrollPosition = (size_t) actual;
this->Repaint();
this->CheckScrolledToBottom();
}
void ScrollableWindow::ScrollDown(int delta) {
IScrollAdapter *adapter = &GetScrollAdapter();
int total = adapter->GetLineCount(this->GetWidth());
int height = this->GetContentHeight();
int optimal = total - height + 1;
int max = max(0, optimal);
int actual = (int) this->scrollPosition + delta;
actual = (actual > max) ? max : actual;
adapter->DrawPage(this->GetContents(), actual);
this->scrollPosition = (size_t) actual;
this->Repaint();
this->CheckScrolledToBottom();
}
void ScrollableWindow::PageUp() {
ScrollUp(this->GetContentHeight() - 1);
}
void ScrollableWindow::PageDown() {
ScrollDown(this->GetContentHeight() - 1);
}
void ScrollableWindow::CheckScrolledToBottom() {
}

31
src/square/ScrollableWindow.h Executable file
View File

@ -0,0 +1,31 @@
#pragma once
#include "stdafx.h"
#include "BorderedWindow.h"
#include "IScrollAdapter.h"
class ScrollableWindow : public BorderedWindow {
public:
ScrollableWindow();
~ScrollableWindow();
void ScrollToTop();
void ScrollToBottom();
void ScrollUp(int delta = 1);
void ScrollDown(int delta = 1);
void PageUp();
void PageDown();
protected:
virtual IScrollAdapter& GetScrollAdapter() = 0;
void OnAdapterChanged();
size_t GetFirstVisible();
size_t GetLastVisible();
private:
void CheckScrolledToBottom();
size_t scrollPosition;
bool scrolledToBottom;
};

View File

@ -0,0 +1,114 @@
#include "stdafx.h"
#include "SimpleScrollAdapter.h"
#include <boost/algorithm/string.hpp>
SimpleScrollAdapter::SimpleScrollAdapter() {
this->lineCount = 0;
}
SimpleScrollAdapter::~SimpleScrollAdapter() {
}
void SimpleScrollAdapter::SetDisplaySize(size_t width, size_t height) {
if (height != this->height || width != this->width) {
this->height = height;
this->width = width;
this->lineCount = -1;
}
}
size_t SimpleScrollAdapter::GetLineCount(size_t width) {
if (this->lineCount == -1) {
Iterator it = this->entries.begin();
for ( ; it != entries.end(); it++) {
this->lineCount += (*it)->GetLineCount(width);
}
}
return this->lineCount;
}
size_t SimpleScrollAdapter::GetEntryCount() {
return this->entries.size();
}
void SimpleScrollAdapter::DrawPage(WINDOW* window, size_t lineNumber) {
wclear(window);
/* find the entry at the specified line number. this is really inefficient,
and runs in O(n) time. need to figure out a way to speed this up. */
int line = 0, curr = 0;
bool found = false;
Iterator it = this->entries.begin();
for ( ; it != this->entries.end(); it++) {
curr = (*it)->GetLineCount(this->width);
if (line + curr > lineNumber) {
found = true;
break;
}
else {
line += curr;
}
}
/* if found, the iterator will be pointing at the first visible
element. */
if (found) {
Iterator end = this->entries.end();
size_t remaining = this->height;
size_t w = this->width;
size_t c = lineNumber - line;
do {
size_t count = (*it)->GetLineCount(w);
for (size_t i = c; i < count; i++) {
wprintw(window, "%s\n", (*it)->GetLine(i, w).c_str());
--remaining;
}
++it;
c = 0;
} while (it != end && remaining != 0);
}
}
void SimpleScrollAdapter::AddLine(const std::string& str) {
lineCount = -1;
std::vector<std::string> lines;
boost::algorithm::split(lines, str, boost::is_any_of("\n"));
for (size_t i = 0; i < lines.size(); i++) {
boost::shared_ptr<Entry> entry(new Entry(lines[i]));
entries.push_back(entry);
}
}
SimpleScrollAdapter::Entry::Entry(const std::string& value) {
this->value = value;
this->charCount = value.size(); // u8len(value);
}
size_t SimpleScrollAdapter::Entry::GetLineCount(size_t width) {
int full = (charCount / width);
int remain = (charCount % width == 0 ? 0 : 1);
return full + remain;
}
std::string SimpleScrollAdapter::Entry::GetLine(size_t n, size_t width) {
size_t start = n * width;
size_t count = start + width;
count = (count > this->value.size()) ? std::string::npos : count;
return this->value.substr(start, count);
}
std::string SimpleScrollAdapter::Entry::GetValue() {
return value;
}

View File

@ -0,0 +1,40 @@
#pragma once
#include "stdafx.h"
#include <boost/shared_ptr.hpp>
#include <curses.h>
#include "IScrollAdapter.h";
class SimpleScrollAdapter : public IScrollAdapter {
public:
SimpleScrollAdapter();
virtual ~SimpleScrollAdapter();
virtual void SetDisplaySize(size_t width, size_t height);
virtual size_t GetLineCount(size_t width);
virtual size_t GetEntryCount();
virtual void DrawPage(WINDOW* window, size_t index);
virtual void AddLine(const std::string& str);
private:
size_t lineCount, width, height;
class Entry : public IEntry {
public:
Entry(const std::string& value);
virtual size_t GetLineCount(size_t width);
virtual std::string GetLine(size_t line, size_t width);
virtual std::string GetValue();
private:
std::string value;
size_t charCount;
};
typedef std::vector<boost::shared_ptr<Entry>> EntryList;
typedef EntryList::iterator Iterator;
EntryList entries;
};

View File

@ -24,6 +24,7 @@ using musik::core::audio::Transport;
TransportWindow::TransportWindow(Transport& transport) {
this->SetSize(Screen::GetWidth() / 2, 4);
this->SetPosition(0, 0);
this->SetColor(BOX_COLOR_BLACK_ON_GREEN);
this->transport = &transport;
this->paused = false;
this->Create();

View File

@ -115,9 +115,12 @@
<ClCompile Include="BorderedWindow.cpp" />
<ClCompile Include="Colors.cpp" />
<ClCompile Include="CommandWindow.cpp" />
<ClCompile Include="IScrollAdapter.h" />
<ClCompile Include="LogWindow.cpp" />
<ClCompile Include="OutputWindow.cpp" />
<ClCompile Include="Screen.cpp" />
<ClCompile Include="ScrollableWindow.cpp" />
<ClCompile Include="SimpleScrollAdapter.cpp" />
<ClCompile Include="TransportEvents.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="stdafx.cpp">
@ -134,6 +137,8 @@
<ClInclude Include="LogWindow.h" />
<ClInclude Include="OutputWindow.h" />
<ClInclude Include="Screen.h" />
<ClInclude Include="ScrollableWindow.h" />
<ClInclude Include="SimpleScrollAdapter.h" />
<ClInclude Include="TransportEvents.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="TransportWindow.h" />

View File

@ -9,6 +9,12 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Source Files\curses">
<UniqueIdentifier>{7ff6ce0d-725d-497c-9ecc-afcbe79faa5b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\windows">
<UniqueIdentifier>{80afa65b-4102-40a7-8f73-b06776d9d610}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -17,29 +23,38 @@
<ClCompile Include="TransportEvents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CommandWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LogWindow.cpp">
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BorderedWindow.cpp">
<Filter>Source Files</Filter>
<Filter>Source Files\curses</Filter>
</ClCompile>
<ClCompile Include="Colors.cpp">
<Filter>Source Files</Filter>
<Filter>Source Files\curses</Filter>
</ClCompile>
<ClCompile Include="Screen.cpp">
<Filter>Source Files</Filter>
<ClCompile Include="SimpleScrollAdapter.cpp">
<Filter>Source Files\curses</Filter>
</ClCompile>
<ClCompile Include="IScrollAdapter.h">
<Filter>Source Files\curses</Filter>
</ClCompile>
<ClCompile Include="LogWindow.cpp">
<Filter>Source Files\windows</Filter>
</ClCompile>
<ClCompile Include="OutputWindow.cpp">
<Filter>Source Files</Filter>
<Filter>Source Files\windows</Filter>
</ClCompile>
<ClCompile Include="TransportWindow.cpp">
<Filter>Source Files</Filter>
<Filter>Source Files\windows</Filter>
</ClCompile>
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
<ClCompile Include="Screen.cpp">
<Filter>Source Files\curses</Filter>
</ClCompile>
<ClCompile Include="CommandWindow.cpp">
<Filter>Source Files\windows</Filter>
</ClCompile>
<ClCompile Include="ScrollableWindow.cpp">
<Filter>Source Files\curses</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@ -52,26 +67,32 @@
<ClInclude Include="TransportEvents.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="CommandWindow.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="LogWindow.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="BorderedWindow.h">
<Filter>Source Files</Filter>
<Filter>Source Files\curses</Filter>
</ClInclude>
<ClInclude Include="Colors.h">
<Filter>Source Files</Filter>
<Filter>Source Files\curses</Filter>
</ClInclude>
<ClInclude Include="Screen.h">
<Filter>Source Files</Filter>
<ClInclude Include="SimpleScrollAdapter.h">
<Filter>Source Files\curses</Filter>
</ClInclude>
<ClInclude Include="LogWindow.h">
<Filter>Source Files\windows</Filter>
</ClInclude>
<ClInclude Include="OutputWindow.h">
<Filter>Source Files</Filter>
<Filter>Source Files\windows</Filter>
</ClInclude>
<ClInclude Include="TransportWindow.h">
<Filter>Source Files</Filter>
<Filter>Source Files\windows</Filter>
</ClInclude>
<ClInclude Include="Screen.h">
<Filter>Source Files\curses</Filter>
</ClInclude>
<ClInclude Include="CommandWindow.h">
<Filter>Source Files\windows</Filter>
</ClInclude>
<ClInclude Include="ScrollableWindow.h">
<Filter>Source Files\curses</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -4,8 +4,10 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "config.h"
#define PDC_WIDE
#else
#include <unistd.h>
#endif
typedef __int64 int64;