Skip to content

Commit

Permalink
Merge pull request #2 from emoacht/develop
Browse files Browse the repository at this point in the history
Added notification area icon
  • Loading branch information
emoacht committed Nov 18, 2015
2 parents 7ebe4e9 + b1f872d commit 6be2871
Show file tree
Hide file tree
Showing 11 changed files with 647 additions and 10 deletions.
4 changes: 4 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
##History

Ver 1.1.1 2015-11-18

- Added flyout to notification area icon

Ver 1.1.0 2015-11-13

- Switched from internal NativeWifi to ManagedNativeWifi
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ WLAN Profile Viewer is a Windows desktop app to manage wireless LAN profiles. It

##Download

[Download](https://github.com/emoacht/WlanProfileViewer/releases/download/1.1.0/WlanProfileViewer110.zip)
[Download](https://github.com/emoacht/WlanProfileViewer/releases/download/1.1.1/WlanProfileViewer111.zip)

##Install

Expand Down
2 changes: 1 addition & 1 deletion README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ WLAN Profile Viewerは無線LANプロファイルを管理するためのWindows

##ダウンロード

[ダウンロード](https://github.com/emoacht/WlanProfileViewer/releases/download/1.1.0/WlanProfileViewer110.zip)
[ダウンロード](https://github.com/emoacht/WlanProfileViewer/releases/download/1.1.1/WlanProfileViewer111.zip)

##インストール

Expand Down
4 changes: 2 additions & 2 deletions WlanProfileViewer/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.4")]
[assembly: AssemblyFileVersion("1.1.0.4")]
[assembly: AssemblyVersion("1.1.1.6")]
[assembly: AssemblyFileVersion("1.1.1.6")]
67 changes: 67 additions & 0 deletions WlanProfileViewer/ViewModels/NotifyWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using Reactive.Bindings.Helpers;

using WlanProfileViewer.Common;
using WlanProfileViewer.Views;

namespace WlanProfileViewer.ViewModels
{
public class NotifyWindowViewModel : BindableDisposableBase
{
private readonly MainWindow _mainWindow;

private ReadOnlyReactiveCollection<ProfileItemViewModel> Profiles { get; }

public ListCollectionView ProfilesView
{
get
{
if (_profilesView == null)
{
_profilesView = new ListCollectionView(Profiles);
_profilesView.Filter = x => ((ProfileItemViewModel)x).IsConnected.Value;
_profilesView.SortDescriptions.Add(new SortDescription(nameof(ProfileItemViewModel.InterfaceDescription), ListSortDirection.Ascending));
}

return _profilesView;
}
}
private ListCollectionView _profilesView;

public ReadOnlyReactiveProperty<bool> IsAnyConnected { get; }

public NotifyWindowViewModel(Window ownerWindow)
{
this._mainWindow = ownerWindow as MainWindow;
if (this._mainWindow == null)
throw new ArgumentException(nameof(ownerWindow));

var mainWindowViewModel = this._mainWindow.DataContext as MainWindowViewModel;

this.Profiles = mainWindowViewModel.Profiles;

IsAnyConnected = this.Profiles
.ObserveElementObservableProperty(x => x.IsConnected)
.ObserveOnUIDispatcher()
.Select(_ =>
{
this.ProfilesView.Refresh();
return (this.ProfilesView.Count > 0);
})
.ToReadOnlyReactiveProperty()
.AddTo(this.Subscription);

mainWindowViewModel.ReloadCommand.Execute();
}
}
}
72 changes: 66 additions & 6 deletions WlanProfileViewer/Views/NotifyIconComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace WlanProfileViewer.Views
public class NotifyIconComponent : Component
{
private readonly Window _ownerWindow;
private readonly IContainer _container;
private readonly Container _container;
private readonly NotifyIcon _notifyIcon;

public NotifyIconComponent(Window ownerWindow)
Expand All @@ -22,7 +22,13 @@ public NotifyIconComponent(Window ownerWindow)

this._ownerWindow = ownerWindow;
this._container = new Container();
this._notifyIcon = new NotifyIcon(this._container);
this._notifyIcon = new NotifyIcon(this._container)
{
ContextMenuStrip = new ContextMenuStrip()
};

_notifyIcon.MouseClick += OnMouseClick;
_notifyIcon.MouseDoubleClick += OnMouseDoubleClick;
}

#region Dispose
Expand Down Expand Up @@ -73,6 +79,8 @@ public float Dpi

#endregion

#region Icon

private void SetIcon(System.Drawing.Icon icon, float dpi)
{
if ((icon == null) || (dpi == 0F))
Expand Down Expand Up @@ -129,16 +137,36 @@ public void ShowIcon(System.Drawing.Icon icon, string text = null, float dpi = _
this.Dpi = dpi;

_notifyIcon.Visible = true;
_notifyIcon.MouseClick += OnMouseClick;
_notifyIcon.MouseDoubleClick += OnMouseClick;
}

#endregion

#region Click

private void OnMouseClick(object sender, MouseEventArgs e)
{
ShowWindow();
if (e.Button == MouseButtons.Right)
{
ShowNotifyWindow();
}
else
{
ShowOwnerWindow();
}
}

private void OnMouseDoubleClick(object sender, MouseEventArgs e)
{
ShowOwnerWindow();
}

private void ShowWindow()
private void ShowNotifyWindow()
{
var window = new NotifyWindow(_ownerWindow, GetClickedPoint());
window.Show();
}

private void ShowOwnerWindow()
{
if (_ownerWindow.WindowState == WindowState.Minimized)
{
Expand All @@ -152,5 +180,37 @@ private void ShowWindow()
_ownerWindow.WindowState = WindowState.Minimized;
}
}

/// <summary>
/// Get the point where NotifyIcon is clicked by the position of ContextMenuStrip and NotifyIcon.
/// </summary>
/// <returns>Cursor location</returns>
/// <remarks>MouseEventArgs.Location property of MouseClick event does not contain data.</remarks>
private Point GetClickedPoint()
{
var contextMenuStrip = _notifyIcon.ContextMenuStrip;

var corners = new Point[]
{
//new Point(contextMenuStrip.Left, contextMenuStrip.Top),
//new Point(contextMenuStrip.Right, contextMenuStrip.Top),
new Point(contextMenuStrip.Left, contextMenuStrip.Bottom),
new Point(contextMenuStrip.Right, contextMenuStrip.Bottom)
};

var notifyIconRect = WindowPosition.GetNotifyIconRect(_notifyIcon);
if (notifyIconRect != Rect.Empty)
{
foreach (var corner in corners)
{
if (notifyIconRect.Contains(corner))
return corner;
}
}

return corners.Last(); // Fallback
}

#endregion
}
}
98 changes: 98 additions & 0 deletions WlanProfileViewer/Views/NotifyWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<Window x:Class="WlanProfileViewer.Views.NotifyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:ma="clr-namespace:MonitorAware.Views;assembly=MonitorAware"
xmlns:controls="clr-namespace:WlanProfileViewer.Views.Controls"
Width="120" Height="120"
MinWidth="120"
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
WindowStyle="None">
<i:Interaction.Behaviors>
<ma:MonitorAwareBehavior/>
</i:Interaction.Behaviors>

<Grid Background="{StaticResource App.Background}">
<StackPanel>
<!-- Connected -->
<Grid Height="30">
<TextBlock x:Name="Connected"
HorizontalAlignment="Center" VerticalAlignment="Center"
Foreground="{StaticResource App.Foreground}"
FontWeight="Bold"
Text="Connected"
Visibility="{Binding IsAnyConnected.Value, Converter={StaticResource BooleanToVisibilityConverterKey}}"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
Foreground="{StaticResource App.Foreground}"
FontWeight="Bold"
Text="Disconnected"
Visibility="{Binding ElementName=Connected, Path=Visibility, Converter={StaticResource VisibilityInverseConverterKey}}"/>
</Grid>

<ListView ItemsSource="{Binding ProfilesView}">
<ListView.Template>
<ControlTemplate TargetType="{x:Type ListView}">
<Border BorderThickness="1">
<ScrollViewer>
<VirtualizingStackPanel IsItemsHost="True"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</ListView.Template>
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="{StaticResource Profile.Connected.Background}"
BorderBrush="{StaticResource App.Background}"
BorderThickness="1">
<StackPanel>
<Grid Height="30">
<Grid Margin="4,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<!-- Signal -->
<controls:SignalProgressBar
Grid.Column="0"
Style="{StaticResource BarStyle}"
Background="{StaticResource Profile.Signal.Background}"
Foreground="{StaticResource Profile.Signal.Foreground}"
Value="{Binding Signal.Value, Mode=OneWay}">
<Control.ToolTip>
<ToolTip DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"
Content="{Binding Value}"
ContentStringFormat="{} {0}%"/>
</Control.ToolTip>
</controls:SignalProgressBar>

<!-- Profile name -->
<TextBlock Grid.Column="1"
Margin="4,0,0,0" VerticalAlignment="Center"
Foreground="{StaticResource App.Foreground}"
FontSize="14"
Text="{Binding Name, Mode=OneTime}"/>
</Grid>
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="0"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</StackPanel>
</Grid>
</Window>
Loading

0 comments on commit 6be2871

Please sign in to comment.