new feature: support for merging screens together

This commit is contained in:
Andrzej Rybczak
2011-11-12 19:47:47 +01:00
parent e31dec7005
commit 56467eaac6
44 changed files with 633 additions and 218 deletions

View File

@@ -349,6 +349,13 @@
#screen_switcher_mode = "sequence: 2 -> 3"
#
##
## Default width of locked screen (in %).
## Acceptable values are from 20 to 80.
##
#
#locked_screen_width_part = "50"
#
##
## Note: You can define startup screen for ncmpcpp
## by choosing screen number from the list above.
##

View File

@@ -249,9 +249,12 @@ If set to "playlist", Search engine will perform searching in current MPD playli
.B display_screens_numbers_on_start = yes/no
If enabled, screens' names and their keybindings will be shown in header window until key is pressed, otherwise they won't be displayed at all.
.TP
.B screen_switcher_previous = SWITCHER_MODE
.B screen_switcher_mode = SWITCHER_MODE
If set to "previous", key_screen_switcher will switch between current and last used screen. If set to "sequence: user_defined_sequence", it will switch between given sequence of screens. Syntax clarification can be found in example config file.
.TP
.B locked_screen_width_part = 20-80
If you want to lock a screen, ncmpcpp asks for % of locked screen's width to be reserved before that and provides a default value, which is the one you can set here.
.TP
.B startup_screen = SCREEN_NUMBER
Screen that has to be displayed at start (playlist by default).
.TP

View File

@@ -2,9 +2,9 @@ bin_PROGRAMS = ncmpcpp
ncmpcpp_SOURCES = browser.cpp charset.cpp clock.cpp conv.cpp curl_handle.cpp \
display.cpp error.cpp help.cpp helpers.cpp lastfm.cpp lastfm_service.cpp lyrics.cpp \
lyrics_fetcher.cpp media_library.cpp menu.cpp mpdpp.cpp ncmpcpp.cpp outputs.cpp \
playlist.cpp playlist_editor.cpp scrollpad.cpp search_engine.cpp sel_items_adder.cpp \
server_info.cpp settings.cpp song.cpp song_info.cpp status.cpp tag_editor.cpp \
tiny_tag_editor.cpp tolower.cpp visualizer.cpp window.cpp
playlist.cpp playlist_editor.cpp screen.cpp scrollpad.cpp search_engine.cpp \
sel_items_adder.cpp server_info.cpp settings.cpp song.cpp song_info.cpp status.cpp \
tag_editor.cpp tiny_tag_editor.cpp tolower.cpp visualizer.cpp window.cpp
# set the include path found by configure
INCLUDES= $(all_includes)

View File

@@ -59,7 +59,7 @@ void Browser::Init()
{
static Display::ScreenFormat sf = { this, &Config.song_list_format };
w = new Menu<MPD::Item>(0, MainStartY, COLS, MainHeight, Config.columns_in_browser && Config.titles_visibility ? Display::Columns() : "", Config.main_color, brNone);
w = new Menu<MPD::Item>(0, MainStartY, COLS, MainHeight, Config.columns_in_browser && Config.titles_visibility ? Display::Columns(COLS) : "", Config.main_color, brNone);
w->HighlightColor(Config.main_highlight_color);
w->CyclicScrolling(Config.use_cyclic_scrolling);
w->CenteredCursor(Config.centered_cursor);
@@ -73,14 +73,19 @@ void Browser::Init()
void Browser::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
w->SetTitle(Config.columns_in_browser && Config.titles_visibility ? Display::Columns() : "");
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
w->SetTitle(Config.columns_in_browser && Config.titles_visibility ? Display::Columns(w->GetWidth()) : "");
hasToBeResized = 0;
}
void Browser::SwitchTo()
{
using Global::myLockedScreen;
using Global::myInactiveScreen;
if (myScreen == this)
{
# ifndef WIN32
@@ -91,7 +96,10 @@ void Browser::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (isLocal()) // local browser doesn't support sorting by mtime
@@ -108,7 +116,7 @@ void Browser::SwitchTo()
std::basic_string<my_char_t> Browser::Title()
{
std::basic_string<my_char_t> result = U("Browse: ");
result += Scroller(TO_WSTRING(itsBrowsedDir), itsScrollBeginning, w->GetWidth()-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
result += Scroller(TO_WSTRING(itsBrowsedDir), itsScrollBeginning, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
return result;
}

View File

@@ -50,6 +50,8 @@ class Browser : public Screen< Menu<MPD::Item> >
virtual List *GetList() { return w; }
virtual bool isMergable() { return true; }
const std::string &CurrentDir() { return itsBrowsedDir; }
bool isLocal() { return itsBrowseLocally; }
@@ -65,6 +67,7 @@ class Browser : public Screen< Menu<MPD::Item> >
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
static bool hasSupportedExtension(const std::string &);

View File

@@ -54,47 +54,57 @@ void Clock::Init()
{
Width = Config.clock_display_seconds ? 60 : 40;
itsPane = new Window(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
w = new Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, Border(Config.main_color));
isInitialized = 1;
}
void Clock::Resize()
{
if (Width <= size_t(COLS) && Height <= MainHeight)
{
w->MoveTo((COLS-Width)/2, (MainHeight-Height)/2+MainStartY);
if (myScreen == this)
{
if (myPlaylist->hasToBeResized)
myPlaylist->Resize();
myPlaylist->Items->Hide();
w->Display();
}
}
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
// used for clearing area out of clock window while resizing terminal
itsPane->Resize(width, MainHeight);
itsPane->MoveTo(x_offset, MainStartY);
itsPane->Refresh();
if (Width <= width && Height <= MainHeight)
w->MoveTo(x_offset+(width-Width)/2, MainStartY+(MainHeight-Height)/2);
}
void Clock::SwitchTo()
{
if (Width > size_t(COLS) || Height > MainHeight)
{
ShowMessage("Screen is too small to display clock!");
return;
}
using Global::myLockedScreen;
if (myScreen == this)
return;
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width, false);
if (Width > width || Height > MainHeight)
{
ShowMessage("Screen is too small to display clock!");
if (myLockedScreen)
UpdateInactiveScreen(myLockedScreen);
return;
}
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
Global::myPrevScreen = myScreen;
myScreen = this;
myPlaylist->Items->Hide();
Global::RedrawHeader = 1;
Prepare();
itsPane->Refresh();
// clearing screen apparently fixes the problem with last digits being misrendered
w->Clear();
w->Display();
@@ -107,8 +117,20 @@ std::basic_string<my_char_t> Clock::Title()
void Clock::Update()
{
if (Width > size_t(COLS) || Height > MainHeight)
myPlaylist->SwitchTo();
if (Width > itsPane->GetWidth() || Height > MainHeight)
{
using Global::myLockedScreen;
using Global::myInactiveScreen;
if (myLockedScreen)
{
if (myInactiveScreen != myLockedScreen)
myScreen = myInactiveScreen;
myLockedScreen->SwitchTo();
}
else
myPlaylist->SwitchTo();
}
static timeval past = { 0, 0 };
gettimeofday(&past, 0);

View File

@@ -50,10 +50,15 @@ class Clock : public Screen<Window>
virtual List *GetList() { return 0; }
virtual bool isMergable() { return true; }
protected:
virtual void Init();
virtual bool isLockable() { return false; }
private:
Window *itsPane;
static void Prepare();
static void Set(int, int);

View File

@@ -69,7 +69,7 @@ namespace
}
}
std::string Display::Columns()
std::string Display::Columns(size_t list_width)
{
if (Config.columns.empty())
return "";
@@ -86,11 +86,11 @@ std::string Display::Columns()
for (std::vector<Column>::const_iterator it = Config.columns.begin(); it != Config.columns.end(); ++it)
{
if (it == Config.columns.end()-1)
width = COLS-where;
width = list_width-where;
else if (last_fixed && it == next2last)
width = COLS-where-1-(++next2last)->width;
width = list_width-where-1-(++next2last)->width;
else
width = it->width*(it->fixed ? 1 : COLS/100.0);
width = it->width*(it->fixed ? 1 : list_width/100.0);
std::basic_string<my_char_t> tag;
if (it->type.length() >= 1 && it->name.empty())
@@ -122,6 +122,7 @@ std::string Display::Columns()
else
result.resize(std::min(where+1, size_t(COLS)), ' ');
}
result.resize(list_width);
return TO_STRING(result);
}
@@ -175,9 +176,9 @@ void Display::SongsInColumns(const MPD::Song &s, void *data, Menu<MPD::Song> *me
if (it == Config.columns.end()-1)
width = menu->GetWidth()-where;
else if (last_fixed && it == next2last)
width = COLS-where-1-(++next2last)->width;
width = menu->GetWidth()-where-1-(++next2last)->width;
else
width = it->width*(it->fixed ? 1 : COLS/100.0);
width = it->width*(it->fixed ? 1 : menu->GetWidth()/100.0);
MPD::Song::GetFunction get = 0;

View File

@@ -34,7 +34,7 @@ namespace Display
std::string *format;
};
std::string Columns();
std::string Columns(size_t);
template <typename T> void Generic(const T &t, void *, Menu<T> *menu)
{

View File

@@ -30,6 +30,8 @@ namespace Global
extern BasicScreen *myScreen;
extern BasicScreen *myOldScreen; // for info, lyrics, popups
extern BasicScreen *myPrevScreen; // "real" screen switching (browser, search, etc.)
extern BasicScreen *myLockedScreen; // points at the screen that was locked (or is null if no screen is locked)
extern BasicScreen *myInactiveScreen; // points at inactive screen, if locking was enabled and two screens are displayed
extern Window *wHeader;
extern Window *wFooter;

View File

@@ -40,14 +40,17 @@ void Help::Init()
void Help::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}
void Help::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
if (myScreen == this)
return;
@@ -55,7 +58,10 @@ void Help::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -211,6 +217,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.GoToMediaLibrary) << "Locate current song in media library\n";
*w << DisplayKeys(Key.ToggleScreenLock) << "Lock/unlock current screen\n";
# ifdef HAVE_TAGLIB_H
*w << DisplayKeys(Key.GoToTagEditor) << "Locate current song in tag editor\n";
# endif // HAVE_TAGLIB_H

View File

@@ -40,8 +40,11 @@ class Help : public Screen<Scrollpad>
virtual List *GetList() { return 0; }
virtual bool isMergable() { return true; }
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
std::string DisplayKeys(int *, int = 2);

View File

@@ -461,3 +461,28 @@ std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, s
return result;
}
bool SwitchToNextColumn(BasicScreen *screen)
{
if (screen == myLibrary)
return myLibrary->NextColumn();
else if (screen == myPlaylistEditor)
return myPlaylistEditor->NextColumn();
# ifdef HAVE_TAGLIB_H
else if (screen == myTagEditor)
return myTagEditor->NextColumn();
# endif // HAVE_TAGLIB_H
return false;
}
bool SwitchToPrevColumn(BasicScreen *screen)
{
if (screen == myLibrary)
return myLibrary->PrevColumn();
else if (screen == myPlaylistEditor)
return myPlaylistEditor->PrevColumn();
# ifdef HAVE_TAGLIB_H
else if (screen == myTagEditor)
return myTagEditor->PrevColumn();
# endif // HAVE_TAGLIB_H
return false;
}

View File

@@ -219,5 +219,8 @@ std::string GetLineValue(std::string &, char = '"', char = '"', bool = 0);
std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, size_t &pos, size_t width);
bool SwitchToNextColumn(BasicScreen *);
bool SwitchToPrevColumn(BasicScreen *);
#endif

View File

@@ -38,8 +38,6 @@
using Global::MainHeight;
using Global::MainStartY;
using Global::myScreen;
using Global::myOldScreen;
Lastfm *myLastfm = new Lastfm;
@@ -51,8 +49,10 @@ void Lastfm::Init()
void Lastfm::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}
@@ -79,13 +79,20 @@ void Lastfm::Take()
void Lastfm::SwitchTo()
{
using Global::myScreen;
using Global::myOldScreen;
using Global::myLockedScreen;
if (myScreen == this)
return myOldScreen->SwitchTo();
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
// get an old info if it waits

View File

@@ -52,6 +52,8 @@ class Lastfm : public Screen<Scrollpad>
virtual List *GetList() { return 0; }
virtual bool isMergable() { return true; }
void Refetch();
bool isDownloading() { return isDownloadInProgress && !isReadyToTake; }
@@ -59,6 +61,7 @@ class Lastfm : public Screen<Scrollpad>
protected:
virtual void Init();
virtual bool isLockable() { return false; }
private:
std::basic_string<my_char_t> itsTitle;

View File

@@ -65,8 +65,10 @@ void Lyrics::Init()
void Lyrics::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}
@@ -98,6 +100,9 @@ void Lyrics::Update()
void Lyrics::SwitchTo()
{
using Global::myLockedScreen;
using Global::myInactiveScreen;
if (myScreen == this)
return myOldScreen->SwitchTo();
@@ -134,14 +139,25 @@ void Lyrics::SwitchTo()
Global::RedrawHeader = 1;
}
else
{
ShowMessage("Song must have both artist and title tag set!");
return;
}
}
// if we resize for locked screen, we have to do that in the end since
// fetching lyrics may fail (eg. if tags are missing) and we don't want
// to adjust screen size then.
if (myLockedScreen)
{
UpdateInactiveScreen(this);
Resize();
}
}
std::basic_string<my_char_t> Lyrics::Title()
{
std::basic_string<my_char_t> result = U("Lyrics: ");
result += Scroller(TO_WSTRING(itsSong.toString("{%a - %t}")), itsScrollBegin, w->GetWidth()-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
result += Scroller(TO_WSTRING(itsSong.toString("{%a - %t}")), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
return result;
}

View File

@@ -51,6 +51,8 @@ class Lyrics : public Screen<Scrollpad>
virtual List *GetList() { return 0; }
virtual bool isMergable() { return true; }
void Edit();
void Refetch();
@@ -63,6 +65,7 @@ class Lyrics : public Screen<Scrollpad>
protected:
virtual void Init();
virtual bool isLockable() { return false; }
private:
void Load();

View File

@@ -36,6 +36,7 @@ using Global::myScreen;
MediaLibrary *myLibrary = new MediaLibrary;
bool MediaLibrary::hasTwoColumns;
size_t MediaLibrary::itsLeftColStartX;
size_t MediaLibrary::itsLeftColWidth;
size_t MediaLibrary::itsMiddleColWidth;
size_t MediaLibrary::itsMiddleColStartX;
@@ -93,27 +94,30 @@ void MediaLibrary::Init()
void MediaLibrary::Resize()
{
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
if (!hasTwoColumns)
{
itsLeftColWidth = COLS/3-1;
itsMiddleColStartX = itsLeftColWidth+1;
itsMiddleColWidth = COLS/3;
itsRightColStartX = itsLeftColWidth+itsMiddleColWidth+2;
itsRightColWidth = COLS-COLS/3*2-1;
itsLeftColStartX = x_offset;
itsLeftColWidth = width/3-1;
itsMiddleColStartX = itsLeftColStartX+itsLeftColWidth+1;
itsMiddleColWidth = width/3;
itsRightColStartX = itsMiddleColStartX+itsMiddleColWidth+1;
itsRightColWidth = width-width/3*2-1;
}
else
{
itsMiddleColStartX = 0;
itsMiddleColWidth = COLS/2;
itsRightColStartX = itsMiddleColWidth+1;
itsRightColWidth = COLS-itsMiddleColWidth-1;
itsMiddleColStartX = x_offset;
itsMiddleColWidth = width/2;
itsRightColStartX = x_offset+itsMiddleColWidth+1;
itsRightColWidth = width-itsMiddleColWidth-1;
}
Artists->Resize(itsLeftColWidth, MainHeight);
Albums->Resize(itsMiddleColWidth, MainHeight);
Songs->Resize(itsRightColWidth, MainHeight);
Artists->MoveTo(0, MainStartY);
Artists->MoveTo(itsLeftColStartX, MainStartY);
Albums->MoveTo(itsMiddleColStartX, MainStartY);
Songs->MoveTo(itsRightColStartX, MainStartY);
@@ -136,6 +140,8 @@ void MediaLibrary::Refresh()
void MediaLibrary::SwitchTo()
{
using Global::myLockedScreen;
if (myScreen == this)
{
if (Config.media_library_disable_two_column_mode)
@@ -169,7 +175,10 @@ void MediaLibrary::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -544,18 +553,18 @@ void MediaLibrary::ApplyFilter(const std::string &s)
GetList()->ApplyFilter(s, 0, REG_ICASE | Config.regex_type);
}
void MediaLibrary::NextColumn()
bool MediaLibrary::NextColumn()
{
if (w == Artists)
{
if (!hasTwoColumns && Songs->ReallyEmpty())
return;
return false;
Artists->HighlightColor(Config.main_highlight_color);
w->Refresh();
w = Albums;
Albums->HighlightColor(Config.active_column_color);
if (!Albums->ReallyEmpty())
return;
return true;
}
if (w == Albums && !Songs->ReallyEmpty())
{
@@ -563,10 +572,12 @@ void MediaLibrary::NextColumn()
w->Refresh();
w = Songs;
Songs->HighlightColor(Config.active_column_color);
return true;
}
return false;
}
void MediaLibrary::PrevColumn()
bool MediaLibrary::PrevColumn()
{
if (w == Songs)
{
@@ -575,7 +586,7 @@ void MediaLibrary::PrevColumn()
w = Albums;
Albums->HighlightColor(Config.active_column_color);
if (!Albums->ReallyEmpty())
return;
return true;
}
if (w == Albums && !hasTwoColumns)
{
@@ -583,7 +594,9 @@ void MediaLibrary::PrevColumn()
w->Refresh();
w = Artists;
Artists->HighlightColor(Config.active_column_color);
return true;
}
return false;
}
void MediaLibrary::LocateSong(const MPD::Song &s)

View File

@@ -66,9 +66,11 @@ class MediaLibrary : public Screen<Window>
virtual List *GetList();
virtual bool isMergable() { return true; }
int Columns() { return hasTwoColumns ? 2 : 3; }
void NextColumn();
void PrevColumn();
bool NextColumn();
bool PrevColumn();
void LocateSong(const MPD::Song &);
@@ -78,6 +80,7 @@ class MediaLibrary : public Screen<Window>
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
void AddToPlaylist(bool);
@@ -92,6 +95,7 @@ class MediaLibrary : public Screen<Window>
static bool SortAllTracks(MPD::Song *, MPD::Song *);
static bool hasTwoColumns;
static size_t itsLeftColStartX;
static size_t itsLeftColWidth;
static size_t itsMiddleColWidth;
static size_t itsMiddleColStartX;

View File

@@ -75,6 +75,8 @@ using namespace MPD;
BasicScreen *Global::myScreen;
BasicScreen *Global::myOldScreen;
BasicScreen *Global::myPrevScreen;
BasicScreen *Global::myLockedScreen;
BasicScreen *Global::myInactiveScreen;
Window *Global::wHeader;
Window *Global::wFooter;
@@ -107,6 +109,40 @@ namespace
}
}
void set_resize_flags()
{
myHelp->hasToBeResized = 1;
myPlaylist->hasToBeResized = 1;
myBrowser->hasToBeResized = 1;
mySearcher->hasToBeResized = 1;
myLibrary->hasToBeResized = 1;
myPlaylistEditor->hasToBeResized = 1;
myLyrics->hasToBeResized = 1;
mySelectedItemsAdder->hasToBeResized = 1;
mySongInfo->hasToBeResized = 1;
# ifdef HAVE_CURL_CURL_H
myLastfm->hasToBeResized = 1;
# endif // HAVE_CURL_CURL_H
# ifdef HAVE_TAGLIB_H
myTinyTagEditor->hasToBeResized = 1;
myTagEditor->hasToBeResized = 1;
# endif // HAVE_TAGLIB_H
# ifdef ENABLE_VISUALIZER
myVisualizer->hasToBeResized = 1;
# endif // ENABLE_VISUALIZER
# ifdef ENABLE_OUTPUTS
myOutputs->hasToBeResized = 1;
# endif // ENABLE_OUTPUTS
# ifdef ENABLE_CLOCK
myClock->hasToBeResized = 1;
# endif // ENABLE_CLOCK
}
void resize_screen()
{
order_resize = 0;
@@ -139,38 +175,9 @@ namespace
if (!Config.statusbar_visibility)
MainHeight++;
myHelp->hasToBeResized = 1;
myPlaylist->hasToBeResized = 1;
myBrowser->hasToBeResized = 1;
mySearcher->hasToBeResized = 1;
myLibrary->hasToBeResized = 1;
myPlaylistEditor->hasToBeResized = 1;
myLyrics->hasToBeResized = 1;
mySelectedItemsAdder->hasToBeResized = 1;
mySongInfo->hasToBeResized = 1;
set_resize_flags();
# ifdef HAVE_CURL_CURL_H
myLastfm->hasToBeResized = 1;
# endif // HAVE_CURL_CURL_H
# ifdef HAVE_TAGLIB_H
myTinyTagEditor->hasToBeResized = 1;
myTagEditor->hasToBeResized = 1;
# endif // HAVE_TAGLIB_H
# ifdef ENABLE_VISUALIZER
myVisualizer->hasToBeResized = 1;
# endif // ENABLE_VISUALIZER
# ifdef ENABLE_OUTPUTS
myOutputs->hasToBeResized = 1;
# endif // ENABLE_OUTPUTS
# ifdef ENABLE_CLOCK
myClock->hasToBeResized = 1;
# endif // ENABLE_CLOCK
myScreen->Resize();
ApplyToVisibleWindows(&BasicScreen::Resize);
if (Config.header_visibility || Config.new_design)
wHeader->Resize(COLS, header_height);
@@ -179,7 +186,7 @@ namespace
wFooter->MoveTo(0, footer_start_y);
wFooter->Resize(COLS, Config.statusbar_visibility ? 2 : 1);
myScreen->Refresh();
ApplyToVisibleWindows(&BasicScreen::Refresh);
RedrawStatusbar = 1;
StatusChanges changes;
if (!Mpd.isPlaying() || design_changed)
@@ -201,6 +208,7 @@ namespace
ShowMessage("User interface: %s", Config.new_design ? "Alternative" : "Classic");
}
wFooter->Refresh();
refresh();
}
# if !defined(WIN32)
@@ -440,6 +448,7 @@ int main(int argc, char *argv[])
// header stuff end
if (input != ERR)
//ApplyToVisibleWindows(&BasicScreen::RefreshWindow);
myScreen->RefreshWindow();
wFooter->ReadKey(input);
@@ -450,9 +459,6 @@ int main(int argc, char *argv[])
RedrawHeader = 1;
title_allowed = 1;
if (myScreen == myPlaylist)
myPlaylist->EnableHighlighting();
// key mapping beginning
if (Keypressed(input, Key.Up))
@@ -607,53 +613,25 @@ int main(int argc, char *argv[])
{
myScreen->SpacePressed();
}
else if (Keypressed(input, Key.PrevColumn)
&& (myScreen == myLibrary
|| myScreen == myPlaylistEditor
# ifdef HAVE_TAGLIB_H
|| myScreen == myTagEditor
# endif // HAVE_TAGLIB_H)
)
)
else if (Keypressed(input, Key.PrevColumn) && SwitchToPrevColumn(myScreen)) { }
else if (Keypressed(input, Key.NextColumn) && SwitchToNextColumn(myScreen)) { }
else if (Keypressed(input, Key.PrevColumn) && myLockedScreen && myInactiveScreen && myScreen->isMergable())
{
if (myScreen == myLibrary)
if (myScreen != myLockedScreen)
{
myLibrary->PrevColumn();
myInactiveScreen = myScreen;
myScreen = myLockedScreen;
RedrawHeader = 1;
}
else if (myScreen == myPlaylistEditor)
{
myPlaylistEditor->PrevColumn();
}
# ifdef HAVE_TAGLIB_H
else if (myScreen == myTagEditor)
{
myTagEditor->PrevColumn();
}
# endif // HAVE_TAGLIB_H
}
else if (Keypressed(input, Key.NextColumn)
&& (myScreen == myLibrary
|| myScreen == myPlaylistEditor
# ifdef HAVE_TAGLIB_H
|| myScreen == myTagEditor
# endif // HAVE_TAGLIB_H)
)
)
else if (Keypressed(input, Key.NextColumn) && myLockedScreen && myInactiveScreen && myScreen->isMergable())
{
if (myScreen == myLibrary)
if (myScreen == myLockedScreen)
{
myLibrary->NextColumn();
myScreen = myInactiveScreen;
myInactiveScreen = myLockedScreen;
RedrawHeader = 1;
}
else if (myScreen == myPlaylistEditor)
{
myPlaylistEditor->NextColumn();
}
# ifdef HAVE_TAGLIB_H
else if (myScreen == myTagEditor)
{
myTagEditor->NextColumn();
}
# endif // HAVE_TAGLIB_H
}
else if (Keypressed(input, Key.VolumeUp))
{
@@ -1397,7 +1375,7 @@ int main(int argc, char *argv[])
if (Config.columns_in_playlist)
{
myPlaylist->Items->SetItemDisplayer(Display::SongsInColumns);
myPlaylist->Items->SetTitle(Config.titles_visibility ? Display::Columns() : "");
myPlaylist->Items->SetTitle(Config.titles_visibility ? Display::Columns(myPlaylist->Items->GetWidth()) : "");
myPlaylist->Items->SetGetStringFunction(Playlist::SongInColumnsToString);
}
else
@@ -1411,7 +1389,7 @@ int main(int argc, char *argv[])
{
Config.columns_in_browser = !Config.columns_in_browser;
ShowMessage("Browser display mode: %s", Config.columns_in_browser ? "Columns" : "Classic");
myBrowser->Main()->SetTitle(Config.columns_in_browser && Config.titles_visibility ? Display::Columns() : "");
myBrowser->Main()->SetTitle(Config.columns_in_browser && Config.titles_visibility ? Display::Columns(myBrowser->Main()->GetWidth()) : "");
}
else if (myScreen == mySearcher)
@@ -1419,7 +1397,7 @@ int main(int argc, char *argv[])
Config.columns_in_search_engine = !Config.columns_in_search_engine;
ShowMessage("Search engine display mode: %s", Config.columns_in_search_engine ? "Columns" : "Classic");
if (mySearcher->Main()->Size() > SearchEngine::StaticOptions)
mySearcher->Main()->SetTitle(Config.columns_in_search_engine && Config.titles_visibility ? Display::Columns() : "");
mySearcher->Main()->SetTitle(Config.columns_in_search_engine && Config.titles_visibility ? Display::Columns(mySearcher->Main()->GetWidth()) : "");
}
}
else if (Keypressed(input, Key.ToggleSeparatorsInPlaylist))
@@ -1736,6 +1714,35 @@ int main(int argc, char *argv[])
if (s)
myLibrary->LocateSong(*s);
}
else if (Keypressed(input, Key.ToggleScreenLock))
{
if (myLockedScreen != 0)
{
BasicScreen::Unlock();
set_resize_flags();
ShowMessage("Screen unlocked");
}
else
{
LockStatusbar();
Statusbar() << "% of the locked screen's width to be reserved (20-80): ";
std::string str_part = wFooter->GetString(IntoStr(Config.locked_screen_width_part*100));
UnlockStatusbar();
if (str_part.empty())
continue;
unsigned part = StrToInt(str_part);
if (part < 20 || part > 80)
{
ShowMessage("Invalid number!");
continue;
}
Config.locked_screen_width_part = part/100.0;
if (myScreen->Lock())
ShowMessage("Screen locked (with %d%% width)", part);
else
ShowMessage("Screen cannot be locked");
}
}
# ifdef HAVE_TAGLIB_H
else if (Keypressed(input, Key.GoToTagEditor))
{
@@ -2353,10 +2360,13 @@ int main(int argc, char *argv[])
}
}
if (myScreen == myPlaylist)
myPlaylist->EnableHighlighting();
# ifdef ENABLE_VISUALIZER
// visualizer sets timmeout to 40ms, but since only it needs such small
// value, we should restore defalt one after switching to another screen.
if (wFooter->GetTimeout() < ncmpcpp_window_timeout && myScreen != myVisualizer)
if (wFooter->GetTimeout() < ncmpcpp_window_timeout && !isVisible(myVisualizer))
wFooter->SetTimeout(ncmpcpp_window_timeout);
# endif // ENABLE_VISUALIZER
}

View File

@@ -45,13 +45,18 @@ void Outputs::Init()
void Outputs::SwitchTo()
{
using Global::myLockedScreen;
if (myScreen == this)
return;
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -64,8 +69,10 @@ void Outputs::SwitchTo()
void Outputs::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}

View File

@@ -48,10 +48,13 @@ class Outputs : public Screen< Menu<MPD::Output> >
virtual List *GetList() { return w; }
virtual bool isMergable() { return true; }
void FetchList();
protected:
virtual void Init();
virtual bool isLockable() { return true; }
};
extern Outputs *myOutputs;

View File

@@ -49,7 +49,7 @@ void Playlist::Init()
{
static Display::ScreenFormat sf = { this, &Config.song_list_format };
Items = new Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist && Config.titles_visibility ? Display::Columns() : "", Config.main_color, brNone);
Items = new Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist && Config.titles_visibility ? Display::Columns(COLS) : "", Config.main_color, brNone);
Items->CyclicScrolling(Config.use_cyclic_scrolling);
Items->CenteredCursor(Config.centered_cursor);
Items->HighlightColor(Config.main_highlight_color);
@@ -92,6 +92,8 @@ void Playlist::Init()
void Playlist::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
using Global::myInactiveScreen;
if (myScreen == this)
return;
@@ -101,7 +103,10 @@ void Playlist::SwitchTo()
itsScrollBegin = 0;
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -116,9 +121,12 @@ void Playlist::SwitchTo()
void Playlist::Resize()
{
Items->Resize(COLS, MainHeight);
Items->MoveTo(0, MainStartY);
Items->SetTitle(Config.columns_in_playlist && Config.titles_visibility ? Display::Columns() : "");
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
Items->Resize(width, MainHeight);
Items->MoveTo(x_offset, MainStartY);
Items->SetTitle(Config.columns_in_playlist && Config.titles_visibility ? Display::Columns(Items->GetWidth()) : "");
if (w == SortDialog) // if sorting window is active, playlist needs refreshing
Items->Display();
@@ -126,7 +134,7 @@ void Playlist::Resize()
if (Items->GetWidth() >= SortDialogWidth && MainHeight >= 5)
{
SortDialog->Resize(SortDialogWidth, SortDialogHeight);
SortDialog->MoveTo((COLS-SortDialogWidth)/2, (MainHeight-SortDialogHeight)/2+MainStartY);
SortDialog->MoveTo(x_offset+(width-SortDialogWidth)/2, (MainHeight-SortDialogHeight)/2+MainStartY);
}
else // if screen is too low to display sorting window, fall back to items list
w = Items;
@@ -139,7 +147,7 @@ std::basic_string<my_char_t> Playlist::Title()
std::basic_string<my_char_t> result = U("Playlist ");
if (ReloadTotalLength || ReloadRemaining)
itsBufferedStats = TotalLength();
result += Scroller(TO_WSTRING(itsBufferedStats), itsScrollBegin, Items->GetWidth()-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
result += Scroller(TO_WSTRING(itsBufferedStats), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
return result;
}

View File

@@ -55,6 +55,8 @@ class Playlist : public Screen<Window>
virtual List *GetList() { return w == Items ? Items : 0; }
virtual bool isMergable() { return true; }
bool isPlaying() { return NowPlaying >= 0 && !Items->Empty(); }
const MPD::Song *NowPlayingSong();
@@ -85,6 +87,7 @@ class Playlist : public Screen<Window>
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
std::string TotalLength();

View File

@@ -35,6 +35,7 @@ using Global::MainStartY;
PlaylistEditor *myPlaylistEditor = new PlaylistEditor;
size_t PlaylistEditor::LeftColumnStartX;
size_t PlaylistEditor::LeftColumnWidth;
size_t PlaylistEditor::RightColumnStartX;
size_t PlaylistEditor::RightColumnWidth;
@@ -70,14 +71,18 @@ void PlaylistEditor::Init()
void PlaylistEditor::Resize()
{
LeftColumnWidth = COLS/3-1;
RightColumnStartX = LeftColumnWidth+1;
RightColumnWidth = COLS-LeftColumnWidth-1;
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
LeftColumnStartX = x_offset;
LeftColumnWidth = width/3-1;
RightColumnStartX = LeftColumnStartX+LeftColumnWidth+1;
RightColumnWidth = width-LeftColumnWidth-1;
Playlists->Resize(LeftColumnWidth, MainHeight);
Content->Resize(RightColumnWidth, MainHeight);
Playlists->MoveTo(0, MainStartY);
Playlists->MoveTo(LeftColumnStartX, MainStartY);
Content->MoveTo(RightColumnStartX, MainStartY);
hasToBeResized = 0;
@@ -98,6 +103,7 @@ void PlaylistEditor::Refresh()
void PlaylistEditor::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
if (myScreen == this)
return;
@@ -105,7 +111,10 @@ void PlaylistEditor::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -139,7 +148,11 @@ void PlaylistEditor::Update()
MPD::SongList list;
Mpd.GetPlaylistContent(locale_to_utf_cpy(Playlists->Current()), list);
if (!list.empty())
Content->SetTitle(Config.titles_visibility ? "Playlist's content (" + IntoStr(list.size()) + " item" + (list.size() == 1 ? ")" : "s)") : "");
{
std::string title = Config.titles_visibility ? "Playlist's content (" + IntoStr(list.size()) + " item" + (list.size() == 1 ? ")" : "s)") : "";
title.resize(Content->GetWidth());
Content->SetTitle(title);
}
else
Content->SetTitle(Config.titles_visibility ? "Playlist's content" : "");
bool bold = 0;
@@ -175,7 +188,7 @@ void PlaylistEditor::Update()
}
}
void PlaylistEditor::NextColumn()
bool PlaylistEditor::NextColumn()
{
if (w == Playlists)
{
@@ -183,10 +196,12 @@ void PlaylistEditor::NextColumn()
w->Refresh();
w = Content;
Content->HighlightColor(Config.active_column_color);
return true;
}
return false;
}
void PlaylistEditor::PrevColumn()
bool PlaylistEditor::PrevColumn()
{
if (w == Content)
{
@@ -194,7 +209,9 @@ void PlaylistEditor::PrevColumn()
w->Refresh();
w = Playlists;
Playlists->HighlightColor(Config.active_column_color);
return true;
}
return false;
}
void PlaylistEditor::AddToPlaylist(bool add_n_play)

View File

@@ -52,18 +52,22 @@ class PlaylistEditor : public Screen<Window>
virtual List *GetList();
void NextColumn();
void PrevColumn();
virtual bool isMergable() { return true; }
bool NextColumn();
bool PrevColumn();
Menu<std::string> *Playlists;
Menu<MPD::Song> *Content;
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
void AddToPlaylist(bool);
static size_t LeftColumnStartX;
static size_t LeftColumnWidth;
static size_t RightColumnStartX;
static size_t RightColumnWidth;

107
src/screen.cpp Normal file
View File

@@ -0,0 +1,107 @@
/***************************************************************************
* Copyright (C) 2008-2011 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <cassert>
#include "screen.h"
#include "global.h"
using Global::myScreen;
using Global::myLockedScreen;
using Global::myInactiveScreen;
void ApplyToVisibleWindows(void (BasicScreen::*f)())
{
if (myLockedScreen)
{
if (myScreen == myLockedScreen)
{
if (myInactiveScreen)
(myInactiveScreen->*f)();
}
else
(myLockedScreen->*f)();
}
(myScreen->*f)();
}
void UpdateInactiveScreen(BasicScreen *screen)
{
myInactiveScreen = myLockedScreen == screen ? 0 : myScreen;
}
bool isVisible(BasicScreen *screen)
{
assert(screen != 0);
if (myLockedScreen)
return screen == myScreen || screen == myInactiveScreen || screen == myLockedScreen;
else
return screen == myScreen;
}
void BasicScreen::GetWindowResizeParams(size_t &x_offset, size_t &width, bool adjust_locked_screen)
{
width = COLS;
x_offset = 0;
if (myLockedScreen && myInactiveScreen)
{
size_t locked_width = COLS*Config.locked_screen_width_part;
if (myLockedScreen == this)
width = locked_width;
else
{
width = COLS-locked_width-1;
x_offset = locked_width+1;
if (adjust_locked_screen)
{
myLockedScreen->Resize();
myLockedScreen->Refresh();
attron(COLOR_PAIR(Config.main_color));
mvvline(Global::MainStartY, x_offset-1, 0, Global::MainHeight);
attroff(COLOR_PAIR(Config.main_color));
refresh();
}
}
}
}
bool BasicScreen::Lock()
{
if (myLockedScreen)
return false;
if (isLockable())
{
myLockedScreen = this;
return true;
}
else
return false;
}
void BasicScreen::Unlock()
{
if (myInactiveScreen && myInactiveScreen != myLockedScreen)
myScreen = myInactiveScreen;
myLockedScreen->SwitchTo();
myLockedScreen = 0;
myInactiveScreen = 0;
}

View File

@@ -28,6 +28,10 @@
#include "settings.h"
#include "status.h"
void ApplyToVisibleWindows(void (BasicScreen::*f)());
void UpdateInactiveScreen(BasicScreen *);
bool isVisible(BasicScreen *);
/// An interface for various instantiations of Screen template class. Since C++ doesn't like
/// comparison of two different instantiations of the same template class we need the most
/// basic class to be non-template to allow it.
@@ -43,7 +47,7 @@ class BasicScreen
/// @see Screen::ActiveWindow()
///
virtual void *ActiveWindow() = 0;
virtual Window *ActiveWindow() = 0;
/// Method used for switching to screen
///
@@ -129,10 +133,23 @@ class BasicScreen
///
virtual bool isTabbable() { return false; }
/// @return true if screen is mergable, ie. can be "proper" subwindow
/// if one of the screens is locked. Screens that somehow resemble popups
/// will want to return false here.
virtual bool isMergable() = 0;
/// Locks current screen.
/// @return true if lock was successful, false otherwise. Note that
/// if there is already locked screen, it'll not overwrite it.
bool Lock();
/// Should be set to true each time screen needs resize
///
bool hasToBeResized;
/// Unlocks a screen, ie. hides merged window (if there is one set).
static void Unlock();
protected:
/// Since screens initialization is lazy, we don't want to do
/// this in the constructor. This function should be invoked
@@ -141,6 +158,18 @@ class BasicScreen
///
virtual void Init() = 0;
/// @return true if screen can be locked. Note that returning
/// false here doesn't neccesarily mean that screen is also not
/// mergable (eg. lyrics screen is not lockable since that wouldn't
/// make much sense, but it's perfectly fine to merge it).
virtual bool isLockable() = 0;
/// Gets X offset and width of current screen to be used eg. in Resize() function.
/// @param adjust_locked_screen indicates whether this function should
/// automatically adjust locked screen's dimensions (is there is one set)
/// if current screen is going to be subwindow.
void GetWindowResizeParams(size_t &x_offset, size_t &width, bool adjust_locked_screen = true);
/// Flag that inditates whether the screen is initialized or not
///
bool isInitialized;
@@ -161,7 +190,7 @@ template <typename WindowType> class Screen : public BasicScreen
/// active
/// @return address to window object cast to void *
///
virtual void *ActiveWindow();
virtual Window *ActiveWindow();
/// @return pointer to currently active window
///
@@ -203,7 +232,7 @@ template <typename WindowType> class Screen : public BasicScreen
WindowType *w;
};
template <typename WindowType> void *Screen<WindowType>::ActiveWindow()
template <typename WindowType> Window *Screen<WindowType>::ActiveWindow()
{
return w;
}

View File

@@ -78,15 +78,18 @@ void SearchEngine::Init()
void SearchEngine::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
w->SetTitle(Config.columns_in_search_engine && Config.titles_visibility ? Display::Columns() : "");
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
w->SetTitle(Config.columns_in_search_engine && Config.titles_visibility ? Display::Columns(w->GetWidth()) : "");
hasToBeResized = 0;
}
void SearchEngine::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
if (myScreen == this)
{
@@ -97,7 +100,10 @@ void SearchEngine::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (w->Empty())
@@ -156,7 +162,7 @@ void SearchEngine::EnterPressed()
if (!w->Back().first)
{
if (Config.columns_in_search_engine)
w->SetTitle(Config.titles_visibility ? Display::Columns() : "");
w->SetTitle(Config.titles_visibility ? Display::Columns(w->GetWidth()) : "");
size_t found = w->Size()-SearchEngine::StaticOptions;
found += 3; // don't count options inserted below
w->InsertSeparator(ResetButton+1);

View File

@@ -48,6 +48,8 @@ class SearchEngine : public Screen< Menu< std::pair<Buffer *, MPD::Song *> > >
virtual List *GetList() { return w->Size() >= StaticOptions ? w : 0; }
virtual bool isMergable() { return true; }
void UpdateFoundList();
void Scroll(int);
void SelectAlbum();
@@ -58,6 +60,7 @@ class SearchEngine : public Screen< Menu< std::pair<Buffer *, MPD::Song *> > >
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
void Prepare();

View File

@@ -43,8 +43,11 @@ class SelectedItemsAdder : public Screen< Menu<std::string> >
virtual List *GetList() { return w; }
virtual bool isMergable() { return false; }
protected:
virtual void Init();
virtual bool isLockable() { return false; }
private:
void SetDimensions();

View File

@@ -40,8 +40,11 @@ class ServerInfo : public Screen<Scrollpad>
virtual List *GetList() { return 0; }
virtual bool isMergable() { return false; }
protected:
virtual void Init();
virtual bool isLockable() { return false; }
private:
void SetDimensions();

View File

@@ -252,6 +252,7 @@ void NcmpcppKeys::SetDefaults()
ToggleSeparatorsInPlaylist[0] = '!';
ToggleLyricsDB[0] = 'L';
ToggleFetchingLyricsInBackground[0] = 'F';
ToggleScreenLock[0] = 12;
GoToParentDir[0] = KEY_BACKSPACE;
SwitchTagTypeList[0] = '`';
Quit[0] = 'q';
@@ -341,6 +342,7 @@ void NcmpcppKeys::SetDefaults()
ToggleSeparatorsInPlaylist[1] = NullKey;
ToggleLyricsDB[1] = NullKey;
ToggleFetchingLyricsInBackground[1] = NullKey;
ToggleScreenLock[1] = NullKey;
GoToParentDir[1] = 127;
SwitchTagTypeList[1] = NullKey;
Quit[1] = 'Q';
@@ -446,6 +448,7 @@ void NcmpcppConfig::SetDefaults()
lines_scrolled = 2;
search_engine_default_search_mode = 0;
visualizer_sync_interval = 30;
locked_screen_width_part = 0.5;
selected_item_suffix_length = 0;
now_playing_suffix_length = 0;
# ifdef HAVE_LANGINFO_H
@@ -1131,6 +1134,12 @@ void NcmpcppConfig::Read()
if (interval)
visualizer_sync_interval = interval;
}
else if (cl.find("locked_screen_width_part") != std::string::npos)
{
unsigned part = StrToInt(v);
if (part)
locked_screen_width_part = part/100.0;
}
else if (cl.find("song_window_title_format") != std::string::npos)
{
if (!v.empty() && MPD::Song::isFormatOk("song_window_title_format", v))

View File

@@ -143,6 +143,7 @@ struct NcmpcppKeys
int ToggleSeparatorsInPlaylist[2];
int ToggleLyricsDB[2];
int ToggleFetchingLyricsInBackground[2];
int ToggleScreenLock[2];
int GoToParentDir[2];
int SwitchTagTypeList[2];
int Quit[2];
@@ -270,6 +271,8 @@ struct NcmpcppConfig
unsigned search_engine_default_search_mode;
unsigned visualizer_sync_interval;
double locked_screen_width_part;
size_t selected_item_suffix_length;
size_t now_playing_suffix_length;

View File

@@ -24,8 +24,6 @@
using Global::MainHeight;
using Global::MainStartY;
using Global::myScreen;
using Global::myOldScreen;
SongInfo *mySongInfo = new SongInfo;
@@ -53,8 +51,10 @@ void SongInfo::Init()
void SongInfo::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}
@@ -65,18 +65,25 @@ std::basic_string<my_char_t> SongInfo::Title()
void SongInfo::SwitchTo()
{
using Global::myScreen;
using Global::myOldScreen;
using Global::myLockedScreen;
if (myScreen == this)
return myOldScreen->SwitchTo();
if (!isInitialized)
Init();
if (myLockedScreen)
UpdateInactiveScreen(this);
MPD::Song *s = myScreen->CurrentSong();
if (!s)
return;
if (hasToBeResized)
if (hasToBeResized || myLockedScreen)
Resize();
myOldScreen = myScreen;

View File

@@ -46,10 +46,13 @@ class SongInfo : public Screen<Scrollpad>
virtual List *GetList() { return 0; }
virtual bool isMergable() { return true; }
static const Metadata Tags[];
protected:
virtual void Init();
virtual bool isLockable() { return false; }
private:
void PrepareSong(MPD::Song &);

View File

@@ -41,6 +41,8 @@
#include "visualizer.h"
using Global::myScreen;
using Global::myLockedScreen;
using Global::myInactiveScreen;
using Global::wFooter;
using Global::Timer;
using Global::wHeader;
@@ -156,6 +158,16 @@ void TraceMpdStatus()
Global::UpdateStatusImmediately = 0;
}
if (myLockedScreen)
{
if (myScreen == myLockedScreen)
{
if (myInactiveScreen)
myInactiveScreen->Update();
}
else
myLockedScreen->Update();
}
myScreen->Update();
if (myScreen->ActiveWindow() == myPlaylist->Items
@@ -283,19 +295,19 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
if (!Global::BlockItemListUpdate)
{
if (myScreen == myBrowser)
if (isVisible(myBrowser))
{
myBrowser->UpdateItemList();
}
else if (myScreen == mySearcher)
else if (isVisible(mySearcher))
{
mySearcher->UpdateFoundList();
}
else if (myScreen == myLibrary)
else if (isVisible(myLibrary))
{
UpdateSongList(myLibrary->Songs);
}
else if (myScreen == myPlaylistEditor)
else if (isVisible(myPlaylistEditor))
{
UpdateSongList(myPlaylistEditor->Content);
}
@@ -305,7 +317,7 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
{
if (myBrowser->Main())
{
if (myScreen == myBrowser)
if (isVisible(myBrowser))
myBrowser->GetDirectory(myBrowser->CurrentDir());
else
myBrowser->Main()->Clear();
@@ -370,7 +382,7 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
else
player_state.clear();
# ifdef ENABLE_VISUALIZER
if (myScreen == myVisualizer)
if (isVisible(myVisualizer))
myVisualizer->Main()->Clear();
# endif // ENABLE_VISUALIZER
break;
@@ -412,7 +424,7 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
if (Config.autocenter_mode && !myPlaylist->Items->isFiltered())
myPlaylist->Items->Highlight(myPlaylist->NowPlaying);
if (Config.now_playing_lyrics && myScreen == myLyrics && Global::myOldScreen == myPlaylist)
if (Config.now_playing_lyrics && isVisible(myLyrics) && Global::myOldScreen == myPlaylist)
myLyrics->ReloadNP = 1;
}
Playlist::ReloadRemaining = 1;
@@ -647,7 +659,7 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
if (changed.PlayerState || (changed.ElapsedTime && (!Config.new_design || Mpd.GetState() == MPD::psPlay)))
wFooter->Refresh();
if (changed.Playlist || changed.Database || changed.PlayerState || changed.SongID)
myScreen->RefreshWindow();
ApplyToVisibleWindows(&BasicScreen::RefreshWindow);
}
Window &Statusbar()

View File

@@ -48,6 +48,7 @@ const std::string TagEditor::PatternsFile = config_dir + "patterns.list";
std::list<std::string> TagEditor::Patterns;
size_t TagEditor::LeftColumnWidth;
size_t TagEditor::LeftColumnStartX;
size_t TagEditor::MiddleColumnWidth;
size_t TagEditor::MiddleColumnStartX;
size_t TagEditor::RightColumnWidth;
@@ -62,7 +63,7 @@ size_t TagEditor::FParserHeight;
void TagEditor::Init()
{
SetDimensions();
SetDimensions(0, COLS);
Albums = new Menu<string_pair>(0, MainStartY, LeftColumnWidth, MainHeight, Config.titles_visibility ? "Albums" : "", Config.main_color, brNone);
Albums->HighlightColor(Config.active_column_color);
@@ -133,17 +134,18 @@ void TagEditor::Init()
isInitialized = 1;
}
void TagEditor::SetDimensions()
void TagEditor::SetDimensions(size_t x_offset, size_t width)
{
MiddleColumnWidth = std::min(26, COLS-2);
LeftColumnWidth = (COLS-MiddleColumnWidth)/2;
MiddleColumnStartX = LeftColumnWidth+1;
RightColumnWidth = COLS-LeftColumnWidth-MiddleColumnWidth-2;
RightColumnStartX = LeftColumnWidth+MiddleColumnWidth+2;
LeftColumnStartX = x_offset;
LeftColumnWidth = (width-MiddleColumnWidth)/2;
MiddleColumnStartX = LeftColumnStartX+LeftColumnWidth+1;
RightColumnWidth = width-LeftColumnWidth-MiddleColumnWidth-2;
RightColumnStartX = MiddleColumnStartX+MiddleColumnWidth+1;
FParserDialogWidth = std::min(30, COLS);
FParserDialogHeight = std::min(size_t(6), MainHeight);
FParserWidth = COLS*0.9;
FParserWidth = width*0.9;
FParserHeight = std::min(size_t(LINES*0.8), MainHeight);
FParserWidthOne = FParserWidth/2;
FParserWidthTwo = FParserWidth-FParserWidthOne;
@@ -151,7 +153,9 @@ void TagEditor::SetDimensions()
void TagEditor::Resize()
{
SetDimensions();
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
SetDimensions(x_offset, width);
Albums->Resize(LeftColumnWidth, MainHeight);
Dirs->Resize(LeftColumnWidth, MainHeight);
@@ -162,15 +166,15 @@ void TagEditor::Resize()
FParserLegend->Resize(FParserWidthTwo, FParserHeight);
FParserPreview->Resize(FParserWidthTwo, FParserHeight);
Albums->MoveTo(0, MainStartY);
Dirs->MoveTo(0, MainStartY);
Albums->MoveTo(LeftColumnStartX, MainStartY);
Dirs->MoveTo(LeftColumnStartX, MainStartY);
TagTypes->MoveTo(MiddleColumnStartX, MainStartY);
Tags->MoveTo(RightColumnStartX, MainStartY);
FParserDialog->MoveTo((COLS-FParserDialogWidth)/2, (MainHeight-FParserDialogHeight)/2+MainStartY);
FParser->MoveTo((COLS-FParserWidth)/2, (MainHeight-FParserHeight)/2+MainStartY);
FParserLegend->MoveTo((COLS-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY);
FParserPreview->MoveTo((COLS-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY);
FParserDialog->MoveTo(x_offset+(width-FParserDialogWidth)/2, (MainHeight-FParserDialogHeight)/2+MainStartY);
FParser->MoveTo(x_offset+(width-FParserWidth)/2, (MainHeight-FParserHeight)/2+MainStartY);
FParserLegend->MoveTo(x_offset+(width-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY);
FParserPreview->MoveTo(x_offset+(width-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY);
if (MainHeight < 5 && (w == FParserDialog || w == FParser || w == FParserHelper)) // screen too low
w = TagTypes; // fall back to main columns
@@ -186,6 +190,7 @@ std::basic_string<my_char_t> TagEditor::Title()
void TagEditor::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
if (myScreen == this)
return;
@@ -193,7 +198,10 @@ void TagEditor::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -800,7 +808,7 @@ List *TagEditor::GetList()
return 0;
}
void TagEditor::NextColumn()
bool TagEditor::NextColumn()
{
if (w == LeftColumn)
{
@@ -808,6 +816,7 @@ void TagEditor::NextColumn()
w->Refresh();
w = TagTypes;
TagTypes->HighlightColor(Config.active_column_color);
return true;
}
else if (w == TagTypes && TagTypes->Choice() < 12 && !Tags->ReallyEmpty())
{
@@ -815,6 +824,7 @@ void TagEditor::NextColumn()
w->Refresh();
w = Tags;
Tags->HighlightColor(Config.active_column_color);
return true;
}
else if (w == FParser)
{
@@ -823,10 +833,12 @@ void TagEditor::NextColumn()
w = FParserHelper;
FParserHelper->SetBorder(Config.active_window_border);
FParserHelper->Display();
return true;
}
return false;
}
void TagEditor::PrevColumn()
bool TagEditor::PrevColumn()
{
if (w == Tags)
{
@@ -834,6 +846,7 @@ void TagEditor::PrevColumn()
w->Refresh();
w = TagTypes;
TagTypes->HighlightColor(Config.active_column_color);
return true;
}
else if (w == TagTypes)
{
@@ -841,6 +854,7 @@ void TagEditor::PrevColumn()
w->Refresh();
w = LeftColumn;
LeftColumn->HighlightColor(Config.active_column_color);
return true;
}
else if (w == FParserHelper)
{
@@ -849,7 +863,9 @@ void TagEditor::PrevColumn()
w = FParser;
FParser->SetBorder(Config.active_window_border);
FParser->Display();
return true;
}
return false;
}
void TagEditor::LocateSong(const MPD::Song &s)

View File

@@ -66,8 +66,10 @@ class TagEditor : public Screen<Window>
virtual List *GetList();
void NextColumn();
void PrevColumn();
virtual bool isMergable() { return true; }
bool NextColumn();
bool PrevColumn();
void LocateSong(const MPD::Song &s);
@@ -85,9 +87,10 @@ class TagEditor : public Screen<Window>
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
void SetDimensions();
void SetDimensions(size_t, size_t);
MPD::SongList EditedSongs;
Menu<std::string> *FParserDialog;
@@ -118,6 +121,7 @@ class TagEditor : public Screen<Window>
static std::list<std::string> Patterns;
static size_t MiddleColumnWidth;
static size_t LeftColumnStartX;
static size_t LeftColumnWidth;
static size_t MiddleColumnStartX;
static size_t RightColumnWidth;

View File

@@ -54,23 +54,32 @@ void TinyTagEditor::Init()
void TinyTagEditor::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}
void TinyTagEditor::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
if (itsEdited.isStream())
{
ShowMessage("Streams cannot be edited!");
}
else if (GetTags())
{
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
myOldScreen = Global::myScreen;
Global::myScreen = this;
myOldScreen = myScreen;
myScreen = this;
Global::RedrawHeader = 1;
}
else

View File

@@ -48,10 +48,13 @@ class TinyTagEditor : public Screen< Menu<Buffer> >
virtual List *GetList() { return 0; }
virtual bool isMergable() { return true; }
bool SetEdited(MPD::Song *);
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
bool GetTags();

View File

@@ -61,6 +61,7 @@ void Visualizer::Init()
void Visualizer::SwitchTo()
{
using Global::myScreen;
using Global::myLockedScreen;
if (myScreen == this)
return;
@@ -68,7 +69,10 @@ void Visualizer::SwitchTo()
if (!isInitialized)
Init();
if (hasToBeResized)
if (myLockedScreen)
UpdateInactiveScreen(this);
if (hasToBeResized || myLockedScreen)
Resize();
if (myScreen != this && myScreen->isTabbable())
@@ -88,8 +92,10 @@ void Visualizer::SwitchTo()
void Visualizer::Resize()
{
w->Resize(COLS, MainHeight);
w->MoveTo(0, MainStartY);
size_t x_offset, width;
GetWindowResizeParams(x_offset, width);
w->Resize(width, MainHeight);
w->MoveTo(x_offset, MainStartY);
hasToBeResized = 0;
}
@@ -154,11 +160,12 @@ void Visualizer::SpacePressed()
void Visualizer::DrawSoundWave(int16_t *buf, ssize_t samples, size_t y_offset, size_t height)
{
const int samples_per_col = samples/COLS;
const int samples_per_col = samples/w->GetWidth();
const int half_height = height/2;
*w << fmtAltCharset;
double prev_point_pos = 0;
for (int i = 0; i < COLS; ++i)
const size_t win_width = w->GetWidth();
for (size_t i = 0; i < win_width; ++i)
{
double point_pos = 0;
for (int j = 0; j < samples_per_col; ++j)
@@ -198,8 +205,9 @@ void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_o
for (unsigned i = 0; i < itsFFTResults; ++i)
itsFreqsMagnitude[i] = sqrt(itsOutput[i][0]*itsOutput[i][0] + itsOutput[i][1]*itsOutput[i][1])/1e5*height/5;
const int freqs_per_col = itsFFTResults/COLS /* cut bandwidth a little to achieve better look */ * 4/5;
for (int i = 0; i < COLS; ++i)
const size_t win_width = w->GetWidth();
const int freqs_per_col = itsFFTResults/win_width /* cut bandwidth a little to achieve better look */ * 7/10;
for (size_t i = 0; i < win_width; ++i)
{
size_t bar_height = 0;
for (int j = 0; j < freqs_per_col; ++j)

View File

@@ -54,6 +54,8 @@ class Visualizer : public Screen<Window>
virtual bool allowsSelection() { return false; }
virtual bool isMergable() { return true; }
void SetFD();
void ResetFD();
void FindOutputID();
@@ -62,6 +64,7 @@ class Visualizer : public Screen<Window>
protected:
virtual void Init();
virtual bool isLockable() { return true; }
private:
void DrawSoundWave(int16_t *, ssize_t, size_t, size_t);