2021-09-17 10:47:02 +02:00
/ *
2024-03-05 18:37:42 +01:00
* Copyright ( c ) 2024 ETH Zürich , IT Services
2021-09-17 10:47:02 +02:00
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
* /
2021-10-04 11:00:30 +02:00
using System ;
2021-09-17 10:47:02 +02:00
using System.Threading.Tasks ;
using System.Windows ;
using System.Windows.Controls ;
using System.Windows.Controls.Primitives ;
using System.Windows.Input ;
using System.Windows.Media ;
2021-10-04 11:00:30 +02:00
using SafeExamBrowser.Core.Contracts.Resources.Icons ;
2021-09-17 10:47:02 +02:00
using SafeExamBrowser.I18n.Contracts ;
using SafeExamBrowser.Proctoring.Contracts ;
using SafeExamBrowser.Settings.Proctoring ;
using SafeExamBrowser.UserInterface.Contracts.Shell ;
2021-10-04 11:00:30 +02:00
using SafeExamBrowser.UserInterface.Shared.Utilities ;
2021-09-17 10:47:02 +02:00
namespace SafeExamBrowser.UserInterface.Desktop.Controls.Taskbar
{
public partial class RaiseHandControl : UserControl , INotificationControl
{
private readonly IProctoringController controller ;
private readonly ProctoringSettings settings ;
private readonly IText text ;
2021-10-04 11:00:30 +02:00
private IconResource LoweredIcon ;
private IconResource RaisedIcon ;
2021-09-17 10:47:02 +02:00
public RaiseHandControl ( IProctoringController controller , ProctoringSettings settings , IText text )
{
this . controller = controller ;
this . settings = settings ;
this . text = text ;
InitializeComponent ( ) ;
InitializeRaiseHandControl ( ) ;
}
private void InitializeRaiseHandControl ( )
{
var originalBrush = NotificationButton . Background ;
controller . HandLowered + = ( ) = > Dispatcher . Invoke ( ShowLowered ) ;
controller . HandRaised + = ( ) = > Dispatcher . Invoke ( ShowRaised ) ;
HandButton . Click + = RaiseHandButton_Click ;
HandButtonText . Text = text . Get ( TextKey . Notification_ProctoringRaiseHand ) ;
2021-10-04 11:00:30 +02:00
LoweredIcon = new XamlIconResource { Uri = new Uri ( "pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Lowered.xaml" ) } ;
RaisedIcon = new XamlIconResource { Uri = new Uri ( "pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Hand_Raised.xaml" ) } ;
Icon . Content = IconResourceLoader . Load ( LoweredIcon ) ;
2023-02-27 13:25:23 +01:00
var lastOpenedBySpacePress = false ;
2023-02-13 13:39:53 +01:00
NotificationButton . PreviewKeyDown + = ( o , args ) = >
{
if ( args . Key = = System . Windows . Input . Key . Space ) // for some reason, the popup immediately closes again if opened by a Space Bar key event - as a mitigation, we record the space bar event and leave the popup open for at least 3 seconds
{
2023-02-27 13:25:23 +01:00
lastOpenedBySpacePress = true ;
2023-02-13 13:39:53 +01:00
}
} ;
NotificationButton . MouseLeave + = ( o , args ) = > Task . Delay ( 250 ) . ContinueWith ( _ = > Dispatcher . Invoke ( ( ) = >
{
2023-02-27 13:25:23 +01:00
if ( Popup . IsOpen & & lastOpenedBySpacePress )
2023-02-13 13:39:53 +01:00
{
return ;
}
Popup . IsOpen = Popup . IsMouseOver ;
} ) ) ;
2021-09-17 10:47:02 +02:00
NotificationButton . PreviewMouseLeftButtonUp + = NotificationButton_PreviewMouseLeftButtonUp ;
NotificationButton . PreviewMouseRightButtonUp + = NotificationButton_PreviewMouseRightButtonUp ;
NotificationButton . ToolTip = text . Get ( TextKey . Notification_ProctoringHandLowered ) ;
Popup . CustomPopupPlacementCallback = new CustomPopupPlacementCallback ( Popup_PlacementCallback ) ;
2023-02-27 13:25:23 +01:00
Popup . MouseLeave + = ( o , args ) = > Task . Delay ( 250 ) . ContinueWith ( _ = > Dispatcher . Invoke ( ( ) = >
{
if ( Popup . IsOpen & & lastOpenedBySpacePress )
{
return ;
}
Popup . IsOpen = IsMouseOver ;
} ) ) ;
2021-09-17 10:47:02 +02:00
Popup . Opened + = ( o , args ) = >
{
Background = Brushes . LightGray ;
NotificationButton . Background = Brushes . LightGray ;
} ;
Popup . Closed + = ( o , args ) = >
{
Background = originalBrush ;
NotificationButton . Background = originalBrush ;
2023-02-27 13:25:23 +01:00
lastOpenedBySpacePress = false ;
2021-09-17 10:47:02 +02:00
} ;
}
private void NotificationButton_PreviewMouseLeftButtonUp ( object sender , MouseButtonEventArgs e )
{
if ( settings . ForceRaiseHandMessage | | Popup . IsOpen )
{
Popup . IsOpen = ! Popup . IsOpen ;
}
else
{
ToggleHand ( ) ;
}
}
private void NotificationButton_PreviewMouseRightButtonUp ( object sender , MouseButtonEventArgs e )
{
Popup . IsOpen = ! Popup . IsOpen ;
}
private CustomPopupPlacement [ ] Popup_PlacementCallback ( Size popupSize , Size targetSize , Point offset )
{
return new [ ]
{
new CustomPopupPlacement ( new Point ( targetSize . Width / 2 - popupSize . Width / 2 , - popupSize . Height ) , PopupPrimaryAxis . None )
} ;
}
private void RaiseHandButton_Click ( object sender , RoutedEventArgs e )
{
ToggleHand ( ) ;
}
private void ToggleHand ( )
{
if ( controller . IsHandRaised )
{
controller . LowerHand ( ) ;
}
else
{
controller . RaiseHand ( Message . Text ) ;
Message . Clear ( ) ;
}
}
private void ShowLowered ( )
{
HandButtonText . Text = text . Get ( TextKey . Notification_ProctoringRaiseHand ) ;
2021-10-04 11:00:30 +02:00
Icon . Content = IconResourceLoader . Load ( LoweredIcon ) ;
2021-09-20 14:53:22 +02:00
Message . IsEnabled = true ;
2021-09-17 10:47:02 +02:00
NotificationButton . ToolTip = text . Get ( TextKey . Notification_ProctoringHandLowered ) ;
2021-10-21 11:17:27 +02:00
Popup . IsOpen = false ;
2021-09-17 10:47:02 +02:00
}
private void ShowRaised ( )
{
HandButtonText . Text = text . Get ( TextKey . Notification_ProctoringLowerHand ) ;
2021-10-04 11:00:30 +02:00
Icon . Content = IconResourceLoader . Load ( RaisedIcon ) ;
2021-09-20 14:53:22 +02:00
Message . IsEnabled = false ;
2021-09-17 10:47:02 +02:00
NotificationButton . ToolTip = text . Get ( TextKey . Notification_ProctoringHandRaised ) ;
}
}
}