1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-23 15:50:05 +02:00

Bug1443: Various odd behavior of label text editor, fixed...

... And label track selection code is simpler to understand, without delayed
side effects happening during drawing.

Left and right arrow keys collapse text range selection correctly
Shift-click adjusts the end of selection nearest the pick
Right (and middle) click and drag do not affect the selection
Copying empty selection has no effect on the clipboard
Left-drag behaves independently of previous selection state
This commit is contained in:
Paul Licameli 2016-07-11 13:59:29 -04:00
parent 5648023cf3
commit cb3e5e6d4f
2 changed files with 60 additions and 114 deletions

View File

@ -269,7 +269,6 @@ void LabelTrack::WarpLabels(const TimeWarper &warper) {
void LabelTrack::ResetFlags() void LabelTrack::ResetFlags()
{ {
mDragXPos = -1;
mInitialCursorPos = 1; mInitialCursorPos = 1;
mCurrentCursorPos = 1; mCurrentCursorPos = 1;
mRightDragging = false; mRightDragging = false;
@ -522,8 +521,6 @@ LabelStruct::LabelStruct(const SelectedRegion &region,
: selectedRegion(region) : selectedRegion(region)
, title(aTitle) , title(aTitle)
{ {
changeInitialMouseXPos = true;
highlighted = false;
updated = false; updated = false;
width = 0; width = 0;
x = 0; x = 0;
@ -541,8 +538,6 @@ LabelStruct::LabelStruct(const SelectedRegion &region,
// Overwrite the times // Overwrite the times
selectedRegion.setTimes(t0, t1); selectedRegion.setTimes(t0, t1);
changeInitialMouseXPos = true;
highlighted = false;
updated = false; updated = false;
width = 0; width = 0;
x = 0; x = 0;
@ -694,9 +689,6 @@ void LabelStruct::DrawTextBox(wxDC & dc, const wxRect & r) const
void LabelStruct::DrawHighlight void LabelStruct::DrawHighlight
( wxDC & dc, int xPos1, int xPos2, int charHeight) const ( wxDC & dc, int xPos1, int xPos2, int charHeight) const
{ {
highlighted = true;
changeInitialMouseXPos = false;
wxPen curPen = dc.GetPen(); wxPen curPen = dc.GetPen();
curPen.SetColour(wxString(wxT("BLUE"))); curPen.SetColour(wxString(wxT("BLUE")));
wxBrush curBrush = dc.GetBrush(); wxBrush curBrush = dc.GetBrush();
@ -826,7 +818,7 @@ void LabelTrack::Draw(wxDC & dc, const wxRect & r,
}} }}
// Draw highlights // Draw highlights
if ((mDragXPos != -1) && (mSelIndex >= 0 )) if ((mInitialCursorPos != mCurrentCursorPos) && (mSelIndex >= 0 ))
{ {
int xpos1, xpos2; int xpos1, xpos2;
CalcHighlightXs(&xpos1, &xpos2); CalcHighlightXs(&xpos1, &xpos2);
@ -866,11 +858,11 @@ void LabelTrack::Draw(wxDC & dc, const wxRect & r,
} }
} }
/// Set the cursor position according to x position of mouse
/// uses GetTextExtent to find the character position /// uses GetTextExtent to find the character position
/// corresponding to the x pixel position. /// corresponding to the x pixel position.
void LabelTrack::SetCurrentCursorPosition(int xPos) int LabelTrack::FindCurrentCursorPosition(int xPos)
{ {
int result = -1;
wxMemoryDC dc; wxMemoryDC dc;
if(msFont.Ok()) if(msFont.Ok())
dc.SetFont(msFont); dc.SetFont(msFont);
@ -898,7 +890,7 @@ void LabelTrack::SetCurrentCursorPosition(int xPos)
if (xPos <= bound) if (xPos <= bound)
{ {
// Found // Found
mCurrentCursorPos = charIndex - 1; result = charIndex - 1;
finished = true; finished = true;
} }
else else
@ -908,10 +900,16 @@ void LabelTrack::SetCurrentCursorPosition(int xPos)
} }
} }
if (!finished) if (!finished)
{
// Cursor should be in the last position // Cursor should be in the last position
mCurrentCursorPos = length; result = length;
}
return result;
}
/// Set the cursor position according to x position of mouse
void LabelTrack::SetCurrentCursorPosition(int xPos)
{
mCurrentCursorPos = FindCurrentCursorPosition(xPos);
} }
void LabelTrack::calculateFontHeight(wxDC & dc) const void LabelTrack::calculateFontHeight(wxDC & dc) const
@ -936,8 +934,6 @@ bool LabelTrack::IsTextSelected()
{ {
if (mSelIndex == -1) if (mSelIndex == -1)
return false; return false;
if (!mLabels[mSelIndex].highlighted)
return false;
if (mCurrentCursorPos == mInitialCursorPos) if (mCurrentCursorPos == mInitialCursorPos)
return false; return false;
return true; return true;
@ -993,14 +989,15 @@ bool LabelTrack::CopySelectedText()
return false; return false;
const auto &labelStruct = mLabels[mSelIndex]; const auto &labelStruct = mLabels[mSelIndex];
if (!labelStruct.highlighted)
return false;
int init = mInitialCursorPos; int init = mInitialCursorPos;
int cur = mCurrentCursorPos; int cur = mCurrentCursorPos;
if (init > cur) if (init > cur)
std::swap(init, cur); std::swap(init, cur);
if (init == cur)
return false;
// data for copying // data for copying
wxString data = labelStruct.title.Mid(init, cur-init); wxString data = labelStruct.title.Mid(init, cur-init);
@ -1043,12 +1040,9 @@ bool LabelTrack::PasteSelectedText(double sel0, double sel1)
auto &labelStruct = mLabels[mSelIndex]; auto &labelStruct = mLabels[mSelIndex];
auto &title = labelStruct.title; auto &title = labelStruct.title;
int cur = mCurrentCursorPos, init = cur; int cur = mCurrentCursorPos, init = mInitialCursorPos;
if (labelStruct.highlighted) { if (init > cur)
init = mInitialCursorPos; std::swap(init, cur);
if (init > cur)
std::swap(init, cur);
}
left = title.Left(init); left = title.Left(init);
if (cur < (int)title.Length()) if (cur < (int)title.Length())
right = title.Mid(cur); right = title.Mid(cur);
@ -1493,20 +1487,9 @@ void LabelTrack::HandleTextDragRelease(const wxMouseEvent & evt)
if(evt.Dragging()) if(evt.Dragging())
{ {
// if dragging happens in text box if (!mRightDragging)
// end dragging x position in pixels // Update drag end
// set flag to update current cursor position SetCurrentCursorPosition(evt.m_x);
mDragXPos = evt.m_x;
// for preventing dragging glygh from changing current cursor position
// set end dragging position to current cursor position
SetCurrentCursorPosition(mDragXPos);
// if it's an invalid dragging, disable displaying
if (mRightDragging) {
mDragXPos = -1;
mRightDragging = false;
}
return; return;
} }
@ -1573,20 +1556,33 @@ void LabelTrack::HandleClick(const wxMouseEvent & evt,
return; return;
} }
// disable displaying if left button is down
if (evt.LeftDown())
mDragXPos = -1;
mSelIndex = OverATextBox(evt.m_x, evt.m_y); mSelIndex = OverATextBox(evt.m_x, evt.m_y);
if (mSelIndex != -1) { if (mSelIndex != -1) {
auto &labelStruct = mLabels[mSelIndex]; auto &labelStruct = mLabels[mSelIndex];
*newSel = labelStruct.selectedRegion; *newSel = labelStruct.selectedRegion;
SetCurrentCursorPosition(evt.m_x);
// for preventing from resetting by shift+mouse left button if (evt.LeftDown()) {
if (labelStruct.changeInitialMouseXPos) // Find the NEW drag end
mInitialCursorPos = mCurrentCursorPos; auto position = FindCurrentCursorPosition(evt.m_x);
mDrawCursor = true;
if (evt.ShiftDown()) {
// Set the drag anchor at the end of the previous selection
// that is farther from the NEW drag end
if (abs(position - mCurrentCursorPos) >
abs(position - mInitialCursorPos))
mInitialCursorPos = mCurrentCursorPos;
}
else
mInitialCursorPos = position;
mCurrentCursorPos = position;
mDrawCursor = true;
mRightDragging = false;
}
else
// Actually this might be right or middle down
mRightDragging = true;
// reset the highlight indicator // reset the highlight indicator
wxRect highlightedRect; wxRect highlightedRect;
@ -1600,28 +1596,8 @@ void LabelTrack::HandleClick(const wxMouseEvent & evt,
xpos1, labelStruct.y - mFontHeight / 2, xpos1, labelStruct.y - mFontHeight / 2,
(int)(xpos2 - xpos1 + 0.5), mFontHeight (int)(xpos2 - xpos1 + 0.5), mFontHeight
}; };
// reset when left button is down
if (evt.LeftDown())
labelStruct.highlighted = false;
// reset when right button is down outside text box
if (evt.RightDown())
{
if (!highlightedRect.Contains(evt.m_x, evt.m_y))
{
mCurrentCursorPos = mInitialCursorPos = 0;
labelStruct.highlighted = false;
}
}
// set changeInitialMouseXPos flag
labelStruct.changeInitialMouseXPos = true;
} }
// disable displaying if right button is down outside text box
if (evt.RightDown()
&& !highlightedRect.Contains(evt.m_x, evt.m_y))
mDragXPos = -1;
// Middle click on GTK: paste from primary selection // Middle click on GTK: paste from primary selection
#if defined(__WXGTK__) && (HAVE_GTK) #if defined(__WXGTK__) && (HAVE_GTK)
if (evt.MiddleDown()) { if (evt.MiddleDown()) {
@ -1634,16 +1610,6 @@ void LabelTrack::HandleClick(const wxMouseEvent & evt,
*newSel = SelectedRegion(t, t); *newSel = SelectedRegion(t, t);
} }
#endif #endif
// handle shift+mouse left button
if (evt.ShiftDown()) {
// if the mouse is clicked in text box, set flags
mDragXPos = evt.m_x;
// for preventing dragging glygh from changing current cursor position
// set end dragging position to current cursor position
SetCurrentCursorPosition(evt.m_x);
}
} }
#if defined(__WXGTK__) && (HAVE_GTK) #if defined(__WXGTK__) && (HAVE_GTK)
@ -1732,9 +1698,8 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
if (len > 0) if (len > 0)
{ {
// IF there are some highlighted letters, THEN DELETE them // IF there are some highlighted letters, THEN DELETE them
if (labelStruct.highlighted) { if (mInitialCursorPos != mCurrentCursorPos)
RemoveSelectedText(); RemoveSelectedText();
}
else else
{ {
// DELETE one letter // DELETE one letter
@ -1763,9 +1728,8 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
if (len > 0) if (len > 0)
{ {
// if there are some highlighted letters, DELETE them // if there are some highlighted letters, DELETE them
if (labelStruct.highlighted) { if (mInitialCursorPos != mCurrentCursorPos)
RemoveSelectedText(); RemoveSelectedText();
}
else else
{ {
// DELETE one letter // DELETE one letter
@ -1789,11 +1753,9 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
// Move cursor to beginning of label // Move cursor to beginning of label
mCurrentCursorPos = 0; mCurrentCursorPos = 0;
if (mods == wxMOD_SHIFT) if (mods == wxMOD_SHIFT)
mDragXPos = 0; ;
else { else
mDragXPos = -1;
mInitialCursorPos = mCurrentCursorPos; mInitialCursorPos = mCurrentCursorPos;
}
break; break;
case WXK_END: case WXK_END:
@ -1801,11 +1763,9 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
// Move cursor to end of label // Move cursor to end of label
mCurrentCursorPos = (int)title.length(); mCurrentCursorPos = (int)title.length();
if (mods == wxMOD_SHIFT) if (mods == wxMOD_SHIFT)
mDragXPos = 0; ;
else { else
mDragXPos = -1;
mInitialCursorPos = mCurrentCursorPos; mInitialCursorPos = mCurrentCursorPos;
}
break; break;
case WXK_LEFT: case WXK_LEFT:
@ -1814,11 +1774,10 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
if (mCurrentCursorPos > 0) { if (mCurrentCursorPos > 0) {
mCurrentCursorPos--; mCurrentCursorPos--;
if (mods == wxMOD_SHIFT) if (mods == wxMOD_SHIFT)
mDragXPos = 0; ;
else { else
mDragXPos = -1; mInitialCursorPos = mCurrentCursorPos =
mInitialCursorPos = mCurrentCursorPos; std::min(mInitialCursorPos, mCurrentCursorPos);
}
} }
break; break;
@ -1828,11 +1787,10 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
if (mCurrentCursorPos < (int)title.length()) { if (mCurrentCursorPos < (int)title.length()) {
mCurrentCursorPos++; mCurrentCursorPos++;
if (mods == wxMOD_SHIFT) if (mods == wxMOD_SHIFT)
mDragXPos = 0; ;
else { else
mDragXPos = -1; mInitialCursorPos = mCurrentCursorPos =
mInitialCursorPos = mCurrentCursorPos; std::max(mInitialCursorPos, mCurrentCursorPos);
}
} }
break; break;
@ -1984,9 +1942,8 @@ bool LabelTrack::OnChar(SelectedRegion &WXUNUSED(newSel), wxKeyEvent & event)
auto &title = labelStruct.title; auto &title = labelStruct.title;
// Test if cursor is in the end of string or not // Test if cursor is in the end of string or not
if (labelStruct.highlighted) { if (mInitialCursorPos != mCurrentCursorPos)
RemoveSelectedText(); RemoveSelectedText();
}
if (mCurrentCursorPos < (int)title.length()) { if (mCurrentCursorPos < (int)title.length()) {
// Get substring on the righthand side of cursor // Get substring on the righthand side of cursor
@ -2048,9 +2005,6 @@ void LabelTrack::ShowContextMenu()
parent->PopupMenu(&menu, x, ls->y + (mIconHeight / 2) - 1); parent->PopupMenu(&menu, x, ls->y + (mIconHeight / 2) - 1);
} }
// it's an invalid dragging event
SetWrongDragging(true);
} }
void LabelTrack::OnContextMenu(wxCommandEvent & evt) void LabelTrack::OnContextMenu(wxCommandEvent & evt)
@ -2126,8 +2080,6 @@ void LabelTrack::RemoveSelectedText()
title = left + right; title = left + right;
mInitialCursorPos = mCurrentCursorPos = left.Length(); mInitialCursorPos = mCurrentCursorPos = left.Length();
labelStruct.highlighted = false;
mDragXPos = -1;
} }
void LabelTrack::Unselect() void LabelTrack::Unselect()

View File

@ -96,8 +96,6 @@ public:
mutable int xText; /// Pixel position of left hand side of text box mutable int xText; /// Pixel position of left hand side of text box
mutable int y; /// Pixel position of label. mutable int y; /// Pixel position of label.
mutable bool highlighted; /// if the text is highlighted
mutable bool changeInitialMouseXPos; /// flag to change initial mouse X pos
bool updated; /// flag to tell if the label times were updated bool updated; /// flag to tell if the label times were updated
}; };
@ -180,9 +178,6 @@ class AUDACITY_DLL_API LabelTrack final : public Track
bool PasteSelectedText(double sel0, double sel1); bool PasteSelectedText(double sel0, double sel1);
static bool IsTextClipSupported(); static bool IsTextClipSupported();
// methods to set flags
void SetWrongDragging(bool rightFlag) { mRightDragging = rightFlag; }
void HandleClick(const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo, void HandleClick(const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo,
SelectedRegion *newSel); SelectedRegion *newSel);
bool HandleGlyphDragRelease(const wxMouseEvent & evt, wxRect & r, const ZoomInfo &zoomInfo, bool HandleGlyphDragRelease(const wxMouseEvent & evt, wxRect & r, const ZoomInfo &zoomInfo,
@ -263,8 +258,6 @@ class AUDACITY_DLL_API LabelTrack final : public Track
static int mFontHeight; static int mFontHeight;
int mCurrentCursorPos; /// current cursor position int mCurrentCursorPos; /// current cursor position
int mInitialCursorPos; /// initial cursor position int mInitialCursorPos; /// initial cursor position
int mDragXPos; /// end X pos of dragging
/// in text box
bool mRightDragging; /// flag to tell if it's a valid dragging bool mRightDragging; /// flag to tell if it's a valid dragging
bool mDrawCursor; /// flag to tell if drawing the bool mDrawCursor; /// flag to tell if drawing the
@ -279,6 +272,7 @@ class AUDACITY_DLL_API LabelTrack final : public Track
void ComputeTextPosition(const wxRect & r, int index) const; void ComputeTextPosition(const wxRect & r, int index) const;
public: public:
int FindCurrentCursorPosition(int xPos);
void SetCurrentCursorPosition(int xPos); void SetCurrentCursorPosition(int xPos);
private: private: