Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit to improve and fix focus handling

  • Loading branch information...
commit 1e7f21e1e6b076208bd721c543a14e6ccc418b91 1 parent dae49a0
Mitja Skuver SilentException authored
201 mediaportal/Core/guilib/GUIControl.cs
View
@@ -34,6 +34,14 @@
namespace MediaPortal.GUI.Library
{
+ public struct DirectionsPassed
+ {
+ public bool Up;
+ public bool Down;
+ public bool Left;
+ public bool Right;
+ }
+
public abstract class GUIBaseControl : System.ComponentModel.ISupportInitialize
{
protected GUIBaseControl()
@@ -53,7 +61,8 @@ public bool IsVisible
set { Visibility = value ? Visibility.Visible : Visibility.Hidden; }
}
- public bool IsFocused { get; set; }
+ protected internal bool IsFocusedInternal { get; set; }
+ public virtual bool IsFocused { get; set; }
public bool Focusable { get; set; }
public MediaPortal.Drawing.Point Location { get; set; }
public Thickness Margin { get; set; }
@@ -140,6 +149,8 @@ public abstract class GUIControl : GUIBaseControl, IDisposable // Control, IDisp
private TransformMatrix _transform = new TransformMatrix();
+ protected internal DirectionsPassed _directionsPassed = new DirectionsPassed();
+
/// <summary>
/// enum to specify the alignment of the control
/// </summary>
@@ -388,8 +399,29 @@ private int Navigate(Direction direction)
}
int nearestIndex = -1;
- double distanceMin = 10000;
- double bearingMin = 10000;
+ //double distanceMin = 10000;
+ //double bearingMin = 10000;
+ double errorMin = 10000;
+
+ double targetBearing = 0;
+ if (direction == Direction.Left)
+ {
+ targetBearing = 180;
+ }
+ if (direction == Direction.Right)
+ {
+ targetBearing = 0;
+ }
+ if (direction == Direction.Up)
+ {
+ targetBearing = -90;
+ }
+ if (direction == Direction.Down)
+ {
+ targetBearing = 90;
+ }
+
+ double diag = Math.Sqrt((GUIGraphicsContext.form.Width * GUIGraphicsContext.form.Width) + (GUIGraphicsContext.form.Height * GUIGraphicsContext.form.Height));
foreach (GUIControl control in FlattenHierarchy(GUIWindowManager.GetWindow(WindowId).Children))
{
@@ -406,36 +438,49 @@ private int Navigate(Direction direction)
double bearing = CalcBearing(new Drawing.Point(currentX, currentY),
new Drawing.Point(control.XPosition, control.YPosition));
- if (direction == Direction.Left && (bearing < 215 || bearing > 325))
- {
- continue;
- }
+ double bearingDistance = targetBearing - bearing;
+ if (bearingDistance > 180) bearingDistance = bearingDistance - 360;
+ if (bearingDistance < -180) bearingDistance = bearingDistance + 360;
+ bearingDistance = Math.Abs(bearingDistance);
- if (direction == Direction.Right && (bearing < -145 || bearing > -35))
+ if (direction != Direction.None && bearingDistance > 45)
{
continue;
}
- if (direction == Direction.Up && (bearing < -45 || bearing > 45))
- {
- continue;
- }
+ double distance = CalcDistance(new Drawing.Point(currentX, currentY),
+ new Drawing.Point(control.XPosition, control.YPosition));
- if (direction == Direction.Down && !(bearing <= -135 || bearing >= 135))
+ // skip same point if user is navigation
+ if (direction != Direction.None && distance == 0)
{
continue;
}
- double distance = CalcDistance(new Drawing.Point(currentX, currentY),
- new Drawing.Point(control.XPosition, control.YPosition));
+ ////if (!(distance <= distanceMin && bearing <= bearingMin))
+ //bearing = Math.Abs(targetBearing - Math.Abs(bearing));
+ ////if (!(distance <= distanceMin && bearing <= bearingMin))
+ //if (distance + bearing > distanceMin + bearingMin)
+ //{
+ // continue;
+ //}
+ double WeightBearing = 1;
+ double WeightDistance = 1;
+
+ if (direction == Direction.None)
+ WeightBearing = 0;
+
+ double error = WeightBearing * ((bearingDistance / 180) * (bearingDistance / 180)) + WeightDistance * ((distance / diag) * (distance / diag));
- if (!(distance <= distanceMin && bearing <= bearingMin))
+ if (error > errorMin)
{
continue;
}
- bearingMin = bearing;
- distanceMin = distance;
+ //bearingMin = bearingDistance;
+ //distanceMin = distance;
+ errorMin = error;
+
nearestIndex = control.GetID;
}
@@ -447,13 +492,18 @@ private static double CalcBearing(Drawing.Point p1, Drawing.Point p2)
double horzDelta = p2.X - p1.X;
double vertDelta = p2.Y - p1.Y;
- // arctan gives us the bearing, just need to convert -pi..+pi to 0..360 deg
- double bearing = Math.Round(90 - Math.Atan2(vertDelta, horzDelta) / Math.PI * 180 + 360) % 360;
+ double bearing = Math.Atan2(vertDelta, horzDelta) / Math.PI * 180;
+
+ //if (horzDelta == 0 && vertDelta == 0) return 0;
- // normalize
- bearing = bearing > 180 ? ((bearing + 180) % 360) - 180 : bearing < -180 ? ((bearing - 180) % 360) + 180 : bearing;
+ //// arctan gives us the bearing, just need to convert -pi..+pi to 0..360 deg
+ //double bearing = Math.Round(90 - Math.Atan2(vertDelta, horzDelta) / Math.PI * 180 + 360) % 360;
- return bearing >= 0 ? bearing - 180 : 180 - bearing;
+ //// normalize
+ //bearing = bearing > 180 ? ((bearing + 180) % 360) - 180 : bearing < -180 ? ((bearing - 180) % 360) + 180 : bearing;
+
+ //return bearing >= 0 ? bearing - 180 : 180 - bearing;
+ return bearing;
}
private static double CalcDistance(Drawing.Point p2, Drawing.Point p1)
@@ -533,6 +583,10 @@ public virtual bool OnMessage(GUIMessage message)
{
case GUIMessage.MessageType.GUI_MSG_SETFOCUS:
+ ClearDirectionsPassedIfNeeded((Direction)message.Param1);
+ bool passed = CheckDirectionsPassed((Direction)message.Param1);
+ SetDirectionsPassed((Direction)message.Param1);
+
// if control is disabled then move 2 the next control
if (Disabled || !CanFocus())
{
@@ -554,7 +608,7 @@ public virtual bool OnMessage(GUIMessage message)
break;
}
- if (controlId == 0)
+ if (passed || controlId == 0)
{
controlId = Navigate((Direction)message.Param1);
}
@@ -639,9 +693,13 @@ public int ParentID
/// </summary>
public virtual bool Focus
{
- get { return IsFocused; }
+ get { return IsFocusedInternal; }
set
{
+ if (value)
+ {
+ UnFocusAllOtherControlsOnWindow();
+ }
if (Focus && !value)
{
QueueAnimation(AnimationType.Unfocus);
@@ -651,10 +709,17 @@ public virtual bool Focus
QueueAnimation(AnimationType.Focus);
}
//SetValue(IsFocusedProperty, value);
- IsFocused = value;
+ IsFocusedInternal = value;
+ ClearDirectionsPassed();
}
}
+ public override bool IsFocused // to maintain compatibility
+ {
+ get { return IsFocusedInternal; }
+ set { Focus = value; }
+ }
+
/// <summary>
/// Preallocates the control its DirectX resources.
/// </summary>
@@ -2051,5 +2116,89 @@ public ILayoutDetail LayoutDetail
get { return _layoutDetail; }
set { _layoutDetail = value; }
}
+
+ internal void ClearDirectionsPassed()
+ {
+ _directionsPassed.Up = false;
+ _directionsPassed.Down = false;
+ _directionsPassed.Left = false;
+ _directionsPassed.Right = false;
+ }
+
+ protected void SetDirectionsPassed(Direction direction)
+ {
+ if (direction == Direction.Up)
+ _directionsPassed.Up = true;
+ if (direction == Direction.Down)
+ _directionsPassed.Down = true;
+ if (direction == Direction.Left)
+ _directionsPassed.Left = true;
+ if (direction == Direction.Right)
+ _directionsPassed.Right = true;
+ if (direction != Direction.None && ParentWindow != null)
+ ParentWindow.AddControlToDirectionsPassed(this);
+ }
+
+ protected void ClearDirectionsPassedIfNeeded(Direction direction)
+ {
+ bool clear = false;
+ if (direction == Direction.Up && !_directionsPassed.Up)
+ clear = true;
+ else if (direction == Direction.Down && !_directionsPassed.Down)
+ clear = true;
+ else if (direction == Direction.Left && !_directionsPassed.Left)
+ clear = true;
+ else if (direction == Direction.Right && !_directionsPassed.Right)
+ clear = true;
+
+ if (clear)
+ ClearDirectionsPassed();
+ }
+
+ protected bool CheckDirectionsPassed(Direction direction)
+ {
+ if (direction == Direction.Up)
+ return _directionsPassed.Up;
+ if (direction == Direction.Down)
+ return _directionsPassed.Down;
+ if (direction == Direction.Left)
+ return _directionsPassed.Left;
+ if (direction == Direction.Right)
+ return _directionsPassed.Right;
+ return false;
+ }
+
+ private void UnFocusAllOtherControlsOnWindow()
+ {
+ //if (ParentControl != null && !(ParentControl is GUIGroup) && !(ParentControl is GUIActionGroup)) return;
+ if (ParentWindow != null && !ParentWindow.HasChild(this)) return;
+
+ GUIWindow win = GUIWindowManager.GetWindow(GUIWindowManager.ActiveWindowEx);
+ if (win != null)
+ {
+ int focusID = win.GetFocusControlId();
+ while (focusID > 0)
+ {
+ //if (focusID != GetID)
+ {
+ win.GetControl(focusID).Focus = false;
+ }
+ focusID = win.GetFocusControlId();
+ }
+ }
+ }
+
+ private GUIWindow _parentWindow;
+ public GUIWindow ParentWindow
+ {
+ get
+ {
+ if (_parentWindow == null && WindowId >= 0)
+ {
+ _parentWindow = GUIWindowManager.GetWindow(WindowId);
+ }
+ return _parentWindow;
+ }
+ }
}
}
54 mediaportal/Core/guilib/GUIWindow.cs
View
@@ -222,6 +222,9 @@ protected enum AutoHideTopBar
private VisualEffect _showAnimation = new VisualEffect(); // for dialogs
private VisualEffect _closeAnimation = new VisualEffect();
+ private List<GUIControl> _focusControlsTried = new List<GUIControl>();
+ private object _focusControlsTriedLock = new object();
+
#endregion
#region ctor
@@ -936,6 +939,8 @@ protected virtual void OnPageDestroy(int new_windowId)
}
}
+ ClearControlsDirectionsPassed();
+
if (GUIGraphicsContext.IsFullScreenVideo == false)
{
if (new_windowId != (int)Window.WINDOW_FULLSCREEN_VIDEO &&
@@ -1203,6 +1208,7 @@ public virtual void UpdateVisibility()
{
for (int x = 0; x < Children.Count; ++x)
{
+ /*
GUIGroup grp = Children[x] as GUIGroup;
if (grp != null)
{
@@ -1216,6 +1222,8 @@ public virtual void UpdateVisibility()
{
Children[x].UpdateVisibility();
}
+ */
+ Children[x].UpdateVisibility();
}
}
@@ -1965,6 +1973,52 @@ public static bool HasWindowVisibilityUpdated
#endregion Fields
+ internal void ClearControlsDirectionsPassed()
+ {
+ lock (_focusControlsTriedLock)
+ {
+ foreach (GUIControl control in _focusControlsTried)
+ {
+ control.ClearDirectionsPassed();
+ }
+ _focusControlsTried.Clear();
+ }
+ }
+
+ internal void AddControlToDirectionsPassed(GUIControl control)
+ {
+ lock (_focusControlsTriedLock)
+ {
+ if (!_focusControlsTried.Contains(control))
+ {
+ _focusControlsTried.Add(control);
+ }
+ }
+ }
+
+ public List<GUIControl> AllChildren
+ {
+ get
+ {
+ List<GUIControl> result = new List<GUIControl>();
+ result.AddRange(Children);
+ foreach (GUIControl ctl in Children)
+ {
+ List<GUIControl> ctlChildren = ctl.AllChildren;
+ if (ctlChildren != null)
+ result.AddRange(ctlChildren);
+ }
+ return result;
+ }
+ }
+
+ public bool HasChild(GUIControl control)
+ {
+ if (AllChildren.Contains(control))
+ return true;
+ return false;
+ }
+
public void BeginInit() {}
public void EndInit() {}
21 mediaportal/Core/guilib/GUIWindowManager.cs
View
@@ -462,6 +462,8 @@ public static void OnAction(Action action)
pWindow.OnAction(action);
}
+ bool focus = true;
+
if (action.wID == Action.ActionType.ACTION_MOVE_UP)
{
if (pWindow.GetFocusControlId() < 0)
@@ -482,6 +484,11 @@ public static void OnAction(Action action)
GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_SETFOCUS, pWindow.GetID, 0,
pWindow.PreviousFocusedId, 0, 0, null);
pWindow.OnMessage(msg);
+ focus = false;
+ }
+ else if (focusState == FocusState.FOCUSED)
+ {
+ focus = false;
}
}
}
@@ -508,10 +515,24 @@ public static void OnAction(Action action)
GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_SETFOCUS, pWindow.GetID, 0,
pWindow.PreviousFocusedId, 0, 0, null);
pWindow.OnMessage(msg);
+ focus = false;
+ }
+ else if (focusState == FocusState.FOCUSED)
+ {
+ focus = false;
}
}
}
}
+
+ if (focus && pWindow.GetFocusControlId() < 0 &&
+ action.wID != Action.ActionType.ACTION_MOUSE_MOVE)
+ {
+ GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_SETFOCUS, pWindow.GetID, 0,
+ pWindow.PreviousFocusedId, 0, 0, null);
+ pWindow.OnMessage(msg);
+ }
+ pWindow.ClearControlsDirectionsPassed();
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.