diff options
Diffstat (limited to 'windows/WinUI')
30 files changed, 2502 insertions, 0 deletions
diff --git a/windows/WinUI/APIHandler.cs b/windows/WinUI/APIHandler.cs new file mode 100644 index 00000000..8e7408a5 --- /dev/null +++ b/windows/WinUI/APIHandler.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Net; +using System.IO; +using Newtonsoft.Json; + +namespace WinUI +{ + + + public class APIHandler + { + static string authtoken = "p3ptrzds5jkr2hbx5ipbyf04"; // delete me! + + private string url = null; + + public APIHandler() + { + url = "http://127.0.0.1:9993"; + } + + public APIHandler(string host, int port) + { + url = "http://" + host + ":" + port; + } + + public ZeroTierStatus GetStatus() + { + var request = WebRequest.Create(url + "/status" + "?auth=" + authtoken) as HttpWebRequest; + if (request != null) + { + request.Method = "GET"; + request.ContentType = "application/json"; + } + + var httpResponse = (HttpWebResponse)request.GetResponse(); + using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) + { + var responseText = streamReader.ReadToEnd(); + + ZeroTierStatus status = null; + try + { + status = JsonConvert.DeserializeObject<ZeroTierStatus>(responseText); + } + catch (JsonReaderException e) + { + Console.WriteLine(e.ToString()); + } + return status; + } + } + + public List<ZeroTierNetwork> GetNetworks() + { + var request = WebRequest.Create(url + "/network" + "?auth=" + authtoken) as HttpWebRequest; + if (request == null) + { + return null; + } + + request.Method = "GET"; + request.ContentType = "application/json"; + + var httpResponse = (HttpWebResponse)request.GetResponse(); + using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) + { + var responseText = streamReader.ReadToEnd(); + + List<ZeroTierNetwork> networkList = null; + try + { + networkList = JsonConvert.DeserializeObject<List<ZeroTierNetwork>>(responseText); + } + catch (JsonReaderException e) + { + Console.WriteLine(e.ToString()); + } + return networkList; + } + } + + public void JoinNetwork(string nwid) + { + var request = WebRequest.Create(url + "/network/" + nwid + "?auth=" + authtoken) as HttpWebRequest; + if (request == null) + { + return; + } + + request.Method = "POST"; + + var httpResponse = (HttpWebResponse)request.GetResponse(); + + if (httpResponse.StatusCode != HttpStatusCode.OK) + { + Console.WriteLine("Error sending join network message"); + } + } + + public void LeaveNetwork(string nwid) + { + var request = WebRequest.Create(url + "/network/" + nwid + "?auth=" + authtoken) as HttpWebRequest; + if (request == null) + { + return; + } + + request.Method = "DELETE"; + + var httpResponse = (HttpWebResponse)request.GetResponse(); + + if (httpResponse.StatusCode != HttpStatusCode.OK) + { + Console.WriteLine("Error sending leave network message"); + } + } + + public List<ZeroTierPeer> GetPeers() + { + var request = WebRequest.Create(url + "/peer" + "?auth=" + authtoken) as HttpWebRequest; + if (request == null) + { + return null; + } + + request.Method = "GET"; + request.ContentType = "application/json"; + + var httpResponse = (HttpWebResponse)request.GetResponse(); + using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) + { + var responseText = streamReader.ReadToEnd(); + + List<ZeroTierPeer> peerList = null; + try + { + peerList = JsonConvert.DeserializeObject<List<ZeroTierPeer>>(responseText); + } + catch (JsonReaderException e) + { + Console.WriteLine(e.ToString()); + } + return peerList; + } + } + } +} diff --git a/windows/WinUI/App.config b/windows/WinUI/App.config new file mode 100644 index 00000000..8e156463 --- /dev/null +++ b/windows/WinUI/App.config @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> + </startup> +</configuration>
\ No newline at end of file diff --git a/windows/WinUI/App.xaml b/windows/WinUI/App.xaml new file mode 100644 index 00000000..08b9b792 --- /dev/null +++ b/windows/WinUI/App.xaml @@ -0,0 +1,14 @@ +<Application x:Class="WinUI.App" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + StartupUri="MainWindow.xaml"> + <Application.Resources> + + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <ResourceDictionary Source="Simple Styles.xaml"/> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + + </Application.Resources> +</Application> diff --git a/windows/WinUI/App.xaml.cs b/windows/WinUI/App.xaml.cs new file mode 100644 index 00000000..a97edde7 --- /dev/null +++ b/windows/WinUI/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace WinUI +{ + /// <summary> + /// Interaction logic for App.xaml + /// </summary> + public partial class App : Application + { + } +} diff --git a/windows/WinUI/Fonts/segoeui.ttf b/windows/WinUI/Fonts/segoeui.ttf Binary files differnew file mode 100644 index 00000000..fc18ebd0 --- /dev/null +++ b/windows/WinUI/Fonts/segoeui.ttf diff --git a/windows/WinUI/Fonts/segoeuib.ttf b/windows/WinUI/Fonts/segoeuib.ttf Binary files differnew file mode 100644 index 00000000..5f31e0ca --- /dev/null +++ b/windows/WinUI/Fonts/segoeuib.ttf diff --git a/windows/WinUI/Fonts/segoeuii.ttf b/windows/WinUI/Fonts/segoeuii.ttf Binary files differnew file mode 100644 index 00000000..7efb70d6 --- /dev/null +++ b/windows/WinUI/Fonts/segoeuii.ttf diff --git a/windows/WinUI/Fonts/segoeuiz.ttf b/windows/WinUI/Fonts/segoeuiz.ttf Binary files differnew file mode 100644 index 00000000..d7bb186b --- /dev/null +++ b/windows/WinUI/Fonts/segoeuiz.ttf diff --git a/windows/WinUI/MainWindow.xaml b/windows/WinUI/MainWindow.xaml new file mode 100644 index 00000000..553d44fe --- /dev/null +++ b/windows/WinUI/MainWindow.xaml @@ -0,0 +1,114 @@ +<Window + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:WinUI" + mc:Ignorable="d" x:Class="WinUI.MainWindow" + Title="ZeroTier One" Height="500" Width="700" Icon="ZeroTierIcon.ico"> + + <Window.Resources> + <ResourceDictionary> + <Style TargetType="{x:Type TabItem}"> + <Setter Property="BorderThickness" + Value="3" /> + <Setter Property="BorderBrush" + Value="Blue" /> + <Setter Property="VerticalContentAlignment" + Value="Center" /> + <Setter Property="HorizontalContentAlignment" + Value="Center" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TabItem}"> + <Border> + <Grid> + <Grid> + <Border x:Name="border" + CornerRadius="3,3,0,0" + Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="1,1,1,0" /> + </Grid> + <Border BorderThickness="{TemplateBinding BorderThickness}" + Padding="{TemplateBinding Padding}"> + <ContentPresenter ContentSource="Header" + HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" + VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> + </Border> + </Grid> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsSelected" + Value="True"> + <Setter TargetName="border" + Property="BorderBrush" + Value="#ff91a2a3" /> + <Setter TargetName="border" + Property="BorderThickness" + Value="0,3,0,0" /> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </ResourceDictionary> + </Window.Resources> + + <DockPanel> + <StatusBar DockPanel.Dock="Bottom" Height="34" Background="#FF234447" Margin="0"> + <StatusBar.ItemsPanel> + <ItemsPanelTemplate> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="*"/> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="Auto"/> + </Grid.ColumnDefinitions> + </Grid> + </ItemsPanelTemplate> + </StatusBar.ItemsPanel> + <StatusBarItem Grid.Column="0" x:Name="networkId" Content="Network ID" Foreground="White"/> + <StatusBarItem Grid.Column="1" x:Name="onlineStatus" Content="ONLINE" Foreground="White"/> + <StatusBarItem Grid.Column="2" x:Name="versionString" Content="1.0.5" Foreground="White" Margin="0"/> + <StatusBarItem Grid.Column="3" x:Name="blank" Content="" Height="43" Foreground="White" Margin="6,0,-6,-9"/> + <StatusBarItem Grid.Column="4"> + <TextBox x:Name="joinNetworkID" Height="23" TextWrapping="Wrap" Width="120" HorizontalAlignment="Right" RenderTransformOrigin="1.168,0.478" ToolTip="Enter Network ID" PreviewTextInput="OnNetworkEntered" MaxLength="16"/> + </StatusBarItem> + <StatusBarItem Grid.Column="5" x:Name="statusBarButton" Foreground="White" RenderTransformOrigin="0.789,0.442"> + <Button x:Name="joinButton" Content="Join" Background="#FFFFB354" Width="77.423" Click="joinButton_Click"/> + </StatusBarItem> + </StatusBar> + <TabControl> + <TabItem x:Name="Networks" Header="Networks" Background="#FF234447" Foreground="White" IsSelected="True" IsManipulationEnabled="True"> + <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <local:NetworksPage x:Name="networksPage" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" Grid.Row="0" Margin="0,0,0,0"/> + </Grid> + </TabItem> + <TabItem x:Name="Peers" Header="Peers" Background="#FF234447" Foreground="White"> + <Grid Background="#FFE5E5E5" HorizontalAlignment="Left" VerticalAlignment="Top"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <local:PeersPage x:Name="peersPage" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="0" Grid.Row="0"/> + </Grid> + </TabItem> + </TabControl> + </DockPanel> +</Window> diff --git a/windows/WinUI/MainWindow.xaml.cs b/windows/WinUI/MainWindow.xaml.cs new file mode 100644 index 00000000..f6cb4f44 --- /dev/null +++ b/windows/WinUI/MainWindow.xaml.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Timers; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Threading; + +namespace WinUI +{ + /// <summary> + /// Interaction logic for MainWindow.xaml + /// </summary> + public partial class MainWindow : Window + { + APIHandler handler = new APIHandler(); + Regex charRegex = new Regex("[0-9a-fxA-FX]"); + Regex wholeStringRegex = new Regex("^[0-9a-fxA-FX]+$"); + + Timer timer = new Timer(); + + public MainWindow() + { + InitializeComponent(); + + networksPage.SetAPIHandler(handler); + + updateStatus(); + updateNetworks(); + updatePeers(); + + DataObject.AddPastingHandler(joinNetworkID, OnPaste); + + timer.Elapsed += new ElapsedEventHandler(OnUpdateTimer); + timer.Interval = 2000; + timer.Enabled = true; + } + + private void updateStatus() + { + var status = handler.GetStatus(); + + networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => + { + this.networkId.Content = status.Address; + })); + versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => + { + this.versionString.Content = status.Version; + })); + onlineStatus.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => + { + this.onlineStatus.Content = (status.Online ? "ONLINE" : "OFFLINE"); + })); + } + + private void updateNetworks() + { + var networks = handler.GetNetworks(); + + networksPage.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => + { + networksPage.setNetworks(networks); + })); + } + + private void updatePeers() + { + var peers = handler.GetPeers(); + + peersPage.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => + { + peersPage.SetPeers(peers); + })); + } + + private void OnUpdateTimer(object source, ElapsedEventArgs e) + { + updateStatus(); + updateNetworks(); + updatePeers(); + } + + private void joinButton_Click(object sender, RoutedEventArgs e) + { + if (joinNetworkID.Text.Length < 16) + { + MessageBox.Show("Invalid Network ID"); + } + else + { + handler.JoinNetwork(joinNetworkID.Text); + } + } + + private void OnNetworkEntered(object sender, TextCompositionEventArgs e) + { + e.Handled = !charRegex.IsMatch(e.Text); + } + + private void OnPaste(object sender, DataObjectPastingEventArgs e) + { + var isText = e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true); + if (!isText) return; + + var text = e.SourceDataObject.GetData(DataFormats.UnicodeText) as string; + + if (!wholeStringRegex.IsMatch(text)) + { + e.CancelCommand(); + } + } + } +} diff --git a/windows/WinUI/NetworkInfoView.xaml b/windows/WinUI/NetworkInfoView.xaml new file mode 100644 index 00000000..86f2b98c --- /dev/null +++ b/windows/WinUI/NetworkInfoView.xaml @@ -0,0 +1,63 @@ +<UserControl x:Class="WinUI.NetworkInfoView" + 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" + > + <Grid Background="#FFFFFFFF" Margin="5,0,5,1"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="auto"/> + <ColumnDefinition Width="10"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> + </Grid.RowDefinitions> + + <Grid Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="auto"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + + <TextBlock x:Name="networkId" Text="8056c2e21c000001" HorizontalAlignment="Left" Grid.Column="0" Foreground="#FF91A2A3"/> + <TextBlock x:Name="networkName" Text="earth.zerotier.net" HorizontalAlignment="Right" Grid.Column="1" Foreground="#FF000000"/> + </Grid> + + <TextBlock TextWrapping="Wrap" Text="Status" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="1" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="Type" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="2" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="MAC" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="3" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="MTU" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="4" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="Broadcast" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="5" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="Bridging" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="6" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="Device" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="7" Foreground="#FF000000"/> + <TextBlock TextWrapping="Wrap" Text="Managed IPs" HorizontalAlignment="Right" Grid.Column="0" Grid.Row="8" Foreground="#FF000000"/> + + <TextBlock x:Name="networkStatus" TextWrapping="Wrap" HorizontalAlignment="Right" Text="OK" TextAlignment="Right" Grid.Column="2" Grid.Row="1" Foreground="#FF000000"/> + <TextBlock x:Name="networkType" TextWrapping="Wrap" Text="PUBLIC" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="2" Foreground="#FF000000"/> + <TextBlock x:Name="macAddress" TextWrapping="Wrap" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="3" Foreground="#FF000000"><Span><Run Text="02:83:4a:1e:4b:3a"/></Span></TextBlock> + <TextBlock x:Name="mtu" TextWrapping="Wrap" Text="2800" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="4" Foreground="#FF000000"/> + <TextBlock x:Name="broadcastEnabled" TextWrapping="Wrap" Text="ENABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="5" Foreground="#FF000000"/> + <TextBlock x:Name="bridgingEnabled" TextWrapping="Wrap" Text="DISABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="6" Foreground="#FF000000"/> + <TextBlock x:Name="deviceName" TextWrapping="Wrap" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="7" Foreground="#FF000000"><Span><Run Text="ethernet_32771"/></Span></TextBlock> + <TextBlock x:Name="managedIps" TextWrapping="Wrap" HorizontalAlignment="Right" TextAlignment="Right" Grid.Column="2" Grid.Row="8" Foreground="#FF000000"><Span><Run Text="28.2.169.248/7 "/></Span><LineBreak/><Span><Run Text="fd80:56c2:e21c:0000:0199:9383:4a02:a9f8/88"/></Span></TextBlock> + + <Grid Grid.Column="0" Grid.Row="9" Grid.ColumnSpan="3" Background="#FFFFFFFF"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <Button /> + <Button x:Name="leaveButton" Content="Leave" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="75" Background="#FFFFB354" Click="leaveButton_Click"/> + </Grid> + </Grid> +</UserControl> diff --git a/windows/WinUI/NetworkInfoView.xaml.cs b/windows/WinUI/NetworkInfoView.xaml.cs new file mode 100644 index 00000000..ccdec288 --- /dev/null +++ b/windows/WinUI/NetworkInfoView.xaml.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WinUI +{ + /// <summary> + /// Interaction logic for NetworkInfoView.xaml + /// </summary> + public partial class NetworkInfoView : UserControl + { + private APIHandler handler; + private ZeroTierNetwork network; + + public NetworkInfoView(APIHandler handler, ZeroTierNetwork network) + { + InitializeComponent(); + + this.handler = handler; + this.network = network; + + UpdateNetworkData(); + } + + private void UpdateNetworkData() + { + this.networkId.Text = network.NetworkId; + this.networkName.Text = network.NetworkName; + this.networkStatus.Text = network.NetworkStatus; + this.networkType.Text = network.NetworkType; + this.macAddress.Text = network.MacAddress; + this.mtu.Text = network.MTU.ToString(); + this.broadcastEnabled.Text = (network.BroadcastEnabled ? "ENABLED" : "DISABLED"); + this.bridgingEnabled.Text = (network.Bridge ? "ENABLED" : "DISABLED"); + this.deviceName.Text = network.DeviceName; + + string iplist = ""; + for (int i = 0; i < network.AssignedAddresses.Length; ++i) + { + iplist += network.AssignedAddresses[i]; + if (i < (network.AssignedAddresses.Length - 1)) + iplist += "\n"; + } + + this.managedIps.Text = iplist; + } + + public bool HasNetwork(ZeroTierNetwork network) + { + if (this.network.NetworkId.Equals(network.NetworkId)) + return true; + + return false; + } + + private void leaveButton_Click(object sender, RoutedEventArgs e) + { + handler.LeaveNetwork(network.NetworkId); + } + } +} diff --git a/windows/WinUI/NetworksPage.xaml b/windows/WinUI/NetworksPage.xaml new file mode 100644 index 00000000..f8aec61b --- /dev/null +++ b/windows/WinUI/NetworksPage.xaml @@ -0,0 +1,13 @@ +<UserControl x:Class="WinUI.NetworksPage" + 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:DesignHeight="300" d:DesignWidth="300"> + <ScrollViewer x:Name="MyScrollViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ActualWidth}" Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ActualHeight}"> + <WrapPanel x:Name="wrapPanel" Background="#FF555555" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> + + </WrapPanel> + </ScrollViewer> +</UserControl> diff --git a/windows/WinUI/NetworksPage.xaml.cs b/windows/WinUI/NetworksPage.xaml.cs new file mode 100644 index 00000000..9ded9970 --- /dev/null +++ b/windows/WinUI/NetworksPage.xaml.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WinUI +{ + /// <summary> + /// Interaction logic for NetworksPage.xaml + /// </summary> + public partial class NetworksPage : UserControl + { + private APIHandler handler; + + public NetworksPage() + { + InitializeComponent(); + } + + public void SetAPIHandler(APIHandler handler) + { + this.handler = handler; + } + + public void setNetworks(List<ZeroTierNetwork> networks) + { + this.wrapPanel.Children.Clear(); + + for (int i = 0; i < networks.Count; ++i) + { + this.wrapPanel.Children.Add( + new NetworkInfoView( + handler, + networks.ElementAt<ZeroTierNetwork>(i))); + } + } + } +} diff --git a/windows/WinUI/PeersPage.xaml b/windows/WinUI/PeersPage.xaml new file mode 100644 index 00000000..bf96f5ef --- /dev/null +++ b/windows/WinUI/PeersPage.xaml @@ -0,0 +1,19 @@ +<UserControl x:Class="WinUI.PeersPage" + 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:DesignHeight="300" d:DesignWidth="300" Background="White" Foreground="Black"> + <DataGrid x:Name="dataGrid" AutoGenerateColumns="False" CanUserResizeColumns="True" Margin="0,0,0,0" CanUserReorderColumns="False" Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ActualWidth}" Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ActualHeight}" CanUserSortColumns="False"> + <DataGrid.Columns> + <DataGridTextColumn Header="Address" Binding="{Binding Address}"/> + <DataGridTextColumn Header="Version" Binding="{Binding VersionString}"/> + <DataGridTextColumn Header="Latency" Binding="{Binding Latency}"/> + <DataGridTextColumn Header="Data Paths" Binding="{Binding DataPaths}"/> + <DataGridTextColumn Header="Last Unicast" Binding="{Binding LastUnicastFrame}"/> + <DataGridTextColumn Header="Last Multicast" Binding="{Binding LastMulticastFrame}"/> + <DataGridTextColumn Header="Role" Binding="{Binding Role}"/> + </DataGrid.Columns> + </DataGrid> +</UserControl> diff --git a/windows/WinUI/PeersPage.xaml.cs b/windows/WinUI/PeersPage.xaml.cs new file mode 100644 index 00000000..b1dd8adf --- /dev/null +++ b/windows/WinUI/PeersPage.xaml.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WinUI +{ + /// <summary> + /// Interaction logic for PeersPage.xaml + /// </summary> + public partial class PeersPage : UserControl + { + private List<ZeroTierPeer> peersList = new List<ZeroTierPeer>(); + + public PeersPage() + { + InitializeComponent(); + + dataGrid.ItemsSource = peersList; + } + + public void SetPeers(List<ZeroTierPeer> peerList) + { + this.peersList = peerList; + dataGrid.ItemsSource = this.peersList; + dataGrid.Items.Refresh(); + } + } +} diff --git a/windows/WinUI/Properties/AssemblyInfo.cs b/windows/WinUI/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..9c7cd133 --- /dev/null +++ b/windows/WinUI/Properties/AssemblyInfo.cs @@ -0,0 +1,56 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ZeroTier One")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ZeroTier, Inc")] +[assembly: AssemblyProduct("ZeroTier One")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file +//inside a <PropertyGroup>. For example, if you are using US english +//in your source files, set the <UICulture> to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// 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.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/windows/WinUI/Properties/Resources.Designer.cs b/windows/WinUI/Properties/Resources.Designer.cs new file mode 100644 index 00000000..57a56f7d --- /dev/null +++ b/windows/WinUI/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WinUI.Properties +{ + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WinUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/windows/WinUI/Properties/Resources.resx b/windows/WinUI/Properties/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/windows/WinUI/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/windows/WinUI/Properties/Settings.Designer.cs b/windows/WinUI/Properties/Settings.Designer.cs new file mode 100644 index 00000000..6812cccd --- /dev/null +++ b/windows/WinUI/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WinUI.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/windows/WinUI/Properties/Settings.settings b/windows/WinUI/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/windows/WinUI/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> +</SettingsFile>
\ No newline at end of file diff --git a/windows/WinUI/Simple Styles.xaml b/windows/WinUI/Simple Styles.xaml new file mode 100644 index 00000000..f2ddedf9 --- /dev/null +++ b/windows/WinUI/Simple Styles.xaml @@ -0,0 +1,1121 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/interactivedesigner/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> + + <!-- SimpleStyles.XAML defines a set of control styles which are simplified starting points for creating your own controls --> + + <!-- Brushes : These are used to define the color for background, foreground, selection, enabled etc of all controls + If you want to change the color of a control you can just chnage the brush; if you want to add a new shape or change arrangement then also edit the template --> + + <!-- NormalBrush is used as the Background for SimpleButton, SimpleRepeatButton --> + <LinearGradientBrush x:Key="NormalBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#EEE" Offset="0.0"/> + <GradientStop Color="#CCC" Offset="1.0"/> + </LinearGradientBrush> + <LinearGradientBrush x:Key="NormalBorderBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#CCC" Offset="0.0"/> + <GradientStop Color="#444" Offset="1.0"/> + </LinearGradientBrush> + + <!-- LightBrush is used for content areas such as Menu, Tab Control background --> + <LinearGradientBrush x:Key="LightBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#FFF" Offset="0.0"/> + <GradientStop Color="#EEE" Offset="1.0"/> + </LinearGradientBrush> + + <!-- MouseOverBrush is used for MouseOver in Button, Radio Button, CheckBox --> + <LinearGradientBrush x:Key="MouseOverBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#FFF" Offset="0.0"/> + <GradientStop Color="#AAA" Offset="1.0"/> + </LinearGradientBrush> + + <!-- PressedBrush is used for Pressed in Button, Radio Button, CheckBox --> + <LinearGradientBrush x:Key="PressedBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#BBB" Offset="0.0"/> + <GradientStop Color="#EEE" Offset="0.1"/> + <GradientStop Color="#EEE" Offset="0.9"/> + <GradientStop Color="#FFF" Offset="1.0"/> + </LinearGradientBrush> + <LinearGradientBrush x:Key="PressedBorderBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#444" Offset="0.0"/> + <GradientStop Color="#888" Offset="1.0"/> + </LinearGradientBrush> + + <!-- SelectedBackgroundBrush is used for the Selected item in ListBoxItem, ComboBoxItem--> + <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD"/> + + <!-- Disabled Brushes are used for the Disabled look of each control --> + <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888"/> + <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE"/> + <SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA"/> + + <!-- Used for background of ScrollViewer, TreeView, ListBox, Expander, TextBox, Tab Control --> + <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF"/> + + <!-- DefaultedBorderBrush is used to show KeyBoardFocus --> + <LinearGradientBrush x:Key="DefaultedBorderBrush" EndPoint="0,1" StartPoint="0,0"> + <GradientStop Color="#777" Offset="0.0"/> + <GradientStop Color="#000" Offset="1.0"/> + </LinearGradientBrush> + + <SolidColorBrush x:Key="SolidBorderBrush" Color="#888"/> + <SolidColorBrush x:Key="LightBorderBrush" Color="#AAA"/> + <SolidColorBrush x:Key="LightColorBrush" Color="#DDD"/> + + <!-- Used for Checkmark, Radio button, TreeViewItem, Expander ToggleButton glyphs --> + <SolidColorBrush x:Key="GlyphBrush" Color="#444"/> + + + <!-- Style and Template pairs are used to define each control Part --> + <!-- The Style provides default values on the control; the Template gives the elements for each control --> + + <!-- SimpleButtonFocusVisual is used to show keyboard focus around a SimpleButton control --> + <Style x:Key="SimpleButtonFocusVisual"> + <Setter Property="Control.Template"> + <Setter.Value> + <ControlTemplate> + <Border> + <Rectangle Margin="2" Stroke="#60000000" StrokeThickness="1" StrokeDashArray="1 2"/> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Button - This control sets brushes on each state. Note that these brushes must be listed above since they are static resources --> + <Style x:Key="SimpleButton" TargetType="{x:Type Button}" BasedOn="{x:Null}"> + <Setter Property="FocusVisualStyle" Value="{DynamicResource SimpleButtonFocusVisual}"/> + <Setter Property="Background" Value="{DynamicResource NormalBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Button}"> + + <!-- We use Grid as a root because it is easy to add more elements to customize the button --> + <Grid x:Name="Grid"> + <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"/> + + <!-- Content Presenter is where the text content etc is placed by the control --> + <!-- The bindings are useful so that the control can be parameterized without editing the template --> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> + </Grid> + + <!--Each state sets a brush on the Border in the template --> + <ControlTemplate.Triggers> + <Trigger Property="IsKeyboardFocused" Value="true"> + <Setter Property="BorderBrush" Value="{DynamicResource DefaultedBorderBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsMouseOver" Value="true"> + <Setter Property="Background" Value="{DynamicResource MouseOverBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsPressed" Value="true"> + <Setter Property="Background" Value="{DynamicResource PressedBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource PressedBorderBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsEnabled" Value="true"/> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="RadioButtonFocusVisual"> + <Setter Property="Control.Template"> + <Setter.Value> + <ControlTemplate> + <Border> + <Rectangle Margin="15,0,0,0" Stroke="#60000000" StrokeThickness="1" StrokeDashArray="1 2"/> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="CheckBoxFocusVisual"> + <Setter Property="Control.Template"> + <Setter.Value> + <ControlTemplate> + <Border> + <Rectangle Margin="15,0,0,0" Stroke="#60000000" StrokeThickness="1" StrokeDashArray="1 2"/> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple CheckBox --> + <Style x:Key="SimpleCheckBox" TargetType="{x:Type CheckBox}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="FocusVisualStyle" Value="{DynamicResource CheckBoxFocusVisual}"/> + <Setter Property="Background" Value="{DynamicResource NormalBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type CheckBox}"> + + <!-- BulletDecorator is used to provide baseline alignment between the checkmark and the Content --> + <BulletDecorator Background="Transparent"> + <BulletDecorator.Bullet> + <Grid Width="13" Height="13"> + <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> + <Path x:Name="CheckMark" Stroke="{DynamicResource GlyphBrush}" StrokeThickness="2" SnapsToDevicePixels="False" Data="M 0 0 L 13 13 M 0 13 L 13 0"/> + </Grid> + </BulletDecorator.Bullet> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> + </BulletDecorator> + + <!-- This uses Visibility to hide and show the CheckMark on IsChecked --> + <ControlTemplate.Triggers> + <Trigger Property="IsChecked" Value="false"> + <Setter Property="Visibility" Value="Collapsed" TargetName="CheckMark"/> + </Trigger> + <Trigger Property="IsMouseOver" Value="true"> + <Setter Property="Background" Value="{DynamicResource MouseOverBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsPressed" Value="true"> + <Setter Property="Background" Value="{DynamicResource PressedBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource PressedBorderBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + </Trigger> + </ControlTemplate.Triggers> + + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Radio Button --> + <Style x:Key="SimpleRadioButton" TargetType="{x:Type RadioButton}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="FocusVisualStyle" Value="{DynamicResource RadioButtonFocusVisual}"/> + <Setter Property="Background" Value="{DynamicResource NormalBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type RadioButton}"> + + <!-- BulletDecorator is used to provide baseline alignment between the checkmark and the Content --> + <BulletDecorator Background="Transparent"> + <BulletDecorator.Bullet> + <Grid Width="13" Height="13"> + <Ellipse x:Name="Ellipse_Border" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="1"/> + <Ellipse Margin="4" x:Name="CheckMark" Fill="{DynamicResource GlyphBrush}"/> + </Grid> + </BulletDecorator.Bullet> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> + </BulletDecorator> + + <ControlTemplate.Triggers> + <Trigger Property="IsChecked" Value="false"> + <Setter Property="Visibility" Value="Collapsed" TargetName="CheckMark"/> + </Trigger> + <Trigger Property="IsMouseOver" Value="true"> + <Setter Property="Fill" Value="{DynamicResource MouseOverBrush}" TargetName="Ellipse_Border"/> + </Trigger> + <Trigger Property="IsPressed" Value="true"> + <Setter Property="Fill" Value="{DynamicResource PressedBrush}" TargetName="Ellipse_Border"/> + <Setter Property="Stroke" Value="{DynamicResource GlyphBrush}" TargetName="Ellipse_Border"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Fill" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Ellipse_Border"/> + <Setter Property="Stroke" Value="#40000000" TargetName="Ellipse_Border"/> + <Setter Property="Foreground" Value="#80000000"/> + </Trigger> + + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Repeat Button - This is used by Simple ScrollBar for the up and down buttons --> + <Style x:Key="SimpleRepeatButton" d:IsControlPart="True" TargetType="{x:Type RepeatButton}" BasedOn="{x:Null}"> + <Setter Property="Background" Value="{DynamicResource NormalBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type RepeatButton}"> + <Grid> + <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> + <ContentPresenter HorizontalAlignment="Center" x:Name="ContentPresenter" VerticalAlignment="Center" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsKeyboardFocused" Value="true"> + <Setter Property="BorderBrush" Value="{DynamicResource DefaultedBorderBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsMouseOver" Value="true"> + <Setter Property="Background" Value="{DynamicResource MouseOverBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsPressed" Value="true"> + <Setter Property="Background" Value="{DynamicResource PressedBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource PressedBorderBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Thumb - The Thumb is the draggable part of the Scrollbar --> + <Style x:Key="SimpleThumbStyle" d:IsControlPart="True" TargetType="{x:Type Thumb}" BasedOn="{x:Null}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Thumb}"> + <Grid Margin="0,0,0,0" x:Name="Grid"> + <Rectangle HorizontalAlignment="Stretch" x:Name="Rectangle" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="2" RadiusY="2" Fill="{DynamicResource NormalBrush}" Stroke="{DynamicResource NormalBorderBrush}"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsFocused" Value="True"/> + <Trigger Property="IsMouseOver" Value="True"/> + <Trigger Property="IsEnabled" Value="False"/> + <Trigger Property="IsDragging" Value="True"/> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ScrollRepeatButton Style - This RepeatButton is used above and below the Thumb in the Scrollbar. They are set to transparent si that they do not show over the scrollbar --> + <Style x:Key="SimpleScrollRepeatButtonStyle" d:IsControlPart="True" TargetType="{x:Type RepeatButton}"> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="BorderBrush" Value="Transparent"/> + <Setter Property="IsTabStop" Value="false"/> + <Setter Property="Focusable" Value="false"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type RepeatButton}"> + <Grid> + <Rectangle Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"/> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ScrollBar This makes use of SimpleThumb, SimpleRepeatButton and SimpleScrollRepeatButton --> + + <Style x:Key="SimpleScrollBar" TargetType="{x:Type ScrollBar}"> + <Setter Property="Stylus.IsFlicksEnabled" Value="false"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ScrollBar}"> + <Grid x:Name="GridRoot" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Background="{TemplateBinding Background}"> + <Grid.RowDefinitions> + <RowDefinition MaxHeight="18"/> + <RowDefinition Height="0.00001*"/> + <RowDefinition MaxHeight="18"/> + </Grid.RowDefinitions> + + <RepeatButton x:Name="DecreaseRepeat" Style="{DynamicResource SimpleRepeatButton}" Command="ScrollBar.LineUpCommand"> + <Grid> + <Path x:Name="DecreaseArrow" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Data="M 0 4 L 8 4 L 4 0 Z"/> + </Grid> + </RepeatButton> + + <!-- Track is a special layout container which sizes the thumb and the repeat button which do jump scrolling either side of it --> + <Track Grid.Row="1" x:Name="PART_Track" Orientation="Vertical" IsDirectionReversed="true"> + <Track.Thumb> + <Thumb Style="{DynamicResource SimpleThumbStyle}"/> + </Track.Thumb> + <Track.IncreaseRepeatButton> + <RepeatButton x:Name="PageUp" Style="{DynamicResource SimpleScrollRepeatButtonStyle}" Command="ScrollBar.PageDownCommand"/> + </Track.IncreaseRepeatButton> + <Track.DecreaseRepeatButton> + <RepeatButton x:Name="PageDown" Style="{DynamicResource SimpleScrollRepeatButtonStyle}" Command="ScrollBar.PageUpCommand"/> + </Track.DecreaseRepeatButton> + </Track> + + <RepeatButton Grid.Row="2" x:Name="IncreaseRepeat" Style="{DynamicResource SimpleRepeatButton}" Command="ScrollBar.LineDownCommand"> + <Grid> + <Path x:Name="IncreaseArrow" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Data="M 0 0 L 4 4 L 8 0 Z"/> + </Grid> + </RepeatButton> + </Grid> + + <!-- This uses a single template for ScrollBar and rotate it to be Horizontal + It also changes the commands so that the it does Left and Right instead of Up and Down Commands --> + <ControlTemplate.Triggers> + <Trigger Property="Orientation" Value="Horizontal"> + + <!-- Rotate the ScrollBar from Vertical to Horizontal --> + <Setter Property="LayoutTransform" TargetName="GridRoot"> + <Setter.Value> + <RotateTransform Angle="-90"/> + </Setter.Value> + </Setter> + + <!-- Track is bound to Orientation internally, so we need to rotate it back to Vertical --> + <Setter TargetName="PART_Track" Property="Orientation" Value="Vertical"/> + + <!-- Change the commands to do Horizontal commands --> + <Setter Property="Command" Value="ScrollBar.LineLeftCommand" TargetName="DecreaseRepeat"/> + <Setter Property="Command" Value="ScrollBar.LineRightCommand" TargetName="IncreaseRepeat"/> + <Setter Property="Command" Value="ScrollBar.PageLeftCommand" TargetName="PageDown"/> + <Setter Property="Command" Value="ScrollBar.PageRightCommand" TargetName="PageUp"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ScrollViewer + ScrollViewer is a Grid control which has a ContentPresenter and a Horizontal and Vertical ScrollBar + It is used by ListBox, MenuItem, ComboBox, and TreeView --> + <Style x:Key="SimpleScrollViewer" TargetType="{x:Type ScrollViewer}" BasedOn="{x:Null}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ScrollViewer}"> + <Grid Background="{TemplateBinding Background}"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*"/> + <ColumnDefinition Width="Auto"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="*"/> + <RowDefinition Height="Auto"/> + </Grid.RowDefinitions> + <ScrollContentPresenter Grid.Column="0" Grid.Row="0" Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" CanContentScroll="{TemplateBinding CanContentScroll}"/> + + <!-- The visibility of the ScrollBars is controlled by the implementation fo the control --> + <ScrollBar Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Column="0" Grid.Row="1" x:Name="PART_HorizontalScrollBar" Style="{DynamicResource SimpleScrollBar}" Orientation="Horizontal" Value="{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Minimum="0" Maximum="{TemplateBinding ScrollableWidth}" /> + <ScrollBar Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Column="1" Grid.Row="0" x:Name="PART_VerticalScrollBar" Style="{DynamicResource SimpleScrollBar}" Orientation="Vertical" Value="{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Minimum="0" Maximum="{TemplateBinding ScrollableHeight}" /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ListBox - This uses SimpleScrollViewer to allow items to be scrolled and SimpleListBoxItem to define the look of each item --> + <Style x:Key="SimpleListBox" TargetType="{x:Type ListBox}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="Background" Value="{DynamicResource WindowBackgroundBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource SolidBorderBrush}"/> + <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> + <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> + <Setter Property="ScrollViewer.CanContentScroll" Value="True"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ListBox}"> + <Grid> + <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> + <ScrollViewer Margin="1" Style="{DynamicResource SimpleScrollViewer}" Focusable="false" Background="{TemplateBinding Background}"> + + <!-- The StackPanel is used to display the children by setting IsItemsHost to be Trus --> + <StackPanel Margin="2" IsItemsHost="true"/> + + </ScrollViewer> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + </Trigger> + <Trigger Property="IsGrouping" Value="true"> + <Setter Property="ScrollViewer.CanContentScroll" Value="false"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ListBoxItem - This is used for each Item in a ListBox. The item's content is placed in the ContentPresenter --> + + <Style x:Key="SimpleListBoxItem" d:IsControlPart="True" TargetType="{x:Type ListBoxItem}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="OverridesDefaultStyle" Value="true"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ListBoxItem}"> + <Grid SnapsToDevicePixels="true"> + <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> + </Grid> + <ControlTemplate.Triggers> + + <!-- Change IsSelected SelectedBackgroundBrush to set the selection color for the items --> + <Trigger Property="IsSelected" Value="true"> + <Setter Property="Background" Value="{DynamicResource SelectedBackgroundBrush}" TargetName="Border"/> + </Trigger> + + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Expander ToggleButton - This Button is used by the Expander control. When it is toggled it switches visibility on the Up_Arrow and Down_Arrow --> + <ControlTemplate x:Key="ExpanderToggleButton" TargetType="{x:Type ToggleButton}"> + <Grid> + <Rectangle Margin="0,0,0,0" x:Name="Rectangle" Fill="Transparent" Stroke="{DynamicResource NormalBorderBrush}"/> + <Path HorizontalAlignment="Center" x:Name="Up_Arrow" VerticalAlignment="Center" Fill="{DynamicResource GlyphBrush}" Data="M 0 0 L 4 4 L 8 0 Z"/> + <Path Visibility="Collapsed" HorizontalAlignment="Center" x:Name="Down_Arrow" VerticalAlignment="Center" Fill="{DynamicResource GlyphBrush}" Data="M 0 4 L 4 0 L 8 4 Z"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="true"> + <Setter Property="Fill" Value="{DynamicResource MouseOverBrush}" TargetName="Rectangle"/> + </Trigger> + <Trigger Property="IsPressed" Value="true"> + <Setter Property="Fill" Value="{DynamicResource PressedBrush}" TargetName="Rectangle"/> + </Trigger> + <Trigger Property="IsChecked" Value="true"> + <Setter Property="Visibility" Value="Visible" TargetName="Down_Arrow"/> + <Setter Property="Visibility" Value="Collapsed" TargetName="Up_Arrow"/> + </Trigger> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Fill" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Rectangle"/> + <Setter Property="Stroke" Value="{DynamicResource DisabledBorderBrush}" TargetName="Rectangle"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + <Setter Property="Fill" Value="{DynamicResource DisabledForegroundBrush}" TargetName="Up_Arrow"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + + <!-- Simple Expander + This uses the Simpler ExpanderToggleButton. It sets Visibility on the ContentPresenter to expand + Limitations : The Simple Expander only expands down --> + <Style x:Key="SimpleExpander" TargetType="{x:Type Expander}"> + <Setter Property="Background" Value="{DynamicResource LightBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Expander}"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="*" x:Name="ContentRow"/> + </Grid.RowDefinitions> + <Border Grid.Row="0" x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2,2,0,0"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="20"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <ToggleButton Template="{DynamicResource ExpanderToggleButton}" Background="{DynamicResource NormalBrush}" IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" OverridesDefaultStyle="True"/> + <ContentPresenter Grid.Column="1" Margin="4" RecognizesAccessKey="True" ContentSource="Header"/> + </Grid> + </Border> + <Border Visibility="Collapsed" Grid.Row="1" x:Name="ExpandSite" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1,0,1,1" CornerRadius="0,0,2,2"> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Focusable="false"/> + </Border> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsExpanded" Value="True"> + <Setter Property="Visibility" Value="Visible" TargetName="ExpandSite"/> + </Trigger> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ComboBox Toggle Button - This is used in ComboBox to expand and collapse the ComboBox Popup--> + <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition/> + <ColumnDefinition Width="20"/> + </Grid.ColumnDefinitions> + <Rectangle Grid.ColumnSpan="2" HorizontalAlignment="Stretch" x:Name="Rectangle" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="5" RadiusY="5" Fill="{DynamicResource NormalBrush}" Stroke="{DynamicResource NormalBorderBrush}"/> + <Rectangle Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" RadiusX="5" RadiusY="5" Fill="{DynamicResource WindowBackgroundBrush}" Stroke="{DynamicResource NormalBorderBrush}"/> + <Path Grid.Column="1" HorizontalAlignment="Center" x:Name="Arrow" VerticalAlignment="Center" Fill="{DynamicResource GlyphBrush}" Data="M 0 0 L 4 4 L 8 0 Z"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="true"> + <Setter Property="Fill" Value="{DynamicResource MouseOverBrush}" TargetName="Rectangle"/> + </Trigger> + <Trigger Property="IsChecked" Value="true"> + <Setter Property="Fill" Value="{DynamicResource PressedBrush}" TargetName="Rectangle"/> + </Trigger> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Fill" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Rectangle"/> + <Setter Property="Stroke" Value="{DynamicResource DisabledBorderBrush}" TargetName="Rectangle"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + <Setter Property="Fill" Value="{DynamicResource DisabledForegroundBrush}" TargetName="Arrow"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + + <!-- This is the area which contains the selected item in the ComboBox --> + + <ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}"> + <!-- This must be named as PART_ContentHost --> + <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}"/> + </ControlTemplate> + + <!-- Simple ComboBox + This uses the ComboBoxToggleButton to expand and collapse a Popup control + SimpleScrollViewer to allow items to be scrolled and SimpleComboBoxItem to define the look of each item + The Popup shows a list of items in a StackPanel--> + + <Style x:Key="SimpleComboBox" TargetType="{x:Type ComboBox}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ComboBox}"> + <Grid> + <!-- The ToggleButton is databound to the ComboBox itself to toggle IsDropDownOpen --> + <ToggleButton Grid.Column="2" Template="{DynamicResource ComboBoxToggleButton}" x:Name="ToggleButton" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/> + <ContentPresenter HorizontalAlignment="Left" Margin="3,3,23,3" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False"/> + + <!-- The TextBox must be named PART_EditableTextBox or ComboBox will not recognize it --> + <TextBox Visibility="Hidden" Template="{DynamicResource ComboBoxTextBox}" HorizontalAlignment="Left" Margin="3,3,23,3" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" Background="Transparent" IsReadOnly="{TemplateBinding IsReadOnly}"/> + + <!-- The Popup shows the list of items in the ComboBox. IsOpen is databound to IsDropDownOpen which is toggled via the ComboBoxToggleButton --> + <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide"> + <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True"> + <Border x:Name="DropDownBorder" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1"/> + <ScrollViewer Margin="4,6,4,6" Style="{DynamicResource SimpleScrollViewer}" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True"> + + <!-- The StackPanel is used to display the children by setting IsItemsHost to be True --> + <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/> + + </ScrollViewer> + </Grid> + </Popup> + </Grid> + <ControlTemplate.Triggers> + <!-- This forces the DropDown to have a minimum size if it is empty --> + <Trigger Property="HasItems" Value="false"> + <Setter Property="MinHeight" Value="95" TargetName="DropDownBorder"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + <Trigger Property="IsGrouping" Value="true"> + <Setter Property="ScrollViewer.CanContentScroll" Value="false"/> + </Trigger> + <Trigger Property="AllowsTransparency" SourceName="Popup" Value="true"> + <Setter Property="CornerRadius" Value="4" TargetName="DropDownBorder"/> + <Setter Property="Margin" Value="0,2,0,0" TargetName="DropDownBorder"/> + </Trigger> + <Trigger Property="IsEditable" Value="true"> + <Setter Property="IsTabStop" Value="false"/> + <Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox"/> + <Setter Property="Visibility" Value="Hidden" TargetName="ContentSite"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple ComboBoxItem - This is used for each item inside of the ComboBox. You can change the selected color of each item below--> + <Style x:Key="SimpleComboBoxItem" d:IsControlPart="True" TargetType="{x:Type ComboBoxItem}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ComboBoxItem}"> + <Grid SnapsToDevicePixels="true"> + <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> + </Grid> + <ControlTemplate.Triggers> + + <!-- Change IsHighlighted SelectedBackgroundBrush to set the selection color for the items --> + <Trigger Property="IsHighlighted" Value="true"> + <Setter Property="Background" Value="{DynamicResource SelectedBackgroundBrush}" TargetName="Border"/> + </Trigger> + + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple SimpleProgressBar + The template uses two Border controls to show the Track and Progress + Limitations : It only supports a horizontal orientated ProgressBar --> + <Style x:Key="SimpleProgressBar" TargetType="{x:Type ProgressBar}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ProgressBar}"> + <Grid> + + <!-- This Border is the track. It must be named PART_Track --> + <Border x:Name="PART_Track" Background="{DynamicResource PressedBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" CornerRadius="2"/> + + <!-- This Border shows progress. It must be named PART_Indicator for the control to function --> + <Border HorizontalAlignment="Left" x:Name="PART_Indicator" Background="{DynamicResource MouseOverBrush}" BorderBrush="{DynamicResource NormalBorderBrush}" BorderThickness="1" CornerRadius="2"/> + + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple TextBox --> + <Style x:Key="SimpleTextBox" TargetType="{x:Type TextBox}"> + <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="AllowDrop" Value="true"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TextBox}"> + <Grid> + <Border x:Name="Border" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" Padding="2" CornerRadius="2"> + + <!-- The implementation places the Content into the ScrollViewer. It must be named PART_ContentHost for the control to function --> + <ScrollViewer Margin="0" x:Name="PART_ContentHost" Style="{DynamicResource SimpleScrollViewer}" Background="{TemplateBinding Background}"/> + + </Border> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Label - This template is just a ContentPresenter that shows the content of the Label --> + <Style x:Key="SimpleLabel" TargetType="{x:Type Label}"> + <Setter Property="HorizontalContentAlignment" Value="Left"/> + <Setter Property="VerticalContentAlignment" Value="Top"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Label}"> + <Grid> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="false"/> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Menu - This template uses a StackPanel to layout MenuItems --> + <Style x:Key="SimpleMenu" TargetType="{x:Type Menu}"> + <Setter Property="Background" Value="{DynamicResource LightBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="SnapsToDevicePixels" Value="True"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Menu}"> + <Grid> + <Border Margin="1" x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> + <StackPanel Background="{TemplateBinding Background}" IsItemsHost="True" ClipToBounds="True" Orientation="Horizontal"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- This BitmapEffect is used by the Simple MenuItem --> + <DropShadowBitmapEffect x:Key="PopupDropShadow" ShadowDepth="1.5" Softness="0.15"/> + + <!-- Simple MenuItem - The template uses triggers to provide four different arrangements of menu item which are set via the Role property --> + <Style x:Key="SimpleMenuItem" TargetType="{x:Type MenuItem}"> + <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> + <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.MenuTextBrushKey}}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type MenuItem}"> + <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> + <Grid> + + <!-- The Grid is used to hold together columns for an Icon, Content, Glyph checkmark and Arrow to show the next level + Size sharing is used in Grid so that the Icon, Content, Arrow for each MenuItem align together --> + <Grid.ColumnDefinitions> + <ColumnDefinition MinWidth="17" Width="Auto" SharedSizeGroup="MenuItemIconColumnGroup"/> + <ColumnDefinition Width="*"/> + <ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup"/> + <ColumnDefinition Width="14"/> + </Grid.ColumnDefinitions> + + <!-- ContentPresenter to show an Icon if needed --> + <ContentPresenter Margin="4,0,6,0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/> + + <!-- Glyph is a checkmark if needed for a checkable menu --> + <Grid Visibility="Hidden" Margin="4,0,6,0" x:Name="GlyphPanel" VerticalAlignment="Center"> + <Path x:Name="GlyphPanelpath" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,2 L0,4.8 L2.5,7.4 L7.1,2.8 L7.1,0 L2.5,4.6 z" FlowDirection="LeftToRight"/> + </Grid> + + <!-- Content for the menu text etc --> + <ContentPresenter Grid.Column="1" Margin="{TemplateBinding Padding}" x:Name="HeaderHost" RecognizesAccessKey="True" ContentSource="Header"/> + + <!-- Arrow drawn path which points to the next level of the menu --> + <Grid Grid.Column="3" Margin="4,0,6,0" x:Name="ArrowPanel" VerticalAlignment="Center"> + <Path x:Name="ArrowPanelPath" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,0 L0,8 L4,4 z"/> + </Grid> + + <!-- The Popup is the body of the menu which expands down or across depending on the level of the item --> + <Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" x:Name="SubMenuPopup" Focusable="false" AllowsTransparency="true" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" VerticalOffset="-3"> + <Grid x:Name="SubMenu"> + <Border x:Name="SubMenuBorder" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1"/> + + <!-- StackPanel holds children of the menu. This is set bu IsItemsHost=True --> + <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/> + </Grid> + </Popup> + + </Grid> + </Border> + + <!-- These triggers re-configure the four arrangements of MenuItem to show different levels of menu via Role --> + <ControlTemplate.Triggers> + + <!-- Role = TopLevelHeader : this is the root menu item in a menu; the Popup expands down --> + <Trigger Property="Role" Value="TopLevelHeader"> + <Setter Property="Margin" Value="0,1,0,1"/> + <Setter Property="Padding" Value="6,3,6,3"/> + <Setter Property="Grid.IsSharedSizeScope" Value="true"/> + <Setter Property="Placement" Value="Bottom" TargetName="SubMenuPopup"/> + <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/> + </Trigger> + + <!-- Role = TopLevelItem : this is a child menu item from the top level without any child items--> + <Trigger Property="Role" Value="TopLevelItem"> + <Setter Property="Margin" Value="0,1,0,1"/> + <Setter Property="Padding" Value="6,3,6,3"/> + <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/> + </Trigger> + + <!-- Role = SubMenuHeader : this is a child menu item which does not have children --> + <Trigger Property="Role" Value="SubmenuHeader"> + <Setter Property="DockPanel.Dock" Value="Top"/> + <Setter Property="Padding" Value="0,2,0,2"/> + <Setter Property="Grid.IsSharedSizeScope" Value="true"/> + </Trigger> + + <!-- Role = SubMenuItem : this is a child menu item which has children--> + <Trigger Property="Role" Value="SubmenuItem"> + <Setter Property="DockPanel.Dock" Value="Top"/> + <Setter Property="Padding" Value="0,2,0,2"/> + <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/> + </Trigger> + <Trigger Property="IsSuspendingPopupAnimation" Value="true"> + <Setter Property="PopupAnimation" Value="None" TargetName="SubMenuPopup"/> + </Trigger> + + <!-- If no Icon is present the we collapse the Icon Content --> + <Trigger Property="Icon" Value="{x:Null}"> + <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/> + </Trigger> + + <!-- The GlyphPanel contains the CheckMark --> + <Trigger Property="IsChecked" Value="true"> + <Setter Property="Visibility" Value="Visible" TargetName="GlyphPanel"/> + <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/> + </Trigger> + + <Trigger Property="AllowsTransparency" SourceName="SubMenuPopup" Value="true"> + <Setter Property="Margin" Value="0,0,3,3" TargetName="SubMenu"/> + <Setter Property="SnapsToDevicePixels" Value="true" TargetName="SubMenu"/> + <Setter Property="BitmapEffect" Value="{DynamicResource PopupDropShadow}" TargetName="SubMenuBorder"/> + </Trigger> + + <!-- Using the system colors for the Menu Highlight and IsEnabled--> + <Trigger Property="IsHighlighted" Value="true"> + <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" TargetName="Border"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple Separator - This template is used for a Separator in a menu --> + <Style x:Key="SimpleSeparator" TargetType="{x:Type Separator}"> + <Setter Property="Height" Value="1"/> + <Setter Property="Margin" Value="0,2,0,2"/> + <Setter Property="Focusable" Value="false"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Separator}"> + <Border BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1"/> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Simple TabControl + This template uses Simple TabItem for each Tab. The TabItems are placed in the TabPanel + Limitations : The Simple TabControl only allow the Tabs to be shown at the top of the Tab control. You can re-position the TabPanel to change this--> + + <Style x:Key="SimpleTabControl" TargetType="{x:Type TabControl}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TabControl}"> + <Grid KeyboardNavigation.TabNavigation="Local"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + + <!-- TabPanel is a layout container which allows the TabItems to wrap and re-order when selected + The implementation knows to use this control because it is marked IsItemsHost = True --> + <TabPanel Grid.Row="0" Margin="0,0,4,-1" x:Name="HeaderPanel" Background="Transparent" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/> + + <Border Grid.Row="1" x:Name="Border" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" CornerRadius="2" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.TabIndex="2"> + + <!-- The implementation switches the content. This control must be named PART_SelectedContentHost --> + <ContentPresenter Margin="4" x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/> + + </Border> + </Grid> + + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + </Trigger> + </ControlTemplate.Triggers> + + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!--Simple TabItem --> + <Style x:Key="SimpleTabItem" d:IsControlPart="True" TargetType="{x:Type TabItem}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TabItem}"> + <Grid> + <Border Margin="0,0,-4,0" x:Name="Border" Background="{DynamicResource LightBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0"> + <ContentPresenter HorizontalAlignment="Center" Margin="12,2,12,2" x:Name="ContentSite" VerticalAlignment="Center" RecognizesAccessKey="True" ContentSource="Header"/> + </Border> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsSelected" Value="True"> + <Setter Property="Panel.ZIndex" Value="100"/> + <Setter Property="Background" Value="{DynamicResource WindowBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderThickness" Value="1,1,1,0" TargetName="Border"/> + </Trigger> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!--Simple Simple SliderThumb - The Thumb is the draggable part of a Slider--> + <Style x:Key="SimpleSliderThumb" d:IsControlPart="True" TargetType="{x:Type Thumb}"> + <Setter Property="SnapsToDevicePixels" Value="true"/> + <Setter Property="Height" Value="14"/> + <Setter Property="Width" Value="14"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Thumb}"> + <Grid> + <Ellipse x:Name="Ellipse" Fill="{DynamicResource NormalBrush}" Stroke="{DynamicResource NormalBorderBrush}" StrokeThickness="1"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter Property="Fill" Value="{DynamicResource MouseOverBrush}" TargetName="Ellipse"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Fill" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Ellipse"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!--Simple Simple Slider + Similiar to ScrollBar this template uses Track to layout the draggable Thumb which has an up and down repeat button + It uses Simple SliderThumb and SimpleScrollRepeatButtonStyle for the page up and down repeat buttons --> + <Style x:Key="SimpleSlider" TargetType="{x:Type Slider}"> + <Setter Property="Background" Value="{DynamicResource LightBrush}"/> + <Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Slider}"> + <Grid x:Name="GridRoot"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/> + <RowDefinition Height="Auto"/> + </Grid.RowDefinitions> + + <!-- TickBar shows the ticks for Slider --> + <TickBar Visibility="Collapsed" x:Name="TopTick" Height="4" SnapsToDevicePixels="True" Placement="Top" Fill="{DynamicResource GlyphBrush}"/> + <Border Grid.Row="1" Margin="0" x:Name="Border" Height="4" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/> + + <!-- The Track lays out the repeat buttons and thumb --> + <Track Grid.Row="1" x:Name="PART_Track"> + <Track.Thumb> + <Thumb Style="{DynamicResource SimpleSliderThumb}"/> + </Track.Thumb> + <Track.IncreaseRepeatButton> + <RepeatButton Style="{DynamicResource SimpleScrollRepeatButtonStyle}" Command="Slider.IncreaseLarge"/> + </Track.IncreaseRepeatButton> + <Track.DecreaseRepeatButton> + <RepeatButton Style="{DynamicResource SimpleScrollRepeatButtonStyle}" Command="Slider.DecreaseLarge"/> + </Track.DecreaseRepeatButton> + </Track> + + <TickBar Visibility="Collapsed" Grid.Row="2" x:Name="BottomTick" Height="4" SnapsToDevicePixels="True" Placement="Bottom" Fill="{TemplateBinding Foreground}"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="TickPlacement" Value="TopLeft"> + <Setter Property="Visibility" Value="Visible" TargetName="TopTick"/> + </Trigger> + <Trigger Property="TickPlacement" Value="BottomRight"> + <Setter Property="Visibility" Value="Visible" TargetName="BottomTick"/> + </Trigger> + <Trigger Property="TickPlacement" Value="Both"> + <Setter Property="Visibility" Value="Visible" TargetName="TopTick"/> + <Setter Property="Visibility" Value="Visible" TargetName="BottomTick"/> + </Trigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> + <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> + </Trigger> + + <!-- Use a rotation to create a Vertical Slider form the default Horizontal --> + <Trigger Property="Orientation" Value="Vertical"> + <Setter Property="LayoutTransform" TargetName="GridRoot"> + <Setter.Value> + <RotateTransform Angle="-90"/> + </Setter.Value> + </Setter> + <!-- Track rotates itself based on orientation so need to force it back --> + <Setter TargetName="PART_Track" Property="Orientation" Value="Horizontal"/> + </Trigger> + + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!--Simple Tree View - This lays out TreeViewItems within a ScrollViewer --> + <Style x:Key="SimpleTreeView" TargetType="{x:Type TreeView}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TreeView}"> + <Grid> + <Border x:Name="Border" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" CornerRadius="1"> + <ScrollViewer Style="{DynamicResource SimpleScrollViewer}" Focusable="False" Background="{TemplateBinding Background}" Padding="4" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="False"> + <ItemsPresenter/> + </ScrollViewer> + </Border> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!--Simple TreeViewItem ToggleButton - + and - button to expand and collapse a TreeViewItem --> + <Style x:Key="SimpleTreeViewItemToggleButton" d:IsControlPart="True" TargetType="{x:Type ToggleButton}"> + <Setter Property="Focusable" Value="False"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ToggleButton}"> + <Grid Width="15" Height="13" Background="Transparent"> + <Path Visibility="Collapsed" HorizontalAlignment="Left" Margin="1,1,1,1" x:Name="IsExpandedPath" VerticalAlignment="Center" Fill="{DynamicResource GlyphBrush}" Data="M 0 4 L 8 4 L 4 8 Z"/> + <Path HorizontalAlignment="Left" Margin="1,1,1,1" x:Name="ExpandPath" VerticalAlignment="Center" Fill="{DynamicResource GlyphBrush}" Data="M 4 0 L 8 4 L 4 8 Z"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsChecked" Value="True"> + <Setter Property="Visibility" Value="Visible" TargetName="IsExpandedPath"/> + <Setter Property="Visibility" Value="Collapsed" TargetName="ExpandPath"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!--Simple TreeViewItem - The TreeViewItem template has a header which shows the Item and a Body which is an ItemsHost control which expands to show child items--> + <Style x:Key="SimpleTreeViewItem" d:IsControlPart="True" TargetType="{x:Type TreeViewItem}"> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> + <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> + <Setter Property="Padding" Value="1,0,0,0"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TreeViewItem}"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition MinWidth="19" Width="Auto"/> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition/> + </Grid.RowDefinitions> + <ToggleButton x:Name="Expander" Style="{DynamicResource SimpleTreeViewItemToggleButton}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/> + <Border Grid.Column="1" x:Name="Selection_Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" x:Name="PART_Header" ContentSource="Header"/> + </Border> + <ItemsPresenter Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" x:Name="ItemsHost"/> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsExpanded" Value="false"> + <Setter Property="Visibility" Value="Collapsed" TargetName="ItemsHost"/> + </Trigger> + <Trigger Property="HasItems" Value="false"> + <Setter Property="Visibility" Value="Hidden" TargetName="Expander"/> + </Trigger> + <Trigger Property="IsSelected" Value="true"> + <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" TargetName="Selection_Border"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> + </Trigger> + <MultiTrigger> + <MultiTrigger.Conditions> + <Condition Property="IsSelected" Value="true"/> + <Condition Property="IsSelectionActive" Value="false"/> + </MultiTrigger.Conditions> + <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" TargetName="Selection_Border"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> + </MultiTrigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> +</ResourceDictionary> diff --git a/windows/WinUI/Themes/Generic.xaml b/windows/WinUI/Themes/Generic.xaml new file mode 100644 index 00000000..2b47588d --- /dev/null +++ b/windows/WinUI/Themes/Generic.xaml @@ -0,0 +1,7 @@ +<ResourceDictionary + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="clr-namespace:WinUI"> + + +</ResourceDictionary> diff --git a/windows/WinUI/WinUI.csproj b/windows/WinUI/WinUI.csproj new file mode 100644 index 00000000..5ebfedcf --- /dev/null +++ b/windows/WinUI/WinUI.csproj @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{4CCA6B98-5E64-45BF-AC34-19B3E2570DB1}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WinUI</RootNamespace> + <AssemblyName>ZeroTier One</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <WarningLevel>4</WarningLevel> + <ExpressionBlendVersion>5.0.40218.0</ExpressionBlendVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <AutorunEnabled>true</AutorunEnabled> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.0</ApplicationVersion> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>true</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <StartupObject>WinUI.App</StartupObject> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>ZeroTierIcon.ico</ApplicationIcon> + </PropertyGroup> + <PropertyGroup> + <SignAssembly>false</SignAssembly> + </PropertyGroup> + <PropertyGroup> + <SignManifests>false</SignManifests> + </PropertyGroup> + <ItemGroup> + <Reference Include="Accessibility" /> + <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="PresentationUI, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> + <Reference Include="ReachFramework" /> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Deployment" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Printing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Xaml"> + <RequiredTargetFramework>4.0</RequiredTargetFramework> + </Reference> + <Reference Include="UIAutomationProvider" /> + <Reference Include="UIAutomationTypes" /> + <Reference Include="WindowsBase" /> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> + </ItemGroup> + <ItemGroup> + <ApplicationDefinition Include="App.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </ApplicationDefinition> + <Compile Include="NetworksPage.xaml.cs"> + <DependentUpon>NetworksPage.xaml</DependentUpon> + </Compile> + <Compile Include="PeersPage.xaml.cs"> + <DependentUpon>PeersPage.xaml</DependentUpon> + </Compile> + <Compile Include="ZeroTierPeerPhysicalPath.cs" /> + <Compile Include="ZeroTierPeer.cs" /> + <Compile Include="ZeroTierNetwork.cs" /> + <Compile Include="ZeroTierStatus.cs" /> + <Page Include="MainWindow.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Compile Include="APIHandler.cs" /> + <Compile Include="App.xaml.cs"> + <DependentUpon>App.xaml</DependentUpon> + <SubType>Code</SubType> + </Compile> + <Compile Include="MainWindow.xaml.cs"> + <DependentUpon>MainWindow.xaml</DependentUpon> + <SubType>Code</SubType> + </Compile> + <Page Include="NetworkInfoView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="NetworksPage.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="PeersPage.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Simple Styles.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Page Include="Themes\Generic.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + </ItemGroup> + <ItemGroup> + <Compile Include="NetworkInfoView.xaml.cs"> + <DependentUpon>NetworkInfoView.xaml</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + <None Include="packages.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + <AppDesigner Include="Properties\" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include=".NETFramework,Version=v4.5"> + <Visible>False</Visible> + <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>false</Install> + </BootstrapperPackage> + </ItemGroup> + <ItemGroup> + <BlendEmbeddedFont Include="Fonts\segoeui.ttf"> + <IsSystemFont>True</IsSystemFont> + <All>True</All> + <AutoFill>True</AutoFill> + </BlendEmbeddedFont> + <BlendEmbeddedFont Include="Fonts\segoeuib.ttf"> + <IsSystemFont>True</IsSystemFont> + <All>True</All> + <AutoFill>True</AutoFill> + </BlendEmbeddedFont> + <BlendEmbeddedFont Include="Fonts\segoeuii.ttf"> + <IsSystemFont>True</IsSystemFont> + <All>True</All> + <AutoFill>True</AutoFill> + </BlendEmbeddedFont> + <BlendEmbeddedFont Include="Fonts\segoeuiz.ttf"> + <IsSystemFont>True</IsSystemFont> + <All>True</All> + <AutoFill>True</AutoFill> + </BlendEmbeddedFont> + <Resource Include="ZeroTierIcon.ico" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(MSBuildExtensionsPath)\Microsoft\Expression\Blend\.NETFramework\v4.5\Microsoft.Expression.Blend.WPF.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/windows/WinUI/ZeroTierIcon.ico b/windows/WinUI/ZeroTierIcon.ico Binary files differnew file mode 100644 index 00000000..2d190c47 --- /dev/null +++ b/windows/WinUI/ZeroTierIcon.ico diff --git a/windows/WinUI/ZeroTierNetwork.cs b/windows/WinUI/ZeroTierNetwork.cs new file mode 100644 index 00000000..cce65441 --- /dev/null +++ b/windows/WinUI/ZeroTierNetwork.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace WinUI +{ + public class ZeroTierNetwork + { + [JsonProperty("nwid")] + public string NetworkId { get; set; } + + [JsonProperty("mac")] + public string MacAddress { get; set; } + + [JsonProperty("name")] + public string NetworkName { get; set; } + + [JsonProperty("status")] + public string NetworkStatus { get; set; } + + [JsonProperty("type")] + public string NetworkType { get; set; } + + [JsonProperty("mtu")] + public int MTU { get; set; } + + [JsonProperty("dhcp")] + public bool DHCP { get; set; } + + [JsonProperty("bridge")] + public bool Bridge { get; set ; } + + [JsonProperty("broadcastEnabled")] + public bool BroadcastEnabled { get ; set; } + + [JsonProperty("portError")] + public int PortError { get; set; } + + [JsonProperty("netconfRevision")] + public int NetconfRevision { get; set; } + + [JsonProperty("multicastSubscriptions")] + public string[] MulticastSubscriptions { get; set; } + + [JsonProperty("assignedAddresses")] + public string[] AssignedAddresses { get; set; } + + [JsonProperty("portDeviceName")] + public string DeviceName { get; set; } + } +} diff --git a/windows/WinUI/ZeroTierPeer.cs b/windows/WinUI/ZeroTierPeer.cs new file mode 100644 index 00000000..3153f7e2 --- /dev/null +++ b/windows/WinUI/ZeroTierPeer.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace WinUI +{ + public class ZeroTierPeer + { + [JsonProperty("address")] + public string Address { get; set; } + + [JsonProperty("lastUnicastFrame")] + public UInt64 LastUnicastFrame { get; set; } + + [JsonProperty("lastMulticastFrame")] + public UInt64 LastMulticastFrame { get; set; } + + [JsonProperty("versionMajor")] + public int VersionMajor { get; set; } + + [JsonProperty("versionMinor")] + public int VersionMinor { get; set; } + + [JsonProperty("versionRev")] + public int Versionrev { get; set; } + + [JsonProperty("version")] + public string Version { get; set; } + + public string VersionString + { + get + { + if (Version == "-1.-1.-1") + return "-"; + else + return Version; + } + } + + [JsonProperty("latency")] + public string Latency { get; set; } + + [JsonProperty("role")] + public string Role { get; set; } + + [JsonProperty("paths")] + public List<ZeroTierPeerPhysicalPath> Paths { get; set; } + + public string DataPaths + { + get + { + string pathStr = ""; + foreach(ZeroTierPeerPhysicalPath path in Paths) + { + pathStr += path.Address + "\n"; + } + return pathStr; + } + } + } +} diff --git a/windows/WinUI/ZeroTierPeerPhysicalPath.cs b/windows/WinUI/ZeroTierPeerPhysicalPath.cs new file mode 100644 index 00000000..3eaa8026 --- /dev/null +++ b/windows/WinUI/ZeroTierPeerPhysicalPath.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace WinUI +{ + public class ZeroTierPeerPhysicalPath + { + [JsonProperty("address")] + public string Address { get; set; } + + [JsonProperty("lastSend")] + public UInt64 LastSend { get; set; } + + [JsonProperty("lastReceive")] + public UInt64 LastReceive { get; set; } + + [JsonProperty("fixed")] + public bool Fixed { get; set; } + + [JsonProperty("preferred")] + public bool Preferred { get; set; } + } +} diff --git a/windows/WinUI/ZeroTierStatus.cs b/windows/WinUI/ZeroTierStatus.cs new file mode 100644 index 00000000..2851d017 --- /dev/null +++ b/windows/WinUI/ZeroTierStatus.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace WinUI +{ + public class ZeroTierStatus + { + [JsonProperty("address")] + public string Address { get; set; } + + [JsonProperty("publicIdentity")] + public string PublicIdentity { get; set; } + + [JsonProperty("online")] + public bool Online { get; set; } + + [JsonProperty("tcpFallbackActive")] + public bool TcpFallbackActive { get; set; } + + [JsonProperty("versionMajor")] + public int VersionMajor { get; set; } + + [JsonProperty("versionMinor")] + public int VersionMinor { get; set; } + + [JsonProperty("versionRev")] + public int VersionRev { get; set; } + + [JsonProperty("version")] + public string Version { get; set; } + + [JsonProperty("clock")] + public UInt64 Clock { get; set; } + } +} diff --git a/windows/WinUI/packages.config b/windows/WinUI/packages.config new file mode 100644 index 00000000..505e5883 --- /dev/null +++ b/windows/WinUI/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> +</packages>
\ No newline at end of file |