From 59189160fd446266ec6f8f51e096036347833a91 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Thu, 26 Jan 2017 00:31:07 +0100 Subject: [PATCH] FScrollView now scrolls automatically to the focused widget --- ChangeLog | 3 ++ src/Makefile.am | 2 +- src/Makefile.in | 2 +- src/fbutton.cpp | 6 +++ src/{fenum.h => fc.h} | 51 +++++++++--------- src/fevent.h | 2 +- src/flineedit.cpp | 6 +++ src/fprogressbar.cpp | 6 +++ src/fscrollview.cpp | 119 ++++++++++++++++++++++++++++-------------- src/fscrollview.h | 15 +++--- src/fterm.h | 2 +- src/fwidget.cpp | 21 +++++++- src/fwidget.h | 1 + test/scrollview.cpp | 1 - 14 files changed, 158 insertions(+), 79 deletions(-) rename src/{fenum.h => fc.h} (97%) diff --git a/ChangeLog b/ChangeLog index dacfb81a..a7351b6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2017-01-26 Markus Gans + * FScrollView now scrolls automatically to the focused widget + 2017-01-22 Markus Gans * A FScrollView object can now have client widgets on the scrolling area diff --git a/src/Makefile.am b/src/Makefile.am index c06f61e4..78851f79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,7 +60,7 @@ finalcutinclude_HEADERS = \ fconfig.h \ fswitch.h \ fdialog.h \ - fenum.h \ + fc.h \ fevent.h \ ffiledialog.h \ final.h \ diff --git a/src/Makefile.in b/src/Makefile.in index fcce5d12..622114ce 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -423,7 +423,7 @@ finalcutinclude_HEADERS = \ fconfig.h \ fswitch.h \ fdialog.h \ - fenum.h \ + fc.h \ fevent.h \ ffiledialog.h \ final.h \ diff --git a/src/fbutton.cpp b/src/fbutton.cpp index 355d47ce..47ceb560 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -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; } diff --git a/src/fenum.h b/src/fc.h similarity index 97% rename from src/fenum.h rename to src/fc.h index 114a155c..fc010df8 100644 --- a/src/fenum.h +++ b/src/fc.h @@ -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 diff --git a/src/fevent.h b/src/fevent.h index e5f49eda..7ab084fb 100644 --- a/src/fevent.h +++ b/src/fevent.h @@ -53,7 +53,7 @@ #ifndef _FEVENT_H #define _FEVENT_H -#include "fenum.h" +#include "fc.h" #include "fpoint.h" diff --git a/src/flineedit.cpp b/src/flineedit.cpp index 250bb81d..13ba6243 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -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; } diff --git a/src/fprogressbar.cpp b/src/fprogressbar.cpp index 2c09ca9e..3b73877b 100644 --- a/src/fprogressbar.cpp +++ b/src/fprogressbar.cpp @@ -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; } diff --git a/src/fscrollview.cpp b/src/fscrollview.cpp index b6540d2d..2a893730 100644 --- a/src/fscrollview.cpp +++ b/src/fscrollview.cpp @@ -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(); diff --git a/src/fscrollview.h b/src/fscrollview.h index 166af108..35f4fab5 100644 --- a/src/fscrollview.h +++ b/src/fscrollview.h @@ -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) diff --git a/src/fterm.h b/src/fterm.h index d915c6cd..af4811b1 100644 --- a/src/fterm.h +++ b/src/fterm.h @@ -52,7 +52,7 @@ #include #include -#include "fenum.h" +#include "fc.h" #include "fobject.h" #include "foptiattr.h" #include "foptimove.h" diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 76e97acf..222696ed 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -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(ev) ); break; + case fc::ChildFocusChanged_Event: + onChildFocusChanged ( static_cast(ev) ); + break; + case fc::Accelerator_Event: onAccel ( static_cast(ev) ); break; @@ -2065,6 +2078,10 @@ void FWidget::onFocusIn (FFocusEvent*) void FWidget::onFocusOut (FFocusEvent*) { } +//---------------------------------------------------------------------- +void FWidget::onChildFocusChanged (FFocusEvent*) +{ } + //---------------------------------------------------------------------- void FWidget::onAccel (FAccelEvent*) { } diff --git a/src/fwidget.h b/src/fwidget.h index 42c96e0a..69a516b1 100644 --- a/src/fwidget.h +++ b/src/fwidget.h @@ -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*); diff --git a/test/scrollview.cpp b/test/scrollview.cpp index e850855b..87c2d5a6 100644 --- a/test/scrollview.cpp +++ b/test/scrollview.cpp @@ -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');