Split base class CellularPanel out of TrackPanel...
... To be reused with the Ruler too. The new base class does all the handling of hit tests on cells and managing of UIHandles, and keyboard events and focus. It has no knowledge of tracks -- that all resides in overriding functions in TrackPanel. Still to do, of course, is reorganizing drawing with callbacks to the cell objects.
This commit is contained in:
parent
d76777bef7
commit
062066eb79
|
@ -254,16 +254,22 @@ template < class A, class B, class DIST > bool within(A a, B b, DIST d)
|
|||
return (a > b - d) && (a < b + d);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(TrackPanel, OverlayPanel)
|
||||
BEGIN_EVENT_TABLE(CellularPanel, OverlayPanel)
|
||||
EVT_MOUSE_EVENTS(CellularPanel::OnMouseEvent)
|
||||
EVT_MOUSE_CAPTURE_LOST(CellularPanel::OnCaptureLost)
|
||||
EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, CellularPanel::OnCaptureKey)
|
||||
EVT_KEY_DOWN(CellularPanel::OnKeyDown)
|
||||
EVT_KEY_UP(CellularPanel::OnKeyUp)
|
||||
EVT_CHAR(CellularPanel::OnChar)
|
||||
EVT_SET_FOCUS(CellularPanel::OnSetFocus)
|
||||
EVT_KILL_FOCUS(CellularPanel::OnKillFocus)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
BEGIN_EVENT_TABLE(TrackPanel, CellularPanel)
|
||||
EVT_MOUSE_EVENTS(TrackPanel::OnMouseEvent)
|
||||
EVT_MOUSE_CAPTURE_LOST(TrackPanel::OnCaptureLost)
|
||||
EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, TrackPanel::OnCaptureKey)
|
||||
EVT_KEY_DOWN(TrackPanel::OnKeyDown)
|
||||
EVT_KEY_UP(TrackPanel::OnKeyUp)
|
||||
EVT_CHAR(TrackPanel::OnChar)
|
||||
|
||||
EVT_PAINT(TrackPanel::OnPaint)
|
||||
EVT_SET_FOCUS(TrackPanel::OnSetFocus)
|
||||
EVT_KILL_FOCUS(TrackPanel::OnKillFocus)
|
||||
EVT_CONTEXT_MENU(TrackPanel::OnContextMenu)
|
||||
|
||||
EVT_TIMER(wxID_ANY, TrackPanel::OnTimer)
|
||||
|
@ -301,11 +307,11 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
|
|||
ViewInfo * viewInfo,
|
||||
TrackPanelListener * listener,
|
||||
AdornedRulerPanel * ruler)
|
||||
: OverlayPanel(parent, id, pos, size, wxWANTS_CHARS | wxNO_BORDER),
|
||||
: CellularPanel(parent, id, pos, size, viewInfo,
|
||||
wxWANTS_CHARS | wxNO_BORDER),
|
||||
mTrackInfo(this),
|
||||
mListener(listener),
|
||||
mTracks(tracks),
|
||||
mViewInfo(viewInfo),
|
||||
mRuler(ruler),
|
||||
mTrackArtist(nullptr),
|
||||
mRefreshBacking(false),
|
||||
|
@ -614,7 +620,7 @@ void TrackPanel::MakeParentRedrawScrollbars()
|
|||
mListener->TP_RedrawScrollbars();
|
||||
}
|
||||
|
||||
void TrackPanel::HandleInterruptedDrag()
|
||||
void CellularPanel::HandleInterruptedDrag()
|
||||
{
|
||||
if (mUIHandle && mUIHandle->StopsOnKeystroke() ) {
|
||||
// The bogus id isn't used anywhere, but may help with debugging.
|
||||
|
@ -718,7 +724,7 @@ void TrackPanel::ProcessUIHandleResult
|
|||
panel->EnsureVisible(pClickedTrack);
|
||||
}
|
||||
|
||||
void TrackPanel::Uncapture(wxMouseState *pState)
|
||||
void CellularPanel::Uncapture(wxMouseState *pState)
|
||||
{
|
||||
auto state = ::wxGetMouseState();
|
||||
if (!pState) {
|
||||
|
@ -732,7 +738,7 @@ void TrackPanel::Uncapture(wxMouseState *pState)
|
|||
HandleMotion( *pState );
|
||||
}
|
||||
|
||||
bool TrackPanel::CancelDragging()
|
||||
bool CellularPanel::CancelDragging()
|
||||
{
|
||||
if (mUIHandle) {
|
||||
// copy shared_ptr for safety, as in HandleClick
|
||||
|
@ -752,7 +758,7 @@ bool TrackPanel::CancelDragging()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TrackPanel::HandleEscapeKey(bool down)
|
||||
bool CellularPanel::HandleEscapeKey(bool down)
|
||||
{
|
||||
if (!down)
|
||||
return false;
|
||||
|
@ -778,7 +784,7 @@ bool TrackPanel::HandleEscapeKey(bool down)
|
|||
return false;
|
||||
}
|
||||
|
||||
void TrackPanel::UpdateMouseState(const wxMouseState &state)
|
||||
void CellularPanel::UpdateMouseState(const wxMouseState &state)
|
||||
{
|
||||
mLastMouseState = state;
|
||||
|
||||
|
@ -798,7 +804,7 @@ void TrackPanel::UpdateMouseState(const wxMouseState &state)
|
|||
}
|
||||
}
|
||||
|
||||
void TrackPanel::HandleModifierKey()
|
||||
void CellularPanel::HandleModifierKey()
|
||||
{
|
||||
HandleCursorForPresentMouseState();
|
||||
}
|
||||
|
@ -813,7 +819,7 @@ void TrackPanel::HandlePageDownKey()
|
|||
mListener->TP_ScrollWindow(GetScreenEndTime());
|
||||
}
|
||||
|
||||
void TrackPanel::HandleCursorForPresentMouseState(bool doHit)
|
||||
void CellularPanel::HandleCursorForPresentMouseState(bool doHit)
|
||||
{
|
||||
// Come here on modifier key or mouse button transitions,
|
||||
// or on starting or stopping of play or record,
|
||||
|
@ -842,7 +848,7 @@ bool TrackPanel::IsAudioActive()
|
|||
/// may cause the appropriate cursor and message to change.
|
||||
/// As this procedure checks which region the mouse is over, it is
|
||||
/// appropriate to establish the message in the status bar.
|
||||
void TrackPanel::HandleMotion( wxMouseState &inState, bool doHit )
|
||||
void CellularPanel::HandleMotion( wxMouseState &inState, bool doHit )
|
||||
{
|
||||
UpdateMouseState( inState );
|
||||
|
||||
|
@ -853,7 +859,7 @@ void TrackPanel::HandleMotion( wxMouseState &inState, bool doHit )
|
|||
HandleMotion( tpmState, doHit );
|
||||
}
|
||||
|
||||
void TrackPanel::HandleMotion
|
||||
void CellularPanel::HandleMotion
|
||||
( const TrackPanelMouseState &tpmState, bool doHit )
|
||||
{
|
||||
auto handle = mUIHandle;
|
||||
|
@ -955,11 +961,8 @@ void TrackPanel::HandleMotion
|
|||
pCursor = &defaultCursor;
|
||||
}
|
||||
|
||||
if (HasEscape())
|
||||
/* i18n-hint Esc is a key on the keyboard */
|
||||
status += wxT(" "), status += _("(Esc to cancel)");
|
||||
mListener->TP_DisplayStatusMessage(status);
|
||||
|
||||
UpdateStatusMessage(status);
|
||||
|
||||
#if wxUSE_TOOLTIPS
|
||||
if (tooltip != GetToolTipText()) {
|
||||
// Unset first, by analogy with AButton
|
||||
|
@ -975,7 +978,16 @@ void TrackPanel::HandleMotion
|
|||
newCell.get(), newCell.get(), refreshCode);
|
||||
}
|
||||
|
||||
bool TrackPanel::HasRotation()
|
||||
void TrackPanel::UpdateStatusMessage( const wxString &st )
|
||||
{
|
||||
auto status = st;
|
||||
if (HasEscape())
|
||||
/* i18n-hint Esc is a key on the keyboard */
|
||||
status += wxT(" "), status += _("(Esc to cancel)");
|
||||
mListener->TP_DisplayStatusMessage(status);
|
||||
}
|
||||
|
||||
bool CellularPanel::HasRotation()
|
||||
{
|
||||
// Is there a nontrivial TAB key rotation?
|
||||
if ( mTargets.size() > 1 )
|
||||
|
@ -984,7 +996,7 @@ bool TrackPanel::HasRotation()
|
|||
return target && target->HasRotation();
|
||||
}
|
||||
|
||||
bool TrackPanel::HasEscape()
|
||||
bool CellularPanel::HasEscape()
|
||||
{
|
||||
if (IsMouseCaptured())
|
||||
return true;
|
||||
|
@ -997,7 +1009,7 @@ bool TrackPanel::HasEscape()
|
|||
return mTargets.size() > 0;
|
||||
}
|
||||
|
||||
bool TrackPanel::ChangeTarget(bool forward, bool cycle)
|
||||
bool CellularPanel::ChangeTarget(bool forward, bool cycle)
|
||||
{
|
||||
auto size = mTargets.size();
|
||||
|
||||
|
@ -1090,7 +1102,7 @@ void TrackPanel::MessageForScreenReader(const wxString& message)
|
|||
}
|
||||
|
||||
/// Determines if a modal tool is active
|
||||
bool TrackPanel::IsMouseCaptured()
|
||||
bool CellularPanel::IsMouseCaptured()
|
||||
{
|
||||
return mUIHandle != NULL;
|
||||
}
|
||||
|
@ -1140,9 +1152,9 @@ void TrackPanel::OnTrackListResizing(wxCommandEvent & e)
|
|||
// Tracks have been removed from the list.
|
||||
void TrackPanel::OnTrackListDeletion(wxCommandEvent & e)
|
||||
{
|
||||
if (mUIHandle) {
|
||||
// copy shared_ptr for safety, as in HandleClick
|
||||
auto handle = mUIHandle;
|
||||
// copy shared_ptr for safety, as in HandleClick
|
||||
auto handle = Target();
|
||||
if (handle) {
|
||||
handle->OnProjectChange(GetProject());
|
||||
}
|
||||
|
||||
|
@ -1349,7 +1361,7 @@ bool TrackInfo::HideTopItem( const wxRect &rect, const wxRect &subRect,
|
|||
}
|
||||
|
||||
/// Handle mouse wheel rotation (for zoom in/out, vertical and horizontal scrolling)
|
||||
void TrackPanel::HandleWheelRotation( TrackPanelMouseEvent &tpmEvent )
|
||||
void CellularPanel::HandleWheelRotation( TrackPanelMouseEvent &tpmEvent )
|
||||
{
|
||||
auto pCell = tpmEvent.pCell;
|
||||
if (!pCell)
|
||||
|
@ -1395,7 +1407,7 @@ void TrackPanel::HandleWheelRotation( TrackPanelMouseEvent &tpmEvent )
|
|||
pCell.get(), pCell.get(), result);
|
||||
}
|
||||
|
||||
void TrackPanel::OnCaptureKey(wxCommandEvent & event)
|
||||
void CellularPanel::OnCaptureKey(wxCommandEvent & event)
|
||||
{
|
||||
mEnableTab = false;
|
||||
wxKeyEvent *kevent = static_cast<wxKeyEvent *>(event.GetEventObject());
|
||||
|
@ -1403,19 +1415,17 @@ void TrackPanel::OnCaptureKey(wxCommandEvent & event)
|
|||
if ( WXK_ESCAPE != code )
|
||||
HandleInterruptedDrag();
|
||||
|
||||
// TODO? Some notion of focused cell, more generally than focused tracks
|
||||
|
||||
// Give focused track precedence
|
||||
Track * const t = GetFocusedTrack();
|
||||
// Give focused cell precedence
|
||||
const auto t = GetFocusedCell();
|
||||
if (t) {
|
||||
const unsigned refreshResult =
|
||||
((TrackPanelCell*)t)->CaptureKey(*kevent, *mViewInfo, this);
|
||||
t->CaptureKey(*kevent, *mViewInfo, this);
|
||||
ProcessUIHandleResult(t, t, refreshResult);
|
||||
event.Skip(kevent->GetSkipped());
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Special TAB key handling, but only if the track didn't capture it
|
||||
// Special TAB key handling, but only if the cell didn't capture it
|
||||
if ( !(t && !kevent->GetSkipped()) &&
|
||||
WXK_TAB == code && HasRotation() ) {
|
||||
// Override TAB navigation in wxWidgets, by not skipping
|
||||
|
@ -1430,6 +1440,26 @@ void TrackPanel::OnCaptureKey(wxCommandEvent & event)
|
|||
}
|
||||
|
||||
void TrackPanel::OnKeyDown(wxKeyEvent & event)
|
||||
{
|
||||
switch (event.GetKeyCode())
|
||||
{
|
||||
// Allow PageUp and PageDown keys to
|
||||
//scroll the Track Panel left and right
|
||||
case WXK_PAGEUP:
|
||||
HandlePageUpKey();
|
||||
return;
|
||||
|
||||
case WXK_PAGEDOWN:
|
||||
HandlePageDownKey();
|
||||
return;
|
||||
|
||||
default:
|
||||
// fall through to base class handler
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularPanel::OnKeyDown(wxKeyEvent & event)
|
||||
{
|
||||
switch (event.GetKeyCode())
|
||||
{
|
||||
|
@ -1450,16 +1480,6 @@ void TrackPanel::OnKeyDown(wxKeyEvent & event)
|
|||
HandleModifierKey();
|
||||
break;
|
||||
|
||||
// Allow PageUp and PageDown keys to
|
||||
//scroll the Track Panel left and right
|
||||
case WXK_PAGEUP:
|
||||
HandlePageUpKey();
|
||||
return;
|
||||
|
||||
case WXK_PAGEDOWN:
|
||||
HandlePageDownKey();
|
||||
return;
|
||||
|
||||
#if 0
|
||||
case WXK_TAB:
|
||||
if ( mEnableTab && HasRotation() ) {
|
||||
|
@ -1472,18 +1492,18 @@ void TrackPanel::OnKeyDown(wxKeyEvent & event)
|
|||
#endif
|
||||
}
|
||||
|
||||
Track *const t = GetFocusedTrack();
|
||||
const auto t = GetFocusedCell();
|
||||
|
||||
if (t) {
|
||||
const unsigned refreshResult =
|
||||
((TrackPanelCell*)t)->KeyDown(event, *mViewInfo, this);
|
||||
t->KeyDown(event, *mViewInfo, this);
|
||||
ProcessUIHandleResult(t, t, refreshResult);
|
||||
}
|
||||
else
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void TrackPanel::OnChar(wxKeyEvent & event)
|
||||
void CellularPanel::OnChar(wxKeyEvent & event)
|
||||
{
|
||||
switch (event.GetKeyCode())
|
||||
{
|
||||
|
@ -1496,17 +1516,17 @@ void TrackPanel::OnChar(wxKeyEvent & event)
|
|||
return;
|
||||
}
|
||||
|
||||
Track *const t = GetFocusedTrack();
|
||||
const auto t = GetFocusedCell();
|
||||
if (t) {
|
||||
const unsigned refreshResult =
|
||||
((TrackPanelCell*)t)->Char(event, *mViewInfo, this);
|
||||
t->Char(event, *mViewInfo, this);
|
||||
ProcessUIHandleResult(t, t, refreshResult);
|
||||
}
|
||||
else
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void TrackPanel::OnKeyUp(wxKeyEvent & event)
|
||||
void CellularPanel::OnKeyUp(wxKeyEvent & event)
|
||||
{
|
||||
bool didSomething = false;
|
||||
switch (event.GetKeyCode())
|
||||
|
@ -1528,10 +1548,10 @@ void TrackPanel::OnKeyUp(wxKeyEvent & event)
|
|||
if (didSomething)
|
||||
return;
|
||||
|
||||
Track * const t = GetFocusedTrack();
|
||||
const auto t = GetFocusedCell();
|
||||
if (t) {
|
||||
const unsigned refreshResult =
|
||||
((TrackPanelCell*)t)->KeyUp(event, *mViewInfo, this);
|
||||
t->KeyUp(event, *mViewInfo, this);
|
||||
ProcessUIHandleResult(t, t, refreshResult);
|
||||
return;
|
||||
}
|
||||
|
@ -1540,7 +1560,7 @@ void TrackPanel::OnKeyUp(wxKeyEvent & event)
|
|||
}
|
||||
|
||||
/// Should handle the case when the mouse capture is lost.
|
||||
void TrackPanel::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(event))
|
||||
void CellularPanel::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(event))
|
||||
{
|
||||
ClearTargets();
|
||||
|
||||
|
@ -1554,10 +1574,37 @@ void TrackPanel::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(event))
|
|||
OnMouseEvent(e);
|
||||
}
|
||||
|
||||
void TrackPanel::OnMouseEvent(wxMouseEvent & event)
|
||||
{
|
||||
if (event.LeftDown()) {
|
||||
// wxTimers seem to be a little unreliable, so this
|
||||
// "primes" it to make sure it keeps going for a while...
|
||||
|
||||
// When this timer fires, we call TrackPanel::OnTimer and
|
||||
// possibly update the screen for offscreen scrolling.
|
||||
mTimer.Stop();
|
||||
mTimer.Start(kTimerInterval, FALSE);
|
||||
}
|
||||
|
||||
|
||||
if (event.ButtonUp()) {
|
||||
//EnsureVisible should be called after processing the up-click.
|
||||
this->CallAfter( [this, event]{
|
||||
const auto foundCell = FindCell(event.m_x, event.m_y);
|
||||
const auto t = FindTrack( foundCell.pCell.get() );
|
||||
if ( t )
|
||||
EnsureVisible(t.get());
|
||||
} );
|
||||
}
|
||||
|
||||
// Must also fall through to base class handler
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
/// This handles just generic mouse events. Then, based
|
||||
/// on our current state, we forward the mouse events to
|
||||
/// various interested parties.
|
||||
void TrackPanel::OnMouseEvent(wxMouseEvent & event)
|
||||
void CellularPanel::OnMouseEvent(wxMouseEvent & event)
|
||||
try
|
||||
{
|
||||
const auto foundCell = FindCell( event.m_x, event.m_y );
|
||||
|
@ -1578,7 +1625,7 @@ try
|
|||
|
||||
// If a mouse event originates from a keyboard context menu event then
|
||||
// event.GetPosition() == wxDefaultPosition. wxContextMenu events are handled in
|
||||
// TrackPanel::OnContextMenu(), and therefore associated mouse events are ignored here.
|
||||
// CellularPanel::OnContextMenu(), and therefore associated mouse events are ignored here.
|
||||
// Not ignoring them was causing bug 613: the mouse events were interpreted as clicking
|
||||
// outside the tracks.
|
||||
if (event.GetPosition() == wxDefaultPosition && (event.RightDown() || event.RightUp())) {
|
||||
|
@ -1604,14 +1651,6 @@ try
|
|||
// parent window 'come alive' if it didn't have focus.
|
||||
wxActivateEvent e;
|
||||
GetParent()->GetEventHandler()->ProcessEvent(e);
|
||||
|
||||
// wxTimers seem to be a little unreliable, so this
|
||||
// "primes" it to make sure it keeps going for a while...
|
||||
|
||||
// When this timer fires, we call TrackPanel::OnTimer and
|
||||
// possibly update the screen for offscreen scrolling.
|
||||
mTimer.Stop();
|
||||
mTimer.Start(kTimerInterval, FALSE);
|
||||
}
|
||||
|
||||
if (event.ButtonDown()) {
|
||||
|
@ -1692,17 +1731,8 @@ try
|
|||
CaptureMouse();
|
||||
}
|
||||
|
||||
//EnsureVisible should be called after the up-click.
|
||||
if (event.ButtonUp()) {
|
||||
if (event.ButtonUp())
|
||||
Uncapture();
|
||||
|
||||
wxRect rect;
|
||||
|
||||
const auto foundCell = FindCell(event.m_x, event.m_y);
|
||||
const auto t = FindTrack( foundCell.pCell.get() );
|
||||
if ( t )
|
||||
EnsureVisible(t.get());
|
||||
}
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
|
@ -1716,7 +1746,7 @@ catch( ... )
|
|||
throw;
|
||||
}
|
||||
|
||||
void TrackPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
|
||||
void CellularPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
|
||||
{
|
||||
auto pCell = tpmEvent.pCell;
|
||||
|
||||
|
@ -1762,7 +1792,7 @@ void TrackPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent )
|
|||
|
||||
double TrackPanel::GetMostRecentXPos()
|
||||
{
|
||||
return mViewInfo->PositionToTime(mMouseMostRecentX, GetLabelWidth());
|
||||
return mViewInfo->PositionToTime(MostRecentXCoord(), GetLabelWidth());
|
||||
}
|
||||
|
||||
void TrackPanel::RefreshTrack(Track *trk, bool refreshbacking)
|
||||
|
@ -2779,7 +2809,7 @@ void TrackPanel::DrawShadow(Track * /* t */ , wxDC * dc, const wxRect & rect)
|
|||
/// Determines which cell is under the mouse
|
||||
/// @param mouseX - mouse X position.
|
||||
/// @param mouseY - mouse Y position.
|
||||
TrackPanel::FoundCell TrackPanel::FindCell(int mouseX, int mouseY)
|
||||
auto TrackPanel::FindCell(int mouseX, int mouseY) -> FoundCell
|
||||
{
|
||||
auto range = Cells();
|
||||
auto &iter = range.first, &end = range.second;
|
||||
|
@ -2861,36 +2891,41 @@ void TrackPanel::DisplaySelection()
|
|||
mListener->TP_DisplaySelection();
|
||||
}
|
||||
|
||||
Track *TrackPanel::GetFocusedTrack()
|
||||
TrackPanelCell *TrackPanel::GetFocusedCell()
|
||||
{
|
||||
return mAx->GetFocus().get();
|
||||
}
|
||||
|
||||
Track *TrackPanel::GetFocusedTrack()
|
||||
{
|
||||
return static_cast<Track*>( GetFocusedCell() );
|
||||
}
|
||||
|
||||
void TrackPanel::SetFocusedCell()
|
||||
{
|
||||
SetFocusedTrack( GetFocusedTrack() );
|
||||
}
|
||||
|
||||
void TrackPanel::SetFocusedTrack( Track *t )
|
||||
{
|
||||
// Make sure we always have the first linked track of a stereo track
|
||||
if (t && !t->GetLinked() && t->GetLink())
|
||||
t = (WaveTrack*)t->GetLink();
|
||||
|
||||
if ( !mAx->SetFocus( Track::Pointer( t ) ) )
|
||||
return;
|
||||
auto cell = mAx->SetFocus( Track::Pointer( t ) ).get();
|
||||
|
||||
if (t && AudacityProject::GetKeyboardCaptureHandler())
|
||||
AudacityProject::ReleaseKeyboard(this);
|
||||
|
||||
if (t)
|
||||
if (cell) {
|
||||
AudacityProject::CaptureKeyboard(this);
|
||||
|
||||
Refresh( false );
|
||||
Refresh( false );
|
||||
}
|
||||
}
|
||||
|
||||
void TrackPanel::OnSetFocus(wxFocusEvent & WXUNUSED(event))
|
||||
void CellularPanel::OnSetFocus(wxFocusEvent & WXUNUSED(event))
|
||||
{
|
||||
SetFocusedTrack( GetFocusedTrack() );
|
||||
Refresh( false );
|
||||
SetFocusedCell();
|
||||
}
|
||||
|
||||
void TrackPanel::OnKillFocus(wxFocusEvent & WXUNUSED(event))
|
||||
void CellularPanel::OnKillFocus(wxFocusEvent & WXUNUSED(event))
|
||||
{
|
||||
if (AudacityProject::HasKeyboardCapture(this))
|
||||
{
|
||||
|
|
199
src/TrackPanel.h
199
src/TrackPanel.h
|
@ -242,9 +242,126 @@ private:
|
|||
const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
|
||||
|
||||
|
||||
class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
||||
public:
|
||||
// This class manages a panel divided into a number of sub-rectangles called
|
||||
// cells, that each implement hit tests returning click-drag-release handler
|
||||
// objects, and other services.
|
||||
// It has no dependency on the Track class.
|
||||
class AUDACITY_DLL_API CellularPanel : public OverlayPanel {
|
||||
public:
|
||||
CellularPanel(wxWindow * parent, wxWindowID id,
|
||||
const wxPoint & pos,
|
||||
const wxSize & size,
|
||||
ViewInfo *viewInfo,
|
||||
// default as for wxPanel:
|
||||
long style = wxTAB_TRAVERSAL | wxNO_BORDER)
|
||||
: OverlayPanel(parent, id, pos, size, style)
|
||||
, mViewInfo( viewInfo )
|
||||
{}
|
||||
|
||||
// Overridables:
|
||||
|
||||
virtual AudacityProject *GetProject() const = 0;
|
||||
|
||||
// Find track info by coordinate
|
||||
struct FoundCell {
|
||||
std::shared_ptr<TrackPanelCell> pCell;
|
||||
wxRect rect;
|
||||
};
|
||||
virtual FoundCell FindCell(int mouseX, int mouseY) = 0;
|
||||
virtual TrackPanelCell *GetFocusedCell() = 0;
|
||||
virtual void SetFocusedCell() = 0;
|
||||
|
||||
virtual void ProcessUIHandleResult
|
||||
(TrackPanelCell *pClickedCell, TrackPanelCell *pLatestCell,
|
||||
unsigned refreshResult) = 0;
|
||||
|
||||
virtual void UpdateStatusMessage( const wxString & ) = 0;
|
||||
|
||||
public:
|
||||
UIHandlePtr Target()
|
||||
{
|
||||
if (mTargets.size())
|
||||
return mTargets[mTarget];
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
bool IsMouseCaptured();
|
||||
|
||||
wxCoord MostRecentXCoord() const { return mMouseMostRecentX; }
|
||||
|
||||
void HandleCursorForPresentMouseState(bool doHit = true);
|
||||
|
||||
protected:
|
||||
bool HasEscape();
|
||||
bool CancelDragging();
|
||||
void ClearTargets()
|
||||
{
|
||||
// Forget the rotation of hit test candidates when the mouse moves from
|
||||
// cell to cell or outside of the panel entirely.
|
||||
mLastCell.reset();
|
||||
mTargets.clear();
|
||||
mTarget = 0;
|
||||
mMouseOverUpdateFlags = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
bool HasRotation();
|
||||
bool ChangeTarget(bool forward, bool cycle);
|
||||
|
||||
void OnMouseEvent(wxMouseEvent & event);
|
||||
void OnCaptureLost(wxMouseCaptureLostEvent & event);
|
||||
void OnCaptureKey(wxCommandEvent & event);
|
||||
void OnKeyDown(wxKeyEvent & event);
|
||||
void OnChar(wxKeyEvent & event);
|
||||
void OnKeyUp(wxKeyEvent & event);
|
||||
|
||||
void OnSetFocus(wxFocusEvent & event);
|
||||
void OnKillFocus(wxFocusEvent & event);
|
||||
|
||||
void HandleInterruptedDrag();
|
||||
void Uncapture( wxMouseState *pState = nullptr );
|
||||
bool HandleEscapeKey(bool down);
|
||||
void UpdateMouseState(const wxMouseState &state);
|
||||
void HandleModifierKey();
|
||||
|
||||
void HandleClick( const TrackPanelMouseEvent &tpmEvent );
|
||||
void HandleWheelRotation( TrackPanelMouseEvent &tpmEvent );
|
||||
|
||||
void HandleMotion( wxMouseState &state, bool doHit = true );
|
||||
void HandleMotion
|
||||
( const TrackPanelMouseState &tpmState, bool doHit = true );
|
||||
|
||||
|
||||
protected:
|
||||
ViewInfo *mViewInfo;
|
||||
|
||||
private:
|
||||
UIHandlePtr mUIHandle;
|
||||
|
||||
std::weak_ptr<TrackPanelCell> mLastCell;
|
||||
std::vector<UIHandlePtr> mTargets;
|
||||
size_t mTarget {};
|
||||
unsigned mMouseOverUpdateFlags{};
|
||||
|
||||
protected:
|
||||
// To do: make a drawing method and make this private
|
||||
wxMouseState mLastMouseState;
|
||||
|
||||
private:
|
||||
int mMouseMostRecentX;
|
||||
int mMouseMostRecentY;
|
||||
|
||||
std::weak_ptr<TrackPanelCell> mpClickedCell;
|
||||
|
||||
bool mEnableTab{};
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class AUDACITY_DLL_API TrackPanel final : public CellularPanel {
|
||||
|
||||
public:
|
||||
TrackPanel(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos,
|
||||
|
@ -263,14 +380,7 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
|||
|
||||
void OnPaint(wxPaintEvent & event);
|
||||
void OnMouseEvent(wxMouseEvent & event);
|
||||
void OnCaptureLost(wxMouseCaptureLostEvent & event);
|
||||
void OnCaptureKey(wxCommandEvent & event);
|
||||
void OnKeyDown(wxKeyEvent & event);
|
||||
void OnChar(wxKeyEvent & event);
|
||||
void OnKeyUp(wxKeyEvent & event);
|
||||
|
||||
void OnSetFocus(wxFocusEvent & event);
|
||||
void OnKillFocus(wxFocusEvent & event);
|
||||
|
||||
void OnContextMenu(wxContextMenuEvent & event);
|
||||
|
||||
|
@ -302,31 +412,24 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
|||
// void SetSelectionFormat(int iformat)
|
||||
// void SetSnapTo(int snapto)
|
||||
|
||||
void HandleInterruptedDrag();
|
||||
void Uncapture( wxMouseState *pState = nullptr );
|
||||
bool CancelDragging();
|
||||
bool HandleEscapeKey(bool down);
|
||||
void UpdateMouseState(const wxMouseState &state);
|
||||
void HandleModifierKey();
|
||||
void HandlePageUpKey();
|
||||
void HandlePageDownKey();
|
||||
AudacityProject * GetProject() const;
|
||||
AudacityProject * GetProject() const override;
|
||||
|
||||
void ScrollIntoView(double pos);
|
||||
void ScrollIntoView(int x);
|
||||
|
||||
void OnTrackMenu(Track *t = NULL);
|
||||
Track * GetFirstSelectedTrack();
|
||||
bool IsMouseCaptured();
|
||||
|
||||
void EnsureVisible(Track * t);
|
||||
void VerticalScroll( float fracPosition);
|
||||
|
||||
TrackPanelCell *GetFocusedCell() override;
|
||||
void SetFocusedCell() override;
|
||||
Track *GetFocusedTrack();
|
||||
void SetFocusedTrack(Track *t);
|
||||
|
||||
void HandleCursorForPresentMouseState(bool doHit = true);
|
||||
|
||||
void UpdateVRulers();
|
||||
void UpdateVRuler(Track *t);
|
||||
void UpdateTrackVRuler(const Track *t);
|
||||
|
@ -338,7 +441,6 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
|||
|
||||
protected:
|
||||
bool IsAudioActive();
|
||||
void HandleClick( const TrackPanelMouseEvent &tpmEvent );
|
||||
|
||||
public:
|
||||
size_t GetTrackCount() const;
|
||||
|
@ -351,9 +453,6 @@ public:
|
|||
void UpdateAccessibility();
|
||||
void MessageForScreenReader(const wxString& message);
|
||||
|
||||
// MM: Handle mouse wheel rotation
|
||||
void HandleWheelRotation( TrackPanelMouseEvent &tpmEvent );
|
||||
|
||||
void MakeParentRedrawScrollbars();
|
||||
|
||||
// If label, rectangle includes track control panel only.
|
||||
|
@ -366,15 +465,7 @@ protected:
|
|||
// a crash, as it can take many seconds for large (eg. 10 track-hours) projects
|
||||
|
||||
// Find track info by coordinate
|
||||
struct FoundCell {
|
||||
std::shared_ptr<TrackPanelCell> pCell;
|
||||
wxRect rect;
|
||||
};
|
||||
FoundCell FindCell(int mouseX, int mouseY);
|
||||
|
||||
void HandleMotion( wxMouseState &state, bool doHit = true );
|
||||
void HandleMotion
|
||||
( const TrackPanelMouseState &tpmState, bool doHit = true );
|
||||
FoundCell FindCell(int mouseX, int mouseY) override;
|
||||
|
||||
int GetVRulerWidth() const;
|
||||
int GetVRulerOffset() const { return mTrackInfo.GetTrackInfoWidth(); }
|
||||
|
@ -447,7 +538,6 @@ protected:
|
|||
TrackPanelListener *mListener;
|
||||
|
||||
std::shared_ptr<TrackList> mTracks;
|
||||
ViewInfo *mViewInfo;
|
||||
|
||||
AdornedRulerPanel *mRuler;
|
||||
|
||||
|
@ -481,11 +571,6 @@ protected:
|
|||
|
||||
bool mRedrawAfterStop;
|
||||
|
||||
wxMouseState mLastMouseState;
|
||||
|
||||
int mMouseMostRecentX;
|
||||
int mMouseMostRecentY;
|
||||
|
||||
friend class TrackPanelAx;
|
||||
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
|
@ -510,48 +595,16 @@ protected:
|
|||
wxSize vrulerSize;
|
||||
|
||||
protected:
|
||||
std::weak_ptr<TrackPanelCell> mLastCell;
|
||||
std::vector<UIHandlePtr> mTargets;
|
||||
size_t mTarget {};
|
||||
unsigned mMouseOverUpdateFlags{};
|
||||
|
||||
public:
|
||||
UIHandlePtr Target()
|
||||
{
|
||||
if (mTargets.size())
|
||||
return mTargets[mTarget];
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
protected:
|
||||
void ClearTargets()
|
||||
{
|
||||
// Forget the rotation of hit test candidates when the mouse moves from
|
||||
// cell to cell or outside of the TrackPanel entirely.
|
||||
mLastCell.reset();
|
||||
mTargets.clear();
|
||||
mTarget = 0;
|
||||
mMouseOverUpdateFlags = 0;
|
||||
}
|
||||
|
||||
bool HasRotation();
|
||||
bool HasEscape();
|
||||
|
||||
bool ChangeTarget(bool forward, bool cycle);
|
||||
|
||||
std::weak_ptr<TrackPanelCell> mpClickedCell;
|
||||
UIHandlePtr mUIHandle;
|
||||
|
||||
std::shared_ptr<TrackPanelCell> mpBackground;
|
||||
|
||||
bool mEnableTab{};
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
void ProcessUIHandleResult
|
||||
(TrackPanelCell *pClickedCell, TrackPanelCell *pLatestCell,
|
||||
unsigned refreshResult);
|
||||
unsigned refreshResult) override;
|
||||
|
||||
void UpdateStatusMessage( const wxString &status ) override;
|
||||
|
||||
// friending GetInfoCommand allow automation to get sizes of the
|
||||
// tracks, track control panel and such.
|
||||
|
|
Loading…
Reference in New Issue
Block a user