1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-11-22 05:40:11 +00:00

Preview release

This commit is contained in:
hawkeye 2022-06-12 23:49:56 -04:00
parent e84fac2123
commit 96b5ae8d8d
8 changed files with 187 additions and 54 deletions

View file

@ -28,10 +28,45 @@ namespace MSFSPopoutPanelManager.Model
public bool FullScreen { get; set; } public bool FullScreen { get; set; }
public bool TouchEnabled { get; set; }
[JsonIgnore] [JsonIgnore]
public bool IsCustomPopout { get { return PanelType == PanelType.CustomPopout; } } public bool IsCustomPopout { get { return PanelType == PanelType.CustomPopout; } }
[JsonIgnore] [JsonIgnore]
public IntPtr PanelHandle { get; set; } public IntPtr PanelHandle { get; set; }
[JsonIgnore]
public bool IsLockable
{
get
{
switch (PanelType)
{
case PanelType.CustomPopout:
case PanelType.BuiltInPopout:
case PanelType.MSFSTouchPanel:
return true;
default:
return false;
}
}
}
[JsonIgnore]
public bool HasTouchableEvent
{
get
{
switch (PanelType)
{
case PanelType.CustomPopout:
case PanelType.BuiltInPopout:
return true;
default:
return false;
}
}
}
} }
} }

View file

@ -12,6 +12,7 @@ namespace MSFSPopoutPanelManager.Model
AlwaysOnTop, AlwaysOnTop,
HideTitlebar, HideTitlebar,
FullScreen, FullScreen,
TouchEnabled,
Invalid Invalid
} }

View file

@ -32,6 +32,13 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0); PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
} }
public static void LeftClickFast(int x, int y)
{
PInvoke.mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
Thread.Sleep(50);
PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
}
public static void PopOutPanel(int x, int y) public static void PopOutPanel(int x, int y)
{ {
LeftClick(x, y); LeftClick(x, y);

View file

@ -16,6 +16,9 @@ namespace MSFSPopoutPanelManager.Provider
public const int SW_MINIMIZE = 6; public const int SW_MINIMIZE = 6;
public const int SW_RESTORE = 9; public const int SW_RESTORE = 9;
public const uint EVENT_SYSTEM_CAPTURESTART = 0x0008;
public const uint EVENT_SYSTEM_CAPTUREEND = 0x0009;
public const uint EVENT_SYSTEM_MOVESIZESTART = 0x000A;
public const uint EVENT_SYSTEM_MOVESIZEEND = 0x000B; public const uint EVENT_SYSTEM_MOVESIZEEND = 0x000B;
public const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B; public const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B;

View file

@ -1,7 +1,10 @@
using MSFSPopoutPanelManager.Model; using MSFSPopoutPanelManager.Model;
using System; using System;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MSFSPopoutPanelManager.Provider namespace MSFSPopoutPanelManager.Provider
{ {
@ -11,6 +14,8 @@ namespace MSFSPopoutPanelManager.Provider
private IntPtr _winEventHook; private IntPtr _winEventHook;
private static PInvoke.WinEventProc _winEvent; // keep this as static to prevent garbage collect or the app will crash private static PInvoke.WinEventProc _winEvent; // keep this as static to prevent garbage collect or the app will crash
private Rectangle _lastWindowRectangle; private Rectangle _lastWindowRectangle;
private uint _prevWinEvent = PInvokeConstant.EVENT_SYSTEM_CAPTUREEND;
private int _winEventClickLock = 0;
public UserProfile UserProfile { get; set; } public UserProfile UserProfile { get; set; }
@ -26,7 +31,7 @@ namespace MSFSPopoutPanelManager.Provider
public void HookWinEvent() public void HookWinEvent()
{ {
// Setup panel config event hooks // Setup panel config event hooks
_winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, DiagnosticManager.GetApplicationProcess().Handle, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT); _winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_CAPTURESTART, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, DiagnosticManager.GetApplicationProcess().Handle, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
} }
public void UnhookWinEvent() public void UnhookWinEvent()
@ -173,34 +178,46 @@ namespace MSFSPopoutPanelManager.Provider
private void EventCallback(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime) private void EventCallback(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime)
{ {
PanelConfig panelConfig; switch(iEvent)
// check by priority to minimize escaping constraint
if (hWnd == IntPtr.Zero
|| idObject != 0
|| hWinEventHook != _winEventHook
|| !AllowEdit
|| !(iEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE || iEvent == PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND)
|| UserProfile.PanelConfigs == null || UserProfile.PanelConfigs.Count == 0)
{ {
return; case PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE:
} case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
case PInvokeConstant.EVENT_SYSTEM_CAPTURESTART:
if(UserProfile.IsLocked) case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
{ // check by priority to speed up comparing of escaping constraints
panelConfig = UserProfile.PanelConfigs.FirstOrDefault(panel => panel.PanelHandle == hWnd); if (hWnd == IntPtr.Zero
|| idObject != 0
if (panelConfig != null && panelConfig.PanelType == PanelType.CustomPopout) || hWinEventHook != _winEventHook
{ || !AllowEdit
// Move window back to original location if user profile is locked || UserProfile.PanelConfigs == null
if (iEvent == PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND) || UserProfile.PanelConfigs.Count == 0)
{ {
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
return; return;
} }
if (iEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE) HandleEventCallback(hWnd, iEvent);
{ break;
default:
break;
}
}
private void HandleEventCallback(IntPtr hWnd, uint iEvent)
{
var panelConfig = UserProfile.PanelConfigs.FirstOrDefault(panel => panel.PanelHandle == hWnd);
if (panelConfig == null)
return;
if (panelConfig.IsLockable && UserProfile.IsLocked)
{
switch (iEvent)
{
case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
// Move window back to original location
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
break;
case PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE:
// Detect if window is maximized, if so, save settings // Detect if window is maximized, if so, save settings
WINDOWPLACEMENT wp = new WINDOWPLACEMENT(); WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
wp.length = System.Runtime.InteropServices.Marshal.SizeOf(wp); wp.length = System.Runtime.InteropServices.Marshal.SizeOf(wp);
@ -209,16 +226,19 @@ namespace MSFSPopoutPanelManager.Provider
{ {
PInvoke.ShowWindow(hWnd, PInvokeConstant.SW_RESTORE); PInvoke.ShowWindow(hWnd, PInvokeConstant.SW_RESTORE);
} }
return; break;
} case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
if (!panelConfig.TouchEnabled || _prevWinEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
break;
if (!panelConfig.HasTouchableEvent || _prevWinEvent == PInvokeConstant.EVENT_SYSTEM_CAPTUREEND)
break;
HandleTouchEvent(panelConfig);
break;
} }
return;
} }
else
panelConfig = UserProfile.PanelConfigs.FirstOrDefault(panel => panel.PanelHandle == hWnd);
if (panelConfig != null)
{ {
switch (iEvent) switch (iEvent)
{ {
@ -260,8 +280,54 @@ namespace MSFSPopoutPanelManager.Provider
case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND: case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
_userProfileManager.WriteUserProfiles(); _userProfileManager.WriteUserProfiles();
break; break;
case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
if (!panelConfig.TouchEnabled || _prevWinEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
break;
if (!panelConfig.HasTouchableEvent || _prevWinEvent == PInvokeConstant.EVENT_SYSTEM_CAPTUREEND)
break;
HandleTouchEvent(panelConfig);
break;
} }
} }
_prevWinEvent = iEvent;
}
private void HandleTouchEvent(PanelConfig panelConfig)
{
Point point;
PInvoke.GetCursorPos(out point);
// Disable left clicking if user is touching the title bar area
if (point.Y - panelConfig.Top > (panelConfig.HideTitlebar ? 5 : 31))
{
var prevWinEventClickLock = ++_winEventClickLock;
UnhookWinEvent();
InputEmulationManager.LeftClickFast(point.X, point.Y);
HookWinEvent();
if (prevWinEventClickLock == _winEventClickLock)
{
Task.Run(() => RefocusMsfs(prevWinEventClickLock));
}
}
}
private async Task RefocusMsfs(int prevWinEventClickLock)
{
Thread.Sleep(1000);
if (prevWinEventClickLock == _winEventClickLock)
{
var simulatorProcess = DiagnosticManager.GetSimulatorProcess();
Rectangle rectangle;
PInvoke.GetWindowRect(simulatorProcess.Handle, out rectangle);
PInvoke.SetCursorPos(rectangle.X + 18, rectangle.Y + 80);
}
} }
} }
} }

View file

@ -215,13 +215,13 @@ namespace MSFSPopoutPanelManager.Provider
}); });
// Remove pop out that do not exist for this pop out iteration // Remove pop out that do not exist for this pop out iteration
foreach(var panelConfig in UserProfile.PanelConfigs.ToList()) //foreach(var panelConfig in UserProfile.PanelConfigs.ToList())
{ //{
if(panelConfig.PanelHandle == IntPtr.Zero) // if(panelConfig.PanelHandle == IntPtr.Zero)
{ // {
UserProfile.PanelConfigs.Remove(panelConfig); // UserProfile.PanelConfigs.Remove(panelConfig);
} // }
} //}
Parallel.ForEach(UserProfile.PanelConfigs, panel => Parallel.ForEach(UserProfile.PanelConfigs, panel =>
{ {
@ -254,6 +254,14 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false); PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false);
Thread.Sleep(1000); Thread.Sleep(1000);
// Built-in panels (ie. Checklist, ATC) needs another window resize since there is a bug where when move between
// monitors, it changes its size
if(panel.PanelType == PanelType.BuiltInPopout)
{
PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false);
Thread.Sleep(1000);
}
// Apply always on top // Apply always on top
if (panel.AlwaysOnTop) if (panel.AlwaysOnTop)
{ {

View file

@ -91,10 +91,10 @@
</Style> </Style>
</DataGrid.CellStyle> </DataGrid.CellStyle>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTemplateColumn Header="Panel Name" Width="250" > <DataGridTemplateColumn Header="Panel Name" Width="230" >
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextBox Name="PanelName" Width="250" BorderThickness="0" TextAlignment="Left" Text="{Binding Path=PanelName, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}" <TextBox Name="PanelName" Width="230" BorderThickness="0" TextAlignment="Left" Text="{Binding Path=PanelName, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}"
SourceUpdated="GridData_SourceUpdated" IsReadOnly="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='DataContext.DataStore.ActiveUserProfile.IsLocked or !DataContext.DataStore.AllowEdit'}" IsEnabled="{Binding Path=IsCustomPopout, Mode=OneWay}"> SourceUpdated="GridData_SourceUpdated" IsReadOnly="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='DataContext.DataStore.ActiveUserProfile.IsLocked or !DataContext.DataStore.AllowEdit'}" IsEnabled="{Binding Path=IsCustomPopout, Mode=OneWay}">
<TextBox.Style> <TextBox.Style>
<Style TargetType="TextBox"> <Style TargetType="TextBox">
@ -117,10 +117,10 @@
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="X-Pos" Width="90"> <DataGridTemplateColumn Header="X-Pos" Width="80">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextBox Name="Left" Width="90" BorderThickness="0" <TextBox Name="Left" Width="80" BorderThickness="0"
Text="{Binding Path=Left, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}" Text="{Binding Path=Left, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
Style="{StaticResource TextBoxColumnFocus}" Style="{StaticResource TextBoxColumnFocus}"
@ -128,10 +128,10 @@
IsHitTestVisible="{c:Binding Path='!FullScreen'}"/> </DataTemplate> IsHitTestVisible="{c:Binding Path='!FullScreen'}"/> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Y-Pos" Width="90"> <DataGridTemplateColumn Header="Y-Pos" Width="80">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextBox Name="Top" Width="90" BorderThickness="0" <TextBox Name="Top" Width="80" BorderThickness="0"
Text="{Binding Path=Top, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}" Text="{Binding Path=Top, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
Style="{StaticResource TextBoxColumnFocus}" Style="{StaticResource TextBoxColumnFocus}"
@ -140,10 +140,10 @@
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Width" Width="90"> <DataGridTemplateColumn Header="Width" Width="80">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextBox Name="Width" Width="90" BorderThickness="0" <TextBox Name="Width" Width="80" BorderThickness="0"
Text="{Binding Path=Width, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}" Text="{Binding Path=Width, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
Style="{StaticResource TextBoxColumnFocus}" Style="{StaticResource TextBoxColumnFocus}"
@ -152,10 +152,10 @@
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Height" Width="90"> <DataGridTemplateColumn Header="Height" Width="80">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextBox Name="Height" Width="90" BorderThickness="0" <TextBox Name="Height" Width="80" BorderThickness="0"
Text="{Binding Path=Height, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}" Text="{Binding Path=Height, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=LostFocus}"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
Style="{StaticResource TextBoxColumnFocus}" Style="{StaticResource TextBoxColumnFocus}"
@ -164,10 +164,10 @@
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Always on Top" Width="90"> <DataGridTemplateColumn Header="Always on Top" Width="80">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<CheckBox Name="AlwaysOnTop" Width="90" Margin="40 0 0 0" <CheckBox Name="AlwaysOnTop" Width="80" Margin="30 0 0 0"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
IsChecked="{Binding Path=AlwaysOnTop, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" IsChecked="{Binding Path=AlwaysOnTop, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}" IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}"
@ -175,10 +175,10 @@
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Hide Title Bar" Width="90"> <DataGridTemplateColumn Header="Hide Title Bar" Width="80">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<CheckBox Name="HideTitlebar" Width="90" Margin="40 0 0 0" <CheckBox Name="HideTitlebar" Width="80" Margin="30 0 0 0"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
IsChecked="{Binding Path=HideTitlebar, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" IsChecked="{Binding Path=HideTitlebar, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}" IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}"
@ -189,13 +189,23 @@
<DataGridTemplateColumn Header="Full Screen Mode" Width="90"> <DataGridTemplateColumn Header="Full Screen Mode" Width="90">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<CheckBox Name="FullScreen" Width="90" Margin="40 0 0 0" <CheckBox Name="FullScreen" Width="90" Margin="35 0 0 0"
SourceUpdated="GridData_SourceUpdated" SourceUpdated="GridData_SourceUpdated"
IsChecked="{Binding Path=FullScreen, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" IsChecked="{Binding Path=FullScreen, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}"/> IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}"/>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Touch Enabled" Width="80">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="TouchEnabled" Width="80" Margin="30 0 0 0"
SourceUpdated="GridData_SourceUpdated"
IsChecked="{Binding Path=TouchEnabled, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='!DataContext.DataStore.ActiveUserProfile.IsLocked and DataContext.DataStore.AllowEdit'}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</WrapPanel> </WrapPanel>

View file

@ -68,6 +68,9 @@ namespace MSFSPopoutPanelManager.WpfApp
case "Full Screen Mode": case "Full Screen Mode":
selectedProperty = PanelConfigPropertyName.FullScreen; selectedProperty = PanelConfigPropertyName.FullScreen;
break; break;
case "Touch Enabled":
selectedProperty = PanelConfigPropertyName.TouchEnabled;
break;
} }
_panelConfigurationViewModel.SelectedPanelConfigItem = new PanelConfigItem() { PanelIndex = panelConfig.PanelIndex, PanelConfigProperty = selectedProperty }; _panelConfigurationViewModel.SelectedPanelConfigItem = new PanelConfigItem() { PanelIndex = panelConfig.PanelIndex, PanelConfigProperty = selectedProperty };