new feature: mouse support

This commit is contained in:
Andrzej Rybczak
2009-05-25 21:46:36 +02:00
parent dd266b0103
commit d965f4e517
22 changed files with 370 additions and 1 deletions

View File

@@ -172,6 +172,8 @@
# #
#block_search_constraints_change_if_items_found = "yes" #block_search_constraints_change_if_items_found = "yes"
# #
#mouse_support = "yes"
#
#enable_window_title = "yes" #enable_window_title = "yes"
# #
## ##

View File

@@ -186,6 +186,9 @@ If your external editor is console application, you need to enable it.
.B block_search_constraints_change_if_items_found = yes/no .B block_search_constraints_change_if_items_found = yes/no
If enabled, fields in Search engine above "Reset" button will be blocked after succesful searching, otherwise they won't. If enabled, fields in Search engine above "Reset" button will be blocked after succesful searching, otherwise they won't.
.TP .TP
.B mouse_support = yes/no
Self-descriptive, isn't it?
.TP
.B allow_physical_files_deletion = yes/no .B allow_physical_files_deletion = yes/no
If enabled, ncmpcpp will be able to delete files using its browser screen. If enabled, ncmpcpp will be able to delete files using its browser screen.
.TP .TP

View File

@@ -259,6 +259,47 @@ void Browser::SpacePressed()
w->Scroll(wDown); w->Scroll(wDown);
} }
void Browser::MouseButtonPressed(MEVENT me)
{
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
return;
if (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED)
{
w->Goto(me.y);
switch (w->Current().type)
{
case itDirectory:
if (me.bstate & BUTTON1_PRESSED)
{
GetDirectory(w->Current().name);
RedrawHeader = 1;
}
else
{
size_t pos = w->GetPosition();
SpacePressed();
if (pos < w->Size()-1)
w->Scroll(wUp);
}
break;
case itPlaylist:
case itSong:
if (me.bstate & BUTTON1_PRESSED)
{
size_t pos = w->GetPosition();
SpacePressed();
if (pos < w->Size()-1)
w->Scroll(wUp);
}
else
EnterPressed();
break;
}
}
else
Screen< Menu<MPD::Item> >::MouseButtonPressed(me);
}
MPD::Song *Browser::CurrentSong() MPD::Song *Browser::CurrentSong()
{ {
return !w->Empty() && w->Current().type == itSong ? w->Current().song : 0; return !w->Empty() && w->Current().type == itSong ? w->Current().song : 0;

View File

@@ -37,6 +37,7 @@ class Browser : public Screen< Menu<MPD::Item> >
virtual void EnterPressed(); virtual void EnterPressed();
virtual void SpacePressed(); virtual void SpacePressed();
virtual void MouseButtonPressed(MEVENT);
virtual MPD::Song *CurrentSong(); virtual MPD::Song *CurrentSong();

View File

@@ -44,6 +44,7 @@ class Clock : public Screen<Window>
virtual void EnterPressed() { } virtual void EnterPressed() { }
virtual void SpacePressed() { } virtual void SpacePressed() { }
virtual void MouseButtonPressed(MEVENT) { }
virtual bool allowsSelection() { return false; } virtual bool allowsSelection() { return false; }

View File

@@ -327,6 +327,65 @@ void MediaLibrary::SpacePressed()
AddToPlaylist(0); AddToPlaylist(0);
} }
void MediaLibrary::MouseButtonPressed(MEVENT me)
{
if (!Artists->Empty() && Artists->hasCoords(me.x, me.y))
{
if (w != Artists)
{
PrevColumn();
PrevColumn();
}
if (size_t(me.y) < Artists->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
Artists->Goto(me.y);
if (me.bstate & BUTTON3_PRESSED)
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
Albums->Clear(0);
Songs->Clear(0);
}
else if (!Albums->Empty() && Albums->hasCoords(me.x, me.y))
{
if (w != Albums)
w == Artists ? NextColumn() : PrevColumn();
if (size_t(me.y) < Albums->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
Albums->Goto(me.y);
if (me.bstate & BUTTON3_PRESSED)
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
Songs->Clear(0);
}
else if (!Songs->Empty() && Songs->hasCoords(me.x, me.y))
{
if (w != Songs)
{
NextColumn();
NextColumn();
}
if (size_t(me.y) < Songs->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
Songs->Goto(me.y);
if (me.bstate & BUTTON1_PRESSED)
{
size_t pos = Songs->GetPosition();
SpacePressed();
if (pos < Songs->Size()-1)
Songs->Scroll(wUp);
}
else
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
}
}
MPD::Song *MediaLibrary::CurrentSong() MPD::Song *MediaLibrary::CurrentSong()
{ {
return w == Songs && !Songs->Empty() ? &Songs->Current() : 0; return w == Songs && !Songs->Empty() ? &Songs->Current() : 0;

View File

@@ -48,6 +48,7 @@ class MediaLibrary : public Screen<Window>
virtual void EnterPressed() { AddToPlaylist(1); } virtual void EnterPressed() { AddToPlaylist(1); }
virtual void SpacePressed(); virtual void SpacePressed();
virtual void MouseButtonPressed(MEVENT);
virtual MPD::Song *CurrentSong(); virtual MPD::Song *CurrentSong();

View File

@@ -118,6 +118,9 @@ namespace NCurses
void IntoSeparator(size_t pos); void IntoSeparator(size_t pos);
void Swap(size_t one, size_t two); void Swap(size_t one, size_t two);
void Move(size_t from, size_t to); void Move(size_t from, size_t to);
bool Goto(size_t y);
size_t GetPosition() const { return itsHighlight; }
bool isBold(int id = -1); bool isBold(int id = -1);
void BoldOption(int index, bool bold); void BoldOption(int index, bool bold);
@@ -358,6 +361,19 @@ template <typename T> void NCurses::Menu<T>::Move(size_t from, size_t to)
} }
} }
template <typename T> bool NCurses::Menu<T>::Goto(size_t y)
{
if (!itsOptionsPtr->at(itsBeginning+y) || itsOptionsPtr->at(itsBeginning+y)->isStatic)
return false;
size_t cur_pos = itsHighlight-itsBeginning;
while (itsHighlight-itsBeginning != int(y) && (y < cur_pos || size_t(itsHighlight) < itsOptions.size()-1))
{
Scroll(y < cur_pos ? wUp : wDown);
y < cur_pos ? cur_pos-- : cur_pos++;
}
return true;
}
template <typename T> void NCurses::Menu<T>::Refresh() template <typename T> void NCurses::Menu<T>::Refresh()
{ {
if (itsOptionsPtr->empty()) if (itsOptionsPtr->empty())

View File

@@ -190,6 +190,13 @@ int main(int argc, char *argv[])
gettimeofday(&now, 0); gettimeofday(&now, 0);
MEVENT mouse_event;
if (Config.mouse_support)
{
mousemask(ALL_MOUSE_EVENTS, 0);
mouseinterval(0);
}
while (!main_exit) while (!main_exit)
{ {
if (!Mpd->Connected()) if (!Mpd->Connected())
@@ -333,6 +340,45 @@ int main(int argc, char *argv[])
{ {
myScreen->Scroll(wEnd); myScreen->Scroll(wEnd);
} }
else if (Config.mouse_support && input == KEY_MOUSE)
{
# ifdef USE_PDCURSES
nc_getmouse(&mouse_event);
# else
getmouse(&mouse_event);
# endif // USE_PDCURSES
if (mouse_event.bstate & BUTTON1_PRESSED
&& mouse_event.y == LINES-(Config.statusbar_visibility ? 2 : 1)
) // progressbar
{
const Song *s = myPlaylist->NowPlayingSong();
if (!s)
continue;
Mpd->Seek(s->GetTotalLength()*mouse_event.x/double(COLS));
UpdateStatusImmediately = 1;
}
else if (mouse_event.bstate & BUTTON1_PRESSED
&& Config.statusbar_visibility
&& Mpd->GetState() > psStop
&& mouse_event.y == LINES-1 && mouse_event.x < 9
) // playing/paused
{
Mpd->Pause();
UpdateStatusImmediately = 1;
}
else if ((mouse_event.bstate & BUTTON2_PRESSED || mouse_event.bstate & BUTTON4_PRESSED)
&& Config.header_visibility
&& mouse_event.y == 0 && size_t(mouse_event.x) > COLS-VolumeState.length()
) // volume
{
if (mouse_event.bstate & BUTTON2_PRESSED)
Mpd->SetVolume(Mpd->GetVolume()-2);
else
Mpd->SetVolume(Mpd->GetVolume()+2);
}
else
myScreen->MouseButtonPressed(mouse_event);
}
else if (input == KEY_RESIZE) else if (input == KEY_RESIZE)
{ {
# ifdef USE_PDCURSES # ifdef USE_PDCURSES

View File

@@ -133,6 +133,20 @@ void Playlist::SpacePressed()
w->Scroll(wDown); w->Scroll(wDown);
} }
void Playlist::MouseButtonPressed(MEVENT me)
{
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
return;
if (me.bstate & BUTTON1_PRESSED)
{
w->Goto(me.y);
Mpd->Play(w->Current().GetPosition());
UpdateStatusImmediately = 1;
}
else
Screen< Menu<MPD::Song> >::MouseButtonPressed(me);
}
MPD::Song *Playlist::CurrentSong() MPD::Song *Playlist::CurrentSong()
{ {
return !w->Empty() ? &w->Current() : 0; return !w->Empty() ? &w->Current() : 0;

View File

@@ -41,6 +41,7 @@ class Playlist : public Screen< Menu<MPD::Song> >
virtual void EnterPressed(); virtual void EnterPressed();
virtual void SpacePressed(); virtual void SpacePressed();
virtual void MouseButtonPressed(MEVENT);
virtual MPD::Song *CurrentSong(); virtual MPD::Song *CurrentSong();

View File

@@ -281,6 +281,44 @@ void PlaylistEditor::SpacePressed()
AddToPlaylist(0); AddToPlaylist(0);
} }
void PlaylistEditor::MouseButtonPressed(MEVENT me)
{
if (!Playlists->Empty() && Playlists->hasCoords(me.x, me.y))
{
if (w != Playlists)
PrevColumn();
if (size_t(me.y) < Playlists->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
Playlists->Goto(me.y);
if (me.bstate & BUTTON3_PRESSED)
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
Content->Clear(0);
}
else if (!Content->Empty() && Content->hasCoords(me.x, me.y))
{
if (w != Content)
NextColumn();
if (size_t(me.y) < Content->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
Content->Goto(me.y);
if (me.bstate & BUTTON1_PRESSED)
{
size_t pos = Content->GetPosition();
SpacePressed();
if (pos < Content->Size()-1)
Content->Scroll(wUp);
}
else
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
}
}
MPD::Song *PlaylistEditor::CurrentSong() MPD::Song *PlaylistEditor::CurrentSong()
{ {
return w == Content && !Content->Empty() ? &Content->Current() : 0; return w == Content && !Content->Empty() ? &Content->Current() : 0;

View File

@@ -37,6 +37,7 @@ class PlaylistEditor : public Screen<Window>
virtual void EnterPressed() { AddToPlaylist(1); } virtual void EnterPressed() { AddToPlaylist(1); }
virtual void SpacePressed(); virtual void SpacePressed();
virtual void MouseButtonPressed(MEVENT);
virtual MPD::Song *CurrentSong(); virtual MPD::Song *CurrentSong();

View File

@@ -49,6 +49,7 @@ class BasicScreen
virtual void EnterPressed() = 0; virtual void EnterPressed() = 0;
virtual void SpacePressed() = 0; virtual void SpacePressed() = 0;
virtual void MouseButtonPressed(MEVENT) { }
virtual MPD::Song *CurrentSong() { return 0; } virtual MPD::Song *CurrentSong() { return 0; }
@@ -76,7 +77,9 @@ template <typename WindowType> class Screen : public BasicScreen
virtual void Refresh(); virtual void Refresh();
virtual void RefreshWindow(); virtual void RefreshWindow();
virtual void ReadKey(int &input); virtual void ReadKey(int &input);
virtual void Scroll(Where where, const int *); virtual void Scroll(Where where, const int * = 0);
virtual void MouseButtonPressed(MEVENT me);
protected: protected:
WindowType *w; WindowType *w;
@@ -126,5 +129,31 @@ template <typename WindowType> void Screen<WindowType>::Scroll(Where where, cons
w->Scroll(where); w->Scroll(where);
} }
template <typename WindowType> void Screen<WindowType>::MouseButtonPressed(MEVENT me)
{
if (me.bstate & BUTTON2_PRESSED)
{
Scroll(wPageDown);
}
else if (me.bstate & BUTTON4_PRESSED)
{
Scroll(wPageUp);
}
}
template <> inline void Screen<Scrollpad>::MouseButtonPressed(MEVENT me)
{
if (me.bstate & BUTTON2_PRESSED)
{
for (size_t i = 0; i < 2; i++)
Scroll(wDown);
}
else if (me.bstate & BUTTON4_PRESSED)
{
for (size_t i = 0; i < 2; i++)
Scroll(wUp);
}
}
#endif #endif

View File

@@ -295,6 +295,34 @@ void SearchEngine::SpacePressed()
w->Scroll(wDown); w->Scroll(wDown);
} }
void SearchEngine::MouseButtonPressed(MEVENT me)
{
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
return;
if (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED)
{
if (!w->Goto(me.y))
return;
w->Refresh();
if ((me.bstate & BUTTON3_PRESSED || w->GetPosition() > 10) && w->GetPosition() < StaticOptions)
EnterPressed();
else if (w->GetPosition() >= StaticOptions)
{
if (me.bstate & BUTTON1_PRESSED)
{
size_t pos = w->GetPosition();
SpacePressed();
if (pos < w->Size()-1)
w->Scroll(wUp);
}
else
EnterPressed();
}
}
else
Screen< Menu< std::pair<Buffer *, MPD::Song *> > >::MouseButtonPressed(me);
}
MPD::Song *SearchEngine::CurrentSong() MPD::Song *SearchEngine::CurrentSong()
{ {
return !w->Empty() ? w->Current().second : 0; return !w->Empty() ? w->Current().second : 0;

View File

@@ -48,6 +48,7 @@ class SearchEngine : public Screen< Menu< std::pair<Buffer *, MPD::Song *> > >
virtual void EnterPressed(); virtual void EnterPressed();
virtual void SpacePressed(); virtual void SpacePressed();
virtual void MouseButtonPressed(MEVENT);
virtual MPD::Song *CurrentSong(); virtual MPD::Song *CurrentSong();

View File

@@ -280,6 +280,7 @@ void DefaultConfiguration(ncmpcpp_config &conf)
conf.use_cyclic_scrolling = false; conf.use_cyclic_scrolling = false;
conf.allow_physical_files_deletion = false; conf.allow_physical_files_deletion = false;
conf.allow_physical_directories_deletion = false; conf.allow_physical_directories_deletion = false;
conf.mouse_support = true;
conf.set_window_title = true; conf.set_window_title = true;
conf.mpd_port = 6600; conf.mpd_port = 6600;
conf.mpd_connection_timeout = 15; conf.mpd_connection_timeout = 15;
@@ -679,6 +680,10 @@ void ReadConfiguration(ncmpcpp_config &conf)
{ {
conf.allow_physical_directories_deletion = v == "yes"; conf.allow_physical_directories_deletion = v == "yes";
} }
else if (cl.find("mouse_support") != string::npos)
{
conf.mouse_support = v == "yes";
}
else if (cl.find("enable_window_title") != string::npos) else if (cl.find("enable_window_title") != string::npos)
{ {
conf.set_window_title = v == "yes"; conf.set_window_title = v == "yes";

View File

@@ -172,6 +172,7 @@ struct ncmpcpp_config
bool use_cyclic_scrolling; bool use_cyclic_scrolling;
bool allow_physical_files_deletion; bool allow_physical_files_deletion;
bool allow_physical_directories_deletion; bool allow_physical_directories_deletion;
bool mouse_support;
int mpd_port; int mpd_port;
int mpd_connection_timeout; int mpd_connection_timeout;

View File

@@ -216,6 +216,21 @@ void TinyTagEditor::EnterPressed()
UnlockStatusbar(); UnlockStatusbar();
} }
void TinyTagEditor::MouseButtonPressed(MEVENT me)
{
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
return;
if (me.bstate & BUTTON1_PRESSED)
{
if (!w->Goto(me.y))
return;
w->Refresh();
EnterPressed();
}
else
Screen< Menu<Buffer> >::MouseButtonPressed(me);
}
bool TinyTagEditor::SetEdited(MPD::Song *s) bool TinyTagEditor::SetEdited(MPD::Song *s)
{ {
if (!s) if (!s)
@@ -728,6 +743,62 @@ void TagEditor::SpacePressed()
Tags->Clear(0); Tags->Clear(0);
} }
void TagEditor::MouseButtonPressed(MEVENT me)
{
if (!LeftColumn->Empty() && LeftColumn->hasCoords(me.x, me.y))
{
if (w != LeftColumn)
{
PrevColumn();
PrevColumn();
}
if (size_t(me.y) < LeftColumn->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
LeftColumn->Goto(me.y);
if (me.bstate & BUTTON1_PRESSED)
EnterPressed();
else
SpacePressed();
}
else
Screen<Window>::MouseButtonPressed(me);
Tags->Clear(0);
}
else if (!TagTypes->Empty() && TagTypes->hasCoords(me.x, me.y))
{
if (w != TagTypes)
w == LeftColumn ? NextColumn() : PrevColumn();
if (size_t(me.y) < TagTypes->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
if (!TagTypes->Goto(me.y))
return;
TagTypes->Refresh();
Tags->Refresh();
if (me.bstate & BUTTON3_PRESSED)
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
}
else if (!Tags->Empty() && Tags->hasCoords(me.x, me.y))
{
if (w != Tags)
{
NextColumn();
NextColumn();
}
if (size_t(me.y) < Tags->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
{
Tags->Goto(me.y);
Tags->Refresh();
if (me.bstate & BUTTON3_PRESSED)
EnterPressed();
}
else
Screen<Window>::MouseButtonPressed(me);
}
}
MPD::Song *TagEditor::CurrentSong() MPD::Song *TagEditor::CurrentSong()
{ {
return w == Tags && !Tags->Empty() ? &Tags->Current() : 0; return w == Tags && !Tags->Empty() ? &Tags->Current() : 0;

View File

@@ -44,6 +44,7 @@ class TinyTagEditor : public Screen< Menu<Buffer> >
virtual void EnterPressed(); virtual void EnterPressed();
virtual void SpacePressed() { } virtual void SpacePressed() { }
virtual void MouseButtonPressed(MEVENT);
virtual bool allowsSelection() { return false; } virtual bool allowsSelection() { return false; }
@@ -74,6 +75,7 @@ class TagEditor : public Screen<Window>
virtual void EnterPressed(); virtual void EnterPressed();
virtual void SpacePressed(); virtual void SpacePressed();
virtual void MouseButtonPressed(MEVENT);
virtual MPD::Song *CurrentSong(); virtual MPD::Song *CurrentSong();

View File

@@ -468,6 +468,8 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e
switch (input) switch (input)
{ {
case ERR: case ERR:
case KEY_MOUSE:
break;
case KEY_UP: case KEY_UP:
if (itsHistory && !encrypted && history_offset > 0) if (itsHistory && !encrypted && history_offset > 0)
{ {
@@ -634,6 +636,11 @@ int Window::Y() const
return itsY; return itsY;
} }
bool Window::hasCoords(int &x, int &y)
{
return wmouse_trafo(itsWindow, &y, &x, 0);
}
void Window::Scrollable(bool scrollable) const void Window::Scrollable(bool scrollable) const
{ {
scrollok(itsWindow, scrollable); scrollok(itsWindow, scrollable);

View File

@@ -107,6 +107,7 @@ namespace NCurses
void GotoXY(int, int); void GotoXY(int, int);
int X() const; int X() const;
int Y() const; int Y() const;
bool hasCoords(int &, int &);
void SetGetStringHelper(GetStringHelper helper) { itsGetStringHelper = helper; } void SetGetStringHelper(GetStringHelper helper) { itsGetStringHelper = helper; }
void SetColor(Color, Color = clDefault); void SetColor(Color, Color = clDefault);