finalcut/src/fscrollbar.cpp

741 lines
17 KiB
C++
Raw Normal View History

// File: fscrollbar.cpp
// Provides: class FScrollbar
2015-05-23 13:35:12 +02:00
2017-09-11 03:06:02 +02:00
#include <algorithm>
2015-05-23 13:35:12 +02:00
#include "fscrollbar.h"
//----------------------------------------------------------------------
// class FScrollbar
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
2015-09-22 04:18:20 +02:00
FScrollbar::FScrollbar(FWidget* parent)
: FWidget(parent)
, 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)
, pageSize(0)
, 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
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)
, 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)
, pageSize(0)
, 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
}
// 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
{
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 )
steps = 1;
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;
steps = double(double(document_size) / double(page_size));
2015-05-23 13:35:12 +02:00
}
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FScrollbar::setOrientation (int o)
{
int 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 (int x, int y, int w, int h, bool adjust)
2015-05-23 13:35:12 +02:00
{
// Set the scrollbar geometry
FWidget::setGeometry (x, y, w, h, adjust);
2015-05-23 13:35:12 +02:00
int nf = 0;
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()
{
draw();
}
//----------------------------------------------------------------------
void FScrollbar::calculateSliderValues()
{
if ( isNewFont() && bar_orientation == fc::horizontal )
bar_length = length - 4;
2015-05-23 13:35:12 +02:00
else
bar_length = length - 2;
slider_length = int(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 = bar_length - slider_length;
2015-05-23 13:35:12 +02:00
return;
}
slider_pos = int( round ( double((bar_length - slider_length) * val)
/ double(max - min) ) );
2015-05-23 13:35:12 +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
}
//----------------------------------------------------------------------
void FScrollbar::drawButtons()
2015-05-23 13:35:12 +02:00
{
setColor (wc.scrollbar_button_fg, wc.scrollbar_button_bg);
2015-05-23 13:35:12 +02:00
if ( isNewFont() )
2015-05-23 13:35:12 +02:00
{
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);
}
2017-09-11 03:06:02 +02:00
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);
}
2015-05-23 13:35:12 +02:00
}
else
2015-05-23 13:35:12 +02:00
{
setPrintPos (1,1);
if ( isMonochron() )
setReverse(true);
2015-05-23 13:35:12 +02:00
if ( bar_orientation == fc::vertical )
{
2017-09-11 03:06:02 +02:00
print (fc::BlackUpPointingTriangle); // ▲
setPrintPos (1, length);
2017-09-11 03:06:02 +02:00
print (fc::BlackDownPointingTriangle); // ▼
}
2017-09-11 03:06:02 +02:00
else // horizontal
{
2017-09-11 03:06:02 +02:00
print (fc::BlackLeftPointingPointer); // ◄
setPrintPos (length, 1);
2017-09-11 03:06:02 +02:00
print (fc::BlackRightPointingPointer); // ►
}
if ( isMonochron() )
setReverse(false);
2015-05-23 13:35:12 +02:00
}
}
//----------------------------------------------------------------------
void FScrollbar::drawBar()
{
int z;
2015-10-11 21:56:16 +02:00
if ( slider_pos == current_slider_pos || length < 3 )
return;
if ( bar_orientation == fc::vertical )
{
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
for (z = 1; z <= slider_pos; z++)
{
setPrintPos (1, 1 + z);
if ( isNewFont() )
2017-09-11 03:06:02 +02:00
print (fc::NF_border_line_left); // ⎸
if ( isMonochron() || max_color < 16 )
2017-09-11 03:06:02 +02:00
print (fc::MediumShade); // ▒
else
print (' ');
}
setColor (wc.scrollbar_bg, wc.scrollbar_fg);
if ( isMonochron() )
setReverse(false);
for (z = 1; z <= slider_length; z++)
{
setPrintPos (1, 1 + slider_pos + z);
if ( isNewFont() )
2015-05-23 13:35:12 +02:00
print (' ');
print (' ');
}
if ( isMonochron() )
setReverse(true);
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
for (z = slider_pos + slider_length + 1; z <= bar_length; z++)
2015-05-23 13:35:12 +02:00
{
setPrintPos (1, 1 + z);
2015-05-23 13:35:12 +02:00
if ( isNewFont() )
2017-09-11 03:06:02 +02:00
print (fc::NF_border_line_left); // ⎸
if ( isMonochron() || max_color < 16 )
print (fc::MediumShade);
2015-05-23 13:35:12 +02:00
else
print (' ');
}
}
else // horizontal
{
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
z = 0;
2015-05-23 13:35:12 +02:00
if ( isNewFont() )
setPrintPos (3 + z, 1);
else
setPrintPos (2 + z, 1);
for (; z < slider_pos; z++)
{
if ( isNewFont() )
2017-09-11 03:06:02 +02:00
print (fc::NF_border_line_upper); // ¯
else if ( isMonochron() || max_color < 16 )
2017-09-11 03:06:02 +02:00
print (fc::MediumShade); // ▒
else
print (' ');
}
setColor (wc.scrollbar_bg, wc.scrollbar_fg);
2015-05-23 13:35:12 +02:00
if ( isMonochron() )
setReverse(false);
z = 0;
for (; z < slider_length; z++)
print (' ');
if ( isMonochron() )
setReverse(true);
setColor (wc.scrollbar_fg, wc.scrollbar_bg);
z = slider_pos + slider_length + 1;
for (; z <= bar_length; z++)
{
if ( isNewFont() )
2017-09-11 03:06:02 +02:00
print (fc::NF_border_line_upper); // ¯
else if ( isMonochron() || max_color < 16 )
2017-09-11 03:06:02 +02:00
print (fc::MediumShade); // ▒
else
print (' ');
2015-05-23 13:35:12 +02:00
}
}
current_slider_pos = slider_pos;
2015-10-11 21:56:16 +02:00
if ( isMonochron() )
setReverse(false);
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
&& ev->getButton() != fc::MiddleButton )
return;
if ( min == max )
return;
mouse_x = ev->getX();
mouse_y = ev->getY();
if ( ev->getButton() == fc::MiddleButton )
{
processMiddleButton (mouse_x, mouse_y);
return;
}
// process LeftButton
scroll_type = getClickedScrollType(mouse_x, mouse_y);
if ( scroll_type == FScrollbar::noScroll )
{
if ( bar_orientation == fc::vertical )
2015-05-23 13:35:12 +02:00
{
if ( mouse_y > slider_pos + 1
&& mouse_y <= slider_pos + slider_length + 1 )
slider_click_pos = mouse_y; // on slider
2015-05-23 13:35:12 +02:00
}
else // horizontal
2015-05-23 13:35:12 +02:00
{
if ( isNewFont() )
{
if ( mouse_x > slider_pos + 2
&& mouse_x <= slider_pos + slider_length + 2 )
slider_click_pos = mouse_x; // on slider
}
else
{
if ( mouse_x > slider_pos + 1
&& mouse_x <= slider_pos + slider_length + 1 )
slider_click_pos = mouse_x; // on slider
}
2015-05-23 13:35:12 +02:00
}
if ( slider_click_pos > 0 )
scroll_type = FScrollbar::scrollJump;
}
if ( scroll_type == FScrollbar::scrollPageBackward
|| scroll_type == FScrollbar::scrollPageForward )
{
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
slider_click_stop_pos = -1;
if ( scroll_type >= FScrollbar::scrollStepBackward
&& 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
&& 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
&& ev->getButton() != fc::MiddleButton )
return;
mouse_x = ev->getX();
mouse_y = ev->getY();
if ( ev->getButton() == fc::MiddleButton )
{
processMiddleButton (mouse_x, mouse_y);
return;
}
// process LeftButton
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 > getWidth()
|| mouse_y < 1 || mouse_y > 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);
}
if ( ( scroll_type == FScrollbar::scrollPageBackward
&& slider_pos < slider_click_stop_pos )
|| ( scroll_type == FScrollbar::scrollPageForward
&& slider_pos + slider_length > slider_click_stop_pos ) )
{
// Scroll to the end
if ( scroll_type == FScrollbar::scrollPageForward
&& slider_pos + slider_length > slider_click_stop_pos )
{
setValue(max);
processScroll();
}
delOwnTimer();
return;
}
processScroll();
}
// private methods of FScrollbar
//----------------------------------------------------------------------
void FScrollbar::init()
{
unsetFocusable();
ignorePadding();
setGeometry(1, 1, getWidth(), getHeight());
}
//----------------------------------------------------------------------
void FScrollbar::draw()
{
if ( length < 2 )
return;
drawButtons();
current_slider_pos = -1;
drawBar();
}
//----------------------------------------------------------------------
FScrollbar::sType FScrollbar::getClickedScrollType (int x, int y)
{
FScrollbar::sType stype;
if ( bar_orientation == fc::vertical )
{
if ( y == 1 )
{
stype = FScrollbar::scrollStepBackward; // decrement button
}
else if ( y > 1 && y <= slider_pos + 1 )
{
stype = FScrollbar::scrollPageBackward; // before slider
}
else if ( y > slider_pos + slider_length + 1 && y < getHeight() )
{
stype = FScrollbar::scrollPageForward; // after slider
}
else if ( y == getHeight() )
{
2017-09-11 03:06:02 +02:00
stype = FScrollbar::scrollStepForward; // increment button
}
else
stype = FScrollbar::noScroll;
}
else // horizontal
{
if ( isNewFont() )
{
if ( x == 1 || x == 2 )
{
stype = FScrollbar::scrollStepBackward; // decrement button
}
else if ( x > 2 && x <= slider_pos + 2 )
{
stype = FScrollbar::scrollPageBackward; // before slider
}
else if ( x > slider_pos + slider_length + 2 && x < getWidth() - 1 )
{
stype = FScrollbar::scrollPageForward; // after slider
}
else if ( x == getWidth() - 1 || x == getWidth() )
{
stype = FScrollbar::scrollStepForward; // increment button
}
2015-05-23 13:35:12 +02:00
else
stype = FScrollbar::noScroll;
}
else
{
if ( x == 1 )
{
stype = FScrollbar::scrollStepBackward; // decrement button
}
else if ( x > 1 && x <= slider_pos + 1 )
{
stype = FScrollbar::scrollPageBackward; // before slider
}
else if ( x > slider_pos + slider_length + 1 && x < getWidth() )
{
stype = FScrollbar::scrollPageForward; // after slider
}
else if ( x == getWidth() )
{
stype = FScrollbar::scrollStepForward; // increment button
}
else
stype = FScrollbar::noScroll;
}
}
return stype;
}
//----------------------------------------------------------------------
void FScrollbar::processMiddleButton (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
else
return;
2015-05-23 13:35:12 +02:00
}
else // horizontal
2015-05-23 13:35:12 +02:00
{
int nf = isNewFont() ? 1 : 0;
if ( x > 1 + nf && x < getWidth() - nf )
{
new_val = int( round ( double(max - min) * (x - 2.0 - nf - (slider_length/2))
/ double(bar_length - slider_length) ) );
}
else
return;
2015-05-23 13:35:12 +02:00
}
if ( new_val != val )
{
setValue(new_val);
drawBar();
updateTerminal();
scroll_type = FScrollbar::scrollJump;
processScroll();
}
}
//----------------------------------------------------------------------
void FScrollbar::processScroll()
{
emitCallback("change-value");
2015-05-23 13:35:12 +02:00
}