diff --git a/ChangeLog b/ChangeLog index a7351b6d..0c1ce36a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2017-01-28 Markus Gans + * Allow to change the focus out from FScrollView to another widget + 2017-01-26 Markus Gans * FScrollView now scrolls automatically to the focused widget diff --git a/src/fbuttongroup.cpp b/src/fbuttongroup.cpp index a344d7ed..99107ff4 100644 --- a/src/fbuttongroup.cpp +++ b/src/fbuttongroup.cpp @@ -36,7 +36,7 @@ FButtonGroup::FButtonGroup (const FString& txt, FWidget* parent) //---------------------------------------------------------------------- FButtonGroup::~FButtonGroup() // destructor { - FButtonList::iterator iter; + FObjectList::iterator iter; if ( buttonlist.empty() ) return; @@ -45,7 +45,8 @@ FButtonGroup::~FButtonGroup() // destructor while ( iter != buttonlist.end() ) { - (*iter)->setGroup(0); + FToggleButton* toggle_button = static_cast(*iter); + toggle_button->setGroup(0); iter = buttonlist.erase(iter); } } @@ -55,44 +56,17 @@ FButtonGroup::~FButtonGroup() // destructor //---------------------------------------------------------------------- FToggleButton* FButtonGroup::getFirstButton() { - if ( buttonlist.empty() ) - return 0; - - FButtonList::const_iterator iter, end; - iter = buttonlist.begin(); - end = buttonlist.end(); - - while ( iter != end ) - { - if ( (*iter)->isEnabled() && (*iter)->acceptFocus() ) - return (*iter); - - ++iter; - } - - return 0; + FWidget* widget = FWidget::getFirstFocusableWidget(buttonlist); + FToggleButton* toggle_button = static_cast(widget); + return toggle_button; } //---------------------------------------------------------------------- FToggleButton* FButtonGroup::getLastButton() { - if ( buttonlist.empty() ) - return 0; - - FButtonList::const_iterator iter, begin; - begin = buttonlist.begin(); - iter = buttonlist.end(); - - do - { - --iter; - - if ( (*iter)->isEnabled() && (*iter)->acceptFocus() ) - return (*iter); - } - while ( iter != begin ); - - return 0; + FWidget* widget = FWidget::getLastFocusableWidget(buttonlist); + FToggleButton* toggle_button = static_cast(widget); + return toggle_button; } //---------------------------------------------------------------------- @@ -143,13 +117,15 @@ bool FButtonGroup::hasFocusedButton() if ( buttonlist.empty() ) return false; - FButtonList::const_iterator iter, end; + FObjectList::const_iterator iter, end; iter = buttonlist.begin(); end = buttonlist.end(); while ( iter != end ) { - if ( (*iter)->hasFocus() ) + FToggleButton* toggle_button = static_cast(*iter); + + if ( toggle_button->hasFocus() ) return true; ++iter; @@ -164,13 +140,15 @@ bool FButtonGroup::hasCheckedButton() if ( buttonlist.empty() ) return false; - FButtonList::const_iterator iter, end; + FObjectList::const_iterator iter, end; iter = buttonlist.begin(); end = buttonlist.end(); while ( iter != end ) { - if ( (*iter)->isChecked() ) + FToggleButton* toggle_button = static_cast(*iter); + + if ( toggle_button->isChecked() ) return true; ++iter; @@ -190,13 +168,14 @@ void FButtonGroup::hide() if ( ! buttonlist.empty() ) { - FButtonList::const_iterator iter, end; + FObjectList::const_iterator iter, end; iter = buttonlist.begin(); end = buttonlist.end(); while ( iter != end ) { - (*iter)->hide(); + FToggleButton* toggle_button = static_cast(*iter); + toggle_button->hide(); ++iter; } } @@ -241,8 +220,13 @@ void FButtonGroup::insert (FToggleButton* button) button->getGroup()->remove(button); // setChecked the first FRadioButton - if ( buttonlist.size() == 1 && isRadioButton(*buttonlist.begin()) ) - (*buttonlist.begin())->setChecked(); + if ( buttonlist.size() == 1 ) + { + FToggleButton* first_button = static_cast(*buttonlist.begin()); + + if ( isRadioButton(first_button) ) + first_button->setChecked(); + } button->setGroup(this); buttonlist.push_back(button); @@ -257,7 +241,7 @@ void FButtonGroup::insert (FToggleButton* button) //---------------------------------------------------------------------- void FButtonGroup::remove (FToggleButton* button) { - FButtonList::iterator iter; + FObjectList::iterator iter; if ( ! button || buttonlist.empty() ) return; @@ -266,7 +250,9 @@ void FButtonGroup::remove (FToggleButton* button) while ( iter != buttonlist.end() ) { - if ( (*iter) == button ) + FToggleButton* toggle_button = static_cast(*iter); + + if ( toggle_button == button ) { iter = buttonlist.erase(iter); button->setGroup(0); @@ -298,24 +284,26 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev) { if ( hasCheckedButton() && ! buttonlist.empty() ) { - FButtonList::const_iterator iter, end; + FObjectList::const_iterator iter, end; iter = buttonlist.begin(); end = buttonlist.end(); while ( iter != end ) { - if ( (*iter)->isChecked() ) + FToggleButton* toggle_button = static_cast(*iter); + + if ( toggle_button->isChecked() ) { - if ( isRadioButton(*iter) ) + if ( isRadioButton(toggle_button) ) { in_ev->ignore(); FWidget* prev_element = getFocusWidget(); - (*iter)->setFocus(); + toggle_button->setFocus(); if ( prev_element ) prev_element->redraw(); - (*iter)->redraw(); + toggle_button->redraw(); } break; @@ -327,30 +315,19 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev) if ( in_ev->isAccepted() ) { + in_ev->ignore(); + FWidget* prev_element = getFocusWidget(); + if ( in_ev->getFocusType() == fc::FocusNextWidget ) - { - in_ev->ignore(); - FWidget* prev_element = getFocusWidget(); focusFirstChild(); - - if ( prev_element ) - prev_element->redraw(); - - if ( getFocusWidget() ) - getFocusWidget()->redraw(); - } else if ( in_ev->getFocusType() == fc::FocusPreviousWidget ) - { - in_ev->ignore(); - FWidget* prev_element = getFocusWidget(); focusLastChild(); - if ( prev_element ) - prev_element->redraw(); + if ( prev_element ) + prev_element->redraw(); - if ( getFocusWidget() ) - getFocusWidget()->redraw(); - } + if ( getFocusWidget() ) + getFocusWidget()->redraw(); } if ( getStatusBar() ) @@ -361,15 +338,11 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev) } } -//---------------------------------------------------------------------- -void FButtonGroup::onFocusOut (FFocusEvent*) -{ } - //---------------------------------------------------------------------- void FButtonGroup::cb_buttonToggled (FWidget* widget, void*) { FToggleButton* button = static_cast(widget); - FButtonList::const_iterator iter, end; + FObjectList::const_iterator iter, end; if ( ! button->isChecked() ) return; @@ -382,14 +355,16 @@ void FButtonGroup::cb_buttonToggled (FWidget* widget, void*) while ( iter != end ) { - if ( (*iter) != button - && (*iter)->isChecked() - && isRadioButton(*iter) ) - { - (*iter)->unsetChecked(); + FToggleButton* toggle_button = static_cast(*iter); - if ( (*iter)->isVisible() && (*iter)->isShown() ) - (*iter)->redraw(); + if ( toggle_button != button + && toggle_button->isChecked() + && isRadioButton(toggle_button) ) + { + toggle_button->unsetChecked(); + + if ( toggle_button->isVisible() && toggle_button->isShown() ) + toggle_button->redraw(); } ++iter; @@ -571,21 +546,23 @@ void FButtonGroup::directFocus() if ( hasCheckedButton() && ! buttonlist.empty() ) { - FButtonList::const_iterator iter, end; + FObjectList::const_iterator iter, end; iter = buttonlist.begin(); end = buttonlist.end(); while ( iter != end ) { - if ( (*iter)->isChecked() ) + FToggleButton* toggle_button = static_cast(*iter); + + if ( toggle_button->isChecked() ) { - if ( isRadioButton(*iter) ) + if ( isRadioButton(toggle_button) ) { found_checked = true; FWidget* focused_widget = getFocusWidget(); FFocusEvent out (fc::FocusOut_Event); FApplication::queueEvent(focused_widget, &out); - (*iter)->setFocus(); + toggle_button->setFocus(); if ( focused_widget ) focused_widget->redraw(); diff --git a/src/fbuttongroup.h b/src/fbuttongroup.h index 14d9d89a..61501cab 100644 --- a/src/fbuttongroup.h +++ b/src/fbuttongroup.h @@ -80,7 +80,6 @@ class FButtonGroup : public FWidget void onMouseDown (FMouseEvent*); void onAccel (FAccelEvent*); void onFocusIn (FFocusEvent*); - void onFocusOut (FFocusEvent*); // Callback method void cb_buttonToggled (FWidget*, void*); @@ -97,9 +96,6 @@ class FButtonGroup : public FWidget void drawLabel(); private: - // Typedef - typedef std::vector FButtonList; - // Disable copy constructor FButtonGroup (const FButtonGroup&); @@ -116,7 +112,7 @@ class FButtonGroup : public FWidget // Data Members FString text; bool border; - FButtonList buttonlist; + FObjectList buttonlist; }; #pragma pack(pop) diff --git a/src/fc.h b/src/fc.h index fc010df8..ff4b4d60 100644 --- a/src/fc.h +++ b/src/fc.h @@ -36,7 +36,8 @@ class fc MouseMove_Event, // mouse move FocusIn_Event, // focus in FocusOut_Event, // focus out - ChildFocusChanged_Event, // child focus changed + ChildFocusIn_Event, // child focus in + ChildFocusOut_Event, // child focus out WindowActive_Event, // activate window WindowInactive_Event, // deactivate window WindowRaised_Event, // raise window diff --git a/src/fobject.cpp b/src/fobject.cpp index 975e727a..5d21e64a 100644 --- a/src/fobject.cpp +++ b/src/fobject.cpp @@ -49,11 +49,11 @@ FObject::~FObject() // destructor } // delete children objects - FObject::object_list children = this->getChildren(); + FObjectList children = this->getChildren(); if ( ! children.empty() ) { - FObject::object_list::const_iterator iter; + FObjectList::const_iterator iter; iter = children.begin(); while ( iter != children.end() ) diff --git a/src/fobject.h b/src/fobject.h index 64444e8e..58b60444 100644 --- a/src/fobject.h +++ b/src/fobject.h @@ -57,7 +57,7 @@ class FObject }; // Typedef - typedef std::list object_list; + typedef std::list FObjectList; // Constructor explicit FObject (FObject* = 0); @@ -68,7 +68,7 @@ class FObject // Accessors virtual const char* getClassName() const; FObject* getParent() const; - object_list getChildren() const; + FObjectList getChildren() const; int numOfChildren() const; // Inquiries @@ -108,7 +108,7 @@ class FObject // Data Members FObject* parent_obj; - object_list children_list; + FObjectList children_list; bool has_parent; static bool timer_modify_lock; }; @@ -124,7 +124,7 @@ inline FObject* FObject::getParent() const { return parent_obj; } //---------------------------------------------------------------------- -inline FObject::object_list FObject::getChildren() const +inline FObject::FObjectList FObject::getChildren() const { return children_list; } //---------------------------------------------------------------------- diff --git a/src/fscrollview.cpp b/src/fscrollview.cpp index 5c195bb4..7d66f244 100644 --- a/src/fscrollview.cpp +++ b/src/fscrollview.cpp @@ -498,7 +498,32 @@ void FScrollView::onWheel (FWheelEvent* ev) } //---------------------------------------------------------------------- -void FScrollView::onChildFocusChanged (FFocusEvent*) +void FScrollView::onFocusIn (FFocusEvent* in_ev) +{ + // Sets the focus to a child widget if it exists + + if ( hasChildren() ) + { + FWidget* prev_element = getFocusWidget(); + + if ( in_ev->getFocusType() == fc::FocusNextWidget ) + focusFirstChild(); + else if ( in_ev->getFocusType() == fc::FocusPreviousWidget ) + focusLastChild(); + + if ( prev_element ) + prev_element->redraw(); + + if ( getFocusWidget() ) + getFocusWidget()->redraw(); + + FFocusEvent cfi (fc::ChildFocusIn_Event); + onChildFocusIn(&cfi); + } +} + +//---------------------------------------------------------------------- +void FScrollView::onChildFocusIn (FFocusEvent*) { // Scrolls the viewport so that the focused widget is visible @@ -532,6 +557,35 @@ void FScrollView::onChildFocusChanged (FFocusEvent*) } } +//---------------------------------------------------------------------- +void FScrollView::onChildFocusOut (FFocusEvent* out_ev) +{ + // Change the focus away from FScrollView to another widget + + FWidget* focus_widget = FWidget::getFocusWidget(); + + if ( out_ev->getFocusType() == fc::FocusNextWidget ) + { + FWidget* last_widget = getLastFocusableWidget(getChildren()); + + if ( focus_widget == last_widget ) + { + out_ev->accept(); + focusNextChild(); + } + } + else if ( out_ev->getFocusType() == fc::FocusPreviousWidget ) + { + FWidget* first_widget = getFirstFocusableWidget(getChildren()); + + if ( focus_widget == first_widget ) + { + out_ev->accept(); + focusPrevChild(); + } + } +} + // protected methods of FScrollView //---------------------------------------------------------------------- diff --git a/src/fscrollview.h b/src/fscrollview.h index 35f4fab5..131b3a59 100644 --- a/src/fscrollview.h +++ b/src/fscrollview.h @@ -91,7 +91,9 @@ class FScrollView : public FWidget // Event handlers void onKeyPress (FKeyEvent*); void onWheel (FWheelEvent*); - void onChildFocusChanged (FFocusEvent*); + void onFocusIn (FFocusEvent*); + void onChildFocusIn (FFocusEvent*); + void onChildFocusOut (FFocusEvent*); protected: // Using-declaration diff --git a/src/fvterm.cpp b/src/fvterm.cpp index f376b594..e7b36be1 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -797,6 +797,7 @@ void FVTerm::resizeArea ( int offset_top, int offset_left default_char.trans_shadow = 0; default_char.inherit_bg = 0; default_char.no_changes = 0; + default_char.printed = 0; std::fill_n (area->text, area_size, default_char); diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 222696ed..60b077ef 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -148,6 +148,52 @@ FWidget* FWidget::getFocusWidget() const return focus_widget; } +//---------------------------------------------------------------------- +FWidget* FWidget::getFirstFocusableWidget (FObjectList children) +{ + if ( children.empty() ) + return 0; + + FObjectList::const_iterator iter, end; + iter = children.begin(); + end = children.end(); + + while ( iter != end ) + { + FWidget* child = static_cast(*iter); + + if ( child->isEnabled() && child->acceptFocus() ) + return child; + + ++iter; + } + + return 0; +} + +//---------------------------------------------------------------------- +FWidget* FWidget::getLastFocusableWidget (FObjectList children) +{ + if ( children.empty() ) + return 0; + + FObjectList::const_iterator iter, begin; + begin = children.begin(); + iter = children.end(); + + do + { + --iter; + FWidget* child = static_cast(*iter); + + if ( child->isEnabled() && child->acceptFocus() ) + return child; + } + while ( iter != begin ); + + return 0; +} + //---------------------------------------------------------------------- FWidget* FWidget::getClickedWidget() { @@ -305,12 +351,6 @@ 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; } @@ -746,8 +786,8 @@ FWidget* FWidget::childWidgetAt (FWidget* p, int x, int y) { if ( p && p->hasChildren() ) { - FObject::object_list children; - FObject::object_list::const_iterator iter, end; + FObjectList children; + FObjectList::const_iterator iter, end; children = p->getChildren(); iter = children.begin(); @@ -776,8 +816,8 @@ FWidget* FWidget::childWidgetAt (FWidget* p, int x, int y) //---------------------------------------------------------------------- int FWidget::numOfFocusableChildren() { - FObject::object_list children; - FObject::object_list::const_iterator iter, end; + FObjectList children; + FObjectList::const_iterator iter, end; if ( ! this->hasChildren() ) return 0; @@ -1044,8 +1084,8 @@ void FWidget::redraw() // draw child elements if ( this->hasChildren() ) { - FObject::object_list children; - FObject::object_list::const_iterator iter, end; + FObjectList children; + FObjectList::const_iterator iter, end; children = this->getChildren(); iter = children.begin(); @@ -1133,8 +1173,8 @@ void FWidget::show() if ( this->hasChildren() ) { - FObject::object_list children; - FObject::object_list::const_iterator iter, end; + FObjectList children; + FObjectList::const_iterator iter, end; children = this->getChildren(); iter = children.begin(); @@ -1186,8 +1226,8 @@ void FWidget::hide() //---------------------------------------------------------------------- bool FWidget::focusFirstChild() { - FObject::object_list children; - FObject::object_list::const_iterator iter, end; + FObjectList children; + FObjectList::const_iterator iter, end; if ( ! this->hasChildren() ) return false; @@ -1228,8 +1268,8 @@ bool FWidget::focusFirstChild() //---------------------------------------------------------------------- bool FWidget::focusLastChild() { - FObject::object_list children; - FObject::object_list::const_iterator iter, begin; + FObjectList children; + FObjectList::const_iterator iter, begin; if ( ! this->hasChildren() ) return false; @@ -1720,8 +1760,8 @@ void FWidget::adjustSize() if ( this->hasChildren() ) { - FObject::object_list children; - FObject::object_list::const_iterator iter, end; + FObjectList children; + FObjectList::const_iterator iter, end; children = this->getChildren(); iter = children.begin(); @@ -1770,12 +1810,12 @@ bool FWidget::focusNextChild() if ( hasParent() ) { - FWidget* parent = static_cast(getParent()); + FWidget* parent = getParentWidget(); if ( parent->hasChildren() && parent->numOfFocusableChildren() > 1 ) { - FObject::object_list children; - FObject::object_list::iterator iter, end; + FObjectList children; + FObjectList::iterator iter, end; children = parent->getChildren(); iter = children.begin(); @@ -1788,7 +1828,7 @@ bool FWidget::focusNextChild() if ( w == this ) { FWidget* next; - FObject::object_list::const_iterator next_element; + FObjectList::const_iterator next_element; next_element = iter; do @@ -1808,20 +1848,31 @@ bool FWidget::focusNextChild() out.setFocusType(fc::FocusNextWidget); FApplication::sendEvent(this, &out); + FFocusEvent cfo (fc::ChildFocusOut_Event); + cfo.setFocusType(fc::FocusNextWidget); + cfo.ignore(); + FApplication::sendEvent(parent, &cfo); + + if ( cfo.isAccepted() ) + out.ignore(); + if ( out.isAccepted() ) { if ( next == this ) return false; next->setFocus(); + FFocusEvent cfi (fc::ChildFocusIn_Event); + FApplication::sendEvent(parent, &cfi); + FFocusEvent in (fc::FocusIn_Event); in.setFocusType(fc::FocusNextWidget); FApplication::sendEvent(next, &in); if ( in.isAccepted() ) { - this->draw(); - next->draw(); + this->redraw(); + next->redraw(); updateTerminal(); flush_out(); } @@ -1843,12 +1894,12 @@ bool FWidget::focusPrevChild() if ( hasParent() ) { - FWidget* parent = static_cast(getParent()); + FWidget* parent = getParentWidget(); if ( parent->hasChildren() && parent->numOfFocusableChildren() > 1 ) { - FObject::object_list children; - FObject::object_list::iterator iter, begin; + FObjectList children; + FObjectList::iterator iter, begin; children = parent->getChildren(); iter = children.end(); @@ -1862,7 +1913,7 @@ bool FWidget::focusPrevChild() if ( w == this ) { FWidget* prev; - FObject::object_list::const_iterator prev_element; + FObjectList::const_iterator prev_element; prev_element = iter; do @@ -1881,20 +1932,31 @@ bool FWidget::focusPrevChild() out.setFocusType(fc::FocusPreviousWidget); FApplication::sendEvent(this, &out); + FFocusEvent cfo (fc::ChildFocusOut_Event); + cfo.setFocusType(fc::FocusPreviousWidget); + cfo.ignore(); + FApplication::sendEvent(parent, &cfo); + + if ( cfo.isAccepted() ) + out.ignore(); + if ( out.isAccepted() ) { if ( prev == this ) return false; prev->setFocus(); + FFocusEvent cfi (fc::ChildFocusIn_Event); + FApplication::sendEvent(parent, &cfi); + FFocusEvent in (fc::FocusIn_Event); in.setFocusType(fc::FocusPreviousWidget); FApplication::sendEvent(prev, &in); if ( in.isAccepted() ) { - this->draw(); - prev->draw(); + this->redraw(); + prev->redraw(); updateTerminal(); flush_out(); } @@ -2004,8 +2066,12 @@ bool FWidget::event (FEvent* ev) onFocusOut ( static_cast(ev) ); break; - case fc::ChildFocusChanged_Event: - onChildFocusChanged ( static_cast(ev) ); + case fc::ChildFocusIn_Event: + onChildFocusIn ( static_cast(ev) ); + break; + + case fc::ChildFocusOut_Event: + onChildFocusOut ( static_cast(ev) ); break; case fc::Accelerator_Event: @@ -2079,7 +2145,11 @@ void FWidget::onFocusOut (FFocusEvent*) { } //---------------------------------------------------------------------- -void FWidget::onChildFocusChanged (FFocusEvent*) +void FWidget::onChildFocusIn (FFocusEvent*) +{ } + +//---------------------------------------------------------------------- +void FWidget::onChildFocusOut (FFocusEvent*) { } //---------------------------------------------------------------------- diff --git a/src/fwidget.h b/src/fwidget.h index 69a516b1..96ad0481 100644 --- a/src/fwidget.h +++ b/src/fwidget.h @@ -124,6 +124,8 @@ class FWidget : public FVTerm FWidget* getParentWidget() const; static FWidget* getMainWidget(); virtual FWidget* getFocusWidget() const; + virtual FWidget* getFirstFocusableWidget (FObjectList); + virtual FWidget* getLastFocusableWidget (FObjectList); static FWidget* getClickedWidget(); static FWidget* getMoveSizeWidget(); static FWidget* getOpenMenu(); @@ -313,7 +315,8 @@ class FWidget : public FVTerm virtual void onMouseMove (FMouseEvent*); virtual void onFocusIn (FFocusEvent*); virtual void onFocusOut (FFocusEvent*); - virtual void onChildFocusChanged (FFocusEvent*); + virtual void onChildFocusIn (FFocusEvent*); + virtual void onChildFocusOut (FFocusEvent*); virtual void onAccel (FAccelEvent*); virtual void onResize (FResizeEvent*); virtual void onShow (FShowEvent*); @@ -521,6 +524,7 @@ class FWidget : public FVTerm // Friend class friend class FToggleButton; + friend class FScrollView; }; #pragma pack(pop) diff --git a/test/scrollview.cpp b/test/scrollview.cpp index 87c2d5a6..c85ceca9 100644 --- a/test/scrollview.cpp +++ b/test/scrollview.cpp @@ -145,7 +145,8 @@ void scrollview::cb_go_west (FWidget*, void*) scrollToX (1); go_north->setFocus(); go_west->redraw(); - go_north->redraw();} + go_north->redraw(); +} //---------------------------------------------------------------------- void scrollview::cb_go_north (FWidget*, void*)