new feature: alternative user interface

This commit is contained in:
Andrzej Rybczak
2009-08-12 02:08:13 +02:00
parent dbca4a80ee
commit 101f01941d
33 changed files with 428 additions and 127 deletions

View File

@@ -65,6 +65,7 @@ void Browser::Init()
void Browser::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
@@ -84,10 +85,10 @@ void Browser::SwitchTo()
RedrawHeader = 1;
}
std::string Browser::Title()
std::basic_string<my_char_t> Browser::Title()
{
std::string result = "Browse: ";
result += TO_STRING(Scroller(itsBrowsedDir, COLS-result.length()-VolumeState.length(), itsScrollBeginning));
std::basic_string<my_char_t> result = U("Browse: ");
result += Scroller(itsBrowsedDir, COLS-result.length()-(Config.new_design ? 2 : VolumeState.length()), itsScrollBeginning);
return result;
}

View File

@@ -32,7 +32,7 @@ class Browser : public Screen< Menu<MPD::Item> >
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void EnterPressed();
virtual void SpacePressed();

View File

@@ -51,7 +51,7 @@ void Clock::Init()
{
Width = Config.clock_display_seconds ? 60 : 40;
w = new Window((COLS-Width)/2, (LINES-Height)/2, Width, Height-1, "", Config.main_color, Border(Config.main_color));
w = new Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, Border(Config.main_color));
w->SetTimeout(ncmpcpp_window_timeout);
isInitialized = 1;
}
@@ -60,7 +60,7 @@ void Clock::Resize()
{
if (Width <= size_t(COLS) && Height <= MainHeight)
{
w->MoveTo((COLS-Width)/2, (LINES-Height)/2);
w->MoveTo((COLS-Width)/2, (MainHeight-Height)/2+MainStartY);
if (myScreen == this)
{
if (myPlaylist->hasToBeResized)
@@ -96,9 +96,9 @@ void Clock::SwitchTo()
w->Display();
}
std::string Clock::Title()
std::basic_string<my_char_t> Clock::Title()
{
return "Clock";
return U("Clock");
}
void Clock::Update()

View File

@@ -36,7 +36,7 @@ class Clock : public Screen<Window>
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void Update();
virtual void Scroll(Where, const int *) { }

View File

@@ -41,6 +41,7 @@ void Help::Init()
void Help::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
@@ -60,9 +61,9 @@ void Help::SwitchTo()
}
std::string Help::Title()
std::basic_string<my_char_t> Help::Title()
{
return "Help";
return U("Help");
}
std::string Help::DisplayKeys(int *key, int size)
@@ -185,6 +186,7 @@ void Help::GetKeybindings()
*w << DisplayKeys(Key.ToggleFindMode) << "Toggle find mode (normal/wrapped)\n";
*w << DisplayKeys(Key.GoToContainingDir) << "Locate song in browser\n";
*w << DisplayKeys(Key.ToggleDisplayMode) << "Toggle display mode\n";
*w << DisplayKeys(Key.ToggleInterface) << "Toggle user interface\n";
*w << DisplayKeys(Key.GoToPosition) << "Go to given position in current song (in % by default)\n";
*w << DisplayKeys(Key.SongInfo) << "Show song's info\n";
# ifdef HAVE_CURL_CURL_H

View File

@@ -30,7 +30,7 @@ class Help : public Screen<Scrollpad>
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void EnterPressed() { }
virtual void SpacePressed() { }

View File

@@ -321,26 +321,24 @@ Buffer ShowTag(const std::string &tag)
return result;
}
#ifdef _UTF8
std::basic_string<my_char_t> Scroller(const std::string &str, size_t width, size_t &pos)
{
std::basic_string<my_char_t> s = TO_WSTRING(str);
return Scroller(TO_WSTRING(str), width, pos);
}
#endif // _UTF8
std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, size_t width, size_t &pos)
{
std::basic_string<my_char_t> s(str);
if (!Config.header_text_scrolling)
return s;
std::basic_string<my_char_t> result;
size_t len;
# ifdef _UTF8
len = Window::Length(s);
# else
len = s.length();
# endif
size_t len = Window::Length(s);
if (len > width)
{
# ifdef _UTF8
s += L" ** ";
# else
s += " ** ";
# endif
s += U(" ** ");
len = 0;
std::basic_string<my_char_t>::const_iterator b = s.begin(), e = s.end();
for (std::basic_string<my_char_t>::const_iterator it = b+pos; it < e && len < width; ++it)

View File

@@ -52,6 +52,49 @@ template <typename A, typename B> std::string StringPairToString(const std::pair
return pair.first;
}
template <typename C> void String2Buffer(const std::basic_string<C> &s, basic_buffer<C> &buf)
{
for (typename std::basic_string<C>::const_iterator it = s.begin(); it != s.end(); ++it)
{
if (*it != '$')
buf << *it;
else if (isdigit(*++it))
buf << Color(*it-'0');
else
{
switch (*it)
{
case '$':
buf << *it;
break;
case 'b':
buf << fmtBold;
break;
case 'a':
buf << fmtAltCharset;
break;
case 'r':
buf << fmtReverse;
break;
case '/':
switch (*++it)
{
case 'b':
buf << fmtBoldEnd;
break;
case 'a':
buf << fmtAltCharsetEnd;
break;
case 'r':
buf << fmtReverseEnd;
break;
}
break;
}
}
}
}
inline bool Keypressed(int in, const int *key)
{
return in == key[0] || in == key[1];
@@ -72,7 +115,10 @@ std::string ExtractTopDirectory(const std::string &);
Buffer ShowTag(const std::string &);
#ifdef _UTF8
std::basic_string<my_char_t> Scroller(const std::string &, size_t, size_t &);
#endif // _UTF8
std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &, size_t, size_t &);
#ifdef HAVE_CURL_CURL_H
size_t write_data(char *, size_t, size_t, void *);

View File

@@ -65,12 +65,13 @@ void Info::Init()
void Info::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
std::string Info::Title()
std::basic_string<my_char_t> Info::Title()
{
return itsTitle;
return TO_WSTRING(itsTitle);
}
#if defined(HAVE_CURL_CURL_H) && defined(HAVE_PTHREAD_H)

View File

@@ -31,7 +31,7 @@ class Info : public Screen<Scrollpad>
virtual void SwitchTo() { }
virtual void Resize();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
# if defined(HAVE_CURL_CURL_H) && defined(HAVE_PTHREAD_H)
virtual void Update();

View File

@@ -75,6 +75,7 @@ void Lyrics::Init()
void Lyrics::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
@@ -187,10 +188,10 @@ void Lyrics::SwitchTo()
}
}
std::string Lyrics::Title()
std::basic_string<my_char_t> Lyrics::Title()
{
std::string result = "Lyrics: ";
result += TO_STRING(Scroller(itsSong.toString("%a - %t"), COLS-result.length()-VolumeState.length(), itsScrollBegin));
std::basic_string<my_char_t> result = U("Lyrics: ");
result += Scroller(itsSong.toString("%a - %t"), COLS-result.length()-(Config.new_design ? 2 : VolumeState.length()), itsScrollBegin);
return result;
}

View File

@@ -46,7 +46,7 @@ class Lyrics : public Screen<Scrollpad>
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void Update();

View File

@@ -99,6 +99,7 @@ void MediaLibrary::Resize()
Albums->Resize(itsMiddleColWidth, MainHeight);
Songs->Resize(itsRightColWidth, MainHeight);
Artists->MoveTo(0, MainStartY);
Albums->MoveTo(itsMiddleColStartX, MainStartY);
Songs->MoveTo(itsRightColStartX, MainStartY);
@@ -153,9 +154,9 @@ void MediaLibrary::SwitchTo()
UpdateSongList(Songs);
}
std::string MediaLibrary::Title()
std::basic_string<my_char_t> MediaLibrary::Title()
{
return "Media library";
return U("Media library");
}
void MediaLibrary::Update()

View File

@@ -40,7 +40,7 @@ class MediaLibrary : public Screen<Window>
virtual void SwitchTo();
virtual void Resize();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void Refresh();
virtual void Update();

View File

@@ -115,26 +115,24 @@ int main(int argc, char *argv[])
InitScreen("ncmpc++ ver. "VERSION, Config.colors_enabled);
MainStartY = 2;
MainHeight = LINES-4;
bool real_header_visibility = Config.header_visibility;
bool real_statusbar_visibility = Config.statusbar_visibility;
if (!Config.header_visibility)
if (Config.new_design)
{
MainStartY -= 2;
MainHeight += 2;
Config.header_visibility = 1;
Config.statusbar_visibility = 0;
}
if (!Config.statusbar_visibility)
MainHeight++;
size_t header_height, footer_start_y, footer_height;
SetWindowsDimensions(header_height, footer_start_y, footer_height);
if (Config.header_visibility)
{
wHeader = new Window(0, 0, COLS, 1, "", Config.header_color, brNone);
wHeader = new Window(0, 0, COLS, header_height, "", Config.header_color, brNone);
wHeader->Display();
}
size_t footer_start_y = LINES-(Config.statusbar_visibility ? 2 : 1);
size_t footer_height = Config.statusbar_visibility ? 2 : 1;
wFooter = new Window(0, footer_start_y, COLS, footer_height, "", Config.statusbar_color, brNone);
wFooter->SetTimeout(ncmpcpp_window_timeout);
wFooter->SetGetStringHelper(StatusbarGetStringHelper);
@@ -150,6 +148,7 @@ int main(int argc, char *argv[])
int input;
bool main_exit = 0;
bool design_changed = 0;
bool title_allowed = !Config.display_screens_numbers_on_start;
std::string screen_title;
@@ -201,7 +200,19 @@ int main(int argc, char *argv[])
{
if (title_allowed)
{
*wHeader << XY(0, 0) << wclrtoeol << fmtBold << myScreen->Title() << fmtBoldEnd;
if (Config.new_design)
{
std::basic_string<my_char_t> title = myScreen->Title();
*wHeader << XY(0, 3) << wclrtoeol;
*wHeader << fmtBold << clBlack;
mvwhline(wHeader->Raw(), 2, 0, 0, COLS);
mvwhline(wHeader->Raw(), 4, 0, 0, COLS);
*wHeader << XY((COLS-Window::Length(title))/2, 3);
*wHeader << Config.statusbar_color << title << clEnd;
*wHeader << clEnd << fmtBoldEnd;
}
else
*wHeader << XY(0, 0) << wclrtoeol << fmtBold << myScreen->Title() << fmtBoldEnd;
}
else
{
@@ -286,6 +297,24 @@ int main(int argc, char *argv[])
// key mapping beginning
if (Keypressed(input, Key.ToggleInterface))
{
Config.new_design = !Config.new_design;
if (Config.new_design)
{
Config.header_visibility = 1;
Config.statusbar_visibility = 0;
}
else
{
Config.header_visibility = real_header_visibility;
Config.statusbar_visibility = real_statusbar_visibility;
}
SetWindowsDimensions(header_height, footer_start_y, footer_height);
UnlockProgressbar();
UnlockStatusbar();
design_changed = 1;
}
if (Keypressed(input, Key.Up))
{
myScreen->Scroll(wUp, Key.Up);
@@ -328,9 +357,9 @@ int main(int argc, char *argv[])
UpdateStatusImmediately = 1;
}
else if (mouse_event.bstate & BUTTON1_PRESSED
&& Config.statusbar_visibility
&& (Config.statusbar_visibility || Config.new_design)
&& Mpd.GetState() > psStop
&& mouse_event.y == LINES-1 && mouse_event.x < 9
&& mouse_event.y == (Config.new_design ? 1 : LINES-1) && mouse_event.x < 9
) // playing/paused
{
Mpd.Pause();
@@ -349,7 +378,7 @@ int main(int argc, char *argv[])
else
myScreen->MouseButtonPressed(mouse_event);
}
else if (input == KEY_RESIZE)
else if (input == KEY_RESIZE || design_changed)
{
# ifdef USE_PDCURSES
resize_term(0, 0);
@@ -364,7 +393,7 @@ int main(int argc, char *argv[])
return 1;
}
MainHeight = LINES-4;
MainHeight = LINES-(Config.new_design ? 7 : 4);
if (!Config.header_visibility)
MainHeight += 2;
@@ -392,19 +421,30 @@ int main(int argc, char *argv[])
myScreen->Resize();
if (Config.header_visibility)
wHeader->Resize(COLS, wHeader->GetHeight());
wHeader->Resize(COLS, header_height);
footer_start_y = LINES-(Config.statusbar_visibility ? 2 : 1);
wFooter->MoveTo(0, footer_start_y);
wFooter->Resize(COLS, wFooter->GetHeight());
wFooter->Resize(COLS, Config.statusbar_visibility ? 2 : 1);
myScreen->Refresh();
RedrawStatusbar = 1;
StatusChanges changes;
if (Mpd.GetState() < psPlay)
if (Mpd.GetState() < psPlay || design_changed)
{
changes.PlayerState = 1;
if (design_changed)
changes.Volume = 1;
}
changes.StatusFlags = 1; // force status update
NcmpcppStatusChanged(&Mpd, changes, NULL);
NcmpcppStatusChanged(&Mpd, changes, 0);
if (design_changed)
{
RedrawStatusbar = 1;
NcmpcppStatusChanged(&Mpd, StatusChanges(), 0);
design_changed = 0;
ShowMessage("User interface: %s", Config.new_design ? "Alternative" : "Classic");
}
}
else if (Keypressed(input, Key.GoToParentDir))
{
@@ -1071,9 +1111,21 @@ int main(int argc, char *argv[])
songpos = 0;
}
std::string tracklength;
*wFooter << fmtBold;
std::string tracklength = "[" + Song::ShowTime(songpos) + "/" + s->GetLength() + "]";
*wFooter << XY(wFooter->GetWidth()-tracklength.length(), 1) << tracklength;
if (Config.new_design)
{
tracklength = Song::ShowTime(songpos);
tracklength += "/";
tracklength += s->GetLength();
*wHeader << XY(0, 0) << tracklength << " ";
wHeader->Refresh();
}
else
{
tracklength = "[" + Song::ShowTime(songpos) + "/" + s->GetLength() + "]";
*wFooter << XY(wFooter->GetWidth()-tracklength.length(), 1) << tracklength;
}
double progressbar_size = songpos/double(s->GetTotalLength());
int howlong = wFooter->GetWidth()*progressbar_size;

View File

@@ -61,12 +61,13 @@ void Outputs::SwitchTo()
void Outputs::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
std::string Outputs::Title()
std::basic_string<my_char_t> Outputs::Title()
{
return "Outputs";
return U("Outputs");
}
void Outputs::EnterPressed()

View File

@@ -37,7 +37,7 @@ class Outputs : public Screen< Menu<MPD::Output> >
virtual void SwitchTo();
virtual void Resize();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void EnterPressed();
virtual void SpacePressed() { }

View File

@@ -105,6 +105,7 @@ void Playlist::SwitchTo()
void Playlist::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
w->SetTitle(Config.columns_in_playlist ? Display::Columns() : "");
SortDialogHeight = std::min(int(MainHeight-2), 18);
if (MainHeight > 6)
@@ -113,12 +114,12 @@ void Playlist::Resize()
hasToBeResized = 0;
}
std::string Playlist::Title()
std::basic_string<my_char_t> Playlist::Title()
{
std::string result = "Playlist ";
std::basic_string<my_char_t> result = U("Playlist ");
if (ReloadTotalLength || ReloadRemaining)
itsBufferedStats = TotalLength();
result += TO_STRING(Scroller(itsBufferedStats, w->GetWidth()-result.length()-VolumeState.length(), itsScrollBegin));
result += Scroller(itsBufferedStats, w->GetWidth()-result.length()-(Config.new_design ? 2 : VolumeState.length()), itsScrollBegin);
return result;
}

View File

@@ -36,7 +36,7 @@ class Playlist : public Screen< Menu<MPD::Song> >
virtual void SwitchTo();
virtual void Resize();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void EnterPressed();
virtual void SpacePressed();

View File

@@ -75,14 +75,15 @@ void PlaylistEditor::Resize()
Playlists->Resize(LeftColumnWidth, MainHeight);
Content->Resize(RightColumnWidth, MainHeight);
Playlists->MoveTo(0, MainStartY);
Content->MoveTo(RightColumnStartX, MainStartY);
hasToBeResized = 0;
}
std::string PlaylistEditor::Title()
std::basic_string<my_char_t> PlaylistEditor::Title()
{
return "Playlist editor";
return U("Playlist editor");
}
void PlaylistEditor::Refresh()

View File

@@ -29,7 +29,7 @@ class PlaylistEditor : public Screen<Window>
virtual void SwitchTo();
virtual void Resize();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void Refresh();
virtual void Update();

View File

@@ -39,7 +39,7 @@ class BasicScreen
virtual void SwitchTo() = 0;
virtual void Resize() = 0;
virtual std::string Title() = 0;
virtual std::basic_string<my_char_t> Title() = 0;
virtual void Update() { }
virtual void Refresh() = 0;

View File

@@ -57,6 +57,7 @@ void SearchEngine::Init()
void SearchEngine::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
@@ -83,9 +84,9 @@ void SearchEngine::SwitchTo()
}
}
std::string SearchEngine::Title()
std::basic_string<my_char_t> SearchEngine::Title()
{
return "Search engine";
return U("Search engine");
}
void SearchEngine::EnterPressed()

View File

@@ -43,7 +43,7 @@ class SearchEngine : public Screen< Menu< std::pair<Buffer *, MPD::Song *> > >
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void EnterPressed();
virtual void SpacePressed();

View File

@@ -25,6 +25,7 @@
#endif // WIN32
#include <fstream>
#include "global.h"
#include "helpers.h"
#include "lyrics.h"
#include "settings.h"
@@ -60,17 +61,6 @@ namespace
key[1] = !two.empty() && two[0] == '\'' ? two[1] : (atoi(two.c_str()) == 0 ? null_key : atoi(two.c_str()));
}
void String2Buffer(const std::string &s, Buffer &buf)
{
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it)
{
if (*it != '$')
buf << *it;
else
buf << Color(*++it-'0');
}
}
Border IntoBorder(const std::string &color)
{
return Border(IntoColor(color));
@@ -86,6 +76,24 @@ void CreateConfigDir()
);
}
void SetWindowsDimensions(size_t &header_height, size_t &footer_start_y, size_t &footer_height)
{
Global::MainStartY = Config.new_design ? 5 : 2;
Global::MainHeight = LINES-(Config.new_design ? 7 : 4);
if (!Config.header_visibility)
{
Global::MainStartY -= 2;
Global::MainHeight += 2;
}
if (!Config.statusbar_visibility)
Global::MainHeight++;
header_height = Config.new_design ? 5 : 1;
footer_start_y = LINES-(Config.statusbar_visibility ? 2 : 1);
footer_height = Config.statusbar_visibility ? 2 : 1;
}
void DefaultKeys(ncmpcpp_keys &keys)
{
keys.Up[0] = KEY_UP;
@@ -152,6 +160,7 @@ void DefaultKeys(ncmpcpp_keys &keys)
keys.GoToContainingDir[0] = 'G';
keys.ToggleAutoCenter[0] = 'U';
keys.ToggleDisplayMode[0] = 'p';
keys.ToggleInterface[0] = '\\';
keys.ToggleLyricsDB[0] = 'L';
keys.GoToParentDir[0] = KEY_BACKSPACE;
keys.SwitchTagTypeList[0] = '`';
@@ -221,6 +230,7 @@ void DefaultKeys(ncmpcpp_keys &keys)
keys.GoToContainingDir[1] = null_key;
keys.ToggleAutoCenter[1] = null_key;
keys.ToggleDisplayMode[1] = null_key;
keys.ToggleInterface[1] = null_key;
keys.ToggleLyricsDB[1] = null_key;
keys.GoToParentDir[1] = 127;
keys.SwitchTagTypeList[1] = null_key;
@@ -237,6 +247,8 @@ void DefaultConfiguration(ncmpcpp_config &conf)
conf.song_window_title_format = "{%a - }{%t}|{%f}";
conf.song_library_format = "{%n - }{%t}|{%f}";
conf.tag_editor_album_format = "{(%y) }%b";
conf.new_header_first_line = "$b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b";
conf.new_header_second_line = "{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}";
conf.browser_playlist_prefix << clRed << "(playlist)" << clEnd << ' ';
conf.pattern = "%n - %t";
conf.selected_item_prefix << clMagenta;
@@ -284,6 +296,7 @@ void DefaultConfiguration(ncmpcpp_config &conf)
conf.allow_physical_files_deletion = false;
conf.allow_physical_directories_deletion = false;
conf.mouse_support = true;
conf.new_design = false;
conf.set_window_title = true;
conf.mpd_port = 6600;
conf.mpd_connection_timeout = 15;
@@ -546,6 +559,16 @@ void ReadConfiguration(ncmpcpp_config &conf)
if (!v.empty())
conf.execute_on_song_change = v;
}
else if (cl.find("alternative_header_first_line_format") != std::string::npos)
{
if (!v.empty())
conf.new_header_first_line = v;
}
else if (cl.find("alternative_header_second_line_format") != std::string::npos)
{
if (!v.empty())
conf.new_header_second_line = v;
}
else if (cl.find("browser_playlist_prefix") != std::string::npos)
{
if (!v.empty())
@@ -693,6 +716,10 @@ void ReadConfiguration(ncmpcpp_config &conf)
{
conf.mouse_support = v == "yes";
}
else if (cl.find("user_interface") != std::string::npos)
{
conf.new_design = v == "alternative";
}
else if (cl.find("enable_window_title") != std::string::npos)
{
conf.set_window_title = v == "yes";

View File

@@ -111,6 +111,7 @@ struct ncmpcpp_keys
int GoToContainingDir[2];
int ToggleAutoCenter[2];
int ToggleDisplayMode[2];
int ToggleInterface[2];
int ToggleLyricsDB[2];
int GoToParentDir[2];
int SwitchTagTypeList[2];
@@ -131,6 +132,8 @@ struct ncmpcpp_config
std::string external_editor;
std::string system_encoding;
std::string execute_on_song_change;
std::string new_header_first_line;
std::string new_header_second_line;
std::string pattern;
@@ -187,6 +190,7 @@ struct ncmpcpp_config
bool allow_physical_files_deletion;
bool allow_physical_directories_deletion;
bool mouse_support;
bool new_design;
int mpd_port;
int mpd_connection_timeout;
@@ -204,6 +208,7 @@ extern ncmpcpp_config Config;
extern ncmpcpp_keys Key;
void CreateConfigDir();
void SetWindowsDimensions(size_t &header_height, size_t &footer_start_y, size_t &footer_height);
void DefaultKeys(ncmpcpp_keys &);
void DefaultConfiguration(ncmpcpp_config &);
void ReadKeys(ncmpcpp_keys &);

View File

@@ -168,6 +168,8 @@ void NcmpcppErrorCallback(Connection *, int errorid, const char *msg, void *)
void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
{
static size_t playing_song_scroll_begin = 0;
static size_t first_line_scroll_begin = 0;
static size_t second_line_scroll_begin = 0;
static std::string player_state;
static int elapsed;
static MPD::Song np;
@@ -315,14 +317,14 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
case psPlay:
{
WindowTitle(utf_to_locale_cpy(np.toString(Config.song_window_title_format)));
player_state = "Playing: ";
player_state = Config.new_design ? "[playing]" : "Playing: ";
Playlist::ReloadRemaining = 1;
changed.ElapsedTime = 1;
break;
}
case psPause:
{
player_state = "[Paused] ";
player_state = Config.new_design ? "[paused] " : "[Paused] ";
break;
}
case psStop:
@@ -333,11 +335,24 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
wFooter->SetColor(Config.statusbar_color);
Playlist::ReloadRemaining = 1;
myPlaylist->NowPlaying = -1;
player_state.clear();
if (Config.new_design)
{
*wHeader << XY(0, 0) << wclrtoeol << XY(0, 1) << wclrtoeol;
player_state = "[stopped]";
changed.Volume = 1;
changed.StatusFlags = 1;
}
else
player_state.clear();
break;
}
}
if (!block_statusbar_update && Config.statusbar_visibility)
if (Config.new_design)
{
*wHeader << XY(0, 1) << fmtBold << player_state << fmtBoldEnd;
wHeader->Refresh();
}
else if (!block_statusbar_update && Config.statusbar_visibility)
{
*wFooter << XY(0, 1);
if (player_state.empty())
@@ -351,6 +366,7 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
if (myPlaylist->isPlaying())
{
np = Mpd.GetCurrentSong();
if (!Config.execute_on_song_change.empty())
system(np.toString(Config.execute_on_song_change).c_str());
if (Mpd.GetState() > psStop)
@@ -367,11 +383,11 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
Playlist::ReloadRemaining = 1;
playing_song_scroll_begin = 0;
first_line_scroll_begin = 0;
second_line_scroll_begin = 0;
if (Mpd.GetState() == psPlay)
{
changed.ElapsedTime = 1;
}
}
static time_t now, past = 0;
time(&now);
@@ -383,7 +399,7 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
np = Mpd.GetCurrentSong();
WindowTitle(utf_to_locale_cpy(np.toString(Config.song_window_title_format)));
}
if (!np.Empty() && !player_state.empty())
if (!np.Empty() && Mpd.GetState() > psStop)
{
int mpd_elapsed = Mpd.GetElapsedTime();
if (elapsed < mpd_elapsed-2 || elapsed+1 > mpd_elapsed)
@@ -391,9 +407,43 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
else if (Mpd.GetState() == psPlay && !RedrawStatusbar)
elapsed++;
if (!block_statusbar_update && Config.statusbar_visibility)
std::string tracklength;
if (Config.new_design)
{
tracklength = Song::ShowTime(elapsed);
if (np.GetTotalLength())
{
tracklength += "/";
tracklength += np.GetLength();
}
basic_buffer<my_char_t> first, second;
String2Buffer(TO_WSTRING(np.toString(Config.new_header_first_line)), first);
String2Buffer(TO_WSTRING(np.toString(Config.new_header_second_line)), second);
size_t first_len = Window::Length(first.Str());
size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2;
size_t first_start = first_len < COLS-first_margin ? (COLS-first_len)/2 : tracklength.length()+1;
size_t second_len = Window::Length(second.Str());
size_t second_margin = (std::max(player_state.length(), size_t(8))+1)*2;
size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : player_state.length()+1;
if (!block_progressbar_update) // if blocked, seeking in progress
*wHeader << XY(0, 0) << wclrtoeol << tracklength;
*wHeader << XY(first_start, 0);
first.Write(*wHeader, first_line_scroll_begin, COLS-tracklength.length()-VolumeState.length()-1, U(" ** "));
*wHeader << XY(0, 1) << wclrtoeol << fmtBold << player_state << fmtBoldEnd;
*wHeader << XY(second_start, 1);
second.Write(*wHeader, second_line_scroll_begin, COLS-player_state.length()-8-2, U(" ** "));
*wHeader << XY(wHeader->GetWidth()-VolumeState.length(), 0) << Config.volume_color << VolumeState << clEnd;
changed.StatusFlags = 1;
}
else if (!block_statusbar_update && Config.statusbar_visibility)
{
std::string tracklength;
if (np.GetTotalLength())
{
tracklength = " [";
@@ -478,38 +528,54 @@ void NcmpcppStatusChanged(Connection *, StatusChanges changed, void *)
{
std::string switch_state;
if (mpd_repeat)
switch_state += mpd_repeat;
if (mpd_random)
switch_state += mpd_random;
if (mpd_single)
switch_state += mpd_single;
if (mpd_consume)
switch_state += mpd_consume;
if (mpd_crossfade)
switch_state += mpd_crossfade;
if (mpd_db_updating)
switch_state += mpd_db_updating;
// this is done by raw ncurses because creating another
// window only for handling this is quite silly
attrset(A_BOLD|COLOR_PAIR(Config.state_line_color));
mvhline(1, 0, 0, COLS);
if (!switch_state.empty())
if (Config.new_design)
{
mvprintw(1, COLS-switch_state.length()-3, "[");
attron(COLOR_PAIR(Config.state_flags_color));
mvprintw(1, COLS-switch_state.length()-2, "%s", switch_state.c_str());
attron(COLOR_PAIR(Config.state_line_color));
mvprintw(1, COLS-2, "]");
switch_state += '[';
switch_state += mpd_repeat ? mpd_repeat : '-';
switch_state += mpd_random ? mpd_random : '-';
switch_state += mpd_single ? mpd_single : '-';
switch_state += mpd_consume ? mpd_consume : '-';
switch_state += mpd_crossfade ? mpd_crossfade : '-';
switch_state += mpd_db_updating ? mpd_db_updating : '-';
switch_state += ']';
*wHeader << XY(COLS-switch_state.length(), 1) << fmtBold << Config.state_flags_color << switch_state << clEnd << fmtBoldEnd;
wHeader->Refresh();
}
else
{
if (mpd_repeat)
switch_state += mpd_repeat;
if (mpd_random)
switch_state += mpd_random;
if (mpd_single)
switch_state += mpd_single;
if (mpd_consume)
switch_state += mpd_consume;
if (mpd_crossfade)
switch_state += mpd_crossfade;
if (mpd_db_updating)
switch_state += mpd_db_updating;
// this is done by raw ncurses because creating another
// window only for handling this is quite silly
attrset(A_BOLD|COLOR_PAIR(Config.state_line_color));
mvhline(1, 0, 0, COLS);
if (!switch_state.empty())
{
mvprintw(1, COLS-switch_state.length()-3, "[");
attron(COLOR_PAIR(Config.state_flags_color));
mvprintw(1, COLS-switch_state.length()-2, "%s", switch_state.c_str());
attroff(COLOR_PAIR(Config.state_flags_color));
attron(COLOR_PAIR(Config.state_line_color));
mvprintw(1, COLS-2, "]");
}
attroff(A_BOLD|COLOR_PAIR(Config.state_line_color));
refresh();
}
attroff(A_BOLD|COLOR_PAIR(Config.state_line_color));
refresh();
}
if (changed.Volume && Config.header_visibility)
{
VolumeState = " Volume: ";
VolumeState = Config.new_design ? " Vol: " : " Volume: ";
int volume = Mpd.GetVolume();
if (volume < 0)
VolumeState += "n/a";

View File

@@ -58,6 +58,7 @@ namespace NCurses
bool SetFormatting(short vb, const std::basic_string<C> &s, short ve, bool for_each = 1);
void RemoveFormatting(short vb, const std::basic_string<C> &s, short ve, bool for_each = 1);
void SetTemp(std::basic_string<C> *);
void Write(Window &w, size_t &pos, size_t width, const std::basic_string<C> &sep);
void Clear();
template <typename T> basic_buffer<C> &operator<<(const T &t)
@@ -72,6 +73,9 @@ namespace NCurses
basic_buffer<C> &operator<<(const basic_buffer<C> &buf);
friend Window &operator<< <>(Window &, const basic_buffer<C> &);
private:
void LoadAttribute(Window &w, short value) const;
};
typedef basic_buffer<char> Buffer;
@@ -140,12 +144,71 @@ template <typename C> void NCurses::basic_buffer<C>::SetTemp(std::basic_string<C
itsTempString = tmp;
}
template <typename C> void NCurses::basic_buffer<C>::Write(Window &w, size_t &pos, size_t width, const std::basic_string<C> &sep)
{
std::basic_string<C> s = itsString.str();
size_t len = Window::Length(s);
if (len > width)
{
s += sep;
len = 0;
typename std::list<typename NCurses::basic_buffer<C>::FormatPos>::const_iterator lb = itsFormat.begin();
if (itsFormat.back().Position > pos) // if there is no attributes from current position, don't load them
{
// load all attributes that are before start position
for (; lb->Position < pos; ++lb)
LoadAttribute(w, lb->Value);
}
for (size_t i = pos; i < s.length() && len < width; ++i)
{
while (i == lb->Position && lb != itsFormat.end())
{
LoadAttribute(w, lb->Value);
++lb;
}
len += wcwidth(s[i]);
w << s[i];
}
if (++pos >= s.length())
pos = 0;
if (len < width)
lb = itsFormat.begin();
for (size_t i = 0; len < width; ++i)
{
while (i == lb->Position && lb != itsFormat.end())
{
LoadAttribute(w, lb->Value);
++lb;
}
len += wcwidth(s[i]);
w << s[i];
}
// load all remained attributes to clean up
for (; lb != itsFormat.end(); ++lb)
LoadAttribute(w, lb->Value);
}
else
w << *this;
}
template <typename C> void NCurses::basic_buffer<C>::Clear()
{
itsString.str(std::basic_string<C>());
itsFormat.clear();
}
template <typename C> void NCurses::basic_buffer<C>::LoadAttribute(Window &w, short value) const
{
if (value < NCurses::fmtNone)
w << NCurses::Color(value);
else
w << NCurses::Format(value);
}
template <typename C> NCurses::basic_buffer<C> &NCurses::basic_buffer<C>::operator<<(std::ostream &(*os)(std::ostream&))
{
itsString << os;
@@ -199,10 +262,7 @@ template <typename C> NCurses::Window &operator<<(NCurses::Window &w, const NCur
w << tmp;
tmp.clear();
}
if (b->Value < NCurses::fmtNone)
w << NCurses::Color(b->Value);
else
w << NCurses::Format(b->Value);
buf.LoadAttribute(w, b->Value);
b++;
}
if (i < s.length())

View File

@@ -58,6 +58,7 @@ void TinyTagEditor::Init()
void TinyTagEditor::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
hasToBeResized = 0;
}
@@ -86,9 +87,9 @@ void TinyTagEditor::SwitchTo()
}
}
std::string TinyTagEditor::Title()
std::basic_string<my_char_t> TinyTagEditor::Title()
{
return "Tiny tag editor";
return U("Tiny tag editor");
}
void TinyTagEditor::EnterPressed()
@@ -375,15 +376,17 @@ void TagEditor::Resize()
TagTypes->Resize(MiddleColumnWidth, MainHeight);
Tags->Resize(RightColumnWidth, MainHeight);
Albums->MoveTo(0, MainStartY);
Dirs->MoveTo(0, MainStartY);
TagTypes->MoveTo(MiddleColumnStartX, MainStartY);
Tags->MoveTo(RightColumnStartX, MainStartY);
hasToBeResized = 0;
}
std::string TagEditor::Title()
std::basic_string<my_char_t> TagEditor::Title()
{
return "Tag editor";
return U("Tag editor");
}
void TagEditor::SwitchTo()

View File

@@ -39,7 +39,7 @@ class TinyTagEditor : public Screen< Menu<Buffer> >
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void EnterPressed();
virtual void SpacePressed() { }
@@ -69,7 +69,7 @@ class TagEditor : public Screen<Window>
virtual void Resize();
virtual void SwitchTo();
virtual std::string Title();
virtual std::basic_string<my_char_t> Title();
virtual void Refresh();
virtual void Update();

View File

@@ -47,10 +47,12 @@
#ifdef _UTF8
# define my_char_t wchar_t
# define U(x) L##x
# define TO_STRING(x) ToString(x)
# define TO_WSTRING(x) ToWString(x)
#else
# define my_char_t char
# define U(x) x
# define TO_STRING(x) (x)
# define TO_WSTRING(x) (x)
#endif
@@ -155,6 +157,7 @@ namespace NCurses
virtual Window *Clone() const { return new Window(*this); }
virtual Window *EmptyClone() const;
static size_t Length(const std::string &s) { return s.length(); }
static size_t Length(const std::wstring &);
protected: