mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-22 23:30:07 +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:
parent
5648023cf3
commit
cb3e5e6d4f
@ -269,7 +269,6 @@ void LabelTrack::WarpLabels(const TimeWarper &warper) {
|
||||
|
||||
void LabelTrack::ResetFlags()
|
||||
{
|
||||
mDragXPos = -1;
|
||||
mInitialCursorPos = 1;
|
||||
mCurrentCursorPos = 1;
|
||||
mRightDragging = false;
|
||||
@ -522,8 +521,6 @@ LabelStruct::LabelStruct(const SelectedRegion ®ion,
|
||||
: selectedRegion(region)
|
||||
, title(aTitle)
|
||||
{
|
||||
changeInitialMouseXPos = true;
|
||||
highlighted = false;
|
||||
updated = false;
|
||||
width = 0;
|
||||
x = 0;
|
||||
@ -541,8 +538,6 @@ LabelStruct::LabelStruct(const SelectedRegion ®ion,
|
||||
// Overwrite the times
|
||||
selectedRegion.setTimes(t0, t1);
|
||||
|
||||
changeInitialMouseXPos = true;
|
||||
highlighted = false;
|
||||
updated = false;
|
||||
width = 0;
|
||||
x = 0;
|
||||
@ -694,9 +689,6 @@ void LabelStruct::DrawTextBox(wxDC & dc, const wxRect & r) const
|
||||
void LabelStruct::DrawHighlight
|
||||
( wxDC & dc, int xPos1, int xPos2, int charHeight) const
|
||||
{
|
||||
highlighted = true;
|
||||
changeInitialMouseXPos = false;
|
||||
|
||||
wxPen curPen = dc.GetPen();
|
||||
curPen.SetColour(wxString(wxT("BLUE")));
|
||||
wxBrush curBrush = dc.GetBrush();
|
||||
@ -826,7 +818,7 @@ void LabelTrack::Draw(wxDC & dc, const wxRect & r,
|
||||
}}
|
||||
|
||||
// Draw highlights
|
||||
if ((mDragXPos != -1) && (mSelIndex >= 0 ))
|
||||
if ((mInitialCursorPos != mCurrentCursorPos) && (mSelIndex >= 0 ))
|
||||
{
|
||||
int 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
|
||||
/// corresponding to the x pixel position.
|
||||
void LabelTrack::SetCurrentCursorPosition(int xPos)
|
||||
int LabelTrack::FindCurrentCursorPosition(int xPos)
|
||||
{
|
||||
int result = -1;
|
||||
wxMemoryDC dc;
|
||||
if(msFont.Ok())
|
||||
dc.SetFont(msFont);
|
||||
@ -898,7 +890,7 @@ void LabelTrack::SetCurrentCursorPosition(int xPos)
|
||||
if (xPos <= bound)
|
||||
{
|
||||
// Found
|
||||
mCurrentCursorPos = charIndex - 1;
|
||||
result = charIndex - 1;
|
||||
finished = true;
|
||||
}
|
||||
else
|
||||
@ -908,10 +900,16 @@ void LabelTrack::SetCurrentCursorPosition(int xPos)
|
||||
}
|
||||
}
|
||||
if (!finished)
|
||||
{
|
||||
// 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
|
||||
@ -936,8 +934,6 @@ bool LabelTrack::IsTextSelected()
|
||||
{
|
||||
if (mSelIndex == -1)
|
||||
return false;
|
||||
if (!mLabels[mSelIndex].highlighted)
|
||||
return false;
|
||||
if (mCurrentCursorPos == mInitialCursorPos)
|
||||
return false;
|
||||
return true;
|
||||
@ -993,14 +989,15 @@ bool LabelTrack::CopySelectedText()
|
||||
return false;
|
||||
|
||||
const auto &labelStruct = mLabels[mSelIndex];
|
||||
if (!labelStruct.highlighted)
|
||||
return false;
|
||||
|
||||
int init = mInitialCursorPos;
|
||||
int cur = mCurrentCursorPos;
|
||||
if (init > cur)
|
||||
std::swap(init, cur);
|
||||
|
||||
if (init == cur)
|
||||
return false;
|
||||
|
||||
// data for copying
|
||||
wxString data = labelStruct.title.Mid(init, cur-init);
|
||||
|
||||
@ -1043,12 +1040,9 @@ bool LabelTrack::PasteSelectedText(double sel0, double sel1)
|
||||
|
||||
auto &labelStruct = mLabels[mSelIndex];
|
||||
auto &title = labelStruct.title;
|
||||
int cur = mCurrentCursorPos, init = cur;
|
||||
if (labelStruct.highlighted) {
|
||||
init = mInitialCursorPos;
|
||||
if (init > cur)
|
||||
std::swap(init, cur);
|
||||
}
|
||||
int cur = mCurrentCursorPos, init = mInitialCursorPos;
|
||||
if (init > cur)
|
||||
std::swap(init, cur);
|
||||
left = title.Left(init);
|
||||
if (cur < (int)title.Length())
|
||||
right = title.Mid(cur);
|
||||
@ -1493,20 +1487,9 @@ void LabelTrack::HandleTextDragRelease(const wxMouseEvent & evt)
|
||||
|
||||
if(evt.Dragging())
|
||||
{
|
||||
// if dragging happens in text box
|
||||
// end dragging x position in pixels
|
||||
// set flag to update current cursor position
|
||||
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;
|
||||
}
|
||||
if (!mRightDragging)
|
||||
// Update drag end
|
||||
SetCurrentCursorPosition(evt.m_x);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1573,20 +1556,33 @@ void LabelTrack::HandleClick(const wxMouseEvent & evt,
|
||||
return;
|
||||
}
|
||||
|
||||
// disable displaying if left button is down
|
||||
if (evt.LeftDown())
|
||||
mDragXPos = -1;
|
||||
|
||||
mSelIndex = OverATextBox(evt.m_x, evt.m_y);
|
||||
if (mSelIndex != -1) {
|
||||
auto &labelStruct = mLabels[mSelIndex];
|
||||
*newSel = labelStruct.selectedRegion;
|
||||
SetCurrentCursorPosition(evt.m_x);
|
||||
|
||||
// for preventing from resetting by shift+mouse left button
|
||||
if (labelStruct.changeInitialMouseXPos)
|
||||
mInitialCursorPos = mCurrentCursorPos;
|
||||
mDrawCursor = true;
|
||||
if (evt.LeftDown()) {
|
||||
// Find the NEW drag end
|
||||
auto position = FindCurrentCursorPosition(evt.m_x);
|
||||
|
||||
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
|
||||
wxRect highlightedRect;
|
||||
@ -1600,28 +1596,8 @@ void LabelTrack::HandleClick(const wxMouseEvent & evt,
|
||||
xpos1, labelStruct.y - mFontHeight / 2,
|
||||
(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
|
||||
#if defined(__WXGTK__) && (HAVE_GTK)
|
||||
if (evt.MiddleDown()) {
|
||||
@ -1634,16 +1610,6 @@ void LabelTrack::HandleClick(const wxMouseEvent & evt,
|
||||
*newSel = SelectedRegion(t, t);
|
||||
}
|
||||
#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)
|
||||
@ -1732,9 +1698,8 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
|
||||
if (len > 0)
|
||||
{
|
||||
// IF there are some highlighted letters, THEN DELETE them
|
||||
if (labelStruct.highlighted) {
|
||||
if (mInitialCursorPos != mCurrentCursorPos)
|
||||
RemoveSelectedText();
|
||||
}
|
||||
else
|
||||
{
|
||||
// DELETE one letter
|
||||
@ -1763,9 +1728,8 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
|
||||
if (len > 0)
|
||||
{
|
||||
// if there are some highlighted letters, DELETE them
|
||||
if (labelStruct.highlighted) {
|
||||
if (mInitialCursorPos != mCurrentCursorPos)
|
||||
RemoveSelectedText();
|
||||
}
|
||||
else
|
||||
{
|
||||
// DELETE one letter
|
||||
@ -1789,11 +1753,9 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
|
||||
// Move cursor to beginning of label
|
||||
mCurrentCursorPos = 0;
|
||||
if (mods == wxMOD_SHIFT)
|
||||
mDragXPos = 0;
|
||||
else {
|
||||
mDragXPos = -1;
|
||||
;
|
||||
else
|
||||
mInitialCursorPos = mCurrentCursorPos;
|
||||
}
|
||||
break;
|
||||
|
||||
case WXK_END:
|
||||
@ -1801,11 +1763,9 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
|
||||
// Move cursor to end of label
|
||||
mCurrentCursorPos = (int)title.length();
|
||||
if (mods == wxMOD_SHIFT)
|
||||
mDragXPos = 0;
|
||||
else {
|
||||
mDragXPos = -1;
|
||||
;
|
||||
else
|
||||
mInitialCursorPos = mCurrentCursorPos;
|
||||
}
|
||||
break;
|
||||
|
||||
case WXK_LEFT:
|
||||
@ -1814,11 +1774,10 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
|
||||
if (mCurrentCursorPos > 0) {
|
||||
mCurrentCursorPos--;
|
||||
if (mods == wxMOD_SHIFT)
|
||||
mDragXPos = 0;
|
||||
else {
|
||||
mDragXPos = -1;
|
||||
mInitialCursorPos = mCurrentCursorPos;
|
||||
}
|
||||
;
|
||||
else
|
||||
mInitialCursorPos = mCurrentCursorPos =
|
||||
std::min(mInitialCursorPos, mCurrentCursorPos);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1828,11 +1787,10 @@ bool LabelTrack::OnKeyDown(SelectedRegion &newSel, wxKeyEvent & event)
|
||||
if (mCurrentCursorPos < (int)title.length()) {
|
||||
mCurrentCursorPos++;
|
||||
if (mods == wxMOD_SHIFT)
|
||||
mDragXPos = 0;
|
||||
else {
|
||||
mDragXPos = -1;
|
||||
mInitialCursorPos = mCurrentCursorPos;
|
||||
}
|
||||
;
|
||||
else
|
||||
mInitialCursorPos = mCurrentCursorPos =
|
||||
std::max(mInitialCursorPos, mCurrentCursorPos);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1984,9 +1942,8 @@ bool LabelTrack::OnChar(SelectedRegion &WXUNUSED(newSel), wxKeyEvent & event)
|
||||
auto &title = labelStruct.title;
|
||||
|
||||
// Test if cursor is in the end of string or not
|
||||
if (labelStruct.highlighted) {
|
||||
if (mInitialCursorPos != mCurrentCursorPos)
|
||||
RemoveSelectedText();
|
||||
}
|
||||
|
||||
if (mCurrentCursorPos < (int)title.length()) {
|
||||
// Get substring on the righthand side of cursor
|
||||
@ -2048,9 +2005,6 @@ void LabelTrack::ShowContextMenu()
|
||||
|
||||
parent->PopupMenu(&menu, x, ls->y + (mIconHeight / 2) - 1);
|
||||
}
|
||||
|
||||
// it's an invalid dragging event
|
||||
SetWrongDragging(true);
|
||||
}
|
||||
|
||||
void LabelTrack::OnContextMenu(wxCommandEvent & evt)
|
||||
@ -2126,8 +2080,6 @@ void LabelTrack::RemoveSelectedText()
|
||||
|
||||
title = left + right;
|
||||
mInitialCursorPos = mCurrentCursorPos = left.Length();
|
||||
labelStruct.highlighted = false;
|
||||
mDragXPos = -1;
|
||||
}
|
||||
|
||||
void LabelTrack::Unselect()
|
||||
|
@ -96,8 +96,6 @@ public:
|
||||
mutable int xText; /// Pixel position of left hand side of text box
|
||||
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
|
||||
};
|
||||
|
||||
@ -180,9 +178,6 @@ class AUDACITY_DLL_API LabelTrack final : public Track
|
||||
bool PasteSelectedText(double sel0, double sel1);
|
||||
static bool IsTextClipSupported();
|
||||
|
||||
// methods to set flags
|
||||
void SetWrongDragging(bool rightFlag) { mRightDragging = rightFlag; }
|
||||
|
||||
void HandleClick(const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo,
|
||||
SelectedRegion *newSel);
|
||||
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;
|
||||
int mCurrentCursorPos; /// current 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 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;
|
||||
|
||||
public:
|
||||
int FindCurrentCursorPosition(int xPos);
|
||||
void SetCurrentCursorPosition(int xPos);
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user