Improve input cursor positioning in FScrollView

This commit is contained in:
Markus Gans 2017-03-08 23:48:30 +01:00
parent bd06df8987
commit 56df867ef7
18 changed files with 145 additions and 63 deletions

View File

@ -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> 2017-02-24 Markus Gans <guru.mail@muenster.de>
* Corrected swapped top and left offset variables * Corrected swapped top and left offset variables
in the class FVTerm in the class FVTerm

View File

@ -19,7 +19,7 @@
The Final Cut 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. 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) ![](doc/fileopen-dialog.png)

View File

@ -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

View File

@ -67,6 +67,20 @@ FObject::~FObject() // destructor
} }
// public methods of FObject // 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) void FObject::addChild (FObject* obj)
{ {

View File

@ -75,6 +75,8 @@ class FObject
// Inquiries // Inquiries
bool hasParent() const; bool hasParent() const;
bool hasChildren() const; bool hasChildren() const;
bool isChild (FObject*) const;
bool isDirectChild (FObject*) const;
bool isTimerInUpdating() const; bool isTimerInUpdating() const;
// Methods // Methods
@ -140,6 +142,10 @@ inline bool FObject::hasParent() const
inline bool FObject::hasChildren() const inline bool FObject::hasChildren() const
{ return bool( ! children_list.empty() ); } { return bool( ! children_list.empty() ); }
//----------------------------------------------------------------------
inline bool FObject::isDirectChild (FObject* obj) const
{ return bool( obj->getParent() == this ); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FObject::isTimerInUpdating() const inline bool FObject::isTimerInUpdating() const
{ return timer_modify_lock; } { return timer_modify_lock; }

View File

@ -709,8 +709,8 @@ int FOptiMove::capDurationToLength (int duration)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
int FOptiMove::repeatedAppend (capability& o, int count, char* dst) int FOptiMove::repeatedAppend (capability& o, int count, char* dst)
{ {
register size_t src_len; register std::size_t src_len;
register size_t dst_len; register std::size_t dst_len;
register int total; register int total;
src_len = std::strlen(o.cap); src_len = std::strlen(o.cap);

View File

@ -2,6 +2,7 @@
// Provides: class FScrollView // Provides: class FScrollView
#include "fscrollview.h" #include "fscrollview.h"
#include "fwindow.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -23,7 +24,7 @@ FScrollView::FScrollView (FWidget* parent)
, vMode(fc::Auto) , vMode(fc::Auto)
, hMode(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.setWidth(save_width);
viewport_geometry.setHeight(save_height); viewport_geometry.setHeight(save_height);
hbar->setValue (xoffset);
vbar->setValue (yoffset);
drawHBar();
drawVBar();
viewport->has_changes = true; viewport->has_changes = true;
setTopPadding (1 - yoffset); setTopPadding (1 - yoffset);
setLeftPadding (1 - xoffset); setLeftPadding (1 - xoffset);
setBottomPadding (1 - (getScrollHeight() - getViewportHeight() - yoffset)); setBottomPadding (1 - (getScrollHeight() - getViewportHeight() - yoffset));
setRightPadding (1 - (getScrollWidth() - getViewportWidth() - xoffset) + nf_offset); setRightPadding (1 - (getScrollWidth() - getViewportWidth() - xoffset) + nf_offset);
copy2area(); copy2area();
hbar->setValue (xoffset);
vbar->setValue (yoffset);
drawHBar();
drawVBar();
updateTerminal(); updateTerminal();
} }
@ -723,6 +724,7 @@ void FScrollView::copy2area()
print_area->changes[ay+y].xmax = uInt(ax+x_end-1); print_area->changes[ay+y].xmax = uInt(ax+x_end-1);
} }
setViewportCursor();
viewport->has_changes = false; viewport->has_changes = false;
print_area->has_changes = true; print_area->has_changes = true;
} }
@ -730,8 +732,29 @@ void FScrollView::copy2area()
// private methods of FScrollView // 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); setForegroundColor (wc.dialog_fg);
setBackgroundColor (wc.dialog_bg); 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) void FScrollView::cb_VBarChange (FWidget*, data_ptr)
{ {

View File

@ -128,11 +128,15 @@ class FScrollView : public FWidget
// Disable assignment operator (=) // Disable assignment operator (=)
FScrollView& operator = (const FScrollView&); FScrollView& operator = (const FScrollView&);
// Accessors
FPoint getViewportCursorPos();
// Methods // Methods
void init(); void init (FWidget*);
void calculateScrollbarPos(); void calculateScrollbarPos();
void setHorizontalScrollBarVisibility(); void setHorizontalScrollBarVisibility();
void setVerticalScrollBarVisibility(); void setVerticalScrollBarVisibility();
void setViewportCursor();
void redrawHBar(); void redrawHBar();
void redrawVBar(); void redrawVBar();
void drawHBar(); void drawHBar();

View File

@ -2381,7 +2381,7 @@ inline char* FString::wc_to_c_str (const wchar_t* s) const
c_string = new char[dest_size](); c_string = new char[dest_size]();
// pre-initialiaze the whole string with '\0' // 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) 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](); dest = new wchar_t[size]();
// pre-initialiaze the whole string with '\0' // 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) catch (const std::bad_alloc& ex)
{ {

View File

@ -379,7 +379,7 @@ int FTerm::parseKeyString ( char buffer[]
, timeval* time_keypressed ) , timeval* time_keypressed )
{ {
register uChar firstchar = uChar(buffer[0]); 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 const long key_timeout = 100000; // 100 ms
int key, len, n; int key, len, n;
@ -831,7 +831,7 @@ FString* FTerm::getXTermFont()
{ {
if ( std::scanf("\033]50;%[^\n]s", temp) == 1 ) 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 // BEL + '\0' = string terminator
if ( n >= 5 && temp[n-1] == BEL[0] && temp[n] == '\0' ) 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 ) 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 // Esc + \ = OSC string terminator
if ( n >= 2 && temp[n-2] == ESC[0] && temp[n-1] == '\\' ) 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 ) 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 // BEL + '\0' = string terminator
if ( n >= 6 && temp[n-1] == BEL[0] && temp[n] == '\0' ) if ( n >= 6 && temp[n-1] == BEL[0] && temp[n] == '\0' )
@ -1969,7 +1969,7 @@ void FTerm::restoreTTYsettings()
int FTerm::getScreenFont() int FTerm::getScreenFont()
{ {
struct console_font_op font; struct console_font_op font;
const size_t data_size = 4 * 32 * 512; const std::size_t data_size = 4 * 32 * 512;
int ret; int ret;
if ( fd_tty < 0 ) if ( fd_tty < 0 )
@ -2026,7 +2026,7 @@ int FTerm::setScreenFont ( uChar* fontdata, uInt count
else else
{ {
const uInt bytes_per_line = font.width / 8; 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 try
{ {

View File

@ -262,7 +262,7 @@ void FVTerm::delPreprocessingHandler (FVTerm* instance)
if ( ! print_area ) if ( ! print_area )
FVTerm::getPrintArea(); FVTerm::getPrintArea();
if ( ! print_area || ! print_area->preprocessing_call.empty() ) if ( ! print_area || print_area->preprocessing_call.empty() )
return; return;
FPreprocessing::iterator iter, end; FPreprocessing::iterator iter, end;
@ -689,6 +689,19 @@ FVTerm::term_area* FVTerm::getPrintArea()
return vdesktop; 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 void FVTerm::createArea ( const FRect& r
, const FPoint& p , const FPoint& p
@ -736,6 +749,8 @@ void FVTerm::resizeArea ( int offset_left, int offset_top
, int rsw, int bsh , int rsw, int bsh
, term_area* area ) , term_area* area )
{ {
// Resize the virtual window to a new size.
assert ( offset_top >= 0 ); assert ( offset_top >= 0 );
assert ( width > 0 ); assert ( width > 0 );
assert ( height > 0 ); assert ( height > 0 );
@ -814,6 +829,7 @@ void FVTerm::resizeArea ( int offset_left, int offset_top
void FVTerm::removeArea (term_area*& area) void FVTerm::removeArea (term_area*& area)
{ {
// remove the virtual window // remove the virtual window
if ( area != 0 ) if ( area != 0 )
{ {
if ( area->changes != 0 ) if ( area->changes != 0 )

View File

@ -283,6 +283,7 @@ class FVTerm : public FObject, public FTerm
// Inquiries // Inquiries
bool hasPrintArea() const; bool hasPrintArea() const;
bool hasChildPrintArea() const; bool hasChildPrintArea() const;
bool isChildPrintArea() const;
bool isVirtualWindow() const; bool isVirtualWindow() const;
// Methods // Methods

View File

@ -674,15 +674,24 @@ bool FWidget::setCursorPos (register int x, register int y)
if ( (flags & fc::focus) == 0 || isWindowWidget() ) if ( (flags & fc::focus) == 0 || isWindowWidget() )
return false; return false;
FWidget* window = FWindow::getWindowWidget(this); if ( ! FWindow::getWindowWidget(this) )
if ( ! window )
return false; return false;
if ( term_area* area = window->getVWin() ) term_area* area = getPrintArea();
if ( area->widget )
{ {
setAreaCursor ( getTermX() - window->getTermX() + x int widget_offsetX = getTermX() - area->widget->getTermX();
, getTermY() - window->getTermY() + y 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 , visible_cursor
, area ); , area );
return true; return true;

View File

@ -27,14 +27,19 @@ class scrollview : public FScrollView
void setScrollSize (int, int); void setScrollSize (int, int);
private: private:
// Disable copy constructor
scrollview (const scrollview&);
// Disable assignment operator (=)
scrollview& operator = (const scrollview&);
// Method // Method
void draw(); void draw();
// Callback methods // Callback methods
void cb_go_east (FWidget*, void*); void cb_go_east (FWidget*, data_ptr);
void cb_go_south (FWidget*, void*); void cb_go_south (FWidget*, data_ptr);
void cb_go_west (FWidget*, void*); void cb_go_west (FWidget*, data_ptr);
void cb_go_north (FWidget*, void*); void cb_go_north (FWidget*, data_ptr);
// Data Members // Data Members
FButton* go_east; FButton* go_east;
@ -44,9 +49,14 @@ class scrollview : public FScrollView
}; };
#pragma pack(pop) #pragma pack(pop)
#include "fcheckbox.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
scrollview::scrollview (FWidget* parent) scrollview::scrollview (FWidget* parent)
: FScrollView(parent) : FScrollView(parent)
, go_east()
, go_south()
, go_west()
, go_north()
{ {
go_east = new FButton(wchar_t(fc::BlackRightPointingPointer) , this); go_east = new FButton(wchar_t(fc::BlackRightPointingPointer) , this);
go_east->setGeometry (1, 1, 5, 1); 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); scrollToX (getScrollWidth() - getViewportWidth() + 1);
go_south->setFocus(); 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); scrollToY (getScrollHeight() - getViewportHeight() + 1);
go_west->setFocus(); 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); scrollToX (1);
go_north->setFocus(); 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); scrollToY (1);
go_east->setFocus(); go_east->setFocus();
@ -184,7 +194,7 @@ class scrollviewdemo : public FDialog
void onClose (FCloseEvent*); void onClose (FCloseEvent*);
// Callback method // Callback method
void cb_quit (FWidget* = 0, void* = 0); void cb_quit (FWidget* = 0, data_ptr = 0);
}; };
#pragma pack(pop) #pragma pack(pop)
@ -224,7 +234,7 @@ scrollviewdemo::~scrollviewdemo()
{ } { }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void scrollviewdemo::cb_quit (FWidget*, void*) void scrollviewdemo::cb_quit (FWidget*, data_ptr)
{ {
close(); close();
} }