+/**\r
+ * Is dest in a given direction from src?\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param src The source rect\r
+ * @param dest The dest rect\r
+ */\r
+static bool IsToDirectionOf(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> src, Dali::Rect<float> dest)\r
+{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ {\r
+ return src.left >= dest.right;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return src.right <= dest.left;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ {\r
+ return src.top >= dest.bottom;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ return src.bottom <= dest.top;\r
+ }\r
+ default:\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * Do the given direction's axis of rect1 and rect2 overlap?\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param rect1 The first rect\r
+ * @param rect2 The second rect\r
+ * @return whether the beams overlap\r
+ */\r
+static bool BeamsOverlap(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
+{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);\r
+ }\r
+ default:\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * One rectangle may be another candidate than another by virtue of being exclusively in the beam of the source rect.\r
+ * @param direction The direction (up, down, left, right)\r
+ * @param source The source rect\r
+ * @param rect1 The first rect\r
+ * @param rect2 The second rect\r
+ * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's beam\r
+ */\r
+static bool BeamBeats(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
+{\r
+ const bool rect1InSrcBeam = BeamsOverlap(direction, source, rect1);\r
+ const bool rect2InSrcBeam = BeamsOverlap(direction, source, rect2);\r
+ // if rect1 isn't exclusively in the src beam, it doesn't win\r
+ if(rect2InSrcBeam || !rect1InSrcBeam)\r
+ {\r
+ return false;\r
+ }\r
+ // we know rect1 is in the beam, and rect2 is not\r
+ // if rect1 is to the direction of, and rect2 is not, rect1 wins.\r
+ // for example, for direction left, if rect1 is to the left of the source\r
+ // and rect2 is below, then we always prefer the in beam rect1, since rect2\r
+ // could be reached by going down.\r
+ if(!IsToDirectionOf(direction, source, rect2))\r
+ {\r
+ return true;\r
+ }\r
+ // for horizontal directions, being exclusively in beam always wins\r
+ if((direction == Dali::Toolkit::Control::KeyboardFocus::LEFT || direction == Dali::Toolkit::Control::KeyboardFocus::RIGHT))\r
+ {\r
+ return true;\r
+ }\r
+ // for vertical directions, beams only beat up to a point:\r
+ // now, as long as rect2 isn't completely closer, rect1 wins\r
+ // e.g for direction down, completely closer means for rect2's top\r
+ // edge to be closer to the source's top edge than rect1's bottom edge.\r
+ return (MajorAxisDistance(direction, source, rect1) < MajorAxisDistanceToFarEdge(direction, source, rect2));\r
+}\r
+\r
+bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect)\r
+{\r
+ // to be a better candidate, need to at least be a candidate in the first place\r
+ if(!IsCandidate(focusedRect, candidateRect, direction))\r
+ {\r
+ return false;\r
+ }\r
+ // we know that candidateRect is a candidate.. if bestCandidateRect is not a candidate,\r
+ // candidateRect is better\r
+ if(!IsCandidate(focusedRect, bestCandidateRect, direction))\r
+ {\r
+ return true;\r
+ }\r
+ // if candidateRect is better by beam, it wins\r
+ if(BeamBeats(direction, focusedRect, candidateRect, bestCandidateRect))\r
+ {\r
+ return true;\r
+ }\r
+ // if bestCandidateRect is better, then candidateRect cant' be :)\r
+ if(BeamBeats(direction, focusedRect, bestCandidateRect, candidateRect))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // otherwise, do fudge-tastic comparison of the major and minor axis\r
+ return (GetWeightedDistanceFor(\r
+ MajorAxisDistance(direction, focusedRect, candidateRect),\r
+ MinorAxisDistance(direction, focusedRect, candidateRect)) < GetWeightedDistanceFor(MajorAxisDistance(direction, focusedRect, bestCandidateRect),\r
+ MinorAxisDistance(direction, focusedRect, bestCandidateRect)));\r