finalcut/src/fscrollbar.cpp

827 lines
20 KiB
C++
Raw Normal View History

2017-11-04 07:03:53 +01:00
/***********************************************************************
* fscrollbar.cpp - Widget FScrollbar *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2012-2019 Markus Gans *
2017-11-04 07:03:53 +01:00
* *
* The Final Cut is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public License *
* as published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* The Final Cut is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/
2015-05-23 13:35:12 +02:00
2017-09-11 03:06:02 +02:00
#include <algorithm>
#include "final/fevent.h"
#include "final/fscrollbar.h"
#include "final/fsize.h"
#include "final/fwidgetcolors.h"
2015-05-23 13:35:12 +02:00
namespace finalcut
{
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
// class FScrollbar
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
2015-09-22 04:18:20 +02:00
FScrollbar::FScrollbar(FWidget* parent)
: FWidget(parent)
2015-05-23 13:35:12 +02:00
{
2015-09-22 04:18:20 +02:00
// The default scrollbar orientation is vertical
setGeometry(FPoint(1, 1), FSize(1, length), false);
2015-09-22 04:18:20 +02:00
init();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
2019-01-12 09:11:22 +01:00
FScrollbar::FScrollbar(fc::orientation o, FWidget* parent)
2015-09-22 04:18:20 +02:00
: FWidget(parent)
2015-05-23 13:35:12 +02:00
{
setOrientation (o);
2015-09-22 04:18:20 +02:00
init();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
2017-09-11 03:06:02 +02:00
FScrollbar::~FScrollbar() // destructor
2015-05-23 13:35:12 +02:00
{
2015-12-19 20:51:04 +01:00
delOwnTimer();
2015-05-23 13:35:12 +02:00
}
// public methods of FScrollbar
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FScrollbar::setMinimum (int minimum)
2015-05-23 13:35:12 +02:00
{
min = minimum;
calculateSliderValues();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::setMaximum (int maximum)
2015-05-23 13:35:12 +02:00
{
max = maximum;
calculateSliderValues();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::setRange (int minimum, int maximum)
2015-05-23 13:35:12 +02:00
{
min = minimum;
max = maximum;
calculateSliderValues();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::setValue (int value)
2015-05-23 13:35:12 +02:00
{
if ( value < min )
val = min;
else if ( value > max )
val = max;
else
val = value;
calculateSliderValues();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::setSteps (double st)
2015-05-23 13:35:12 +02:00
{
if ( st <= 0.0 )
steps = 1.0;
else
steps = st;
2015-05-23 13:35:12 +02:00
if ( pagesize == 0 )
pagesize = int(double(max)/steps);
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FScrollbar::setPageSize (int document_size, int page_size)
2015-05-23 13:35:12 +02:00
{
if ( page_size == 0 )
2015-05-23 13:35:12 +02:00
{
pagesize = document_size;
steps = 1.0;
2015-05-23 13:35:12 +02:00
}
else
2015-05-23 13:35:12 +02:00
{
pagesize = page_size;
if ( document_size <= 0 || page_size <= 0 )
steps = 1.0;
else
steps = double(double(document_size) / double(page_size));
2015-05-23 13:35:12 +02:00
}
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
2019-01-12 09:11:22 +01:00
void FScrollbar::setOrientation (fc::orientation o)
{
std::size_t nf = 0;
length = ( getHeight() > getWidth() ) ? getHeight() : getWidth();
2015-05-23 13:35:12 +02:00
if ( o == fc::vertical && bar_orientation == fc::horizontal )
2015-05-23 13:35:12 +02:00
{
setWidth(1);
setHeight(length);
2015-05-23 13:35:12 +02:00
}
else if ( o == fc::horizontal && bar_orientation == fc::vertical )
2015-05-23 13:35:12 +02:00
{
setWidth(length);
setHeight(1);
if ( isNewFont() )
nf = 2;
2015-05-23 13:35:12 +02:00
}
slider_length = bar_length = length - nf - 2;
bar_orientation = o;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::setGeometry ( const FPoint& pos, const FSize& size
2018-11-20 21:11:04 +01:00
, bool adjust )
2015-05-23 13:35:12 +02:00
{
// Set the scrollbar geometry
FWidget::setGeometry (pos, size, adjust);
2015-05-23 13:35:12 +02:00
std::size_t nf = 0;
std::size_t w = size.getWidth();
std::size_t h = size.getHeight();
length = ( h > w ) ? h : w;
2015-05-23 13:35:12 +02:00
if ( bar_orientation == fc::vertical )
2015-05-23 13:35:12 +02:00
{
setWidth(isNewFont() ? 2 : 1);
setHeight(length);
}
2017-09-11 03:06:02 +02:00
else // horizontal
{
setWidth(length);
setHeight(1);
if ( isNewFont() )
nf = 2;
2015-05-23 13:35:12 +02:00
}
slider_length = bar_length = length - nf - 2;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::resize()
2015-05-23 13:35:12 +02:00
{
FWidget::resize();
setOrientation (bar_orientation);
setValue (val);
calculateSliderValues();
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FScrollbar::redraw()
{
if ( isShown() )
draw();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::calculateSliderValues()
{
if ( isNewFont() && bar_orientation == fc::horizontal )
bar_length = ( length > 2 ) ? length - 4 : 1;
2015-05-23 13:35:12 +02:00
else
bar_length = ( length > 2 ) ? length - 2 : 1;
slider_length = std::size_t(double(bar_length) / steps);
2015-05-23 13:35:12 +02:00
if ( slider_length < 1 )
slider_length = 1;
else if ( slider_length > bar_length )
slider_length = bar_length;
2015-05-23 13:35:12 +02:00
if ( val == min )
{
slider_pos = 0;
2015-05-23 13:35:12 +02:00
return;
}
2015-05-23 13:35:12 +02:00
if ( val == max )
{
slider_pos = int(bar_length - slider_length);
2015-05-23 13:35:12 +02:00
return;
}
std::size_t v = ( min < 0 ) ? std::size_t(val - min) : std::size_t(val);
2015-05-23 13:35:12 +02:00
if ( slider_length >= bar_length )
slider_pos = 0;
else
slider_pos = int( round ( double((bar_length - slider_length) * v)
/ double(max - min) ) );
if ( slider_pos > int(bar_length - slider_length) )
slider_pos = int(bar_length - slider_length);
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::drawVerticalBar()
2015-05-23 13:35:12 +02:00
{
int z;
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
2015-05-23 13:35:12 +02:00
for (z = 1; z <= slider_pos; z++)
2015-05-23 13:35:12 +02:00
{
print() << FPoint(1, 1 + z);
if ( isNewFont() )
{
if ( isMonochron() || max_color < 16 )
print (fc::MediumShade); // ▒
else
print (fc::NF_border_line_left); // ⎸
}
if ( isMonochron() || max_color < 16 )
print (fc::MediumShade); // ▒
else
print (' ');
2015-05-23 13:35:12 +02:00
}
setColor (wc.scrollbar_bg, wc.scrollbar_fg);
2015-10-11 21:56:16 +02:00
if ( isMonochron() )
setReverse(false);
for (z = 1; z <= int(slider_length); z++)
{
print() << FPoint(1, 1 + slider_pos + z);
if ( isNewFont() )
print (' ');
print (' ');
}
if ( isMonochron() )
setReverse(true);
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
for (z = slider_pos + int(slider_length) + 1; z <= int(bar_length); z++)
{
print() << FPoint(1, 1 + z);
if ( isNewFont() )
{
if ( isMonochron() || max_color < 16 )
print (fc::MediumShade); // ▒
else
print (fc::NF_border_line_left); // ⎸
}
if ( isMonochron() || max_color < 16 )
print (fc::MediumShade);
else
print (' ');
}
if ( isMonochron() )
setReverse(false);
}
//----------------------------------------------------------------------
void FScrollbar::drawHorizontalBar()
{
int z;
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
if ( isNewFont() )
print() << FPoint(3, 1);
else
print() << FPoint(2, 1);
for (z = 0; z < slider_pos; z++)
{
if ( isNewFont() && max_color > 8 )
print (fc::NF_border_line_upper); // ¯
else if ( isMonochron() || max_color < 16 )
print (fc::MediumShade); // ▒
else
print (' ');
}
setColor (wc.scrollbar_bg, wc.scrollbar_fg);
if ( isMonochron() )
setReverse(false);
2015-05-23 13:35:12 +02:00
for (z = 0; z < int(slider_length); z++)
print (' ');
if ( isMonochron() )
setReverse(true);
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
z = slider_pos + int(slider_length) + 1;
for (; z <= int(bar_length); z++)
{
if ( isNewFont() && max_color > 8 )
print (fc::NF_border_line_upper); // ¯
else if ( isMonochron() || max_color < 16 )
print (fc::MediumShade); // ▒
else
print (' ');
}
if ( isMonochron() )
setReverse(false);
}
//----------------------------------------------------------------------
void FScrollbar::drawBar()
{
if ( ! isShown() )
return;
if ( slider_pos == current_slider_pos || length < 3 )
return;
if ( bar_orientation == fc::vertical )
drawVerticalBar();
else // horizontal
drawHorizontalBar();
current_slider_pos = slider_pos;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FScrollbar::onMouseDown (FMouseEvent* ev)
2015-05-23 13:35:12 +02:00
{
int mouse_x, mouse_y;
2015-10-11 21:56:16 +02:00
if ( ev->getButton() != fc::LeftButton
2017-11-26 22:37:18 +01:00
&& ev->getButton() != fc::MiddleButton )
return;
if ( min == max )
return;
mouse_x = ev->getX();
mouse_y = ev->getY();
if ( ev->getButton() == fc::MiddleButton )
{
2018-02-18 21:50:24 +01:00
jumpToClickPos (mouse_x, mouse_y);
return;
}
// Process left button
scroll_type = getClickedScrollType(mouse_x, mouse_y);
if ( scroll_type == FScrollbar::noScroll )
{
2018-02-18 21:50:24 +01:00
slider_click_pos = getSliderClickPos (mouse_x, mouse_y);
if ( slider_click_pos > 0 )
scroll_type = FScrollbar::scrollJump;
}
if ( scroll_type == FScrollbar::scrollPageBackward
2017-11-26 22:37:18 +01:00
|| scroll_type == FScrollbar::scrollPageForward )
{
if ( bar_orientation == fc::vertical )
slider_click_stop_pos = mouse_y - 2;
else
2018-11-20 21:11:04 +01:00
{
if ( isNewFont() )
slider_click_stop_pos = mouse_x - 3;
else
slider_click_stop_pos = mouse_x - 2;
2018-11-20 21:11:04 +01:00
}
}
2015-05-23 13:35:12 +02:00
else
slider_click_stop_pos = -1;
if ( scroll_type >= FScrollbar::scrollStepBackward
2017-11-26 22:37:18 +01:00
&& scroll_type <= FScrollbar::scrollPageForward )
2015-05-23 13:35:12 +02:00
{
processScroll();
threshold_reached = false;
addTimer(threshold_time);
}
}
2015-10-11 21:56:16 +02:00
//----------------------------------------------------------------------
void FScrollbar::onMouseUp (FMouseEvent* ev)
{
if ( ev->getButton() != fc::LeftButton
2017-11-26 22:37:18 +01:00
&& ev->getButton() != fc::MiddleButton )
return;
slider_click_pos = -1;
if ( scroll_type != FScrollbar::noScroll )
{
delOwnTimer();
scroll_type = FScrollbar::noScroll;
}
}
//----------------------------------------------------------------------
void FScrollbar::onMouseMove (FMouseEvent* ev)
{
int mouse_x, mouse_y, new_scroll_type;
if ( ev->getButton() != fc::LeftButton
2017-11-26 22:37:18 +01:00
&& ev->getButton() != fc::MiddleButton )
return;
mouse_x = ev->getX();
mouse_y = ev->getY();
if ( ev->getButton() == fc::MiddleButton )
{
2018-02-18 21:50:24 +01:00
jumpToClickPos (mouse_x, mouse_y);
return;
}
// Process left button
new_scroll_type = getClickedScrollType(mouse_x, mouse_y);
if ( scroll_type == FScrollbar::scrollJump )
{
int new_val;
2015-10-11 21:56:16 +02:00
2015-05-23 13:35:12 +02:00
if ( bar_orientation == fc::vertical )
{
int dy = mouse_y - slider_click_pos;
slider_click_pos = mouse_y;
new_val = int( round ( double((max - min) * (slider_pos + dy))
/ double(bar_length - slider_length) ) );
}
else // horizontal
{
int dx = mouse_x - slider_click_pos;
slider_click_pos = mouse_x;
new_val = int( round ( double((max - min) * (slider_pos + dx))
/ double(bar_length - slider_length) ) );
}
if ( new_val != val )
{
setValue(new_val);
drawBar();
updateTerminal();
processScroll();
}
}
if ( mouse_x < 1 || mouse_x > int(getWidth())
|| mouse_y < 1 || mouse_y > int(getHeight()) )
{
delOwnTimer();
}
else if ( scroll_type != FScrollbar::scrollJump )
{
addTimer(repeat_time);
}
if ( scroll_type != new_scroll_type )
{
delOwnTimer();
}
}
//----------------------------------------------------------------------
void FScrollbar::onWheel (FWheelEvent* ev)
{
int wheel = ev->getWheel();
if ( scroll_type != FScrollbar::noScroll )
{
delOwnTimer();
scroll_type = FScrollbar::noScroll;
}
if ( wheel == fc::WheelUp )
scroll_type = FScrollbar::scrollWheelUp;
else if ( wheel == fc::WheelDown )
scroll_type = FScrollbar::scrollWheelDown;
processScroll();
}
//----------------------------------------------------------------------
void FScrollbar::onTimer (FTimerEvent*)
{
if ( scroll_type == FScrollbar::noScroll )
return;
if ( ! threshold_reached )
{
threshold_reached = true;
delOwnTimer();
addTimer(repeat_time);
}
2018-02-18 21:50:24 +01:00
// Timer stop condition
if ( ( scroll_type == FScrollbar::scrollPageBackward
2018-02-18 21:50:24 +01:00
&& slider_pos == slider_click_stop_pos )
2017-11-26 22:37:18 +01:00
|| ( scroll_type == FScrollbar::scrollPageForward
2018-02-18 21:50:24 +01:00
&& slider_pos == slider_click_stop_pos ) )
{
int max_slider_pos = int(bar_length - slider_length);
2018-02-18 21:50:24 +01:00
if ( scroll_type == FScrollbar::scrollPageBackward
&& slider_pos == 0 )
{
2018-02-18 21:50:24 +01:00
jumpToClickPos(0); // Scroll to the start
processScroll();
}
else if ( scroll_type == FScrollbar::scrollPageForward
&& slider_pos == max_slider_pos )
{
jumpToClickPos (max_slider_pos); // Scroll to the end
processScroll();
}
delOwnTimer();
return;
}
processScroll();
}
// private methods of FScrollbar
//----------------------------------------------------------------------
void FScrollbar::init()
{
unsetFocusable();
ignorePadding();
setGeometry(FPoint(1, 1), FSize(getWidth(), getHeight()));
}
//----------------------------------------------------------------------
void FScrollbar::draw()
{
if ( length < 2 )
return;
drawButtons();
current_slider_pos = -1;
drawBar();
}
//----------------------------------------------------------------------
void FScrollbar::drawButtons()
{
setColor (wc.scrollbar_button_fg, wc.scrollbar_button_bg);
if ( isNewFont() )
{
print() << FPoint(1, 1);
if ( bar_orientation == fc::vertical )
{
print() << fc::NF_rev_up_arrow1
<< fc::NF_rev_up_arrow2
<< FPoint(1, int(length))
<< fc::NF_rev_down_arrow1
<< fc::NF_rev_down_arrow2;
}
else // horizontal
{
print() << fc::NF_rev_left_arrow1
<< fc::NF_rev_left_arrow2
<< FPoint(int(length) - 1, 1)
<< fc::NF_rev_right_arrow1
<< fc::NF_rev_right_arrow2;
}
}
else
{
print() << FPoint(1, 1);
if ( isMonochron() )
setReverse(true);
if ( bar_orientation == fc::vertical )
{
print() << fc::BlackUpPointingTriangle // ▲
<< FPoint(1, int(length))
<< fc::BlackDownPointingTriangle; // ▼
}
else // horizontal
{
print() << fc::BlackLeftPointingPointer // ◄
<< FPoint(int(length), 1)
<< fc::BlackRightPointingPointer; // ►
}
if ( isMonochron() )
setReverse(false);
}
}
//----------------------------------------------------------------------
FScrollbar::sType FScrollbar::getClickedScrollType (int x, int y)
{
if ( bar_orientation == fc::vertical )
{
2018-02-08 00:25:51 +01:00
return getVerticalClickedScrollType(y);
}
else // horizontal
{
return getHorizontalClickedScrollType(x);
}
}
//----------------------------------------------------------------------
FScrollbar::sType FScrollbar::getVerticalClickedScrollType (int y)
{
if ( y == 1 )
{
return FScrollbar::scrollStepBackward; // decrement button
}
else if ( y > 1 && y <= slider_pos + 1 )
{
return FScrollbar::scrollPageBackward; // before slider
}
else if ( y > slider_pos + int(slider_length) + 1 && y < int(getHeight()) )
2018-02-08 00:25:51 +01:00
{
return FScrollbar::scrollPageForward; // after slider
}
else if ( y == int(getHeight()) )
2018-02-08 00:25:51 +01:00
{
return FScrollbar::scrollStepForward; // increment button
}
return FScrollbar::noScroll;
}
//----------------------------------------------------------------------
FScrollbar::sType FScrollbar::getHorizontalClickedScrollType (int x)
{
if ( isNewFont() )
{
if ( x == 1 || x == 2 )
{
2018-02-08 00:25:51 +01:00
return FScrollbar::scrollStepBackward; // decrement button
}
2018-02-08 00:25:51 +01:00
else if ( x > 2 && x <= slider_pos + 2 )
{
2018-02-08 00:25:51 +01:00
return FScrollbar::scrollPageBackward; // before slider
}
else if ( x > slider_pos + int(slider_length) + 2 && x < int(getWidth()) - 1 )
{
2018-02-08 00:25:51 +01:00
return FScrollbar::scrollPageForward; // after slider
}
else if ( x == int(getWidth()) - 1 || x == int(getWidth()) )
{
2018-02-08 00:25:51 +01:00
return FScrollbar::scrollStepForward; // increment button
}
2018-02-08 00:25:51 +01:00
return FScrollbar::noScroll;
}
2018-02-08 00:25:51 +01:00
else
{
2018-02-08 00:25:51 +01:00
if ( x == 1 )
{
2018-02-08 00:25:51 +01:00
return FScrollbar::scrollStepBackward; // decrement button
}
2018-02-08 00:25:51 +01:00
else if ( x > 1 && x <= slider_pos + 1 )
{
2018-02-08 00:25:51 +01:00
return FScrollbar::scrollPageBackward; // before slider
}
else if ( x > slider_pos + int(slider_length) + 1 && x < int(getWidth()) )
2018-02-08 00:25:51 +01:00
{
return FScrollbar::scrollPageForward; // after slider
}
else if ( x == int(getWidth()) )
2018-02-08 00:25:51 +01:00
{
return FScrollbar::scrollStepForward; // increment button
}
2018-02-08 00:25:51 +01:00
return FScrollbar::noScroll;
}
}
//----------------------------------------------------------------------
2018-02-18 21:50:24 +01:00
int FScrollbar::getSliderClickPos (int mouse_x, int mouse_y)
{
2018-02-18 21:50:24 +01:00
// Get the clicked position on the slider
2018-02-18 21:50:24 +01:00
if ( bar_orientation == fc::vertical )
{
if ( mouse_y > slider_pos + 1
&& mouse_y <= slider_pos + int(slider_length) + 1 )
2018-02-18 21:50:24 +01:00
return mouse_y; // on slider
}
else // horizontal bar orientation
{
if ( isNewFont() )
{
2018-02-18 21:50:24 +01:00
if ( mouse_x > slider_pos + 2
&& mouse_x <= slider_pos + int(slider_length) + 2 )
2018-02-18 21:50:24 +01:00
return mouse_x; // on slider
2015-05-23 13:35:12 +02:00
}
2018-02-18 21:50:24 +01:00
else
2015-05-23 13:35:12 +02:00
{
2018-02-18 21:50:24 +01:00
if ( mouse_x > slider_pos + 1
&& mouse_x <= slider_pos + int(slider_length) + 1 )
2018-02-18 21:50:24 +01:00
return mouse_x; // on slider
}
}
2018-02-18 21:50:24 +01:00
return -1;
}
//----------------------------------------------------------------------
void FScrollbar::jumpToClickPos (int x, int y)
{
int new_val;
if ( bar_orientation == fc::vertical )
{
if ( y >1 && y < int(getHeight()) )
2018-02-18 21:50:24 +01:00
{
new_val = int( round ( double(max - min) * (y - 2.0 - (slider_length/2))
/ double(bar_length - slider_length) ) );
2015-05-23 13:35:12 +02:00
}
2018-02-18 21:50:24 +01:00
else
return;
}
else // horizontal
{
int nf = isNewFont() ? 1 : 0;
if ( x > 1 + nf && x < int(getWidth()) - nf )
{
2018-02-18 21:50:24 +01:00
new_val = int( round ( double(max - min) * (x - 2.0 - nf - (slider_length/2))
/ double(bar_length - slider_length) ) );
}
2018-02-18 21:50:24 +01:00
else
return;
}
if ( new_val != val )
{
setValue(new_val);
drawBar();
updateTerminal();
scroll_type = FScrollbar::scrollJump;
processScroll();
}
}
2018-02-18 21:50:24 +01:00
//----------------------------------------------------------------------
void FScrollbar::jumpToClickPos (int pos)
{
if ( bar_orientation == fc::vertical )
jumpToClickPos (0, pos + 2);
else
{
if ( isNewFont() )
jumpToClickPos (pos + 3, 0);
else
jumpToClickPos (pos + 2, 0);
}
}
//----------------------------------------------------------------------
void FScrollbar::avoidScrollOvershoot()
{
// Avoid overshoot
if ( ( scroll_type == FScrollbar::scrollPageBackward
&& slider_pos < slider_click_stop_pos )
|| ( scroll_type == FScrollbar::scrollPageForward
&& slider_pos > slider_click_stop_pos ) )
{
jumpToClickPos (slider_click_stop_pos);
delOwnTimer();
}
}
//----------------------------------------------------------------------
void FScrollbar::processScroll()
{
emitCallback("change-value");
2018-02-18 21:50:24 +01:00
avoidScrollOvershoot();
2015-05-23 13:35:12 +02:00
}
} // namespace finalcut