876 lines
22 KiB
C++
876 lines
22 KiB
C++
/***********************************************************************
|
|
* ftextview.cpp - Widget FTextView (a multiline text viewer) *
|
|
* *
|
|
* This file is part of the FINAL CUT widget toolkit *
|
|
* *
|
|
* Copyright 2014-2020 Markus Gans *
|
|
* *
|
|
* 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. *
|
|
* *
|
|
* 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/>. *
|
|
***********************************************************************/
|
|
|
|
#include <memory>
|
|
|
|
#include "final/fapplication.h"
|
|
#include "final/fc.h"
|
|
#include "final/fdialog.h"
|
|
#include "final/fevent.h"
|
|
#include "final/fstring.h"
|
|
#include "final/fscrollbar.h"
|
|
#include "final/fstatusbar.h"
|
|
#include "final/ftextview.h"
|
|
#include "final/fwidgetcolors.h"
|
|
|
|
namespace finalcut
|
|
{
|
|
|
|
//----------------------------------------------------------------------
|
|
// class FTextView
|
|
//----------------------------------------------------------------------
|
|
|
|
// constructor and destructor
|
|
//----------------------------------------------------------------------
|
|
FTextView::FTextView(FWidget* parent)
|
|
: FWidget{parent}
|
|
{
|
|
init();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
FTextView::~FTextView() // destructor
|
|
{ }
|
|
|
|
|
|
// public methods of FTextView
|
|
//----------------------------------------------------------------------
|
|
FString FTextView::getText() const
|
|
{
|
|
if ( data.empty() )
|
|
return FString{""};
|
|
|
|
std::size_t len{0};
|
|
|
|
for (auto&& line : data)
|
|
len += line.getLength() + 1; // String length + '\n'
|
|
|
|
FString s{len}; // Reserves storage
|
|
auto iter = s.begin();
|
|
|
|
for (auto&& line : data)
|
|
{
|
|
if ( ! line.isEmpty() )
|
|
{
|
|
if ( iter != s.begin() )
|
|
{
|
|
*iter = '\n';
|
|
++iter;
|
|
}
|
|
|
|
std::copy (line.begin(), line.end(), iter);
|
|
iter += std::distance(line.begin(), line.end());
|
|
}
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::setSize (const FSize& size, bool adjust)
|
|
{
|
|
// Sets the text view size
|
|
|
|
FWidget::setSize (size, adjust);
|
|
changeOnResize();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::setGeometry ( const FPoint& pos, const FSize& size
|
|
, bool adjust)
|
|
{
|
|
// Sets the text view geometry
|
|
|
|
FWidget::setGeometry(pos, size, adjust);
|
|
changeOnResize();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::resetColors()
|
|
{
|
|
const auto& wc = getColorTheme();
|
|
setForegroundColor (wc->dialog_fg);
|
|
setBackgroundColor (wc->dialog_bg);
|
|
FWidget::resetColors();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::setText (const FString& str)
|
|
{
|
|
clear();
|
|
insert(str, -1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::scrollToX (int x)
|
|
{
|
|
scrollTo (x, yoffset);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::scrollToY (int y)
|
|
{
|
|
scrollTo (xoffset, y);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::scrollBy (int dx, int dy)
|
|
{
|
|
scrollTo (xoffset + dx, yoffset + dy);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::scrollTo (int x, int y)
|
|
{
|
|
const bool changeX( x != xoffset );
|
|
const bool changeY( y != yoffset );
|
|
|
|
if ( ! isShown() || ! (changeX || changeY) )
|
|
return;
|
|
|
|
if ( changeX && isHorizontallyScrollable() )
|
|
{
|
|
const auto xoffset_end = int(max_line_width - getTextWidth());
|
|
xoffset = x;
|
|
|
|
if ( xoffset < 0 )
|
|
xoffset = 0;
|
|
|
|
if ( xoffset > xoffset_end )
|
|
xoffset = xoffset_end;
|
|
|
|
if ( update_scrollbar )
|
|
{
|
|
hbar->setValue (xoffset);
|
|
hbar->drawBar();
|
|
}
|
|
}
|
|
|
|
if ( changeY && isVerticallyScrollable() )
|
|
{
|
|
const auto yoffset_end = int(getRows() - getTextHeight());
|
|
yoffset = y;
|
|
|
|
if ( yoffset < 0 )
|
|
yoffset = 0;
|
|
|
|
if ( yoffset > yoffset_end )
|
|
yoffset = yoffset_end;
|
|
|
|
if ( update_scrollbar )
|
|
{
|
|
vbar->setValue (yoffset);
|
|
vbar->drawBar();
|
|
}
|
|
}
|
|
|
|
drawText();
|
|
updateTerminal();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::scrollToBegin()
|
|
{
|
|
scrollToY (0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::scrollToEnd()
|
|
{
|
|
scrollToY (int(getRows() - getTextHeight()));
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::hide()
|
|
{
|
|
FWidget::hide();
|
|
hideArea (getSize());
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::append (const FString& str)
|
|
{
|
|
insert(str, -1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::insert (const FString& str, int pos)
|
|
{
|
|
FString s{};
|
|
|
|
if ( pos < 0 || pos >= int(getRows()) )
|
|
pos = int(getRows());
|
|
|
|
if ( str.isEmpty() )
|
|
s = "\n";
|
|
else
|
|
s = FString{str}.rtrim().expandTabs(FTerm::getTabstop());
|
|
|
|
|
|
auto text_split = s.split("\r\n");
|
|
|
|
for (auto&& line : text_split) // Line loop
|
|
{
|
|
line = line.removeBackspaces()
|
|
.removeDel()
|
|
.replaceControlCodes()
|
|
.rtrim();
|
|
const auto column_width = getColumnWidth(line);
|
|
|
|
if ( column_width > max_line_width )
|
|
{
|
|
max_line_width = column_width;
|
|
|
|
if ( column_width > getTextWidth() )
|
|
{
|
|
const int hmax = ( max_line_width > getTextWidth() )
|
|
? int(max_line_width) - int(getTextWidth())
|
|
: 0;
|
|
hbar->setMaximum (hmax);
|
|
hbar->setPageSize (int(max_line_width), int(getTextWidth()));
|
|
hbar->calculateSliderValues();
|
|
|
|
if ( isShown() && isHorizontallyScrollable() )
|
|
hbar->show();
|
|
}
|
|
}
|
|
}
|
|
|
|
auto iter = data.begin();
|
|
data.insert (iter + pos, text_split.begin(), text_split.end());
|
|
const int vmax = ( getRows() > getTextHeight() )
|
|
? int(getRows()) - int(getTextHeight())
|
|
: 0;
|
|
vbar->setMaximum (vmax);
|
|
vbar->setPageSize (int(getRows()), int(getTextHeight()));
|
|
vbar->calculateSliderValues();
|
|
|
|
if ( isShown() && ! vbar->isShown() && isVerticallyScrollable() )
|
|
vbar->show();
|
|
|
|
if ( isShown() && vbar->isShown() && ! isVerticallyScrollable() )
|
|
vbar->hide();
|
|
|
|
processChanged();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::replaceRange (const FString& str, int from, int to)
|
|
{
|
|
if ( from > to || from >= int(getRows()) || to >= int(getRows()) )
|
|
return;
|
|
|
|
auto iter = data.begin();
|
|
data.erase (iter + from, iter + to + 1);
|
|
|
|
if ( ! str.isNull() )
|
|
insert(str, from);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::clear()
|
|
{
|
|
data.clear();
|
|
data.shrink_to_fit();
|
|
xoffset = 0;
|
|
yoffset = 0;
|
|
max_line_width = 0;
|
|
|
|
vbar->setMinimum(0);
|
|
vbar->setValue(0);
|
|
vbar->hide();
|
|
|
|
hbar->setMinimum(0);
|
|
hbar->setValue(0);
|
|
hbar->hide();
|
|
|
|
// clear list from screen
|
|
setColor();
|
|
|
|
|
|
if ( useFDialogBorder() )
|
|
{
|
|
auto parent = getParentWidget();
|
|
|
|
if ( parent )
|
|
static_cast<FDialog*>(parent)->redraw();
|
|
}
|
|
else
|
|
drawBorder();
|
|
|
|
const std::size_t size = getWidth() - 2;
|
|
|
|
if ( size == 0 )
|
|
return;
|
|
|
|
for (int y{0}; y < int(getTextHeight()); y++)
|
|
{
|
|
print() << FPoint{2, 2 - nf_offset + y}
|
|
<< FString{size, L' '};
|
|
}
|
|
|
|
updateTerminal();
|
|
processChanged();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onKeyPress (FKeyEvent* ev)
|
|
{
|
|
const auto idx = int(ev->key());
|
|
|
|
if ( key_map.find(idx) != key_map.end() )
|
|
{
|
|
key_map[idx]();
|
|
ev->accept();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onMouseDown (FMouseEvent* ev)
|
|
{
|
|
if ( ev->getButton() != fc::LeftButton )
|
|
return;
|
|
|
|
if ( ! hasFocus() )
|
|
{
|
|
FWidget* focused_widget = getFocusWidget();
|
|
setFocus();
|
|
|
|
if ( focused_widget )
|
|
focused_widget->redraw();
|
|
|
|
if ( getStatusBar() )
|
|
getStatusBar()->drawMessage();
|
|
}
|
|
|
|
auto parent = getParentWidget();
|
|
|
|
if ( ! parent )
|
|
return;
|
|
|
|
const auto& dialog = static_cast<FDialog*>(parent);
|
|
|
|
if ( parent->isDialogWidget()
|
|
&& dialog->isResizeable()
|
|
&& ! dialog->isZoomed() )
|
|
{
|
|
const int b = ev->getButton();
|
|
const auto& tp = ev->getTermPos();
|
|
const auto& p = parent->termToWidgetPos(tp);
|
|
parent->setFocus();
|
|
|
|
try
|
|
{
|
|
const auto& _ev = \
|
|
std::make_shared<FMouseEvent>(fc::MouseDown_Event, p, tp, b);
|
|
FApplication::sendEvent (parent, _ev.get());
|
|
}
|
|
catch (const std::bad_alloc&)
|
|
{
|
|
badAllocOutput ("FMouseEvent");
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onMouseUp (FMouseEvent* ev)
|
|
{
|
|
auto parent = getParentWidget();
|
|
|
|
if ( parent && parent->isDialogWidget() )
|
|
{
|
|
const auto& dialog = static_cast<FDialog*>(parent);
|
|
|
|
if ( dialog->isResizeable() && ! dialog->isZoomed() )
|
|
{
|
|
const int b = ev->getButton();
|
|
const auto& tp = ev->getTermPos();
|
|
const auto& p = parent->termToWidgetPos(tp);
|
|
parent->setFocus();
|
|
|
|
try
|
|
{
|
|
const auto& _ev = \
|
|
std::make_shared<FMouseEvent>(fc::MouseUp_Event, p, tp, b);
|
|
FApplication::sendEvent (parent, _ev.get());
|
|
}
|
|
catch (const std::bad_alloc&)
|
|
{
|
|
badAllocOutput ("FMouseEvent");
|
|
}
|
|
}
|
|
}
|
|
|
|
vbar->redraw();
|
|
hbar->redraw();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onMouseMove (FMouseEvent* ev)
|
|
{
|
|
auto parent = getParentWidget();
|
|
|
|
if ( parent && parent->isDialogWidget() )
|
|
{
|
|
const auto& dialog = static_cast<FDialog*>(parent);
|
|
|
|
if ( dialog->isResizeable() && ! dialog->isZoomed() )
|
|
{
|
|
const int b = ev->getButton();
|
|
const auto& tp = ev->getTermPos();
|
|
const auto& p = parent->termToWidgetPos(tp);
|
|
parent->setFocus();
|
|
|
|
try
|
|
{
|
|
const auto& _ev = \
|
|
std::make_shared<FMouseEvent>(fc::MouseMove_Event, p, tp, b);
|
|
FApplication::sendEvent (parent, _ev.get());
|
|
}
|
|
catch (const std::bad_alloc&)
|
|
{
|
|
badAllocOutput ("FMouseEvent");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onWheel (FWheelEvent* ev)
|
|
{
|
|
static constexpr int distance = 4;
|
|
|
|
switch ( ev->getWheel() )
|
|
{
|
|
case fc::WheelUp:
|
|
scrollBy (0, -distance);
|
|
break;
|
|
|
|
case fc::WheelDown:
|
|
scrollBy (0, distance);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( isShown() )
|
|
drawText();
|
|
|
|
updateTerminal();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onFocusIn (FFocusEvent*)
|
|
{
|
|
if ( getStatusBar() )
|
|
getStatusBar()->drawMessage();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::onFocusOut (FFocusEvent*)
|
|
{
|
|
if ( getStatusBar() )
|
|
{
|
|
getStatusBar()->clearMessage();
|
|
getStatusBar()->drawMessage();
|
|
}
|
|
}
|
|
|
|
|
|
// protected methods of FTextView
|
|
//----------------------------------------------------------------------
|
|
void FTextView::adjustSize()
|
|
{
|
|
FWidget::adjustSize();
|
|
const std::size_t width = getWidth();
|
|
const std::size_t height = getHeight();
|
|
const auto last_line = int(getRows());
|
|
const auto max_width = int(max_line_width);
|
|
|
|
if ( xoffset >= max_width - int(width) - nf_offset )
|
|
xoffset = max_width - int(width) - nf_offset - 1;
|
|
|
|
if ( xoffset < 0 )
|
|
xoffset = 0;
|
|
|
|
if ( yoffset > last_line - int(height) - nf_offset + 2 )
|
|
yoffset = last_line - int(height) - nf_offset + 2;
|
|
|
|
if ( yoffset < 0 )
|
|
yoffset = 0;
|
|
|
|
if ( height < 3 )
|
|
return;
|
|
|
|
const int vmax = ( last_line > int(height) - 2 + nf_offset )
|
|
? last_line - int(height) + 2 - nf_offset
|
|
: 0;
|
|
vbar->setMaximum (vmax);
|
|
vbar->setPageSize (last_line, int(height) - 2 + nf_offset);
|
|
vbar->setX (int(width));
|
|
vbar->setHeight (height - 2 + std::size_t(nf_offset), false);
|
|
vbar->setValue (yoffset);
|
|
vbar->resize();
|
|
|
|
if ( width < 3 )
|
|
return;
|
|
|
|
const int hmax = ( max_width > int(width) - nf_offset - 2 )
|
|
? max_width - int(width) + nf_offset + 2
|
|
: 0;
|
|
hbar->setMaximum (hmax);
|
|
hbar->setPageSize (max_width, int(width) - nf_offset - 2);
|
|
hbar->setY (int(height));
|
|
hbar->setWidth (width - 2, false);
|
|
hbar->setValue (xoffset);
|
|
hbar->resize();
|
|
|
|
if ( isShown() )
|
|
{
|
|
if ( isHorizontallyScrollable() )
|
|
hbar->show();
|
|
else
|
|
hbar->hide();
|
|
|
|
if ( isVerticallyScrollable() )
|
|
vbar->show();
|
|
else
|
|
vbar->hide();
|
|
}
|
|
}
|
|
|
|
|
|
// private methods of FTextView
|
|
//----------------------------------------------------------------------
|
|
std::size_t FTextView::getTextHeight() const
|
|
{
|
|
return getHeight() - 2 + std::size_t(nf_offset);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
std::size_t FTextView::getTextWidth() const
|
|
{
|
|
return getWidth() - 2 - std::size_t(nf_offset);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::init()
|
|
{
|
|
initScrollbar (vbar, fc::vertical, this, &FTextView::cb_vbarChange);
|
|
initScrollbar (hbar, fc::horizontal, this, &FTextView::cb_hbarChange);
|
|
resetColors();
|
|
nf_offset = FTerm::isNewFont() ? 1 : 0;
|
|
setTopPadding(1);
|
|
setLeftPadding(1);
|
|
setBottomPadding(1);
|
|
setRightPadding(1 + nf_offset);
|
|
mapKeyFunctions();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void FTextView::mapKeyFunctions()
|
|
{
|
|
key_map[fc::Fkey_up] = [this] { scrollBy (0, -1); };
|
|
key_map[fc::Fkey_down] = [this] { scrollBy (0, 1); };
|
|
key_map[fc::Fkey_left] = [this] { scrollBy (-1, 0); };
|
|
key_map[fc::Fkey_right] = [this] { scrollBy (1, 0); };
|
|
key_map[fc::Fkey_ppage] = [this] { scrollBy (0, -int(getTextHeight())); };
|
|
key_map[fc::Fkey_npage] = [this] { scrollBy (0, int(getTextHeight())); };
|
|
key_map[fc::Fkey_home] = [this] { scrollToBegin(); };
|
|
key_map[fc::Fkey_end] = [this] { scrollToEnd(); };
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::draw()
|
|
{
|
|
setColor();
|
|
drawBorder();
|
|
drawScrollbars();
|
|
drawText();
|
|
|
|
if ( hasFocus() && getStatusBar() )
|
|
{
|
|
const auto& msg = getStatusbarMessage();
|
|
const auto& curMsg = getStatusBar()->getMessage();
|
|
|
|
if ( curMsg != msg )
|
|
{
|
|
getStatusBar()->setMessage(msg);
|
|
getStatusBar()->drawMessage();
|
|
}
|
|
}
|
|
|
|
setCursorPos ({int(getWidth()), int(getHeight())});
|
|
updateTerminal();
|
|
flush();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::drawBorder()
|
|
{
|
|
if ( ! useFDialogBorder() )
|
|
{
|
|
if ( FTerm::isMonochron() )
|
|
setReverse(true);
|
|
|
|
const FRect box{FPoint{1, 1}, getSize()};
|
|
finalcut::drawListBorder (this, box);
|
|
|
|
if ( FTerm::isMonochron() )
|
|
setReverse(false);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::drawScrollbars() const
|
|
{
|
|
if ( ! hbar->isShown() && isHorizontallyScrollable() )
|
|
hbar->show();
|
|
else
|
|
hbar->redraw();
|
|
|
|
if ( ! vbar->isShown() && isVerticallyScrollable() )
|
|
vbar->show();
|
|
else
|
|
vbar->redraw();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::drawText()
|
|
{
|
|
if ( data.empty() || getHeight() <= 2 || getWidth() <= 2 )
|
|
return;
|
|
|
|
auto num = getTextHeight();
|
|
|
|
if ( num > getRows() )
|
|
num = getRows();
|
|
|
|
setColor();
|
|
|
|
if ( FTerm::isMonochron() )
|
|
setReverse(true);
|
|
|
|
for (std::size_t y{0}; y < num; y++) // Line loop
|
|
{
|
|
const std::size_t n = std::size_t(yoffset) + y;
|
|
const std::size_t pos = std::size_t(xoffset) + 1;
|
|
const auto text_width = getTextWidth();
|
|
const FString line(getColumnSubString(data[n], pos, text_width));
|
|
const auto column_width = getColumnWidth(line);
|
|
std::size_t trailing_whitespace{0};
|
|
print() << FPoint{2, 2 - nf_offset + int(y)};
|
|
|
|
for (auto&& ch : line) // Column loop
|
|
{
|
|
if ( getColumnWidth(ch) == 0 )
|
|
continue;
|
|
else if ( isPrintable(ch) )
|
|
print (ch);
|
|
else
|
|
print ('.');
|
|
}
|
|
|
|
if ( column_width <= text_width )
|
|
trailing_whitespace = text_width - column_width;
|
|
|
|
print() << FString{trailing_whitespace, L' '};
|
|
}
|
|
|
|
if ( FTerm::isMonochron() )
|
|
setReverse(false);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline bool FTextView::useFDialogBorder() const
|
|
{
|
|
const auto& parent = getParentWidget();
|
|
bool use_fdialog_border{false};
|
|
|
|
if ( parent
|
|
&& parent->isDialogWidget()
|
|
&& isPaddingIgnored()
|
|
&& getGeometry() == FRect { 1
|
|
, 2
|
|
, parent->getWidth()
|
|
, parent->getHeight() - 1} )
|
|
{
|
|
use_fdialog_border = true;
|
|
}
|
|
|
|
return use_fdialog_border;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline bool FTextView::isPrintable (wchar_t ch) const
|
|
{
|
|
// Check for printable characters
|
|
|
|
const bool utf8 = ( FTerm::getEncoding() == fc::UTF8 ) ? true : false;
|
|
|
|
if ( (utf8 && std::iswprint(std::wint_t(ch)))
|
|
|| (!utf8 && std::isprint(char(ch))) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::processChanged() const
|
|
{
|
|
emitCallback("changed");
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::changeOnResize() const
|
|
{
|
|
const std::size_t width = getWidth();
|
|
const std::size_t height = getHeight();
|
|
|
|
if ( FTerm::isNewFont() )
|
|
{
|
|
vbar->setGeometry (FPoint{int(width), 1}, FSize{2, height - 1});
|
|
hbar->setGeometry (FPoint{1, int(height)}, FSize{width - 2, 1});
|
|
}
|
|
else
|
|
{
|
|
vbar->setGeometry (FPoint{int(width), 2}, FSize{1, height - 2});
|
|
hbar->setGeometry (FPoint{2, int(height)}, FSize{width - 2, 1});
|
|
}
|
|
|
|
vbar->resize();
|
|
hbar->resize();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::cb_vbarChange (const FWidget*)
|
|
{
|
|
const FScrollbar::sType scrollType = vbar->getScrollType();
|
|
static constexpr int wheel_distance = 4;
|
|
int distance{1};
|
|
assert ( scrollType == FScrollbar::noScroll
|
|
|| scrollType == FScrollbar::scrollJump
|
|
|| scrollType == FScrollbar::scrollStepBackward
|
|
|| scrollType == FScrollbar::scrollStepForward
|
|
|| scrollType == FScrollbar::scrollPageBackward
|
|
|| scrollType == FScrollbar::scrollPageForward
|
|
|| scrollType == FScrollbar::scrollWheelUp
|
|
|| scrollType == FScrollbar::scrollWheelDown );
|
|
|
|
if ( scrollType >= FScrollbar::scrollStepBackward )
|
|
update_scrollbar = true;
|
|
else
|
|
update_scrollbar = false;
|
|
|
|
switch ( scrollType )
|
|
{
|
|
case FScrollbar::noScroll:
|
|
break;
|
|
|
|
case FScrollbar::scrollPageBackward:
|
|
distance = int(getClientHeight());
|
|
// fall through
|
|
case FScrollbar::scrollStepBackward:
|
|
scrollBy (0, -distance);
|
|
break;
|
|
|
|
case FScrollbar::scrollPageForward:
|
|
distance = int(getClientHeight());
|
|
// fall through
|
|
case FScrollbar::scrollStepForward:
|
|
scrollBy (0, distance);
|
|
break;
|
|
|
|
case FScrollbar::scrollJump:
|
|
scrollToY (vbar->getValue());
|
|
break;
|
|
|
|
case FScrollbar::scrollWheelUp:
|
|
scrollBy (0, -wheel_distance);
|
|
break;
|
|
|
|
case FScrollbar::scrollWheelDown:
|
|
scrollBy (0, wheel_distance);
|
|
break;
|
|
}
|
|
|
|
update_scrollbar = true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void FTextView::cb_hbarChange (const FWidget*)
|
|
{
|
|
const FScrollbar::sType scrollType = hbar->getScrollType();
|
|
static constexpr int wheel_distance = 4;
|
|
int distance{1};
|
|
assert ( scrollType == FScrollbar::noScroll
|
|
|| scrollType == FScrollbar::scrollJump
|
|
|| scrollType == FScrollbar::scrollStepBackward
|
|
|| scrollType == FScrollbar::scrollStepForward
|
|
|| scrollType == FScrollbar::scrollPageBackward
|
|
|| scrollType == FScrollbar::scrollPageForward
|
|
|| scrollType == FScrollbar::scrollWheelUp
|
|
|| scrollType == FScrollbar::scrollWheelDown );
|
|
|
|
if ( scrollType >= FScrollbar::scrollStepBackward )
|
|
update_scrollbar = true;
|
|
else
|
|
update_scrollbar = false;
|
|
|
|
switch ( scrollType )
|
|
{
|
|
case FScrollbar::noScroll:
|
|
break;
|
|
|
|
case FScrollbar::scrollPageBackward:
|
|
distance = int(getClientWidth());
|
|
// fall through
|
|
case FScrollbar::scrollStepBackward:
|
|
scrollBy (-distance, 0);
|
|
break;
|
|
|
|
case FScrollbar::scrollPageForward:
|
|
distance = int(getClientWidth());
|
|
// fall through
|
|
case FScrollbar::scrollStepForward:
|
|
scrollBy (distance, 0);
|
|
break;
|
|
|
|
case FScrollbar::scrollJump:
|
|
scrollToX (hbar->getValue());
|
|
break;
|
|
|
|
case FScrollbar::scrollWheelUp:
|
|
scrollBy (-wheel_distance, 0);
|
|
break;
|
|
|
|
case FScrollbar::scrollWheelDown:
|
|
scrollBy (wheel_distance, 0);
|
|
break;
|
|
}
|
|
|
|
update_scrollbar = true;
|
|
}
|
|
|
|
} // namespace finalcut
|