Merge branch 'MoreResponsibleUI'

This commit is contained in:
qianlifeng 2014-02-22 16:28:23 +08:00
commit 2309d30909
11 changed files with 271 additions and 358 deletions

View File

@ -11,7 +11,7 @@
<ColumnDefinition Width="150"></ColumnDefinition> <ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="120"></ColumnDefinition> <ColumnDefinition Width="120"></ColumnDefinition>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBox x:Name="tbHotkey" AcceptsTab="False" IsTabStop="False" TabIndex="100" VerticalContentAlignment="Center" Grid.Column="0" PreviewKeyDown="TbHotkey_OnPreviewKeyDown"></TextBox> <TextBox x:Name="tbHotkey" TabIndex="100" VerticalContentAlignment="Center" Grid.Column="0" PreviewKeyDown="TbHotkey_OnPreviewKeyDown"></TextBox>
<TextBlock x:Name="tbMsg" Visibility="Hidden" Margin="5 0 0 0" VerticalAlignment="Center" Grid.Column="1" ></TextBlock> <TextBlock x:Name="tbMsg" Visibility="Hidden" Margin="5 0 0 0" VerticalAlignment="Center" Grid.Column="1" ></TextBlock>
</Grid> </Grid>
</UserControl> </UserControl>

55
Wox/ImagePathConverter.cs Normal file
View File

@ -0,0 +1,55 @@
using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Wox
{
public class ImagePathConverter : IMultiValueConverter
{
private static ImageSource GetIcon(string fileName)
{
Icon icon = Icon.ExtractAssociatedIcon(fileName);
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
new Int32Rect(0, 0, icon.Width, icon.Height),
BitmapSizeOptions.FromEmptyOptions());
}
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] == null) return null;
string path = values[0].ToString();
string pluginDirectory = values[1].ToString();
string resolvedPath = string.Empty;
if (!string.IsNullOrEmpty(path) && path.Contains(":\\") && File.Exists(path))
{
resolvedPath = path;
}
else if (!string.IsNullOrEmpty(path) && File.Exists(pluginDirectory + path))
{
resolvedPath = pluginDirectory + path;
}
if (resolvedPath.ToLower().EndsWith(".exe") || resolvedPath.ToLower().EndsWith(".lnk"))
{
return GetIcon(resolvedPath);
}
if(!string.IsNullOrEmpty(path)) return new BitmapImage(new Uri(resolvedPath));
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@ -30,8 +30,9 @@ namespace Wox
public partial class MainWindow public partial class MainWindow
{ {
private static readonly object locker = new object(); private static readonly object locker = new object();
private readonly GloablHotkey globalHotkey = new GloablHotkey();
private static readonly List<Result> waitShowResultList = new List<Result>();
private readonly GloablHotkey globalHotkey = new GloablHotkey();
private readonly KeyboardSimulator keyboardSimulator = new KeyboardSimulator(new InputSimulator()); private readonly KeyboardSimulator keyboardSimulator = new KeyboardSimulator(new InputSimulator());
private readonly Storyboard progressBarStoryboard = new Storyboard(); private readonly Storyboard progressBarStoryboard = new Storyboard();
private bool WinRStroked; private bool WinRStroked;
@ -43,7 +44,7 @@ namespace Wox
InitializeComponent(); InitializeComponent();
InitialTray(); InitialTray();
resultCtrl.resultItemChangedEvent += resultCtrl_resultItemChangedEvent;
ThreadPool.SetMaxThreads(30, 10); ThreadPool.SetMaxThreads(30, 10);
InitProgressbarAnimation(); InitProgressbarAnimation();
try try
@ -54,17 +55,14 @@ namespace Wox
{ {
SetTheme(CommonStorage.Instance.UserSetting.Theme = "Default"); SetTheme(CommonStorage.Instance.UserSetting.Theme = "Default");
} }
Closing += MainWindow_Closing;
} }
public void SetHotkey(string hotkeyStr,EventHandler<HotkeyEventArgs> action) public void SetHotkey(string hotkeyStr, EventHandler<HotkeyEventArgs> action)
{ {
HotkeyModel hotkey = new HotkeyModel(hotkeyStr); var hotkey = new HotkeyModel(hotkeyStr);
try try
{ {
HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys,action); HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys, action);
} }
catch (Exception) catch (Exception)
{ {
@ -74,15 +72,19 @@ namespace Wox
public void RemoveHotkey(string hotkeyStr) public void RemoveHotkey(string hotkeyStr)
{ {
HotkeyManager.Current.Remove(hotkeyStr); if (!string.IsNullOrEmpty(hotkeyStr))
{
HotkeyManager.Current.Remove(hotkeyStr);
}
} }
private void SetCustomPluginHotkey() private void SetCustomPluginHotkey()
{ {
if (CommonStorage.Instance.UserSetting.CustomPluginHotkeys == null) return;
foreach (CustomPluginHotkey hotkey in CommonStorage.Instance.UserSetting.CustomPluginHotkeys) foreach (CustomPluginHotkey hotkey in CommonStorage.Instance.UserSetting.CustomPluginHotkeys)
{ {
CustomPluginHotkey hotkey1 = hotkey; CustomPluginHotkey hotkey1 = hotkey;
SetHotkey(hotkey.Hotkey,delegate SetHotkey(hotkey.Hotkey, delegate
{ {
ShowApp(); ShowApp();
ChangeQuery(hotkey1.ActionKeyword); ChangeQuery(hotkey1.ActionKeyword);
@ -103,18 +105,13 @@ namespace Wox
e.Handled = true; e.Handled = true;
} }
private void MainWindow_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
}
private void WakeupApp() private void WakeupApp()
{ {
//After hide wox in the background for a long time. It will become very slow in the next show. //After hide wox in the background for a long time. It will become very slow in the next show.
//This is caused by the Virtual Mermory Page Mechanisam. So, our solution is execute some codes in every min //This is caused by the Virtual Mermory Page Mechanisam. So, our solution is execute some codes in every min
//which may prevent sysetem uninstall memory from RAM to disk. //which may prevent sysetem uninstall memory from RAM to disk.
var t = new Timer(1000 * 60 * 5) { AutoReset = true, Enabled = true }; var t = new Timer(1000*60*5) {AutoReset = true, Enabled = true};
t.Elapsed += (o, e) => Dispatcher.Invoke(new Action(() => t.Elapsed += (o, e) => Dispatcher.Invoke(new Action(() =>
{ {
if (Visibility != Visibility.Visible) if (Visibility != Visibility.Visible)
@ -144,23 +141,16 @@ namespace Wox
private void InitialTray() private void InitialTray()
{ {
notifyIcon = new NotifyIcon { Text = "Wox", Icon = Properties.Resources.app, Visible = true }; notifyIcon = new NotifyIcon {Text = "Wox", Icon = Properties.Resources.app, Visible = true};
notifyIcon.Click += (o, e) => ShowWox(); notifyIcon.Click += (o, e) => ShowWox();
var open = new MenuItem("Open"); var open = new MenuItem("Open");
open.Click += (o, e) => ShowWox(); open.Click += (o, e) => ShowWox();
var exit = new MenuItem("Exit"); var exit = new MenuItem("Exit");
exit.Click += (o, e) => CloseApp(); exit.Click += (o, e) => CloseApp();
MenuItem[] childen = { open, exit }; MenuItem[] childen = {open, exit};
notifyIcon.ContextMenu = new ContextMenu(childen); notifyIcon.ContextMenu = new ContextMenu(childen);
} }
private void resultCtrl_resultItemChangedEvent()
{
resultCtrl.Margin = resultCtrl.GetCurrentResultCount() > 0
? new Thickness { Top = grid.Margin.Top }
: new Thickness { Top = 0 };
}
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e) private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{ {
resultCtrl.Dirty = true; resultCtrl.Dirty = true;
@ -243,12 +233,12 @@ namespace Wox
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{ {
Left = (SystemParameters.PrimaryScreenWidth - ActualWidth) / 2; Left = (SystemParameters.PrimaryScreenWidth - ActualWidth)/2;
Top = (SystemParameters.PrimaryScreenHeight - ActualHeight) / 3; Top = (SystemParameters.PrimaryScreenHeight - ActualHeight)/3;
SetHotkey(CommonStorage.Instance.UserSetting.Hotkey,OnHotkey); SetHotkey(CommonStorage.Instance.UserSetting.Hotkey, OnHotkey);
SetCustomPluginHotkey(); SetCustomPluginHotkey();
WakeupApp(); //WakeupApp();
Plugins.Init(); Plugins.Init();
globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback; globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
@ -259,13 +249,13 @@ namespace Wox
if (CommonStorage.Instance.UserSetting.ReplaceWinR) if (CommonStorage.Instance.UserSetting.ReplaceWinR)
{ {
//todo:need refatoring. move those codes to CMD file or expose events //todo:need refatoring. move those codes to CMD file or expose events
if (keyevent == KeyEvent.WM_KEYDOWN && vkcode == (int)Keys.R && state.WinPressed) if (keyevent == KeyEvent.WM_KEYDOWN && vkcode == (int) Keys.R && state.WinPressed)
{ {
WinRStroked = true; WinRStroked = true;
Dispatcher.BeginInvoke(new Action(OnWinRPressed)); Dispatcher.BeginInvoke(new Action(OnWinRPressed));
return false; return false;
} }
if (keyevent == KeyEvent.WM_KEYUP && WinRStroked && vkcode == (int)Keys.LWin) if (keyevent == KeyEvent.WM_KEYUP && WinRStroked && vkcode == (int) Keys.LWin)
{ {
WinRStroked = false; WinRStroked = false;
keyboardSimulator.ModifiedKeyStroke(VirtualKeyCode.LWIN, VirtualKeyCode.CONTROL); keyboardSimulator.ModifiedKeyStroke(VirtualKeyCode.LWIN, VirtualKeyCode.CONTROL);
@ -341,13 +331,21 @@ namespace Wox
}); });
lock (locker) lock (locker)
{ {
resultCtrl.Dispatcher.Invoke(new Action(() => waitShowResultList.AddRange(list);
{
List<Result> l =
list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text).ToList();
resultCtrl.AddResults(list);
}));
} }
Dispatcher.DelayInvoke("ShowResult", k => resultCtrl.Dispatcher.Invoke(new Action(() =>
{
int t1 = Environment.TickCount;
List<Result> l =
waitShowResultList.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text)
.ToList();
waitShowResultList.Clear();
resultCtrl.AddResults(l);
Debug.WriteLine("Total Time:" + (Environment.TickCount - t1) + " Count:" + l.Count);
})), TimeSpan.FromMilliseconds(50));
} }
} }
@ -373,6 +371,7 @@ namespace Wox
public void CloseApp() public void CloseApp()
{ {
notifyIcon.Visible = false; notifyIcon.Visible = false;
Close();
Environment.Exit(0); Environment.Exit(0);
} }
@ -388,7 +387,7 @@ namespace Wox
public void ShowMsg(string title, string subTitle, string iconPath) public void ShowMsg(string title, string subTitle, string iconPath)
{ {
var m = new Msg { Owner = GetWindow(this) }; var m = new Msg {Owner = GetWindow(this)};
m.Show(title, subTitle, iconPath); m.Show(title, subTitle, iconPath);
} }

View File

@ -1,26 +0,0 @@
<UserControl x:Class="Wox.ResultItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignWidth="400"
x:Name="resultItemControl"
Style="{DynamicResource ItemStyle}"
Height="50">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5" Cursor="Hand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"></ColumnDefinition>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" ></Image>
<Grid Margin="5 0 5 0" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition x:Name="SubTitleRowDefinition"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Style="{DynamicResource ItemTitleStyle}" VerticalAlignment="Center" x:Name="tbTitle">Title</TextBlock>
<TextBlock Style="{DynamicResource ItemSubTitleStyle}" Grid.Row="1" x:Name="tbSubTitle">sub title</TextBlock>
</Grid>
</Grid>
</UserControl>

View File

@ -1,105 +0,0 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Wox.Annotations;
using Wox.Helper;
using Wox.Infrastructure;
using Wox.Plugin;
using Brush = System.Windows.Media.Brush;
namespace Wox
{
public partial class ResultItem : UserControl, INotifyPropertyChanged
{
private bool selected;
public Result Result { get; private set; }
public bool Selected
{
get
{
return selected;
}
set
{
selected = value;
OnPropertyChanged("Selected");
}
}
public ResultItem(Result result)
{
InitializeComponent();
Result = result;
tbTitle.Text = result.Title;
tbSubTitle.Text = result.SubTitle;
if (string.IsNullOrEmpty(result.SubTitle))
{
SubTitleRowDefinition.Height = new GridLength(0);
}
string path = string.Empty;
if (!string.IsNullOrEmpty(result.IcoPath) && result.IcoPath.Contains(":\\") && File.Exists(result.IcoPath))
{
path = result.IcoPath;
}
else if (!string.IsNullOrEmpty(result.IcoPath) && File.Exists(result.PluginDirectory + result.IcoPath))
{
path = result.PluginDirectory + result.IcoPath;
}
if (!string.IsNullOrEmpty(path))
{
if (path.ToLower().EndsWith(".exe") || path.ToLower().EndsWith(".lnk"))
{
imgIco.Source = GetIcon(path);
}
else
{
imgIco.Source = new BitmapImage(new Uri(path));
}
}
AddHandler(MouseLeftButtonUpEvent, new RoutedEventHandler((o, e) =>
{
if (Result.Action != null)
Result.Action(new ActionContext()
{
SpecialKeyState = new GloablHotkey().CheckModifiers()
});
CommonStorage.Instance.UserSelectedRecords.Add(result);
if (!result.DontHideWoxAfterSelect)
{
App.Window.HideApp();
}
e.Handled = true;
}));
}
private static ImageSource GetIcon(string fileName)
{
Icon icon = Icon.ExtractAssociatedIcon(fileName);
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
new Int32Rect(0, 0, icon.Width, icon.Height),
BitmapSizeOptions.FromEmptyOptions());
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -3,9 +3,55 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wox="clr-namespace:Wox"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"> d:DesignHeight="300" d:DesignWidth="300">
<ScrollViewer x:Name="sv" Template="{DynamicResource ScrollViewerControlTemplate}" MaxHeight="300" VerticalScrollBarVisibility="Auto"> <UserControl.Resources>
<StackPanel x:Name="pnlContainer"/> <wox:ImagePathConverter x:Key="ImagePathConverter"/>
</ScrollViewer> </UserControl.Resources>
<Grid x:Name="gridContainer">
<ListBox x:Name="lbResults" Style="{DynamicResource listboxStyle}" SelectionChanged ="lbResults_SelectionChanged" Focusable="False" KeyboardNavigation.DirectionalNavigation="Cycle" SelectionMode="Single" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListBox.Resources>
<!--SelectedItem with focus-->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{DynamicResource ResultItemHighlightBackgroundColor}"/>
<!--SelectedItem without focus-->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{DynamicResource ResultItemHighlightBackgroundColor}"/>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Height="40" VerticalAlignment="Stretch" Margin="5" Cursor="Hand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"></ColumnDefinition>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" >
<Image.Source>
<MultiBinding Converter="{StaticResource ImagePathConverter}">
<MultiBinding.Bindings>
<Binding Path="IcoPath" />
<Binding Path="PluginDirectory" />
</MultiBinding.Bindings>
</MultiBinding>
</Image.Source>
</Image>
<Grid Margin="5 0 5 0" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto" x:Name="SubTitleRowDefinition"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Style="{DynamicResource ItemTitleStyle}" VerticalAlignment="Center" x:Name="tbTitle" Text="{Binding Title}"></TextBlock>
<TextBlock Style="{DynamicResource ItemSubTitleStyle}" Visibility="{Binding SubTitle, Converter={wox:StringNullOrEmptyToVisibilityConverter}}" Grid.Row="1" x:Name="tbSubTitle" Text="{Binding SubTitle}"></TextBlock>
</Grid>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="tbTitle" Property="Style" Value="{DynamicResource ItemTitleSelectedStyle}"/>
<Setter TargetName="tbSubTitle" Property="Style" Value="{DynamicResource ItemSubTitleSelectedStyle}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl> </UserControl>

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System;
using System.Linq; using System.Collections.Generic;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using Wox.Helper; using Wox.Helper;
@ -12,70 +13,37 @@ namespace Wox
{ {
public bool Dirty { get; set; } public bool Dirty { get; set; }
public delegate void ResultItemsChanged();
public event ResultItemsChanged resultItemChangedEvent;
protected virtual void OnResultItemChangedEvent()
{
ResultItemsChanged handler = resultItemChangedEvent;
if (handler != null) handler();
}
public void AddResults(List<Result> results) public void AddResults(List<Result> results)
{ {
if (results.Count == 0) return;
if (Dirty) if (Dirty)
{ {
Dirty = false; Dirty = false;
pnlContainer.Children.Clear(); lbResults.Items.Clear();
} }
foreach (var result in results)
for (int i = 0; i < results.Count; i++)
{ {
Result result = results[i]; int position = GetInsertLocation(result.Score);
if (!CheckExisted(result)) lbResults.Items.Insert(position, result);
{
ResultItem control = new ResultItem(result);
pnlContainer.Children.Insert(GetInsertLocation(result.Score), control);
}
} }
gridContainer.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 };
SelectFirst(); SelectFirst();
pnlContainer.UpdateLayout();
double resultItemHeight = 0;
if (pnlContainer.Children.Count > 0)
{
var resultItem = pnlContainer.Children[0] as ResultItem;
if (resultItem != null)
resultItemHeight = resultItem.ActualHeight;
}
pnlContainer.Height = pnlContainer.Children.Count * resultItemHeight;
OnResultItemChangedEvent();
}
private bool CheckExisted(Result result)
{
return pnlContainer.Children.Cast<ResultItem>().Any(child => child.Result.Equals(result));
} }
private int GetInsertLocation(int currentScore) private int GetInsertLocation(int currentScore)
{ {
int location = pnlContainer.Children.Count; int location = lbResults.Items.Count;
if (pnlContainer.Children.Count == 0) return 0; if (lbResults.Items.Count == 0) return 0;
if (currentScore > ((ResultItem)pnlContainer.Children[0]).Result.Score) return 0; if (currentScore > ((Result)lbResults.Items[0]).Score) return 0;
for (int index = 1; index < pnlContainer.Children.Count; index++) for (int index = 1; index < lbResults.Items.Count; index++)
{ {
ResultItem next = pnlContainer.Children[index] as ResultItem; Result next = lbResults.Items[index] as Result;
ResultItem prev = pnlContainer.Children[index - 1] as ResultItem; Result prev = lbResults.Items[index - 1] as Result;
if (next != null && prev != null) if (next != null && prev != null)
{ {
if ((currentScore >= next.Result.Score && currentScore <= prev.Result.Score)) if ((currentScore >= next.Score && currentScore <= prev.Score))
{ {
if (currentScore == next.Result.Score) if (currentScore == next.Score)
{ {
location = index + 1; location = index + 1;
} }
@ -90,40 +58,10 @@ namespace Wox
return location; return location;
} }
public int GetCurrentResultCount()
{
return pnlContainer.Children.Count;
}
public int GetCurrentSelectedResultIndex()
{
for (int i = 0; i < pnlContainer.Children.Count; i++)
{
var resultItemControl = pnlContainer.Children[i] as ResultItem;
if (resultItemControl != null && resultItemControl.Selected)
{
return i;
}
}
return -1;
}
public void UnSelectAll()
{
for (int i = 0; i < pnlContainer.Children.Count; i++)
{
var resultItemControl = pnlContainer.Children[i] as ResultItem;
if (resultItemControl != null && resultItemControl.Selected)
{
resultItemControl.Selected = false;
}
}
}
public void SelectNext() public void SelectNext()
{ {
int index = GetCurrentSelectedResultIndex(); int index = lbResults.SelectedIndex;
if (index == pnlContainer.Children.Count - 1) if (index == lbResults.Items.Count - 1)
{ {
index = -1; index = -1;
} }
@ -132,95 +70,44 @@ namespace Wox
public void SelectPrev() public void SelectPrev()
{ {
int index = GetCurrentSelectedResultIndex(); int index = lbResults.SelectedIndex;
if (index == 0) if (index == 0)
{ {
index = pnlContainer.Children.Count; index = lbResults.Items.Count;
} }
Select(index - 1); Select(index - 1);
} }
private void Select(int index) private void SelectFirst()
{
if (pnlContainer.Children.Count > 0)
{
int oldIndex = GetCurrentSelectedResultIndex();
UnSelectAll();
var resultItemControl = pnlContainer.Children[index] as ResultItem;
if (resultItemControl != null)
{
resultItemControl.Selected = true;
double scrollPosition = 0;
Point newItemBottomPoint = resultItemControl.TranslatePoint(new Point(0, resultItemControl.ActualHeight), pnlContainer);
scrollPosition = newItemBottomPoint.Y;
if (index == 0)
{
sv.ScrollToTop();
return;
}
if (index == pnlContainer.Children.Count - 1)
{
sv.ScrollToBottom();
return;
}
if (index < oldIndex)
{
//move up and old item is at the top of the scroll view
var scrollPostionY = sv.VerticalOffset - sv.VerticalOffset%resultItemControl.ActualHeight +
resultItemControl.ActualHeight;
if (newItemBottomPoint.Y - scrollPostionY == 0)
{
scrollPosition = sv.VerticalOffset - resultItemControl.ActualHeight;
}
else
{
return;
}
}
else
{
//move down and old item is at the bottom of scroll view
double scrollPostionY = (sv.ActualHeight + sv.VerticalOffset) - (sv.ActualHeight + sv.VerticalOffset)%resultItemControl.ActualHeight;
if (scrollPostionY == newItemBottomPoint.Y - resultItemControl.ActualHeight)
{
scrollPosition = newItemBottomPoint.Y - sv.ActualHeight;
}
else
{
return;
}
}
sv.ScrollToVerticalOffset(scrollPosition);
}
}
}
public void SelectFirst()
{ {
Select(0); Select(0);
} }
private void Select(int index)
{
if (index >= 0 && index < lbResults.Items.Count)
{
lbResults.SelectedItem = lbResults.Items.GetItemAt(index);
}
}
public Result AcceptSelect() public Result AcceptSelect()
{ {
int index = GetCurrentSelectedResultIndex(); int index = lbResults.SelectedIndex;
if (index < 0) return null; if (index < 0) return null;
var resultItemControl = pnlContainer.Children[index] as ResultItem; var result = lbResults.Items[index] as Result;
if (resultItemControl != null) if (result != null)
{ {
if (resultItemControl.Result.Action != null) if (result.Action != null)
{ {
resultItemControl.Result.Action(new ActionContext() result.Action(new ActionContext()
{ {
SpecialKeyState = new GloablHotkey().CheckModifiers() SpecialKeyState = new GloablHotkey().CheckModifiers()
}); });
} }
return resultItemControl.Result; return result;
} }
return null; return null;
@ -233,9 +120,16 @@ namespace Wox
public void Clear() public void Clear()
{ {
pnlContainer.Children.Clear(); lbResults.Items.Clear();
pnlContainer.Height = 0; gridContainer.Margin = new Thickness { Top = 0 };
OnResultItemChangedEvent(); }
private void lbResults_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
lbResults.ScrollIntoView(e.AddedItems[0]);
}
} }
} }
} }

View File

@ -0,0 +1,26 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace Wox
{
public class StringNullOrEmptyToVisibilityConverter : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.IsNullOrEmpty(value as string) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@ -30,16 +30,35 @@
<Setter Property="FontSize" Value="16" /> <Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Medium" /> <Setter Property="FontWeight" Value="Medium" />
</Style> </Style>
<Style x:Key="ItemSubTitleStyle" TargetType="{x:Type TextBlock}"> <Style x:Key="ItemSubTitleStyle" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#D9D9D4" /> <Setter Property="Foreground" Value="#D9D9D4" />
</Style> </Style>
<Style x:Key="ItemStyle" TargetType="{x:Type UserControl}"> <Style x:Key="ItemTitleSelectedStyle" TargetType="{x:Type TextBlock}" >
<Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="#FFFFF8" />
<Style.Triggers> <Setter Property="FontSize" Value="16" />
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Selected}" Value="true"> <Setter Property="FontWeight" Value="Medium" />
<Setter Property="Background" Value="#4F6180" /> </Style>
</DataTrigger> <Style x:Key="ItemSubTitleSelectedStyle" TargetType="{x:Type TextBlock}" >
</Style.Triggers> <Setter Property="Foreground" Value="#D9D9D4" />
</Style>
<Color x:Key="ResultItemHighlightBackgroundColor">#4F6180</Color>
<Style x:Key="listboxStyle" TargetType="{x:Type ListBox}">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer Focusable="false" Template="{DynamicResource ScrollViewerControlTemplate}">
<StackPanel IsItemsHost="True" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </Style>
<!-- ScrollViewer Style --> <!-- ScrollViewer Style -->

View File

@ -23,32 +23,42 @@
<Setter Property="Stroke" Value="Blue"></Setter> <Setter Property="Stroke" Value="Blue"></Setter>
</Style> </Style>
<!-- Item Style --> <!-- Item Style -->
<Style x:Key="ItemTitleStyle" TargetType="{x:Type TextBlock}" > <Style x:Key="ItemTitleStyle" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#141411"></Setter> <Setter Property="Foreground" Value="#141411"></Setter>
<Setter Property="FontSize" Value="16"></Setter> <Setter Property="FontSize" Value="16"></Setter>
<Setter Property="FontWeight" Value="Medium"></Setter> <Setter Property="FontWeight" Value="Medium"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=resultItemControl, Path=Selected}" Value="true">
<Setter Property="Foreground" Value="#F6F6FF"></Setter>
</DataTrigger>
</Style.Triggers>
</Style> </Style>
<Style x:Key="ItemSubTitleStyle" TargetType="{x:Type TextBlock}" > <Style x:Key="ItemSubTitleStyle" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#B3B2B0"></Setter> <Setter Property="Foreground" Value="#B3B2B0"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=resultItemControl, Path=Selected}" Value="true">
<Setter Property="Foreground" Value="#F6F6FF"></Setter>
</DataTrigger>
</Style.Triggers>
</Style> </Style>
<Style x:Key="ItemStyle" TargetType="{x:Type UserControl}" > <Style x:Key="ItemTitleSelectedStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="Transparent"></Setter> <Setter Property="Foreground" Value="#F6F6FF" />
<Style.Triggers> <Setter Property="FontSize" Value="16"></Setter>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Selected}" Value="true"> <Setter Property="FontWeight" Value="Medium"></Setter>
<Setter Property="Background" Value="#543BFD"></Setter> </Style>
</DataTrigger> <Style x:Key="ItemSubTitleSelectedStyle" TargetType="{x:Type TextBlock}">
</Style.Triggers> <Setter Property="Foreground" Value="#F6F6FF" />
</Style>
<Color x:Key="ResultItemHighlightBackgroundColor">#543BFD</Color>
<Style x:Key="listboxStyle" TargetType="{x:Type ListBox}">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer Focusable="false" Template="{DynamicResource ScrollViewerControlTemplate}">
<StackPanel IsItemsHost="True" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </Style>
<!-- ScrollViewer Style --> <!-- ScrollViewer Style -->
@ -123,4 +133,4 @@
</Setter> </Setter>
</Style> </Style>
</ResourceDictionary> </ResourceDictionary>

View File

@ -135,6 +135,7 @@
<Compile Include="HotkeyControl.xaml.cs"> <Compile Include="HotkeyControl.xaml.cs">
<DependentUpon>HotkeyControl.xaml</DependentUpon> <DependentUpon>HotkeyControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="ImagePathConverter.cs" />
<Compile Include="Msg.xaml.cs"> <Compile Include="Msg.xaml.cs">
<DependentUpon>Msg.xaml</DependentUpon> <DependentUpon>Msg.xaml</DependentUpon>
</Compile> </Compile>
@ -147,12 +148,10 @@
<Compile Include="ResultPanel.xaml.cs"> <Compile Include="ResultPanel.xaml.cs">
<DependentUpon>ResultPanel.xaml</DependentUpon> <DependentUpon>ResultPanel.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="ResultItem.xaml.cs">
<DependentUpon>ResultItem.xaml</DependentUpon>
</Compile>
<Compile Include="SettingWindow.xaml.cs"> <Compile Include="SettingWindow.xaml.cs">
<DependentUpon>SettingWindow.xaml</DependentUpon> <DependentUpon>SettingWindow.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="StringNullOrEmptyToVisibilityConverter.cs" />
<Compile Include="WebSearchSetting.xaml.cs"> <Compile Include="WebSearchSetting.xaml.cs">
<DependentUpon>WebSearchSetting.xaml</DependentUpon> <DependentUpon>WebSearchSetting.xaml</DependentUpon>
</Compile> </Compile>
@ -184,10 +183,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="ResultItem.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SettingWindow.xaml"> <Page Include="SettingWindow.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>