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>
* Corrected swapped top and left offset variables
in the class FVTerm

View File

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

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

@ -21,7 +21,7 @@
// ▕▁▁▁▁▁▁▁▁▁▏
// ▲
// │
// ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ 1 *▕▔▔▔▔▔▔▔▔▏
// ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▏
// ▕ FApplication ▏-┬- - - -▕ FEvent ▏
// ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▏
// :

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

@ -4,7 +4,7 @@
// Base class
// ══════════
//
// ▕▔▔▔▔▔▔▔▏ 1 1▕▔▔▔▔▔▔▔▔▔▔▔▏
// ▕▔▔▔▔▔▔▔▏1 1▕▔▔▔▔▔▔▔▔▔▔▔▏
// ▕ FTerm ▏-┬- - - -▕ FOptiMove ▏
// ▕▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▁▁▁▏
// :

View File

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

View File

@ -11,7 +11,7 @@
// │ │
// └─────┬─────┘
// │
// ▕▔▔▔▔▔▔▔▔▏ 1 *▕▔▔▔▔▔▔▔▔▔▏
// ▕▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▔▏
// ▕ FVTerm ▏-┬- - - -▕ FString ▏
// ▕▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▁▏
// :
@ -283,6 +283,7 @@ class FVTerm : public FObject, public FTerm
// Inquiries
bool hasPrintArea() const;
bool hasChildPrintArea() const;
bool isChildPrintArea() const;
bool isVirtualWindow() const;
// Methods

View File

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

View File

@ -16,7 +16,7 @@
// ▕▁▁▁▁▁▁▁▁▏
// ▲
// │
// ▕▔▔▔▔▔▔▔▔▔▏ 1 1▕▔▔▔▔▔▔▔▔▔▔▔▔▏
// ▕▔▔▔▔▔▔▔▔▔▏1 1▕▔▔▔▔▔▔▔▔▔▔▔▔▏
// ▕ FWidget ▏-┬- - - -▕ FStatusBar ▏
// ▕▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▁▁▁▁▏
// :

View File

@ -21,7 +21,7 @@
// ▕▁▁▁▁▁▁▁▁▁▏
// ▲
// │
// ▕▔▔▔▔▔▔▔▔▔▏ 1 *▕▔▔▔▔▔▔▔▔▏
// ▕▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▏
// ▕ FWindow ▏-┬- - - -▕ FEvent ▏
// ▕▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▏
// :

View File

@ -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();
}