Added the concept of ScrollAdapter ItemDecorators that can be used to decorate entries in a ScrollableWindow.

This commit is contained in:
Casey Langen 2016-06-22 21:19:34 -07:00
parent e1086b9847
commit 45c8aeb1c7
9 changed files with 72 additions and 34 deletions

View File

@ -3,6 +3,7 @@ set (BOX_SRCS
./stdafx.cpp ./stdafx.cpp
./app/layout/BrowseLayout.cpp ./app/layout/BrowseLayout.cpp
./app/layout/ConsoleLayout.cpp ./app/layout/ConsoleLayout.cpp
./app/layout/IndexerLayout.cpp
./app/layout/LibraryLayout.cpp ./app/layout/LibraryLayout.cpp
./app/layout/NowPlayingLayout.cpp ./app/layout/NowPlayingLayout.cpp
./app/layout/SearchLayout.cpp ./app/layout/SearchLayout.cpp

View File

@ -44,15 +44,14 @@
#include "IndexerLayout.h" #include "IndexerLayout.h"
using namespace musik::core::library::constants; using namespace musik::core::library::constants;
using namespace musik::core; using namespace musik::core;
using namespace musik::box; using namespace musik::box;
using namespace cursespp; using namespace cursespp;
using namespace std::placeholders;
#define SEARCH_HEIGHT 3 #define SEARCH_HEIGHT 3
IndexerLayout::IndexerLayout( IndexerLayout::IndexerLayout(musik::core::LibraryPtr library)
musik::core::LibraryPtr library)
: LayoutBase() : LayoutBase()
, library(library) { , library(library) {
this->InitializeWindows(); this->InitializeWindows();
@ -83,7 +82,7 @@ void IndexerLayout::Layout() {
int leftWidth = cx / 3; /* 1/3 width */ int leftWidth = cx / 3; /* 1/3 width */
int rightX = leftWidth; int rightX = leftWidth;
int rightWidth = cx - rightX; /* remainder (~2/3) */ int rightWidth = cx - rightX; /* remainder (~2/3) */
this->browseLabel->MoveAndResize(leftX, startY, leftWidth, LABEL_HEIGHT); this->browseLabel->MoveAndResize(leftX, startY, leftWidth, LABEL_HEIGHT);
this->addedPathsLabel->MoveAndResize(rightX, startY, rightWidth, LABEL_HEIGHT); this->addedPathsLabel->MoveAndResize(rightX, startY, rightWidth, LABEL_HEIGHT);
@ -106,9 +105,26 @@ void IndexerLayout::RefreshAddedPaths() {
this->addedPathsAdapter.AddEntry(e); this->addedPathsAdapter.AddEntry(e);
} }
ScrollAdapterBase::ItemDecorator decorator =
std::bind(&IndexerLayout::ListItemDecorator, this, _1, _2, _3);
this->addedPathsAdapter.SetItemDecorator(decorator);
this->addedPathsList->OnAdapterChanged(); this->addedPathsList->OnAdapterChanged();
} }
int64 IndexerLayout::ListItemDecorator(
cursespp::ScrollableWindow* scrollable,
size_t index,
cursespp::IScrollAdapter::EntryPtr entry)
{
if (scrollable == this->addedPathsList.get()) {
if (index == this->addedPathsList->GetSelectedIndex()) {
return COLOR_PAIR(BOX_COLOR_BLACK_ON_GREEN);
}
}
return -1;
}
void IndexerLayout::InitializeWindows() { void IndexerLayout::InitializeWindows() {
this->SetContentColor(BOX_COLOR_WHITE_ON_BLACK); this->SetContentColor(BOX_COLOR_WHITE_ON_BLACK);
@ -116,10 +132,10 @@ void IndexerLayout::InitializeWindows() {
this->title->SetText("settings", TextLabel::AlignCenter); this->title->SetText("settings", TextLabel::AlignCenter);
this->browseLabel.reset(new TextLabel()); this->browseLabel.reset(new TextLabel());
this->browseLabel->SetText("browse filesystem", TextLabel::AlignLeft); this->browseLabel->SetText("browse (SPACE to add)", TextLabel::AlignLeft);
this->addedPathsLabel.reset(new TextLabel()); this->addedPathsLabel.reset(new TextLabel());
this->addedPathsLabel->SetText("indexed paths", TextLabel::AlignLeft); this->addedPathsLabel->SetText("indexed paths (DEL to remove)", TextLabel::AlignLeft);
this->addedPathsList.reset(new cursespp::ListWindow(&this->addedPathsAdapter, nullptr)); this->addedPathsList.reset(new cursespp::ListWindow(&this->addedPathsAdapter, nullptr));
this->addedPathsList->SetContentColor(BOX_COLOR_WHITE_ON_BLACK); this->addedPathsList->SetContentColor(BOX_COLOR_WHITE_ON_BLACK);

View File

@ -56,8 +56,7 @@ namespace musik {
public sigslot::has_slots<> public sigslot::has_slots<>
{ {
public: public:
IndexerLayout( IndexerLayout(musik::core::LibraryPtr library);
musik::core::LibraryPtr library);
virtual ~IndexerLayout(); virtual ~IndexerLayout();
@ -72,6 +71,11 @@ namespace musik {
void InitializeWindows(); void InitializeWindows();
void RefreshAddedPaths(); void RefreshAddedPaths();
int64 ListItemDecorator(
cursespp::ScrollableWindow* w,
size_t index,
cursespp::IScrollAdapter::EntryPtr entry);
musik::core::LibraryPtr library; musik::core::LibraryPtr library;
std::shared_ptr<cursespp::TextLabel> title; std::shared_ptr<cursespp::TextLabel> title;

View File

@ -37,6 +37,8 @@
#include <stdafx.h> #include <stdafx.h>
namespace cursespp { namespace cursespp {
class ScrollableWindow;
class IScrollAdapter { class IScrollAdapter {
public: public:
virtual ~IScrollAdapter() { } virtual ~IScrollAdapter() { }
@ -71,6 +73,6 @@ namespace cursespp {
virtual void SetDisplaySize(size_t width, size_t height) = 0; virtual void SetDisplaySize(size_t width, size_t height) = 0;
virtual size_t GetEntryCount() = 0; virtual size_t GetEntryCount() = 0;
virtual EntryPtr GetEntry(size_t index) = 0; virtual EntryPtr GetEntry(size_t index) = 0;
virtual void DrawPage(WINDOW* window, size_t index, ScrollPosition *result = NULL) = 0; virtual void DrawPage(ScrollableWindow* window, size_t index, ScrollPosition *result = NULL) = 0;
}; };
} }

View File

@ -47,7 +47,7 @@ class EmptyAdapter : public IScrollAdapter {
virtual void SetDisplaySize(size_t width, size_t height) { } virtual void SetDisplaySize(size_t width, size_t height) { }
virtual size_t GetEntryCount() { return 0; } virtual size_t GetEntryCount() { return 0; }
virtual EntryPtr GetEntry(size_t index) { return IScrollAdapter::EntryPtr(); } virtual EntryPtr GetEntry(size_t index) { return IScrollAdapter::EntryPtr(); }
virtual void DrawPage(WINDOW* window, size_t index, ScrollPosition *result = NULL) { } virtual void DrawPage(ScrollableWindow* window, size_t index, ScrollPosition *result = NULL) { }
}; };
static EmptyAdapter emptyAdapter; static EmptyAdapter emptyAdapter;
@ -156,9 +156,7 @@ void ListWindow::PageDown() {
void ListWindow::ScrollTo(size_t index) { void ListWindow::ScrollTo(size_t index) {
this->GetScrollAdapter().DrawPage( this->GetScrollAdapter().DrawPage(
this->GetContent(), this, index, &this->GetScrollPosition());
index,
&this->GetScrollPosition());
this->Repaint(); this->Repaint();
} }

View File

@ -40,7 +40,12 @@
#include <sigslot/sigslot.h> #include <sigslot/sigslot.h>
namespace cursespp { namespace cursespp {
class ListWindow : public ScrollableWindow { class ListWindow :
public ScrollableWindow
#if (__clang_major__ == 7 && __clang_minor__ == 3)
, public std::enable_shared_from_this<ListWindow>
#endif
{
public: public:
static size_t NO_SELECTION; static size_t NO_SELECTION;

View File

@ -34,6 +34,7 @@
#include <stdafx.h> #include <stdafx.h>
#include "ScrollAdapterBase.h" #include "ScrollAdapterBase.h"
#include "ScrollableWindow.h"
#include "MultiLineEntry.h" #include "MultiLineEntry.h"
using namespace cursespp; using namespace cursespp;
@ -103,7 +104,7 @@ void ScrollAdapterBase::GetVisibleItems(
start = actual; start = actual;
} }
void ScrollAdapterBase::DrawPage(WINDOW* window, size_t index, ScrollPosition *result) { void ScrollAdapterBase::DrawPage(ScrollableWindow* scrollable, size_t index, ScrollPosition *result) {
if (result != NULL) { if (result != NULL) {
result->visibleEntryCount = 0; result->visibleEntryCount = 0;
result->firstVisibleEntryIndex = 0; result->firstVisibleEntryIndex = 0;
@ -112,6 +113,8 @@ void ScrollAdapterBase::DrawPage(WINDOW* window, size_t index, ScrollPosition *r
result->logicalIndex = 0; result->logicalIndex = 0;
} }
WINDOW* window = scrollable->GetContent();
werase(window); werase(window);
if (this->height == 0 || this->width == 0 || this->GetEntryCount() == 0) { if (this->height == 0 || this->width == 0 || this->GetEntryCount() == 0) {
@ -137,7 +140,15 @@ void ScrollAdapterBase::DrawPage(WINDOW* window, size_t index, ScrollPosition *r
size_t count = entry->GetLineCount(); size_t count = entry->GetLineCount();
for (size_t i = 0; i < count && drawnLines < this->height; i++) { for (size_t i = 0; i < count && drawnLines < this->height; i++) {
int64 attrs = entry->GetAttrs(i); int64 attrs = -1;
if (this->decorator) {
attrs = this->decorator(scrollable, e, entry);
}
if (attrs == -1) {
attrs = entry->GetAttrs(i);
}
if (attrs != -1) { if (attrs != -1) {
wattron(window, attrs); wattron(window, attrs);

View File

@ -41,23 +41,33 @@
namespace cursespp { namespace cursespp {
class ScrollAdapterBase : public IScrollAdapter { class ScrollAdapterBase : public IScrollAdapter {
public: public:
typedef std::function<int64(ScrollableWindow*, size_t, EntryPtr)> ItemDecorator;
ScrollAdapterBase(); ScrollAdapterBase();
virtual ~ScrollAdapterBase(); virtual ~ScrollAdapterBase();
virtual void SetDisplaySize(size_t width, size_t height); virtual void SetDisplaySize(size_t width, size_t height);
virtual size_t GetLineCount(); virtual size_t GetLineCount();
virtual void DrawPage(WINDOW* window, size_t index, ScrollPosition *result = NULL);
virtual void DrawPage(
ScrollableWindow* window,
size_t index,
ScrollPosition *result = nullptr);
virtual size_t GetEntryCount() = 0; virtual size_t GetEntryCount() = 0;
virtual EntryPtr GetEntry(size_t index) = 0; virtual EntryPtr GetEntry(size_t index) = 0;
virtual void SetItemDecorator(ItemDecorator decorator) { this->decorator = decorator; }
protected: protected:
void GetVisibleItems(size_t desired, std::deque<EntryPtr>& target, size_t& start); void GetVisibleItems(size_t desired, std::deque<EntryPtr>& target, size_t& start);
virtual ItemDecorator GetItemDecorator() { return this->decorator; }
size_t GetWidth() { return this->width; } size_t GetWidth() { return this->width; }
size_t GetHeight() { return this->height; } size_t GetHeight() { return this->height; }
private: private:
size_t width, height; size_t width, height;
ItemDecorator decorator;
}; };
} }

View File

@ -49,7 +49,7 @@ typedef IScrollAdapter::ScrollPosition ScrollPos;
{ \ { \
ScrollPos& pos = GetScrollPosition(); \ ScrollPos& pos = GetScrollPosition(); \
GetScrollAdapter().DrawPage( \ GetScrollAdapter().DrawPage( \
this->GetContent(), \ this, \
pos.firstVisibleEntryIndex, \ pos.firstVisibleEntryIndex, \
&pos); \ &pos); \
} \ } \
@ -66,9 +66,9 @@ void ScrollableWindow::OnSizeChanged() {
IScrollAdapter& adapter = this->GetScrollAdapter(); IScrollAdapter& adapter = this->GetScrollAdapter();
ScrollPos& pos = this->GetScrollPosition(); ScrollPos& pos = this->GetScrollPosition();
adapter.SetDisplaySize( adapter.SetDisplaySize(
this->GetContentWidth(), this->GetContentWidth(),
this->GetContentHeight()); this->GetContentHeight());
} }
@ -96,12 +96,7 @@ void ScrollableWindow::OnAdapterChanged() {
} }
else { else {
ScrollPos &pos = this->GetScrollPosition(); ScrollPos &pos = this->GetScrollPosition();
adapter->DrawPage(this, pos.firstVisibleEntryIndex, &pos);
adapter->DrawPage(
this->GetContent(),
pos.firstVisibleEntryIndex,
&pos);
this->Repaint(); this->Repaint();
} }
} }
@ -112,13 +107,13 @@ void ScrollableWindow::Show() {
} }
void ScrollableWindow::ScrollToTop() { void ScrollableWindow::ScrollToTop() {
GetScrollAdapter().DrawPage(this->GetContent(), 0, &this->GetScrollPosition()); GetScrollAdapter().DrawPage(this, 0, &this->GetScrollPosition());
this->Repaint(); this->Repaint();
} }
void ScrollableWindow::ScrollToBottom() { void ScrollableWindow::ScrollToBottom() {
GetScrollAdapter().DrawPage( GetScrollAdapter().DrawPage(
this->GetContent(), this,
GetScrollAdapter().GetEntryCount(), GetScrollAdapter().GetEntryCount(),
&this->GetScrollPosition()); &this->GetScrollPosition());
@ -130,9 +125,7 @@ void ScrollableWindow::ScrollUp(int delta) {
if (pos.firstVisibleEntryIndex > 0) { if (pos.firstVisibleEntryIndex > 0) {
GetScrollAdapter().DrawPage( GetScrollAdapter().DrawPage(
this->GetContent(), this, pos.firstVisibleEntryIndex - delta, &pos);
pos.firstVisibleEntryIndex - delta,
&pos);
this->Repaint(); this->Repaint();
} }
@ -142,9 +135,7 @@ void ScrollableWindow::ScrollDown(int delta) {
ScrollPos &pos = this->GetScrollPosition(); ScrollPos &pos = this->GetScrollPosition();
GetScrollAdapter().DrawPage( GetScrollAdapter().DrawPage(
this->GetContent(), this, pos.firstVisibleEntryIndex + delta, &pos);
pos.firstVisibleEntryIndex + delta,
&pos);
this->Repaint(); this->Repaint();
} }