From 8a5bd27c2018e0ae4f980e77aea891f70b1ce562 Mon Sep 17 00:00:00 2001
From: ocboogie <boogie@mikulec.com>
Date: Sat, 12 May 2018 16:30:29 -0700
Subject: [PATCH 1/5] Add global key bindings for changing current ruleset

---
 .../Overlays/Toolbar/ToolbarModeSelector.cs   | 49 ++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
index 1da51e4a5a..4855c004c4 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
@@ -1,11 +1,14 @@
 // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
 
+using System;
 using System.Linq;
+using System.Collections.Generic;
 using osu.Framework.Allocation;
 using osu.Framework.Caching;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
+using osu.Framework.Input.Bindings;
 using OpenTK;
 using OpenTK.Graphics;
 using osu.Framework.Configuration;
@@ -14,7 +17,7 @@ using osu.Game.Rulesets;
 
 namespace osu.Game.Overlays.Toolbar
 {
-    public class ToolbarModeSelector : Container
+    public class ToolbarModeSelector : KeyBindingContainer<int>
     {
         private const float padding = 10;
 
@@ -22,6 +25,7 @@ namespace osu.Game.Overlays.Toolbar
         private readonly Drawable modeButtonLine;
         private ToolbarModeButton activeButton;
 
+        private int rulesetCount;
         private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
 
         public ToolbarModeSelector()
@@ -64,9 +68,50 @@ namespace osu.Game.Overlays.Toolbar
             };
         }
 
+        public override IEnumerable<osu.Framework.Input.Bindings.KeyBinding> DefaultKeyBindings
+        {
+            get
+            {
+                var keybinds = new List<osu.Framework.Input.Bindings.KeyBinding>();
+                for (int i = 0; i < Math.Min(rulesetCount, 10); i++)
+                {
+                    InputKey numberKey;
+                    if (i == 9)
+                        numberKey = InputKey.Number0;
+                    else
+                        numberKey = (InputKey)i + 110;
+
+                    keybinds.Add(new osu.Framework.Input.Bindings.KeyBinding(new[] { InputKey.Control, numberKey }, i));
+                }
+                return keybinds;
+            }
+        }
+
+        private class RulesetSwitcherInputHandler : Container, IKeyBindingHandler<int>
+        {
+            private Bindable<RulesetInfo> ruleset;
+            private RulesetStore rulesets;
+
+            public RulesetSwitcherInputHandler(Bindable<RulesetInfo> ruleset, RulesetStore rulesets)
+            {
+                this.ruleset = ruleset;
+                this.rulesets = rulesets;
+            }
+
+            public bool OnPressed(int action)
+            {
+                ruleset.Value = rulesets.GetRuleset(action);
+
+                return true;
+            }
+
+            public bool OnReleased(int action) => false;
+        }
+
         [BackgroundDependencyLoader(true)]
         private void load(RulesetStore rulesets, OsuGame game)
         {
+            this.rulesetCount = rulesets.AvailableRulesets.Count();
             foreach (var r in rulesets.AvailableRulesets)
             {
                 modeButtons.Add(new ToolbarModeButton
@@ -85,6 +130,8 @@ namespace osu.Game.Overlays.Toolbar
                 ruleset.BindTo(game.Ruleset);
             else
                 ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault();
+
+            Add(new RulesetSwitcherInputHandler(ruleset, rulesets));
         }
 
         public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput;

From 26f06a9ae1612e19bdc372873fd17ed84f70179e Mon Sep 17 00:00:00 2001
From: ocboogie <boogie@mikulec.com>
Date: Sat, 12 May 2018 17:25:15 -0700
Subject: [PATCH 2/5] Resolve linting issues in ToolbarModeSelector.cs

---
 osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
index 4855c004c4..889cf8885e 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
@@ -89,8 +89,8 @@ namespace osu.Game.Overlays.Toolbar
 
         private class RulesetSwitcherInputHandler : Container, IKeyBindingHandler<int>
         {
-            private Bindable<RulesetInfo> ruleset;
-            private RulesetStore rulesets;
+            private readonly Bindable<RulesetInfo> ruleset;
+            private readonly RulesetStore rulesets;
 
             public RulesetSwitcherInputHandler(Bindable<RulesetInfo> ruleset, RulesetStore rulesets)
             {
@@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Toolbar
         [BackgroundDependencyLoader(true)]
         private void load(RulesetStore rulesets, OsuGame game)
         {
-            this.rulesetCount = rulesets.AvailableRulesets.Count();
+            rulesetCount = rulesets.AvailableRulesets.Count();
             foreach (var r in rulesets.AvailableRulesets)
             {
                 modeButtons.Add(new ToolbarModeButton

From 327c7432be72ab79e882a6dc9d8e0c51d310d485 Mon Sep 17 00:00:00 2001
From: ocboogie <boogie@mikulec.com>
Date: Sun, 13 May 2018 19:33:52 -0700
Subject: [PATCH 3/5] Use OnKeyDown instead of a IKeyBindingHandler

---
 .../Overlays/Toolbar/ToolbarModeSelector.cs   | 66 ++++++-------------
 1 file changed, 21 insertions(+), 45 deletions(-)

diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
index 889cf8885e..7286cf3f1c 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
@@ -4,12 +4,14 @@
 using System;
 using System.Linq;
 using System.Collections.Generic;
+using osu.Framework;
 using osu.Framework.Allocation;
 using osu.Framework.Caching;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
-using osu.Framework.Input.Bindings;
+using osu.Framework.Input;
 using OpenTK;
+using OpenTK.Input;
 using OpenTK.Graphics;
 using osu.Framework.Configuration;
 using osu.Framework.Graphics.Shapes;
@@ -17,7 +19,7 @@ using osu.Game.Rulesets;
 
 namespace osu.Game.Overlays.Toolbar
 {
-    public class ToolbarModeSelector : KeyBindingContainer<int>
+    public class ToolbarModeSelector : Container
     {
         private const float padding = 10;
 
@@ -25,7 +27,7 @@ namespace osu.Game.Overlays.Toolbar
         private readonly Drawable modeButtonLine;
         private ToolbarModeButton activeButton;
 
-        private int rulesetCount;
+        private RulesetStore rulesets;
         private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
 
         public ToolbarModeSelector()
@@ -68,50 +70,10 @@ namespace osu.Game.Overlays.Toolbar
             };
         }
 
-        public override IEnumerable<osu.Framework.Input.Bindings.KeyBinding> DefaultKeyBindings
-        {
-            get
-            {
-                var keybinds = new List<osu.Framework.Input.Bindings.KeyBinding>();
-                for (int i = 0; i < Math.Min(rulesetCount, 10); i++)
-                {
-                    InputKey numberKey;
-                    if (i == 9)
-                        numberKey = InputKey.Number0;
-                    else
-                        numberKey = (InputKey)i + 110;
-
-                    keybinds.Add(new osu.Framework.Input.Bindings.KeyBinding(new[] { InputKey.Control, numberKey }, i));
-                }
-                return keybinds;
-            }
-        }
-
-        private class RulesetSwitcherInputHandler : Container, IKeyBindingHandler<int>
-        {
-            private readonly Bindable<RulesetInfo> ruleset;
-            private readonly RulesetStore rulesets;
-
-            public RulesetSwitcherInputHandler(Bindable<RulesetInfo> ruleset, RulesetStore rulesets)
-            {
-                this.ruleset = ruleset;
-                this.rulesets = rulesets;
-            }
-
-            public bool OnPressed(int action)
-            {
-                ruleset.Value = rulesets.GetRuleset(action);
-
-                return true;
-            }
-
-            public bool OnReleased(int action) => false;
-        }
-
         [BackgroundDependencyLoader(true)]
         private void load(RulesetStore rulesets, OsuGame game)
         {
-            rulesetCount = rulesets.AvailableRulesets.Count();
+            this.rulesets = rulesets;
             foreach (var r in rulesets.AvailableRulesets)
             {
                 modeButtons.Add(new ToolbarModeButton
@@ -130,8 +92,22 @@ namespace osu.Game.Overlays.Toolbar
                 ruleset.BindTo(game.Ruleset);
             else
                 ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault();
+        }
 
-            Add(new RulesetSwitcherInputHandler(ruleset, rulesets));
+        protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
+        {
+            base.OnKeyDown(state, args);
+            if (!state.Keyboard.ControlPressed || args.Repeat || (int)args.Key < 109 ||  (int)args.Key > 118) {
+                return false;
+            }
+
+            RulesetInfo targetRuleset = rulesets.GetRuleset(args.Key == Key.Number0 ? 9 : (int)args.Key - 110);
+            if (targetRuleset == null || targetRuleset == ruleset.Value) {
+                return false;
+            }
+
+            ruleset.Value = targetRuleset;
+            return true;
         }
 
         public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput;

From ebd9d1a0376becee8ee0f71e93cca67daf9799e7 Mon Sep 17 00:00:00 2001
From: ocboogie <boogie@mikulec.com>
Date: Sun, 13 May 2018 19:43:26 -0700
Subject: [PATCH 4/5] Resolve linting issues in ToolbarModeSelector.cs

---
 osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
index 7286cf3f1c..eeaa15d58a 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
@@ -1,10 +1,7 @@
 // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
 
-using System;
 using System.Linq;
-using System.Collections.Generic;
-using osu.Framework;
 using osu.Framework.Allocation;
 using osu.Framework.Caching;
 using osu.Framework.Graphics;

From 42519e3723e5abcde81c0c04005dae38a657aeb8 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Mon, 21 May 2018 14:45:44 +0900
Subject: [PATCH 5/5] Rewrite code for clarity

This also uses the AvailableRulesets list rather than private IDs
---
 .../Overlays/Toolbar/ToolbarModeSelector.cs   | 25 +++++++++----------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
index eeaa15d58a..3078c44844 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
@@ -76,15 +76,13 @@ namespace osu.Game.Overlays.Toolbar
                 modeButtons.Add(new ToolbarModeButton
                 {
                     Ruleset = r,
-                    Action = delegate
-                    {
-                        ruleset.Value = r;
-                    }
+                    Action = delegate { ruleset.Value = r; }
                 });
             }
 
             ruleset.ValueChanged += rulesetChanged;
             ruleset.DisabledChanged += disabledChanged;
+
             if (game != null)
                 ruleset.BindTo(game.Ruleset);
             else
@@ -94,17 +92,18 @@ namespace osu.Game.Overlays.Toolbar
         protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
         {
             base.OnKeyDown(state, args);
-            if (!state.Keyboard.ControlPressed || args.Repeat || (int)args.Key < 109 ||  (int)args.Key > 118) {
-                return false;
+
+            if (state.Keyboard.ControlPressed && !args.Repeat && args.Key >= Key.Number1 && args.Key <= Key.Number9)
+            {
+                int requested = args.Key - Key.Number1;
+
+                RulesetInfo found = rulesets.AvailableRulesets.Skip(requested).FirstOrDefault();
+                if (found != null)
+                    ruleset.Value = found;
+                return true;
             }
 
-            RulesetInfo targetRuleset = rulesets.GetRuleset(args.Key == Key.Number0 ? 9 : (int)args.Key - 110);
-            if (targetRuleset == null || targetRuleset == ruleset.Value) {
-                return false;
-            }
-
-            ruleset.Value = targetRuleset;
-            return true;
+            return false;
         }
 
         public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput;