summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2011-11-19 13:50:14 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2011-11-19 14:04:35 +0800
commitae0e722efddd0d5f290ada815c1e12dc636a96a5 (patch)
tree169d809ed9801626eb0e222b31fc547fcdab8706
parent9919334ca66802d3540030de24a2532cb42889e5 (diff)
SexyAppFramework: Improved the FindFocusableWidget()
-rw-r--r--osframework/source/SexyAppFramework/Widget.cpp99
-rw-r--r--osframework/source/SexyAppFramework/Widget.h2
2 files changed, 85 insertions, 16 deletions
diff --git a/osframework/source/SexyAppFramework/Widget.cpp b/osframework/source/SexyAppFramework/Widget.cpp
index 6a91c2b..06cd3b6 100644
--- a/osframework/source/SexyAppFramework/Widget.cpp
+++ b/osframework/source/SexyAppFramework/Widget.cpp
@@ -430,6 +430,49 @@ bool Widget::KeyDownUp(KeyCode theKey, bool down)
return false;
}
+
+Widget* Widget::GetTopLevel()
+{
+ Widget* p = this;
+
+ while (p)
+ {
+ if (!p->mParent)
+ return p;
+ if (p->mParent == p->mWidgetManager)
+ return p;
+ p = (Widget*)p->mParent;
+ }
+
+ return this;
+}
+
+WidgetVector::iterator Widget::FindClosest(Widget* theWidget)
+{
+ if (!theWidget || mSortedWidgets.empty())
+ return mSortedWidgets.end();
+
+ WidgetVector::iterator it;
+ WidgetVector::iterator best = mSortedWidgets.end();
+ Point center = theWidget->GetAbsCenter();
+ int bestDist = 0x7fffffff;
+ for (it = mSortedWidgets.begin(); it != mSortedWidgets.end(); ++it)
+ {
+ if (!(*it)->IsFocusable())
+ continue;
+
+ Point diff = center - (*it)->GetAbsCenter();
+ int dist = diff.mX * diff.mX + diff.mY * diff.mY;
+ if (dist < bestDist)
+ {
+ bestDist = dist;
+ best = it;
+ }
+ }
+
+ return best;
+}
+
WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
{
Widget* widget = 0;
@@ -443,7 +486,7 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
// Find the current focus
for (it = mSortedWidgets.begin(); it != mSortedWidgets.end(); ++it)
{
- if ((*it)->IsFocusable())
+ if ((*it)->mHasFocus && (*it)->IsFocusable())
{
current = *it;
break;
@@ -452,6 +495,18 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
if (!current)
{
+ // Find the current focus
+ Widget* topLevel = GetTopLevel();
+ Widget* current = topLevel->mFocus;
+
+ while (current && current->mFocus)
+ current = current->mFocus;
+ if (current)
+ return FindClosest(current);
+ }
+
+ if (!current)
+ {
for (it = mSortedWidgets.begin(); it != mSortedWidgets.end(); ++it)
if ((*it)->IsFocusable())
return it;
@@ -461,15 +516,17 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
{
it = std::find(mSortedWidgets.begin(), mSortedWidgets.end(), current);
}
- if (it == mSortedWidgets.end())
- return it;
+ if (!current)
+ return mSortedWidgets.end();
- Point center = current->GetCenter();
+ Point center = current->GetAbsCenter();
+ Point leftTop = current->GetAbsPos();
if (direct == LAY_Below)
{
for (it++; it != mSortedWidgets.end(); it++)
{
- if ((*it)->IsFocusable() && (*it)->Top() > current->Top())
+ Point pos = (*it)->GetAbsPos();
+ if ((*it)->IsFocusable() && pos.mY > leftTop.mY)
{
widget = *it;
break;
@@ -480,16 +537,19 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
{
WidgetVector::iterator pit = it;
WidgetVector::iterator best = it;
- Point diff = center - (*it)->GetCenter();
+ Point diff = center - (*it)->GetAbsCenter();
int dist = diff.mX * diff.mX + diff.mY * diff.mY;
int bestDist = dist;
for (++it; it != mSortedWidgets.end(); pit = it++)
{
- if ((*it)->Left() < (*pit)->Left())
+ if ((*it)->Left() <= (*pit)->Left())
break;
- Point c = (*it)->GetCenter();
+ if (!(*it)->IsFocusable())
+ continue;
+
+ Point c = (*it)->GetAbsCenter();
diff = center - c;
dist = diff.mX * diff.mX + diff.mY * diff.mY;
if (dist < bestDist)
@@ -509,7 +569,8 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
do
{
--it;
- if ((*it)->IsFocusable() && (*it)->Top() < current->Top())
+ Point pos = (*it)->GetAbsPos();
+ if ((*it)->IsFocusable() && pos.mY < leftTop.mY)
{
widget = *it;
break;
@@ -521,7 +582,7 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
{
WidgetVector::iterator pit = it;
WidgetVector::iterator best = it;
- Point diff = center - (*it)->GetCenter();
+ Point diff = center - (*it)->GetAbsCenter();
int dist = diff.mX * diff.mX + diff.mY * diff.mY;
int bestDist = dist;
@@ -530,7 +591,10 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
if ((*it)->Left() >= (*pit)->Left())
break;
- Point c = (*it)->GetCenter();
+ if (!(*it)->IsFocusable())
+ continue;
+
+ Point c = (*it)->GetAbsCenter();
diff = center - c;
dist = diff.mX * diff.mX + diff.mY * diff.mY;
if (dist < bestDist)
@@ -549,7 +613,8 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
for (; it != mSortedWidgets.end(); ++it)
{
- if ((*it)->IsFocusable() && (*it)->Left() > current->Left())
+ Point pos = (*it)->GetAbsPos();
+ if ((*it)->IsFocusable() && pos.mX > leftTop.mX)
{
widget = *it;
break;
@@ -562,7 +627,8 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
do
{
--it;
- if ((*it)->IsFocusable() && (*it)->Left() > current->Left())
+ Point pos = (*it)->GetAbsPos();
+ if ((*it)->IsFocusable() && pos.mX > leftTop.mX)
{
widget = *it;
break;
@@ -579,8 +645,8 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
do
{
--it;
- if ((*it)->IsFocusable() &&
- (*it)->Left() <= current->Left())
+ Point pos = (*it)->GetAbsPos();
+ if ((*it)->IsFocusable() && pos.mX <= leftTop.mX)
{
widget = *it;
break;
@@ -592,7 +658,8 @@ WidgetVector::iterator Widget::FindFocusableWidget(int direct, Widget* current)
{
for (it = saved + 1; it != mSortedWidgets.end(); ++it)
{
- if ((*it)->IsFocusable() && (*it)->Left() <= current->Left())
+ Point pos = (*it)->GetAbsPos();
+ if ((*it)->IsFocusable() && pos.mX <= leftTop.mX)
{
widget = *it;
break;
diff --git a/osframework/source/SexyAppFramework/Widget.h b/osframework/source/SexyAppFramework/Widget.h
index 86d5441..722d9b8 100644
--- a/osframework/source/SexyAppFramework/Widget.h
+++ b/osframework/source/SexyAppFramework/Widget.h
@@ -118,6 +118,7 @@ public:
virtual bool AxisMoved(const Event& event);
virtual void UserEvent(const Event event);
virtual bool IsPointVisible(int x, int y);
+ virtual Widget* GetTopLevel();
//////// Helper functions
@@ -147,6 +148,7 @@ public:
bool IsFocusable();
protected:
+ virtual WidgetVector::iterator FindClosest(Widget* theWidget);
virtual WidgetVector::iterator FindFocusableWidget(int direct, // the LayoutFlags
Widget* current = 0);