Add auto-scrolling; Right-click menu with settings
Now three settings can be toggled through the right-click menu― whether or not the view should be transparent when no lyrics are available (or no music is playing); whether or not the dragger should be, as well; and whether or not auto-scroll should be toggled. Auto-scroll, when enabled, will scroll through the text automatically, in proportion with current position in the song.
This commit is contained in:
parent
2316c1bf5f
commit
78dec2ec7e
|
@ -58,44 +58,22 @@ LyricsTextView::MouseDown(BPoint where)
|
||||||
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
|
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
|
||||||
|
|
||||||
if (buttons & B_SECONDARY_MOUSE_BUTTON)
|
if (buttons & B_SECONDARY_MOUSE_BUTTON)
|
||||||
_RightClickPopUp(where)->Go(ConvertToScreen(where), true, false);
|
((LyricsView*)Parent()->Parent())->MouseDown(
|
||||||
|
Parent()->ConvertToParent(ConvertToParent(where)));
|
||||||
else
|
else
|
||||||
BTextView::MouseDown(where);
|
BTextView::MouseDown(where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BPopUpMenu*
|
|
||||||
LyricsTextView::_RightClickPopUp(BPoint where)
|
|
||||||
{
|
|
||||||
BPopUpMenu* menu = new BPopUpMenu("rightClickPopUp");
|
|
||||||
BMenuItem* copy =
|
|
||||||
new BMenuItem("Copy", new BMessage(B_COPY), 'C', B_COMMAND_KEY);
|
|
||||||
BMenuItem* selectAll = new BMenuItem("Select all",
|
|
||||||
new BMessage(B_SELECT_ALL), 'A', B_COMMAND_KEY);
|
|
||||||
|
|
||||||
int32 start = -1, end = -1;
|
|
||||||
GetSelection(&start, &end);
|
|
||||||
|
|
||||||
copy->SetEnabled(start >= 0 && end > 0);
|
|
||||||
copy->SetTarget(this);
|
|
||||||
menu->AddItem(copy);
|
|
||||||
|
|
||||||
selectAll->SetTarget(this);
|
|
||||||
menu->AddItem(selectAll);
|
|
||||||
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LyricsView::LyricsView(BRect frame)
|
LyricsView::LyricsView(BRect frame)
|
||||||
:
|
:
|
||||||
BView(frame, "Lyrics", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_PULSE_NEEDED)
|
BView(frame, "Lyrics", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_PULSE_NEEDED)
|
||||||
{
|
{
|
||||||
BRect dragRect(0, 0, 10, frame.Height());
|
BRect dragRect(0, 0, 10, frame.Height());
|
||||||
BDragger* airdrag = new BDragger(dragRect, this,
|
fDragger = new BDragger(dragRect, this,
|
||||||
B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||||
airdrag->SetViewColor(B_TRANSPARENT_COLOR);
|
fDragger->SetViewColor(B_TRANSPARENT_COLOR);
|
||||||
AddChild(airdrag);
|
AddChild(fDragger);
|
||||||
|
|
||||||
BRect textRect(0, 0, Bounds().Width(), Bounds().Height() - 10);
|
BRect textRect(0, 0, Bounds().Width(), Bounds().Height() - 10);
|
||||||
fTextView = new LyricsTextView(textRect, "lyricsText", textRect,
|
fTextView = new LyricsTextView(textRect, "lyricsText", textRect,
|
||||||
|
@ -108,7 +86,10 @@ LyricsView::LyricsView(BRect frame)
|
||||||
fScrollView->ScrollBar(B_VERTICAL)->Hide();
|
fScrollView->ScrollBar(B_VERTICAL)->Hide();
|
||||||
AddChild(fScrollView);
|
AddChild(fScrollView);
|
||||||
|
|
||||||
fTransparentInactivity = false;
|
fAutoScroll = false;
|
||||||
|
fTransparentInactivity = true;
|
||||||
|
fTransparentDragger = false;
|
||||||
|
|
||||||
fFgColor = ui_color(B_PANEL_TEXT_COLOR);
|
fFgColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||||
fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
|
fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||||
|
|
||||||
|
@ -120,15 +101,21 @@ LyricsView::LyricsView(BMessage* data)
|
||||||
:
|
:
|
||||||
BView(data)
|
BView(data)
|
||||||
{
|
{
|
||||||
fTransparentInactivity = false;
|
fAutoScroll = false;
|
||||||
|
fTransparentInactivity = true;
|
||||||
|
fTransparentDragger = false;
|
||||||
|
|
||||||
fFgColor = ui_color(B_PANEL_TEXT_COLOR);
|
fFgColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||||
fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
|
fBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||||
|
|
||||||
fTextView = dynamic_cast<LyricsTextView*>(FindView("lyricsText"));
|
fTextView = dynamic_cast<LyricsTextView*>(FindView("lyricsText"));
|
||||||
fScrollView = dynamic_cast<BScrollView*>(FindView("scrollView"));
|
fScrollView = dynamic_cast<BScrollView*>(FindView("scrollView"));
|
||||||
|
fDragger = dynamic_cast<BDragger*>(FindView("_dragger_"));
|
||||||
data->FindColor("background_color", &fBgColor);
|
data->FindColor("background_color", &fBgColor);
|
||||||
data->FindColor("foreground_color", &fFgColor);
|
data->FindColor("foreground_color", &fFgColor);
|
||||||
|
data->FindBool("autoscroll", &fAutoScroll);
|
||||||
data->FindBool("transparent_inactivity", &fTransparentInactivity);
|
data->FindBool("transparent_inactivity", &fTransparentInactivity);
|
||||||
|
data->FindBool("transparent_dragger", &fTransparentDragger);
|
||||||
|
|
||||||
_Init(Frame());
|
_Init(Frame());
|
||||||
}
|
}
|
||||||
|
@ -140,10 +127,13 @@ LyricsView::Archive(BMessage* data, bool deep) const
|
||||||
status_t status = BView::Archive(data, deep);
|
status_t status = BView::Archive(data, deep);
|
||||||
data->AddColor("background_color", fBgColor);
|
data->AddColor("background_color", fBgColor);
|
||||||
data->AddColor("foreground_color", fFgColor);
|
data->AddColor("foreground_color", fFgColor);
|
||||||
|
data->AddBool("autoscroll", fAutoScroll);
|
||||||
data->AddBool("transparent_inactivity", fTransparentInactivity);
|
data->AddBool("transparent_inactivity", fTransparentInactivity);
|
||||||
|
data->AddBool("transparent_dragger", fTransparentDragger);
|
||||||
|
|
||||||
data->AddString("class", "LyricsView");
|
data->AddString("class", "LyricsView");
|
||||||
data->AddString("add_on", "application/x-vnd.mediamonitor");
|
data->AddString("add_on", "application/x-vnd.mediamonitor");
|
||||||
|
data->PrintToStream();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,8 +168,24 @@ LyricsView::MessageReceived(BMessage* msg)
|
||||||
_UpdateColors();
|
_UpdateColors();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LYRICS_AUTO_SCROLL:
|
||||||
|
fAutoScroll = !fAutoScroll;
|
||||||
|
break;
|
||||||
|
case LYRICS_TRANSPARENTLY_INACTIVE:
|
||||||
|
case LYRICS_TRANSPARENTLY_DRAG: {
|
||||||
|
if (msg->what == LYRICS_TRANSPARENTLY_INACTIVE)
|
||||||
|
fTransparentInactivity = !fTransparentInactivity;
|
||||||
|
if (msg->what == LYRICS_TRANSPARENTLY_DRAG)
|
||||||
|
fTransparentDragger = !fTransparentDragger;
|
||||||
|
|
||||||
|
if (fCurrentPath.IsEmpty() == true)
|
||||||
|
_ClearText();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
BView::MessageReceived(msg);
|
BView::MessageReceived(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,6 +203,23 @@ LyricsView::Pulse()
|
||||||
fCurrentPath = path;
|
fCurrentPath = path;
|
||||||
_ClearText();
|
_ClearText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fAutoScroll == true) {
|
||||||
|
float position = _GetPositionProportion();
|
||||||
|
if (position > 0)
|
||||||
|
fTextView->ScrollToOffset(fTextView->TextLength() * position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LyricsView::MouseDown(BPoint where)
|
||||||
|
{
|
||||||
|
uint32 buttons = 0;
|
||||||
|
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
|
||||||
|
|
||||||
|
if (buttons & B_SECONDARY_MOUSE_BUTTON)
|
||||||
|
_RightClickPopUp()->Go(ConvertToScreen(where), true, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -214,6 +237,8 @@ LyricsView::_SetText(const char* text)
|
||||||
{
|
{
|
||||||
if (fScrollView->IsHidden() == true)
|
if (fScrollView->IsHidden() == true)
|
||||||
fScrollView->Show();
|
fScrollView->Show();
|
||||||
|
if (fDragger->IsHidden() == true)
|
||||||
|
fDragger->Show();
|
||||||
|
|
||||||
fTextView->SetText(text);
|
fTextView->SetText(text);
|
||||||
fTextView->SetAlignment(B_ALIGN_LEFT);
|
fTextView->SetAlignment(B_ALIGN_LEFT);
|
||||||
|
@ -223,8 +248,17 @@ LyricsView::_SetText(const char* text)
|
||||||
void
|
void
|
||||||
LyricsView::_ClearText()
|
LyricsView::_ClearText()
|
||||||
{
|
{
|
||||||
if (fScrollView->IsHidden() == false && fTransparentInactivity == true)
|
if (fTransparentInactivity == true) {
|
||||||
|
if (fScrollView->IsHidden() == false)
|
||||||
fScrollView->Hide();
|
fScrollView->Hide();
|
||||||
|
if (fDragger->IsHidden() == false && fTransparentDragger == true)
|
||||||
|
fDragger->Hide();
|
||||||
|
} else {
|
||||||
|
if (fScrollView->IsHidden() == true)
|
||||||
|
fScrollView->Show();
|
||||||
|
if (fDragger->IsHidden() == true)
|
||||||
|
fDragger->Show();
|
||||||
|
}
|
||||||
|
|
||||||
fTextView->SetText("No lyrics to display!");
|
fTextView->SetText("No lyrics to display!");
|
||||||
fTextView->SetAlignment(B_ALIGN_CENTER);
|
fTextView->SetAlignment(B_ALIGN_CENTER);
|
||||||
|
@ -253,6 +287,53 @@ LyricsView::_UpdateColors()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BPopUpMenu*
|
||||||
|
LyricsView::_RightClickPopUp()
|
||||||
|
{
|
||||||
|
BPopUpMenu* menu = new BPopUpMenu("rightClickPopUp");
|
||||||
|
menu->SetRadioMode(false);
|
||||||
|
|
||||||
|
BMenuItem* copy =
|
||||||
|
new BMenuItem("Copy", new BMessage(B_COPY), 'C', B_COMMAND_KEY);
|
||||||
|
|
||||||
|
int32 start = -1, end = -1;
|
||||||
|
fTextView->GetSelection(&start, &end);
|
||||||
|
|
||||||
|
copy->SetEnabled(start >= 0 && end > 0);
|
||||||
|
copy->SetTarget(fTextView);
|
||||||
|
menu->AddItem(copy);
|
||||||
|
|
||||||
|
BMenuItem* selectAll = new BMenuItem("Select all",
|
||||||
|
new BMessage(B_SELECT_ALL), 'A', B_COMMAND_KEY);
|
||||||
|
selectAll->SetTarget(fTextView);
|
||||||
|
menu->AddItem(selectAll);
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
BMenuItem* autoScroll = new BMenuItem("Auto-scroll",
|
||||||
|
new BMessage(LYRICS_AUTO_SCROLL));
|
||||||
|
autoScroll->SetMarked(fAutoScroll);
|
||||||
|
autoScroll->SetTarget(this);
|
||||||
|
menu->AddItem(autoScroll);
|
||||||
|
|
||||||
|
BMenu* hideMenu = new BMenu("Hide when inactive");
|
||||||
|
menu->AddItem(hideMenu);
|
||||||
|
|
||||||
|
BMenuItem* hideInactive = hideMenu->Superitem();
|
||||||
|
hideInactive->SetMessage(new BMessage(LYRICS_TRANSPARENTLY_INACTIVE));
|
||||||
|
hideInactive->SetMarked(fTransparentInactivity);
|
||||||
|
hideInactive->SetTarget(this);
|
||||||
|
|
||||||
|
BMenuItem* hideDragger = new BMenuItem("… including the dragger",
|
||||||
|
new BMessage(LYRICS_TRANSPARENTLY_DRAG));
|
||||||
|
hideDragger->SetMarked(fTransparentDragger);
|
||||||
|
hideDragger->SetTarget(this);
|
||||||
|
hideMenu->AddItem(hideDragger);
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BString
|
BString
|
||||||
LyricsView::_GetCurrentPath()
|
LyricsView::_GetCurrentPath()
|
||||||
{
|
{
|
||||||
|
@ -266,3 +347,29 @@ LyricsView::_GetCurrentPath()
|
||||||
reply.FindString("result", &result);
|
reply.FindString("result", &result);
|
||||||
return result.ReplaceAll("file://", "");
|
return result.ReplaceAll("file://", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
LyricsView::_GetPositionProportion()
|
||||||
|
{
|
||||||
|
int64 position = _GetIntProperty("Position");
|
||||||
|
int64 duration = _GetIntProperty("Duration");
|
||||||
|
if (position >= 0 && duration > 0)
|
||||||
|
return (float)position / (float)duration;
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
LyricsView::_GetIntProperty(const char* specifier)
|
||||||
|
{
|
||||||
|
BMessage message, reply;
|
||||||
|
message.what = B_GET_PROPERTY;
|
||||||
|
message.AddSpecifier(specifier);
|
||||||
|
message.AddSpecifier("Window", 0);
|
||||||
|
BMessenger("application/x-vnd.Haiku-MediaPlayer").SendMessage(&message, &reply);
|
||||||
|
|
||||||
|
int64 result = -1;
|
||||||
|
reply.FindInt64("result", &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,18 @@
|
||||||
|
|
||||||
#include <TextView.h>
|
#include <TextView.h>
|
||||||
|
|
||||||
|
class BDragger;
|
||||||
class BPopUpMenu;
|
class BPopUpMenu;
|
||||||
class BScrollView;
|
class BScrollView;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LYRICS_AUTO_SCROLL = 'lvas',
|
||||||
|
LYRICS_TRANSPARENTLY_INACTIVE = 'lvti',
|
||||||
|
LYRICS_TRANSPARENTLY_DRAG = 'lvtd'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class LyricsTextView : public BTextView {
|
class LyricsTextView : public BTextView {
|
||||||
public:
|
public:
|
||||||
LyricsTextView(BRect frame, const char* name, BRect textFrame,
|
LyricsTextView(BRect frame, const char* name, BRect textFrame,
|
||||||
|
@ -21,9 +29,6 @@ public:
|
||||||
static LyricsTextView* Instantiate(BMessage* data);
|
static LyricsTextView* Instantiate(BMessage* data);
|
||||||
|
|
||||||
virtual void MouseDown(BPoint where);
|
virtual void MouseDown(BPoint where);
|
||||||
|
|
||||||
private:
|
|
||||||
BPopUpMenu* _RightClickPopUp(BPoint where);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +43,8 @@ public:
|
||||||
virtual void MessageReceived(BMessage* msg);
|
virtual void MessageReceived(BMessage* msg);
|
||||||
virtual void Pulse();
|
virtual void Pulse();
|
||||||
|
|
||||||
|
virtual void MouseDown(BPoint where);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _Init(BRect frame);
|
void _Init(BRect frame);
|
||||||
|
|
||||||
|
@ -46,12 +53,19 @@ private:
|
||||||
|
|
||||||
void _UpdateColors();
|
void _UpdateColors();
|
||||||
|
|
||||||
|
BPopUpMenu* _RightClickPopUp();
|
||||||
|
|
||||||
BString _GetCurrentPath();
|
BString _GetCurrentPath();
|
||||||
|
float _GetPositionProportion();
|
||||||
|
int64 _GetIntProperty(const char* specifier);
|
||||||
|
|
||||||
LyricsTextView* fTextView;
|
LyricsTextView* fTextView;
|
||||||
BScrollView* fScrollView;
|
BScrollView* fScrollView;
|
||||||
|
BDragger* fDragger;
|
||||||
|
|
||||||
|
bool fAutoScroll;
|
||||||
bool fTransparentInactivity;
|
bool fTransparentInactivity;
|
||||||
|
bool fTransparentDragger;
|
||||||
|
|
||||||
rgb_color fBgColor;
|
rgb_color fBgColor;
|
||||||
rgb_color fFgColor;
|
rgb_color fFgColor;
|
||||||
|
|
Ŝarĝante…
Reference in New Issue