Allow to change the focus out from FScrollView

This commit is contained in:
Markus Gans 2017-01-28 22:03:15 +01:00
parent d2ba29d842
commit 36bba82e9f
12 changed files with 244 additions and 135 deletions

View File

@ -1,3 +1,6 @@
2017-01-28 Markus Gans <guru.mail@muenster.de>
* Allow to change the focus out from FScrollView to another widget
2017-01-26 Markus Gans <guru.mail@muenster.de>
* FScrollView now scrolls automatically to the focused widget

View File

@ -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<FToggleButton*>(*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<FToggleButton*>(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<FToggleButton*>(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<FToggleButton*>(*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<FToggleButton*>(*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<FToggleButton*>(*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<FToggleButton*>(*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<FToggleButton*>(*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<FToggleButton*>(*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,22 +315,12 @@ 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 )
@ -351,7 +329,6 @@ void FButtonGroup::onFocusIn (FFocusEvent* in_ev)
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<FToggleButton*>(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<FToggleButton*>(*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<FToggleButton*>(*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();

View File

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

View File

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

View File

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

View File

@ -57,7 +57,7 @@ class FObject
};
// Typedef
typedef std::list<FObject*> object_list;
typedef std::list<FObject*> 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; }
//----------------------------------------------------------------------

View File

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

View File

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

View File

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

View File

@ -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<FWidget*>(*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<FWidget*>(*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<FWidget*>(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<FWidget*>(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<FFocusEvent*>(ev) );
break;
case fc::ChildFocusChanged_Event:
onChildFocusChanged ( static_cast<FFocusEvent*>(ev) );
case fc::ChildFocusIn_Event:
onChildFocusIn ( static_cast<FFocusEvent*>(ev) );
break;
case fc::ChildFocusOut_Event:
onChildFocusOut ( static_cast<FFocusEvent*>(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*)
{ }
//----------------------------------------------------------------------

View File

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

View File

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