aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml
blob: 9a3b3405ed1089496a8d70340cf602fc0975b699 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<UserControl x:Class="Tango.MachineStudio.UI.Views.LoginView"
             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:rules="clr-namespace:Tango.MachineStudio.Common.ValidationRules;assembly=Tango.MachineStudio.Common"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
             xmlns:web="clr-namespace:Tango.Web;assembly=Tango.Web"
             xmlns:automation="clr-namespace:Tango.MachineStudio.Common.Automation;assembly=Tango.MachineStudio.Common"
             xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
             xmlns:helpers="clr-namespace:Tango.SharedUI.Helpers;assembly=Tango.SharedUI"
             xmlns:common="clr-namespace:Tango.MachineStudio.Common;assembly=Tango.MachineStudio.Common"
             xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views"
             mc:Ignorable="d" 
             d:DesignHeight="720" d:DesignWidth="1280" DataContext="{Binding LoginViewVM, Source={StaticResource Locator}}" Background="Transparent">

    <UserControl.Resources>
        <rules:Required x:Key="Required"></rules:Required>
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        <converters:BooleanToVisibilityInverseConverter x:Key="BooleanToVisibilityInverseConverter" />
        <converters:EnumToItemsSourceConverter x:Key="EnumToItemsSourceConverter" />
    </UserControl.Resources>


    <UserControl.InputBindings>
        <KeyBinding Key="Return" Command="{Binding LoginCommand}"></KeyBinding>
    </UserControl.InputBindings>
    <Grid Background="Transparent">

        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsLogging}" Value="True">
                        <Setter Property="Cursor" Value="AppStarting"></Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsLogging}" Value="False">
                        <Setter Property="Cursor" Value="Arrow"></Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="40">
            <Image Source="{StaticResource MachineBig}" RenderOptions.BitmapScalingMode="Fant" Width="100"></Image>
            <TextBlock Margin="20 0 0 0" VerticalAlignment="Center" FontSize="70" Foreground="{StaticResource AccentColorBrush}">Machine Studio</TextBlock>
        </StackPanel>

        <Grid>
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="-600 110 0 0" Visibility="{Binding ShowLoggingDetails,Converter={StaticResource BooleanToVisibilityConverter}}">
                <RadioButton ToolTip="Login using your an active directory account" IsChecked="{Binding IsActiveDirectory}" FontSize="16" VerticalContentAlignment="Center" Padding="10 0 0 0">
                    <Image Source="/Images/active_directory.png" Stretch="Uniform" Height="80" RenderOptions.BitmapScalingMode="Fant" />
                </RadioButton>
                <RadioButton ToolTip="Login using a standard Machine Studio account" IsChecked="{Binding IsStandardUser}" FontSize="16" Margin="0 20 0 0" VerticalContentAlignment="Center" Padding="10 0 0 0">
                    <Image Source="/Images/machinestudio_login.png" Stretch="Uniform" Height="55" RenderOptions.BitmapScalingMode="Fant" />
                </RadioButton>
            </StackPanel>
            <DockPanel HorizontalAlignment="Center" VerticalAlignment="Center" Width="320" Margin="0 120 0 0" Height="510">

                <Grid DockPanel.Dock="Bottom" Margin="25 20 0 0" >
                    <Button AutomationProperties.AutomationId="{x:Static automation:UI.LoginButton}" Height="50" Command="{Binding LoginCommand}" Content="LOGIN">
                        <Button.Style>
                            <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                                <Setter Property="Visibility" Value="Visible"></Setter>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsChangingPassword}" Value="True">
                                        <Setter Property="Visibility" Value="Hidden"></Setter>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Button.Style>
                    </Button>

                    <Button AutomationProperties.AutomationId="{x:Static automation:UI.LoginButton}" Height="50" Command="{Binding UpdatePasswordCommand}" Content="CHANGE PASSWORD">
                        <Button.Style>
                            <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                                <Setter Property="Visibility" Value="Hidden"></Setter>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsChangingPassword}" Value="True">
                                        <Setter Property="Visibility" Value="Visible"></Setter>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Button.Style>
                    </Button>
                </Grid>

                <Grid>
                    <StackPanel Visibility="{Binding ShowLoggingDetails,Converter={StaticResource BooleanToVisibilityConverter}}">
                        <TextBlock HorizontalAlignment="Center" FontSize="24">Login to your account</TextBlock>
                        <Image Source="/Images/login.png" RenderOptions.BitmapScalingMode="Fant" Width="100" Margin="0 20 0 0"></Image>
                        <DockPanel Margin="0 20 0 0">
                            <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=txtEmail, Path=BorderBrush}" Kind="EmailOutline" />
                            <TextBox x:Name="txtEmail" IsTabStop="True" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" Text="{Binding Email,UpdateSourceTrigger=PropertyChanged,ValidatesOnNotifyDataErrors=True}" AutomationProperties.IsRequiredForForm="True">
                                <TextBox.Style>
                                    <Style TargetType="TextBox" BasedOn="{StaticResource MaterialDesignFloatingHintTextBox}">
                                        <Setter Property="materialDesign:HintAssist.Hint" Value="Active Directory Email"></Setter>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding IsStandardUser}" Value="True">
                                                <Setter Property="materialDesign:HintAssist.Hint" Value="Machine Studio Email"></Setter>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBox.Style>
                            </TextBox>
                        </DockPanel>
                        <DockPanel Margin="0 20 0 0">
                            <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=txtPass, Path=BorderBrush}" Kind="Key" />
                            <PasswordBox x:Name="txtPass" helpers:PasswordHelper.Attach="True" helpers:PasswordHelper.Password="{Binding Password,Mode=TwoWay}" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:HintAssist.Hint="Password" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" AutomationProperties.IsRequiredForForm="True" />
                        </DockPanel>
                        <DockPanel Margin="0 40 0 0" IsEnabled="{Binding EnableSlotSelection}">
                            <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=combo, Path=BorderBrush}" Kind="Settings" />
                            <ComboBox x:Name="combo" ItemsSource="{Binding Source={x:Type web:DeploymentSlot},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding DeploymentSlot}" SelectedValuePath="Value" DisplayMemberPath="DisplayName" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:HintAssist.Hint="Environment" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" />
                        </DockPanel>
                        <TextBlock Visibility="{Binding EnableSlotSelection,Converter={StaticResource BooleanToVisibilityInverseConverter}}" Margin="25 0 0 0" FontSize="10" Foreground="Gray">Environment selection requires restarting the application</TextBlock>
                        <CheckBox Margin="25 20 0 0" IsChecked="{Binding RememberMe}">Remember me</CheckBox>
                    </StackPanel>

                    <StackPanel Visibility="{Binding IsLogging,Converter={StaticResource BooleanToVisibilityConverter}}" VerticalAlignment="Center">
                        <Grid>
                            <ProgressBar Width="300" Height="300" HorizontalAlignment="Center" VerticalAlignment="Center" IsIndeterminate="{Binding IsLogging}" Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" />
                            <Image Source="{StaticResource MachineBig}" Width="200" RenderOptions.BitmapScalingMode="Fant"></Image>
                        </Grid>
                        <TextBlock HorizontalAlignment="Center" Margin="0 30 0 0" FontSize="16" FontStyle="Italic" Foreground="{StaticResource GrayBrush200}" Text="{Binding ProgressLog}"></TextBlock>
                    </StackPanel>

                    <StackPanel Visibility="{Binding IsChangingPassword,Converter={StaticResource BooleanToVisibilityConverter}}">
                        <TextBlock HorizontalAlignment="Center" FontSize="24">Password change required</TextBlock>
                        <Image Source="/Images/login.png" RenderOptions.BitmapScalingMode="Fant" Width="100" Margin="0 20 0 0"></Image>
                        <DockPanel Margin="0 40 0 0">
                            <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=txtNewPass1, Path=BorderBrush}" Kind="Key" />
                            <PasswordBox x:Name="txtNewPass1" helpers:PasswordHelper.Attach="True" helpers:PasswordHelper.Password="{Binding NewPassword1,Mode=TwoWay,UpdateSourceTrigger=LostFocus,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:HintAssist.Hint="New Password" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" AutomationProperties.IsRequiredForForm="True" />
                        </DockPanel>
                        <DockPanel Margin="0 40 0 0">
                            <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=txtNewPass2, Path=BorderBrush}" Kind="Key" />
                            <PasswordBox x:Name="txtNewPass2" helpers:PasswordHelper.Attach="True" helpers:PasswordHelper.Password="{Binding NewPassword2,Mode=TwoWay,UpdateSourceTrigger=LostFocus,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:HintAssist.Hint="Confirm Password" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" AutomationProperties.IsRequiredForForm="True" />
                        </DockPanel>
                    </StackPanel>
                </Grid>
            </DockPanel>
        </Grid>
    </Grid>
</UserControl>
ivate set; } /// <summary> /// Gets the line terminator at the insertion position. /// </summary> public string LineTerminator { get; private set; } /// <summary> /// Gets/Sets the insertion position. /// </summary> public int InsertionPosition { get; set; } readonly int startPosition; AnchorSegment wholeSnippetAnchor; bool deactivateIfSnippetEmpty; /// <summary> /// Gets the start position of the snippet insertion. /// </summary> public int StartPosition { get { if (wholeSnippetAnchor != null) return wholeSnippetAnchor.Offset; else return startPosition; } } /// <summary> /// Inserts text at the insertion position and advances the insertion position. /// This method will add the current indentation to every line in <paramref name="text"/> and will /// replace newlines with the expected newline for the document. /// </summary> public void InsertText(string text) { if (text == null) throw new ArgumentNullException("text"); if (currentStatus != Status.Insertion) throw new InvalidOperationException(); text = text.Replace("\t", this.Tab); using (this.Document.RunUpdate()) { int textOffset = 0; SimpleSegment segment; while ((segment = NewLineFinder.NextNewLine(text, textOffset)) != SimpleSegment.Invalid) { string insertString = text.Substring(textOffset, segment.Offset - textOffset) + this.LineTerminator + this.Indentation; this.Document.Insert(InsertionPosition, insertString); this.InsertionPosition += insertString.Length; textOffset = segment.EndOffset; } string remainingInsertString = text.Substring(textOffset); this.Document.Insert(InsertionPosition, remainingInsertString); this.InsertionPosition += remainingInsertString.Length; } } Dictionary<SnippetElement, IActiveElement> elementMap = new Dictionary<SnippetElement, IActiveElement>(); List<IActiveElement> registeredElements = new List<IActiveElement>(); /// <summary> /// Registers an active element. Elements should be registered during insertion and will be called back /// when insertion has completed. /// </summary> /// <param name="owner">The snippet element that created the active element.</param> /// <param name="element">The active element.</param> public void RegisterActiveElement(SnippetElement owner, IActiveElement element) { if (owner == null) throw new ArgumentNullException("owner"); if (element == null) throw new ArgumentNullException("element"); if (currentStatus != Status.Insertion) throw new InvalidOperationException(); elementMap.Add(owner, element); registeredElements.Add(element); } /// <summary> /// Returns the active element belonging to the specified snippet element, or null if no such active element is found. /// </summary> public IActiveElement GetActiveElement(SnippetElement owner) { if (owner == null) throw new ArgumentNullException("owner"); IActiveElement element; if (elementMap.TryGetValue(owner, out element)) return element; else return null; } /// <summary> /// Gets the list of active elements. /// </summary> public IEnumerable<IActiveElement> ActiveElements { get { return registeredElements; } } /// <summary> /// Calls the <see cref="IActiveElement.OnInsertionCompleted"/> method on all registered active elements /// and raises the <see cref="InsertionCompleted"/> event. /// </summary> /// <param name="e">The EventArgs to use</param> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification="There is an event and this method is raising it.")] public void RaiseInsertionCompleted(EventArgs e) { if (currentStatus != Status.Insertion) throw new InvalidOperationException(); if (e == null) e = EventArgs.Empty; currentStatus = Status.RaisingInsertionCompleted; int endPosition = this.InsertionPosition; this.wholeSnippetAnchor = new AnchorSegment(Document, startPosition, endPosition - startPosition); TextDocumentWeakEventManager.UpdateFinished.AddListener(Document, this); deactivateIfSnippetEmpty = (endPosition != startPosition); foreach (IActiveElement element in registeredElements) { element.OnInsertionCompleted(); } if (InsertionCompleted != null) InsertionCompleted(this, e); currentStatus = Status.Interactive; if (registeredElements.Count == 0) { // deactivate immediately if there are no interactive elements Deactivate(new SnippetEventArgs(DeactivateReason.NoActiveElements)); } else { myInputHandler = new SnippetInputHandler(this); // disable existing snippet input handlers - there can be only 1 active snippet foreach (TextAreaStackedInputHandler h in TextArea.StackedInputHandlers) { if (h is SnippetInputHandler) TextArea.PopStackedInputHandler(h); } TextArea.PushStackedInputHandler(myInputHandler); } } SnippetInputHandler myInputHandler; /// <summary> /// Occurs when the all snippet elements have been inserted. /// </summary> public event EventHandler InsertionCompleted; /// <summary> /// Calls the <see cref="IActiveElement.Deactivate"/> method on all registered active elements. /// </summary> /// <param name="e">The EventArgs to use</param> public void Deactivate(SnippetEventArgs e) { if (currentStatus == Status.Deactivated || currentStatus == Status.RaisingDeactivated) return; if (currentStatus != Status.Interactive) throw new InvalidOperationException("Cannot call Deactivate() until RaiseInsertionCompleted() has finished."); if (e == null) e = new SnippetEventArgs(DeactivateReason.Unknown); TextDocumentWeakEventManager.UpdateFinished.RemoveListener(Document, this); currentStatus = Status.RaisingDeactivated; TextArea.PopStackedInputHandler(myInputHandler); foreach (IActiveElement element in registeredElements) { element.Deactivate(e); } if (Deactivated != null) Deactivated(this, e); currentStatus = Status.Deactivated; } /// <summary> /// Occurs when the interactive mode is deactivated. /// </summary> public event EventHandler<SnippetEventArgs> Deactivated; bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) { return ReceiveWeakEvent(managerType, sender, e); } /// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/> protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) { if (managerType == typeof(TextDocumentWeakEventManager.UpdateFinished)) { // Deactivate if snippet is deleted. This is necessary for correctly leaving interactive // mode if Undo is pressed after a snippet insertion. if (wholeSnippetAnchor.Length == 0 && deactivateIfSnippetEmpty) Deactivate(new SnippetEventArgs(DeactivateReason.Deleted)); return true; } return false; } } }