Experimental change to support selectable headers in the TrackListView.

This commit is contained in:
casey langen 2017-03-20 17:08:08 -07:00
parent 269dd1fb2e
commit 04eb8c13ea
15 changed files with 221 additions and 222 deletions

View File

@ -21,7 +21,6 @@ set (BOX_SRCS
./app/util/PreferenceKeys.cpp
./app/util/Playback.cpp
./app/window/CategoryListView.cpp
./app/window/EntryWithHeader.cpp
./app/window/LogWindow.cpp
./app/window/TrackListView.cpp
./app/window/TransportWindow.cpp

View File

@ -201,8 +201,11 @@ bool BrowseLayout::KeyPress(const std::string& key) {
}
else if (Hotkeys::Is(Hotkeys::ContextMenu, key)) {
if (this->GetFocus() == this->trackList) {
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, *this->trackList);
return true;
TrackPtr track = this->trackList->GetSelectedTrack();
if (track) {
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, track->GetId());
return true;
}
}
}
else if (Hotkeys::Is(Hotkeys::ViewRefresh, key)) {

View File

@ -152,7 +152,10 @@ bool TrackSearchLayout::KeyPress(const std::string& key) {
return true;
}
else if (Hotkeys::Is(Hotkeys::ContextMenu, key)) {
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, *this->trackList);
TrackPtr track = this->trackList->GetSelectedTrack();
if (track) {
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, track->GetId());
}
}
else if (key == "KEY_DOWN") {
if (this->GetFocus() == this->input) {

View File

@ -226,16 +226,8 @@ PlayQueueOverlays::PlayQueueOverlays() {
void PlayQueueOverlays::ShowAddTrackOverlay(
PlaybackService& playback,
TrackListView& trackList)
unsigned long long trackId)
{
size_t selectedIndex = trackList.GetSelectedIndex();
if (selectedIndex == ListWindow::NO_SELECTION) {
return;
}
DBID trackId = trackList.Get(selectedIndex)->GetId();
auto adapter = createAddToAdapter();
std::shared_ptr<ListOverlay> dialog(new ListOverlay());

View File

@ -47,7 +47,7 @@ namespace musik {
static void ShowAddTrackOverlay(
musik::core::audio::PlaybackService& playback,
musik::box::TrackListView& trackList);
unsigned long long trackId);
static void ShowAddCategoryOverlay(
musik::core::audio::PlaybackService& playback,

View File

@ -50,8 +50,14 @@ namespace musik {
auto tracks = trackList->GetTrackList();
if (tracks && tracks->Count()) {
size_t index = (focused.get() == trackList.get())
? trackList->GetSelectedIndex() : 0;
size_t index = 0;
if (focused.get() == trackList.get()) {
index = trackList->GetSelectedTrackIndex();
if (index == cursespp::ListWindow::NO_SELECTION) {
return;
}
}
playback.Play(*tracks, index);
}

View File

@ -1,77 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include <stdafx.h>
#include "EntryWithHeader.h"
#include <boost/algorithm/string.hpp>
#include <cursespp/Text.h>
using namespace musik::box;
using namespace cursespp;
EntryWithHeader::EntryWithHeader(
const std::string& header, const std::string& value)
{
this->header = header;
this->value = value;
this->attrs = -1;
}
void EntryWithHeader::SetWidth(size_t width) {
this->width = width;
}
int64 EntryWithHeader::GetAttrs(size_t line) {
return (line == 0) ? this->headerAttrs : this->attrs;
}
void EntryWithHeader::SetAttrs(int64 headerAttrs, int64 attrs) {
this->headerAttrs = headerAttrs;
this->attrs = attrs;
}
size_t EntryWithHeader::GetLineCount() {
return 2;
}
#define TRUNCATE(value, width) \
u8substr(value, 0, width > 0 ? width : 0)
std::string EntryWithHeader::GetLine(size_t line) {
if (line == 0) {
return text::Ellipsize(this->header, this->width);
}
return TRUNCATE(this->value, this->width);
}

View File

@ -1,59 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <cursespp/IScrollAdapter.h>
namespace musik {
namespace box {
class EntryWithHeader : public cursespp::IScrollAdapter::IEntry {
public:
EntryWithHeader(const std::string& header, const std::string& value);
virtual ~EntryWithHeader() { }
virtual void SetWidth(size_t width);
virtual int64 GetAttrs(size_t line);
virtual size_t GetLineCount();
virtual std::string GetLine(size_t line);
void SetAttrs(int64 headerAttrs, int64 attrs);
private:
size_t width;
std::string header, value;
int64 headerAttrs, attrs;
};
}
}

View File

@ -44,7 +44,7 @@
#include <glue/util/Duration.h>
#include <app/util/Hotkeys.h>
#include <app/window/EntryWithHeader.h>
#include <app/overlay/PlayQueueOverlays.h>
#include <boost/format.hpp>
@ -109,14 +109,14 @@ void TrackListView::Requery(std::shared_ptr<TrackListQueryBase> query) {
void TrackListView::OnQueryCompleted(IQuery* query) {
if (this->query && query == this->query.get()) {
if (this->query->GetStatus() == IQuery::Finished) {
this->metadata = this->query->GetResult();
this->headers = this->query->GetHeaders();
this->tracks = this->query->GetResult();
this->headers.Set(this->query->GetHeaders());
/* if the query was functionally the same as the last query, don't
mess with the selected index */
if (this->lastQueryHash != this->query->GetQueryHash()) {
this->SetSelectedIndex(0);
this->ScrollToTop();
this->SetSelectedIndex(this->headers.HeaderAt(0) ? 1 : 0);
}
this->lastQueryHash = this->query->GetQueryHash();
@ -130,12 +130,12 @@ void TrackListView::OnQueryCompleted(IQuery* query) {
}
std::shared_ptr<const TrackList> TrackListView::GetTrackList() {
return this->metadata;
return this->tracks;
}
void TrackListView::SetTrackList(std::shared_ptr<const TrackList> trackList) {
if (this->metadata != trackList) {
this->metadata = trackList;
if (this->tracks != trackList) {
this->tracks = trackList;
this->SetSelectedIndex(0);
this->ScrollToTop();
this->OnAdapterChanged();
@ -147,24 +147,34 @@ void TrackListView::SetTrackList(std::shared_ptr<const TrackList> trackList) {
void TrackListView::Clear() {
this->query.reset();
this->metadata.reset(new TrackList(this->library));
this->headers.reset(new std::set<size_t>());
this->tracks.reset(new TrackList(this->library));
this->headers.Reset();
this->OnAdapterChanged();
}
TrackPtr TrackListView::Get(size_t index) {
return this->metadata->Get(index);
TrackPtr TrackListView::GetSelectedTrack() {
auto i = this->GetSelectedTrackIndex();
return (i == ListWindow::NO_SELECTION) ? TrackPtr() : this->tracks->Get(i);
}
size_t TrackListView::GetSelectedTrackIndex() {
auto i = this->GetSelectedIndex();
if (i != ListWindow::NO_SELECTION) {
auto entry = adapter->GetEntry(this, i);
return static_cast<TrackListEntry*>(entry.get())->GetIndex();
}
return ListWindow::NO_SELECTION;
}
size_t TrackListView::Count() {
return this->metadata ? this->metadata->Count() : 0;
return this->tracks ? this->tracks->Count() : 0;
}
void TrackListView::ScrollToPlaying() {
if (this->playing && this->metadata) {
if (this->playing && this->tracks) {
DBID id = this->playing->GetId();
for (size_t i = 0; i < this->metadata->Count(); i++) {
if (this->metadata->GetId(i) == id) {
for (size_t i = 0; i < this->tracks->Count(); i++) {
if (this->tracks->GetId(i) == id) {
this->SetSelectedIndex(i);
auto pos = this->GetScrollPosition();
@ -188,12 +198,29 @@ void TrackListView::ProcessMessage(IMessage &message) {
bool TrackListView::KeyPress(const std::string& key) {
bool handled = false;
if (Hotkeys::Is(Hotkeys::NavigateJumpToPlaying, key)) {
if (key == "KEY_ENTER") {
if (headers.HeaderAt(this->GetSelectedIndex())) {
auto track = this->GetSelectedTrack();
unsigned long long fieldId = std::stoull(
track->GetValue(constants::Track::ALBUM_ID));
PlayQueueOverlays::ShowAddCategoryOverlay(
this->playback,
this->library,
constants::Track::ALBUM,
fieldId);
handled = true;
}
}
else if (Hotkeys::Is(Hotkeys::NavigateJumpToPlaying, key)) {
this->ScrollToPlaying();
handled = true;
}
handled = ListWindow::KeyPress(key);
if (!handled) {
handled = ListWindow::KeyPress(key);
}
if (handled) {
this->lastChanged = now();
@ -224,8 +251,54 @@ TrackListView::Adapter::Adapter(TrackListView &parent)
: parent(parent) {
}
/* * * * TrackListView::HeaderCalculator * * * */
void TrackListView::HeaderCalculator::Set(Headers rawOffsets) {
this->rawOffsets = rawOffsets;
this->absoluteOffsets.reset();
if (rawOffsets) {
this->absoluteOffsets.reset(new std::set<size_t>());
size_t i = 0;
for (auto val : (*this->rawOffsets)) {
this->absoluteOffsets->insert(val + i);
i++;
}
}
}
void TrackListView::HeaderCalculator::Reset() {
this->absoluteOffsets.reset();
this->rawOffsets.reset();
}
size_t TrackListView::HeaderCalculator::OffsetTrackIndex(size_t index) {
size_t result = index;
if (this->absoluteOffsets) {
for (auto offset : (*this->absoluteOffsets)) {
if (result != 0 && offset <= index) {
--result;
}
else {
break;
}
}
}
return result;
}
size_t TrackListView::HeaderCalculator::Count() {
return this->absoluteOffsets ? this->absoluteOffsets->size() : 0;
}
bool TrackListView::HeaderCalculator::HeaderAt(size_t index) {
return this->absoluteOffsets &&
this->absoluteOffsets->find(index) != this->absoluteOffsets->end();
}
/* * * * TrackListView::Adapter * * * */
size_t TrackListView::Adapter::GetEntryCount() {
return parent.metadata ? parent.metadata->Count() : 0;
return parent.tracks ? parent.tracks->Count() + parent.headers.Count() : 0;
}
#define TRACK_COL_WIDTH 3
@ -267,8 +340,28 @@ static std::string formatWithoutAlbum(TrackPtr track, size_t width) {
% trackNum % title % duration % artist);
}
IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWindow* window, size_t index) {
TrackPtr track = parent.metadata->Get(index);
IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWindow* window, size_t rawIndex) {
bool selected = (rawIndex == parent.GetSelectedIndex());
if (this->parent.headers.HeaderAt(rawIndex)) {
/* the next track at the next logical index will have the album
tracks we're interesetd in. */
auto trackIndex = this->parent.headers.OffsetTrackIndex(rawIndex + 1);
TrackPtr track = parent.tracks->Get(trackIndex);
std::string album = track->GetValue(constants::Track::ALBUM);
std::shared_ptr<TrackListEntry> entry(new
TrackListEntry(album, trackIndex, RowType::Separator));
entry->SetAttrs(selected
? COLOR_PAIR(CURSESPP_LIST_ITEM_HIGHLIGHTED_HEADER)
: COLOR_PAIR(CURSESPP_LIST_ITEM_HEADER));
return entry;
}
size_t trackIndex = this->parent.headers.OffsetTrackIndex(rawIndex);
TrackPtr track = parent.tracks->Get(trackIndex);
if (!track) {
return MISSING_ENTRY;
@ -277,11 +370,9 @@ IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWi
int64 attrs = CURSESPP_DEFAULT_COLOR;
if (parent.decorator) {
attrs = parent.decorator(track, index);
attrs = parent.decorator(track, trackIndex);
}
else {
bool selected = index == parent.GetSelectedIndex();
attrs = selected
? COLOR_PAIR(CURSESPP_HIGHLIGHTED_LIST_ITEM)
: CURSESPP_DEFAULT_COLOR;
@ -304,15 +395,10 @@ IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWi
? parent.formatter(track, this->GetWidth())
: formatWithoutAlbum(track, this->GetWidth());
if (this->parent.headers && this->parent.headers->find(index) != this->parent.headers->end()) {
std::string album = track->GetValue(constants::Track::ALBUM);
std::shared_ptr<EntryWithHeader> entry(new EntryWithHeader(album, text));
entry->SetAttrs(COLOR_PAIR(CURSESPP_LIST_ITEM_HEADER), attrs);
return entry;
}
else {
std::shared_ptr<SingleLineEntry> entry(new SingleLineEntry(text));
entry->SetAttrs(attrs);
return entry;
}
std::shared_ptr<TrackListEntry> entry(
new TrackListEntry(text, trackIndex, RowType::Track));
entry->SetAttrs(attrs);
return entry;
}

View File

@ -38,6 +38,7 @@
#include <cursespp/ScrollAdapterBase.h>
#include <cursespp/IKeyHandler.h>
#include <cursespp/ListWindow.h>
#include <cursespp/SingleLineEntry.h>
#include <core/library/query/local/TrackListQueryBase.h>
#include <core/audio/PlaybackService.h>
@ -55,8 +56,10 @@ namespace musik {
public sigslot::has_slots<>
{
public:
/* events */
sigslot::signal1<musik::core::db::local::TrackListQueryBase*> Requeried;
/* types */
typedef std::function<std::string(
musik::core::TrackPtr, size_t)> RowFormatter;
@ -65,8 +68,27 @@ namespace musik {
typedef std::shared_ptr<std::set<size_t> > Headers;
enum class RowType : char { Track = 't', Separator = 's' };
/* our special type of list entry */
class TrackListEntry : public cursespp::SingleLineEntry {
public:
TrackListEntry(const std::string& str, int index, RowType type)
: cursespp::SingleLineEntry(str), index(index), type(type) { }
virtual ~TrackListEntry() { }
RowType GetType() { return type; }
int GetIndex() { return index; }
private:
RowType type;
int index;
};
typedef musik::core::db::local::TrackListQueryBase TrackListQueryBase;
/* ctor, dtor */
TrackListView(
musik::core::audio::PlaybackService& playback,
musik::core::ILibraryPtr library,
@ -75,14 +97,16 @@ namespace musik {
virtual ~TrackListView();
/* IWindow */
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
virtual bool KeyPress(const std::string& key);
/* regular methods */
std::shared_ptr<const musik::core::TrackList> GetTrackList();
void SetTrackList(std::shared_ptr<const musik::core::TrackList> trackList);
musik::core::TrackPtr GetSelectedTrack();
size_t GetSelectedTrackIndex();
void Clear();
musik::core::TrackPtr Get(size_t index);
size_t Count();
void Requery(std::shared_ptr<TrackListQueryBase> query);
@ -105,12 +129,26 @@ namespace musik {
};
private:
/* class to help with header offset calculation */
class HeaderCalculator {
public:
void Set(Headers rawOffsets);
void Reset();
size_t OffsetTrackIndex(size_t index);
bool HeaderAt(size_t index);
size_t Count();
private:
Headers absoluteOffsets;
Headers rawOffsets;
};
void OnTrackChanged(size_t index, musik::core::TrackPtr track);
void ScrollToPlaying();
std::shared_ptr<TrackListQueryBase> query;
std::shared_ptr<const musik::core::TrackList> metadata;
Headers headers;
std::shared_ptr<const musik::core::TrackList> tracks;
HeaderCalculator headers;
Adapter* adapter;
musik::core::audio::PlaybackService& playback;
musik::core::TrackPtr playing;

View File

@ -66,12 +66,14 @@ indicies we'll use to store them */
#define THEME_COLOR_BANNER_FOREGROUND 38
#define THEME_COLOR_LIST_HEADER_BACKGROUND 39
#define THEME_COLOR_LIST_HEADER_FOREGROUND 40
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND 41
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND 42
#define THEME_COLOR_LIST_ITEM_ACTIVE_BACKGROUND 43
#define THEME_COLOR_LIST_ITEM_ACTIVE_FOREGROUND 44
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_BACKGROUND 45
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_FOREGROUND 46
#define THEME_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND 41
#define THEME_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND 42
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND 43
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND 44
#define THEME_COLOR_LIST_ITEM_ACTIVE_BACKGROUND 45
#define THEME_COLOR_LIST_ITEM_ACTIVE_FOREGROUND 46
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_BACKGROUND 47
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_FOREGROUND 48
/* user-readable names for the color identifiers above. these are
used as key names in the config files */
@ -100,6 +102,8 @@ used as key names in the config files */
#define JSON_KEY_COLOR_BANNER_FOREGROUND "banner_foreground"
#define JSON_KEY_COLOR_LIST_HEADER_BACKGROUND "list_header_background"
#define JSON_KEY_COLOR_LIST_HEADER_FOREGROUND "list_header_foreground"
#define JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND "list_header_highlighted_background"
#define JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND "list_header_highlighted_foreground"
#define JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND "list_item_highlighted_background"
#define JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND "list_item_highlighted_foreground"
#define JSON_KEY_COLOR_LIST_ITEM_ACTIVE_BACKGROUND "list_item_active_background"
@ -282,6 +286,8 @@ struct Theme {
/* listview */
listHeaderBackground.Set(THEME_COLOR_LIST_HEADER_BACKGROUND, 36, 36, 31, -1);
listHeaderForeground.Set(THEME_COLOR_LIST_HEADER_FOREGROUND, 166, 226, 46, COLOR_256_GREEN);
listHeaderHighlightedBackground.Set(THEME_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND, 166, 226, 46, COLOR_256_GREEN);
listHeaderHighlightedForeground.Set(THEME_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND, 36, 36, 31, -1);
listHighlightedBackground.Set(THEME_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND, 166, 226, 46, COLOR_256_GREEN);
listHighlightedForeground.Set(THEME_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND, 24, 24, 20, COLOR_BLACK);
listActiveBackground.Set(THEME_COLOR_LIST_ITEM_ACTIVE_BACKGROUND, 66, 66, 56, COLOR_256_MEDIUM_GRAY);
@ -336,6 +342,8 @@ struct Theme {
this->bannerForeground.Set(colors.value(JSON_KEY_COLOR_BANNER_FOREGROUND, unset));
this->listHeaderBackground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_BACKGROUND, unset));
this->listHeaderForeground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_FOREGROUND, unset));
this->listHeaderHighlightedBackground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND, unset));
this->listHeaderHighlightedForeground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND, unset));
this->listHighlightedBackground.Set(colors.value(JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND, unset));
this->listHighlightedForeground.Set(colors.value(JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND, unset));
this->listActiveBackground.Set(colors.value(JSON_KEY_COLOR_LIST_ITEM_ACTIVE_BACKGROUND, unset));
@ -414,6 +422,11 @@ struct Theme {
listHeaderForeground.Id(mode, COLOR_GREEN),
listHeaderBackground.Id(mode, -1));
init_pair(
CURSESPP_LIST_ITEM_HIGHLIGHTED_HEADER,
listHeaderHighlightedForeground.Id(mode, -1),
listHeaderHighlightedBackground.Id(mode, COLOR_GREEN));
init_pair(
CURSESPP_SELECTED_LIST_ITEM,
listActiveForeground.Id(mode, COLOR_YELLOW),
@ -468,6 +481,8 @@ struct Theme {
/* listview */
Color listHeaderBackground;
Color listHeaderForeground;
Color listHeaderHighlightedBackground;
Color listHeaderHighlightedForeground;
Color listHighlightedBackground;
Color listHighlightedForeground;
Color listActiveForeground;

View File

@ -42,30 +42,31 @@
#define CURSESPP_HIGHLIGHTED_LIST_ITEM 2
#define CURSESPP_HIGHLIGHTED_SELECTED_LIST_ITEM 3
#define CURSESPP_LIST_ITEM_HEADER 4
#define CURSESPP_LIST_ITEM_HIGHLIGHTED_HEADER 5
#define CURSESPP_DEFAULT_CONTENT_COLOR 5
#define CURSESPP_DEFAULT_FRAME_COLOR 6
#define CURSESPP_FOCUSED_FRAME_COLOR 7
#define CURSESPP_DEFAULT_CONTENT_COLOR 6
#define CURSESPP_DEFAULT_FRAME_COLOR 7
#define CURSESPP_FOCUSED_FRAME_COLOR 8
#define CURSESPP_TEXT_DEFAULT 8
#define CURSESPP_TEXT_DISABLED 9
#define CURSESPP_TEXT_FOCUSED 10
#define CURSESPP_TEXT_ACTIVE 11
#define CURSESPP_TEXT_WARNING 12
#define CURSESPP_TEXT_ERROR 13
#define CURSESPP_TEXT_HIDDEN 14
#define CURSESPP_TEXT_DEFAULT 9
#define CURSESPP_TEXT_DISABLED 10
#define CURSESPP_TEXT_FOCUSED 11
#define CURSESPP_TEXT_ACTIVE 12
#define CURSESPP_TEXT_WARNING 13
#define CURSESPP_TEXT_ERROR 14
#define CURSESPP_TEXT_HIDDEN 15
#define CURSESPP_BUTTON_NORMAL 16
#define CURSESPP_BUTTON_HIGHLIGHTED 18
#define CURSESPP_BUTTON_HIGHLIGHTED 17
#define CURSESPP_SHORTCUT_ROW_NORMAL 19
#define CURSESPP_SHORTCUT_ROW_FOCUSED 20
#define CURSESPP_SHORTCUT_ROW_NORMAL 18
#define CURSESPP_SHORTCUT_ROW_FOCUSED 19
#define CURSESPP_OVERLAY_FRAME 21
#define CURSESPP_OVERLAY_CONTENT 22
#define CURSESPP_OVERLAY_INPUT_FRAME 23
#define CURSESPP_OVERLAY_FRAME 20
#define CURSESPP_OVERLAY_CONTENT 21
#define CURSESPP_OVERLAY_INPUT_FRAME 22
#define CURSESPP_BANNER 24
#define CURSESPP_BANNER 23
namespace cursespp {
class Colors {

View File

@ -48,7 +48,7 @@ namespace cursespp {
virtual std::string GetLine(size_t line);
void SetAttrs(int64 attrs);
private:
size_t width;
std::string value;

View File

@ -149,7 +149,6 @@ xcopy "$(ProjectDir)data\locales\*" "$(TargetDir)locales\" /Y /e</Command>
<ClCompile Include="app\util\Playback.cpp" />
<ClCompile Include="app\util\PreferenceKeys.cpp" />
<ClCompile Include="app\window\CategoryListView.cpp" />
<ClCompile Include="app\window\EntryWithHeader.cpp" />
<ClCompile Include="app\window\LogWindow.cpp" />
<ClCompile Include="app\window\TrackListView.cpp" />
<ClCompile Include="app\window\TransportWindow.cpp" />
@ -203,7 +202,6 @@ xcopy "$(ProjectDir)data\locales\*" "$(TargetDir)locales\" /Y /e</Command>
<ClInclude Include="app\util\PreferenceKeys.h" />
<ClInclude Include="app\util\Version.h" />
<ClInclude Include="app\window\CategoryListView.h" />
<ClInclude Include="app\window\EntryWithHeader.h" />
<ClInclude Include="app\window\LogWindow.h" />
<ClInclude Include="app\window\TrackListView.h" />
<ClInclude Include="app\window\TransportWindow.h" />

View File

@ -48,9 +48,6 @@
<ClCompile Include="app\util\GlobalHotkeys.cpp">
<Filter>app\util</Filter>
</ClCompile>
<ClCompile Include="app\window\EntryWithHeader.cpp">
<Filter>app\window</Filter>
</ClCompile>
<ClCompile Include="app\layout\ConsoleLayout.cpp">
<Filter>app\layout</Filter>
</ClCompile>
@ -219,9 +216,6 @@
<ClInclude Include="cursespp\IOrderable.h">
<Filter>cursespp</Filter>
</ClInclude>
<ClInclude Include="app\window\EntryWithHeader.h">
<Filter>app\window</Filter>
</ClInclude>
<ClInclude Include="app\layout\ConsoleLayout.h">
<Filter>app\layout</Filter>
</ClInclude>