2022-06-30 23:53:08 +00:00
using CommunityToolkit.Mvvm.ComponentModel ;
using MSFSPopoutPanelManager.Model ;
2022-01-27 13:40:04 +00:00
using MSFSPopoutPanelManager.Provider ;
using MSFSPopoutPanelManager.Shared ;
using System ;
using System.Linq ;
using System.Threading ;
using System.Windows ;
namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
2022-06-30 23:53:08 +00:00
public class PanelSelectionViewModel : ObservableObject
2022-01-27 13:40:04 +00:00
{
private UserProfileManager _userProfileManager ;
private PanelSelectionManager _panelSelectionManager ;
private PanelPopOutManager _panelPopoutManager ;
private SimConnectManager _simConnectManager ;
private bool _minimizeForPopOut ;
public event EventHandler OnPopOutStarted ;
public event EventHandler OnPopOutCompleted ;
2022-06-30 23:53:08 +00:00
public event EventHandler OnUserProfileChanged ;
2022-01-27 13:40:04 +00:00
2022-06-30 23:53:08 +00:00
public DataStore DataStore { get ; private set ; }
2022-01-27 13:40:04 +00:00
public bool IsEditingPanelCoorOverlay { get ; set ; }
public DelegateCommand AddProfileCommand = > new DelegateCommand ( OnAddProfile , CanExecute ) ;
public DelegateCommand DeleteProfileCommand = > new DelegateCommand ( OnDeleteProfile , CanExecute ) ;
2022-04-18 16:24:00 +00:00
public DelegateCommand ChangeProfileCommand = > new DelegateCommand ( OnChangeProfile , CanExecute ) ;
2022-01-27 13:40:04 +00:00
public DelegateCommand AddProfileBindingCommand = > new DelegateCommand ( OnAddProfileBinding , CanExecute ) ;
public DelegateCommand DeleteProfileBindingCommand = > new DelegateCommand ( OnDeleteProfileBinding , CanExecute ) ;
public DelegateCommand SetPowerOnRequiredCommand = > new DelegateCommand ( ( e ) = > _userProfileManager . WriteUserProfiles ( ) , CanExecute ) ;
public DelegateCommand StartPanelSelectionCommand = > new DelegateCommand ( OnStartPanelSelection , CanExecute ) ;
public DelegateCommand StartPopOutCommand = > new DelegateCommand ( OnStartPopOut , CanExecute ) ;
public DelegateCommand SaveAutoPanningCameraCommand = > new DelegateCommand ( OnSaveAutoPanningCamera , CanExecute ) ;
public DelegateCommand EditPanelCoorOverlayCommand = > new DelegateCommand ( OnEditPanelCoorOverlay , CanExecute ) ;
public PanelSelectionViewModel ( DataStore dataStore , UserProfileManager userProfileManager , PanelPopOutManager panelPopoutManager , SimConnectManager simConnectManager )
{
DataStore = dataStore ;
2022-06-30 23:53:08 +00:00
DataStore . OnActiveUserProfileChanged + = ( sender , e ) = >
{
2022-07-06 18:09:10 +00:00
if ( IsEditingPanelCoorOverlay & & DataStore . AppSetting . AutoDisableTrackIR )
_simConnectManager . TurnOnTrackIR ( ) ;
ShowPanelOverlay ( false ) ;
2022-04-18 16:24:00 +00:00
} ;
2022-01-27 13:40:04 +00:00
_userProfileManager = userProfileManager ;
_simConnectManager = simConnectManager ;
_panelSelectionManager = new PanelSelectionManager ( userProfileManager ) ;
_panelSelectionManager . OnPanelLocationAdded + = ( sender , e ) = > { AddPanelCoorOverlay ( e . Value ) ; } ;
_panelSelectionManager . OnPanelLocationRemoved + = ( sender , e ) = > { RemoveLastAddedPanelCoorOverlay ( ) ; } ;
_panelSelectionManager . OnAllPanelLocationsRemoved + = ( sender , e ) = > { RemoveAllPanelCoorOverlay ( ) ; } ;
_panelSelectionManager . OnPanelSelectionCompleted + = HandlePanelSelectionCompleted ;
_panelPopoutManager = panelPopoutManager ;
_panelPopoutManager . OnPopOutStarted + = HandleOnPopOutStarted ;
_panelPopoutManager . OnPopOutCompleted + = HandleOnPopOutCompleted ;
}
public void Initialize ( )
{
_userProfileManager . ReadUserProfiles ( ) ;
DataStore . UserProfiles = _userProfileManager . UserProfiles ;
2022-04-18 16:24:00 +00:00
DataStore . ActiveUserProfileId = DataStore . UserProfiles . ToList ( ) . Exists ( p = > p . ProfileId = = DataStore . AppSetting . LastUsedProfileId ) ? DataStore . AppSetting . LastUsedProfileId : - 1 ;
2022-01-27 13:40:04 +00:00
IsEditingPanelCoorOverlay = false ;
InputHookManager . SubscribeToStartPopOutEvent = true ;
}
private void OnAddProfile ( object commandParameter )
{
var param = commandParameter as AddProfileCommandParameter ;
if ( param . CopyProfileId = = - 1 )
DataStore . ActiveUserProfileId = _userProfileManager . AddUserProfile ( param . ProfileName ) ;
else
DataStore . ActiveUserProfileId = _userProfileManager . AddUserProfileByCopyingProfile ( param . ProfileName , param . CopyProfileId ) ;
2022-04-18 16:24:00 +00:00
DataStore . AppSetting . LastUsedProfileId = DataStore . ActiveUserProfileId ;
2022-01-27 13:40:04 +00:00
}
private void OnDeleteProfile ( object commandParameter )
{
if ( _userProfileManager . DeleteUserProfile ( DataStore . ActiveUserProfileId ) )
DataStore . ActiveUserProfileId = - 1 ;
}
2022-04-18 16:24:00 +00:00
private void OnChangeProfile ( object commandParameter )
2022-01-27 13:40:04 +00:00
{
2022-04-18 16:24:00 +00:00
DataStore . AppSetting . LastUsedProfileId = DataStore . ActiveUserProfileId ;
2022-06-30 23:53:08 +00:00
OnUserProfileChanged ? . Invoke ( this , null ) ;
2022-01-27 13:40:04 +00:00
}
private void OnAddProfileBinding ( object commandParameter )
{
2022-04-18 03:38:33 +00:00
var index = DataStore . ActiveUserProfileId ;
2022-01-27 13:40:04 +00:00
_userProfileManager . AddProfileBinding ( DataStore . CurrentMsfsPlaneTitle , DataStore . ActiveUserProfileId ) ;
2022-04-18 03:38:33 +00:00
// force profile refresh
DataStore . ActiveUserProfileId = - 1 ;
DataStore . ActiveUserProfileId = index ;
2022-01-27 13:40:04 +00:00
}
private void OnDeleteProfileBinding ( object commandParameter )
{
2022-04-18 03:38:33 +00:00
var index = DataStore . ActiveUserProfileId ;
_userProfileManager . DeleteProfileBinding ( DataStore . CurrentMsfsPlaneTitle , DataStore . ActiveUserProfileId ) ;
// force profile refresh
DataStore . ActiveUserProfileId = - 1 ;
DataStore . ActiveUserProfileId = index ;
2022-01-27 13:40:04 +00:00
}
private void OnStartPanelSelection ( object commandParameter )
{
2022-05-04 15:11:04 +00:00
// Turn off TrackIR if TrackIR is started
if ( DataStore . AppSetting . AutoDisableTrackIR )
_simConnectManager . TurnOffTrackIR ( ) ;
2022-07-06 18:09:10 +00:00
RemoveAllPanelCoorOverlay ( ) ;
2022-01-27 13:40:04 +00:00
WindowManager . MinimizeWindow ( DataStore . ApplicationHandle ) ; // Window hide doesn't work when try to reshow window after selection completes. So need to use minimize.
_panelSelectionManager . UserProfile = DataStore . ActiveUserProfile ;
_panelSelectionManager . AppSetting = DataStore . AppSetting ;
_panelSelectionManager . Start ( ) ;
}
private void OnStartPopOut ( object commandParameter )
{
Thread . Sleep ( 500 ) ; // allow time for the mouse to be stopped moving by the user
2022-07-06 18:09:10 +00:00
ShowPanelOverlay ( false ) ;
InputHookManager . EndHook ( ) ;
2022-01-27 13:40:04 +00:00
2022-07-06 18:09:10 +00:00
if ( ! ( DataStore . IsSimulatorStarted ) )
2022-01-27 13:40:04 +00:00
{
Logger . LogStatus ( "MSFS/SimConnect has not been started. Please try again at a later time." , StatusMessageType . Error ) ;
return ;
}
2022-07-06 18:09:10 +00:00
if ( DataStore . ActiveUserProfile . PanelSourceCoordinates . Count = = 0 )
{
Logger . LogStatus ( "No panel has been selected for the profile. Please select at least one panel." , StatusMessageType . Error ) ;
return ;
}
2022-02-07 03:05:05 +00:00
if ( DataStore . ActiveUserProfile ! = null & & DataStore . ActiveUserProfile . PanelSourceCoordinates . Count > 0 )
2022-01-27 13:40:04 +00:00
{
2022-07-06 18:09:10 +00:00
// Turn off TrackIR if TrackIR is started
if ( DataStore . AppSetting . AutoDisableTrackIR )
_simConnectManager . TurnOffTrackIR ( ) ;
2022-01-27 13:40:04 +00:00
Logger . LogStatus ( "Panels pop out in progress....." , StatusMessageType . Info ) ;
var messageDialog = new OnScreenMessageDialog ( $"Panels pop out in progress for profile:\n{DataStore.ActiveUserProfile.ProfileName}" , DataStore . AppSetting . AutoPopOutPanelsWaitDelay . InitialCockpitView ) ;
messageDialog . ShowDialog ( ) ;
// Turn on power if required to pop out panels
_simConnectManager . TurnOnPower ( DataStore . ActiveUserProfile . PowerOnRequiredForColdStart ) ;
Thread . Sleep ( DataStore . AppSetting . AutoPopOutPanelsWaitDelay . InstrumentationPowerOn * 1000 ) ; // Wait for battery to be turned on
_panelPopoutManager . UserProfile = DataStore . ActiveUserProfile ;
_panelPopoutManager . AppSetting = DataStore . AppSetting ;
_panelPopoutManager . StartPopout ( ) ;
// Turn off power if needed after pop out
_simConnectManager . TurnOffpower ( ) ;
}
}
private void OnSaveAutoPanningCamera ( object commandParameter )
{
var simualatorProcess = DiagnosticManager . GetSimulatorProcess ( ) ;
2022-07-06 18:09:10 +00:00
if ( simualatorProcess = = null )
2022-01-27 13:40:04 +00:00
{
2022-07-06 18:09:10 +00:00
Logger . LogStatus ( "MSFS/SimConnect has not been started. Please try again at a later time." , StatusMessageType . Error ) ;
return ;
2022-01-27 13:40:04 +00:00
}
2022-07-06 18:09:10 +00:00
InputEmulationManager . SaveCustomView ( simualatorProcess . Handle , DataStore . AppSetting . AutoPanningKeyBinding ) ;
Logger . LogStatus ( "Auto Panning Camera has been saved succesfully." , StatusMessageType . Info ) ;
2022-01-27 13:40:04 +00:00
}
private void OnEditPanelCoorOverlay ( object commandParameter )
{
2022-05-04 15:11:04 +00:00
// Turn off TrackIR if TrackIR is started
2022-07-06 18:09:10 +00:00
if ( DataStore . AppSetting . AutoDisableTrackIR )
2022-05-04 15:11:04 +00:00
{
2022-06-30 23:53:08 +00:00
if ( IsEditingPanelCoorOverlay )
2022-05-04 15:11:04 +00:00
_simConnectManager . TurnOffTrackIR ( ) ;
else
_simConnectManager . TurnOnTrackIR ( ) ;
}
2022-01-27 13:40:04 +00:00
if ( IsEditingPanelCoorOverlay )
{
2022-07-06 18:09:10 +00:00
ShowPanelOverlay ( true ) ;
2022-01-27 13:40:04 +00:00
_panelSelectionManager . UserProfile = DataStore . ActiveUserProfile ;
_panelSelectionManager . AppSetting = DataStore . AppSetting ;
2022-07-06 18:09:10 +00:00
if ( DataStore . AppSetting . UseAutoPanning )
InputEmulationManager . LoadCustomView ( DataStore . AppSetting . AutoPanningKeyBinding ) ;
InputHookManager . StartHook ( ) ;
2022-01-27 13:40:04 +00:00
}
else
{
2022-07-06 18:09:10 +00:00
InputHookManager . EndHook ( ) ;
ShowPanelOverlay ( false ) ;
2022-01-27 13:40:04 +00:00
}
}
private void AddPanelCoorOverlay ( PanelSourceCoordinate panelSourceCoordinate )
{
PanelCoorOverlay overlay = new PanelCoorOverlay ( panelSourceCoordinate . PanelIndex ) ;
overlay . IsEditingPanelLocation = IsEditingPanelCoorOverlay ;
2022-07-06 18:09:10 +00:00
overlay . WindowStartupLocation = WindowStartupLocation . Manual ;
overlay . MoveWindow ( panelSourceCoordinate . X , panelSourceCoordinate . Y ) ;
2022-01-27 13:40:04 +00:00
overlay . ShowInTaskbar = false ;
overlay . Show ( ) ;
2022-07-06 18:09:10 +00:00
overlay . WindowLocationChanged + = ( sender , e ) = >
{
panelSourceCoordinate . X = e . Value . X ;
panelSourceCoordinate . Y = e . Value . Y ;
_userProfileManager . WriteUserProfiles ( ) ;
} ;
2022-01-27 13:40:04 +00:00
}
private void RemoveLastAddedPanelCoorOverlay ( )
{
RemovePanelCoorOverlay ( false ) ;
}
private void RemoveAllPanelCoorOverlay ( )
{
RemovePanelCoorOverlay ( true ) ;
}
private void RemovePanelCoorOverlay ( bool removeAll )
{
for ( int i = Application . Current . Windows . Count - 1 ; i > = 1 ; i - - )
{
if ( Application . Current . Windows [ i ] . GetType ( ) = = typeof ( PanelCoorOverlay ) )
{
Application . Current . Windows [ i ] . Close ( ) ;
if ( ! removeAll )
break ;
}
}
}
private void HandleOnPopOutStarted ( object sender , EventArgs e )
{
// Hide panel coordinate overlays
2022-07-06 18:09:10 +00:00
ShowPanelOverlay ( false ) ;
2022-01-27 13:40:04 +00:00
// Close all pop out panels
WindowManager . CloseAllCustomPopoutPanels ( ) ;
2022-05-04 15:11:04 +00:00
// Turn off TrackIR if TrackIR is started
if ( DataStore . AppSetting . AutoDisableTrackIR )
_simConnectManager . TurnOffTrackIR ( ) ;
2022-01-27 13:40:04 +00:00
// Temporary minimize the app for pop out process
_minimizeForPopOut = DataStore . ApplicationWindow . WindowState ! = WindowState . Minimized ;
if ( _minimizeForPopOut )
WindowManager . MinimizeWindow ( DataStore . ApplicationHandle ) ;
OnPopOutStarted ? . Invoke ( this , null ) ;
}
private void HandleOnPopOutCompleted ( object sender , EventArgs < bool > hasResult )
{
// Restore window state
if ( _minimizeForPopOut )
{
WindowManager . BringWindowToForeground ( DataStore . ApplicationHandle ) ;
DataStore . ApplicationWindow . Show ( ) ;
}
if ( hasResult . Value )
{
OnPopOutCompleted ? . Invoke ( this , null ) ;
}
2022-05-04 15:11:04 +00:00
if ( DataStore . AppSetting . AutoDisableTrackIR )
_simConnectManager . TurnOnTrackIR ( ) ;
2022-01-27 13:40:04 +00:00
}
private void HandlePanelSelectionCompleted ( object sender , EventArgs e )
{
WindowManager . BringWindowToForeground ( DataStore . ApplicationHandle ) ;
DataStore . ApplicationWindow . Show ( ) ;
if ( DataStore . ActiveUserProfile . PanelSourceCoordinates . Count > 0 )
Logger . LogStatus ( "Panels selection is completed. Please click 'Start Pop Out' to start popping out these panels." , StatusMessageType . Info ) ;
else
Logger . LogStatus ( "Panels selection is completed. No panel has been selected." , StatusMessageType . Info ) ;
2022-05-04 15:11:04 +00:00
2022-07-06 18:09:10 +00:00
IsEditingPanelCoorOverlay = true ;
2022-01-27 13:40:04 +00:00
}
private bool CanExecute ( object commandParameter )
{
return true ;
}
2022-07-06 18:09:10 +00:00
private void ShowPanelOverlay ( bool show )
{
IsEditingPanelCoorOverlay = show ;
RemoveAllPanelCoorOverlay ( ) ;
if ( show & & DataStore . ActiveUserProfile ! = null )
DataStore . ActiveUserProfile . PanelSourceCoordinates . ToList ( ) . ForEach ( c = > AddPanelCoorOverlay ( c ) ) ;
}
2022-01-27 13:40:04 +00:00
}
public class AddProfileCommandParameter
{
public string ProfileName { get ; set ; }
public int CopyProfileId { get ; set ; }
}
}