FScrollView now scrolls automatically to the focused widget

This commit is contained in:
Markus Gans 2017-01-26 00:31:07 +01:00
parent 51b1d18a84
commit 59189160fd
14 changed files with 158 additions and 79 deletions

View File

@ -1,3 +1,6 @@
2017-01-26 Markus Gans <guru.mail@muenster.de>
* FScrollView now scrolls automatically to the focused widget
2017-01-22 Markus Gans <guru.mail@muenster.de>
* A FScrollView object can now have client widgets
on the scrolling area

View File

@ -60,7 +60,7 @@ finalcutinclude_HEADERS = \
fconfig.h \
fswitch.h \
fdialog.h \
fenum.h \
fc.h \
fevent.h \
ffiledialog.h \
final.h \

View File

@ -423,7 +423,7 @@ finalcutinclude_HEADERS = \
fconfig.h \
fswitch.h \
fdialog.h \
fenum.h \
fc.h \
fevent.h \
ffiledialog.h \
final.h \

View File

@ -199,9 +199,15 @@ bool FButton::setShadow (bool on)
if ( on
&& (Encoding != fc::VT100 || isTeraTerm() )
&& Encoding != fc::ASCII )
{
flags |= fc::shadow;
setShadowSize(1,1);
}
else
{
flags &= ~fc::shadow;
setShadowSize(0,0);
}
return on;
}

View File

@ -1,4 +1,4 @@
// File: fenum.h
// File: fc.h
// Provides: class fc
//
// Standalone class
@ -8,8 +8,8 @@
// ▕ fc ▏
// ▕▁▁▁▁▁▁▁▁▏
#ifndef _FENUM_H
#define _FENUM_H
#ifndef _FC_H
#define _FC_H
//----------------------------------------------------------------------
@ -25,27 +25,28 @@ class fc
// event types
enum events
{
None_Event, // invalid event
KeyPress_Event, // key pressed
KeyUp_Event, // key released
KeyDown_Event, // key pressed
MouseDown_Event, // mouse button pressed
MouseUp_Event, // mouse button released
MouseDoubleClick_Event, // mouse button double click
MouseWheel_Event, // mouse wheel rolled
MouseMove_Event, // mouse move
FocusIn_Event, // focus in
FocusOut_Event, // focus out
WindowActive_Event, // activate window
WindowInactive_Event, // deactivate window
WindowRaised_Event, // raise window
WindowLowered_Event, // lower window
Accelerator_Event, // keyboard accelerator
Resize_Event, // terminal resize
Show_Event, // widget is shown
Hide_Event, // widget is hidden
Close_Event, // widget close
Timer_Event // timer event occur
None_Event, // invalid event
KeyPress_Event, // key pressed
KeyUp_Event, // key released
KeyDown_Event, // key pressed
MouseDown_Event, // mouse button pressed
MouseUp_Event, // mouse button released
MouseDoubleClick_Event, // mouse button double click
MouseWheel_Event, // mouse wheel rolled
MouseMove_Event, // mouse move
FocusIn_Event, // focus in
FocusOut_Event, // focus out
ChildFocusChanged_Event, // child focus changed
WindowActive_Event, // activate window
WindowInactive_Event, // deactivate window
WindowRaised_Event, // raise window
WindowLowered_Event, // lower window
Accelerator_Event, // keyboard accelerator
Resize_Event, // terminal resize
Show_Event, // widget is shown
Hide_Event, // widget is hidden
Close_Event, // widget close
Timer_Event // timer event occur
};
// properties of a widget
@ -1065,4 +1066,4 @@ class fc
#pragma pack(pop)
#endif // _FENUM_H
#endif // _FC_H

View File

@ -53,7 +53,7 @@
#ifndef _FEVENT_H
#define _FEVENT_H
#include "fenum.h"
#include "fc.h"
#include "fpoint.h"

View File

@ -139,9 +139,15 @@ bool FLineEdit::setShadow (bool on)
if ( on
&& (Encoding != fc::VT100 || isTeraTerm() )
&& Encoding != fc::ASCII )
{
flags |= fc::shadow;
setShadowSize(1,1);
}
else
{
flags &= ~fc::shadow;
setShadowSize(0,0);
}
return on;
}

View File

@ -72,9 +72,15 @@ bool FProgressbar::setShadow (bool on)
if ( on
&& (Encoding != fc::VT100 || isTeraTerm() )
&& Encoding != fc::ASCII )
{
flags |= fc::shadow;
setShadowSize(1,1);
}
else
{
flags &= ~fc::shadow;
setShadowSize(0,0);
}
return on;
}

View File

@ -12,8 +12,8 @@
//----------------------------------------------------------------------
FScrollView::FScrollView (FWidget* parent)
: FWidget(parent)
, scroll_size(1,1,1,1)
, scroll_offset()
, scroll_geometry(1,1,1,1)
, viewport_geometry()
, viewport(0)
, vbar(0)
, hbar(0)
@ -48,8 +48,8 @@ void FScrollView::setScrollWidth (int width)
if ( viewport )
{
FPoint no_shadow(0,0);
scroll_size.setWidth (width);
resizeArea (scroll_size, no_shadow, viewport);
scroll_geometry.setWidth (width);
resizeArea (scroll_geometry, no_shadow, viewport);
setPreprocessingHandler
(
_PREPROC_HANDLER (this, &FScrollView::copy2area)
@ -75,8 +75,8 @@ void FScrollView::setScrollHeight (int height)
if ( viewport )
{
FPoint no_shadow(0,0);
scroll_size.setHeight (height);
resizeArea (scroll_size, no_shadow, viewport);
scroll_geometry.setHeight (height);
resizeArea (scroll_geometry, no_shadow, viewport);
setPreprocessingHandler
(
_PREPROC_HANDLER (this, &FScrollView::copy2area)
@ -105,8 +105,8 @@ void FScrollView::setScrollSize (int width, int height)
if ( viewport )
{
FPoint no_shadow(0,0);
scroll_size.setSize (width, height);
resizeArea (scroll_size, no_shadow, viewport);
scroll_geometry.setSize (width, height);
resizeArea (scroll_geometry, no_shadow, viewport);
setPreprocessingHandler
(
_PREPROC_HANDLER (this, &FScrollView::copy2area)
@ -137,12 +137,12 @@ void FScrollView::setX (int x, bool adjust)
if ( ! adjust )
{
scroll_size.setX (getTermX() + getLeftPadding() - 1);
scroll_geometry.setX (getTermX() + getLeftPadding() - 1);
if ( viewport )
{
viewport->offset_top = scroll_size.getX();
viewport->offset_left = scroll_size.getY();
viewport->offset_top = scroll_geometry.getX();
viewport->offset_left = scroll_geometry.getY();
}
}
}
@ -154,12 +154,12 @@ void FScrollView::setY (int y, bool adjust)
if ( ! adjust )
{
scroll_size.setY (getTermY() + getTopPadding() - 1);
scroll_geometry.setY (getTermY() + getTopPadding() - 1);
if ( viewport )
{
viewport->offset_top = scroll_size.getX();
viewport->offset_left = scroll_size.getY();
viewport->offset_top = scroll_geometry.getX();
viewport->offset_left = scroll_geometry.getY();
}
}
}
@ -168,15 +168,15 @@ void FScrollView::setY (int y, bool adjust)
void FScrollView::setPos (int x, int y, bool adjust)
{
FWidget::setPos (x, y, adjust);
scroll_size.setPos ( getTermX() + getLeftPadding() - 1
scroll_geometry.setPos ( getTermX() + getLeftPadding() - 1
, getTermY() + getTopPadding() - 1 );
if ( ! adjust )
{
if ( viewport )
{
viewport->offset_top = scroll_size.getX();
viewport->offset_left = scroll_size.getY();
viewport->offset_top = scroll_geometry.getX();
viewport->offset_left = scroll_geometry.getY();
}
}
}
@ -185,6 +185,7 @@ void FScrollView::setPos (int x, int y, bool adjust)
void FScrollView::setWidth (int w, bool adjust)
{
FWidget::setWidth (w, adjust);
viewport_geometry.setWidth(w);
calculateScrollbarPos();
if ( getScrollWidth() < getViewportWidth() )
@ -195,6 +196,7 @@ void FScrollView::setWidth (int w, bool adjust)
void FScrollView::setHeight (int h, bool adjust)
{
FWidget::setHeight (h, adjust);
viewport_geometry.setHeight(h);
calculateScrollbarPos();
if ( getScrollHeight() < getViewportHeight() )
@ -205,6 +207,7 @@ void FScrollView::setHeight (int h, bool adjust)
void FScrollView::setSize (int w, int h, bool adjust)
{
FWidget::setSize (w, h, adjust);
viewport_geometry.setSize(w, h);
calculateScrollbarPos();
if ( getScrollWidth() < getViewportWidth()
@ -216,8 +219,9 @@ void FScrollView::setSize (int w, int h, bool adjust)
void FScrollView::setGeometry (int x, int y, int w, int h, bool adjust)
{
FWidget::setGeometry (x, y, w, h, adjust);
scroll_size.setPos ( getTermX() + getLeftPadding() - 1
, getTermY() + getTopPadding() - 1 );
scroll_geometry.setPos ( getTermX() + getLeftPadding() - 1
, getTermY() + getTopPadding() - 1 );
viewport_geometry.setSize(w, h);
calculateScrollbarPos();
if ( getScrollWidth() < getViewportWidth()
@ -227,8 +231,8 @@ void FScrollView::setGeometry (int x, int y, int w, int h, bool adjust)
}
else if ( ! adjust && viewport )
{
viewport->offset_top = scroll_size.getX();
viewport->offset_left = scroll_size.getY();
viewport->offset_top = scroll_geometry.getX();
viewport->offset_left = scroll_geometry.getY();
}
}
@ -262,20 +266,20 @@ void FScrollView::clearArea (int fillchar)
//----------------------------------------------------------------------
void FScrollView::scrollToX (int x)
{
scrollTo (x, scroll_offset.getY() + 1);
scrollTo (x, viewport_geometry.getY() + 1);
}
//----------------------------------------------------------------------
void FScrollView::scrollToY (int y)
{
scrollTo (scroll_offset.getX() + 1, y);
scrollTo (viewport_geometry.getX() + 1, y);
}
//----------------------------------------------------------------------
void FScrollView::scrollTo (int x, int y)
{
short& xoffset = scroll_offset.x_ref();
short& yoffset = scroll_offset.y_ref();
short& xoffset = viewport_geometry.x1_ref();
short& yoffset = viewport_geometry.y1_ref();
short xoffset_end = short(getScrollWidth() - getViewportWidth());
short yoffset_end = short(getScrollHeight() - getViewportHeight());
x--;
@ -344,8 +348,8 @@ void FScrollView::onKeyPress (FKeyEvent* ev)
{
int key = ev->key();
bool hasChanges = false;
short& xoffset = scroll_offset.x_ref();
short& yoffset = scroll_offset.y_ref();
short& xoffset = viewport_geometry.x1_ref();
short& yoffset = viewport_geometry.y1_ref();
short xoffset_before = xoffset;
short yoffset_before = yoffset;
short xoffset_end = short(getScrollWidth() - getViewportWidth());
@ -440,7 +444,7 @@ void FScrollView::onKeyPress (FKeyEvent* ev)
void FScrollView::onWheel (FWheelEvent* ev)
{
bool hasChanges = false;
short& yoffset = scroll_offset.y_ref();
short& yoffset = viewport_geometry.y1_ref();
short yoffset_before = yoffset;
int wheel = ev->getWheel();
@ -493,6 +497,41 @@ void FScrollView::onWheel (FWheelEvent* ev)
updateTerminal();
}
//----------------------------------------------------------------------
void FScrollView::onChildFocusChanged (FFocusEvent*)
{
// Scrolls the viewport so that the focused widget is visible
FRect widget_geometry;
FWidget* focus_widget = FWidget::getFocusWidget();
if ( ! focus_widget )
return;
widget_geometry = focus_widget->getGeometryWithShadow();
if ( ! viewport_geometry.contains(widget_geometry) )
{
int x, y;
int vx = viewport_geometry.getX();
int vy = viewport_geometry.getY();
int wx = widget_geometry.getX();
int wy = widget_geometry.getY();
if ( wx > vx )
x = widget_geometry.getX2() - viewport_geometry.getWidth() + 3;
else if ( wx < vx )
x = wx;
if ( wy > vy )
y = widget_geometry.getY2() - viewport_geometry.getHeight() + 3;
else if ( wy < vy )
y = wy;
scrollTo (x, y);
}
}
// protected methods of FScrollView
//----------------------------------------------------------------------
@ -517,16 +556,16 @@ void FScrollView::adjustSize()
FWidget::adjustSize();
int width = getWidth();
int height = getHeight();
int xoffset = scroll_offset.getX();
int yoffset = scroll_offset.getY();
int xoffset = viewport_geometry.getX();
int yoffset = viewport_geometry.getY();
scroll_size.setPos ( getTermX() + getLeftPadding() - 1
, getTermY() + getTopPadding() - 1 );
scroll_geometry.setPos ( getTermX() + getLeftPadding() - 1
, getTermY() + getTopPadding() - 1 );
if ( viewport )
{
viewport->offset_top = scroll_size.getX();
viewport->offset_left = scroll_size.getY();
viewport->offset_top = scroll_geometry.getX();
viewport->offset_left = scroll_geometry.getY();
}
hbar->setMaximum (getScrollWidth() - getViewportWidth());
@ -566,8 +605,8 @@ void FScrollView::copy2area()
ax = getTermX() - print_area->offset_top;
ay = getTermY() - print_area->offset_left;
dx = scroll_offset.getX();
dy = scroll_offset.getY();
dx = viewport_geometry.getX();
dy = viewport_geometry.getY();
y_end = getViewportHeight();
x_end = getViewportWidth();
@ -636,8 +675,8 @@ void FScrollView::init()
if ( h < 1 )
h = 1;
scroll_size.setRect (0, 0, w, h);
createArea (scroll_size, no_shadow, viewport);
scroll_geometry.setRect (0, 0, w, h);
createArea (scroll_geometry, no_shadow, viewport);
setPreprocessingHandler
(
_PREPROC_HANDLER (this, &FScrollView::copy2area)
@ -718,7 +757,7 @@ void FScrollView::cb_VBarChange (FWidget*, void*)
FScrollbar::sType scrollType;
bool hasChanges = false;
short distance = 1;
short& yoffset = scroll_offset.y_ref();
short& yoffset = viewport_geometry.y1_ref();
short yoffset_before = yoffset;
short yoffset_end = short(getScrollHeight() - getViewportHeight());
scrollType = vbar->getScrollType();
@ -821,7 +860,7 @@ void FScrollView::cb_HBarChange (FWidget*, void*)
FScrollbar::sType scrollType;
bool hasChanges = false;
short distance = 1;
short& xoffset = scroll_offset.x_ref();
short& xoffset = viewport_geometry.x1_ref();
short xoffset_before = xoffset;
short xoffset_end = short(getScrollWidth() - getViewportWidth());
scrollType = hbar->getScrollType();

View File

@ -91,6 +91,7 @@ class FScrollView : public FWidget
// Event handlers
void onKeyPress (FKeyEvent*);
void onWheel (FWheelEvent*);
void onChildFocusChanged (FFocusEvent*);
protected:
// Using-declaration
@ -129,8 +130,8 @@ class FScrollView : public FWidget
void cb_HBarChange (FWidget*, void*);
// Data Members
FRect scroll_size;
FPoint scroll_offset;
FRect scroll_geometry;
FRect viewport_geometry;
term_area* viewport; // virtual scroll content
FScrollbar* vbar;
FScrollbar* hbar;
@ -157,23 +158,23 @@ inline int FScrollView::getViewportHeight() const
//----------------------------------------------------------------------
inline int FScrollView::getScrollWidth() const
{ return scroll_size.getWidth(); }
{ return scroll_geometry.getWidth(); }
//----------------------------------------------------------------------
inline int FScrollView::getScrollHeight() const
{ return scroll_size.getHeight(); }
{ return scroll_geometry.getHeight(); }
//----------------------------------------------------------------------
inline const FPoint FScrollView::getScrollPos() const
{ return scroll_offset; }
{ return viewport_geometry.getPos(); }
//----------------------------------------------------------------------
inline int FScrollView::getScrollX() const
{ return scroll_offset.getX(); }
{ return viewport_geometry.getX(); }
//----------------------------------------------------------------------
inline int FScrollView::getScrollY() const
{ return scroll_offset.getY(); }
{ return viewport_geometry.getY(); }
//----------------------------------------------------------------------
inline void FScrollView::scrollTo (FPoint pos)

View File

@ -52,7 +52,7 @@
#include <map>
#include <queue>
#include "fenum.h"
#include "fc.h"
#include "fobject.h"
#include "foptiattr.h"
#include "foptimove.h"

View File

@ -264,6 +264,7 @@ void FWidget::setStatusbarMessage (FString msg)
bool FWidget::setFocus (bool on)
{
FWindow* window;
FWidget* last_focus;
if ( ! enable )
return false;
@ -271,13 +272,15 @@ bool FWidget::setFocus (bool on)
if ( on == focus )
return true;
last_focus = FWidget::getFocusWidget();
// set widget focus
if ( on && ! focus )
{
int focusable_children = numOfFocusableChildren();
if ( FWidget::getFocusWidget() )
FWidget::getFocusWidget()->unsetFocus();
if ( last_focus )
last_focus->unsetFocus();
if ( (!isDialogWidget() && focusable_children == 0)
|| (isDialogWidget() && focusable_children == 1) )
@ -302,6 +305,12 @@ bool FWidget::setFocus (bool on)
window->setWindowFocusWidget(this);
}
if ( hasParent() && last_focus != FWidget::getFocusWidget() )
{
FFocusEvent cfc (fc::ChildFocusChanged_Event);
FApplication::sendEvent(getParentWidget(), &cfc);
}
return focus = (on) ? true : false;
}
@ -1995,6 +2004,10 @@ bool FWidget::event (FEvent* ev)
onFocusOut ( static_cast<FFocusEvent*>(ev) );
break;
case fc::ChildFocusChanged_Event:
onChildFocusChanged ( static_cast<FFocusEvent*>(ev) );
break;
case fc::Accelerator_Event:
onAccel ( static_cast<FAccelEvent*>(ev) );
break;
@ -2065,6 +2078,10 @@ void FWidget::onFocusIn (FFocusEvent*)
void FWidget::onFocusOut (FFocusEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onChildFocusChanged (FFocusEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onAccel (FAccelEvent*)
{ }

View File

@ -313,6 +313,7 @@ class FWidget : public FVTerm
virtual void onMouseMove (FMouseEvent*);
virtual void onFocusIn (FFocusEvent*);
virtual void onFocusOut (FFocusEvent*);
virtual void onChildFocusChanged (FFocusEvent*);
virtual void onAccel (FAccelEvent*);
virtual void onResize (FResizeEvent*);
virtual void onShow (FShowEvent*);

View File

@ -60,7 +60,6 @@ scrollview::scrollview (FWidget* parent)
go_north = new FButton(wchar_t(fc::BlackUpPointingTriangle) , this);
go_north->setGeometry (1, getScrollHeight() - 2, 5, 1);
if ( isCygwinTerminal() )
{
go_south->setText ('v');