Improve input cursor positioning in FScrollView
This commit is contained in:
parent
bd06df8987
commit
56df867ef7
|
@ -1,3 +1,6 @@
|
|||
2017-03-08 Markus Gans <guru.mail@muenster.de>
|
||||
* Improve input cursor positioning in FScrollView
|
||||
|
||||
2017-02-24 Markus Gans <guru.mail@muenster.de>
|
||||
* Corrected swapped top and left offset variables
|
||||
in the class FVTerm
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
The Final Cut
|
||||
=============
|
||||
The Final Cut is a class library and widget toolkit with full mouse support for creating a text-based user interface. The library supports the programmer to develop an application for the text console. It allows the simultaneous handling of multiple windows on the screen.
|
||||
The Final Cut is a class library and widget toolkit with full mouse support for creating a [text-based user interface](https://en.wikipedia.org/wiki/Text-based_user_interface). The library supports the programmer to develop an application for the text console. It allows the simultaneous handling of multiple windows on the screen.
|
||||
The C++ class design was inspired by the Qt framework. It provides common controls like dialog windows, push buttons, check boxes, radio buttons, input lines, list boxes, status bars and so on.
|
||||
|
||||
![](doc/fileopen-dialog.png)
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0
|
||||
select(1, [0], NULL, NULL, {0, 100000}) = 1 (in [0], left {0, 99999})
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE) = 0
|
||||
read(0, "", 1023) = 0
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0
|
||||
select(1, [0], NULL, NULL, {0, 100000}) = 1 (in [0], left {0, 99998})
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE) = 0
|
||||
read(0, "", 1023) = 0
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0
|
||||
select(1, [0], NULL, NULL, {0, 100000}) = 1 (in [0], left {0, 99999})
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE) = 0
|
||||
read(0, "", 1023) = 0
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0
|
||||
select(1, [0], NULL, NULL, {0, 100000}) = 1 (in [0], left {0, 99999})
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE) = 0
|
||||
read(0, "", 1023) = 0
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0
|
||||
select(1, [0], NULL, NULL, {0, 100000}) = 1 (in [0], left {0, 99999})
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE) = 0
|
||||
read(0, "", 1023) = 0
|
||||
fcntl(0, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0
|
||||
^CProcess 7036 detached
|
||||
|
|
@ -67,6 +67,20 @@ FObject::~FObject() // destructor
|
|||
}
|
||||
|
||||
// public methods of FObject
|
||||
//----------------------------------------------------------------------
|
||||
bool FObject::isChild (FObject* obj) const
|
||||
{
|
||||
while ( FObject* p_obj = obj->getParent() )
|
||||
{
|
||||
obj = p_obj;
|
||||
|
||||
if ( obj == this )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FObject::addChild (FObject* obj)
|
||||
{
|
||||
|
|
|
@ -75,6 +75,8 @@ class FObject
|
|||
// Inquiries
|
||||
bool hasParent() const;
|
||||
bool hasChildren() const;
|
||||
bool isChild (FObject*) const;
|
||||
bool isDirectChild (FObject*) const;
|
||||
bool isTimerInUpdating() const;
|
||||
|
||||
// Methods
|
||||
|
@ -140,6 +142,10 @@ inline bool FObject::hasParent() const
|
|||
inline bool FObject::hasChildren() const
|
||||
{ return bool( ! children_list.empty() ); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool FObject::isDirectChild (FObject* obj) const
|
||||
{ return bool( obj->getParent() == this ); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool FObject::isTimerInUpdating() const
|
||||
{ return timer_modify_lock; }
|
||||
|
|
|
@ -709,8 +709,8 @@ int FOptiMove::capDurationToLength (int duration)
|
|||
//----------------------------------------------------------------------
|
||||
int FOptiMove::repeatedAppend (capability& o, int count, char* dst)
|
||||
{
|
||||
register size_t src_len;
|
||||
register size_t dst_len;
|
||||
register std::size_t src_len;
|
||||
register std::size_t dst_len;
|
||||
register int total;
|
||||
|
||||
src_len = std::strlen(o.cap);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Provides: class FScrollView
|
||||
|
||||
#include "fscrollview.h"
|
||||
#include "fwindow.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -23,7 +24,7 @@ FScrollView::FScrollView (FWidget* parent)
|
|||
, vMode(fc::Auto)
|
||||
, hMode(fc::Auto)
|
||||
{
|
||||
init();
|
||||
init(parent);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -329,16 +330,16 @@ void FScrollView::scrollTo (int x, int y)
|
|||
|
||||
viewport_geometry.setWidth(save_width);
|
||||
viewport_geometry.setHeight(save_height);
|
||||
hbar->setValue (xoffset);
|
||||
vbar->setValue (yoffset);
|
||||
drawHBar();
|
||||
drawVBar();
|
||||
viewport->has_changes = true;
|
||||
setTopPadding (1 - yoffset);
|
||||
setLeftPadding (1 - xoffset);
|
||||
setBottomPadding (1 - (getScrollHeight() - getViewportHeight() - yoffset));
|
||||
setRightPadding (1 - (getScrollWidth() - getViewportWidth() - xoffset) + nf_offset);
|
||||
copy2area();
|
||||
hbar->setValue (xoffset);
|
||||
vbar->setValue (yoffset);
|
||||
drawHBar();
|
||||
drawVBar();
|
||||
updateTerminal();
|
||||
}
|
||||
|
||||
|
@ -723,6 +724,7 @@ void FScrollView::copy2area()
|
|||
print_area->changes[ay+y].xmax = uInt(ax+x_end-1);
|
||||
}
|
||||
|
||||
setViewportCursor();
|
||||
viewport->has_changes = false;
|
||||
print_area->has_changes = true;
|
||||
}
|
||||
|
@ -730,8 +732,29 @@ void FScrollView::copy2area()
|
|||
|
||||
// private methods of FScrollView
|
||||
//----------------------------------------------------------------------
|
||||
void FScrollView::init()
|
||||
inline FPoint FScrollView::getViewportCursorPos()
|
||||
{
|
||||
int x, y;
|
||||
FWidget* window = FWindow::getWindowWidget(this);
|
||||
if ( window )
|
||||
{
|
||||
int widget_offsetX = getTermX() - window->getTermX();
|
||||
int widget_offsetY = getTermY() - window->getTermY();
|
||||
x = widget_offsetX + viewport->input_cursor_x - viewport_geometry.getX();
|
||||
y = widget_offsetY + viewport->input_cursor_y - viewport_geometry.getY();
|
||||
return FPoint(x,y);
|
||||
}
|
||||
else
|
||||
return FPoint(-1,-1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FScrollView::init (FWidget* parent)
|
||||
{
|
||||
assert ( parent != 0 );
|
||||
assert ( std::strcmp ( parent->getClassName()
|
||||
, const_cast<char*>("FScrollView") ) != 0 );
|
||||
|
||||
setForegroundColor (wc.dialog_fg);
|
||||
setBackgroundColor (wc.dialog_bg);
|
||||
|
||||
|
@ -849,6 +872,25 @@ void FScrollView::setVerticalScrollBarVisibility()
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FScrollView::setViewportCursor()
|
||||
{
|
||||
if ( ! isChild(getFocusWidget()) )
|
||||
return;
|
||||
|
||||
FPoint cursor_pos ( viewport->input_cursor_x - 1
|
||||
, viewport->input_cursor_y - 1 );
|
||||
FPoint window_cursor_pos = getViewportCursorPos();
|
||||
print_area->input_cursor_x = window_cursor_pos.getX();
|
||||
print_area->input_cursor_y = window_cursor_pos.getY();
|
||||
|
||||
if ( viewport->input_cursor_visible
|
||||
&& viewport_geometry.contains(cursor_pos) )
|
||||
print_area->input_cursor_visible = true;
|
||||
else
|
||||
print_area->input_cursor_visible = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FScrollView::cb_VBarChange (FWidget*, data_ptr)
|
||||
{
|
||||
|
|
|
@ -128,11 +128,15 @@ class FScrollView : public FWidget
|
|||
// Disable assignment operator (=)
|
||||
FScrollView& operator = (const FScrollView&);
|
||||
|
||||
// Accessors
|
||||
FPoint getViewportCursorPos();
|
||||
|
||||
// Methods
|
||||
void init();
|
||||
void init (FWidget*);
|
||||
void calculateScrollbarPos();
|
||||
void setHorizontalScrollBarVisibility();
|
||||
void setVerticalScrollBarVisibility();
|
||||
void setViewportCursor();
|
||||
void redrawHBar();
|
||||
void redrawVBar();
|
||||
void drawHBar();
|
||||
|
|
|
@ -2381,7 +2381,7 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const
|
|||
c_string = new char[dest_size]();
|
||||
|
||||
// pre-initialiaze the whole string with '\0'
|
||||
std::memset (c_string, '\0', size_t(dest_size));
|
||||
std::memset (c_string, '\0', std::size_t(dest_size));
|
||||
}
|
||||
catch (const std::bad_alloc& ex)
|
||||
{
|
||||
|
@ -2435,7 +2435,7 @@ inline wchar_t* FString::c_to_wc_str (const char* s) const
|
|||
{
|
||||
dest = new wchar_t[size]();
|
||||
// pre-initialiaze the whole string with '\0'
|
||||
std::wmemset (dest, L'\0', size_t(size));
|
||||
std::wmemset (dest, L'\0', std::size_t(size));
|
||||
}
|
||||
catch (const std::bad_alloc& ex)
|
||||
{
|
||||
|
|
|
@ -379,7 +379,7 @@ int FTerm::parseKeyString ( char buffer[]
|
|||
, timeval* time_keypressed )
|
||||
{
|
||||
register uChar firstchar = uChar(buffer[0]);
|
||||
register size_t buf_len = std::strlen(buffer);
|
||||
register std::size_t buf_len = std::strlen(buffer);
|
||||
const long key_timeout = 100000; // 100 ms
|
||||
int key, len, n;
|
||||
|
||||
|
@ -831,7 +831,7 @@ FString* FTerm::getXTermFont()
|
|||
{
|
||||
if ( std::scanf("\033]50;%[^\n]s", temp) == 1 )
|
||||
{
|
||||
size_t n = std::strlen(temp);
|
||||
std::size_t n = std::strlen(temp);
|
||||
|
||||
// BEL + '\0' = string terminator
|
||||
if ( n >= 5 && temp[n-1] == BEL[0] && temp[n] == '\0' )
|
||||
|
@ -868,7 +868,7 @@ FString* FTerm::getXTermTitle()
|
|||
{
|
||||
if ( std::scanf("\033]l%[^\n]s", temp) == 1 )
|
||||
{
|
||||
size_t n = std::strlen(temp);
|
||||
std::size_t n = std::strlen(temp);
|
||||
|
||||
// Esc + \ = OSC string terminator
|
||||
if ( n >= 2 && temp[n-2] == ESC[0] && temp[n-1] == '\\' )
|
||||
|
@ -912,7 +912,7 @@ const FString FTerm::getXTermColorName (int color)
|
|||
{
|
||||
if ( std::scanf("\033]4;%d;%[^\n]s", &color, temp) == 2 )
|
||||
{
|
||||
size_t n = std::strlen(temp);
|
||||
std::size_t n = std::strlen(temp);
|
||||
|
||||
// BEL + '\0' = string terminator
|
||||
if ( n >= 6 && temp[n-1] == BEL[0] && temp[n] == '\0' )
|
||||
|
@ -1969,7 +1969,7 @@ void FTerm::restoreTTYsettings()
|
|||
int FTerm::getScreenFont()
|
||||
{
|
||||
struct console_font_op font;
|
||||
const size_t data_size = 4 * 32 * 512;
|
||||
const std::size_t data_size = 4 * 32 * 512;
|
||||
int ret;
|
||||
|
||||
if ( fd_tty < 0 )
|
||||
|
@ -2026,7 +2026,7 @@ int FTerm::setScreenFont ( uChar* fontdata, uInt count
|
|||
else
|
||||
{
|
||||
const uInt bytes_per_line = font.width / 8;
|
||||
const size_t data_size = bytes_per_line * 32 * font.charcount;
|
||||
const std::size_t data_size = bytes_per_line * 32 * font.charcount;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -262,7 +262,7 @@ void FVTerm::delPreprocessingHandler (FVTerm* instance)
|
|||
if ( ! print_area )
|
||||
FVTerm::getPrintArea();
|
||||
|
||||
if ( ! print_area || ! print_area->preprocessing_call.empty() )
|
||||
if ( ! print_area || print_area->preprocessing_call.empty() )
|
||||
return;
|
||||
|
||||
FPreprocessing::iterator iter, end;
|
||||
|
@ -689,6 +689,19 @@ FVTerm::term_area* FVTerm::getPrintArea()
|
|||
return vdesktop;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool FVTerm::isChildPrintArea() const
|
||||
{
|
||||
FVTerm* p_obj = static_cast<FVTerm*>(getParent());
|
||||
|
||||
if ( p_obj
|
||||
&& p_obj->child_print_area
|
||||
&& p_obj->child_print_area == this->print_area )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FVTerm::createArea ( const FRect& r
|
||||
, const FPoint& p
|
||||
|
@ -736,6 +749,8 @@ void FVTerm::resizeArea ( int offset_left, int offset_top
|
|||
, int rsw, int bsh
|
||||
, term_area* area )
|
||||
{
|
||||
// Resize the virtual window to a new size.
|
||||
|
||||
assert ( offset_top >= 0 );
|
||||
assert ( width > 0 );
|
||||
assert ( height > 0 );
|
||||
|
@ -814,6 +829,7 @@ void FVTerm::resizeArea ( int offset_left, int offset_top
|
|||
void FVTerm::removeArea (term_area*& area)
|
||||
{
|
||||
// remove the virtual window
|
||||
|
||||
if ( area != 0 )
|
||||
{
|
||||
if ( area->changes != 0 )
|
||||
|
|
|
@ -283,6 +283,7 @@ class FVTerm : public FObject, public FTerm
|
|||
// Inquiries
|
||||
bool hasPrintArea() const;
|
||||
bool hasChildPrintArea() const;
|
||||
bool isChildPrintArea() const;
|
||||
bool isVirtualWindow() const;
|
||||
|
||||
// Methods
|
||||
|
|
|
@ -674,15 +674,24 @@ bool FWidget::setCursorPos (register int x, register int y)
|
|||
if ( (flags & fc::focus) == 0 || isWindowWidget() )
|
||||
return false;
|
||||
|
||||
FWidget* window = FWindow::getWindowWidget(this);
|
||||
|
||||
if ( ! window )
|
||||
if ( ! FWindow::getWindowWidget(this) )
|
||||
return false;
|
||||
|
||||
if ( term_area* area = window->getVWin() )
|
||||
term_area* area = getPrintArea();
|
||||
|
||||
if ( area->widget )
|
||||
{
|
||||
setAreaCursor ( getTermX() - window->getTermX() + x
|
||||
, getTermY() - window->getTermY() + y
|
||||
int widget_offsetX = getTermX() - area->widget->getTermX();
|
||||
int widget_offsetY = getTermY() - area->widget->getTermY();
|
||||
|
||||
if ( isChildPrintArea() )
|
||||
{
|
||||
widget_offsetX += (1 - area->widget->getLeftPadding());
|
||||
widget_offsetY += (1 - area->widget->getTopPadding());
|
||||
}
|
||||
|
||||
setAreaCursor ( widget_offsetX + x
|
||||
, widget_offsetY + y
|
||||
, visible_cursor
|
||||
, area );
|
||||
return true;
|
||||
|
|
|
@ -27,14 +27,19 @@ class scrollview : public FScrollView
|
|||
void setScrollSize (int, int);
|
||||
|
||||
private:
|
||||
// Disable copy constructor
|
||||
scrollview (const scrollview&);
|
||||
// Disable assignment operator (=)
|
||||
scrollview& operator = (const scrollview&);
|
||||
|
||||
// Method
|
||||
void draw();
|
||||
|
||||
// Callback methods
|
||||
void cb_go_east (FWidget*, void*);
|
||||
void cb_go_south (FWidget*, void*);
|
||||
void cb_go_west (FWidget*, void*);
|
||||
void cb_go_north (FWidget*, void*);
|
||||
void cb_go_east (FWidget*, data_ptr);
|
||||
void cb_go_south (FWidget*, data_ptr);
|
||||
void cb_go_west (FWidget*, data_ptr);
|
||||
void cb_go_north (FWidget*, data_ptr);
|
||||
|
||||
// Data Members
|
||||
FButton* go_east;
|
||||
|
@ -44,9 +49,14 @@ class scrollview : public FScrollView
|
|||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "fcheckbox.h"
|
||||
//----------------------------------------------------------------------
|
||||
scrollview::scrollview (FWidget* parent)
|
||||
: FScrollView(parent)
|
||||
, go_east()
|
||||
, go_south()
|
||||
, go_west()
|
||||
, go_north()
|
||||
{
|
||||
go_east = new FButton(wchar_t(fc::BlackRightPointingPointer) , this);
|
||||
go_east->setGeometry (1, 1, 5, 1);
|
||||
|
@ -128,7 +138,7 @@ void scrollview::draw()
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void scrollview::cb_go_east (FWidget*, void*)
|
||||
void scrollview::cb_go_east (FWidget*, data_ptr)
|
||||
{
|
||||
scrollToX (getScrollWidth() - getViewportWidth() + 1);
|
||||
go_south->setFocus();
|
||||
|
@ -137,7 +147,7 @@ void scrollview::cb_go_east (FWidget*, void*)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void scrollview::cb_go_south (FWidget*, void*)
|
||||
void scrollview::cb_go_south (FWidget*, data_ptr)
|
||||
{
|
||||
scrollToY (getScrollHeight() - getViewportHeight() + 1);
|
||||
go_west->setFocus();
|
||||
|
@ -146,7 +156,7 @@ void scrollview::cb_go_south (FWidget*, void*)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void scrollview::cb_go_west (FWidget*, void*)
|
||||
void scrollview::cb_go_west (FWidget*, data_ptr)
|
||||
{
|
||||
scrollToX (1);
|
||||
go_north->setFocus();
|
||||
|
@ -155,7 +165,7 @@ void scrollview::cb_go_west (FWidget*, void*)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void scrollview::cb_go_north (FWidget*, void*)
|
||||
void scrollview::cb_go_north (FWidget*, data_ptr)
|
||||
{
|
||||
scrollToY (1);
|
||||
go_east->setFocus();
|
||||
|
@ -184,7 +194,7 @@ class scrollviewdemo : public FDialog
|
|||
void onClose (FCloseEvent*);
|
||||
|
||||
// Callback method
|
||||
void cb_quit (FWidget* = 0, void* = 0);
|
||||
void cb_quit (FWidget* = 0, data_ptr = 0);
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
@ -224,7 +234,7 @@ scrollviewdemo::~scrollviewdemo()
|
|||
{ }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void scrollviewdemo::cb_quit (FWidget*, void*)
|
||||
void scrollviewdemo::cb_quit (FWidget*, data_ptr)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue