Implement the support for shortcut key

This commit is contained in:
Colin Liu 2016-02-12 14:21:12 +08:00
parent e15baeb4a2
commit df85543337
9 changed files with 330 additions and 404 deletions

View File

@ -17,9 +17,37 @@
Icon="Images\app.png"
AllowsTransparency="True"
Visibility="{Binding IsVisible,Converter={converters:VisibilityConverter}}"
PreviewKeyDown="Window_PreviewKeyDown"
>
<Window.InputBindings>
<KeyBinding Key="Esc" Command="{Binding EscCommand}"></KeyBinding>
<KeyBinding Key="Tab" Command="{Binding SelectNextItemCommand}"></KeyBinding>
<KeyBinding Key="N" Modifiers="Ctrl" Command="{Binding SelectNextItemCommand}"></KeyBinding>
<KeyBinding Key="J" Modifiers="Ctrl" Command="{Binding SelectNextItemCommand}"></KeyBinding>
<KeyBinding Key="Tab" Modifiers="Shift" Command="{Binding SelectPrevItemCommand}"></KeyBinding>
<KeyBinding Key="P" Modifiers="Ctrl" Command="{Binding SelectPrevItemCommand}"></KeyBinding>
<KeyBinding Key="K" Modifiers="Ctrl" Command="{Binding SelectPrevItemCommand}"></KeyBinding>
<KeyBinding Key="O" Modifiers="Ctrl" Command="{Binding CtrlOCommand}"></KeyBinding>
<KeyBinding Key="D" Modifiers="Ctrl" Command="{Binding SelectNextPageCommand}"></KeyBinding>
<KeyBinding Key="U" Modifiers="Ctrl" Command="{Binding SelectPrevPageCommand}"></KeyBinding>
<KeyBinding Key="F1" Command="{Binding StartHelpCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Shift" Command="{Binding ShiftEnterCommand}"></KeyBinding>
<KeyBinding Key="Enter" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Ctrl" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Alt" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="D1" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="0"></KeyBinding>
<KeyBinding Key="D2" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="1"></KeyBinding>
<KeyBinding Key="D3" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="2"></KeyBinding>
<KeyBinding Key="D4" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="3"></KeyBinding>
<KeyBinding Key="D5" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="4"></KeyBinding>
<KeyBinding Key="D6" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="5"></KeyBinding>
</Window.InputBindings>
<Window.Resources>
<DataTemplate DataType="{x:Type vm:ResultPanelViewModel}">

View File

@ -1,40 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media.Animation;
using NHotkey;
using NHotkey.Wpf;
using Wox.Core.Plugin;
using Wox.Core.Resource;
using Wox.Core.Updater;
using Wox.Core.UserSettings;
using Wox.Helper;
using Wox.Infrastructure;
using Wox.Infrastructure.Hotkey;
using Wox.Plugin;
using Wox.Storage;
using Application = System.Windows.Application;
using ContextMenu = System.Windows.Forms.ContextMenu;
using DataFormats = System.Windows.DataFormats;
using DragEventArgs = System.Windows.DragEventArgs;
using IDataObject = System.Windows.IDataObject;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MenuItem = System.Windows.Forms.MenuItem;
using MessageBox = System.Windows.MessageBox;
using Stopwatch = Wox.Infrastructure.Stopwatch;
using ToolTip = System.Windows.Controls.ToolTip;
using Wox.ViewModel;
using Wox.Plugin;
namespace Wox
{
@ -59,7 +40,6 @@ namespace Wox
//pnlResult.ItemDropEvent += pnlResult_ItemDropEvent;
Closing += MainWindow_Closing;
}
//void pnlResult_ItemDropEvent(Result result, IDataObject dropDataObject, DragEventArgs args)
@ -173,20 +153,6 @@ namespace Wox
if (e.ChangedButton == MouseButton.Left) DragMove();
}
private void ShowWox(bool selectAll = true)
{
//UserSettingStorage.Instance.IncreaseActivateTimes();
//Left = GetWindowsLeft();
//Top = GetWindowsTop();
//Show();
//Activate();
//Focus();
//tbQuery.Focus();
//ResetQueryHistoryIndex();
//if (selectAll) tbQuery.SelectAll();
}
private void MainWindow_OnDeactivated(object sender, EventArgs e)
{
if (UserSettingStorage.Instance.HideWhenDeactive)
@ -196,114 +162,49 @@ namespace Wox
}
}
//private void TbQuery_OnPreviewKeyDown(object sender, KeyEventArgs e)
//{
// //when alt is pressed, the real key should be e.SystemKey
// Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
// switch (key)
// {
// case Key.Escape:
// if (IsInContextMenuMode)
// {
// BackToResultMode();
// }
// else
// {
// HideWox();
// }
// e.Handled = true;
// break;
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
//The code here is to supress the conflict of Window.InputBinding and ListBox native Down/Up Key handle
var vm = this.DataContext as MainViewModel;
//when alt is pressed, the real key should be e.SystemKey
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
switch (key)
{
case Key.Down:
if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
{
vm.DisplayNextQueryCommand.Execute(null);
}
else
{
vm.SelectNextItemCommand.Execute(null);
}
e.Handled = true;
break;
// case Key.Tab:
// if (GlobalHotkey.Instance.CheckModifiers().ShiftPressed)
// {
// SelectPrevItem();
// }
// else
// {
// SelectNextItem();
// }
// e.Handled = true;
// break;
// case Key.N:
// case Key.J:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// SelectNextItem();
// }
// break;
// case Key.P:
// case Key.K:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// SelectPrevItem();
// }
// break;
// case Key.O:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// if (IsInContextMenuMode)
// {
// BackToResultMode();
// }
// else
// {
// ShowContextMenu(GetActiveResult());
// }
// }
// break;
// case Key.Down:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// DisplayNextQuery();
// }
// else
// {
// SelectNextItem();
// }
// e.Handled = true;
// break;
// case Key.Up:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// DisplayPrevQuery();
// }
// else
// {
// SelectPrevItem();
// }
// e.Handled = true;
// break;
// case Key.D:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// pnlResult.SelectNextPage();
// }
// break;
// case Key.PageDown:
// pnlResult.SelectNextPage();
// e.Handled = true;
// break;
// case Key.U:
// if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
// {
// pnlResult.SelectPrevPage();
// }
// break;
// case Key.PageUp:
// pnlResult.SelectPrevPage();
// e.Handled = true;
// break;
case Key.Up:
if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
{
vm.DisplayPrevQueryCommand.Execute(null);
}
else
{
vm.SelectPrevItemCommand.Execute(null);
}
e.Handled = true;
break;
case Key.PageDown:
vm.SelectNextPageCommand.Execute(null);
e.Handled = true;
break;
case Key.PageUp:
vm.SelectPrevPageCommand.Execute(null);
e.Handled = true;
break;
}
}
//TODO: Colin - Figure out how to raise BackKeyDownEvent?
// case Key.Back:
// if (BackKeyDownEvent != null)
// {
@ -315,144 +216,6 @@ namespace Wox
// }
// break;
// case Key.F1:
// Process.Start("http://doc.getwox.com");
// break;
// case Key.Enter:
// Result activeResult = GetActiveResult();
// if (GlobalHotkey.Instance.CheckModifiers().ShiftPressed)
// {
// ShowContextMenu(activeResult);
// }
// else
// {
// SelectResult(activeResult);
// }
// e.Handled = true;
// break;
// case Key.D1:
// SelectItem(1);
// break;
// case Key.D2:
// SelectItem(2);
// break;
// case Key.D3:
// SelectItem(3);
// break;
// case Key.D4:
// SelectItem(4);
// break;
// case Key.D5:
// SelectItem(5);
// break;
// case Key.D6:
// SelectItem(6);
// break;
// }
//}
//private void DisplayPrevQuery()
//{
// var prev = QueryHistoryStorage.Instance.Previous();
// DisplayQueryHistory(prev);
//}
//private void DisplayNextQuery()
//{
// var nextQuery = QueryHistoryStorage.Instance.Next();
// DisplayQueryHistory(nextQuery);
//}
//private void DisplayQueryHistory(HistoryItem history)
//{
// if (history != null)
// {
// var historyMetadata = QueryHistoryStorage.MetaData;
// ChangeQueryText(history.Query, true);
// var executeQueryHistoryTitle = GetTranslation("executeQuery");
// var lastExecuteTime = GetTranslation("lastExecuteTime");
// pnlResult.RemoveResultsExcept(historyMetadata);
// UpdateResultViewInternal(new List<Result>
// {
// new Result
// {
// Title = string.Format(executeQueryHistoryTitle,history.Query),
// SubTitle = string.Format(lastExecuteTime,history.ExecutedDateTime),
// IcoPath = "Images\\history.png",
// PluginDirectory = WoxDirectroy.Executable,
// Action = _ =>{
// ChangeQuery(history.Query,true);
// return false;
// }
// }
// }, historyMetadata);
// }
//}
//private void SelectItem(int index)
//{
// int zeroBasedIndex = index - 1;
// SpecialKeyState keyState = GlobalHotkey.Instance.CheckModifiers();
// if (keyState.AltPressed || keyState.CtrlPressed)
// {
// List<Result> visibleResults = pnlResult.GetVisibleResults();
// if (zeroBasedIndex < visibleResults.Count)
// {
// SelectResult(visibleResults[zeroBasedIndex]);
// }
// }
//}
//private bool IsInContextMenuMode
//{
// get { return pnlContextMenu.Visibility == Visibility.Visible; }
//}
//private Result GetActiveResult()
//{
// if (IsInContextMenuMode)
// {
// return pnlContextMenu.GetActiveResult();
// }
// else
// {
// return pnlResult.GetActiveResult();
// }
//}
//private void SelectPrevItem()
//{
// if (IsInContextMenuMode)
// {
// pnlContextMenu.SelectPrev();
// }
// else
// {
// pnlResult.SelectPrev();
// }
// toolTip.IsOpen = false;
//}
//private void SelectNextItem()
//{
// if (IsInContextMenuMode)
// {
// pnlContextMenu.SelectNext();
// }
// else
// {
// pnlResult.SelectNext();
// }
// toolTip.IsOpen = false;
//}
private void MainWindow_OnDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
@ -468,6 +231,7 @@ namespace Wox
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidWoxPluginFileFormat"));
}
}
e.Handled = false;
}
private void TbQuery_OnPreviewDragOver(object sender, DragEventArgs e)

View File

@ -56,6 +56,7 @@ namespace Wox
{
this.MainVM.QueryText = query;
//TODO: Colin - Adjust CaretIndext
//Application.Current.Dispatcher.Invoke(() =>
//{
@ -71,6 +72,7 @@ namespace Wox
{
this.MainVM.QueryText = query;
//TODO: Colin - Select all text
//Application.Current.Dispatcher.Invoke(() =>
//{
@ -216,7 +218,7 @@ namespace Wox
UserSettingStorage.Instance.IncreaseActivateTimes();
this.MainVM.IsVisible = true;
//TODO:Adjust window properties
//TODO: Colin - Adjust window properties
//Left = GetWindowsLeft();
//Top = GetWindowsTop();

View File

@ -9,7 +9,7 @@
<ListBox x:Name="lbResults" MaxHeight="{Binding MaxHeight}" SelectedItem="{Binding SelectedResult}"
HorizontalContentAlignment="Stretch" ItemsSource="{Binding Results}" Margin="{Binding Margin}"
Style="{DynamicResource BaseListboxStyle}" SelectionChanged="lbResults_SelectionChanged" Focusable="False"
KeyboardNavigation.DirectionalNavigation="Cycle" SelectionMode="Single"
KeyboardNavigation.DirectionalNavigation="Cycle" SelectionMode="Single" Drop="ListBoxItem_OnDrop"
VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard">
<ListBox.ItemTemplate>
<DataTemplate>

View File

@ -18,7 +18,6 @@ namespace Wox
public partial class ResultPanel : UserControl
{
public event Action<Result, IDataObject, DragEventArgs> ItemDropEvent;
private readonly object _resultsUpdateLock = new object();
public void AddResults(List<Result> newResults, string resultId)
{
@ -77,54 +76,6 @@ namespace Wox
}
public void SelectNext()
{
int index = lbResults.SelectedIndex;
if (index == lbResults.Items.Count - 1)
{
index = -1;
}
Select(index + 1);
}
public void SelectPrev()
{
int index = lbResults.SelectedIndex;
if (index == 0)
{
index = lbResults.Items.Count;
}
Select(index - 1);
}
private void SelectFirst()
{
Select(0);
}
private void Select(int index)
{
if (index >= 0 && index < lbResults.Items.Count)
{
lbResults.SelectedItem = lbResults.Items.GetItemAt(index);
}
}
public List<Result> GetVisibleResults()
{
List<Result> visibleElements = new List<Result>();
VirtualizingStackPanel virtualizingStackPanel = GetInnerStackPanel(lbResults);
for (int i = (int)virtualizingStackPanel.VerticalOffset; i <= virtualizingStackPanel.VerticalOffset + virtualizingStackPanel.ViewportHeight; i++)
{
ListBoxItem item = lbResults.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
if (item != null)
{
visibleElements.Add(item.DataContext as Result);
}
}
return visibleElements;
}
private void UpdateItemNumber()
{
//VirtualizingStackPanel virtualizingStackPanel = GetInnerStackPanel(lbResults);
@ -146,51 +97,6 @@ namespace Wox
//}
}
private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
private VirtualizingStackPanel GetInnerStackPanel(FrameworkElement element)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
if (child == null) continue;
if (child is VirtualizingStackPanel) return child as VirtualizingStackPanel;
var panel = GetInnerStackPanel(child);
if (panel != null)
return panel;
}
return null;
}
public Result GetActiveResult()
{
int index = lbResults.SelectedIndex;
if (index < 0) return null;
return lbResults.Items[index] as Result;
}
public ResultPanel()
{
InitializeComponent();
@ -208,28 +114,6 @@ namespace Wox
}
}
public void SelectNextPage()
{
int index = lbResults.SelectedIndex;
index += 5;
if (index >= lbResults.Items.Count)
{
index = lbResults.Items.Count - 1;
}
Select(index);
}
public void SelectPrevPage()
{
int index = lbResults.SelectedIndex;
index -= 5;
if (index < 0)
{
index = 0;
}
Select(index);
}
private void ListBoxItem_OnDrop(object sender, DragEventArgs e)
{
var item = ItemsControl.ContainerFromElement(lbResults, e.OriginalSource as DependencyObject) as ListBoxItem;

View File

@ -25,9 +25,9 @@ namespace Wox.ViewModel
public class RelayCommand : ICommand
{
private Action _action;
private Action<object> _action;
public RelayCommand(Action action)
public RelayCommand(Action<object> action)
{
this._action = action;
}
@ -43,7 +43,7 @@ namespace Wox.ViewModel
{
if (null != this._action)
{
this._action();
this._action(parameter);
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -185,13 +186,73 @@ namespace Wox.ViewModel
set;
}
public ICommand SelectNextItemCommand
{
get;
set;
}
public ICommand SelectPrevItemCommand
{
get;
set;
}
public ICommand CtrlOCommand
{
get;
set;
}
public ICommand DisplayNextQueryCommand
{
get;
set;
}
public ICommand DisplayPrevQueryCommand
{
get;
set;
}
public ICommand SelectNextPageCommand
{
get;
set;
}
public ICommand SelectPrevPageCommand
{
get;
set;
}
public ICommand StartHelpCommand
{
get;
set;
}
public ICommand ShiftEnterCommand
{
get;
set;
}
public ICommand OpenResultCommand
{
get;
set;
}
#endregion
#region Private Methods
private void InitializeKeyCommands()
{
this.EscCommand = new RelayCommand(() => {
this.EscCommand = new RelayCommand((parameter) => {
if (this.IsActionPanelVisible)
{
@ -203,6 +264,97 @@ namespace Wox.ViewModel
}
});
this.SelectNextItemCommand = new RelayCommand((parameter) => {
if (this.IsActionPanelVisible)
{
this._actionPanel.SelectNextResult();
}
else
{
this._searchResultPanel.SelectNextResult();
}
});
this.SelectPrevItemCommand = new RelayCommand((parameter) => {
if (this.IsActionPanelVisible)
{
this._actionPanel.SelectPrevResult();
}
else
{
this._searchResultPanel.SelectPrevResult();
}
});
this.CtrlOCommand = new RelayCommand((parameter) => {
if (this.IsActionPanelVisible)
{
BackToSearchMode();
}
else
{
ShowActionPanel(this._searchResultPanel.SelectedResult.RawResult);
}
});
this.DisplayNextQueryCommand = new RelayCommand((parameter) => {
var nextQuery = QueryHistoryStorage.Instance.Next();
DisplayQueryHistory(nextQuery);
});
this.DisplayPrevQueryCommand = new RelayCommand((parameter) => {
var prev = QueryHistoryStorage.Instance.Previous();
DisplayQueryHistory(prev);
});
this.SelectNextPageCommand = new RelayCommand((parameter) => {
this._searchResultPanel.SelectNextPage();
});
this.SelectPrevPageCommand = new RelayCommand((parameter) => {
this._searchResultPanel.SelectPrevPage();
});
this.StartHelpCommand = new RelayCommand((parameter) => {
Process.Start("http://doc.getwox.com");
});
this.ShiftEnterCommand = new RelayCommand((parameter) => {
if (!this.IsActionPanelVisible && null != this._searchResultPanel.SelectedResult)
{
this.ShowActionPanel(this._searchResultPanel.SelectedResult.RawResult);
}
});
this.OpenResultCommand = new RelayCommand((parameter) => {
if(null != parameter)
{
var index = int.Parse(parameter.ToString());
this._searchResultPanel.SelectResult(index);
}
if (null != this._searchResultPanel.SelectedResult)
{
this._searchResultPanel.SelectedResult.OpenResultCommand.Execute(null);
}
});
}
private void InitializeResultPanel()
@ -406,7 +558,7 @@ namespace Wox.ViewModel
private void UpdateResultViewInternal(List<Result> list, PluginMetadata metadata)
{
Stopwatch.Normal($"UI update cost for {metadata.Name}",
Infrastructure.Stopwatch.Normal($"UI update cost for {metadata.Name}",
() => { this._searchResultPanel.AddResults(list, metadata.ID); });
}
@ -417,6 +569,38 @@ namespace Wox.ViewModel
this.IsSearchResultPanelVisible = true;
}
private void DisplayQueryHistory(HistoryItem history)
{
if (history != null)
{
var historyMetadata = QueryHistoryStorage.MetaData;
this.QueryText = history.Query;
//TODO: Need to select all text
var executeQueryHistoryTitle = InternationalizationManager.Instance.GetTranslation("executeQuery");
var lastExecuteTime = InternationalizationManager.Instance.GetTranslation("lastExecuteTime");
this._searchResultPanel.RemoveResultsExcept(historyMetadata);
UpdateResultViewInternal(new List<Result>
{
new Result
{
Title = string.Format(executeQueryHistoryTitle,history.Query),
SubTitle = string.Format(lastExecuteTime,history.ExecutedDateTime),
IcoPath = "Images\\history.png",
PluginDirectory = WoxDirectroy.Executable,
Action = _ =>{
this.QueryText = history.Query;
//TODO: Need to select all text
return false;
}
}
}, historyMetadata);
}
}
#endregion
#region Public Methods

View File

@ -25,7 +25,7 @@ namespace Wox.ViewModel
{
this._result = result;
this.OpenResultCommand = new RelayCommand(() => {
this.OpenResultCommand = new RelayCommand((parameter) => {
bool hideWindow = result.Action(new ActionContext
{
@ -38,7 +38,7 @@ namespace Wox.ViewModel
}
});
this.OpenResultActionPanelCommand = new RelayCommand(()=> {
this.OpenResultActionPanelCommand = new RelayCommand((parameter) => {
if(null!= ResultActionPanelOpened)
{

View File

@ -124,6 +124,70 @@ namespace Wox.ViewModel
#region Public Methods
public void SelectResult(int index)
{
if(index <= this.Results.Count - 1)
{
this.SelectedResult = this.Results[index];
}
}
public void SelectNextResult()
{
if (null != this.SelectedResult)
{
var index = this.Results.IndexOf(this.SelectedResult);
if(index == this.Results.Count - 1)
{
index = -1;
}
this.SelectedResult = this.Results.ElementAt(index + 1);
}
}
public void SelectPrevResult()
{
if (null != this.SelectedResult)
{
var index = this.Results.IndexOf(this.SelectedResult);
if (index == 0)
{
index = this.Results.Count;
}
this.SelectedResult = this.Results.ElementAt(index - 1);
}
}
public void SelectNextPage()
{
var index = 0;
if (null != this.SelectedResult)
{
index = this.Results.IndexOf(this.SelectedResult);
}
index += 5;
if (index > this.Results.Count - 1)
{
index = this.Results.Count - 1;
}
this.SelectedResult = this.Results.ElementAt(index);
}
public void SelectPrevPage()
{
var index = 0;
if (null != this.SelectedResult)
{
index = this.Results.IndexOf(this.SelectedResult);
}
index -= 5;
if (index < 0)
{
index = 0;
}
this.SelectedResult = this.Results.ElementAt(index);
}
public void Clear()
{
this._results.Clear();