4
4
using System . Globalization ;
5
5
using System . Linq ;
6
6
using System . Runtime . InteropServices . ComTypes ;
7
- using System . Threading . Tasks ;
8
7
using System . Windows . Forms ;
9
- using System . Windows . Input ;
10
8
using Microsoft . Vbe . Interop ;
11
9
using NLog ;
12
10
using Rubberduck . Common ;
18
16
using Rubberduck . UI . Command . MenuItems ;
19
17
using Infralution . Localization . Wpf ;
20
18
using Rubberduck . Common . Dispatch ;
21
- using Rubberduck . Common . Hotkeys ;
22
- using Rubberduck . UI . Command ;
23
- using Hotkey = Rubberduck . Common . Hotkeys . Hotkey ;
24
19
25
20
namespace Rubberduck
26
21
{
@@ -35,7 +30,6 @@ public class App : IDisposable
35
30
private readonly RubberduckCommandBar _stateBar ;
36
31
private readonly IIndenter _indenter ;
37
32
private readonly IRubberduckHooks _hooks ;
38
- private readonly IEnumerable < ICommand > _appCommands ;
39
33
40
34
private readonly Logger _logger ;
41
35
@@ -47,19 +41,13 @@ public class App : IDisposable
47
41
private readonly IDictionary < VBComponents , Tuple < IConnectionPoint , int > > _componentsEventsConnectionPoints =
48
42
new Dictionary < VBComponents , Tuple < IConnectionPoint , int > > ( ) ;
49
43
50
- private IReadOnlyDictionary < string , RubberduckHotkey > _hotkeyNameMap ;
51
-
52
- private IReadOnlyDictionary < RubberduckHotkey , ICommand > _hotkeyActions ;
53
- private IReadOnlyDictionary < string , ICommand > _secondKeyActions ;
54
-
55
44
public App ( VBE vbe , IMessageBox messageBox ,
56
45
IRubberduckParser parser ,
57
46
IGeneralConfigService configService ,
58
47
IAppMenu appMenus ,
59
48
RubberduckCommandBar stateBar ,
60
49
IIndenter indenter ,
61
- IRubberduckHooks hooks ,
62
- IEnumerable < ICommand > appCommands )
50
+ IRubberduckHooks hooks )
63
51
{
64
52
_vbe = vbe ;
65
53
_messageBox = messageBox ;
@@ -70,10 +58,10 @@ public App(VBE vbe, IMessageBox messageBox,
70
58
_stateBar = stateBar ;
71
59
_indenter = indenter ;
72
60
_hooks = hooks ;
73
- _appCommands = appCommands ;
74
61
_logger = LogManager . GetCurrentClassLogger ( ) ;
75
62
76
- _hooks . MessageReceived += hooks_MessageReceived ;
63
+ _hooks . MessageReceived += _hooks_MessageReceived ;
64
+ _configService . SettingsChanged += _configService_SettingsChanged ;
77
65
_configService . LanguageChanged += ConfigServiceLanguageChanged ;
78
66
_parser . State . StateChanged += Parser_StateChanged ;
79
67
_stateBar . Refresh += _stateBar_Refresh ;
@@ -93,20 +81,43 @@ public App(VBE vbe, IMessageBox messageBox,
93
81
UiDispatcher . Initialize ( ) ;
94
82
}
95
83
84
+ private void _hooks_MessageReceived ( object sender , HookEventArgs e )
85
+ {
86
+ if ( sender is MouseHookWrapper )
87
+ {
88
+ // right-click detected
89
+ _appMenus . EvaluateCanExecute ( _parser . State ) ;
90
+ }
91
+ }
92
+
93
+ private void _configService_SettingsChanged ( object sender , EventArgs e )
94
+ {
95
+ // also updates the ShortcutKey text
96
+ _appMenus . Localize ( ) ;
97
+ _hooks . HookHotkeys ( ) ;
98
+ }
99
+
96
100
public void Startup ( )
97
101
{
98
102
CleanReloadConfig ( ) ;
99
103
104
+ foreach ( var project in _vbe . VBProjects . Cast < VBProject > ( ) )
105
+ {
106
+ _parser . State . AddProject ( project ) ;
107
+ }
108
+
100
109
_appMenus . Initialize ( ) ;
101
110
_appMenus . Localize ( ) ;
102
111
103
- //_hooks.AddHook(new LowLevelKeyboardHook(_vbe));
104
- HookHotkeys ( ) ;
112
+ _hooks . HookHotkeys ( ) ;
105
113
_hooks . Attach ( ) ;
106
114
}
107
115
116
+ #region sink handlers. todo: move to another class
108
117
async void sink_ProjectRemoved ( object sender , DispatcherEventArgs < VBProject > e )
109
118
{
119
+ _parser . State . RemoveProject ( e . Item ) ;
120
+
110
121
Debug . WriteLine ( string . Format ( "Project '{0}' was removed." , e . Item . Name ) ) ;
111
122
Tuple < IConnectionPoint , int > value ;
112
123
if ( _componentsEventsConnectionPoints . TryGetValue ( e . Item . VBComponents , out value ) )
@@ -120,6 +131,8 @@ async void sink_ProjectRemoved(object sender, DispatcherEventArgs<VBProject> e)
120
131
121
132
async void sink_ProjectAdded ( object sender , DispatcherEventArgs < VBProject > e )
122
133
{
134
+ _parser . State . AddProject ( e . Item ) ;
135
+
123
136
if ( ! _parser . State . AllDeclarations . Any ( ) )
124
137
{
125
138
// forces menus to evaluate their CanExecute state:
@@ -239,138 +252,31 @@ async void sink_ProjectActivated(object sender, DispatcherEventArgs<VBProject> e
239
252
Debug . WriteLine ( string . Format ( "Project '{0}' was activated." , e . Item . Name ) ) ;
240
253
// do something?
241
254
}
255
+ #endregion
242
256
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 )
257
+ private void _stateBar_Refresh ( object sender , EventArgs e )
282
258
{
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 ;
259
+ _parser . State . OnParseRequested ( sender ) ;
306
260
}
307
261
308
- private void AwaitNextKey ( bool eatNextKey = false , HotkeyInfo info = default ( HotkeyInfo ) )
262
+ private void Parser_StateChanged ( object sender , EventArgs e )
309
263
{
310
- _isAwaitingTwoStepKey = eatNextKey ;
311
- foreach ( var hook in _hooks . Hooks . OfType < ILowLevelKeyboardHook > ( ) )
264
+ if ( _parser . State . Status != ParserState . Ready )
312
265
{
313
- hook . EatNextKey = eatNextKey ;
314
- }
315
-
316
- _skipKeyUp = eatNextKey ;
317
- if ( eatNextKey )
318
- {
319
- _stateBar . SetStatusText ( "(" + info + ") was pressed. Waiting for second key..." ) ;
266
+ _hooks . Detach ( ) ;
320
267
}
321
268
else
322
269
{
323
- _stateBar . SetStatusText ( _parser . State . Status . ToString ( ) ) ;
270
+ _hooks . Attach ( ) ;
324
271
}
325
- }
326
-
327
- private void _stateBar_Refresh ( object sender , EventArgs e )
328
- {
329
- _parser . State . OnParseRequested ( sender ) ;
330
- }
331
272
332
- private void Parser_StateChanged ( object sender , EventArgs e )
333
- {
334
273
Debug . WriteLine ( "App handles StateChanged ({0}), evaluating menu states..." , _parser . State . Status ) ;
335
274
_appMenus . EvaluateCanExecute ( _parser . State ) ;
336
275
}
337
276
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
-
347
277
private void CleanReloadConfig ( )
348
278
{
349
279
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 ) ;
374
280
}
375
281
376
282
private void ConfigServiceLanguageChanged ( object sender , EventArgs e )
@@ -410,7 +316,6 @@ public void Dispose()
410
316
item . Value . Item1 . Unadvise ( item . Value . Item2 ) ;
411
317
}
412
318
413
- _hooks . MessageReceived -= hooks_MessageReceived ;
414
319
_hooks . Dispose ( ) ;
415
320
}
416
321
}
0 commit comments