Skip to content

Commit fdf1ab9

Browse files
committed
hotkeys work again.. not the cleanest, but at least it's out of App class now
1 parent d1a4af3 commit fdf1ab9

19 files changed

+132
-228
lines changed

RetailCoder.VBE/App.cs

Lines changed: 4 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Globalization;
55
using System.Linq;
66
using System.Runtime.InteropServices.ComTypes;
7-
using System.Threading.Tasks;
87
using System.Windows.Forms;
98
using System.Windows.Input;
109
using Microsoft.Vbe.Interop;
@@ -18,9 +17,6 @@
1817
using Rubberduck.UI.Command.MenuItems;
1918
using Infralution.Localization.Wpf;
2019
using Rubberduck.Common.Dispatch;
21-
using Rubberduck.Common.Hotkeys;
22-
using Rubberduck.UI.Command;
23-
using Hotkey = Rubberduck.Common.Hotkeys.Hotkey;
2420

2521
namespace Rubberduck
2622
{
@@ -35,7 +31,6 @@ public class App : IDisposable
3531
private readonly RubberduckCommandBar _stateBar;
3632
private readonly IIndenter _indenter;
3733
private readonly IRubberduckHooks _hooks;
38-
private readonly IEnumerable<ICommand> _appCommands;
3934

4035
private readonly Logger _logger;
4136

@@ -47,19 +42,13 @@ public class App : IDisposable
4742
private readonly IDictionary<VBComponents, Tuple<IConnectionPoint, int>> _componentsEventsConnectionPoints =
4843
new Dictionary<VBComponents, Tuple<IConnectionPoint, int>>();
4944

50-
private IReadOnlyDictionary<string, RubberduckHotkey> _hotkeyNameMap;
51-
52-
private IReadOnlyDictionary<RubberduckHotkey, ICommand> _hotkeyActions;
53-
private IReadOnlyDictionary<string, ICommand> _secondKeyActions;
54-
5545
public App(VBE vbe, IMessageBox messageBox,
5646
IRubberduckParser parser,
5747
IGeneralConfigService configService,
5848
IAppMenu appMenus,
5949
RubberduckCommandBar stateBar,
6050
IIndenter indenter,
61-
IRubberduckHooks hooks,
62-
IEnumerable<ICommand> appCommands)
51+
IRubberduckHooks hooks)
6352
{
6453
_vbe = vbe;
6554
_messageBox = messageBox;
@@ -70,10 +59,8 @@ public App(VBE vbe, IMessageBox messageBox,
7059
_stateBar = stateBar;
7160
_indenter = indenter;
7261
_hooks = hooks;
73-
_appCommands = appCommands;
7462
_logger = LogManager.GetCurrentClassLogger();
7563

76-
_hooks.MessageReceived += hooks_MessageReceived;
7764
_configService.LanguageChanged += ConfigServiceLanguageChanged;
7865
_parser.State.StateChanged += Parser_StateChanged;
7966
_stateBar.Refresh += _stateBar_Refresh;
@@ -100,11 +87,11 @@ public void Startup()
10087
_appMenus.Initialize();
10188
_appMenus.Localize();
10289

103-
//_hooks.AddHook(new LowLevelKeyboardHook(_vbe));
104-
HookHotkeys();
90+
_hooks.HookHotkeys();
10591
_hooks.Attach();
10692
}
10793

94+
#region sink handlers. todo: move to another class
10895
async void sink_ProjectRemoved(object sender, DispatcherEventArgs<VBProject> e)
10996
{
11097
Debug.WriteLine(string.Format("Project '{0}' was removed.", e.Item.Name));
@@ -239,90 +226,7 @@ async void sink_ProjectActivated(object sender, DispatcherEventArgs<VBProject> e
239226
Debug.WriteLine(string.Format("Project '{0}' was activated.", e.Item.Name));
240227
// do something?
241228
}
242-
243-
private Keys _firstStepHotKey;
244-
private bool _isAwaitingTwoStepKey;
245-
private bool _skipKeyUp;
246-
247-
private void hooks_MessageReceived(object sender, HookEventArgs e)
248-
{
249-
if (sender is LowLevelKeyboardHook)
250-
{
251-
HandleLowLevelKeyhook(e);
252-
return;
253-
}
254-
255-
var hotKey = sender as IHotkey;
256-
if (hotKey != null)
257-
{
258-
HandleHotkey(hotKey);
259-
}
260-
else
261-
{
262-
AwaitNextKey();
263-
}
264-
}
265-
266-
private void HandleHotkey(IHotkey hotkey)
267-
{
268-
if (hotkey.IsTwoStepHotkey)
269-
{
270-
_firstStepHotKey = hotkey.HotkeyInfo.Keys;
271-
AwaitNextKey(true, hotkey.HotkeyInfo);
272-
}
273-
else
274-
{
275-
_firstStepHotKey = Keys.None;
276-
_hotkeyActions[_hotkeyNameMap[hotkey.Key]].Execute(null);
277-
AwaitNextKey();
278-
}
279-
}
280-
281-
private void HandleLowLevelKeyhook(HookEventArgs e)
282-
{
283-
if (_skipKeyUp)
284-
{
285-
_skipKeyUp = false;
286-
return;
287-
}
288-
289-
if (_isAwaitingTwoStepKey)
290-
{
291-
// todo: use _firstStepHotKey and e.Key to run 2-step hotkey action
292-
if (_firstStepHotKey == Keys.I && e.Key == Keys.M)
293-
{
294-
_indenter.IndentCurrentModule();
295-
}
296-
297-
AwaitNextKey();
298-
return;
299-
}
300-
301-
var component = _vbe.ActiveCodePane.CodeModule.Parent;
302-
_parser.ParseComponent(component);
303-
304-
AwaitNextKey();
305-
return;
306-
}
307-
308-
private void AwaitNextKey(bool eatNextKey = false, HotkeyInfo info = default(HotkeyInfo))
309-
{
310-
_isAwaitingTwoStepKey = eatNextKey;
311-
foreach (var hook in _hooks.Hooks.OfType<ILowLevelKeyboardHook>())
312-
{
313-
hook.EatNextKey = eatNextKey;
314-
}
315-
316-
_skipKeyUp = eatNextKey;
317-
if (eatNextKey)
318-
{
319-
_stateBar.SetStatusText("(" + info + ") was pressed. Waiting for second key...");
320-
}
321-
else
322-
{
323-
_stateBar.SetStatusText(_parser.State.Status.ToString());
324-
}
325-
}
229+
#endregion
326230

327231
private void _stateBar_Refresh(object sender, EventArgs e)
328232
{
@@ -335,42 +239,9 @@ private void Parser_StateChanged(object sender, EventArgs e)
335239
_appMenus.EvaluateCanExecute(_parser.State);
336240
}
337241

338-
private void HookHotkeys()
339-
{
340-
var settings = _config.UserSettings.GeneralSettings.HotkeySettings;
341-
foreach (var hotkey in settings.Where(hotkey => hotkey.IsEnabled))
342-
{
343-
_hooks.AddHook(new Hotkey((IntPtr)_vbe.MainWindow.HWnd, hotkey.ToString()));
344-
}
345-
}
346-
347242
private void CleanReloadConfig()
348243
{
349244
LoadConfig();
350-
var hotkeys = _config.UserSettings.GeneralSettings.HotkeySettings
351-
.Where(hotkey => hotkey.IsEnabled).ToList();
352-
353-
_hotkeyNameMap = hotkeys
354-
.ToDictionary(
355-
hotkey => hotkey.ToString(),
356-
hotkey => (RubberduckHotkey)Enum.Parse(typeof(RubberduckHotkey), hotkey.Name));
357-
358-
_hotkeyActions = (from hotkey in hotkeys
359-
let value = (RubberduckHotkey)Enum.Parse(typeof(RubberduckHotkey),hotkey.Name)
360-
where string.IsNullOrEmpty(hotkey.Key2)
361-
select new
362-
{
363-
Hotkey = value,
364-
Command = _appCommands.OfType<IHotkeyCommand>()
365-
.SingleOrDefault(command => command.Hotkey == (RubberduckHotkey)Enum.Parse(typeof(RubberduckHotkey),hotkey.Name))
366-
})
367-
.ToDictionary(kvp => kvp.Hotkey, kvp => (ICommand)kvp.Command);
368-
369-
_secondKeyActions = hotkeys
370-
.Where(hotkey => !string.IsNullOrEmpty(hotkey.Key2))
371-
.ToDictionary(
372-
hotkey => hotkey.Key2,
373-
hotkey => hotkey.Command);
374245
}
375246

376247
private void ConfigServiceLanguageChanged(object sender, EventArgs e)
@@ -410,7 +281,6 @@ public void Dispose()
410281
item.Value.Item1.Unadvise(item.Value.Item2);
411282
}
412283

413-
_hooks.MessageReceived -= hooks_MessageReceived;
414284
_hooks.Dispose();
415285
}
416286
}

RetailCoder.VBE/AutoSave/AutoSave.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@ public AutoSave(VBE vbe, IGeneralConfigService configService)
2020
{
2121
_vbe = vbe;
2222
_configService = configService;
23-
_config = _configService.LoadConfiguration();
2423

2524
_configService.SettingsChanged += ConfigServiceSettingsChanged;
2625

27-
_timer.Enabled = _config.UserSettings.GeneralSettings.AutoSaveEnabled
28-
&& _config.UserSettings.GeneralSettings.AutoSavePeriod != 0;
26+
// todo: move this out of ctor
27+
//_timer.Enabled = _config.UserSettings.GeneralSettings.AutoSaveEnabled
28+
// && _config.UserSettings.GeneralSettings.AutoSavePeriod != 0;
2929

30-
if (_config.UserSettings.GeneralSettings.AutoSavePeriod != 0)
31-
{
32-
_timer.Interval = _config.UserSettings.GeneralSettings.AutoSavePeriod * 1000;
33-
_timer.Elapsed += _timer_Elapsed;
34-
}
30+
//if (_config.UserSettings.GeneralSettings.AutoSavePeriod != 0)
31+
//{
32+
// _timer.Interval = _config.UserSettings.GeneralSettings.AutoSavePeriod * 1000;
33+
// _timer.Elapsed += _timer_Elapsed;
34+
//}
3535
}
3636

37-
void ConfigServiceSettingsChanged(object sender, EventArgs e)
37+
private void ConfigServiceSettingsChanged(object sender, EventArgs e)
3838
{
3939
_config = _configService.LoadConfiguration();
4040

RetailCoder.VBE/Common/Hotkeys/Hotkey.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,50 @@
11
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
4+
using System.Diagnostics;
45
using System.Windows.Forms;
6+
using System.Windows.Input;
57
using Rubberduck.Common.WinAPI;
68

79
namespace Rubberduck.Common.Hotkeys
810
{
911
public class Hotkey : IHotkey
1012
{
1113
private readonly string _key;
14+
private readonly ICommand _command;
1215
private readonly IntPtr _hWndVbe;
1316

14-
public Hotkey(IntPtr hWndVbe, string key, Keys secondKey = Keys.None)
17+
public Hotkey(IntPtr hWndVbe, string key, ICommand command, Keys secondKey = Keys.None)
1518
{
1619
_hWndVbe = hWndVbe;
1720

1821
IsTwoStepHotkey = secondKey != Keys.None;
1922
_key = key;
23+
_command = command;
2024
Combo = GetCombo(key);
2125
SecondKey = secondKey;
2226
}
2327

28+
public ICommand Command { get { return _command; } }
2429
public string Key { get { return _key; } }
2530
public HotkeyInfo HotkeyInfo { get; private set; }
2631
public Keys Combo { get; private set; }
2732
public Keys SecondKey { get; private set; }
2833
public bool IsTwoStepHotkey { get; private set; }
2934
public bool IsAttached { get; private set; }
3035

36+
public event EventHandler<HookEventArgs> MessageReceived;
37+
38+
public void OnMessageReceived()
39+
{
40+
var handler = MessageReceived;
41+
if (handler != null)
42+
{
43+
var args = new HookEventArgs(HotkeyInfo.Keys);
44+
handler.Invoke(this, args);
45+
}
46+
}
47+
3148
public void Attach()
3249
{
3350
var hotKey = _key;
@@ -71,6 +88,7 @@ private void HookKey(Keys key, uint shift)
7188

7289
HotkeyInfo = new HotkeyInfo(hookId, Combo);
7390
IsAttached = true;
91+
Debug.WriteLine("Hotkey '{0}' hooked successfully to command '{1}'", Key, Command.GetType());
7492
}
7593

7694
private static readonly IDictionary<char,uint> Modifiers = new Dictionary<char, uint>

RetailCoder.VBE/Common/Hotkeys/IHotkey.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
using System.Windows.Forms;
2+
using System.Windows.Input;
23

34
namespace Rubberduck.Common.Hotkeys
45
{
56
public interface IHotkey : IAttachable
67
{
78
string Key { get; }
9+
ICommand Command { get; }
810
HotkeyInfo HotkeyInfo { get; }
911
Keys Combo { get; }
1012
Keys SecondKey { get; }

RetailCoder.VBE/Common/IAttachable.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
using System;
2+
13
namespace Rubberduck.Common
24
{
35
public interface IAttachable
46
{
57
bool IsAttached { get; }
8+
event EventHandler<HookEventArgs> MessageReceived;
69

710
void Attach();
811
void Detach();

RetailCoder.VBE/Common/IHook.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

RetailCoder.VBE/Common/ILowLevelKeyboardHook.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace Rubberduck.Common
22
{
3-
public interface ILowLevelKeyboardHook : IHook
3+
public interface ILowLevelKeyboardHook : IAttachable
44
{
55
bool EatNextKey { get; set; }
66
}

RetailCoder.VBE/Common/IRubberduckHooks.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33

44
namespace Rubberduck.Common
55
{
6-
public interface IRubberduckHooks : IHook, IDisposable
6+
public interface IRubberduckHooks : IDisposable, IAttachable
77
{
8-
IEnumerable<IAttachable> Hooks { get; }
9-
void AddHook(IAttachable hook);
8+
void HookHotkeys();
109
}
1110
}

RetailCoder.VBE/Common/ITimerHook.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)