2017-11-04 07:03:53 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* fscrollbar.cpp - Widget FScrollbar *
|
|
|
|
* *
|
|
|
|
* This file is part of the Final Cut widget toolkit *
|
|
|
|
* *
|
2018-02-08 00:25:51 +01:00
|
|
|
* Copyright 2012-2018 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>
|
|
|
|
|
2017-09-17 21:32:46 +02:00
|
|
|
#include "final/fscrollbar.h"
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-09-20 23:59:01 +02:00
|
|
|
namespace finalcut
|
|
|
|
{
|
2017-10-02 07:32:33 +02:00
|
|
|
|
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)
|
2016-09-27 00:46:05 +02:00
|
|
|
, scroll_type(FScrollbar::noScroll)
|
|
|
|
, threshold_reached(false)
|
|
|
|
, threshold_time(500)
|
|
|
|
, repeat_time(10)
|
|
|
|
, slider_click_pos(-1)
|
|
|
|
, slider_click_stop_pos(-1)
|
|
|
|
, current_slider_pos(-1)
|
|
|
|
, slider_pos(0)
|
2017-09-11 03:06:02 +02:00
|
|
|
, slider_length(18) // = bar_length
|
|
|
|
, bar_length(18) // = length - 2
|
2015-09-22 04:18:20 +02:00
|
|
|
, val(0)
|
|
|
|
, min(0)
|
|
|
|
, max(99)
|
|
|
|
, steps(1)
|
2017-10-02 07:32:33 +02:00
|
|
|
, pagesize(0)
|
2015-09-22 04:18:20 +02:00
|
|
|
, length(20)
|
|
|
|
, bar_orientation(fc::vertical)
|
|
|
|
, max_color(getMaxColor())
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2015-09-22 04:18:20 +02:00
|
|
|
// The default scrollbar orientation is vertical
|
2016-09-25 23:53:48 +02:00
|
|
|
setGeometry(1, 1, 1, length, false);
|
2015-09-22 04:18:20 +02:00
|
|
|
init();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2015-09-22 04:18:20 +02:00
|
|
|
FScrollbar::FScrollbar(int o, FWidget* parent)
|
|
|
|
: FWidget(parent)
|
2016-09-27 00:46:05 +02:00
|
|
|
, scroll_type(FScrollbar::noScroll)
|
|
|
|
, threshold_reached(false)
|
|
|
|
, threshold_time(500)
|
|
|
|
, repeat_time(10)
|
|
|
|
, slider_click_pos(-1)
|
|
|
|
, slider_click_stop_pos(-1)
|
|
|
|
, current_slider_pos(-1)
|
|
|
|
, slider_pos(0)
|
2017-09-11 03:06:02 +02:00
|
|
|
, slider_length(18) // = bar_length
|
|
|
|
, bar_length(18) // = length - 2
|
2015-09-22 04:18:20 +02:00
|
|
|
, val(0)
|
|
|
|
, min(0)
|
|
|
|
, max(99)
|
|
|
|
, steps(1)
|
2017-10-02 07:32:33 +02:00
|
|
|
, pagesize(0)
|
2015-09-22 04:18:20 +02:00
|
|
|
, length(20)
|
|
|
|
, bar_orientation(fc::vertical)
|
|
|
|
, max_color(getMaxColor())
|
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
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
// public methods of FScrollbar
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::setMinimum (int minimum)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
min = minimum;
|
|
|
|
calculateSliderValues();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::setMaximum (int maximum)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
max = maximum;
|
|
|
|
calculateSliderValues();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2017-12-27 23:51:32 +01:00
|
|
|
void FScrollbar::setRange (int minimum, int maximum)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
min = minimum;
|
|
|
|
max = maximum;
|
|
|
|
calculateSliderValues();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::setValue (int value)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
val = value;
|
|
|
|
calculateSliderValues();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2017-04-09 20:08:53 +02:00
|
|
|
void FScrollbar::setSteps (double st)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( st <= 0 )
|
|
|
|
steps = 1;
|
|
|
|
else
|
|
|
|
steps = st;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-10-02 07:32:33 +02:00
|
|
|
if ( pagesize == 0 )
|
|
|
|
pagesize = int(double(max)/steps);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::setPageSize (int document_size, int page_size)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( page_size == 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-10-02 07:32:33 +02:00
|
|
|
pagesize = document_size;
|
2016-11-02 00:37:58 +01:00
|
|
|
steps = 1.0;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-10-02 07:32:33 +02:00
|
|
|
pagesize = page_size;
|
2017-04-09 20:08:53 +02:00
|
|
|
steps = double(double(document_size) / double(page_size));
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::setOrientation (int o)
|
|
|
|
{
|
|
|
|
int nf = 0;
|
2017-09-17 21:32:46 +02:00
|
|
|
length = ( getHeight() > getWidth() ) ? getHeight() : getWidth();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( o == fc::vertical && bar_orientation == fc::horizontal )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
setWidth(1);
|
|
|
|
setHeight(length);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
else if ( o == fc::horizontal && bar_orientation == fc::vertical )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
setWidth(length);
|
|
|
|
setHeight(1);
|
|
|
|
|
|
|
|
if ( isNewFont() )
|
|
|
|
nf = 2;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2017-12-27 23:51:32 +01:00
|
|
|
|
2017-07-03 16:56:32 +02:00
|
|
|
slider_length = bar_length = length - nf - 2;
|
2016-11-02 00:37:58 +01:00
|
|
|
bar_orientation = o;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::setGeometry (int x, int y, int w, int h, bool adjust)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-08-06 17:02:19 +02:00
|
|
|
// Set the scrollbar geometry
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
FWidget::setGeometry (x, y, w, h, adjust);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
int nf = 0;
|
2017-09-17 21:32:46 +02:00
|
|
|
length = ( h > w ) ? h : w;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( bar_orientation == fc::vertical )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
setWidth(isNewFont() ? 2 : 1);
|
|
|
|
setHeight(length);
|
|
|
|
}
|
2017-09-11 03:06:02 +02:00
|
|
|
else // horizontal
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
setWidth(length);
|
|
|
|
setHeight(1);
|
|
|
|
|
|
|
|
if ( isNewFont() )
|
|
|
|
nf = 2;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-07-03 16:56:32 +02:00
|
|
|
slider_length = bar_length = length - nf - 2;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::resize()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
FWidget::resize();
|
|
|
|
setOrientation (bar_orientation);
|
|
|
|
setValue (val);
|
|
|
|
calculateSliderValues();
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::redraw()
|
|
|
|
{
|
|
|
|
draw();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::calculateSliderValues()
|
|
|
|
{
|
|
|
|
if ( isNewFont() && bar_orientation == fc::horizontal )
|
2016-09-27 00:46:05 +02:00
|
|
|
bar_length = length - 4;
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2016-09-27 00:46:05 +02:00
|
|
|
bar_length = length - 2;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
slider_length = int(double(bar_length) / steps);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-09-27 00:46:05 +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 )
|
|
|
|
{
|
2016-09-27 00:46:05 +02:00
|
|
|
slider_pos = 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
if ( val == max )
|
|
|
|
{
|
2016-09-27 00:46:05 +02:00
|
|
|
slider_pos = bar_length - slider_length;
|
2015-05-23 13:35:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-09 20:08:53 +02:00
|
|
|
slider_pos = int( round ( double((bar_length - slider_length) * val)
|
2017-12-02 18:52:51 +01:00
|
|
|
/ double(max - min) ) );
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-09-27 00:46:05 +02:00
|
|
|
if ( slider_pos < 0 )
|
|
|
|
slider_pos = 0;
|
|
|
|
else if ( slider_pos > bar_length - slider_length )
|
|
|
|
slider_pos = bar_length - slider_length;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2017-12-27 23:51:32 +01:00
|
|
|
void FScrollbar::drawVerticalBar()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-12-27 23:51:32 +01:00
|
|
|
int z;
|
|
|
|
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
for (z = 1; z <= slider_pos; z++)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2017-12-27 23:51:32 +01:00
|
|
|
setPrintPos (1, 1 + z);
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isNewFont() )
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
|
|
|
if ( isMonochron() || max_color < 16 )
|
|
|
|
print (fc::MediumShade); // ▒
|
|
|
|
else
|
|
|
|
print (fc::NF_border_line_left); // ⎸
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() || max_color < 16 )
|
|
|
|
print (fc::MediumShade); // ▒
|
|
|
|
else
|
|
|
|
print (' ');
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
setColor (wc.scrollbar_bg, wc.scrollbar_fg);
|
2015-10-11 21:56:16 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(false);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
for (z = 1; z <= slider_length; z++)
|
2017-02-20 00:00:53 +01:00
|
|
|
{
|
2017-12-27 23:51:32 +01:00
|
|
|
setPrintPos (1, 1 + slider_pos + z);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isNewFont() )
|
|
|
|
print (' ');
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
print (' ');
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(true);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
|
2016-09-25 23:53:48 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
for (z = slider_pos + slider_length + 1; z <= bar_length; z++)
|
|
|
|
{
|
|
|
|
setPrintPos (1, 1 + z);
|
2016-09-25 23:53:48 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isNewFont() )
|
2018-06-12 16:37:48 +02:00
|
|
|
{
|
|
|
|
if ( isMonochron() || max_color < 16 )
|
|
|
|
print (fc::MediumShade); // ▒
|
|
|
|
else
|
|
|
|
print (fc::NF_border_line_left); // ⎸
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() || max_color < 16 )
|
|
|
|
print (fc::MediumShade);
|
|
|
|
else
|
2017-02-20 00:00:53 +01:00
|
|
|
print (' ');
|
2017-12-27 23:51:32 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(false);
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::drawHorizontalBar()
|
|
|
|
{
|
2017-12-29 02:10:05 +01:00
|
|
|
int z;
|
2017-12-27 23:51:32 +01:00
|
|
|
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isNewFont() )
|
|
|
|
setPrintPos (3, 1);
|
|
|
|
else
|
|
|
|
setPrintPos (2, 1);
|
2017-02-20 00:00:53 +01:00
|
|
|
|
2017-12-29 02:10:05 +01:00
|
|
|
for (z = 0; z < slider_pos; z++)
|
2017-02-20 00:00:53 +01:00
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
if ( isNewFont() && max_color > 8 )
|
2017-12-27 23:51:32 +01:00
|
|
|
print (fc::NF_border_line_upper); // ¯
|
|
|
|
else if ( isMonochron() || max_color < 16 )
|
|
|
|
print (fc::MediumShade); // ▒
|
2017-02-20 00:00:53 +01:00
|
|
|
else
|
2017-12-27 23:51:32 +01:00
|
|
|
print (' ');
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
setColor (wc.scrollbar_bg, wc.scrollbar_fg);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(false);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
for (z = 0; z < slider_length; z++)
|
|
|
|
print (' ');
|
|
|
|
|
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(true);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
|
|
|
|
z = slider_pos + slider_length + 1;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
for (; z <= bar_length; z++)
|
|
|
|
{
|
2018-06-12 16:37:48 +02:00
|
|
|
if ( isNewFont() && max_color > 8 )
|
2017-12-27 23:51:32 +01:00
|
|
|
print (fc::NF_border_line_upper); // ¯
|
|
|
|
else if ( isMonochron() || max_color < 16 )
|
|
|
|
print (fc::MediumShade); // ▒
|
|
|
|
else
|
2017-02-20 00:00:53 +01:00
|
|
|
print (' ');
|
2017-12-27 23:51:32 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(false);
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::drawBar()
|
|
|
|
{
|
|
|
|
if ( slider_pos == current_slider_pos || length < 3 )
|
|
|
|
return;
|
2017-02-20 00:00:53 +01:00
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
if ( bar_orientation == fc::vertical )
|
|
|
|
drawVerticalBar();
|
|
|
|
else // horizontal
|
|
|
|
drawHorizontalBar();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-02-20 00:00:53 +01:00
|
|
|
current_slider_pos = slider_pos;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FScrollbar::onMouseDown (FMouseEvent* ev)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
int mouse_x, mouse_y;
|
2015-10-11 21:56:16 +02:00
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( ev->getButton() != fc::LeftButton
|
2017-11-26 22:37:18 +01:00
|
|
|
&& ev->getButton() != fc::MiddleButton )
|
2016-11-02 00:37:58 +01:00
|
|
|
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);
|
2016-11-02 00:37:58 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
// Process left button
|
2016-11-02 00:37:58 +01:00
|
|
|
scroll_type = getClickedScrollType(mouse_x, mouse_y);
|
|
|
|
|
2017-02-20 00:00:53 +01:00
|
|
|
if ( scroll_type == FScrollbar::noScroll )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-18 21:50:24 +01:00
|
|
|
slider_click_pos = getSliderClickPos (mouse_x, mouse_y);
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2017-02-20 00:00:53 +01:00
|
|
|
if ( slider_click_pos > 0 )
|
|
|
|
scroll_type = FScrollbar::scrollJump;
|
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( scroll_type == FScrollbar::scrollPageBackward
|
2017-11-26 22:37:18 +01:00
|
|
|
|| scroll_type == FScrollbar::scrollPageForward )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
if ( bar_orientation == fc::vertical )
|
|
|
|
slider_click_stop_pos = mouse_y - 2;
|
|
|
|
else
|
|
|
|
if ( isNewFont() )
|
|
|
|
slider_click_stop_pos = mouse_x - 3;
|
|
|
|
else
|
|
|
|
slider_click_stop_pos = mouse_x - 2;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
slider_click_stop_pos = -1;
|
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
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
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
processScroll();
|
|
|
|
threshold_reached = false;
|
|
|
|
addTimer(threshold_time);
|
|
|
|
}
|
|
|
|
}
|
2015-10-11 21:56:16 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::onMouseUp (FMouseEvent* ev)
|
|
|
|
{
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( ev->getButton() != fc::LeftButton
|
2017-11-26 22:37:18 +01:00
|
|
|
&& ev->getButton() != fc::MiddleButton )
|
2016-11-02 00:37:58 +01:00
|
|
|
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;
|
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( ev->getButton() != fc::LeftButton
|
2017-11-26 22:37:18 +01:00
|
|
|
&& ev->getButton() != fc::MiddleButton )
|
2016-11-02 00:37:58 +01:00
|
|
|
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);
|
2016-11-02 00:37:58 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
// Process left button
|
2016-11-02 00:37:58 +01:00
|
|
|
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 )
|
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
int dy = mouse_y - slider_click_pos;
|
|
|
|
slider_click_pos = mouse_y;
|
2017-04-09 20:08:53 +02:00
|
|
|
new_val = int( round ( double((max - min) * (slider_pos + dy))
|
|
|
|
/ double(bar_length - slider_length) ) );
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
else // horizontal
|
|
|
|
{
|
|
|
|
int dx = mouse_x - slider_click_pos;
|
|
|
|
slider_click_pos = mouse_x;
|
2017-04-09 20:08:53 +02:00
|
|
|
new_val = int( round ( double((max - min) * (slider_pos + dx))
|
|
|
|
/ double(bar_length - slider_length) ) );
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( new_val != val )
|
|
|
|
{
|
|
|
|
setValue(new_val);
|
|
|
|
drawBar();
|
|
|
|
updateTerminal();
|
|
|
|
processScroll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-18 23:34:11 +01:00
|
|
|
if ( mouse_x < 1 || mouse_x > getWidth()
|
2017-11-26 22:37:18 +01:00
|
|
|
|| mouse_y < 1 || mouse_y > getHeight() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
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
|
2016-12-18 23:34:11 +01:00
|
|
|
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 ) )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-18 21:50:24 +01:00
|
|
|
int max_slider_pos = bar_length - slider_length;
|
|
|
|
|
|
|
|
if ( scroll_type == FScrollbar::scrollPageBackward
|
|
|
|
&& slider_pos == 0 )
|
2017-01-02 08:07:46 +01:00
|
|
|
{
|
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
|
2017-01-02 08:07:46 +01:00
|
|
|
processScroll();
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
delOwnTimer();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
processScroll();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// private methods of FScrollbar
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::init()
|
|
|
|
{
|
|
|
|
unsetFocusable();
|
|
|
|
ignorePadding();
|
|
|
|
setGeometry(1, 1, getWidth(), getHeight());
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::draw()
|
|
|
|
{
|
2017-02-20 00:00:53 +01:00
|
|
|
if ( length < 2 )
|
|
|
|
return;
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
drawButtons();
|
|
|
|
current_slider_pos = -1;
|
|
|
|
drawBar();
|
|
|
|
}
|
|
|
|
|
2017-12-27 23:51:32 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::drawButtons()
|
|
|
|
{
|
|
|
|
setColor (wc.scrollbar_button_fg, wc.scrollbar_button_bg);
|
|
|
|
|
|
|
|
if ( isNewFont() )
|
|
|
|
{
|
|
|
|
setPrintPos (1,1);
|
|
|
|
|
|
|
|
if ( bar_orientation == fc::vertical )
|
|
|
|
{
|
|
|
|
print (fc::NF_rev_up_arrow1);
|
|
|
|
print (fc::NF_rev_up_arrow2);
|
|
|
|
setPrintPos (1, length);
|
|
|
|
print (fc::NF_rev_down_arrow1);
|
|
|
|
print (fc::NF_rev_down_arrow2);
|
|
|
|
}
|
|
|
|
else // horizontal
|
|
|
|
{
|
|
|
|
print (fc::NF_rev_left_arrow1);
|
|
|
|
print (fc::NF_rev_left_arrow2);
|
|
|
|
setPrintPos (length - 1, 1);
|
|
|
|
print (fc::NF_rev_right_arrow1);
|
|
|
|
print (fc::NF_rev_right_arrow2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setPrintPos (1,1);
|
|
|
|
|
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(true);
|
|
|
|
|
|
|
|
if ( bar_orientation == fc::vertical )
|
|
|
|
{
|
|
|
|
print (fc::BlackUpPointingTriangle); // ▲
|
|
|
|
setPrintPos (1, length);
|
|
|
|
print (fc::BlackDownPointingTriangle); // ▼
|
|
|
|
}
|
|
|
|
else // horizontal
|
|
|
|
{
|
|
|
|
print (fc::BlackLeftPointingPointer); // ◄
|
|
|
|
setPrintPos (length, 1);
|
|
|
|
print (fc::BlackRightPointingPointer); // ►
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( isMonochron() )
|
|
|
|
setReverse(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
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 + slider_length + 1 && y < getHeight() )
|
|
|
|
{
|
|
|
|
return FScrollbar::scrollPageForward; // after slider
|
|
|
|
}
|
|
|
|
else if ( y == getHeight() )
|
|
|
|
{
|
|
|
|
return FScrollbar::scrollStepForward; // increment button
|
|
|
|
}
|
|
|
|
|
|
|
|
return FScrollbar::noScroll;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
FScrollbar::sType FScrollbar::getHorizontalClickedScrollType (int x)
|
|
|
|
{
|
|
|
|
if ( isNewFont() )
|
|
|
|
{
|
|
|
|
if ( x == 1 || x == 2 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::scrollStepBackward; // decrement button
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-08 00:25:51 +01:00
|
|
|
else if ( x > 2 && x <= slider_pos + 2 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::scrollPageBackward; // before slider
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-08 00:25:51 +01:00
|
|
|
else if ( x > slider_pos + slider_length + 2 && x < getWidth() - 1 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::scrollPageForward; // after slider
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-08 00:25:51 +01:00
|
|
|
else if ( x == getWidth() - 1 || x == getWidth() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::scrollStepForward; // increment button
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-08 00:25:51 +01:00
|
|
|
|
|
|
|
return FScrollbar::noScroll;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-08 00:25:51 +01:00
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
if ( x == 1 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::scrollStepBackward; // decrement button
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-08 00:25:51 +01:00
|
|
|
else if ( x > 1 && x <= slider_pos + 1 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::scrollPageBackward; // before slider
|
|
|
|
}
|
|
|
|
else if ( x > slider_pos + slider_length + 1 && x < getWidth() )
|
|
|
|
{
|
|
|
|
return FScrollbar::scrollPageForward; // after slider
|
|
|
|
}
|
|
|
|
else if ( x == getWidth() )
|
|
|
|
{
|
|
|
|
return FScrollbar::scrollStepForward; // increment button
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-02-08 00:25:51 +01:00
|
|
|
return FScrollbar::noScroll;
|
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-02-18 21:50:24 +01:00
|
|
|
int FScrollbar::getSliderClickPos (int mouse_x, int mouse_y)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-18 21:50:24 +01:00
|
|
|
// Get the clicked position on the slider
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2018-02-18 21:50:24 +01:00
|
|
|
if ( bar_orientation == fc::vertical )
|
|
|
|
{
|
|
|
|
if ( mouse_y > slider_pos + 1
|
|
|
|
&& mouse_y <= slider_pos + slider_length + 1 )
|
|
|
|
return mouse_y; // on slider
|
|
|
|
}
|
|
|
|
else // horizontal bar orientation
|
|
|
|
{
|
|
|
|
if ( isNewFont() )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-02-18 21:50:24 +01:00
|
|
|
if ( mouse_x > slider_pos + 2
|
|
|
|
&& mouse_x <= slider_pos + slider_length + 2 )
|
|
|
|
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 + slider_length + 1 )
|
|
|
|
return mouse_x; // on slider
|
|
|
|
}
|
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
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 < getHeight() )
|
|
|
|
{
|
|
|
|
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;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-02-18 21:50:24 +01:00
|
|
|
if ( x > 1 + nf && x < getWidth() - nf )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
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) ) );
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-02-18 21:50:24 +01:00
|
|
|
else
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( new_val != val )
|
|
|
|
{
|
|
|
|
setValue(new_val);
|
|
|
|
drawBar();
|
|
|
|
updateTerminal();
|
|
|
|
scroll_type = FScrollbar::scrollJump;
|
|
|
|
processScroll();
|
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FScrollbar::processScroll()
|
|
|
|
{
|
|
|
|
emitCallback("change-value");
|
2018-02-18 21:50:24 +01:00
|
|
|
avoidScrollOvershoot();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
|
|
|
|
} // namespace finalcut
|