1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-29 14:48:39 +02:00

Remove the code for ruler pushbuttons and keyboard navigation...

This commit is contained in:
Paul Licameli 2016-06-01 13:22:47 -04:00
commit 2345f37133
2 changed files with 53 additions and 696 deletions

View File

@ -1935,14 +1935,6 @@ BEGIN_EVENT_TABLE(AdornedRulerPanel, OverlayPanel)
// Scrub bar menu commands // Scrub bar menu commands
EVT_MENU(OnShowHideScrubbingID, AdornedRulerPanel::OnToggleScrubbing) EVT_MENU(OnShowHideScrubbingID, AdornedRulerPanel::OnToggleScrubbing)
// Key events, to navigate buttons
EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, AdornedRulerPanel::OnCaptureKey)
EVT_KEY_DOWN(AdornedRulerPanel::OnKeyDown)
// Correct management of track focus
EVT_SET_FOCUS(AdornedRulerPanel::OnSetFocus)
EVT_KILL_FOCUS(AdornedRulerPanel::OnKillFocus)
// Pop up menus on Windows // Pop up menus on Windows
EVT_CONTEXT_MENU(AdornedRulerPanel::OnContextMenu) EVT_CONTEXT_MENU(AdornedRulerPanel::OnContextMenu)
@ -1996,8 +1988,6 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* parent,
mPlayRegionDragsSelection = (gPrefs->Read(wxT("/QuickPlay/DragSelection"), 0L) == 1)? true : false; mPlayRegionDragsSelection = (gPrefs->Read(wxT("/QuickPlay/DragSelection"), 0L) == 1)? true : false;
mQuickPlayEnabled = !!gPrefs->Read(wxT("/QuickPlay/QuickPlayEnabled"), 1L); mQuickPlayEnabled = !!gPrefs->Read(wxT("/QuickPlay/QuickPlayEnabled"), 1L);
mButtonFont.Create(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
UpdatePrefs(); UpdatePrefs();
#if wxUSE_TOOLTIPS #if wxUSE_TOOLTIPS
@ -2060,101 +2050,12 @@ void AdornedRulerPanel::UpdatePrefs()
UpdateRects(); UpdateRects();
RegenerateTooltips(mPrevZone); RegenerateTooltips(mPrevZone);
mButtonFontSize = -1;
} }
void AdornedRulerPanel::ReCreateButtons() void AdornedRulerPanel::ReCreateButtons()
{ {
} }
namespace {
enum { ArrowWidth = 8, ArrowSpacing = 1, ArrowHeight = ArrowWidth / 2 };
// Find the part of the button rectangle in which you can click the arrow.
// It includes the lower right corner.
wxRect GetArrowRect(const wxRect &buttonRect)
{
// Change the following lines to change the size of the hot zone.
// Make the hot zone as tall as the button
auto width = std::min(
std::max(1, buttonRect.GetWidth()) - 1,
ArrowWidth + 2 * ArrowSpacing
+ 2 // bevel around arrow
+ 2 // outline around the bevel
);
auto height = buttonRect.GetHeight();
return wxRect {
buttonRect.GetRight() + 1 - width,
buttonRect.GetBottom() + 1 - height,
width, height
};
}
wxRect GetTextRect(const wxRect &buttonRect)
{
auto result = buttonRect;
result.width -= GetArrowRect(buttonRect).width;
return result;
}
// Compensate for off-by-one problem in the bevel-drawing functions
struct Deflator {
Deflator(wxRect &rect) : mRect(rect) {
--mRect.width;
--mRect.height;
}
~Deflator() {
++mRect.width;
++mRect.height;
}
wxRect &mRect;
};
}
wxFont &AdornedRulerPanel::GetButtonFont() const
{
if (mButtonFontSize < 0) {
mButtonFontSize = 10;
bool done;
do {
done = true;
mButtonFont.SetPointSize(mButtonFontSize);
wxCoord width, height;
for (auto button = StatusChoice::FirstButton; done && IsButton(button); ++button) {
auto rect = GetTextRect(GetButtonRect(button));
auto availableWidth = rect.GetWidth();
auto availableHeight = rect.GetHeight();
// Deduct for outlines, and room to move text
// I might deduct 2 more for bevel, but that made the text too small.
#ifdef __WXMSW__
// Deduct less for MSW, because GetTextExtent appears to overstate width, and
// I don't know why. Not really happy with this arbitrary fix.
availableWidth -= 1;
availableHeight -= 1;
#else
availableWidth -= 2 + 1;
availableHeight -= 2 + 1;
#endif
GetParent()->GetTextExtent(
wxGetTranslation(GetPushButtonStrings(button)->label),
&width, &height, NULL, NULL, &mButtonFont);
// Yes, < not <= ! Leave at least some room.
done = width < availableWidth && height < availableHeight;
}
mButtonFontSize--;
} while (mButtonFontSize > 0 && !done);
}
return mButtonFont;
}
void AdornedRulerPanel::InvalidateRuler() void AdornedRulerPanel::InvalidateRuler()
{ {
mRuler.Invalidate(); mRuler.Invalidate();
@ -2169,7 +2070,6 @@ void AdornedRulerPanel::RegenerateTooltips(StatusChoice choice)
} }
else { else {
switch(choice) { switch(choice) {
case StatusChoice::QuickPlayButton :
case StatusChoice::EnteringQP : case StatusChoice::EnteringQP :
if (!mQuickPlayEnabled) { if (!mQuickPlayEnabled) {
this->SetToolTip(_("Quick-Play disabled")); this->SetToolTip(_("Quick-Play disabled"));
@ -2178,14 +2078,6 @@ void AdornedRulerPanel::RegenerateTooltips(StatusChoice choice)
this->SetToolTip(_("Quick-Play enabled")); this->SetToolTip(_("Quick-Play enabled"));
} }
break; break;
case StatusChoice::ScrubBarButton :
if (!mShowScrubbing) {
this->SetToolTip(_("Scrub bar hidden"));
}
else {
this->SetToolTip(_("Scrub bar shown"));
}
break;
case StatusChoice::EnteringScrubZone : case StatusChoice::EnteringScrubZone :
this->SetToolTip(_("Scrub Bar")); this->SetToolTip(_("Scrub Bar"));
break; break;
@ -2239,8 +2131,6 @@ void AdornedRulerPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
DoDrawPlayRegion(&backDC); DoDrawPlayRegion(&backDC);
DoDrawPushbuttons(&backDC);
DoDrawEdge(&backDC); DoDrawEdge(&backDC);
DisplayBitmap(dc); DisplayBitmap(dc);
@ -2347,25 +2237,8 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
} }
const auto position = evt.GetPosition(); const auto position = evt.GetPosition();
const bool overButtons = GetButtonAreaRect(true).Contains(position);
StatusChoice button;
{
auto mouseState = FindButton(evt);
button = mouseState.button;
if (IsButton(button)) {
TabState newState{ button, mouseState.state == PointerState::InArrow };
if (mTabState != newState) {
// Change the button highlight
mTabState = newState;
Refresh(false);
}
}
else if(evt.Leaving() && !HasFocus())
// erase the button highlight
Refresh(false);
}
const bool inScrubZone = !overButtons && const bool inScrubZone =
// only if scrubbing is allowed now // only if scrubbing is allowed now
mProject->GetScrubber().CanScrub() && mProject->GetScrubber().CanScrub() &&
mShowScrubbing && mShowScrubbing &&
@ -2373,13 +2246,11 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
const StatusChoice zone = const StatusChoice zone =
evt.Leaving() evt.Leaving()
? StatusChoice::Leaving ? StatusChoice::Leaving
: overButtons : inScrubZone
? button ? StatusChoice::EnteringScrubZone
: inScrubZone : mInner.Contains(position)
? StatusChoice::EnteringScrubZone ? StatusChoice::EnteringQP
: mInner.Contains(position) : StatusChoice::NoChange;
? StatusChoice::EnteringQP
: StatusChoice::NoChange;
const bool changeInZone = (zone != mPrevZone); const bool changeInZone = (zone != mPrevZone);
const bool changing = evt.Leaving() || evt.Entering() || changeInZone; const bool changing = evt.Leaving() || evt.Entering() || changeInZone;
@ -2397,17 +2268,12 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
// Handle status bar messages // Handle status bar messages
UpdateStatusBarAndTooltips (changing ? zone : StatusChoice::NoChange); UpdateStatusBarAndTooltips (changing ? zone : StatusChoice::NoChange);
if ((IsButton(zone) || IsButton(mPrevZone)) &&
(changing || evt.Moving() || evt.Dragging()))
// So that the highlights in pushbuttons can update
Refresh(false);
mPrevZone = zone; mPrevZone = zone;
auto &scrubber = mProject->GetScrubber(); auto &scrubber = mProject->GetScrubber();
if (scrubber.HasStartedScrubbing()) { if (scrubber.HasStartedScrubbing()) {
if (IsButton(zone) || evt.RightDown()) if (evt.RightDown())
// Fall through to pushbutton handling // Fall through to context menu handling
; ;
else { else {
bool switchToQP = (zone == StatusChoice::EnteringQP && mQuickPlayEnabled); bool switchToQP = (zone == StatusChoice::EnteringQP && mQuickPlayEnabled);
@ -2480,14 +2346,10 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
return; return;
} }
if (HasCapture() && mCaptureState.button != StatusChoice::NoButton)
HandlePushbuttonEvent(evt);
else if (!HasCapture() && overButtons)
HandlePushbuttonClick(evt);
// Handle popup menus // Handle popup menus
else if (!HasCapture() && evt.RightDown() && !(evt.LeftIsDown())) { if (!HasCapture() && evt.RightDown() && !(evt.LeftIsDown())) {
ShowButtonMenu ShowContextMenu
(inScrubZone ? StatusChoice::ScrubBarButton : StatusChoice::QuickPlayButton, (inScrubZone ? MenuChoice::Scrub : MenuChoice::QuickPlay,
&position); &position);
return; return;
} }
@ -2689,8 +2551,6 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt)
HideQuickPlayIndicator(); HideQuickPlayIndicator();
mCaptureState = CaptureState{};
if (mPlayRegionEnd < mPlayRegionStart) { if (mPlayRegionEnd < mPlayRegionStart) {
// Swap values to ensure mPlayRegionStart < mPlayRegionEnd // Swap values to ensure mPlayRegionStart < mPlayRegionEnd
double tmp = mPlayRegionStart; double tmp = mPlayRegionStart;
@ -2806,39 +2666,32 @@ void AdornedRulerPanel::UpdateStatusBarAndTooltips(StatusChoice choice)
wxString message {}; wxString message {};
if (IsButton(choice)) { const auto &scrubber = mProject->GetScrubber();
bool state = GetButtonState(choice); const bool scrubbing = scrubber.HasStartedScrubbing();
const auto &strings = *GetPushButtonStrings(choice); if (scrubbing && choice != StatusChoice::Leaving)
message = wxGetTranslation(state ? strings.disable : strings.enable); // Don't distinguish zones
} choice = StatusChoice::EnteringScrubZone;
else {
const auto &scrubber = mProject->GetScrubber();
const bool scrubbing = scrubber.HasStartedScrubbing();
if (scrubbing && choice != StatusChoice::Leaving)
// Don't distinguish zones
choice = StatusChoice::EnteringScrubZone;
switch (choice) { switch (choice) {
case StatusChoice::EnteringQP: case StatusChoice::EnteringQP:
{ {
// message = Insert timeline status bar message here // message = Insert timeline status bar message here
}
break;
case StatusChoice::EnteringScrubZone:
{
if (scrubbing) {
if(!scrubber.IsAlwaysSeeking())
message = _("Click or drag to seek");
}
else
message = _("Click to scrub, Double-Click to scroll, Drag to seek");
}
break;
default:
break;
} }
break;
case StatusChoice::EnteringScrubZone:
{
if (scrubbing) {
if(!scrubber.IsAlwaysSeeking())
message = _("Click or drag to seek");
}
else
message = _("Click to scrub, Double-Click to scroll, Drag to seek");
}
break;
default:
break;
} }
// Display a message, or empty message // Display a message, or empty message
@ -2858,99 +2711,9 @@ void AdornedRulerPanel::OnToggleScrubbing(wxCommandEvent&)
PostSizeEventToParent(); PostSizeEventToParent();
} }
void AdornedRulerPanel::OnCaptureKey(wxCommandEvent &event)
{
wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
int keyCode = kevent->GetKeyCode();
switch (keyCode)
{
case WXK_DOWN:
case WXK_NUMPAD_DOWN:
case WXK_UP:
case WXK_NUMPAD_UP:
case WXK_TAB:
case WXK_NUMPAD_TAB:
case WXK_RIGHT:
case WXK_NUMPAD_RIGHT:
case WXK_LEFT:
case WXK_NUMPAD_LEFT:
case WXK_RETURN:
case WXK_NUMPAD_ENTER:
return;
}
event.Skip();
}
void AdornedRulerPanel::OnKeyDown(wxKeyEvent &event)
{
switch (event.GetKeyCode())
{
case WXK_DOWN:
case WXK_NUMPAD_DOWN:
// Always takes our focus away, so redraw.
mProject->GetTrackPanel()->OnNextTrack();
break;
case WXK_UP:
case WXK_NUMPAD_UP:
mProject->GetTrackPanel()->OnPrevTrack();
break;
case WXK_TAB:
case WXK_NUMPAD_TAB:
if (event.ShiftDown())
goto prev;
else
goto next;
case WXK_RIGHT:
case WXK_NUMPAD_RIGHT:
next:
++mTabState;
Refresh();
break;
case WXK_LEFT:
case WXK_NUMPAD_LEFT:
prev:
--mTabState;
Refresh();
break;
case WXK_RETURN:
case WXK_NUMPAD_ENTER:
if(mTabState.mMenu)
ShowButtonMenu(mTabState.mButton, nullptr);
else {
ToggleButtonState(mTabState.mButton);
Refresh();
}
break;
default:
event.Skip();
break;
}
}
void AdornedRulerPanel::OnSetFocus(wxFocusEvent & WXUNUSED(event))
{
AudacityProject::CaptureKeyboard(this);
mTabState = TabState{};
Refresh( false );
}
void AdornedRulerPanel::OnKillFocus(wxFocusEvent & WXUNUSED(event))
{
AudacityProject::ReleaseKeyboard(this);
Refresh(false);
}
void AdornedRulerPanel::OnContextMenu(wxContextMenuEvent & WXUNUSED(event)) void AdornedRulerPanel::OnContextMenu(wxContextMenuEvent & WXUNUSED(event))
{ {
ShowButtonMenu(mTabState.mButton, nullptr); ShowContextMenu(MenuChoice::QuickPlay, nullptr);
} }
void AdornedRulerPanel::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(evt)) void AdornedRulerPanel::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(evt))
@ -3022,11 +2785,8 @@ void AdornedRulerPanel::ShowScrubMenu(const wxPoint & pos)
auto cleanup = finally([this]{ PopEventHandler(); }); auto cleanup = finally([this]{ PopEventHandler(); });
wxMenu rulerMenu; wxMenu rulerMenu;
auto label = wxGetTranslation(
AdornedRulerPanel::PushbuttonLabels
[static_cast<int>(StatusChoice::ScrubBarButton)].label);
rulerMenu.AppendCheckItem(OnShowHideScrubbingID, _("Scrub Bar")); rulerMenu.AppendCheckItem(OnShowHideScrubbingID, _("Scrub Bar"));
if(GetButtonState(StatusChoice::ScrubBarButton)) if(mShowScrubbing)
rulerMenu.FindItem(OnShowHideScrubbingID)->Check(); rulerMenu.FindItem(OnShowHideScrubbingID)->Check();
rulerMenu.AppendSeparator(); rulerMenu.AppendSeparator();
@ -3162,329 +2922,31 @@ void AdornedRulerPanel::DoDrawPlayRegion(wxDC * dc)
} }
} }
wxRect AdornedRulerPanel::GetButtonAreaRect(bool includeBorder) const void AdornedRulerPanel::ShowContextMenu( MenuChoice choice, const wxPoint *pPosition)
{ {
int x, y, bottomMargin;
if(includeBorder)
x = 0, y = 0, bottomMargin = 0;
else {
x = std::max(LeftMargin, FocusBorderLeft);
y = std::max(TopMargin, FocusBorderTop);
bottomMargin = std::max(BottomMargin, FocusBorderBottom);
}
wxRect rect {
x, y,
mProject->GetTrackPanel()->GetLeftOffset() - x,
GetRulerHeight() - y - bottomMargin
};
// Leave room for one digit on the ruler, so "0.0" is not obscured if you go to start.
// But the digit string at the left end may be longer if you are not at the start.
// Perhaps there should be room for more than one digit.
wxScreenDC dc;
dc.SetFont(*mRuler.GetFonts().major);
rect.width -= dc.GetTextExtent(wxT("0")).GetWidth();
return rect;
}
wxRect AdornedRulerPanel::GetButtonRect( StatusChoice button ) const
{
if (!IsButton(button))
return wxRect {};
wxRect rect { GetButtonAreaRect() };
// Reduce the height
rect.height -= (GetRulerHeight() - ProperRulerHeight);
auto num = static_cast<unsigned>(button);
auto denom = static_cast<unsigned>(StatusChoice::NumButtons);
rect.x += (num * rect.width) / denom;
rect.width = (((1 + num) * rect.width) / denom) - rect.x;
return rect;
}
auto AdornedRulerPanel::InButtonRect( StatusChoice button, wxMouseEvent *pEvent ) const
-> PointerState
{
auto rect = GetButtonRect(button);
auto state = pEvent ? *pEvent : ::wxGetMouseState();
auto point = pEvent ? pEvent->GetPosition() : ScreenToClient(state.GetPosition());
if(!rect.Contains(point))
return PointerState::Out;
else {
auto rightDown = state.RightIsDown()
#ifdef __WXMAC__
// make drag with Mac Control down act like right drag
|| (state.RawControlDown() && state.ButtonIsDown(wxMOUSE_BTN_ANY))
#endif
;
if(rightDown ||
(pEvent && pEvent->RightUp()) ||
GetArrowRect(rect).Contains(point))
return PointerState::InArrow;
else
return PointerState::In;
}
}
auto AdornedRulerPanel::FindButton( wxMouseEvent &mouseEvent ) const
-> CaptureState
{
for (auto button = StatusChoice::FirstButton; IsButton(button); ++button) {
auto state = InButtonRect( button, &mouseEvent );
if (state != PointerState::Out)
return CaptureState{ button, state };
}
return { StatusChoice::NoButton, PointerState::Out };
}
bool AdornedRulerPanel::GetButtonState( StatusChoice button ) const
{
switch(button) {
case StatusChoice::QuickPlayButton:
return mQuickPlayEnabled;
case StatusChoice::ScrubBarButton:
return mShowScrubbing;
default:
wxASSERT(false);
return false;
}
}
void AdornedRulerPanel::ToggleButtonState( StatusChoice button )
{
wxCommandEvent dummy;
switch(button) {
case StatusChoice::QuickPlayButton:
OnToggleQuickPlay(dummy);
break;
case StatusChoice::ScrubBarButton:
OnToggleScrubbing(dummy);
break;
default:
wxASSERT(false);
}
UpdateStatusBarAndTooltips(mCaptureState.button);
}
void AdornedRulerPanel::ShowButtonMenu( StatusChoice button, const wxPoint *pPosition)
{
if (!IsButton(button))
return;
wxPoint position; wxPoint position;
if(pPosition) if(pPosition)
position = *pPosition; position = *pPosition;
else else
{ {
auto rect = GetArrowRect(GetButtonRect(button)); auto rect = GetRect();
position = { rect.GetLeft() + 1, rect.GetBottom() + 1 }; position = { rect.GetLeft() + 1, rect.GetBottom() + 1 };
} }
// Be sure the arrow button appears pressed switch (choice) {
mTabState = { button, true }; case MenuChoice::QuickPlay:
mShowingMenu = true; ShowMenu(position); break;
Refresh(); case MenuChoice::Scrub:
ShowScrubMenu(position); break;
// Do the rest after Refresh() takes effect default:
CallAfter([=]{ return;
switch (button) {
case StatusChoice::QuickPlayButton:
ShowMenu(position); break;
case StatusChoice::ScrubBarButton:
ShowScrubMenu(position); break;
default:
return;
}
// dismiss and clear Quick-Play indicator
HideQuickPlayIndicator();
if (HasCapture())
ReleaseMouse();
mShowingMenu = false;
Refresh();
});
}
const AdornedRulerPanel::ButtonStrings AdornedRulerPanel::PushbuttonLabels
[static_cast<size_t>(StatusChoice::NumButtons)]
{
{ XO("Quick-Play"), XO("Enable Quick-Play"), XO("Disable Quick-Play") },
/* i18n-hint: A long screen area (bar) controlling variable speed play (scrubbing) */
{ XO("Scrub Bar"), XO("Show Scrub Bar"), XO("Hide Scrub Bar") },
};
namespace {
void DrawButtonBackground(wxDC *dc, const wxRect &rect, bool down, bool highlight) {
// Choose the pen
if (highlight)
AColor::Light(dc, false);
else
// This color choice corresponds to part of TrackInfo::DrawBordersWithin() :
AColor::Dark(dc, false);
auto pen = dc->GetPen();
// pen.SetWidth(2);
// Choose the brush
if (down)
AColor::Solo(dc, true, false);
else
AColor::MediumTrackInfo(dc, false);
dc->SetPen(pen);
dc->DrawRectangle(rect);
// Draw the bevel
auto rect2 = rect.Deflate(1, 1);
Deflator def(rect2);
AColor::BevelTrackInfo(*dc, !down, rect2);
}
}
void AdornedRulerPanel::DoDrawPushbutton
(wxDC *dc, StatusChoice button, bool buttonState, bool arrowState) const
{
// Adapted from TrackInfo::DrawMuteSolo()
ADCChanger changer(dc);
const auto rect = GetButtonRect( button );
const auto arrowRect = GetArrowRect(rect);
auto arrowBev = arrowRect.Deflate(1, 1);
const auto textRect = GetTextRect(rect);
auto textBev = textRect.Deflate(1, 1);
// Draw borders, bevels, and backgrounds of the split sections
const bool tabHighlight =
mTabState.mButton == button &&
(HasFocus() || rect.Contains( ScreenToClient(::wxGetMousePosition()) ));
if (tabHighlight)
arrowState = arrowState || mShowingMenu;
if (tabHighlight && mTabState.mMenu) {
// Draw highlighted arrow after
DrawButtonBackground(dc, textRect, buttonState, false);
DrawButtonBackground(dc, arrowRect, arrowState, true);
}
else {
// Draw maybe highlighted text after
DrawButtonBackground(dc, arrowRect, arrowState, false);
DrawButtonBackground(dc, textRect, buttonState, (tabHighlight && !mTabState.mMenu));
} }
// Draw the menu triangle // dismiss and clear Quick-Play indicator
{ HideQuickPlayIndicator();
auto x = arrowBev.GetX() + ArrowSpacing;
auto y = arrowBev.GetY() + (arrowBev.GetHeight() - ArrowHeight) / 2;
// Color it as in TrackInfo::DrawTitleBar if (HasCapture())
#ifdef EXPERIMENTAL_THEMING ReleaseMouse();
wxColour c = theTheme.Colour( clrTrackPanelText );
#else
wxColour c = *wxBLACK;
#endif
//if (pointerState == PointerState::InArrow)
dc->SetBrush( wxBrush{ c } );
//else
//dc->SetBrush( wxBrush{ *wxTRANSPARENT_BRUSH } ); // Make outlined arrow only
dc->SetPen( wxPen{ c } );
// This function draws an arrow half as tall as wide:
AColor::Arrow(*dc, x, y, ArrowWidth);
}
// Draw the text
{
dc->SetTextForeground(theTheme.Colour(clrTrackPanelText));
wxCoord textWidth, textHeight;
wxString str = wxGetTranslation(GetPushButtonStrings(button)->label);
dc->SetFont(GetButtonFont());
dc->GetTextExtent(str, &textWidth, &textHeight);
auto xx = textBev.x + (textBev.width - textWidth) / 2;
auto yy = textBev.y + (textBev.height - textHeight) / 2;
if (buttonState)
// Shift the text a bit for "down" appearance
++xx, ++yy;
dc->DrawText(str, xx, yy);
}
}
void AdornedRulerPanel::HandlePushbuttonClick(wxMouseEvent &evt)
{
auto pair = FindButton(evt);
auto button = pair.button;
if (IsButton(button) && evt.ButtonDown()) {
CaptureMouse();
mCaptureState = pair;
Refresh();
}
}
void AdornedRulerPanel::HandlePushbuttonEvent(wxMouseEvent &evt)
{
if(evt.ButtonUp()) {
if(HasCapture())
ReleaseMouse();
auto button = mCaptureState.button;
auto capturedIn = mCaptureState.state;
auto in = InButtonRect(button, &evt);
if (in != capturedIn)
;
else if (in == PointerState::In)
ToggleButtonState(button);
else
ShowButtonMenu(button, nullptr);
mCaptureState = CaptureState{};
}
Refresh();
}
void AdornedRulerPanel::DoDrawPushbuttons(wxDC *dc) const
{
// Paint the area behind the buttons
wxRect background = GetButtonAreaRect();
#ifndef SCRUB_ABOVE
// Reduce the height
background.y = mInner.y;
background.height = mInner.height;
#endif
AColor::MediumTrackInfo(dc, false);
dc->DrawRectangle(background);
for (auto button = StatusChoice::FirstButton; IsButton(button); ++button) {
bool buttonState = GetButtonState(button);
bool arrowState = false;
if (button == mCaptureState.button) {
auto in = InButtonRect(button, nullptr);
if (in == mCaptureState.state) {
if (in == PointerState::In) {
// Toggle button's apparent state for mouseover
buttonState = !buttonState;
}
else if (in == PointerState::InArrow) {
// Menu arrow is not sticky
arrowState = true;
}
}
}
DoDrawPushbutton(dc, button, buttonState, arrowState);
}
} }
void AdornedRulerPanel::DoDrawBackground(wxDC * dc) void AdornedRulerPanel::DoDrawBackground(wxDC * dc)

View File

@ -318,37 +318,11 @@ public:
void ReCreateButtons(); void ReCreateButtons();
enum class StatusChoice { enum class StatusChoice {
FirstButton = 0, EnteringQP,
QuickPlayButton = FirstButton,
ScrubBarButton,
NumButtons,
LastButton = NumButtons - 1,
NoButton = -1,
EnteringQP = NumButtons,
EnteringScrubZone, EnteringScrubZone,
Leaving, Leaving,
NoChange NoChange
}; };
enum class PointerState {
Out = 0, In, InArrow
};
struct CaptureState {
CaptureState() {}
CaptureState(StatusChoice s, PointerState p) : button(s), state(p) {}
StatusChoice button { StatusChoice::NoButton };
PointerState state { PointerState::Out };
};
friend inline StatusChoice &operator++ (StatusChoice &choice) {
choice = static_cast<StatusChoice>(1 + static_cast<int>(choice));
return choice;
}
friend inline StatusChoice &operator-- (StatusChoice &choice) {
choice = static_cast<StatusChoice>(-1 + static_cast<int>(choice));
return choice;
}
void RegenerateTooltips(StatusChoice choice); void RegenerateTooltips(StatusChoice choice);
@ -368,15 +342,6 @@ private:
void HandleQPRelease(wxMouseEvent &event); void HandleQPRelease(wxMouseEvent &event);
void StartQPPlay(bool looped, bool cutPreview); void StartQPPlay(bool looped, bool cutPreview);
static inline bool IsButton(StatusChoice choice)
{
auto integer = static_cast<int>(choice);
return integer >= 0 &&
integer < static_cast<int>(StatusChoice::NumButtons);
}
static inline bool IsButton(int choice)
{ return IsButton(static_cast<StatusChoice>(choice)); }
void UpdateStatusBarAndTooltips(StatusChoice choice); void UpdateStatusBarAndTooltips(StatusChoice choice);
void OnCaptureLost(wxMouseCaptureLostEvent &evt); void OnCaptureLost(wxMouseCaptureLostEvent &evt);
@ -393,32 +358,8 @@ private:
void ShowOrHideQuickPlayIndicator(bool show); void ShowOrHideQuickPlayIndicator(bool show);
void DoDrawPlayRegion(wxDC * dc); void DoDrawPlayRegion(wxDC * dc);
wxRect GetButtonAreaRect(bool includeBorder = false) const; enum class MenuChoice { QuickPlay, Scrub };
void ShowContextMenu( MenuChoice choice, const wxPoint *pPosition);
struct ButtonStrings {
wxString label, enable, disable;
};
static const ButtonStrings PushbuttonLabels[];
static const ButtonStrings *GetPushButtonStrings(StatusChoice choice)
{
if(IsButton(choice))
return &PushbuttonLabels[static_cast<size_t>(choice)];
return nullptr;
}
wxRect GetButtonRect( StatusChoice button ) const;
PointerState InButtonRect( StatusChoice button, wxMouseEvent *pEvent ) const;
CaptureState FindButton( wxMouseEvent &mouseEvent ) const;
bool GetButtonState( StatusChoice button ) const;
void ToggleButtonState( StatusChoice button );
void ShowButtonMenu( StatusChoice button, const wxPoint *pPosition);
void DoDrawPushbutton
(wxDC *dc, StatusChoice button, bool buttonState, bool arrowState) const;
void DoDrawPushbuttons(wxDC *dc) const;
void HandlePushbuttonClick(wxMouseEvent &evt);
void HandlePushbuttonEvent(wxMouseEvent &evt);
wxFont &GetButtonFont() const;
double Pos2Time(int p, bool ignoreFisheye = false); double Pos2Time(int p, bool ignoreFisheye = false);
int Time2Pos(double t, bool ignoreFisheye = false); int Time2Pos(double t, bool ignoreFisheye = false);
@ -473,18 +414,12 @@ private:
void OnToggleScrubbing(wxCommandEvent&); void OnToggleScrubbing(wxCommandEvent&);
void OnCaptureKey(wxCommandEvent &event);
void OnKeyDown(wxKeyEvent &event);
void OnSetFocus(wxFocusEvent &);
void OnKillFocus(wxFocusEvent &);
void OnContextMenu(wxContextMenuEvent & WXUNUSED(event)); void OnContextMenu(wxContextMenuEvent & WXUNUSED(event));
bool mPlayRegionDragsSelection; bool mPlayRegionDragsSelection;
bool mTimelineToolTip; bool mTimelineToolTip;
bool mQuickPlayEnabled; bool mQuickPlayEnabled;
CaptureState mCaptureState {};
enum MouseEventState { enum MouseEventState {
mesNone, mesNone,
mesDraggingPlayRegionStart, mesDraggingPlayRegionStart,
@ -502,49 +437,9 @@ private:
StatusChoice mPrevZone { StatusChoice::NoChange }; StatusChoice mPrevZone { StatusChoice::NoChange };
struct TabState {
StatusChoice mButton { StatusChoice::FirstButton };
bool mMenu { false };
TabState() {}
TabState(StatusChoice button, bool menu)
: mButton{ button }, mMenu{ menu } {}
bool operator == (const TabState &rhs) const
{ return mButton == rhs.mButton && mMenu == rhs.mMenu; }
bool operator != (const TabState &rhs) const { return !(*this == rhs); }
TabState &operator ++ () {
if (!mMenu)
mMenu = true;
else {
mMenu = false;
if (!IsButton (++mButton))
mButton = StatusChoice::FirstButton;
}
return *this;
}
TabState &operator -- () {
if (mMenu)
mMenu = false;
else {
mMenu = true;
if (!IsButton (--mButton))
mButton = StatusChoice::LastButton;
}
return *this;
}
};
TabState mTabState;
bool mShowScrubbing { true }; bool mShowScrubbing { true };
mutable int mButtonFontSize { -1 };
mutable wxFont mButtonFont;
bool mDoubleClick {}; bool mDoubleClick {};
bool mShowingMenu {};
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()