mirror of
https://github.com/hawkeye-stan/msfs-popout-panel-manager.git
synced 2024-12-26 22:32:01 +00:00
Version v4.0.0 Release
This commit is contained in:
parent
bff0412386
commit
5d4d5dcac3
552 changed files with 10794 additions and 74126 deletions
4
.editorconfig
Normal file
4
.editorconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
[*.cs]
|
||||
|
||||
# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
dotnet_diagnostic.CS8618.severity = none
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,6 +8,7 @@
|
|||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.backup
|
||||
.nuget/
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
#include <Joystick.h>
|
||||
#include <NewEncoder.h>
|
||||
|
||||
// Rotary Encoder Inputs
|
||||
#define CLK1 19
|
||||
#define DT1 18
|
||||
#define SW1 17
|
||||
|
||||
#define CLK2 2
|
||||
#define DT2 3
|
||||
#define SW2 4
|
||||
|
||||
#define VRx A0
|
||||
#define VRy A1
|
||||
#define JSW 8
|
||||
|
||||
// Rotatry encoder variables
|
||||
int currentStateCLK1;
|
||||
int lastStateCLK1;
|
||||
int currentStateCLK2;
|
||||
int lastStateCLK2;
|
||||
|
||||
String currentEvent = "";
|
||||
String currentDir1 = "";
|
||||
String currentDir2 = "";
|
||||
boolean rotaryEncoderRotating1 = false;
|
||||
boolean rotaryEncoderRotating2 = false;
|
||||
|
||||
unsigned long lastButton1Press = 0;
|
||||
unsigned long lastButton2Press = 0;
|
||||
|
||||
Joystick joystick(VRx, VRy, JSW);
|
||||
|
||||
NewEncoder encoderLower(DT1, CLK1, -32768, 32767, 0, FULL_PULSE);
|
||||
NewEncoder encoderUpper(DT2, CLK2, -32768, 32767, 0, FULL_PULSE);
|
||||
int16_t prevEncoderValueLower;
|
||||
int16_t prevEncoderValueUpper;
|
||||
|
||||
void setup() {
|
||||
// Set encoder pins as inputs
|
||||
pinMode(SW1, INPUT_PULLUP);
|
||||
pinMode(SW2, INPUT_PULLUP);
|
||||
|
||||
// Setup joystick
|
||||
joystick.initialize();
|
||||
joystick.calibrate();
|
||||
joystick.setSensivity(3);
|
||||
|
||||
// Setup Serial Monitor
|
||||
Serial.begin(9600);
|
||||
|
||||
NewEncoder::EncoderState encoderState1;
|
||||
NewEncoder::EncoderState encoderState2;
|
||||
|
||||
encoderLower.begin();
|
||||
encoderLower.getState(encoderState1);
|
||||
prevEncoderValueLower = encoderState1.currentValue;
|
||||
|
||||
encoderUpper.begin();
|
||||
encoderUpper.getState(encoderState2);
|
||||
prevEncoderValueUpper = encoderState2.currentValue;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int16_t currentEncoderValueLower;
|
||||
int16_t currentEncoderValueUpper;
|
||||
NewEncoder::EncoderState currentEncoderStateLower;
|
||||
NewEncoder::EncoderState currentEncoderStateUpper;
|
||||
|
||||
// Read rotary encoder lower
|
||||
if (encoderLower.getState(currentEncoderStateLower)) {
|
||||
currentEncoderValueLower = currentEncoderStateLower.currentValue;
|
||||
if (currentEncoderValueLower != prevEncoderValueLower) {
|
||||
if(currentEncoderValueLower > prevEncoderValueLower){
|
||||
Serial.println("EncoderLower:CW:" + String(currentEncoderValueLower - prevEncoderValueLower));
|
||||
}
|
||||
else{
|
||||
Serial.println("EncoderLower:CCW:" + String(prevEncoderValueLower - currentEncoderValueLower));
|
||||
}
|
||||
prevEncoderValueLower = currentEncoderValueLower;
|
||||
}
|
||||
}
|
||||
|
||||
// Read rotary encoder upper
|
||||
if (encoderUpper.getState(currentEncoderStateUpper)) {
|
||||
currentEncoderValueUpper = currentEncoderStateUpper.currentValue;
|
||||
if (currentEncoderValueUpper != prevEncoderValueUpper) {
|
||||
if(currentEncoderValueUpper > prevEncoderValueUpper){
|
||||
Serial.println("EncoderUpper:CW:" + String(currentEncoderValueUpper - prevEncoderValueUpper));
|
||||
}
|
||||
else{
|
||||
Serial.println("EncoderUpper:CCW:" + String(prevEncoderValueUpper - currentEncoderValueUpper));
|
||||
}
|
||||
prevEncoderValueUpper = currentEncoderValueUpper;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the rotary encoder button state
|
||||
int btnState1 = digitalRead(SW1);
|
||||
int btnState2 = digitalRead(SW2);
|
||||
|
||||
//If we detect LOW signal, button is pressed
|
||||
if (btnState1 == LOW) {
|
||||
//if 500ms have passed since last LOW pulse, it means that the
|
||||
//button has been pressed, released and pressed again
|
||||
if (millis() - lastButton1Press > 500) {
|
||||
Serial.println("EncoderLower:SW");
|
||||
}
|
||||
|
||||
// Remember last button press event
|
||||
lastButton1Press = millis();
|
||||
}
|
||||
|
||||
if (btnState2 == LOW) {
|
||||
//if 500ms have passed since last LOW pulse, it means that the
|
||||
//button has been pressed, released and pressed again
|
||||
if (millis() - lastButton2Press > 500) {
|
||||
Serial.println("EncoderUpper:SW");
|
||||
}
|
||||
|
||||
// Remember last button press event
|
||||
lastButton2Press = millis();
|
||||
}
|
||||
|
||||
// Read joystick
|
||||
if(joystick.isPressed())
|
||||
{
|
||||
Serial.println("Joystick:SW");
|
||||
}
|
||||
|
||||
if(joystick.isReleased())
|
||||
{
|
||||
// left
|
||||
if(joystick.isLeft())
|
||||
{
|
||||
Serial.println("Joystick:UP");
|
||||
}
|
||||
|
||||
// right
|
||||
if(joystick.isRight())
|
||||
{
|
||||
Serial.println("Joystick:DOWN");
|
||||
}
|
||||
|
||||
// up
|
||||
if(joystick.isUp())
|
||||
{
|
||||
Serial.println("Joystick:RIGHT");
|
||||
}
|
||||
|
||||
// down
|
||||
if(joystick.isDown())
|
||||
{
|
||||
Serial.println("Joystick:LEFT");
|
||||
}
|
||||
}
|
||||
|
||||
// slow down a bit
|
||||
delay(200);
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
#include <Joystick.h>
|
||||
#include <NewEncoder.h>
|
||||
|
||||
// Rotary Encoder Inputs
|
||||
#define CLK1 19
|
||||
#define DT1 18
|
||||
#define SW1 17
|
||||
|
||||
#define CLK2 2
|
||||
#define DT2 3
|
||||
#define SW2 4
|
||||
|
||||
#define VRx A0
|
||||
#define VRy A1
|
||||
#define JSW 8
|
||||
|
||||
// Rotatry encoder variables
|
||||
int currentStateCLK1;
|
||||
int lastStateCLK1;
|
||||
int currentStateCLK2;
|
||||
int lastStateCLK2;
|
||||
|
||||
String currentEvent = "";
|
||||
String currentDir1 = "";
|
||||
String currentDir2 = "";
|
||||
boolean rotaryEncoderRotating1 = false;
|
||||
boolean rotaryEncoderRotating2 = false;
|
||||
|
||||
unsigned long lastButton1Press = 0;
|
||||
unsigned long lastButton2Press = 0;
|
||||
|
||||
Joystick joystick(VRx, VRy, JSW);
|
||||
|
||||
NewEncoder encoderLower(DT1, CLK1, -32768, 32767, 0, FULL_PULSE);
|
||||
NewEncoder encoderUpper(DT2, CLK2, -32768, 32767, 0, FULL_PULSE);
|
||||
int16_t prevEncoderValueLower;
|
||||
int16_t prevEncoderValueUpper;
|
||||
|
||||
void setup() {
|
||||
// Set encoder pins as inputs
|
||||
pinMode(SW1, INPUT_PULLUP);
|
||||
pinMode(SW2, INPUT_PULLUP);
|
||||
|
||||
// Setup joystick
|
||||
joystick.initialize();
|
||||
joystick.calibrate();
|
||||
joystick.setSensivity(3);
|
||||
|
||||
// Setup Serial Monitor
|
||||
Serial.begin(9600);
|
||||
|
||||
NewEncoder::EncoderState encoderState1;
|
||||
NewEncoder::EncoderState encoderState2;
|
||||
|
||||
encoderLower.begin();
|
||||
encoderLower.getState(encoderState1);
|
||||
prevEncoderValueLower = encoderState1.currentValue;
|
||||
|
||||
encoderUpper.begin();
|
||||
encoderUpper.getState(encoderState2);
|
||||
prevEncoderValueUpper = encoderState2.currentValue;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int16_t currentEncoderValueLower;
|
||||
int16_t currentEncoderValueUpper;
|
||||
NewEncoder::EncoderState currentEncoderStateLower;
|
||||
NewEncoder::EncoderState currentEncoderStateUpper;
|
||||
|
||||
// Read rotary encoder lower
|
||||
if (encoderLower.getState(currentEncoderStateLower)) {
|
||||
currentEncoderValueLower = currentEncoderStateLower.currentValue;
|
||||
if (currentEncoderValueLower != prevEncoderValueLower) {
|
||||
if(currentEncoderValueLower > prevEncoderValueLower){
|
||||
Serial.println("EncoderLower:CW:" + String(currentEncoderValueLower - prevEncoderValueLower));
|
||||
}
|
||||
else{
|
||||
Serial.println("EncoderLower:CCW:" + String(prevEncoderValueLower - currentEncoderValueLower));
|
||||
}
|
||||
prevEncoderValueLower = currentEncoderValueLower;
|
||||
}
|
||||
}
|
||||
|
||||
// Read rotary encoder upper
|
||||
if (encoderUpper.getState(currentEncoderStateUpper)) {
|
||||
currentEncoderValueUpper = currentEncoderStateUpper.currentValue;
|
||||
if (currentEncoderValueUpper != prevEncoderValueUpper) {
|
||||
if(currentEncoderValueUpper > prevEncoderValueUpper){
|
||||
Serial.println("EncoderUpper:CW:" + String(currentEncoderValueUpper - prevEncoderValueUpper));
|
||||
}
|
||||
else{
|
||||
Serial.println("EncoderUpper:CCW:" + String(prevEncoderValueUpper - currentEncoderValueUpper));
|
||||
}
|
||||
prevEncoderValueUpper = currentEncoderValueUpper;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the rotary encoder button state
|
||||
int btnState1 = digitalRead(SW1);
|
||||
int btnState2 = digitalRead(SW2);
|
||||
|
||||
//If we detect LOW signal, button is pressed
|
||||
if (btnState1 == LOW) {
|
||||
//if 500ms have passed since last LOW pulse, it means that the
|
||||
//button has been pressed, released and pressed again
|
||||
if (millis() - lastButton1Press > 500) {
|
||||
Serial.println("EncoderLower:SW");
|
||||
}
|
||||
|
||||
// Remember last button press event
|
||||
lastButton1Press = millis();
|
||||
}
|
||||
|
||||
if (btnState2 == LOW) {
|
||||
//if 500ms have passed since last LOW pulse, it means that the
|
||||
//button has been pressed, released and pressed again
|
||||
if (millis() - lastButton2Press > 500) {
|
||||
Serial.println("EncoderUpper:SW");
|
||||
}
|
||||
|
||||
// Remember last button press event
|
||||
lastButton2Press = millis();
|
||||
}
|
||||
|
||||
// Read joystick
|
||||
if(joystick.isPressed())
|
||||
{
|
||||
Serial.println("Joystick:SW");
|
||||
}
|
||||
|
||||
if(joystick.isReleased())
|
||||
{
|
||||
// left
|
||||
if(joystick.isLeft())
|
||||
{
|
||||
Serial.println("Joystick:LEFT");
|
||||
}
|
||||
|
||||
// right
|
||||
if(joystick.isRight())
|
||||
{
|
||||
Serial.println("Joystick:RIGHT");
|
||||
}
|
||||
|
||||
// up
|
||||
if(joystick.isUp())
|
||||
{
|
||||
Serial.println("Joystick:UP");
|
||||
}
|
||||
|
||||
// down
|
||||
if(joystick.isDown())
|
||||
{
|
||||
Serial.println("Joystick:DOWN");
|
||||
}
|
||||
}
|
||||
|
||||
// slow down a bit
|
||||
delay(200);
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,197 +0,0 @@
|
|||
#include <Joystick.h>
|
||||
#include <NewEncoder.h>
|
||||
#include <Keypad.h>
|
||||
|
||||
// Rotary Encoder Inputs
|
||||
#define CLK1 19
|
||||
#define DT1 18
|
||||
#define SW1 17
|
||||
|
||||
#define CLK2 2
|
||||
#define DT2 3
|
||||
#define SW2 4
|
||||
|
||||
#define VRx A0
|
||||
#define VRy A1
|
||||
|
||||
const byte ROWS = 4;
|
||||
const byte COLS = 4;
|
||||
|
||||
char hexaKeys[ROWS][COLS] = {
|
||||
{'1', '2', '3', 'A'},
|
||||
{'4', '5', '6', 'B'},
|
||||
{'7', '8', '9', 'C'},
|
||||
{'*', '0', '#', 'D'}
|
||||
};
|
||||
|
||||
byte rowPins[ROWS] = {31, 33, 35, 37};
|
||||
byte colPins[COLS] = {39, 41, 43, 45};
|
||||
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
|
||||
|
||||
// Rotatry encoder variables
|
||||
int currentStateCLK1;
|
||||
int lastStateCLK1;
|
||||
int currentStateCLK2;
|
||||
int lastStateCLK2;
|
||||
|
||||
String currentEvent = "";
|
||||
String currentDir1 = "";
|
||||
String currentDir2 = "";
|
||||
boolean rotaryEncoderRotating1 = false;
|
||||
boolean rotaryEncoderRotating2 = false;
|
||||
|
||||
unsigned long lastButton1Press = 0;
|
||||
unsigned long lastButton2Press = 0;
|
||||
|
||||
Joystick joystick(VRx, VRy, 8);
|
||||
|
||||
NewEncoder encoderLower(DT1, CLK1, -32768, 32767, 0, FULL_PULSE);
|
||||
NewEncoder encoderUpper(DT2, CLK2, -32768, 32767, 0, FULL_PULSE);
|
||||
int16_t prevEncoderValueLower;
|
||||
int16_t prevEncoderValueUpper;
|
||||
|
||||
void setup() {
|
||||
// Set encoder pins as inputs
|
||||
pinMode(SW1, INPUT_PULLUP);
|
||||
pinMode(SW2, INPUT_PULLUP);
|
||||
|
||||
// Setup joystick
|
||||
joystick.initialize();
|
||||
joystick.calibrate();
|
||||
joystick.setSensivity(3);
|
||||
|
||||
// Setup Serial Monitor
|
||||
Serial.begin(9600);
|
||||
|
||||
NewEncoder::EncoderState encoderState1;
|
||||
NewEncoder::EncoderState encoderState2;
|
||||
|
||||
encoderLower.begin();
|
||||
encoderLower.getState(encoderState1);
|
||||
prevEncoderValueLower = encoderState1.currentValue;
|
||||
|
||||
encoderUpper.begin();
|
||||
encoderUpper.getState(encoderState2);
|
||||
prevEncoderValueUpper = encoderState2.currentValue;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int16_t currentEncoderValueLower;
|
||||
int16_t currentEncoderValueUpper;
|
||||
NewEncoder::EncoderState currentEncoderStateLower;
|
||||
NewEncoder::EncoderState currentEncoderStateUpper;
|
||||
|
||||
// Read rotary encoder lower
|
||||
if (encoderLower.getState(currentEncoderStateLower)) {
|
||||
currentEncoderValueLower = currentEncoderStateLower.currentValue;
|
||||
if (currentEncoderValueLower != prevEncoderValueLower) {
|
||||
if(currentEncoderValueLower > prevEncoderValueLower){
|
||||
Serial.println("EncoderLower:CW:" + String(currentEncoderValueLower - prevEncoderValueLower));
|
||||
}
|
||||
else{
|
||||
Serial.println("EncoderLower:CCW:" + String(prevEncoderValueLower - currentEncoderValueLower));
|
||||
}
|
||||
prevEncoderValueLower = currentEncoderValueLower;
|
||||
}
|
||||
}
|
||||
|
||||
// Read rotary encoder upper
|
||||
if (encoderUpper.getState(currentEncoderStateUpper)) {
|
||||
currentEncoderValueUpper = currentEncoderStateUpper.currentValue;
|
||||
if (currentEncoderValueUpper != prevEncoderValueUpper) {
|
||||
if(currentEncoderValueUpper > prevEncoderValueUpper){
|
||||
Serial.println("EncoderUpper:CW:" + String(currentEncoderValueUpper - prevEncoderValueUpper));
|
||||
}
|
||||
else{
|
||||
Serial.println("EncoderUpper:CCW:" + String(prevEncoderValueUpper - currentEncoderValueUpper));
|
||||
}
|
||||
prevEncoderValueUpper = currentEncoderValueUpper;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the rotary encoder button state
|
||||
int btnState1 = digitalRead(SW1);
|
||||
int btnState2 = digitalRead(SW2);
|
||||
|
||||
//If we detect LOW signal, button is pressed
|
||||
if (btnState1 == LOW) {
|
||||
//if 500ms have passed since last LOW pulse, it means that the
|
||||
//button has been pressed, released and pressed again
|
||||
if (millis() - lastButton1Press > 500) {
|
||||
Serial.println("EncoderLower:SW");
|
||||
}
|
||||
|
||||
// Remember last button press event
|
||||
lastButton1Press = millis();
|
||||
}
|
||||
|
||||
if (btnState2 == LOW) {
|
||||
//if 500ms have passed since last LOW pulse, it means that the
|
||||
//button has been pressed, released and pressed again
|
||||
if (millis() - lastButton2Press > 500) {
|
||||
Serial.println("EncoderUpper:SW");
|
||||
}
|
||||
|
||||
// Remember last button press event
|
||||
lastButton2Press = millis();
|
||||
}
|
||||
|
||||
// Read joystick
|
||||
if(joystick.isPressed())
|
||||
{
|
||||
Serial.println("Joystick:SW");
|
||||
}
|
||||
|
||||
// Read joystick (updated for joystick mounted at 90 degree)
|
||||
if(joystick.isReleased())
|
||||
{
|
||||
// left
|
||||
if(joystick.isLeft())
|
||||
{
|
||||
//Serial.println("Joystick:LEFT");
|
||||
Serial.println("Joystick:UP");
|
||||
}
|
||||
|
||||
// right
|
||||
if(joystick.isRight())
|
||||
{
|
||||
//Serial.println("Joystick:RIGHT");
|
||||
Serial.println("Joystick:DOWN");
|
||||
}
|
||||
|
||||
// up
|
||||
if(joystick.isUp())
|
||||
{
|
||||
//Serial.println("Joystick:UP");
|
||||
Serial.println("Joystick:RIGHT");
|
||||
}
|
||||
|
||||
// down
|
||||
if(joystick.isDown())
|
||||
{
|
||||
//Serial.println("Joystick:DOWN");
|
||||
Serial.println("Joystick:LEFT");
|
||||
}
|
||||
}
|
||||
|
||||
// Read keypad
|
||||
char customKey = customKeypad.getKey();
|
||||
|
||||
if (customKey){
|
||||
if(customKey == '#')
|
||||
{
|
||||
Serial.println("Keypad:KeyPound");
|
||||
}
|
||||
else if(customKey == '*')
|
||||
{
|
||||
Serial.println("Keypad:KeyAsterisk");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Keypad:Key" + String(customKey));
|
||||
}
|
||||
}
|
||||
|
||||
// slow down a bit
|
||||
delay(100);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>ArduinoAgent</AssemblyName>
|
||||
<PackageId>MSFS 2020 Popout Panel Manager ArduinoAgent</PackageId>
|
||||
<Product>MSFS 2020 Popout Panel Manager ArduinoAgent</Product>
|
||||
<Authors>Stanley Kwok</Authors>
|
||||
<Company>Stanley Kwok</Company>
|
||||
<Copyright>Stanley Kwok 2021</Copyright>
|
||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||
<RootNamespace>MSFSPopoutPanelManager.ArduinoAgent</RootNamespace>
|
||||
<Platforms>x64</Platforms>
|
||||
<Version>3.4.6.0321</Version>
|
||||
<AssemblyVersion>3.4.6.0321</AssemblyVersion>
|
||||
<FileVersion>3.4.6.0321</FileVersion>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<DebugType>Embedded</DebugType>
|
||||
<Configurations>Debug;Release;DebugTouchPanel;ReleaseTouchPanel</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugTouchPanel|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Ports" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,62 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace MSFSPopoutPanelManager.ArduinoAgent
|
||||
{
|
||||
public class ArduinoInputData
|
||||
{
|
||||
public ArduinoInputData(string inputName, string inputAction, int acceleration)
|
||||
{
|
||||
InputName = (InputName)Enum.Parse(typeof(InputName), inputName);
|
||||
InputAction = (InputAction)Enum.Parse(typeof(InputAction), inputAction);
|
||||
Acceleration = acceleration;
|
||||
}
|
||||
|
||||
public InputName InputName { get; set; }
|
||||
|
||||
public InputAction InputAction { get; set; }
|
||||
|
||||
public int Acceleration { get; set; }
|
||||
}
|
||||
|
||||
public enum InputAction
|
||||
{
|
||||
NONE,
|
||||
|
||||
// Rotary Encoder
|
||||
CW,
|
||||
CCW,
|
||||
SW,
|
||||
|
||||
// Joystick
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
|
||||
// Keypad
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
Key4,
|
||||
Key5,
|
||||
Key6,
|
||||
Key7,
|
||||
Key8,
|
||||
Key9,
|
||||
Key0,
|
||||
KeyA,
|
||||
KeyB,
|
||||
KeyC,
|
||||
KeyD,
|
||||
KeyAsterisk,
|
||||
KeyPound
|
||||
}
|
||||
|
||||
public enum InputName
|
||||
{
|
||||
EncoderLower,
|
||||
EncoderUpper,
|
||||
Joystick,
|
||||
Keypad
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
|
||||
namespace MSFSPopoutPanelManager.ArduinoAgent
|
||||
{
|
||||
public class ArduinoProvider
|
||||
{
|
||||
private const string ARDUINO_COM_PORT = "COM3";
|
||||
private const int ARDUINO_BAUD_RATE = 9600;
|
||||
|
||||
private SerialPort _serialPort;
|
||||
|
||||
public event EventHandler<bool> OnConnectionChanged;
|
||||
public event EventHandler<ArduinoInputData> OnDataReceived;
|
||||
|
||||
public ArduinoProvider()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort = new SerialPort
|
||||
{
|
||||
PortName = ARDUINO_COM_PORT,
|
||||
BaudRate = ARDUINO_BAUD_RATE
|
||||
};
|
||||
_serialPort.DataReceived += DataReceived;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileLogger.WriteException($"Arduino Error: {ex.Message}", null);
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (!IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort.Open();
|
||||
OnConnectionChanged?.Invoke(this, true);
|
||||
FileLogger.WriteLog($"Arduino connected.", StatusMessageType.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileLogger.WriteException($"Arduino Connection Error - {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (_serialPort.IsOpen)
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort.Close();
|
||||
FileLogger.WriteLog($"Arduino disconnected.", StatusMessageType.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileLogger.WriteException($"Arduino Connection Error - {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
OnConnectionChanged?.Invoke(this, false);
|
||||
}
|
||||
|
||||
public void SendToArduino(string data)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsConnected)
|
||||
_serialPort.WriteLine(data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FileLogger.WriteException($"Arduino Connection Error - {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
if (_serialPort.IsOpen)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dataEvents = new List<ArduinoInputData>();
|
||||
|
||||
int byteToRead = _serialPort.BytesToRead;
|
||||
|
||||
while (byteToRead > 0)
|
||||
{
|
||||
|
||||
var message = _serialPort.ReadTo("\r\n");
|
||||
var data = message.Split(":");
|
||||
|
||||
ArduinoInputData dataEvent;
|
||||
|
||||
// Calculate acceleration
|
||||
if (data.Length == 3)
|
||||
{
|
||||
var accelerationValue = Convert.ToInt32(data[2]);
|
||||
//dataEvent = new ArduinoInputData(data[0], data[1], accelerationValue == 1 ? 1 : accelerationValue / 2);
|
||||
dataEvent = new ArduinoInputData(data[0], data[1], accelerationValue <= 2 ? 1 : accelerationValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataEvent = new ArduinoInputData(data[0], data[1], 1);
|
||||
}
|
||||
|
||||
dataEvents.Add(dataEvent);
|
||||
|
||||
byteToRead = _serialPort.BytesToRead;
|
||||
}
|
||||
|
||||
foreach (var evt in dataEvents)
|
||||
{
|
||||
OnDataReceived?.Invoke(this, evt);
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_serialPort.DiscardInBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_serialPort == null)
|
||||
return false;
|
||||
|
||||
return _serialPort.IsOpen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
DomainModel/DataFile/AppSetttingFile.cs
Normal file
19
DomainModel/DataFile/AppSetttingFile.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Setting;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.DataFile
|
||||
{
|
||||
public class AppSetttingFile
|
||||
{
|
||||
public AppSetttingFile()
|
||||
{
|
||||
FileVersion = "4.0";
|
||||
ApplicationSetting = new ApplicationSetting();
|
||||
}
|
||||
|
||||
public string FileVersion { get; set; }
|
||||
|
||||
public ApplicationSetting ApplicationSetting { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
18
DomainModel/DataFile/UserProfileFile.cs
Normal file
18
DomainModel/DataFile/UserProfileFile.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.DataFile
|
||||
{
|
||||
public class UserProfileFile
|
||||
{
|
||||
public UserProfileFile()
|
||||
{
|
||||
FileVersion = "4.0";
|
||||
Profiles = new List<UserProfile>();
|
||||
}
|
||||
|
||||
public string FileVersion { get; set; }
|
||||
|
||||
public IList<UserProfile> Profiles { get; set; }
|
||||
}
|
||||
}
|
46
DomainModel/DomainModel.csproj
Normal file
46
DomainModel/DomainModel.csproj
Normal file
|
@ -0,0 +1,46 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<AssemblyName>DomainModel</AssemblyName>
|
||||
<PackageId>MSFS 2020 Popout Panel Manager Domain Model</PackageId>
|
||||
<Product>MSFS 2020 Popout Panel Manager Domain Model</Product>
|
||||
<Authors>Stanley Kwok</Authors>
|
||||
<Company>Stanley Kwok</Company>
|
||||
<Copyright>Stanley Kwok 2021</Copyright>
|
||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||
<RootNamespace>MSFSPopoutPanelManager.DomainModel</RootNamespace>
|
||||
<Platforms>x64</Platforms>
|
||||
<Version>4.0.0.0</Version>
|
||||
<AssemblyVersion>4.0.0.0</AssemblyVersion>
|
||||
<FileVersion>4.0.0.0</FileVersion>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<DebugType>Embedded</DebugType>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseTouchPanel|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugTouchPanel|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fody" Version="6.7.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
78
DomainModel/Legacy/LegacyAppSetting.cs
Normal file
78
DomainModel/Legacy/LegacyAppSetting.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Setting;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Legacy
|
||||
{
|
||||
public class LegacyAppSetting
|
||||
{
|
||||
public string AutoUpdaterUrl { get; set; }
|
||||
|
||||
public int LastUsedProfileId { get; set; }
|
||||
|
||||
public bool MinimizeToTray { get; set; }
|
||||
|
||||
public bool AlwaysOnTop { get; set; }
|
||||
|
||||
public bool AutoClose { get; set; }
|
||||
|
||||
public bool UseAutoPanning { get; set; }
|
||||
|
||||
public bool MinimizeAfterPopOut { get; set; }
|
||||
|
||||
public string AutoPanningKeyBinding { get; set; }
|
||||
|
||||
public bool StartMinimized { get; set; }
|
||||
|
||||
public bool AutoPopOutPanels { get; set; }
|
||||
|
||||
public bool AutoDisableTrackIR { get; set; }
|
||||
|
||||
public int OnScreenMessageDuration { get; set; }
|
||||
|
||||
public bool UseLeftRightControlToPopOut { get; set; }
|
||||
|
||||
public bool IsEnabledTouchPanelServer { get; set; }
|
||||
|
||||
public bool AutoResizeMsfsGameWindow { get; set; }
|
||||
|
||||
public LegacyAfterPopOutCameraView AfterPopOutCameraView { get; set; }
|
||||
|
||||
public LegacyTouchScreenSettings TouchScreenSettings { get; set; }
|
||||
|
||||
public LegacyTouchPanelSettings TouchPanelSettings { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyAfterPopOutCameraView
|
||||
{
|
||||
public bool EnableReturnToCameraView { get; set; }
|
||||
|
||||
public AfterPopOutCameraViewType CameraView { get; set; }
|
||||
|
||||
public string CustomCameraKeyBinding { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyTouchScreenSettings
|
||||
{
|
||||
public int TouchDownUpDelay { get; set; }
|
||||
|
||||
public bool RefocusGameWindow { get; set; }
|
||||
|
||||
public int RefocusGameWindowDelay { get; set; }
|
||||
|
||||
public bool RealSimGearGTN750Gen1Override { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyTouchPanelSettings
|
||||
{
|
||||
public bool EnableTouchPanelIntegration { get; set; }
|
||||
|
||||
public bool AutoStart { get; set; }
|
||||
|
||||
public int DataRefreshInterval { get; set; }
|
||||
|
||||
public int MapRefreshInterval { get; set; }
|
||||
|
||||
public bool UseArduino { get; set; }
|
||||
|
||||
public bool EnableSound { get; set; }
|
||||
}
|
||||
}
|
84
DomainModel/Legacy/LegacyProfile.cs
Normal file
84
DomainModel/Legacy/LegacyProfile.cs
Normal file
|
@ -0,0 +1,84 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Legacy
|
||||
{
|
||||
public class LegacyProfile
|
||||
{
|
||||
public int ProfileId { get; set; }
|
||||
|
||||
public string ProfileName { get; set; }
|
||||
|
||||
public ObservableCollection<string> BindingAircrafts { get; set; }
|
||||
|
||||
public ObservableCollection<LegacyPanelSourceCoordinate> PanelSourceCoordinates { get; set; }
|
||||
|
||||
public ObservableCollection<LegacyPanelConfig> PanelConfigs { get; set; }
|
||||
|
||||
public ObservableCollection<LegacyTouchPanelBinding> TouchPanelBindings { get; set; }
|
||||
|
||||
public bool IsLocked { get; set; }
|
||||
|
||||
public bool PowerOnRequiredForColdStart { get; set; }
|
||||
|
||||
public bool IncludeInGamePanels { get; set; }
|
||||
|
||||
public bool RealSimGearGTN750Gen1Override { get; set; }
|
||||
|
||||
public LegacyMsfsGameWindowConfig MsfsGameWindowConfig { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyPanelSourceCoordinate
|
||||
{
|
||||
public int PanelIndex { get; set; }
|
||||
|
||||
public int X { get; set; }
|
||||
|
||||
public int Y { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyPanelConfig
|
||||
{
|
||||
public int PanelIndex { get; set; }
|
||||
|
||||
public string PanelName { get; set; }
|
||||
|
||||
public PanelType PanelType { get; set; }
|
||||
|
||||
public int Top { get; set; }
|
||||
|
||||
public int Left { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
public bool AlwaysOnTop { get; set; }
|
||||
|
||||
public bool HideTitlebar { get; set; }
|
||||
|
||||
public bool FullScreen { get; set; }
|
||||
|
||||
public bool TouchEnabled { get; set; }
|
||||
|
||||
public bool DisableGameRefocus { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyTouchPanelBinding
|
||||
{
|
||||
public string PlaneId { get; set; }
|
||||
|
||||
public string PanelId { get; set; }
|
||||
}
|
||||
|
||||
public class LegacyMsfsGameWindowConfig
|
||||
{
|
||||
public int Top { get; set; }
|
||||
|
||||
public int Left { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
}
|
||||
}
|
24
DomainModel/Profile/HudBarConfig.cs
Normal file
24
DomainModel/Profile/HudBarConfig.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class HudBarConfig : ObservableObject
|
||||
{
|
||||
public HudBarConfig()
|
||||
{
|
||||
IsEnabled = false;
|
||||
HudBarType = HudBarType.Generic_Aircraft;
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public HudBarType HudBarType { get; set; }
|
||||
}
|
||||
|
||||
public enum HudBarType
|
||||
{
|
||||
None = 0, // not selectable
|
||||
Generic_Aircraft = 1,
|
||||
PMDG_737 = 2
|
||||
}
|
||||
}
|
35
DomainModel/Profile/MsfsGameWindowConfig.cs
Normal file
35
DomainModel/Profile/MsfsGameWindowConfig.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class MsfsGameWindowConfig : ObservableObject
|
||||
{
|
||||
public MsfsGameWindowConfig()
|
||||
{
|
||||
Top = 0;
|
||||
Left = 0;
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
}
|
||||
|
||||
public MsfsGameWindowConfig(int left, int top, int width, int height)
|
||||
{
|
||||
Top = top;
|
||||
Left = left;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
public int Top { get; set; }
|
||||
|
||||
public int Left { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsValid => Width != 0 && Height != 0;
|
||||
}
|
||||
}
|
99
DomainModel/Profile/PanelConfig.cs
Normal file
99
DomainModel/Profile/PanelConfig.cs
Normal file
|
@ -0,0 +1,99 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class PanelConfig : ObservableObject
|
||||
{
|
||||
public PanelConfig()
|
||||
{
|
||||
if (Id == Guid.Empty)
|
||||
Id = Guid.NewGuid();
|
||||
|
||||
PanelName = "Default Panel Name";
|
||||
PanelHandle = IntPtr.MaxValue;
|
||||
AutoGameRefocus = true;
|
||||
PanelSource = new PanelSource();
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
|
||||
PropertyChanged += PanelConfig_PropertyChanged;
|
||||
}
|
||||
|
||||
private void PanelConfig_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "FullScreen" && FullScreen)
|
||||
{
|
||||
AlwaysOnTop = false;
|
||||
HideTitlebar = false;
|
||||
}
|
||||
else if (e.PropertyName == "TouchEnabled" && TouchEnabled)
|
||||
{
|
||||
AutoGameRefocus = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public PanelType PanelType { get; set; }
|
||||
|
||||
public string PanelName { get; set; }
|
||||
|
||||
public int Top { get; set; }
|
||||
|
||||
public int Left { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
public bool AlwaysOnTop { get; set; }
|
||||
|
||||
public bool HideTitlebar { get; set; }
|
||||
|
||||
public bool FullScreen { get; set; }
|
||||
|
||||
public bool TouchEnabled { get; set; }
|
||||
|
||||
public bool AutoGameRefocus { get; set; }
|
||||
|
||||
public PanelSource PanelSource { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IntPtr PanelHandle { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsEditingPanel { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsCustomPopOut => PanelType == PanelType.CustomPopout;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsBuiltInPopOut => PanelType == PanelType.BuiltInPopout;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasPanelSource => PanelType == PanelType.BuiltInPopout || (PanelType == PanelType.CustomPopout && PanelSource != null && PanelSource.X != null);
|
||||
|
||||
[JsonIgnore]
|
||||
public bool? IsPopOutSuccess
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PanelHandle == IntPtr.MaxValue)
|
||||
return null;
|
||||
|
||||
if (PanelHandle == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsSelectedPanelSource { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsShownPanelSource { get; set; }
|
||||
}
|
||||
}
|
38
DomainModel/Profile/PanelConfigColors.cs
Normal file
38
DomainModel/Profile/PanelConfigColors.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class PanelConfigColors
|
||||
{
|
||||
public static string GetNextAvailableColor(List<PanelConfig> panelConfigs)
|
||||
{
|
||||
foreach (string colorName in Enum.GetNames<Colors>())
|
||||
{
|
||||
if (panelConfigs.Any(p => p.PanelSource.Color == colorName))
|
||||
continue;
|
||||
|
||||
return colorName;
|
||||
}
|
||||
|
||||
return "White";
|
||||
}
|
||||
}
|
||||
|
||||
public enum Colors
|
||||
{
|
||||
LimeGreen,
|
||||
Red,
|
||||
Blue,
|
||||
Fuchsia,
|
||||
Orange,
|
||||
Yellow,
|
||||
Cyan,
|
||||
Ivory,
|
||||
Pink,
|
||||
Indigo,
|
||||
Purple,
|
||||
Crimson
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
|
||||
namespace MSFSPopoutPanelManager.Shared
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class PanelConfigItem
|
||||
{
|
||||
|
@ -25,9 +25,7 @@ namespace MSFSPopoutPanelManager.Shared
|
|||
HideTitlebar,
|
||||
FullScreen,
|
||||
TouchEnabled,
|
||||
DisableGameRefocus,
|
||||
RowHeader,
|
||||
None,
|
||||
Invalid,
|
||||
AutoGameRefocus,
|
||||
None
|
||||
}
|
||||
}
|
18
DomainModel/Profile/PanelSource.cs
Normal file
18
DomainModel/Profile/PanelSource.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class PanelSource : ObservableObject
|
||||
{
|
||||
public int? X { get; set; }
|
||||
|
||||
public int? Y { get; set; }
|
||||
|
||||
public string Color { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IntPtr PanelHandle { get; set; }
|
||||
}
|
||||
}
|
15
DomainModel/Profile/PanelType.cs
Normal file
15
DomainModel/Profile/PanelType.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public enum PanelType
|
||||
{
|
||||
PopOutManager = 0,
|
||||
BuiltInPopout = 1,
|
||||
CustomPopout = 2,
|
||||
FlightSimMainWindow = 3,
|
||||
HudBarWindow = 4,
|
||||
MultiMonitorWindow = 5,
|
||||
PanelSourceWindow = 6,
|
||||
StatusMessageWindow = 7,
|
||||
Unknown = 100
|
||||
}
|
||||
}
|
20
DomainModel/Profile/ProfileSetting.cs
Normal file
20
DomainModel/Profile/ProfileSetting.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
public class ProfileSetting : ObservableObject
|
||||
{
|
||||
public ProfileSetting()
|
||||
{
|
||||
HudBarConfig = new HudBarConfig();
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
}
|
||||
|
||||
public bool PowerOnRequiredForColdStart { get; set; }
|
||||
|
||||
public bool IncludeInGamePanels { get; set; }
|
||||
|
||||
public HudBarConfig HudBarConfig { get; set; }
|
||||
}
|
||||
}
|
125
DomainModel/Profile/UserProfile.cs
Normal file
125
DomainModel/Profile/UserProfile.cs
Normal file
|
@ -0,0 +1,125 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Newtonsoft.Json;
|
||||
using PropertyChanged;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Profile
|
||||
{
|
||||
[SuppressPropertyChangedWarnings]
|
||||
public class UserProfile : ObservableObject, IComparable<UserProfile>
|
||||
{
|
||||
public UserProfile()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
IsLocked = false;
|
||||
|
||||
AircraftBindings = new ObservableCollection<string>();
|
||||
PanelConfigs = new ObservableCollection<PanelConfig>();
|
||||
ProfileSetting = new ProfileSetting();
|
||||
MsfsGameWindowConfig = new MsfsGameWindowConfig();
|
||||
|
||||
this.PropertyChanged += (sender, e) =>
|
||||
{
|
||||
var evtArg = e as PropertyChangedExtendedEventArgs;
|
||||
if (!evtArg.DisableSave)
|
||||
ProfileChanged?.Invoke(this, null);
|
||||
};
|
||||
|
||||
PanelConfigs.CollectionChanged += (sender, e) =>
|
||||
{
|
||||
switch (e.Action)
|
||||
{
|
||||
case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
|
||||
if (e.NewItems[0] == null)
|
||||
return;
|
||||
|
||||
((PanelConfig)e.NewItems[0]).PropertyChanged += (sender, e) =>
|
||||
{
|
||||
var evtArg = e as PropertyChangedExtendedEventArgs;
|
||||
if (!evtArg.DisableSave)
|
||||
ProfileChanged?.Invoke(this, null);
|
||||
|
||||
OnPanelConfigChanged(sender, e);
|
||||
};
|
||||
ProfileChanged?.Invoke(this, null);
|
||||
OnPanelConfigChanged(sender, e);
|
||||
break;
|
||||
case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
|
||||
case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
|
||||
case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
|
||||
ProfileChanged?.Invoke(this, null);
|
||||
OnPanelConfigChanged(sender, e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
}
|
||||
|
||||
public event EventHandler ProfileChanged;
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool IsLocked { get; set; }
|
||||
|
||||
public ObservableCollection<string> AircraftBindings { get; set; }
|
||||
|
||||
public ObservableCollection<PanelConfig> PanelConfigs { get; set; }
|
||||
|
||||
public ProfileSetting ProfileSetting { get; set; }
|
||||
|
||||
public MsfsGameWindowConfig MsfsGameWindowConfig { get; set; }
|
||||
|
||||
public int CompareTo(UserProfile other)
|
||||
{
|
||||
int result = this.Name.ToLower().CompareTo(other.Name.ToLower());
|
||||
if (result == 0)
|
||||
result = this.Name.ToLower().CompareTo(other.Name.ToLower());
|
||||
return result;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsEditingPanelSource { get; set; }
|
||||
|
||||
private bool _isPoppedOut;
|
||||
[JsonIgnore]
|
||||
public bool IsPoppedOut
|
||||
{
|
||||
get { return _isPoppedOut; }
|
||||
set
|
||||
{
|
||||
_isPoppedOut = value;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
foreach (var panelConfig in PanelConfigs)
|
||||
panelConfig.PanelHandle = IntPtr.MaxValue; // reset panel is popped out status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public Guid CurrentMoveResizePanelId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasUnidentifiedPanelSource { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasAircraftBindings => AircraftBindings != null && AircraftBindings.Count > 0;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasCustomPanels => PanelConfigs.Count(p => p.PanelType == PanelType.CustomPopout) > 0;
|
||||
|
||||
private void OnPanelConfigChanged(object sender, EventArgs e)
|
||||
{
|
||||
HasUnidentifiedPanelSource = PanelConfigs.Any(p => p.PanelType == PanelType.CustomPopout && p.PanelSource.X == null);
|
||||
}
|
||||
}
|
||||
}
|
32
DomainModel/Setting/AfterPopOutCameraView.cs
Normal file
32
DomainModel/Setting/AfterPopOutCameraView.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class AfterPopOutCameraView : ObservableObject
|
||||
{
|
||||
public AfterPopOutCameraView()
|
||||
{
|
||||
// Default values
|
||||
IsEnabled = true;
|
||||
CameraView = AfterPopOutCameraViewType.CockpitCenterView;
|
||||
KeyBinding = "1";
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public AfterPopOutCameraViewType CameraView { get; set; }
|
||||
|
||||
public string KeyBinding { get; set; }
|
||||
|
||||
// Use for MVVM binding only
|
||||
[JsonIgnore]
|
||||
public bool IsEnabledCustomCameraKeyBinding { get { return IsEnabled && CameraView == AfterPopOutCameraViewType.CustomCameraView; } }
|
||||
}
|
||||
|
||||
public enum AfterPopOutCameraViewType
|
||||
{
|
||||
CockpitCenterView,
|
||||
CustomCameraView
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ using System.Text;
|
|||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace MSFSPopoutPanelManager.UserDataAgent
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
internal class AppAutoStart
|
||||
{
|
37
DomainModel/Setting/ApplicationSetting.cs
Normal file
37
DomainModel/Setting/ApplicationSetting.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class ApplicationSetting : ObservableObject
|
||||
{
|
||||
public ApplicationSetting()
|
||||
{
|
||||
GeneralSetting = new GeneralSetting();
|
||||
AutoPopOutSetting = new AutoPopOutSetting();
|
||||
PopOutSetting = new PopOutSetting();
|
||||
RefocusSetting = new RefocusSetting();
|
||||
TouchSetting = new TouchSetting();
|
||||
TrackIRSetting = new TrackIRSetting();
|
||||
WindowedModeSetting = new WindowedModeSetting();
|
||||
SystemSetting = new SystemSetting();
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
}
|
||||
|
||||
public GeneralSetting GeneralSetting { get; set; }
|
||||
|
||||
public AutoPopOutSetting AutoPopOutSetting { get; set; }
|
||||
|
||||
public PopOutSetting PopOutSetting { get; set; }
|
||||
|
||||
public RefocusSetting RefocusSetting { get; set; }
|
||||
|
||||
public TouchSetting TouchSetting { get; set; }
|
||||
|
||||
public TrackIRSetting TrackIRSetting { get; set; }
|
||||
|
||||
public WindowedModeSetting WindowedModeSetting { get; set; }
|
||||
|
||||
public SystemSetting SystemSetting { get; set; }
|
||||
}
|
||||
}
|
17
DomainModel/Setting/AutoPanning.cs
Normal file
17
DomainModel/Setting/AutoPanning.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class AutoPanning : ObservableObject
|
||||
{
|
||||
public AutoPanning()
|
||||
{
|
||||
IsEnabled = true;
|
||||
KeyBinding = "0";
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public string KeyBinding { get; set; }
|
||||
}
|
||||
}
|
17
DomainModel/Setting/AutoPopOutSetting.cs
Normal file
17
DomainModel/Setting/AutoPopOutSetting.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class AutoPopOutSetting : ObservableObject
|
||||
{
|
||||
public AutoPopOutSetting()
|
||||
{
|
||||
IsEnabled = true;
|
||||
ReadyToFlyDelay = 3;
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public int ReadyToFlyDelay { get; set; }
|
||||
}
|
||||
}
|
45
DomainModel/Setting/GeneralSetting.cs
Normal file
45
DomainModel/Setting/GeneralSetting.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class GeneralSetting : ObservableObject
|
||||
{
|
||||
public GeneralSetting()
|
||||
{
|
||||
AlwaysOnTop = true;
|
||||
MinimizeToTray = false;
|
||||
StartMinimized = false;
|
||||
AutoClose = true;
|
||||
CheckForUpdate = true;
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
}
|
||||
|
||||
public bool AlwaysOnTop { get; set; }
|
||||
|
||||
public bool AutoClose { get; set; }
|
||||
|
||||
public bool MinimizeToTray { get; set; }
|
||||
|
||||
public bool StartMinimized { get; set; }
|
||||
|
||||
public bool CheckForUpdate { get; set; }
|
||||
|
||||
[JsonIgnore, IgnorePropertyChanged]
|
||||
public bool AutoStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return AppAutoStart.CheckIsAutoStart();
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
AppAutoStart.Activate();
|
||||
else
|
||||
AppAutoStart.Deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
DomainModel/Setting/PopOutSetting.cs
Normal file
38
DomainModel/Setting/PopOutSetting.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class PopOutSetting : ObservableObject
|
||||
{
|
||||
public PopOutSetting()
|
||||
{
|
||||
MinimizeDuringPopOut = true;
|
||||
MinimizeAfterPopOut = false;
|
||||
UseLeftRightControlToPopOut = false;
|
||||
AutoActivePause = false;
|
||||
|
||||
AfterPopOutCameraView = new AfterPopOutCameraView();
|
||||
AutoPanning = new AutoPanning();
|
||||
PopOutTitleBarCustomization = new PopOutTitleBarCustomization();
|
||||
EnablePanelResetWhenLocked = true;
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
}
|
||||
|
||||
public AutoPanning AutoPanning { get; set; }
|
||||
|
||||
public AfterPopOutCameraView AfterPopOutCameraView { get; set; }
|
||||
|
||||
public bool MinimizeDuringPopOut { get; set; }
|
||||
|
||||
public bool MinimizeAfterPopOut { get; set; }
|
||||
|
||||
public bool UseLeftRightControlToPopOut { get; set; }
|
||||
|
||||
public bool EnablePanelResetWhenLocked { get; set; }
|
||||
|
||||
public bool AutoActivePause { get; set; }
|
||||
|
||||
public PopOutTitleBarCustomization PopOutTitleBarCustomization { get; set; }
|
||||
};
|
||||
}
|
15
DomainModel/Setting/PopOutTitleBarCustomization.cs
Normal file
15
DomainModel/Setting/PopOutTitleBarCustomization.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class PopOutTitleBarCustomization
|
||||
{
|
||||
public PopOutTitleBarCustomization()
|
||||
{
|
||||
IsEnabled = false;
|
||||
HexColor = "000000";
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public string HexColor { get; set; }
|
||||
}
|
||||
}
|
17
DomainModel/Setting/RefocusGameWindow.cs
Normal file
17
DomainModel/Setting/RefocusGameWindow.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class RefocusGameWindow : ObservableObject
|
||||
{
|
||||
public RefocusGameWindow()
|
||||
{
|
||||
IsEnabled = true;
|
||||
Delay = 1;
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public double Delay { get; set; }
|
||||
}
|
||||
}
|
16
DomainModel/Setting/RefocusSetting.cs
Normal file
16
DomainModel/Setting/RefocusSetting.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class RefocusSetting : ObservableObject
|
||||
{
|
||||
public RefocusSetting()
|
||||
{
|
||||
RefocusGameWindow = new RefocusGameWindow();
|
||||
|
||||
InitializeChildPropertyChangeBinding();
|
||||
}
|
||||
|
||||
public RefocusGameWindow RefocusGameWindow { get; set; }
|
||||
}
|
||||
}
|
18
DomainModel/Setting/SystemSetting.cs
Normal file
18
DomainModel/Setting/SystemSetting.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using System;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class SystemSetting : ObservableObject
|
||||
{
|
||||
public SystemSetting()
|
||||
{
|
||||
LastUsedProfileId = Guid.Empty;
|
||||
AutoUpdaterUrl = "https://raw.githubusercontent.com/hawkeye-stan/msfs-popout-panel-manager/master/autoupdate.xml";
|
||||
}
|
||||
|
||||
public string AutoUpdaterUrl { get; set; }
|
||||
|
||||
public Guid LastUsedProfileId { get; set; }
|
||||
}
|
||||
}
|
14
DomainModel/Setting/TouchSetting.cs
Normal file
14
DomainModel/Setting/TouchSetting.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class TouchSetting : ObservableObject
|
||||
{
|
||||
public TouchSetting()
|
||||
{
|
||||
TouchDownUpDelay = 0;
|
||||
}
|
||||
|
||||
public int TouchDownUpDelay { get; set; }
|
||||
}
|
||||
}
|
14
DomainModel/Setting/TrackIRSetting.cs
Normal file
14
DomainModel/Setting/TrackIRSetting.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class TrackIRSetting : ObservableObject
|
||||
{
|
||||
public TrackIRSetting()
|
||||
{
|
||||
AutoDisableTrackIR = true;
|
||||
}
|
||||
|
||||
public bool AutoDisableTrackIR { get; set; }
|
||||
}
|
||||
}
|
14
DomainModel/Setting/WindowedModeSetting.cs
Normal file
14
DomainModel/Setting/WindowedModeSetting.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||
{
|
||||
public class WindowedModeSetting : ObservableObject
|
||||
{
|
||||
public WindowedModeSetting()
|
||||
{
|
||||
AutoResizeMsfsGameWindow = true;
|
||||
}
|
||||
|
||||
public bool AutoResizeMsfsGameWindow { get; set; }
|
||||
}
|
||||
}
|
94
DomainModel/SimConnect/HudBarData737.cs
Normal file
94
DomainModel/SimConnect/HudBarData737.cs
Normal file
|
@ -0,0 +1,94 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.Shared;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.SimConnect
|
||||
{
|
||||
public class HudBarData737 : ObservableObject, IHudBarData
|
||||
{
|
||||
public HudBarType HudBarType => HudBarType.PMDG_737;
|
||||
|
||||
public double ElevatorTrim { get; set; }
|
||||
|
||||
public double AileronTrim { get; set; }
|
||||
|
||||
public double RudderTrim { get; set; }
|
||||
|
||||
public double Flap { get; set; }
|
||||
|
||||
public double ParkingBrake { get; set; }
|
||||
|
||||
public double GearLeft { get; set; }
|
||||
|
||||
public double GearCenter { get; set; }
|
||||
|
||||
public double GearRight { get; set; }
|
||||
|
||||
public double SimRate { get; set; }
|
||||
|
||||
public string ElevatorTrimFormatted => Math.Round(ElevatorTrim / 10, 2).ToString("F2");
|
||||
|
||||
public string AileronTrimFormatted => Math.Round(AileronTrim / 16384 * 57, 2).ToString("F2");
|
||||
|
||||
public string RudderTrimFormatted => Math.Round(RudderTrim * 2 * 10, 2).ToString("F2");
|
||||
|
||||
public string FlapFormatted => MapFlap(Flap);
|
||||
|
||||
public string ParkingBrakeFormatted => ParkingBrake > 0 ? "Engaged" : "Disengaged";
|
||||
|
||||
public string GearLeftFormatted => MapGear(GearLeft);
|
||||
|
||||
public string GearCenterFormatted => MapGear(GearCenter);
|
||||
|
||||
public string GearRightFormatted => MapGear(GearRight);
|
||||
|
||||
private string MapFlap(double flap)
|
||||
{
|
||||
switch (Convert.ToInt32(flap))
|
||||
{
|
||||
case 0:
|
||||
return "0";
|
||||
case 1:
|
||||
return "1";
|
||||
case 2:
|
||||
return "2";
|
||||
case 3:
|
||||
return "5";
|
||||
case 4:
|
||||
return "10";
|
||||
case 5:
|
||||
return "15";
|
||||
case 6:
|
||||
return "25";
|
||||
case 7:
|
||||
return "30";
|
||||
case 8:
|
||||
return "40";
|
||||
default:
|
||||
return "5";
|
||||
}
|
||||
}
|
||||
|
||||
private string MapGear(double gear)
|
||||
{
|
||||
if (gear == 100)
|
||||
return "DOWN";
|
||||
if (gear == 0)
|
||||
return "UP";
|
||||
|
||||
return "MOVING";
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Type type = this.GetType();
|
||||
PropertyInfo[] properties = type.GetProperties();
|
||||
for (int i = 0; i < properties.Length; ++i)
|
||||
{
|
||||
if (properties[i].SetMethod != null)
|
||||
properties[i].SetValue(this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
DomainModel/SimConnect/HudBarDataGeneric.cs
Normal file
67
DomainModel/SimConnect/HudBarDataGeneric.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.Shared;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.SimConnect
|
||||
{
|
||||
public class HudBarDataGeneric : ObservableObject, IHudBarData
|
||||
{
|
||||
public HudBarType HudBarType => HudBarType.Generic_Aircraft;
|
||||
|
||||
public double ElevatorTrim { get; set; }
|
||||
|
||||
public double AileronTrim { get; set; }
|
||||
|
||||
public double RudderTrim { get; set; }
|
||||
|
||||
public double Flap { get; set; }
|
||||
|
||||
public double ParkingBrake { get; set; }
|
||||
|
||||
public double GearLeft { get; set; }
|
||||
|
||||
public double GearCenter { get; set; }
|
||||
|
||||
public double GearRight { get; set; }
|
||||
|
||||
public double SimRate { get; set; }
|
||||
|
||||
public string ElevatorTrimFormatted => Math.Round(ElevatorTrim / 10, 2).ToString("F2");
|
||||
|
||||
public string AileronTrimFormatted => Math.Round(AileronTrim / 16384 * 57, 2).ToString("F2");
|
||||
|
||||
public string RudderTrimFormatted => Math.Round(RudderTrim * 2 * 10, 2).ToString("F2");
|
||||
|
||||
public string FlapFormatted => Flap.ToString("F0");
|
||||
|
||||
public string ParkingBrakeFormatted => ParkingBrake > 0 ? "Engaged" : "Disengaged";
|
||||
|
||||
public string GearLeftFormatted => MapGear(GearLeft);
|
||||
|
||||
public string GearCenterFormatted => MapGear(GearCenter);
|
||||
|
||||
public string GearRightFormatted => MapGear(GearRight);
|
||||
|
||||
private string MapGear(double gear)
|
||||
{
|
||||
if (gear == 100)
|
||||
return "DOWN";
|
||||
if (gear == 0)
|
||||
return "UP";
|
||||
|
||||
return "MOVING";
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Type type = this.GetType();
|
||||
PropertyInfo[] properties = type.GetProperties();
|
||||
for (int i = 0; i < properties.Length; ++i)
|
||||
{
|
||||
if (properties[i].SetMethod != null)
|
||||
properties[i].SetValue(this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
DomainModel/SimConnect/IHudBarData.cs
Normal file
45
DomainModel/SimConnect/IHudBarData.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
|
||||
namespace MSFSPopoutPanelManager.DomainModel.SimConnect
|
||||
{
|
||||
public interface IHudBarData
|
||||
{
|
||||
public HudBarType HudBarType { get; }
|
||||
|
||||
public double ElevatorTrim { get; set; }
|
||||
|
||||
public double AileronTrim { get; set; }
|
||||
|
||||
public double RudderTrim { get; set; }
|
||||
|
||||
public double Flap { get; set; }
|
||||
|
||||
public double ParkingBrake { get; set; }
|
||||
|
||||
public double GearLeft { get; set; }
|
||||
|
||||
public double GearCenter { get; set; }
|
||||
|
||||
public double GearRight { get; set; }
|
||||
|
||||
public double SimRate { get; set; }
|
||||
|
||||
public string ParkingBrakeFormatted { get; }
|
||||
|
||||
public string GearLeftFormatted { get; }
|
||||
|
||||
public string GearCenterFormatted { get; }
|
||||
|
||||
public string GearRightFormatted { get; }
|
||||
|
||||
public string ElevatorTrimFormatted { get; }
|
||||
|
||||
public string AileronTrimFormatted { get; }
|
||||
|
||||
public string RudderTrimFormatted { get; }
|
||||
|
||||
public string FlapFormatted { get; }
|
||||
|
||||
public void Clear();
|
||||
}
|
||||
}
|
117
GETTING_STARTED.md
Normal file
117
GETTING_STARTED.md
Normal file
|
@ -0,0 +1,117 @@
|
|||
# GETTING STARTED
|
||||
|
||||
In this tutorial, you'll be adding 3 pop out panels for the aircraft TBM 930. Two of the panels is display only (PFD and MFD) and the third is a touch screen pop out (GTC 580).
|
||||
|
||||
To get started, launch MSFS Pop Out Panel Manager and then start MSFS. When you are at the main menu select TBM 930 as your aircraft. You do not have to start a flight session yet. Back to Pop Out Panel Manager, you should see the following screen and you can click the Add Profile button to add your first aircraft profile.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted1.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
Type the name for the new aircraft profile "TBM 930" and click Accept.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted2.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
Since your current in game aircraft is TBM 930, once the new profile is added, your selected active in-game aircraft will automatically bind this profile (in green color). This binding will allow Pop Out Panel Manager to automatically switch to this profile when you switch to TBM 930 aicraft in the game. Only one profile can be bound to an in-game aircraft at a time and you can unbind aircraft at any time. Next click the Add Pop Out Panel button 3 times to add 3 panels to this profile.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted3.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
Once the 3 panels are added, enter a descriptive name for each of the 3 panels. When you're still in the game's main menu, Identify Source Panel Location button for the 3 panels will not be available. You will now need to start a flight with the TBM 930 aircraft. Please go to world map, pick an airport and start a flight. Once you're in a flight, the Identify Source Panel Location button will be enable.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted4.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
Next, click the Identify Source Panel Location button one at a time. After each click of the button, left click on the game screen at the corresponding instrumentation panel in game to each of the pop out panel definition. A circle will appear to match the pop out panel circle color. If you need to adjust the color circle placement, just left click and drag the circle to new location. You can also zoom in and out of the cockpit view using your mouse wheel so you can see more in-game panels at a time.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted5.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
Once you're satified with the color circles placement, click the Toggle Edit Source Panel Location button (the green target icon). This will end the source panel configuration and will save the current camera angle and your game window size (if using Windowed mode) to be recalled later to be used when popping out panels. The Start Pop Out button should now be enabled. Click this button and start the pop out process. If Pop Out Panel Manager app window is overlapping your selected instrumentation panels, don't worry, the app will relocate itself when simulating the in-game pop out keystrokes. You should also see a progress window indicating Pop Out Manager is in process of configuring and popping out panels.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted6.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
Once the process has been completed successfully, you should see all 3 panels appear at the upper left corner of the game screen. All 3 pop out panels definition will now have green border showing everything is working. You can then configure the panel by:
|
||||
|
||||
* Changing the top, left, width, and height by entering a number
|
||||
* Use the up/down arrow next to each property and a pop out box will allow you to change the property by 1 or 10 pixels at a time.
|
||||
* For the fastest way, click the Move and Resize Panel icon, this will allow you to use keyboard shortcuts to adjust the panel. Please see help section of the app for keyboard commands (click the question mark icon at the upper right corner of the app).
|
||||
|
||||
In this tutorial, since the 3rd panel is a touch enable panel (GTC 580). You can click the hand icon for this panel to activate touch support.
|
||||
|
||||
Once you've completed all panel configurations, please click the Lock icon to lock this profile from accidental changes.
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted7.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
If you encounter any error during pop out, the panel with error will have a red border. You can click the Red Exclaimation mark icon for help to resolve the error. In this tutorial, the problem is the source panel blue circle for this particular pop out is not within the in-game instrumentation panel area. To fix this, click the Toggle Edit Source Panel button, and then use your mouse to drag and move the blue circle to a location within the GTC 580 panel. Finally, click the Toggle Edit Source Panel button again to save the changes. Now click Start Pop Out and the error should be resolved.
|
||||
|
||||
Tip #1: If you have trouble finding the number circle on screen or figuring out the color circle you're dragging corresponding to which pop out panel, you can left click and hold either the pop out panel source target icon or the color circle itself and find the corresponding pop out panel or color circle.
|
||||
|
||||
Tip #2: Hovering your mouse on any input element may provide tool tip to further explain the function of each icon or action.
|
||||
|
||||
Tip #3: Sometimes, you may encounter issue in MSFS that certain panel does not pop out correctly. You can try changing the order in how Pop Out Panel Manager launching the pop out by reording the pop out panel definition using mosue drag and drop. You can click and drag to arrange pop out panel definitions to new sequence.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted8.png" width="900" hspace="10"/>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
An additional feature for Pop Out Panel Manager is you can add and manage built-in panels from the toolbar such as Checklist, ATC, Weather panel. One use case is you can place a panel such as ATC on a touch screen, configure the panel to be touch enabled, and operate this panel using touch.
|
||||
|
||||
To do this, first check the Include in-game menu bar panels option for the profile. The built-in panels themselves have to be opened manually and popped out first. Currently, Pop Out Panel Manager do not have a way to control built-in panel. Luckily, MSFS will remember these built-in panels opened and popped out state. As long as you don't close them during your flight session, they will be reopened and popped out the next time when you start a flight.
|
||||
|
||||
In this tutorial, when you have ATC built-in panel opened and popped out, click Start Pop Out button. A new entry for ATC is then added to the profile. You can configure its size and location and touch capability like any other pop out panel.
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<img src="assets/readme/images/gettingstarted9.png" width="900" hspace="10"/>
|
||||
</p>
|
|
@ -3,118 +3,144 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32602.215
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfApp", "WpfApp\WpfApp.csproj", "{54712A0A-B344-45E4-85C4-0A913305A0E6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{15FC98CD-0A69-437B-A5E5-67D025DB5CDC}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.gitignore = .gitignore
|
||||
autoupdate.xml = autoupdate.xml
|
||||
latestreleasenotes.txt = latestreleasenotes.txt
|
||||
GETTING_STARTED.md = GETTING_STARTED.md
|
||||
LICENSE = LICENSE
|
||||
README.md = README.md
|
||||
RELEASENOTES.md = RELEASENOTES.md
|
||||
rollback.xml = rollback.xml
|
||||
VERSION.md = VERSION.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsAgent", "WindowsAgent\WindowsAgent.csproj", "{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArduinoAgent", "ArduinoAgent\ArduinoAgent.csproj", "{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimconnectAgent", "SimconnectAgent\SimconnectAgent.csproj", "{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebServer", "WebServer\WebServer.csproj", "{D20EA590-22C2-4F93-AC25-AF6960F97E03}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserDataAgent", "UserDataAgent\UserDataAgent.csproj", "{677B6DF0-8E19-4B08-8480-F7C365B6BB89}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orchestration", "Orchestration\Orchestration.csproj", "{9CD4014F-B3EA-4E67-9329-9679931E2688}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TouchPanelAgent", "TouchPanelAgent\TouchPanelAgent.csproj", "{2F36A227-C92C-4B42-B1E4-480015492357}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MainApp", "MainApp\MainApp.csproj", "{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DomainModel", "DomainModel\DomainModel.csproj", "{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{143369CD-7A52-43A0-9364-41A46A645B05}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
assets\logo.png = assets\logo.png
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "readme", "readme", "{71539661-D87F-46E3-82F2-2608B5AF74BA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{FF7DD7EF-43C5-4E7C-8283-1087F51935F9}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
assets\readme\images\app.png = assets\readme\images\app.png
|
||||
assets\readme\images\gettingstarted1.png = assets\readme\images\gettingstarted1.png
|
||||
assets\readme\images\gettingstarted2.png = assets\readme\images\gettingstarted2.png
|
||||
assets\readme\images\gettingstarted3.png = assets\readme\images\gettingstarted3.png
|
||||
assets\readme\images\gettingstarted4.png = assets\readme\images\gettingstarted4.png
|
||||
assets\readme\images\gettingstarted5.png = assets\readme\images\gettingstarted5.png
|
||||
assets\readme\images\gettingstarted6.png = assets\readme\images\gettingstarted6.png
|
||||
assets\readme\images\gettingstarted7.png = assets\readme\images\gettingstarted7.png
|
||||
assets\readme\images\gettingstarted8.png = assets\readme\images\gettingstarted8.png
|
||||
assets\readme\images\gettingstarted9.png = assets\readme\images\gettingstarted9.png
|
||||
assets\readme\images\rollback.png = assets\readme\images\rollback.png
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
DebugTouchPanel|x64 = DebugTouchPanel|x64
|
||||
Local|Any CPU = Local|Any CPU
|
||||
Local|x64 = Local|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
ReleaseTouchPanel|x64 = ReleaseTouchPanel|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.Debug|x64.Build.0 = Debug|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.Release|x64.ActiveCfg = Release|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.Release|x64.Build.0 = Release|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{54712A0A-B344-45E4-85C4-0A913305A0E6}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Debug|x64.Build.0 = Debug|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Local|Any CPU.ActiveCfg = Local|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Local|Any CPU.Build.0 = Local|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Local|x64.ActiveCfg = Local|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Local|x64.Build.0 = Local|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Release|Any CPU.Build.0 = Release|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Release|x64.ActiveCfg = Release|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.Release|x64.Build.0 = Release|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{4BDDE1F9-FBDD-479A-B88E-B27D0513C046}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Debug|x64.Build.0 = Debug|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Release|x64.ActiveCfg = Release|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Release|x64.Build.0 = Release|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.Debug|x64.Build.0 = Debug|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.Release|x64.ActiveCfg = Release|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.Release|x64.Build.0 = Release|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{E72F813F-EE30-4384-B02F-EB5D4BCFEC49}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Local|Any CPU.ActiveCfg = Local|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Local|Any CPU.Build.0 = Local|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Local|x64.ActiveCfg = Local|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Local|x64.Build.0 = Local|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Release|Any CPU.Build.0 = Release|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Release|x64.ActiveCfg = Debug|x64
|
||||
{BDD878A3-EF5B-43C7-94B7-CEFA04C67A9E}.Release|x64.Build.0 = Debug|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Debug|x64.Build.0 = Debug|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Local|Any CPU.ActiveCfg = Local|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Local|Any CPU.Build.0 = Local|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Local|x64.ActiveCfg = Local|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Local|x64.Build.0 = Local|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Release|Any CPU.Build.0 = Release|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Release|x64.ActiveCfg = Release|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.Release|x64.Build.0 = Release|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{1BBF7803-BA8D-4AEF-8319-061E93AE5F3D}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.Debug|x64.Build.0 = Debug|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.Release|x64.ActiveCfg = Release|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.Release|x64.Build.0 = Release|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{D20EA590-22C2-4F93-AC25-AF6960F97E03}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.Debug|x64.Build.0 = Debug|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.Release|x64.ActiveCfg = Release|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.Release|x64.Build.0 = Release|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{677B6DF0-8E19-4B08-8480-F7C365B6BB89}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Debug|x64.Build.0 = Debug|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Local|Any CPU.ActiveCfg = Local|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Local|Any CPU.Build.0 = Local|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Local|x64.ActiveCfg = Local|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Local|x64.Build.0 = Local|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Release|Any CPU.Build.0 = Release|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Release|x64.ActiveCfg = Release|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.Release|x64.Build.0 = Release|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{9CD4014F-B3EA-4E67-9329-9679931E2688}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.Debug|x64.Build.0 = Debug|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.DebugTouchPanel|x64.ActiveCfg = DebugTouchPanel|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.DebugTouchPanel|x64.Build.0 = DebugTouchPanel|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.Release|x64.ActiveCfg = Release|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.Release|x64.Build.0 = Release|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.ReleaseTouchPanel|x64.ActiveCfg = ReleaseTouchPanel|x64
|
||||
{2F36A227-C92C-4B42-B1E4-480015492357}.ReleaseTouchPanel|x64.Build.0 = ReleaseTouchPanel|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Debug|x64.Build.0 = Debug|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Local|Any CPU.ActiveCfg = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Local|Any CPU.Build.0 = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Local|x64.ActiveCfg = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Local|x64.Build.0 = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Release|Any CPU.Build.0 = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Release|x64.ActiveCfg = Release|x64
|
||||
{5EEA1D18-3036-4A9F-876C-45DE2AC9F247}.Release|x64.Build.0 = Release|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Debug|x64.Build.0 = Debug|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Local|Any CPU.ActiveCfg = Local|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Local|Any CPU.Build.0 = Local|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Local|x64.ActiveCfg = Local|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Local|x64.Build.0 = Local|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Release|Any CPU.Build.0 = Release|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Release|x64.ActiveCfg = Release|x64
|
||||
{602CA4F9-B6AE-4500-A52F-082D47CB1F9A}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{143369CD-7A52-43A0-9364-41A46A645B05} = {15FC98CD-0A69-437B-A5E5-67D025DB5CDC}
|
||||
{71539661-D87F-46E3-82F2-2608B5AF74BA} = {143369CD-7A52-43A0-9364-41A46A645B05}
|
||||
{FF7DD7EF-43C5-4E7C-8283-1087F51935F9} = {71539661-D87F-46E3-82F2-2608B5AF74BA}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D1607553-61E8-4ED6-B382-ABA6F6944586}
|
||||
EndGlobalSection
|
||||
|
|
21
MainApp/App.xaml
Normal file
21
MainApp/App.xaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<Application
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<materialDesign:BundledTheme
|
||||
BaseTheme="Dark"
|
||||
PrimaryColor="BlueGrey"
|
||||
SecondaryColor="Blue" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
|
||||
<ResourceDictionary Source="CustomControl/themes/NumericUpDown.xaml" />
|
||||
<ResourceDictionary Source="Styles/CustomScrollViewStyle.xaml" />
|
||||
<ResourceDictionary x:Name="CustomMaterialDesignExpander" Source="Styles/CustomMaterialDesignExpander.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -1,27 +1,81 @@
|
|||
using MSFSPopoutPanelManager.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using MSFSPopoutPanelManager.Orchestration;
|
||||
using MSFSPopoutPanelManager.Shared;
|
||||
using MSFSPopoutPanelManager.WindowsAgent;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace MSFSPopoutPanelManager.WpfApp
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
private static Mutex _mutex = null;
|
||||
public static IHost AppHost { get; private set; }
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
public App()
|
||||
{
|
||||
}
|
||||
|
||||
protected override async void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
// Override default WPF System DPI Awareness to Per Monitor Awareness
|
||||
// For this to work make sure [assembly:dpiawareness]
|
||||
DpiAwareness.Enable();
|
||||
|
||||
// Must run this first
|
||||
Initialize();
|
||||
|
||||
// Setup dependency injections
|
||||
AppHost = Host.CreateDefaultBuilder()
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
services.AddSingleton<AppWindow>();
|
||||
|
||||
services.AddSingleton<MainOrchestrator>();
|
||||
services.AddSingleton<OrchestratorUIHelper>(s => new OrchestratorUIHelper(s.GetRequiredService<MainOrchestrator>()));
|
||||
|
||||
services.AddSingleton<ApplicationViewModel>(s => new ApplicationViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddSingleton<HelpViewModel>(s => new HelpViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddSingleton<ProfileCardListViewModel>(s => new ProfileCardListViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddSingleton<ProfileCardViewModel>(s => new ProfileCardViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddSingleton<TrayIconViewModel>(s => new TrayIconViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
|
||||
services.AddTransient<AddProfileViewModel>(s => new AddProfileViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddTransient<PopOutPanelListViewModel>(s => new PopOutPanelListViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddTransient<PopOutPanelCardViewModel>(s => new PopOutPanelCardViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddTransient<PanelConfigFieldViewModel>(s => new PanelConfigFieldViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddTransient<PanelCoorOverlayViewModel>(s => new PanelCoorOverlayViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
|
||||
services.AddTransient<MessageWindowViewModel>(s => new MessageWindowViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
services.AddTransient<HudBarViewModel>(s => new HudBarViewModel(s.GetRequiredService<MainOrchestrator>()));
|
||||
|
||||
}).Build();
|
||||
|
||||
await AppHost!.StartAsync();
|
||||
|
||||
// Startup window (must come after DPI setup above)
|
||||
MainWindow = AppHost.Services.GetRequiredService<AppWindow>();
|
||||
MainWindow.Show();
|
||||
|
||||
base.OnStartup(e);
|
||||
|
||||
// Setup orchestration UI handler
|
||||
var orchestrationUIHelper = App.AppHost.Services.GetRequiredService<OrchestratorUIHelper>();
|
||||
|
||||
// Setup message window dialog
|
||||
var messageWindow = new MessageWindow();
|
||||
messageWindow.Show();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
const string appName = "MSFS PopOut Panel Manager";
|
||||
bool createdNew;
|
||||
|
||||
_mutex = new Mutex(true, appName, out createdNew);
|
||||
var mutex = new Mutex(true, appName, out createdNew);
|
||||
|
||||
if (!createdNew)
|
||||
{
|
||||
|
@ -35,23 +89,19 @@ namespace MSFSPopoutPanelManager.WpfApp
|
|||
TaskScheduler.UnobservedTaskException += HandleTaskSchedulerUnobservedTaskException;
|
||||
AppDomain.CurrentDomain.UnhandledException += HandledDomainException;
|
||||
}
|
||||
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
private void HandleTaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
||||
private void HandleTaskSchedulerUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
|
||||
{
|
||||
FileLogger.WriteException(e.Exception.Message, e.Exception);
|
||||
//ShowExceptionDialog();
|
||||
}
|
||||
|
||||
private void HandleDispatcherException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||
private void HandleDispatcherException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
if (e.Exception.Message != "E_INVALIDARG") // Ignore this error
|
||||
{
|
||||
FileLogger.WriteException(e.Exception.Message, e.Exception);
|
||||
//ShowExceptionDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,23 +109,6 @@ namespace MSFSPopoutPanelManager.WpfApp
|
|||
{
|
||||
var exception = (Exception)e.ExceptionObject;
|
||||
FileLogger.WriteException(exception.Message, exception);
|
||||
//ShowExceptionDialog();
|
||||
}
|
||||
|
||||
private void ShowExceptionDialog()
|
||||
{
|
||||
var messageBoxTitle = "MSFS Pop Out Panel Manager - Critical Error!";
|
||||
var messageBoxMessage = "Application has encountered a critical error and will be closed.\nPlease see the file 'error.log' for information.";
|
||||
var messageBoxButtons = MessageBoxButton.OK;
|
||||
|
||||
if (MessageBox.Show(messageBoxMessage, messageBoxTitle, messageBoxButtons) == MessageBoxResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
162
MainApp/AppWindow.xaml
Normal file
162
MainApp/AppWindow.xaml
Normal file
|
@ -0,0 +1,162 @@
|
|||
<Window
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.AppWindow"
|
||||
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:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Title="MSFS POP OUT PANEL MANAGER"
|
||||
Width="1000"
|
||||
Height="600"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
Icon="logo.ico"
|
||||
ResizeMode="NoResize"
|
||||
Style="{StaticResource MaterialDesignWindow}"
|
||||
WindowState="{Binding InitialWindowState, Mode=OneWay}"
|
||||
WindowStyle="None"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<system:Double x:Key="IconSize">28</system:Double>
|
||||
</Window.Resources>
|
||||
<Border
|
||||
Margin="0"
|
||||
Background="{StaticResource MaterialDesignDarkBackground}"
|
||||
CornerRadius="15">
|
||||
<Grid d:DataContext="{d:DesignInstance viewmodel:ApplicationViewModel}">
|
||||
<local:TrayIcon x:Name="SystemTrayIcon" />
|
||||
<materialDesign:DialogHost
|
||||
Background="Transparent"
|
||||
DialogTheme="Inherit"
|
||||
Identifier="RootDialog">
|
||||
<materialDesign:DrawerHost OverlayBackground="Transparent" RightDrawerCornerRadius="15">
|
||||
<materialDesign:DrawerHost.RightDrawerContent>
|
||||
<DockPanel>
|
||||
<Button
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="8,8,12,0"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Static materialDesign:DrawerHost.CloseDrawerCommand}"
|
||||
DockPanel.Dock="Top"
|
||||
Style="{StaticResource MaterialDesignIconButton}">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="ArrowRight" />
|
||||
</Button>
|
||||
<StackPanel Name="panelPreferenceDrawer" />
|
||||
</DockPanel>
|
||||
</materialDesign:DrawerHost.RightDrawerContent>
|
||||
<DockPanel>
|
||||
<materialDesign:ColorZone
|
||||
Padding="12,4,12,4"
|
||||
materialDesign:ElevationAssist.Elevation="Dp4"
|
||||
CornerRadius="15,15,0,0"
|
||||
DockPanel.Dock="Top"
|
||||
Mode="PrimaryDark">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="200" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" Margin="0,0,0,0">
|
||||
<Button
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Left"
|
||||
IsHitTestVisible="false">
|
||||
<Button.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignFlatButton}" TargetType="Button">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding FlightSimData.IsSimulatorStarted}" Value="True">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
<Setter Property="Content" Value="{materialDesign:PackIcon Kind=AccessPointNetwork, Size={StaticResource IconSize}}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.IsSimulatorStarted}" Value="False">
|
||||
<Setter Property="Foreground" Value="Red" />
|
||||
<Setter Property="Content" Value="{materialDesign:PackIcon Kind=AccessPointNetworkOff, Size={StaticResource IconSize}}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Width="Auto">
|
||||
<TextBlock
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="White"
|
||||
Style="{StaticResource MaterialDesignHeadline6TextBlock}"
|
||||
Text="MSFS POP OUT PANEL MANAGER" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="2"
|
||||
Margin="0,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="0,0,0,0"
|
||||
Click="SettingsButton_Click"
|
||||
Command="{x:Static materialDesign:DrawerHost.OpenDrawerCommand}"
|
||||
Foreground="White"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="Preferences">
|
||||
<materialDesign:PackIcon Kind="Cog" />
|
||||
</Button>
|
||||
<Button
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="10,0,0,0"
|
||||
Click="HelpButton_Click"
|
||||
Command="{x:Static materialDesign:DrawerHost.OpenDrawerCommand}"
|
||||
Foreground="White"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="Help">
|
||||
<materialDesign:PackIcon Kind="Help" />
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="BtnMinimize"
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="10,0,0,0"
|
||||
Click="BtnMinimize_Click"
|
||||
Foreground="White"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="Minimize application">
|
||||
<materialDesign:PackIcon Kind="WindowMinimize" />
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="BtnClose"
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="10,0,0,0"
|
||||
Click="BtnClose_Click"
|
||||
Foreground="White"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="Close application">
|
||||
<materialDesign:PackIcon Kind="Close" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</materialDesign:ColorZone>
|
||||
<local:ProfileCardList
|
||||
x:Name="ProfileCardList"
|
||||
Width="1024"
|
||||
Margin="0,8,0,8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
DockPanel.Dock="Top" />
|
||||
</DockPanel>
|
||||
</materialDesign:DrawerHost>
|
||||
</materialDesign:DialogHost>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
133
MainApp/AppWindow.xaml.cs
Normal file
133
MainApp/AppWindow.xaml.cs
Normal file
|
@ -0,0 +1,133 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using MSFSPopoutPanelManager.WindowsAgent;
|
||||
using Prism.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class AppWindow : Window
|
||||
{
|
||||
private ApplicationViewModel _viewModel;
|
||||
|
||||
// This command has to be here since it doesn't work in view model, window StateChanged never gets fire
|
||||
public DelegateCommand RestoreWindowCommand => new DelegateCommand(() => { this.WindowState = WindowState.Normal; }, () => { return true; });
|
||||
|
||||
public AppWindow()
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<ApplicationViewModel>();
|
||||
InitializeComponent();
|
||||
Loaded += AppWindow_Loaded;
|
||||
Closing += AppWindow_Closing;
|
||||
StateChanged += AppWindow_StateChanged;
|
||||
WindowActionManager.OnPopOutManagerAlwaysOnTopChanged += (sender, e) => { this.Topmost = e; };
|
||||
this.MouseLeftButtonDown += (sender, e) => DragMove();
|
||||
}
|
||||
|
||||
private void AppWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_viewModel.ApplicationHandle = new WindowInteropHelper(Window.GetWindow(this)).Handle;
|
||||
_viewModel.ApplicationWindow = Application.Current.MainWindow;
|
||||
_viewModel.Initialize();
|
||||
|
||||
this.DataContext = _viewModel;
|
||||
|
||||
// Try to fix always on to click through. This won't work for app's title bar since mouseEnter won't be triggered.
|
||||
// This is super tricky to trick POPM process is MSFS process to avoid Windows OS focus stealing
|
||||
this.MouseEnter += (sender, e) =>WindowActionManager.SetWindowFocus(WindowProcessManager.GetApplicationProcess().Handle);
|
||||
}
|
||||
|
||||
private void AppWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
_viewModel.WindowClosing();
|
||||
}
|
||||
|
||||
private void AppWindow_StateChanged(object? sender, EventArgs e)
|
||||
{
|
||||
switch (this.WindowState)
|
||||
{
|
||||
case WindowState.Maximized:
|
||||
this.ShowInTaskbar = true;
|
||||
break;
|
||||
case WindowState.Minimized:
|
||||
if (_viewModel.AppSettingData.ApplicationSetting.GeneralSetting.MinimizeToTray)
|
||||
{
|
||||
SystemTrayIcon.Tray.Visibility = Visibility.Visible;
|
||||
this.ShowInTaskbar = false;
|
||||
}
|
||||
break;
|
||||
case WindowState.Normal:
|
||||
SystemTrayIcon.Tray.Visibility = Visibility.Hidden;
|
||||
this.ShowInTaskbar = true;
|
||||
|
||||
// Fix always on top status once app is minimize and then restore
|
||||
if (_viewModel.AppSettingData.ApplicationSetting.GeneralSetting.AlwaysOnTop)
|
||||
WindowActionManager.ApplyAlwaysOnTop(_viewModel.ApplicationHandle, PanelType.PopOutManager, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SettingsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.panelPreferenceDrawer.Children.Clear();
|
||||
this.panelPreferenceDrawer.Children.Add(new PreferenceDrawer());
|
||||
}
|
||||
|
||||
private void HelpButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.panelPreferenceDrawer.Children.Clear();
|
||||
this.panelPreferenceDrawer.Children.Add(new HelpDrawer());
|
||||
}
|
||||
|
||||
private void BtnMinimize_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
private void BtnClose_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
//private void _viewModel_OnStatusMessageUpdated(object sender, (List<Run>, int) e)
|
||||
//{
|
||||
// var (messages, duration) = e;
|
||||
|
||||
// if (messages == null)
|
||||
// return;
|
||||
|
||||
// TextBlockMessage.Inlines.Clear();
|
||||
|
||||
// foreach (var run in messages)
|
||||
// TextBlockMessage.Inlines.Add(run);
|
||||
|
||||
// var lastRun = TextBlockMessage.Inlines.LastInline;
|
||||
|
||||
// if (lastRun != null && ((Run)lastRun).Text == Environment.NewLine)
|
||||
// TextBlockMessage.Inlines.Remove(lastRun);
|
||||
|
||||
// ScrollViewerMessageBar.ScrollToEnd();
|
||||
|
||||
// if (duration != -1)
|
||||
// {
|
||||
// Task.Run(() =>
|
||||
// {
|
||||
// Thread.Sleep(duration * 1000);
|
||||
|
||||
// Application.Current.Dispatcher.Invoke(() =>
|
||||
// {
|
||||
// TextBlockMessage.Inlines.Clear();
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -10,3 +10,4 @@ using System.Windows.Media;
|
|||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
28
MainApp/Converter/InverseBooleanOrConverter.cs
Normal file
28
MainApp/Converter/InverseBooleanOrConverter.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public class InverseBooleanOrConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (values.LongLength > 0)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (value is bool && (bool)value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return new object[] { false };
|
||||
}
|
||||
}
|
||||
}
|
20
MainApp/CustomControl/FontSizeConverter.cs
Normal file
20
MainApp/CustomControl/FontSizeConverter.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp.CustomControl
|
||||
{
|
||||
public class FontSizeConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double v = (double)value;
|
||||
return v * 0.6;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
216
MainApp/CustomControl/NumericUpDown.cs
Normal file
216
MainApp/CustomControl/NumericUpDown.cs
Normal file
|
@ -0,0 +1,216 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp.CustomControl
|
||||
{
|
||||
[TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
|
||||
[TemplatePart(Name = "PART_ButtonUp", Type = typeof(ButtonBase))]
|
||||
[TemplatePart(Name = "PART_ButtonDown", Type = typeof(ButtonBase))]
|
||||
public class NumericUpDown : Control
|
||||
{
|
||||
private TextBox PART_TextBox = new TextBox();
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
TextBox? textBox = GetTemplateChild("PART_TextBox") as TextBox;
|
||||
if (textBox != null)
|
||||
{
|
||||
PART_TextBox = textBox;
|
||||
PART_TextBox.PreviewKeyDown += textBox_PreviewKeyDown;
|
||||
PART_TextBox.TextChanged += textBox_TextChanged;
|
||||
PART_TextBox.Text = Value.ToString();
|
||||
}
|
||||
|
||||
ButtonBase? PART_ButtonUp = GetTemplateChild("PART_ButtonUp") as ButtonBase;
|
||||
if (PART_ButtonUp != null)
|
||||
{
|
||||
PART_ButtonUp.Click += buttonUp_Click;
|
||||
}
|
||||
|
||||
ButtonBase? PART_ButtonDown = GetTemplateChild("PART_ButtonDown") as ButtonBase;
|
||||
if (PART_ButtonDown != null)
|
||||
{
|
||||
PART_ButtonDown.Click += buttonDown_Click;
|
||||
}
|
||||
}
|
||||
|
||||
static NumericUpDown()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
|
||||
}
|
||||
|
||||
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ValueChanged", RoutingStrategy.Direct,
|
||||
typeof(ValueChangedEventHandler), typeof(NumericUpDown));
|
||||
public event ValueChangedEventHandler ValueChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
base.AddHandler(NumericUpDown.ValueChangedEvent, value);
|
||||
}
|
||||
remove
|
||||
{
|
||||
base.RemoveHandler(NumericUpDown.ValueChangedEvent, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Places
|
||||
{
|
||||
get { return (int)GetValue(PlacesProperty); }
|
||||
set { SetValue(PlacesProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PlacesProperty = DependencyProperty.Register("Places", typeof(int), typeof(NumericUpDown));
|
||||
|
||||
public double MaxValue
|
||||
{
|
||||
get { return (double)GetValue(MaxValueProperty); }
|
||||
set { SetValue(MaxValueProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty MaxValueProperty =
|
||||
DependencyProperty.Register("MaxValue", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(100D, maxValueChangedCallback, coerceMaxValueCallback));
|
||||
private static object coerceMaxValueCallback(DependencyObject d, object value)
|
||||
{
|
||||
double minValue = ((NumericUpDown)d).MinValue;
|
||||
if ((double)value < minValue)
|
||||
return minValue;
|
||||
|
||||
return value;
|
||||
}
|
||||
private static void maxValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
NumericUpDown numericUpDown = ((NumericUpDown)d);
|
||||
numericUpDown.CoerceValue(MinValueProperty);
|
||||
numericUpDown.CoerceValue(ValueProperty);
|
||||
}
|
||||
|
||||
public double MinValue
|
||||
{
|
||||
get { return (double)GetValue(MinValueProperty); }
|
||||
set { SetValue(MinValueProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MinValueProperty =
|
||||
DependencyProperty.Register("MinValue", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(0D, minValueChangedCallback, coerceMinValueCallback));
|
||||
|
||||
private static object coerceMinValueCallback(DependencyObject d, object value)
|
||||
{
|
||||
double maxValue = ((NumericUpDown)d).MaxValue;
|
||||
if ((double)value > maxValue)
|
||||
return maxValue;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void minValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
NumericUpDown numericUpDown = ((NumericUpDown)d);
|
||||
numericUpDown.CoerceValue(NumericUpDown.MaxValueProperty);
|
||||
numericUpDown.CoerceValue(NumericUpDown.ValueProperty);
|
||||
}
|
||||
|
||||
public double Increment
|
||||
{
|
||||
get { return (double)GetValue(IncrementProperty); }
|
||||
set { SetValue(IncrementProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty IncrementProperty =
|
||||
DependencyProperty.Register("Increment", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(1D, null, coerceIncrementCallback));
|
||||
private static object coerceIncrementCallback(DependencyObject d, object value)
|
||||
{
|
||||
NumericUpDown numericUpDown = ((NumericUpDown)d);
|
||||
double i = numericUpDown.MaxValue - numericUpDown.MinValue;
|
||||
if ((double)value > i)
|
||||
return i;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public double Value
|
||||
{
|
||||
get { return (double)GetValue(ValueProperty); }
|
||||
set { SetValue(ValueProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty ValueProperty =
|
||||
DependencyProperty.Register("Value", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(0D, valueChangedCallback, coerceValueCallback), validateValueCallback);
|
||||
private static void valueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
NumericUpDown numericUpDown = (NumericUpDown)d;
|
||||
ValueChangedEventArgs ea =
|
||||
new ValueChangedEventArgs(NumericUpDown.ValueChangedEvent, d, (double)e.OldValue, (double)e.NewValue);
|
||||
numericUpDown.RaiseEvent(ea);
|
||||
numericUpDown.PART_TextBox.Text = e.NewValue.ToString();
|
||||
}
|
||||
private static bool validateValueCallback(object value)
|
||||
{
|
||||
double val = (double)value;
|
||||
if (val > double.MinValue && val < double.MaxValue)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
private static object coerceValueCallback(DependencyObject d, object value)
|
||||
{
|
||||
double val = (double)value;
|
||||
double minValue = ((NumericUpDown)d).MinValue;
|
||||
double maxValue = ((NumericUpDown)d).MaxValue;
|
||||
double result;
|
||||
if (val < minValue)
|
||||
result = minValue;
|
||||
else if (val > maxValue)
|
||||
result = maxValue;
|
||||
else
|
||||
result = (double)value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void buttonUp_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Value < MaxValue)
|
||||
Value += Increment;
|
||||
|
||||
Value = Math.Round(Value, Places);
|
||||
}
|
||||
private void buttonDown_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Value > MinValue)
|
||||
Value -= Increment;
|
||||
|
||||
Value = Math.Round(Value, Places);
|
||||
}
|
||||
|
||||
private void textBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Space)
|
||||
e.Handled = true;
|
||||
}
|
||||
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
int index = PART_TextBox.CaretIndex;
|
||||
double result;
|
||||
if (!double.TryParse(PART_TextBox.Text, out result))
|
||||
{
|
||||
var changes = e.Changes.FirstOrDefault();
|
||||
if (changes != null)
|
||||
{
|
||||
PART_TextBox.Text = PART_TextBox.Text.Remove(changes.Offset, changes.AddedLength);
|
||||
PART_TextBox.CaretIndex = index > 0 ? index - changes.AddedLength : 0;
|
||||
}
|
||||
}
|
||||
else if (result < MaxValue && result > MinValue)
|
||||
Value = result;
|
||||
else
|
||||
{
|
||||
PART_TextBox.Text = Value.ToString();
|
||||
PART_TextBox.CaretIndex = index > 0 ? index - 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
MainApp/CustomControl/Themes/NumericUpDown.xaml
Normal file
52
MainApp/CustomControl/Themes/NumericUpDown.xaml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp.CustomControl">
|
||||
<local:FontSizeConverter x:Key="FontSizeConverter" />
|
||||
<Style TargetType="{x:Type local:NumericUpDown}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type local:NumericUpDown}">
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="PART_TextBox"
|
||||
Margin="-20,0,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
BorderThickness="0" />
|
||||
<Grid Grid.Column="1">
|
||||
<RepeatButton
|
||||
x:Name="PART_ButtonUp"
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="-40,0,0,0"
|
||||
Padding="2,0"
|
||||
Content="▲"
|
||||
FontSize="{Binding FontSize, Converter={StaticResource FontSizeConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:NumericUpDown}}}" />
|
||||
<RepeatButton
|
||||
x:Name="PART_ButtonDown"
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="1,0,0,0"
|
||||
Padding="2,0"
|
||||
Content="▼"
|
||||
FontSize="{Binding FontSize, Converter={StaticResource FontSizeConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:NumericUpDown}}}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush" Value="Gray" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="Width" Value="100" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
18
MainApp/CustomControl/ValueChangeEventHandler.cs
Normal file
18
MainApp/CustomControl/ValueChangeEventHandler.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp.CustomControl
|
||||
{
|
||||
public delegate void ValueChangedEventHandler(object sender, ValueChangedEventArgs e);
|
||||
|
||||
public class ValueChangedEventArgs : RoutedEventArgs
|
||||
{
|
||||
public ValueChangedEventArgs(RoutedEvent routedEvent, object source, double oldValue, double newValue)
|
||||
: base(routedEvent, source)
|
||||
{
|
||||
OldValue = oldValue;
|
||||
NewValue = newValue;
|
||||
}
|
||||
public double OldValue { get; private set; }
|
||||
public double NewValue { get; private set; }
|
||||
}
|
||||
}
|
272
MainApp/HudBar.xaml
Normal file
272
MainApp/HudBar.xaml
Normal file
|
@ -0,0 +1,272 @@
|
|||
<Window
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.HudBar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Title="HudBar"
|
||||
Width="1920"
|
||||
MinWidth="1920"
|
||||
MinHeight="40"
|
||||
MaxHeight="40"
|
||||
ResizeMode="NoResize"
|
||||
WindowStyle="None"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
<Style
|
||||
x:Key="TxtBoxLabel"
|
||||
BasedOn="{StaticResource MaterialDesignBody1TextBlock}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TxtBoxData"
|
||||
BasedOn="{StaticResource MaterialDesignBody1TextBlock}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="0,5,10,5" />
|
||||
<Setter Property="Foreground" Value="Lime" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="VerticalSeparator"
|
||||
BasedOn="{StaticResource {x:Type Separator}}"
|
||||
TargetType="Separator">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter Property="Margin" Value="6,0,6,0" />
|
||||
<Setter Property="LayoutTransform">
|
||||
<Setter.Value>
|
||||
<TransformGroup>
|
||||
<TransformGroup.Children>
|
||||
<TransformCollection>
|
||||
<RotateTransform Angle="90" />
|
||||
</TransformCollection>
|
||||
</TransformGroup.Children>
|
||||
</TransformGroup>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<materialDesign:ColorZone Height="40" Mode="Dark">
|
||||
<Grid d:DataContext="{d:DesignInstance viewmodel:HudBarViewModel}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="130" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="6*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="4*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="100" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="10,5,0,0"
|
||||
Style="{StaticResource TxtBoxLabel}"
|
||||
Text="{Binding HudBarTypeText}" />
|
||||
<DockPanel Grid.Column="1">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="2">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Elevator Trim:</TextBlock>
|
||||
<TextBlock Style="{StaticResource TxtBoxData}" Text="{Binding FlightSimData.HudBarData.ElevatorTrimFormatted}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="3">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="4">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Aileron Trim:</TextBlock>
|
||||
<TextBlock Style="{StaticResource TxtBoxData}" Text="{Binding FlightSimData.HudBarData.AileronTrimFormatted}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="5">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="6">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Rudder Trim:</TextBlock>
|
||||
<TextBlock Style="{StaticResource TxtBoxData}" Text="{Binding FlightSimData.HudBarData.RudderTrimFormatted}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="7">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="8">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Flaps:</TextBlock>
|
||||
<TextBlock Style="{StaticResource TxtBoxData}" Text="{Binding FlightSimData.HudBarData.FlapFormatted}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="9">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="10">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Brake:</TextBlock>
|
||||
<TextBlock Text="{Binding FlightSimData.HudBarData.ParkingBrakeFormatted}">
|
||||
<TextBlock.Style>
|
||||
<Style BasedOn="{StaticResource TxtBoxData}" TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.ParkingBrakeFormatted}" Value="Disengaged">
|
||||
<Setter Property="TextBlock.Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.ParkingBrakeFormatted}" Value="Engaged">
|
||||
<Setter Property="TextBlock.Foreground" Value="Red" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="11">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="12">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Gear:</TextBlock>
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock Text="L">
|
||||
<TextBlock.Style>
|
||||
<Style BasedOn="{StaticResource TxtBoxData}" TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="10,5,10,0" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearLeftFormatted}" Value="DOWN">
|
||||
<Setter Property="TextBlock.Foreground" Value="Lime" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearLeftFormatted}" Value="UP">
|
||||
<Setter Property="TextBlock.Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearLeftFormatted}" Value="MOVING">
|
||||
<Setter Property="TextBlock.Foreground" Value="Red" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBlock Text="C">
|
||||
<TextBlock.Style>
|
||||
<Style BasedOn="{StaticResource TxtBoxData}" TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="10,5,10,0" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearCenterFormatted}" Value="DOWN">
|
||||
<Setter Property="TextBlock.Foreground" Value="Lime" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearCenterFormatted}" Value="UP">
|
||||
<Setter Property="TextBlock.Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearCenterFormatted}" Value="MOVING">
|
||||
<Setter Property="TextBlock.Foreground" Value="Red" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBlock Text="R">
|
||||
<TextBlock.Style>
|
||||
<Style BasedOn="{StaticResource TxtBoxData}" TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="10,5,10,0" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearRightFormatted}" Value="DOWN">
|
||||
<Setter Property="TextBlock.Foreground" Value="Lime" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearRightFormatted}" Value="UP">
|
||||
<Setter Property="TextBlock.Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HudBarData.GearRightFormatted}" Value="MOVING">
|
||||
<Setter Property="TextBlock.Foreground" Value="Red" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="13">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="14">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Timer:</TextBlock>
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock Style="{StaticResource TxtBoxData}" Text="{Binding Timer, StringFormat={}{0:HH:mm:ss}}" />
|
||||
<Button
|
||||
Width="80"
|
||||
Height="28"
|
||||
Margin="10,0,0,0"
|
||||
Command="{Binding StartStopTimerCommand}"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
<TextBlock Foreground="White" Text="{c:Binding 'IsTimerStarted ? "STOP" : "START"'}" />
|
||||
</Button>
|
||||
<Button
|
||||
Width="80"
|
||||
Height="28"
|
||||
Margin="15,0,10,0"
|
||||
Command="{Binding ResetTimerCommand}"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
<TextBlock Foreground="White" Text="RESET" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="15">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="16">
|
||||
<TextBlock Style="{StaticResource TxtBoxLabel}">Sim Rate:</TextBlock>
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,5,5,0"
|
||||
Style="{StaticResource TxtBoxData}"
|
||||
Text="{Binding FlightSimData.HudBarData.SimRate}" />
|
||||
<TextBlock
|
||||
Margin="0,5,20,0"
|
||||
Style="{StaticResource TxtBoxData}"
|
||||
Text="X" />
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="0,0,15,0"
|
||||
Command="{Binding IncreaseSimRateCommand}"
|
||||
Style="{StaticResource MaterialDesignFloatingActionButton}">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="ArrowUp" />
|
||||
</Button>
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding DecreaseSimRateCommand}"
|
||||
Style="{StaticResource MaterialDesignFloatingActionButton}">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="ArrowDown" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="17">
|
||||
<Separator Style="{StaticResource VerticalSeparator}" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Column="18">
|
||||
<Button
|
||||
x:Name="BtnClose"
|
||||
Width="80"
|
||||
Height="28"
|
||||
Click="BtnClose_Click"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
<TextBlock Foreground="White" Text="Close" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</materialDesign:ColorZone>
|
||||
</Window>
|
49
MainApp/HudBar.xaml.cs
Normal file
49
MainApp/HudBar.xaml.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class HudBar : Window
|
||||
{
|
||||
private HudBarViewModel _viewModel;
|
||||
|
||||
public HudBar(Guid panelId)
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<HudBarViewModel>();
|
||||
_viewModel.PanelId = panelId;
|
||||
|
||||
InitializeComponent();
|
||||
Loaded += (sender, e) =>
|
||||
{
|
||||
DataContext = _viewModel;
|
||||
_viewModel.PanelConfig.PanelHandle = new WindowInteropHelper(Window.GetWindow(this)).Handle;
|
||||
_viewModel.PanelConfig.Width = Convert.ToInt32(Width);
|
||||
_viewModel.PanelConfig.Height = Convert.ToInt32(Height);
|
||||
};
|
||||
|
||||
this.MouseLeftButtonDown += HudBar_MouseLeftButtonDown;
|
||||
this.Topmost = true;
|
||||
|
||||
Closing += HudBar_Closing;
|
||||
}
|
||||
|
||||
private void HudBar_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
_viewModel.CloseCommand.Execute(null);
|
||||
}
|
||||
|
||||
private void HudBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
DragMove();
|
||||
}
|
||||
|
||||
private void BtnClose_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
102
MainApp/MainApp.csproj
Normal file
102
MainApp/MainApp.csproj
Normal file
|
@ -0,0 +1,102 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<AssemblyName>MSFSPopoutPanelManager</AssemblyName>
|
||||
<PackageId>MSFS 2020 Popout Panel Manager</PackageId>
|
||||
<Product>MSFS 2020 Popout Panel Manager</Product>
|
||||
<Authors>Stanley Kwok</Authors>
|
||||
<Company>Stanley Kwok</Company>
|
||||
<Copyright>Stanley Kwok 2021</Copyright>
|
||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||
<RootNamespace>MSFSPopoutPanelManager.MainApp</RootNamespace>
|
||||
<ApplicationIcon>logo.ico</ApplicationIcon>
|
||||
<Platforms>x64</Platforms>
|
||||
<Version>4.0.0.0</Version>
|
||||
<AssemblyVersion>4.0.0.0</AssemblyVersion>
|
||||
<FileVersion>4.0.0.0</FileVersion>
|
||||
<DebugType>embedded</DebugType>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
<!-- Publishing options -->
|
||||
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
|
||||
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
<PublishReadyToRunComposite>false</PublishReadyToRunComposite>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="logo.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="log4net.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Autoupdater.NET.Official" Version="1.8.3" />
|
||||
<PackageReference Include="DotNetKit.Wpf.AutoCompleteComboBox" Version="1.6.0" />
|
||||
<PackageReference Include="Fody" Version="6.7.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="gong-wpf-dragdrop" Version="3.2.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="CalcBinding" Version="2.5.2" />
|
||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="4.9.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageReference Include="Prism.Core" Version="8.1.97" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="InputSimulatorCore" Version="1.0.5" />
|
||||
<PackageReference Include="WindowsHook" Version="1.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="AppWindow.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="CustomControl\Themes\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DomainModel\DomainModel.csproj" />
|
||||
<ProjectReference Include="..\Orchestration\Orchestration.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="logo.png">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyItems" AfterTargets="ComputeFilesToPublish">
|
||||
<!-- Copy all plugin-extensions items -->
|
||||
<ItemGroup>
|
||||
<Skipper Include="$(SolutionDir)\Assets\Community\zzz-ready-to-fly-button-skipper\**"></Skipper>
|
||||
<License Include="$(SolutionDir)\LICENSE"></License>
|
||||
<Version Include="$(SolutionDir)\VERSION.md"></Version>
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(License)" DestinationFolder="$(PublishDir)" SkipUnchangedFiles="false" OverwriteReadOnlyFiles="true" />
|
||||
<Copy SourceFiles="@(Version)" DestinationFolder="$(PublishDir)" SkipUnchangedFiles="false" OverwriteReadOnlyFiles="true" />
|
||||
<Copy SourceFiles="@(Skipper)" DestinationFolder="$(PublishDir)Community\zzz-ready-to-fly-button-skipper\%(RecursiveDir)" SkipUnchangedFiles="false" OverwriteReadOnlyFiles="true" />
|
||||
</Target>
|
||||
</Project>
|
64
MainApp/MessageWindow.xaml
Normal file
64
MainApp/MessageWindow.xaml
Normal file
|
@ -0,0 +1,64 @@
|
|||
<Window
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.MessageWindow"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Title="MSFS Pop Out Panel Manager"
|
||||
Width="Auto"
|
||||
Height="Auto"
|
||||
AllowsTransparency="True"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Topmost="True"
|
||||
WindowStyle="None"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
<Style
|
||||
x:Key="Label"
|
||||
BasedOn="{StaticResource MaterialDesignBody1TextBlock}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<materialDesign:ColorZone
|
||||
Width="Auto"
|
||||
Height="Auto"
|
||||
Mode="Dark">
|
||||
<DockPanel
|
||||
Width="400"
|
||||
Height="225"
|
||||
d:DataContext="{d:DesignInstance viewmodel:MessageWindowViewModel}">
|
||||
<WrapPanel
|
||||
Height="30"
|
||||
Background="SlateGray"
|
||||
DockPanel.Dock="Top">
|
||||
<TextBlock
|
||||
Padding="10,5,10,5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Style="{StaticResource MaterialDesignBody1TextBlock}">
|
||||
MSFS POP OUT PANEL MANAGER
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="20,5,20,10">
|
||||
<ScrollViewer
|
||||
x:Name="ScrollViewerMessage"
|
||||
Height="Auto"
|
||||
DockPanel.Dock="Bottom"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
VerticalScrollBarVisibility="Hidden">
|
||||
<TextBlock
|
||||
x:Name="TextBlockMessage"
|
||||
LineHeight="18"
|
||||
LineStackingStrategy="BlockLineHeight" />
|
||||
</ScrollViewer>
|
||||
</WrapPanel>
|
||||
</DockPanel>
|
||||
</materialDesign:ColorZone>
|
||||
</Window>
|
72
MainApp/MessageWindow.xaml.cs
Normal file
72
MainApp/MessageWindow.xaml.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class MessageWindow : Window
|
||||
{
|
||||
private MessageWindowViewModel _viewModel;
|
||||
|
||||
public MessageWindow()
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<MessageWindowViewModel>();
|
||||
|
||||
InitializeComponent();
|
||||
Loaded += (sender, e) =>
|
||||
{
|
||||
DataContext = _viewModel;
|
||||
_viewModel.Handle = new WindowInteropHelper(Window.GetWindow(this)).Handle;
|
||||
|
||||
// Set window binding, needs to be in code after window loaded
|
||||
Binding visibleBinding = new Binding("IsVisible");
|
||||
visibleBinding.Source = _viewModel;
|
||||
visibleBinding.Converter = new BooleanToVisibilityConverter();
|
||||
BindingOperations.SetBinding(this, Window.VisibilityProperty, visibleBinding);
|
||||
|
||||
// Set window click through
|
||||
WindowsServices.SetWindowExTransparent(_viewModel.Handle);
|
||||
|
||||
_viewModel.OnMessageUpdated += _viewModel_OnMessageUpdated;
|
||||
};
|
||||
}
|
||||
|
||||
private void _viewModel_OnMessageUpdated(object sender, List<Run> e)
|
||||
{
|
||||
if (e == null)
|
||||
return;
|
||||
|
||||
TextBlockMessage.Inlines.Clear();
|
||||
|
||||
foreach (var run in e)
|
||||
TextBlockMessage.Inlines.Add(run);
|
||||
|
||||
ScrollViewerMessage.ScrollToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public static class WindowsServices
|
||||
{
|
||||
const int WS_EX_TRANSPARENT = 0x00000020;
|
||||
const int GWL_EXSTYLE = (-20);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern int GetWindowLong(IntPtr hwnd, int index);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
|
||||
|
||||
public static void SetWindowExTransparent(IntPtr hwnd)
|
||||
{
|
||||
var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
}
|
70
MainApp/PanelCoorOverlay.xaml
Normal file
70
MainApp/PanelCoorOverlay.xaml
Normal file
|
@ -0,0 +1,70 @@
|
|||
<Window
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.PanelCoorOverlay"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="PanelCoorOverlay"
|
||||
Width="30"
|
||||
Height="30"
|
||||
AllowsTransparency="True"
|
||||
Background="#01F0F0FF"
|
||||
Loaded="Window_Loaded"
|
||||
MouseMove="Window_MouseMove"
|
||||
ResizeMode="NoResize"
|
||||
SizeToContent="WidthAndHeight"
|
||||
WindowStyle="None"
|
||||
mc:Ignorable="d">
|
||||
<Canvas
|
||||
Width="30"
|
||||
Height="30"
|
||||
PreviewMouseDown="Canvas_PreviewMouseDown"
|
||||
ToolTip="{Binding Panel.PanelName}">
|
||||
<Grid>
|
||||
<Ellipse
|
||||
x:Name="OverlayCircle"
|
||||
Canvas.Left="1"
|
||||
Canvas.Top="1"
|
||||
Width="28"
|
||||
Height="28"
|
||||
Fill="Transparent"
|
||||
StrokeThickness="6" />
|
||||
<Ellipse
|
||||
x:Name="OverlayBlinkingCircle"
|
||||
Canvas.Left="0"
|
||||
Canvas.Top="0"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Fill="Transparent"
|
||||
Stroke="Black"
|
||||
StrokeThickness="7"
|
||||
Visibility="{c:Binding Panel.IsShownPanelSource}">
|
||||
<Ellipse.Triggers>
|
||||
<EventTrigger RoutedEvent="Ellipse.Loaded">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
AutoReverse="True"
|
||||
RepeatBehavior="Forever"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="0:0:0.4" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</Ellipse.Triggers>
|
||||
</Ellipse>
|
||||
<Ellipse
|
||||
x:Name="OverlayCircleBorder"
|
||||
Canvas.Left="0"
|
||||
Canvas.Top="0"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Fill="Transparent"
|
||||
Opacity="0.5"
|
||||
Stroke="White" />
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</Window>
|
96
MainApp/PanelCoorOverlay.xaml.cs
Normal file
96
MainApp/PanelCoorOverlay.xaml.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using MSFSPopoutPanelManager.WindowsAgent;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class PanelCoorOverlay : Window
|
||||
{
|
||||
private PanelCoorOverlayViewModel _viewModel;
|
||||
|
||||
private const int WINDOW_ADJUSTMENT = 15; // half of window height with shadow adjustment
|
||||
private int _xCoor;
|
||||
private int _yCoor;
|
||||
|
||||
public bool IsEditingPanelLocation { get; set; }
|
||||
|
||||
public Guid PanelId { get; set; }
|
||||
|
||||
public IntPtr WindowHandle { get; set; }
|
||||
|
||||
public event EventHandler<System.Drawing.Point> WindowLocationChanged;
|
||||
|
||||
public PanelCoorOverlay(Guid id)
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<PanelCoorOverlayViewModel>();
|
||||
_viewModel.SetPanelId(id);
|
||||
PanelId = id;
|
||||
|
||||
InitializeComponent();
|
||||
Loaded += PanelCoorOverlay_Loaded;
|
||||
|
||||
OverlayCircle.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString(_viewModel.Panel.PanelSource.Color));
|
||||
|
||||
if (!_viewModel.ProfileData.ActiveProfile.IsEditingPanelSource)
|
||||
OverlayBlinkingCircle.Visibility = Visibility.Collapsed;
|
||||
|
||||
IsEditingPanelLocation = false;
|
||||
this.Topmost = true;
|
||||
this.Left = 0;
|
||||
this.Top = 0;
|
||||
|
||||
this.MouseUp += PanelCoorOverlay_MouseUp; // detect location change when user release mouse button when dragging the overlay window
|
||||
}
|
||||
|
||||
private void PanelCoorOverlay_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.DataContext = _viewModel;
|
||||
}
|
||||
|
||||
private void PanelCoorOverlay_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.Top is double.NaN || this.Left is double.NaN)
|
||||
return;
|
||||
|
||||
// Fixed broken window left/top coordinate for DPI Awareness Per Monitor
|
||||
var handle = new WindowInteropHelper(this).Handle;
|
||||
var rect = WindowActionManager.GetWindowRectangle(handle);
|
||||
WindowLocationChanged?.Invoke(this, new System.Drawing.Point(rect.X + WINDOW_ADJUSTMENT, rect.Y + WINDOW_ADJUSTMENT));
|
||||
|
||||
if (_viewModel.Panel != null)
|
||||
_viewModel.Panel.IsSelectedPanelSource = false;
|
||||
}
|
||||
|
||||
public void SetWindowCoor(int x, int y)
|
||||
{
|
||||
_xCoor = x;
|
||||
_yCoor = y;
|
||||
}
|
||||
|
||||
private void Window_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
if (IsEditingPanelLocation && e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
|
||||
this.DragMove();
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Fixed broken window left/top coordinate for DPI Awareness Per Monitor
|
||||
var handle = new WindowInteropHelper(this).Handle;
|
||||
|
||||
WindowActionManager.MoveWindow(handle, _xCoor - WINDOW_ADJUSTMENT, _yCoor - WINDOW_ADJUSTMENT, Convert.ToInt32(this.Width), Convert.ToInt32(this.Height));
|
||||
WindowActionManager.ApplyAlwaysOnTop(handle, PanelType.PanelSourceWindow, true);
|
||||
}
|
||||
|
||||
private void Canvas_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && _viewModel.Panel != null)
|
||||
_viewModel.Panel.IsSelectedPanelSource = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||
<Platform>x64</Platform>
|
||||
<PublishDir>..\..\..\publish\master</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<SelfContained>true</SelfContained>
|
||||
<DeleteExistingFiles>true</DeleteExistingFiles>
|
||||
<PublishWithAspNetCoreTargetManifest>true</PublishWithAspNetCoreTargetManifest>
|
316
MainApp/Styles/CustomMaterialDesignExpander.xaml
Normal file
316
MainApp/Styles/CustomMaterialDesignExpander.xaml
Normal file
|
@ -0,0 +1,316 @@
|
|||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:profileDomain="clr-namespace:MSFSPopoutPanelManager.DomainModel.Profile;assembly=DomainModel"
|
||||
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf">
|
||||
|
||||
<Duration x:Key="ExpandDuration">0:0:0.250</Duration>
|
||||
<Duration x:Key="CollapseDuration">0:0:0.200</Duration>
|
||||
|
||||
<KeyTime x:Key="ExpandKeyTime">0:0:0.250</KeyTime>
|
||||
<KeyTime x:Key="CollapseKeyTime">0:0:0.200</KeyTime>
|
||||
|
||||
<Style x:Key="MaterialDesignExpanderToggleButton" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Border Background="Transparent" BorderThickness="0">
|
||||
<wpf:PackIcon
|
||||
x:Name="ExpandPath"
|
||||
Width="24"
|
||||
Height="24"
|
||||
Padding="0"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Kind="ChevronDown"
|
||||
Opacity="0.5"
|
||||
RenderTransformOrigin="0.5 0.5"
|
||||
Visibility="{c:Binding 'DataItem.PanelType!=profileDomain:PanelType.HudBarWindow'}">
|
||||
<wpf:PackIcon.RenderTransform>
|
||||
<RotateTransform x:Name="ExpandPathRotateTransform" />
|
||||
</wpf:PackIcon.RenderTransform>
|
||||
</wpf:PackIcon>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CheckStates">
|
||||
<VisualState x:Name="Checked">
|
||||
<Storyboard>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPathRotateTransform" Storyboard.TargetProperty="Angle">
|
||||
<EasingDoubleKeyFrame KeyTime="{StaticResource ExpandKeyTime}" Value="180" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Unchecked">
|
||||
<Storyboard>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPathRotateTransform" Storyboard.TargetProperty="Angle">
|
||||
<EasingDoubleKeyFrame KeyTime="{StaticResource CollapseKeyTime}" Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MaterialDesignHorizontalHeaderStyleButton" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ToggleButton
|
||||
x:Name="ExpanderButton"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsChecked="{Binding Path=IsChecked, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
RenderTransformOrigin="0.5 0.5">
|
||||
<ToggleButton.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignExpanderToggleButton}" TargetType="{x:Type ToggleButton}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ExpandDirection, RelativeSource={RelativeSource AncestorType=Expander, AncestorLevel=1}}" Value="Up">
|
||||
<Setter Property="RenderTransform">
|
||||
<Setter.Value>
|
||||
<RotateTransform Angle="180" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MaterialDesignHorizontalHeaderStyleContent" TargetType="{x:Type Button}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Padding="{Binding Path=(wpf:ExpanderAssist.HorizontalHeaderPadding), RelativeSource={RelativeSource AncestorType=Expander, AncestorLevel=1}}" Background="{TemplateBinding Background}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentStringFormat="{TemplateBinding ContentStringFormat}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CustomMaterialDesignExpander" TargetType="{x:Type Expander}">
|
||||
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Expander}">
|
||||
<ControlTemplate.Resources>
|
||||
<local:ExpanderRotateAngleConverter x:Key="ExpanderRotateAngleConverter" />
|
||||
</ControlTemplate.Resources>
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<DockPanel Background="{TemplateBinding Background}">
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
|
||||
<Button
|
||||
Name="HeaderSiteContent"
|
||||
Background="{TemplateBinding wpf:ExpanderAssist.HeaderBackground}"
|
||||
BorderThickness="0"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
|
||||
DockPanel.Dock="Top"
|
||||
Focusable="False"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsTabStop="False"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}"
|
||||
TextElement.FontSize="{TemplateBinding wpf:ExpanderAssist.HeaderFontSize}" />
|
||||
<StackPanel
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<ToggleButton
|
||||
Name="HeaderSiteButton"
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
Background="{TemplateBinding wpf:ExpanderAssist.HeaderBackground}"
|
||||
BorderThickness="0"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
|
||||
Cursor="Hand"
|
||||
Focusable="False"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsTabStop="False"
|
||||
TextElement.FontSize="{TemplateBinding wpf:ExpanderAssist.HeaderFontSize}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<Border Name="ContentSite">
|
||||
<Border.LayoutTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform x:Name="ContentSiteScaleTransform" />
|
||||
<RotateTransform Angle="{Binding Path=ExpandDirection, RelativeSource={RelativeSource AncestorType=Expander}, Converter={StaticResource ExpanderRotateAngleConverter}}" />
|
||||
</TransformGroup>
|
||||
</Border.LayoutTransform>
|
||||
<Grid
|
||||
Name="ContentPanel"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
|
||||
<Grid.LayoutTransform>
|
||||
<RotateTransform Angle="{Binding Path=ExpandDirection, RelativeSource={RelativeSource AncestorType=Expander}, Converter={StaticResource ExpanderRotateAngleConverter}, ConverterParameter=-1}" />
|
||||
</Grid.LayoutTransform>
|
||||
<ContentPresenter
|
||||
Name="PART_Content"
|
||||
ContentStringFormat="{TemplateBinding ContentStringFormat}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
|
||||
Focusable="False"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="ExpansionStates">
|
||||
<VisualStateGroup.Transitions>
|
||||
<VisualTransition To="Expanded">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentPanel"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="{DynamicResource ExpandDuration}" />
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentSiteScaleTransform"
|
||||
Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="{DynamicResource ExpandDuration}">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<CubicEase EasingMode="EaseInOut" />
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="PART_Content"
|
||||
Storyboard.TargetProperty="Visibility"
|
||||
Duration="0:0:0">
|
||||
<DiscreteObjectKeyFrame KeyTime="0%" Value="{x:Static Visibility.Visible}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
|
||||
<VisualTransition To="Collapsed">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentPanel"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="1"
|
||||
To="0"
|
||||
Duration="{DynamicResource CollapseDuration}" />
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentSiteScaleTransform"
|
||||
Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
|
||||
From="1"
|
||||
To="0"
|
||||
Duration="{DynamicResource CollapseDuration}">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<CubicEase EasingMode="EaseInOut" />
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="PART_Content"
|
||||
Storyboard.TargetProperty="Visibility"
|
||||
Duration="{DynamicResource CollapseDuration}">
|
||||
<DiscreteObjectKeyFrame KeyTime="100%" Value="{x:Static Visibility.Collapsed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
</VisualStateGroup.Transitions>
|
||||
|
||||
<VisualState x:Name="Expanded">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentPanel"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="1"
|
||||
Duration="0" />
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentSiteScaleTransform"
|
||||
Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
|
||||
To="1"
|
||||
Duration="0" />
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="PART_Content"
|
||||
Storyboard.TargetProperty="Visibility"
|
||||
Duration="0">
|
||||
<DiscreteObjectKeyFrame KeyTime="0%" Value="{x:Static Visibility.Visible}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Collapsed">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentPanel"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0"
|
||||
Duration="0" />
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ContentSiteScaleTransform"
|
||||
Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
|
||||
To="0"
|
||||
Duration="0" />
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="PART_Content"
|
||||
Storyboard.TargetProperty="Visibility"
|
||||
Duration="0">
|
||||
<DiscreteObjectKeyFrame KeyTime="100%" Value="{x:Static Visibility.Collapsed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="ExpandDirection" Value="Up">
|
||||
<Setter TargetName="HeaderSiteButton" Property="DockPanel.Dock" Value="Bottom" />
|
||||
<Setter TargetName="HeaderSiteButton" Property="Style" Value="{StaticResource MaterialDesignHorizontalHeaderStyleButton}" />
|
||||
<Setter TargetName="HeaderSiteContent" Property="Style" Value="{StaticResource MaterialDesignHorizontalHeaderStyleContent}" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="ExpandDirection" Value="Down">
|
||||
<Setter TargetName="HeaderSiteButton" Property="DockPanel.Dock" Value="Top" />
|
||||
<Setter TargetName="HeaderSiteButton" Property="Style" Value="{StaticResource MaterialDesignHorizontalHeaderStyleButton}" />
|
||||
<Setter TargetName="HeaderSiteContent" Property="Style" Value="{StaticResource MaterialDesignHorizontalHeaderStyleContent}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="VerticalContentAlignment" Value="Top" />
|
||||
<Setter Property="wpf:ExpanderAssist.HeaderBackground" Value="Transparent" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
44
MainApp/Styles/CustomScrollViewStyle.xaml
Normal file
44
MainApp/Styles/CustomScrollViewStyle.xaml
Normal file
|
@ -0,0 +1,44 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Style TargetType="{x:Type ScrollViewer}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollViewer}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollContentPresenter Grid.Column="0" />
|
||||
<ScrollBar
|
||||
Name="PART_VerticalScrollBar"
|
||||
Grid.Column="1"
|
||||
Width="10"
|
||||
MinWidth="10"
|
||||
Maximum="{TemplateBinding ScrollableHeight}"
|
||||
Opacity="0.5"
|
||||
ViewportSize="{TemplateBinding ViewportHeight}"
|
||||
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
|
||||
Value="{TemplateBinding VerticalOffset}" />
|
||||
<ScrollBar
|
||||
Name="PART_HorizontalScrollBar"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Height="10"
|
||||
MinHeight="10"
|
||||
Maximum="{TemplateBinding ScrollableWidth}"
|
||||
Opacity="0.5"
|
||||
Orientation="Horizontal"
|
||||
ViewportSize="{TemplateBinding ViewportWidth}"
|
||||
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
|
||||
Value="{TemplateBinding HorizontalOffset}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
33
MainApp/Styles/ExpanderRotateAngleConverter.cs
Normal file
33
MainApp/Styles/ExpanderRotateAngleConverter.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public class ExpanderRotateAngleConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double factor = 1.0;
|
||||
if (parameter is { } parameterValue)
|
||||
{
|
||||
if (!double.TryParse(parameterValue.ToString(), out factor))
|
||||
{
|
||||
factor = 1.0;
|
||||
}
|
||||
}
|
||||
return value switch
|
||||
{
|
||||
ExpandDirection.Left => 90 * factor,
|
||||
ExpandDirection.Right => -90 * factor,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
92
MainApp/UserControl/Dialog/AddProfileDialog.xaml
Normal file
92
MainApp/UserControl/Dialog/AddProfileDialog.xaml
Normal file
|
@ -0,0 +1,92 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.AddProfileDialog"
|
||||
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:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
|
||||
Width="400"
|
||||
Height="210"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<local:InverseBooleanOrConverter x:Key="InverseBooleanOrConverter" />
|
||||
</UserControl.Resources>
|
||||
<StackPanel>
|
||||
<materialDesign:ColorZone
|
||||
Height="30"
|
||||
materialDesign:ElevationAssist.Elevation="Dp4"
|
||||
Mode="PrimaryDark">
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Margin="24,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="Add Profile" />
|
||||
</StackPanel>
|
||||
</materialDesign:ColorZone>
|
||||
<StackPanel
|
||||
Height="84"
|
||||
Margin="24,12,24,16"
|
||||
HorizontalAlignment="Stretch"
|
||||
FocusManager.FocusedElement="{Binding ElementName=TxtBoxName}">
|
||||
<ComboBox
|
||||
materialDesign:HintAssist.FloatingScale="0.75"
|
||||
materialDesign:HintAssist.Hint="Copy From Profile"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding ProfileData.Profiles}"
|
||||
MaxDropDownHeight="280"
|
||||
SelectedValue="{Binding CopiedProfile, Mode=TwoWay}"
|
||||
Style="{StaticResource MaterialDesignFloatingHintComboBox}" />
|
||||
<TextBox
|
||||
x:Name="TxtBoxName"
|
||||
Margin="0,8,0,0"
|
||||
VerticalAlignment="Center"
|
||||
materialDesign:HintAssist.FloatingScale="0.75"
|
||||
materialDesign:HintAssist.Hint="Profile Name"
|
||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}">
|
||||
<Binding
|
||||
Mode="TwoWay"
|
||||
Path="Profile.Name"
|
||||
UpdateSourceTrigger="PropertyChanged"
|
||||
ValidatesOnDataErrors="True">
|
||||
<Binding.ValidationRules>
|
||||
<viewmodel:PostiveValidationRule />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Height="50"
|
||||
Margin="24,12,24,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="BtnAccept"
|
||||
Command="{x:Static wpf:DialogHost.CloseDialogCommand}"
|
||||
CommandParameter="ADD"
|
||||
IsDefault="True"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
ACCEPT
|
||||
<Button.IsEnabled>
|
||||
<MultiBinding Converter="{StaticResource InverseBooleanOrConverter}" Mode="TwoWay">
|
||||
<Binding ElementName="TxtBoxName" Path="(Validation.HasError)" />
|
||||
<Binding Path="Profile.Name.Length" />
|
||||
</MultiBinding>
|
||||
</Button.IsEnabled>
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="BtnCancel"
|
||||
Margin="12,0,0,0"
|
||||
Command="{x:Static wpf:DialogHost.CloseDialogCommand}"
|
||||
CommandParameter="CANCEL"
|
||||
IsCancel="True"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
CANCEL
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
26
MainApp/UserControl/Dialog/AddProfileDialog.xaml.cs
Normal file
26
MainApp/UserControl/Dialog/AddProfileDialog.xaml.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using MaterialDesignThemes.Wpf;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class AddProfileDialog : UserControl
|
||||
{
|
||||
public AddProfileViewModel ViewModel { get; set; }
|
||||
|
||||
public AddProfileDialog()
|
||||
{
|
||||
ViewModel = App.AppHost.Services.GetRequiredService<AddProfileViewModel>();
|
||||
InitializeComponent();
|
||||
Loaded += (sender, e) =>
|
||||
{
|
||||
DataContext = ViewModel;
|
||||
BtnAccept.IsEnabled = false;
|
||||
};
|
||||
}
|
||||
|
||||
public DialogClosingEventHandler ClosingEventHandler { get { return ViewModel.ClosingEventHandler; } }
|
||||
}
|
||||
}
|
55
MainApp/UserControl/Dialog/ConfirmationDialog.xaml
Normal file
55
MainApp/UserControl/Dialog/ConfirmationDialog.xaml
Normal file
|
@ -0,0 +1,55 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.ConfirmationDialog"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
|
||||
Width="400"
|
||||
MinHeight="170"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel>
|
||||
<materialDesign:ColorZone
|
||||
Height="30"
|
||||
materialDesign:ElevationAssist.Elevation="Dp4"
|
||||
Mode="PrimaryDark">
|
||||
<StackPanel
|
||||
Margin="24,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Title}" />
|
||||
</StackPanel>
|
||||
</materialDesign:ColorZone>
|
||||
<StackPanel
|
||||
MinHeight="40"
|
||||
Margin="24,24,24,16"
|
||||
Orientation="Vertical">
|
||||
<TextBlock
|
||||
VerticalAlignment="Top"
|
||||
Text="{Binding Content}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Margin="24,12,24,8"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Command="{x:Static wpf:DialogHost.CloseDialogCommand}"
|
||||
CommandParameter="CONFIRM"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
<TextBlock Text="{Binding ConfirmButtonText}" />
|
||||
</Button>
|
||||
<Button
|
||||
Margin="12,0,0,0"
|
||||
Command="{x:Static wpf:DialogHost.CloseDialogCommand}"
|
||||
CommandParameter="CANCEL"
|
||||
IsCancel="True"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}">
|
||||
CANCEL
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
14
MainApp/UserControl/Dialog/ConfirmationDialog.xaml.cs
Normal file
14
MainApp/UserControl/Dialog/ConfirmationDialog.xaml.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class ConfirmationDialog : UserControl
|
||||
{
|
||||
public ConfirmationDialog(string content, string confirmButtonText)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new ConfirmationViewModel(content, confirmButtonText);
|
||||
}
|
||||
}
|
||||
}
|
343
MainApp/UserControl/HelpDrawer.xaml
Normal file
343
MainApp/UserControl/HelpDrawer.xaml
Normal file
|
@ -0,0 +1,343 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.HelpDrawer"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Width="1024"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<Style
|
||||
x:Key="TextBlockHeading"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Width" Value="Auto" />
|
||||
<Setter Property="Margin" Value="0,5,0,0" />
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlockSubheading"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Width" Value="Auto" />
|
||||
<Setter Property="Margin" Value="0,5,0,5" />
|
||||
</Style>
|
||||
<Style TargetType="AccessText">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Width" Value="Auto" />
|
||||
<Setter Property="Margin" Value="5,-2,0,0" />
|
||||
</Style>
|
||||
<Style TargetType="Line">
|
||||
<Setter Property="Margin" Value="0,5,0,5" />
|
||||
</Style>
|
||||
<Style TargetType="{x:Type ScrollViewer}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollViewer}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollContentPresenter Grid.Column="0" />
|
||||
<ScrollBar
|
||||
Name="PART_VerticalScrollBar"
|
||||
Grid.Column="1"
|
||||
Width="10"
|
||||
MinWidth="10"
|
||||
Maximum="{TemplateBinding ScrollableHeight}"
|
||||
Opacity="0.5"
|
||||
ViewportSize="{TemplateBinding ViewportHeight}"
|
||||
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
|
||||
Value="{TemplateBinding VerticalOffset}" />
|
||||
<ScrollBar
|
||||
Name="PART_HorizontalScrollBar"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Height="10"
|
||||
MinHeight="10"
|
||||
Maximum="{TemplateBinding ScrollableWidth}"
|
||||
Opacity="0.5"
|
||||
Orientation="Horizontal"
|
||||
ViewportSize="{TemplateBinding ViewportWidth}"
|
||||
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
|
||||
Value="{TemplateBinding HorizontalOffset}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<DockPanel d:DataContext="{d:DesignInstance viewmodel:HelpViewModel}">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
|
||||
<TreeView
|
||||
Width="210"
|
||||
VerticalAlignment="Stretch"
|
||||
DockPanel.Dock="Left">
|
||||
<TreeView.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type TreeViewItem}">
|
||||
<Setter Property="IsExpanded" Value="True" />
|
||||
<Setter Property="Foreground" Value="#666666" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Style.Resources>
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="White" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="White" />
|
||||
</Style.Resources>
|
||||
</Style>
|
||||
</TreeView.ItemContainerStyle>
|
||||
<TreeViewItem
|
||||
Margin="-5,0,0,10"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Foreground="Gray"
|
||||
Header="Help"
|
||||
IsHitTestVisible="False" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryKeyboardCommands"
|
||||
Margin="0,0,0,10"
|
||||
Header="Keyboard Commands"
|
||||
IsSelected="True" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryUserGuide"
|
||||
Margin="0,0,0,10"
|
||||
Header="User Guide" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryDownloadLatestRelease"
|
||||
Margin="0,0,0,10"
|
||||
Header="Download Latest Release" />
|
||||
<TreeViewItem
|
||||
x:Name="CategorySupport"
|
||||
Margin="0,0,0,10"
|
||||
Header="Support" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryAbout"
|
||||
Margin="0,0,0,10"
|
||||
Header="About" />
|
||||
</TreeView>
|
||||
</ScrollViewer>
|
||||
<ScrollViewer
|
||||
Width="780"
|
||||
Height="565"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="0,-5,0,0">
|
||||
<!-- Keyboard Commands -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryKeyboardCommands, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Keyboard Commands</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<TextBlock Margin="0,0,0,20" TextWrapping="Wrap">
|
||||
To configure a pop out panel, first click on the move and resize icon<InlineUIContainer>
|
||||
<materialDesign:PackIcon Kind="MoveResize" />
|
||||
</InlineUIContainer>
|
||||
for the panel. You can then use keyboard commands below to adjust pop out panel when the icon turns green. To end panel configuration using keyboard commands, just click the icon<InlineUIContainer>
|
||||
<materialDesign:PackIcon Kind="MoveResize" />
|
||||
</InlineUIContainer>
|
||||
again to end panel adjustment.</TextBlock>
|
||||
<TextBlock>
|
||||
<Run Foreground="LightSkyBlue">Up Arrow</Run>
|
||||
- Move panel up by 10 pixels<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Down Arrow</Run>
|
||||
- Move panel down by 10 pixels<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Left Arrow</Run>
|
||||
- Move panel left by 10 pixels<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Right Arrow</Run>
|
||||
- Move panel right by 10 pixels<LineBreak /><LineBreak />
|
||||
|
||||
<Run Foreground="LightSkyBlue">Shift + Up Arrow</Run>
|
||||
- Move panel up by 1 pixel<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Shift + Down Arrow</Run>
|
||||
- Move panel down by 1 pixel<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Shift + Left Arrow</Run>
|
||||
- Move panel left by 1 pixel<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Shift + Right Arrow</Run>
|
||||
- Move panel right by 1 pixel<LineBreak /><LineBreak />
|
||||
|
||||
<Run Foreground="LightSkyBlue">Ctrl + Up Arrow</Run>
|
||||
- Decrease height by 10 pixels<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Ctrl + Down Arrow</Run>
|
||||
- Increase height by 10 pixels<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Ctrl + Left Arrow</Run>
|
||||
- Decrease width by 10 pixels<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Ctrl + Right Arrow</Run>
|
||||
- Increase width by 10 pixels<LineBreak /><LineBreak />
|
||||
|
||||
<Run Foreground="LightSkyBlue">Shift + Ctrl + Up Arrow</Run>
|
||||
- Decrease height by 1 pixel<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Shift + Ctrl + Down Arrow</Run>
|
||||
- Increase height by 1 pixel<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Shift + Ctrl + Left Arrow</Run>
|
||||
- Decrease width by 1 pixel<LineBreak />
|
||||
<Run Foreground="LightSkyBlue">Shift + Ctrl + Right Arrow</Run>
|
||||
- Increase width by 1 pixel<LineBreak />
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- User Guide -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryUserGuide, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">User Guide</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
</WrapPanel>
|
||||
<TextBlock Width="Auto">
|
||||
<Hyperlink
|
||||
NavigateUri="Getting Started"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="Getting Started" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<TextBlock Width="Auto" Margin="0,10,0,0">
|
||||
<Hyperlink
|
||||
NavigateUri="User Guide"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="User Guide" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Download Latest -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDownloadLatestRelease, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Download Latest Release</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
</WrapPanel>
|
||||
<TextBlock Width="Auto">
|
||||
<Hyperlink
|
||||
NavigateUri="Download Latest GitHub"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="Download latest release (GitHub)" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<TextBlock Width="Auto" Margin="0,10,0,0">
|
||||
<Hyperlink
|
||||
NavigateUri="Download Latest FlightsimTo"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="Download latest release (Flightsim.to)" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Support -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategorySupport, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Support</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
</WrapPanel>
|
||||
<TextBlock Width="Auto" Margin="0,0,0,0">
|
||||
<Hyperlink
|
||||
NavigateUri="Open Data Folder"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="Open application data file folder" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<TextBlock Width="Auto" Margin="0,10,0,0">
|
||||
<Hyperlink
|
||||
NavigateUri="Download VCC Library"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="Download VC++ Library that is required by SimConnect to establish connection to MSFS" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<Button
|
||||
Width="190"
|
||||
Margin="0,10,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Command="{Binding DeleteAppCacheCommand}"
|
||||
Content="Delete Application Cache"
|
||||
IsEnabled="{Binding HasOrphanAppCache}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}"
|
||||
ToolTip="This will delete all orphan application cache files in your Windows user account 'AppData/Local/Temp/.net/MSFSPopoutPanelManager' folder" />
|
||||
<Button
|
||||
Width="280"
|
||||
Margin="0,10,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Command="{Binding RollBackCommand}"
|
||||
Content="Rollback to previous version 3.4.6.0321"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}"
|
||||
ToolTip="This will rollback the application to previous version 3.4.6.0321. All changes since installing the latest v4.0.0 update will be lost."
|
||||
Visibility="{Binding IsRollBackCommandVisible, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}" />
|
||||
</WrapPanel>
|
||||
|
||||
<!-- About -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryAbout, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">About</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
</WrapPanel>
|
||||
<TextBlock Width="Auto" Margin="0,0,0,0">
|
||||
<Hyperlink
|
||||
NavigateUri="Version Info"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<WrapPanel>
|
||||
|
||||
<WrapPanel Margin="0">
|
||||
<Label
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
Content="Version" />
|
||||
<Label
|
||||
Margin="5,0,0,0"
|
||||
Padding="0"
|
||||
Content="{Binding ApplicationVersion}" />
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<Label
|
||||
Margin="0,5,0,0"
|
||||
Padding="0"
|
||||
Content="© 2022 Stanley Kwok. All rights reserved." />
|
||||
<TextBlock Width="Auto" Margin="0,10,0,0">
|
||||
<Hyperlink
|
||||
NavigateUri="License"
|
||||
RequestNavigate="Hyperlink_RequestNavigate"
|
||||
Style="{StaticResource MaterialDesignBody2Hyperlink}">
|
||||
<TextBlock Text="Public Release License" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
|
25
MainApp/UserControl/HelpDrawer.xaml.cs
Normal file
25
MainApp/UserControl/HelpDrawer.xaml.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class HelpDrawer : UserControl
|
||||
{
|
||||
private HelpViewModel _viewModel;
|
||||
|
||||
public HelpDrawer()
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<HelpViewModel>();
|
||||
InitializeComponent();
|
||||
Loaded += (sender, e) => { DataContext = _viewModel; };
|
||||
}
|
||||
|
||||
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
_viewModel.HyperLinkCommand.Execute(e.Uri.ToString());
|
||||
}
|
||||
}
|
||||
}
|
352
MainApp/UserControl/PopOutPanelCard.xaml
Normal file
352
MainApp/UserControl/PopOutPanelCard.xaml
Normal file
|
@ -0,0 +1,352 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.PopOutPanelCard"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:profileDomain="clr-namespace:MSFSPopoutPanelManager.DomainModel.Profile;assembly=DomainModel"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
Width="860"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
<system:Double x:Key="UpDownButtonSize">22</system:Double>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
<DataTrigger
|
||||
x:Key="TriggerIsProfileLocked"
|
||||
Binding="{Binding ProfileData.ActiveProfile.IsLocked}"
|
||||
Value="True">
|
||||
<Setter Property="FrameworkElement.IsHitTestVisible" Value="False" />
|
||||
<Setter Property="FrameworkElement.Opacity" Value="0.8" />
|
||||
</DataTrigger>
|
||||
<DataTrigger
|
||||
x:Key="TriggerIsProfileUnlocked"
|
||||
Binding="{Binding ProfileData.ActiveProfile.IsLocked}"
|
||||
Value="False">
|
||||
<Setter Property="FrameworkElement.IsHitTestVisible" Value="True" />
|
||||
<Setter Property="Button.Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<Style TargetType="{x:Type Expander}">
|
||||
<Style.Triggers>
|
||||
<StaticResource ResourceKey="TriggerIsProfileLocked" />
|
||||
<StaticResource ResourceKey="TriggerIsProfileUnlocked" />
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="ToggleButton"
|
||||
BasedOn="{StaticResource MaterialDesignSwitchToggleButton}"
|
||||
TargetType="ToggleButton">
|
||||
<Setter Property="Margin" Value="4,0,4,0" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlockLabel"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Margin" Value="5,0,40,0" />
|
||||
<Setter Property="LineHeight" Value="18" />
|
||||
</Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignIconForegroundButton}" TargetType="Button" />
|
||||
<Style
|
||||
x:Key="PopOutPanelExpander"
|
||||
BasedOn="{StaticResource CustomMaterialDesignExpander}"
|
||||
TargetType="Expander">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="False">
|
||||
<Setter Property="BorderBrush" Value="Red" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="True">
|
||||
<Setter Property="BorderBrush" Value="Green" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.IsSelectedPanelSource}" Value="True">
|
||||
<Setter Property="Background" Value="SlateGray" />
|
||||
<Setter Property="Opacity" Value="0.9" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="PopOutPanelExpanderVisibility" TargetType="StackPanel">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="True">
|
||||
<Setter Property="FrameworkElement.Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="{x:Null}">
|
||||
<Setter Property="FrameworkElement.Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="False">
|
||||
<Setter Property="FrameworkElement.Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="ErrorPanelExpanderVisibility" TargetType="StackPanel">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="True">
|
||||
<Setter Property="FrameworkElement.Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="{x:Null}">
|
||||
<Setter Property="FrameworkElement.Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.IsPopOutSuccess}" Value="False">
|
||||
<Setter Property="FrameworkElement.Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="TxtBlockErrorMessage" TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.PanelType}" Value="{x:Static profileDomain:PanelType.CustomPopout}">
|
||||
<Setter Property="Text" Value="Unable to pop out this panel. Please check the source panel circle defined for this panel is at the correct location and not blocked by other window. Also please check if this panel is a duplicate with another panel. Lastly, please close all instrumentation pop outs that were opened manually." />
|
||||
<Setter Property="LineHeight" Value="18" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding DataItem.PanelType}" Value="{x:Static profileDomain:PanelType.BuiltInPopout}">
|
||||
<Setter Property="Text" Value="Unable to configure this built-in panel. Please make sure this panel has been opened and popped out by the game." />
|
||||
<Setter Property="LineHeight" Value="18" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TxtBlockDisableWhenFullScreen"
|
||||
BasedOn="{StaticResource TextBlockLabel}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.FullScreen}" Value="True">
|
||||
<Setter Property="Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<DockPanel>
|
||||
<Expander
|
||||
x:Name="RootExpander"
|
||||
Width="860"
|
||||
materialDesign:ExpanderAssist.HorizontalHeaderPadding="10,0,10,0"
|
||||
BorderThickness="1">
|
||||
<Expander.Style>
|
||||
<Style BasedOn="{StaticResource PopOutPanelExpander}" TargetType="Expander">
|
||||
<Style.Triggers>
|
||||
<StaticResource ResourceKey="TriggerIsProfileLocked" />
|
||||
<StaticResource ResourceKey="TriggerIsProfileUnlocked" />
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Expander.Style>
|
||||
<Expander.Header>
|
||||
<StackPanel Width="805" Orientation="Horizontal">
|
||||
<StackPanel
|
||||
Width="24"
|
||||
Height="52"
|
||||
Margin="0"
|
||||
Style="{StaticResource ErrorPanelExpanderVisibility}">
|
||||
<materialDesign:PopupBox
|
||||
x:Name="PopupErrorMessage"
|
||||
Margin="0,15,0,0"
|
||||
Padding="5"
|
||||
PlacementMode="RightAndAlignMiddles"
|
||||
PopupHorizontalOffset="-10"
|
||||
PopupUniformCornerRadius="10"
|
||||
PopupVerticalOffset="15"
|
||||
StaysOpen="True">
|
||||
<materialDesign:PopupBox.ToggleContent>
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Foreground="Red"
|
||||
Kind="AlertCircleOutline" />
|
||||
</materialDesign:PopupBox.ToggleContent>
|
||||
<TextBlock
|
||||
Width="450"
|
||||
Style="{StaticResource TxtBlockErrorMessage}"
|
||||
TextWrapping="Wrap" />
|
||||
</materialDesign:PopupBox>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Drag panel handle -->
|
||||
<StackPanel
|
||||
Width="24"
|
||||
Height="52"
|
||||
Margin="0"
|
||||
Style="{StaticResource PopOutPanelExpanderVisibility}">
|
||||
<materialDesign:PackIcon
|
||||
x:Name="IconDrag"
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="0,15,0,0"
|
||||
Kind="Menu"
|
||||
Opacity="0.5" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Panel name text box -->
|
||||
<TextBox
|
||||
x:Name="TxtBoxPanelName"
|
||||
Width="260"
|
||||
Margin="8,0,0,0"
|
||||
Padding="0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalContentAlignment="Left"
|
||||
materialDesign:HintAssist.FloatingScale="1"
|
||||
materialDesign:HintAssist.Hint="Panel Name"
|
||||
GotFocus="TextBox_GotFocus"
|
||||
IsEnabled="{c:Binding 'DataItem.PanelType==profileDomain:PanelType.CustomPopout'}"
|
||||
KeyDown="TextBox_KeyDown"
|
||||
SourceUpdated="Data_SourceUpdated"
|
||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Text="{Binding DataItem.PanelName, Mode=TwoWay, NotifyOnSourceUpdated=True}" />
|
||||
|
||||
<!-- Identify source panel button -->
|
||||
<StackPanel
|
||||
x:Name="StackPanelIdentifyPanelSource"
|
||||
Width="440"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{c:Binding 'DataItem.PanelType==profileDomain:PanelType.CustomPopout and DataItem.PanelSource.X == null'}">
|
||||
<Button
|
||||
x:Name="BtnIdentifySourcePanel"
|
||||
HorizontalAlignment="Center"
|
||||
Command="{Binding AddPanelSourceLocationCommand}"
|
||||
Content="Identify Source Panel Location"
|
||||
Foreground="White"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}"
|
||||
ToolTip="Identify source aircraft instrumentation panel location" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Panel configurations -->
|
||||
<StackPanel
|
||||
x:Name="StackPanelAdjustment"
|
||||
Width="440"
|
||||
Orientation="Horizontal"
|
||||
Visibility="{c:Binding 'DataItem.PanelType==profileDomain:PanelType.BuiltInPopout or DataItem.PanelType==profileDomain:PanelType.HudBarWindow or DataItem.PanelSource.X != null'}">
|
||||
<local:PanelConfigField
|
||||
Margin="20,0,0,0"
|
||||
BindingPath="Top"
|
||||
DataItem="{Binding DataItem}"
|
||||
SourceUpdated="Data_SourceUpdated" />
|
||||
<local:PanelConfigField
|
||||
Margin="20,0,0,0"
|
||||
BindingPath="Left"
|
||||
DataItem="{Binding DataItem}"
|
||||
SourceUpdated="Data_SourceUpdated" />
|
||||
<local:PanelConfigField
|
||||
Margin="20,0,0,0"
|
||||
BindingPath="Width"
|
||||
DataItem="{Binding DataItem}"
|
||||
SourceUpdated="Data_SourceUpdated" />
|
||||
<local:PanelConfigField
|
||||
Margin="20,0,0,0"
|
||||
BindingPath="Height"
|
||||
DataItem="{Binding DataItem}"
|
||||
SourceUpdated="Data_SourceUpdated" />
|
||||
|
||||
<local:MoveAndResizePanelButton Margin="12,0,0,0" />
|
||||
|
||||
<local:TouchEnabledButton
|
||||
Width="{StaticResource IconSize}"
|
||||
Margin="12,0,0,0"
|
||||
Visibility="{c:Binding 'DataItem.PanelType!=profileDomain:PanelType.HudBarWindow'}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Source panel icon -->
|
||||
<StackPanel Margin="12,0,0,0" VerticalAlignment="Center">
|
||||
<Button
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
IsHitTestVisible="{Binding ProfileData.ActiveProfile.IsEditingPanelSource}"
|
||||
PreviewMouseDown="PanelSourceIcon_PreviewMouseDown"
|
||||
PreviewMouseUp="PanelSourceIcon_PreviewMouseUp"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="Hold the left mouse button to show the panel source location"
|
||||
Visibility="{c:Binding 'DataItem.PanelType==profileDomain:PanelType.CustomPopout'}">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="Crosshairs">
|
||||
<materialDesign:PackIcon.Style>
|
||||
<Style>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProfileData.ActiveProfile.IsEditingPanelSource}" Value="True">
|
||||
<Setter Property="materialDesign:PackIcon.Foreground" Value="{Binding DataItem.PanelSource.Color}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ProfileData.ActiveProfile.IsEditingPanelSource}" Value="False">
|
||||
<Setter Property="materialDesign:PackIcon.Opacity" Value="0.3" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</materialDesign:PackIcon.Style>
|
||||
</materialDesign:PackIcon>
|
||||
</Button>
|
||||
<StackPanel Width="{StaticResource IconSize}" Visibility="{c:Binding 'DataItem.PanelType!=profileDomain:PanelType.CustomPopOut'}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Delete panel button -->
|
||||
<StackPanel Margin="12,0,0,0" VerticalAlignment="Center">
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="0"
|
||||
Command="{Binding DeletePanelCommand}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Delete panel">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="DeleteOutline" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Expander.Header>
|
||||
<StackPanel
|
||||
Margin="42,8,24,16"
|
||||
Orientation="Horizontal"
|
||||
TextBlock.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
Visibility="{c:Binding 'DataItem.PanelType!=profileDomain:PanelType.HudBarWindow'}">
|
||||
|
||||
<WrapPanel>
|
||||
<ToggleButton
|
||||
x:Name="TglBtnAlwaysOnTop"
|
||||
Margin="0,0,0,0"
|
||||
IsChecked="{Binding DataItem.AlwaysOnTop, Mode=TwoWay, NotifyOnSourceUpdated=True}"
|
||||
IsEnabled="{c:Binding !DataItem.FullScreen}"
|
||||
SourceUpdated="Data_SourceUpdated"
|
||||
Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TxtBlockDisableWhenFullScreen}" ToolTip="Set this panel to be always on top">
|
||||
Always on Top
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel>
|
||||
<ToggleButton
|
||||
x:Name="TglBtnFullScreen"
|
||||
Margin="0,0,0,0"
|
||||
IsChecked="{Binding DataItem.FullScreen, Mode=TwoWay, NotifyOnSourceUpdated=True}"
|
||||
SourceUpdated="Data_SourceUpdated"
|
||||
Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}" ToolTip="Expand this panel into full screen (emulate keystroke Alt-Enter)">Full Screen Mode</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel>
|
||||
<ToggleButton
|
||||
x:Name="TglBtnHideTitlebar"
|
||||
Margin="0,0,0,0"
|
||||
IsChecked="{Binding DataItem.HideTitlebar, Mode=TwoWay, NotifyOnSourceUpdated=True}"
|
||||
IsEnabled="{c:Binding !DataItem.FullScreen}"
|
||||
SourceUpdated="Data_SourceUpdated"
|
||||
Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TxtBlockDisableWhenFullScreen}" ToolTip="Hide the title bar for this panel">
|
||||
Hide Title Bar
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel>
|
||||
<ToggleButton
|
||||
x:Name="TglBtnAutoGameRefocus"
|
||||
Margin="0,0,0,0"
|
||||
IsChecked="{Binding DataItem.AutoGameRefocus, Mode=TwoWay, NotifyOnSourceUpdated=True}"
|
||||
SourceUpdated="Data_SourceUpdated"
|
||||
Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}" ToolTip="Automatic game refocus when clicking this panel or when using touch on this panel">Automatic Game Refocus</TextBlock>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
</DockPanel>
|
||||
</UserControl>
|
128
MainApp/UserControl/PopOutPanelCard.xaml.cs
Normal file
128
MainApp/UserControl/PopOutPanelCard.xaml.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class PopOutPanelCard : UserControl
|
||||
{
|
||||
private PopOutPanelCardViewModel _viewModel;
|
||||
public static readonly DependencyProperty DataItemProperty = DependencyProperty.Register("DataItem", typeof(PanelConfig), typeof(PopOutPanelCard));
|
||||
|
||||
public PopOutPanelCard()
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<PopOutPanelCardViewModel>();
|
||||
Loaded += (sender, e) =>
|
||||
{
|
||||
_viewModel.DataItem = DataItem;
|
||||
this.DataContext = _viewModel;
|
||||
InitializeComponent();
|
||||
};
|
||||
}
|
||||
|
||||
public PanelConfig DataItem
|
||||
{
|
||||
get { return (PanelConfig)GetValue(DataItemProperty); }
|
||||
set { SetValue(DataItemProperty, value); }
|
||||
}
|
||||
|
||||
private void TextBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
Keyboard.ClearFocus();
|
||||
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(RootExpander), RootExpander as IInputElement);
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var txtBox = (TextBox)sender;
|
||||
txtBox.Dispatcher.BeginInvoke(new Action(() => txtBox.SelectAll()));
|
||||
}
|
||||
|
||||
private void BtnUpDown_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var button = (Button)sender;
|
||||
var buttonType = button.Name.Substring(9);
|
||||
|
||||
var txtBox = this.FindName($"TxtBox{buttonType}") as TextBox;
|
||||
if (txtBox != null)
|
||||
txtBox.Dispatcher.BeginInvoke(new Action(() => txtBox.Focus()));
|
||||
}
|
||||
|
||||
private string _oldText;
|
||||
|
||||
private void TxtBox_NumbersOnly(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
int result;
|
||||
e.Handled = !(int.TryParse(e.Text, out result) || (e.Text.Trim() == "-"));
|
||||
|
||||
if (!e.Handled)
|
||||
_oldText = ((TextBox)sender).Text;
|
||||
}
|
||||
|
||||
private void TxtBox_NumbersOnlyTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
int result;
|
||||
var txtBox = (TextBox)sender;
|
||||
|
||||
if (String.IsNullOrEmpty(txtBox.Text))
|
||||
txtBox.Text = "0";
|
||||
else if (!(int.TryParse(txtBox.Text, out result) || (txtBox.Text.Trim() == "-")))
|
||||
{
|
||||
txtBox.Text = _oldText;
|
||||
}
|
||||
}
|
||||
|
||||
private void Data_SourceUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)
|
||||
{
|
||||
string? param = null;
|
||||
|
||||
if (sender is PanelConfigField)
|
||||
param = ((PanelConfigField)sender).BindingPath;
|
||||
else if (sender is ToggleButton)
|
||||
param = ((ToggleButton)sender).Name.Substring(6);
|
||||
else if (sender is TextBox)
|
||||
param = ((TextBox)sender).Name.Substring(6);
|
||||
|
||||
if (!String.IsNullOrEmpty(param))
|
||||
_viewModel.PanelAttributeUpdatedCommand.Execute(param);
|
||||
}
|
||||
|
||||
private void PanelSourceIcon_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed && _viewModel.DataItem != null && _viewModel.ProfileData.ActiveProfile.IsEditingPanelSource)
|
||||
_viewModel.DataItem.IsShownPanelSource = true;
|
||||
}
|
||||
|
||||
private void PanelSourceIcon_PreviewMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Released && _viewModel.DataItem != null && _viewModel.ProfileData.ActiveProfile.IsEditingPanelSource)
|
||||
_viewModel.DataItem.IsShownPanelSource = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomTextBox : TextBox
|
||||
{
|
||||
static CustomTextBox()
|
||||
{
|
||||
TextProperty.OverrideMetadata(typeof(CustomTextBox), new FrameworkPropertyMetadata(null, null, CoerceChanged));
|
||||
}
|
||||
|
||||
private static object CoerceChanged(DependencyObject d, object basevalue)
|
||||
{
|
||||
TextBox? txtBox = d as TextBox;
|
||||
if (txtBox != null && basevalue == null)
|
||||
{
|
||||
return txtBox.Text;
|
||||
}
|
||||
return basevalue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.EditPanelSourceButton"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
</UserControl.Resources>
|
||||
<DockPanel
|
||||
Width="35"
|
||||
Margin="0"
|
||||
VerticalAlignment="Center">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Foreground="{Binding DataItem.PanelSource.Color}"
|
||||
Kind="CrosshairsGps" />
|
||||
</DockPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,12 @@
|
|||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class EditPanelSourceButton : UserControl
|
||||
{
|
||||
public EditPanelSourceButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.MoveAndResizePanelButton"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
</UserControl.Resources>
|
||||
<ToggleButton
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=MoveResize,
|
||||
Size={StaticResource IconSize}}"
|
||||
Background="Transparent"
|
||||
Command="{Binding MoveResizePanelCommand}"
|
||||
IsChecked="{Binding DataItem.IsEditingPanel, Mode=TwoWay}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Use keyboard commands to edit panel size 
and location. Please see help for more info.">
|
||||
<ToggleButton.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignActionSecondaryToggleButton}" TargetType="ToggleButton">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.IsEditingPanel}" Value="True">
|
||||
<Setter Property="Foreground" Value="LimeGreen" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="MoveResize" />
|
||||
</ToggleButton>
|
||||
</UserControl>
|
|
@ -0,0 +1,12 @@
|
|||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class MoveAndResizePanelButton : UserControl
|
||||
{
|
||||
public MoveAndResizePanelButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
51
MainApp/UserControl/PopOutPanelCard/MoveUpDownButton.xaml
Normal file
51
MainApp/UserControl/PopOutPanelCard/MoveUpDownButton.xaml
Normal file
|
@ -0,0 +1,51 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.MoveUpDownButton"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="UpDownIconSize">14</system:Double>
|
||||
<system:Double x:Key="UpDownButtonSize">22</system:Double>
|
||||
</UserControl.Resources>
|
||||
<StackPanel
|
||||
Width="25"
|
||||
Height="52"
|
||||
Margin="0"
|
||||
VerticalAlignment="Center">
|
||||
<WrapPanel
|
||||
Height="26"
|
||||
Margin="0,4,0,-4"
|
||||
VerticalAlignment="Center">
|
||||
<Button
|
||||
x:Name="BtnMovePanelUp"
|
||||
Width="{StaticResource UpDownButtonSize}"
|
||||
Height="{StaticResource UpDownButtonSize}"
|
||||
Command="{Binding MovePanelUpCommand}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Move panel Up">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownButtonSize}"
|
||||
Height="{StaticResource UpDownButtonSize}"
|
||||
Kind="CaretUp" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<WrapPanel Height="26" VerticalAlignment="Center">
|
||||
<Button
|
||||
x:Name="BtnMovePanelDown"
|
||||
Width="{StaticResource UpDownButtonSize}"
|
||||
Height="{StaticResource UpDownButtonSize}"
|
||||
Command="{Binding MovePanelDownCommand}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Move panel down">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownButtonSize}"
|
||||
Height="{StaticResource UpDownButtonSize}"
|
||||
Kind="CaretDown" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
MainApp/UserControl/PopOutPanelCard/MoveUpDownButton.xaml.cs
Normal file
12
MainApp/UserControl/PopOutPanelCard/MoveUpDownButton.xaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class MoveUpDownButton : UserControl
|
||||
{
|
||||
public MoveUpDownButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
148
MainApp/UserControl/PopOutPanelCard/PanelConfigField.xaml
Normal file
148
MainApp/UserControl/PopOutPanelCard/PanelConfigField.xaml
Normal file
|
@ -0,0 +1,148 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.PanelConfigField"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="UpDownIconSize">14</system:Double>
|
||||
<system:Double x:Key="UpDownButtonSize">22</system:Double>
|
||||
<Style BasedOn="{StaticResource MaterialDesignFloatingHintTextBox}" TargetType="TextBox">
|
||||
<Setter Property="materialDesign:HintAssist.FloatingScale" Value="1" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<EventSetter Event="KeyDown" Handler="TextBox_KeyDown" />
|
||||
<EventSetter Event="GotFocus" Handler="TextBox_GotFocus" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="BtnPlusMinus"
|
||||
BasedOn="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Width" Value="30" />
|
||||
<Setter Property="Height" Value="30" />
|
||||
<Setter Property="Margin" Value="0,0,5,0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Command" Value="{Binding PlusMinusCommand}" />
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox
|
||||
x:Name="TxtBoxData"
|
||||
Width="50"
|
||||
Margin="0,0,0,0"
|
||||
materialDesign:HintAssist.Hint="{Binding BindingPath}"
|
||||
IsEnabled="{c:Binding '!DataItem.FullScreen'}"
|
||||
PreviewTextInput="TxtBox_NumbersOnly"
|
||||
SourceUpdated="Data_SourceUpdated"
|
||||
TextChanged="TxtBox_NumbersOnlyTextChanged" />
|
||||
<materialDesign:PopupBox
|
||||
x:Name="PopupBoxAdjustment"
|
||||
Padding="5"
|
||||
IsEnabled="{c:Binding '!DataItem.FullScreen'}"
|
||||
PlacementMode="RightAndAlignMiddles"
|
||||
PopupHorizontalOffset="-20"
|
||||
PopupUniformCornerRadius="10"
|
||||
StaysOpen="True">
|
||||
<materialDesign:PopupBox.ToggleContent>
|
||||
<Button
|
||||
Width="{StaticResource UpDownButtonSize}"
|
||||
Height="{StaticResource UpDownButtonSize}"
|
||||
Margin="-4,12,0,0"
|
||||
Click="BtnPopupBoxOpen_Click">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownIconSize}"
|
||||
Height="{StaticResource UpDownIconSize}"
|
||||
Foreground="White"
|
||||
Kind="ArrowUpDown" />
|
||||
</Button>
|
||||
</materialDesign:PopupBox.ToggleContent>
|
||||
<StackPanel
|
||||
Width="155"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label
|
||||
Width="60"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Content="1 pixel" />
|
||||
<Button
|
||||
Command="{Binding PlusMinusCommand}"
|
||||
CommandParameter="1"
|
||||
Style="{StaticResource BtnPlusMinus}"
|
||||
ToolTip="Add 1 pixel">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownIconSize}"
|
||||
Height="{StaticResource UpDownIconSize}"
|
||||
Kind="Plus" />
|
||||
</Button>
|
||||
<Button
|
||||
Command="{Binding PlusMinusCommand}"
|
||||
CommandParameter="-1"
|
||||
Style="{StaticResource BtnPlusMinus}"
|
||||
ToolTip="Subtract 1 pixel">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownIconSize}"
|
||||
Height="{StaticResource UpDownIconSize}"
|
||||
Kind="Minus" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<Separator
|
||||
Height="2"
|
||||
Margin="0"
|
||||
Padding="0" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label
|
||||
Width="60"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Content="10 pixels" />
|
||||
<Button
|
||||
Command="{Binding PlusMinusCommand}"
|
||||
CommandParameter="10"
|
||||
Style="{StaticResource BtnPlusMinus}"
|
||||
ToolTip="Add 10 pixels">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownIconSize}"
|
||||
Height="{StaticResource UpDownIconSize}"
|
||||
Kind="Plus" />
|
||||
</Button>
|
||||
<Button
|
||||
Command="{Binding PlusMinusCommand}"
|
||||
CommandParameter="-10"
|
||||
Style="{StaticResource BtnPlusMinus}"
|
||||
ToolTip="Subtract 10 pixels">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownIconSize}"
|
||||
Height="{StaticResource UpDownIconSize}"
|
||||
Kind="Minus" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<Button
|
||||
Width="{StaticResource UpDownButtonSize}"
|
||||
Height="{StaticResource UpDownButtonSize}"
|
||||
Margin="5,0,0,0"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Click="BtnPopupBoxClose_Click"
|
||||
Style="{StaticResource MaterialDesignIconForegroundButton}">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource UpDownIconSize}"
|
||||
Height="{StaticResource UpDownIconSize}"
|
||||
Kind="CloseBoxOutline" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</materialDesign:PopupBox>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
103
MainApp/UserControl/PopOutPanelCard/PanelConfigField.xaml.cs
Normal file
103
MainApp/UserControl/PopOutPanelCard/PanelConfigField.xaml.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class PanelConfigField : UserControl
|
||||
{
|
||||
private PanelConfigFieldViewModel _viewModel;
|
||||
|
||||
public static readonly DependencyProperty DataItemProperty = DependencyProperty.Register("DataItem", typeof(PanelConfig), typeof(PanelConfigField));
|
||||
public static readonly DependencyProperty BindingPathProperty = DependencyProperty.Register("BindingPath", typeof(string), typeof(PanelConfigField));
|
||||
public static readonly RoutedEvent SourceUpdatedEvent = EventManager.RegisterRoutedEvent("SourceUpdatedEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(PanelConfigField));
|
||||
|
||||
public PanelConfigField()
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<PanelConfigFieldViewModel>();
|
||||
Loaded += (sender, e) =>
|
||||
{
|
||||
_viewModel.DataItem = DataItem;
|
||||
_viewModel.BindingPath = BindingPath;
|
||||
_viewModel.SourceUpdatedEvent = SourceUpdatedEvent;
|
||||
this.DataContext = _viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
Binding binding = new Binding($"DataItem.{BindingPath}");
|
||||
binding.Mode = BindingMode.TwoWay;
|
||||
binding.NotifyOnSourceUpdated = true;
|
||||
TxtBoxData.SetBinding(TextBox.TextProperty, binding);
|
||||
};
|
||||
}
|
||||
|
||||
public PanelConfig DataItem
|
||||
{
|
||||
get { return (PanelConfig)GetValue(DataItemProperty); }
|
||||
set { SetValue(DataItemProperty, value); }
|
||||
}
|
||||
|
||||
public string BindingPath
|
||||
{
|
||||
get { return (string)GetValue(BindingPathProperty); }
|
||||
set { SetValue(BindingPathProperty, value); }
|
||||
}
|
||||
|
||||
private void TextBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
Keyboard.ClearFocus();
|
||||
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this.Parent), this.Parent as IInputElement);
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
TxtBoxData.Dispatcher.BeginInvoke(new Action(() => TxtBoxData.SelectAll()));
|
||||
}
|
||||
|
||||
private string _oldText;
|
||||
|
||||
private void TxtBox_NumbersOnly(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
int result;
|
||||
e.Handled = !(int.TryParse(e.Text, out result) || (e.Text.Trim() == "-"));
|
||||
|
||||
if (!e.Handled)
|
||||
_oldText = ((TextBox)sender).Text;
|
||||
}
|
||||
|
||||
private void TxtBox_NumbersOnlyTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
int result;
|
||||
var txtBox = (TextBox)sender;
|
||||
|
||||
if (String.IsNullOrEmpty(txtBox.Text))
|
||||
txtBox.Text = "0";
|
||||
else if (!(int.TryParse(txtBox.Text, out result) || (txtBox.Text.Trim() == "-")))
|
||||
{
|
||||
txtBox.Text = _oldText;
|
||||
}
|
||||
}
|
||||
|
||||
private void Data_SourceUpdated(object sender, DataTransferEventArgs e)
|
||||
{
|
||||
_viewModel.DataUpdatedCommand.Execute(null);
|
||||
}
|
||||
|
||||
private void BtnPopupBoxOpen_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PopupBoxAdjustment.IsPopupOpen = true;
|
||||
}
|
||||
|
||||
private void BtnPopupBoxClose_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PopupBoxAdjustment.IsPopupOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
38
MainApp/UserControl/PopOutPanelCard/TouchEnabledButton.xaml
Normal file
38
MainApp/UserControl/PopOutPanelCard/TouchEnabledButton.xaml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.TouchEnabledButton"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
</UserControl.Resources>
|
||||
<ToggleButton
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=HandBackRightOutline,
|
||||
Size={StaticResource IconSize}}"
|
||||
Background="Transparent"
|
||||
Command="{Binding TouchEnabledCommand}"
|
||||
IsChecked="{Binding DataItem.TouchEnabled, Mode=TwoWay}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Toggle panel touch capability">
|
||||
<ToggleButton.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignActionSecondaryToggleButton}" TargetType="ToggleButton">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataItem.TouchEnabled}" Value="True">
|
||||
<Setter Property="Foreground" Value="LimeGreen" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="HandBackRightOffOutline" />
|
||||
</ToggleButton>
|
||||
</UserControl>
|
|
@ -0,0 +1,12 @@
|
|||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class TouchEnabledButton : UserControl
|
||||
{
|
||||
public TouchEnabledButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
60
MainApp/UserControl/PopOutPanelList.xaml
Normal file
60
MainApp/UserControl/PopOutPanelList.xaml
Normal file
|
@ -0,0 +1,60 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.PopOutPanelList"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
|
||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<local:DummyConverter x:Key="DummyConverter" />
|
||||
</UserControl.Resources>
|
||||
<ScrollViewer
|
||||
Height="350"
|
||||
materialDesign:ScrollViewerAssist.IsAutoHideEnabled="True"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<ListView
|
||||
x:Name="PopOutPanelCardList"
|
||||
Height="Auto"
|
||||
Margin="16,0,0,0"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Left"
|
||||
dd:DragDrop.IsDragSource="{c:Binding '!ProfileData.ActiveProfile.IsLocked'}"
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
dd:DragDrop.UseDefaultEffectDataTemplate="True"
|
||||
ItemsSource="{Binding ProfileData.ActiveProfile.PanelConfigs, Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:PopOutPanelCard Height="Auto" DataItem="{Binding '', Converter={StaticResource DummyConverter}}" />
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListViewItem">
|
||||
<Border
|
||||
Name="Border"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ContentPresenter
|
||||
Margin="{TemplateBinding Padding}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
</ListView>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
28
MainApp/UserControl/PopOutPanelList.xaml.cs
Normal file
28
MainApp/UserControl/PopOutPanelList.xaml.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using System.Globalization;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class PopOutPanelList : UserControl
|
||||
{
|
||||
public PopOutPanelList()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
45
MainApp/UserControl/PopOutPanelListEmpty.xaml
Normal file
45
MainApp/UserControl/PopOutPanelListEmpty.xaml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.PopOutPanelListEmpty"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel Height="335" Margin="10,0,10,0">
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Vertical">
|
||||
<materialDesign:PackIcon
|
||||
Width="40"
|
||||
Height="40"
|
||||
Margin="0,0,45,0"
|
||||
HorizontalAlignment="Right"
|
||||
Foreground="white"
|
||||
Kind="ArrowUpBoldOutline" />
|
||||
<TextBlock
|
||||
Width="80"
|
||||
Margin="0,5,24,0"
|
||||
FontSize="16"
|
||||
Foreground="gray"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap">
|
||||
Click here to add
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,35,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="24"
|
||||
Foreground="gray">
|
||||
Add pop out panels to aircraft profile
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="0,0,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="gray">
|
||||
(by identifying instrumetation source panel location in the game)
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
MainApp/UserControl/PopOutPanelListEmpty.xaml.cs
Normal file
12
MainApp/UserControl/PopOutPanelListEmpty.xaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class PopOutPanelListEmpty : UserControl
|
||||
{
|
||||
public PopOutPanelListEmpty()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
544
MainApp/UserControl/PreferenceDrawer.xaml
Normal file
544
MainApp/UserControl/PreferenceDrawer.xaml
Normal file
|
@ -0,0 +1,544 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.PreferenceDrawer"
|
||||
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:localcontrol="clr-namespace:MSFSPopoutPanelManager.MainApp.CustomControl"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Width="1024"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<Style
|
||||
x:Key="TextBlockHeading"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Width" Value="Auto" />
|
||||
<Setter Property="Margin" Value="0,5,0,0" />
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlockSubheading"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Width" Value="Auto" />
|
||||
<Setter Property="Margin" Value="0,5,0,5" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="ToggleButton"
|
||||
BasedOn="{StaticResource MaterialDesignSwitchToggleButton}"
|
||||
TargetType="ToggleButton">
|
||||
<Setter Property="Margin" Value="4,0,4,0" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlockLabel"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Width" Value="700" />
|
||||
<Setter Property="Margin" Value="5,0,0,0" />
|
||||
<Setter Property="LineHeight" Value="20" />
|
||||
</Style>
|
||||
<Style TargetType="Line">
|
||||
<Setter Property="Margin" Value="0,5,0,5" />
|
||||
</Style>
|
||||
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<DockPanel d:DataContext="{d:DesignInstance viewmodel:ApplicationViewModel}">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
|
||||
<TreeView
|
||||
Width="210"
|
||||
VerticalAlignment="Stretch"
|
||||
DockPanel.Dock="Left">
|
||||
<TreeView.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type TreeViewItem}">
|
||||
<Setter Property="IsExpanded" Value="True" />
|
||||
<Setter Property="Foreground" Value="#666666" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Style.Resources>
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="White" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="White" />
|
||||
</Style.Resources>
|
||||
</Style>
|
||||
</TreeView.ItemContainerStyle>
|
||||
<TreeViewItem
|
||||
Margin="-5,0,0,10"
|
||||
Padding="0"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Foreground="Gray"
|
||||
Header="Preferences"
|
||||
IsHitTestVisible="False" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryGeneralSettings"
|
||||
Margin="0,0,0,10"
|
||||
Padding="0"
|
||||
Header="General Settings"
|
||||
IsSelected="True" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryAutoPopOutPanelSettings"
|
||||
Margin="0,0,0,10"
|
||||
Header="Auto Pop Out Panel Settings" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryPopOutSettings"
|
||||
Margin="0,0,0,10"
|
||||
Header="Pop Out Settings" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryGameRefocusSettings"
|
||||
Margin="0,0,0,10"
|
||||
Header="Game Refocus Settings" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryTouchSettings"
|
||||
Margin="0,0,0,10"
|
||||
Header="Touch Settings" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryTrackIRSettings"
|
||||
Margin="0,0,0,10"
|
||||
Header="Track IR Settings" />
|
||||
<TreeViewItem
|
||||
x:Name="CategoryWindowedModeSettings"
|
||||
Margin="0,0,0,10"
|
||||
Header="Windowed Mode Settings" />
|
||||
</TreeView>
|
||||
</ScrollViewer>
|
||||
|
||||
<ScrollViewer
|
||||
Width="780"
|
||||
Height="565"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="0,-4,0,0">
|
||||
<!-- General Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryGeneralSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel
|
||||
Width="Auto"
|
||||
Margin="0,0,20,20"
|
||||
Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Always on Top</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.GeneralSetting.AlwaysOnTop, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Pin the application on top of all open windows.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Auto Start</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.GeneralSetting.AutoStart, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Enable auto start application when MSFS starts. This adds a XML config entry in EXE.xml file.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Minimize to Tray</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.GeneralSetting.MinimizeToTray, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Minimize the application to system tray.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Start Minimized</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.GeneralSetting.StartMinimized, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Start the application in minimized mode in system tray.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Auto Close When Exiting MSFS</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.GeneralSetting.AutoClose, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Automatically close the application when exiting MSFS.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Check for Update</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.GeneralSetting.CheckForUpdate, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Enable checking for update of application through Github.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Auto Pop Out Panel Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryAutoPopOutPanelSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Enable Auto Pop Out Panels</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.AutoPopOutSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Automatic pop out panels when an aircraft livery is bound to a profile. The following steps will be performed.</TextBlock>
|
||||
</WrapPanel>
|
||||
<StackPanel Margin="46,0,0,0" Orientation="Vertical">
|
||||
<TextBlock Margin="0,10,0,0" Style="{StaticResource TextBlockLabel}">
|
||||
1. Detect flight start signal using SimConnect.
|
||||
</TextBlock>
|
||||
<TextBlock Margin="0,10,0,0" Style="{StaticResource TextBlockLabel}">
|
||||
2. Wait for cockpit view to appear before executing pop out panel sequence.
|
||||
</TextBlock>
|
||||
<TextBlock Margin="0,10,0,0" Style="{StaticResource TextBlockLabel}">
|
||||
3. If configured for profile on cold start, execute and detect instrumentation power on before executing pop out panel sequence.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Ready to Fly Button Delay</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<localcontrol:NumericUpDown
|
||||
Width="90"
|
||||
Height="24"
|
||||
FontSize="12"
|
||||
Increment="1"
|
||||
MaxValue="10"
|
||||
MinValue="0"
|
||||
Value="{Binding AppSettingData.ApplicationSetting.AutoPopOutSetting.ReadyToFlyDelay, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Width="640"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource TextBlockLabel}"
|
||||
TextWrapping="Wrap">
|
||||
Amount of time in seconds to delay auto pop out panels from starting after ready to fly button has been pressed automatically. Extending this delay helps resolve auto pop out failure because cockpit has not been loaded completely yet depending on the speed of your PC.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Pop Out Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryPopOutSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,0" Orientation="Vertical">
|
||||
<WrapPanel Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Enable Auto Panning</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AutoPanning.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Enable automatic panning of cockpit view when popping out panels. Auto Panning remembers the custom cockpit camera angle you used when defining the locations of pop out panel.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AutoPanning.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<StackPanel
|
||||
Width="Auto"
|
||||
Margin="40,15,0,0"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal">
|
||||
<WrapPanel>
|
||||
<Label Content="Ctrl-Alt-" FontSize="14" />
|
||||
<ComboBox
|
||||
Width="35"
|
||||
VerticalAlignment="top"
|
||||
SelectedValue="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AutoPanning.KeyBinding, Mode=TwoWay}"
|
||||
SelectedValuePath="Tag">
|
||||
<ComboBoxItem Content="0" Tag="0" />
|
||||
<ComboBoxItem Content="1" Tag="1" />
|
||||
<ComboBoxItem Content="2" Tag="2" />
|
||||
<ComboBoxItem Content="3" Tag="3" />
|
||||
<ComboBoxItem Content="4" Tag="4" />
|
||||
<ComboBoxItem Content="5" Tag="5" />
|
||||
<ComboBoxItem Content="6" Tag="6" />
|
||||
<ComboBoxItem Content="7" Tag="7" />
|
||||
<ComboBoxItem Content="8" Tag="8" />
|
||||
<ComboBoxItem Content="9" Tag="9" />
|
||||
</ComboBox>
|
||||
</WrapPanel>
|
||||
<TextBlock
|
||||
Width="620"
|
||||
Margin="10,3,0,0"
|
||||
Style="{StaticResource TextBlockLabel}">
|
||||
Configure key binding for saving and recalling of custom MSFS cockpit camera view when defining the locations of pop out panel. Requires binding keystroke to custom camera in MSFS control setting. (Default: Ctrl-Alt-0 to save and Alt-0 to load).
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,20,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Minimize Pop Out Panel Manager During Pop Out</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.MinimizeDuringPopOut, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Minimize Pop Out Panel Manager during pop out process.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,20,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Minimize Pop Out Panel Manager After Pop Out</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.MinimizeAfterPopOut, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Minimize Pop Out Panel Manager after all panels have been popped out.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,20,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Enable Active Pause</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AutoActivePause, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Enable active pause when panels are being popped out.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="0,20,20,0" Orientation="Vertical">
|
||||
<WrapPanel Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Enable Return to Predefined Camera View After Pop Out</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AfterPopOutCameraView.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Enable return to a predefined camera view after pop out.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AfterPopOutCameraView.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="46,10,0,0" Orientation="Horizontal">
|
||||
<ComboBox
|
||||
Width="160"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
SelectedValue="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AfterPopOutCameraView.CameraView, Mode=TwoWay}"
|
||||
SelectedValuePath="Tag">
|
||||
<ComboBoxItem Content="Cockpit Center View" Tag="CockpitCenterView" />
|
||||
<ComboBoxItem Content="Custom Camera View" Tag="CustomCameraView" />
|
||||
</ComboBox>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AfterPopOutCameraView.IsEnabledCustomCameraKeyBinding, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<StackPanel Margin="44,10,0,0" Orientation="Horizontal">
|
||||
<Label Content="Alt-" FontSize="14" />
|
||||
<ComboBox
|
||||
Width="35"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
SelectedValue="{Binding AppSettingData.ApplicationSetting.PopOutSetting.AfterPopOutCameraView.KeyBinding, Mode=TwoWay}"
|
||||
SelectedValuePath="Tag">
|
||||
<ComboBoxItem Content="0" Tag="0" />
|
||||
<ComboBoxItem Content="1" Tag="1" />
|
||||
<ComboBoxItem Content="2" Tag="2" />
|
||||
<ComboBoxItem Content="3" Tag="3" />
|
||||
<ComboBoxItem Content="4" Tag="4" />
|
||||
<ComboBoxItem Content="5" Tag="5" />
|
||||
<ComboBoxItem Content="6" Tag="6" />
|
||||
<ComboBoxItem Content="7" Tag="7" />
|
||||
<ComboBoxItem Content="8" Tag="8" />
|
||||
<ComboBoxItem Content="9" Tag="9" />
|
||||
</ComboBox>
|
||||
<TextBlock
|
||||
Width="620"
|
||||
Margin="10,3,0,0"
|
||||
Style="{StaticResource TextBlockLabel}">
|
||||
Configure key binding for custom camera view to load. Requires binding keystroke to custom camera in MSFS control setting. (Default: Alt-1 to load).
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel Margin="0,20,20,0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Enable Panel Reset When Profile Is Locked</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.EnablePanelResetWhenLocked, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">
|
||||
Enable panel to go back to its original location when move if the profile is locked. Disable this setting will allow panel to be moved when profile is locked
|
||||
but the profile setting will be unchanged. With this setting disable, Pop Out Panel Manager will no longer detect pop out panel's movement when profile is locked which may save some CPU cycles.
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel Margin="0,20,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Pop Out Title Bar Color Customization</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton
|
||||
x:Name="TglBtnPopOutColorCustomizationEnable"
|
||||
IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.IsEnabled, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">
|
||||
Enable setting the color of title bar for pop out panel. The color is set in Hexidemical format of RGB color (RRGGBB). For example, black is "#000000" and white is "#FFFFFF".
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel Visibility="{Binding AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<Label Margin="42,10,0,0">Color:</Label>
|
||||
<Label Margin="0,10,0,0">#</Label>
|
||||
<TextBox
|
||||
Width="50"
|
||||
Height="22"
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Top"
|
||||
materialDesign:TextFieldAssist.CharacterCounterVisibility="Hidden"
|
||||
AcceptsReturn="False"
|
||||
IsEnabled="{Binding Path=IsChecked, ElementName=TglBtnPopOutColorCustomizationEnable}"
|
||||
MaxLength="6"
|
||||
Style="{StaticResource MaterialDesignTextBox}"
|
||||
Text="{Binding AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.HexColor, Mode=TwoWay}" />
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Use Left Control + Right Control to Pop Out Panel</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.PopOutSetting.UseLeftRightControlToPopOut, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">
|
||||
If your keyboard does not have a Right-Alt key to perform left click to pop out panel, you can map Left Ctrl + Right Ctrl in MSFS control setting to pop out
|
||||
panel instead. For this feature to work, please map (CTRL + RIGHT CTRL) in Control Options => Miscellaneous => New UI Window Mode in the game
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Game Refocus Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryGameRefocusSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Refocus Game Window</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.RefocusSetting.RefocusGameWindow.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Automactically set focus back to game window after a period of inactivity when either clicking on a panel or touching a panel when touch feature is enabled. This will give you flight control back when using pop out panel to overcome the current MSFS limitation. This setting needs to be enabled for each profile and each pop out panel's automatic refocus setting to work.</TextBlock>
|
||||
</WrapPanel>
|
||||
<StackPanel
|
||||
Margin="46,10,0,0"
|
||||
Orientation="Horizontal"
|
||||
Visibility="{Binding AppSettingData.ApplicationSetting.RefocusSetting.RefocusGameWindow.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<localcontrol:NumericUpDown
|
||||
Width="90"
|
||||
Height="24"
|
||||
FontSize="12"
|
||||
Increment="0.1"
|
||||
MaxValue="10"
|
||||
MinValue="0.5"
|
||||
Places="1"
|
||||
Value="{Binding AppSettingData.ApplicationSetting.RefocusSetting.RefocusGameWindow.Delay, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Width="620"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource TextBlockLabel}">
|
||||
Amount of time in seconds to wait for touch inactivity before input focus goes back to game window.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Touch Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryTouchSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Touch Down Touch Up Delay</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<localcontrol:NumericUpDown
|
||||
Width="90"
|
||||
Height="24"
|
||||
FontSize="12"
|
||||
Increment="5"
|
||||
MaxValue="100"
|
||||
MinValue="0"
|
||||
Value="{Binding AppSettingData.ApplicationSetting.TouchSetting.TouchDownUpDelay, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Width="630"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource TextBlockLabel}">
|
||||
Amount of time in milliseconds to delay touch down and then touch up event when operating touch enabled panel. If your touch is not registering consistently, increasing this value may help.
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
FontSize="14"
|
||||
TextWrapping="Wrap">
|
||||
For panel display on direct connected touch monitor, 0 milliseconds work really well.<LineBreak /><LineBreak />
|
||||
For panel display on a tablet using software such as Spacedesk, since there is higher latency for touch signal, increasing this value 5ms at a time may compensate for this latency.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- TrackIR Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryTrackIRSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Auto Disable Track IR</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.TrackIRSetting.AutoDisableTrackIR, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">Automactically disable Track IR during panel selections and pop out process. Track IR will be re-enabled once these processes are completed.</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<!-- Windowed Mode Settings -->
|
||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryWindowedModeSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource TextBlockHeading}">Auto Resize MSFS Game Window (Used with Windowed Display Mode only)</TextBlock>
|
||||
<Line
|
||||
Stretch="Fill"
|
||||
Stroke="Gray"
|
||||
X2="1" />
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.WindowedModeSetting.AutoResizeMsfsGameWindow, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}">
|
||||
Enable automatic resize of MSFS game window when using Windowed Display Mode. When playing the game in Windowed Display Mode, this setting is used to resize game window to match original size
|
||||
and location when panel profile was initially defined. When this setting is first checked, current game window size and location will also be saved automatically.
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</UserControl>
|
16
MainApp/UserControl/PreferenceDrawer.xaml.cs
Normal file
16
MainApp/UserControl/PreferenceDrawer.xaml.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class PreferenceDrawer : UserControl
|
||||
{
|
||||
public PreferenceDrawer()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
392
MainApp/UserControl/ProfileCard.xaml
Normal file
392
MainApp/UserControl/ProfileCard.xaml
Normal file
|
@ -0,0 +1,392 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.ProfileCard"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="clr-namespace:MSFSPopoutPanelManager.DomainModel.Profile;assembly=DomainModel"
|
||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Width="900"
|
||||
Height="535"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<local:StringToHudBarTypeConverter x:Key="StringToHudBarTypeConverter" />
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
<system:Double x:Key="UpDownIconSize">14</system:Double>
|
||||
<system:Double x:Key="UpDownButtonSize">22</system:Double>
|
||||
<DataTrigger
|
||||
x:Key="TriggerIsDisabledAppInput"
|
||||
Binding="{Binding IsDisabledAppInput}"
|
||||
Value="True">
|
||||
<Setter Property="FrameworkElement.Opacity" Value="0.6" />
|
||||
<Setter Property="FrameworkElement.IsHitTestVisible" Value="False" />
|
||||
</DataTrigger>
|
||||
<Style
|
||||
x:Key="ToggleButton"
|
||||
BasedOn="{StaticResource MaterialDesignSwitchToggleButton}"
|
||||
TargetType="ToggleButton">
|
||||
<Setter Property="Margin" Value="4,0,4,0" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlockLabel"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="Margin" Value="5,0,0,0" />
|
||||
<Setter Property="LineHeight" Value="18" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TxtBlockDisableWhenLocked"
|
||||
BasedOn="{StaticResource TextBlockLabel}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProfileData.ActiveProfile.IsLocked}" Value="True">
|
||||
<Setter Property="Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="CmbBoxDisableWhenLocked"
|
||||
BasedOn="{StaticResource MaterialDesignComboBox}"
|
||||
TargetType="ComboBox">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProfileData.ActiveProfile.IsLocked}" Value="True">
|
||||
<Setter Property="Foreground" Value="DimGray" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<ObjectDataProvider
|
||||
x:Key="HudBarTypeEnum"
|
||||
MethodName="GetValues"
|
||||
ObjectType="system:Enum">
|
||||
<ObjectDataProvider.MethodParameters>
|
||||
<x:Type TypeName="domain:HudBarType" />
|
||||
</ObjectDataProvider.MethodParameters>
|
||||
</ObjectDataProvider>
|
||||
</UserControl.Resources>
|
||||
<Grid d:DataContext="{d:DesignInstance viewmodel:ProfileCardViewModel}">
|
||||
<materialDesign:Card
|
||||
x:Name="rootCard"
|
||||
Width="900"
|
||||
Height="535"
|
||||
IsHitTestVisible="{c:Binding '!IsDisabledAppInput'}"
|
||||
UniformCornerRadius="16">
|
||||
<materialDesign:Card.Style>
|
||||
<Style>
|
||||
<Style.Triggers>
|
||||
<StaticResource ResourceKey="TriggerIsDisabledAppInput" />
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</materialDesign:Card.Style>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="44" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="55" />
|
||||
</Grid.RowDefinitions>
|
||||
<materialDesign:ColorZone
|
||||
Grid.Row="0"
|
||||
materialDesign:ElevationAssist.Elevation="Dp2"
|
||||
DockPanel.Dock="Top"
|
||||
Mode="PrimaryDark">
|
||||
<StackPanel Height="44" Margin="16,6,8,0">
|
||||
<DockPanel>
|
||||
<StackPanel Width="812" Orientation="Horizontal">
|
||||
<TextBox
|
||||
x:Name="TxtBoxProfileTitle"
|
||||
Margin="8,0,0,0"
|
||||
FontSize="22"
|
||||
FontWeight="Medium"
|
||||
Foreground="White"
|
||||
KeyDown="TxtBoxProfileTitle_KeyDown"
|
||||
Text="{Binding ProfileData.ActiveProfile.Name, Mode=TwoWay}">
|
||||
<TextBox.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignTextBox}" TargetType="TextBox">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=ToggleButtonEditProfileTitle, Path=IsChecked}" Value="False">
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="IsReadOnly" Value="true" />
|
||||
<Setter Property="IsHitTestVisible" Value="false" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ElementName=ToggleButtonEditProfileTitle, Path=IsChecked}" Value="True">
|
||||
<Setter Property="IsReadOnly" Value="false" />
|
||||
<Setter Property="IsHitTestVisible" Value="true" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBox.Style>
|
||||
</TextBox>
|
||||
<ToggleButton
|
||||
x:Name="ToggleButtonEditProfileTitle"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="8,0,0,0"
|
||||
materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=PencilOff,
|
||||
Size=14}"
|
||||
Click="ToggleButtonEditProfileTitle_Click"
|
||||
IsChecked="False"
|
||||
Style="{StaticResource MaterialDesignActionDarkToggleButton}"
|
||||
ToolTip="Edit aircraft profile name">
|
||||
<materialDesign:PackIcon
|
||||
Width="14"
|
||||
Height="14"
|
||||
Kind="Pencil" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<Button
|
||||
x:Name="BtnDeleteProfile"
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Command="{Binding DeleteProfileCommand}"
|
||||
IsEnabled="True"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
ToolTip="Delete profile">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="DeleteOutline" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</materialDesign:ColorZone>
|
||||
|
||||
<DockPanel Grid.Row="1">
|
||||
<Expander Style="{DynamicResource CustomMaterialDesignExpander}">
|
||||
<Expander.Header>
|
||||
<StackPanel Width="800" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Height="20"
|
||||
Margin="0,0,10,0"
|
||||
Style="{StaticResource MaterialDesignSubtitle1TextBlock}">
|
||||
Active Aircraft:
|
||||
</TextBlock>
|
||||
<TextBlock Height="20" Text="{c:Binding 'FlightSimData.AircraftName == null ? "Aircraft binding information is currently unavailable" : FlightSimData.AircraftName'}">
|
||||
<TextBlock.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignSubtitle1TextBlock}" TargetType="{x:Type TextBlock}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProfileData.IsAircraftBoundToProfile}" Value="True">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ProfileData.IsAircraftBoundToProfile}" Value="False">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ProfileData.IsAllowedAddAircraftBinding}" Value="False">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter Property="ToolTip" Value="Aircraft is currently bound to another profile" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding FlightSimData.HasAircraftName}" Value="False">
|
||||
<Setter Property="Foreground" Value="AntiqueWhite" />
|
||||
<Setter Property="ToolTip" Value="No aircraft has been loaded by the game yet" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<ToggleButton
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="10,0,0,0"
|
||||
materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=AirplaneMinus,
|
||||
Size={StaticResource IconSize}}"
|
||||
Background="Transparent"
|
||||
Command="{Binding ToggleAircraftBindingCommand}"
|
||||
IsChecked="{Binding ProfileData.IsAircraftBoundToProfile, Mode=OneWay}"
|
||||
Style="{StaticResource MaterialDesignActionSecondaryToggleButton}"
|
||||
ToolTip="Toggle aircraft binding to profile"
|
||||
Visibility="{c:Binding 'FlightSimData.HasAircraftName and ProfileData.IsAllowedAddAircraftBinding'}">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="AirplanePlus" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</Expander.Header>
|
||||
<StackPanel Margin="22,0,0,8">
|
||||
<WrapPanel>
|
||||
<ToggleButton IsChecked="{Binding ProfileData.ActiveProfile.ProfileSetting.PowerOnRequiredForColdStart, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||
<TextBlock Style="{StaticResource TextBlockLabel}" ToolTip="During cold start, Pop Out Manager will first turn on power and avionics for the aircraft in order 
to pop out the instrumentation panels. After pop out is completed, Pop Out Manager will then 
turn off aircraft power and avionics to put the aircraft back to cold and dark state.">Power on is required to pop out panels on cold start (for G1000 based aircrafts ONLY if needed)</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel Margin="0,8,0,0">
|
||||
<ToggleButton
|
||||
IsChecked="{Binding ProfileData.ActiveProfile.ProfileSetting.IncludeInGamePanels, Mode=TwoWay, NotifyOnTargetUpdated=True}"
|
||||
IsEnabled="{c:Binding '!ProfileData.ActiveProfile.IsLocked',
|
||||
Mode=OneWay}"
|
||||
Style="{StaticResource ToggleButton}"
|
||||
TargetUpdated="IncludeInGamePanel_TargetUpdated" />
|
||||
<TextBlock Style="{StaticResource TxtBlockDisableWhenLocked}" ToolTip="Add in-game menu bar panels such as VFR Map, Checklist, ATC, etc. to profile to enable panel size and location management and touch support">Include in-game menu bar panels for pop out management and touch screen support</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
|
||||
<StackPanel Margin="0,8,0,0" Orientation="Horizontal">
|
||||
<WrapPanel>
|
||||
<ToggleButton
|
||||
IsChecked="{Binding ProfileData.ActiveProfile.ProfileSetting.HudBarConfig.IsEnabled, Mode=TwoWay, NotifyOnTargetUpdated=True}"
|
||||
IsEnabled="{c:Binding '!ProfileData.ActiveProfile.IsLocked',
|
||||
Mode=OneWay}"
|
||||
Style="{StaticResource ToggleButton}"
|
||||
TargetUpdated="AddHudBar_TargetUpdated" />
|
||||
<TextBlock Style="{StaticResource TxtBlockDisableWhenLocked}" ToolTip="Add an HUD bar to the game">Add a HUD Bar</TextBlock>
|
||||
<ComboBox
|
||||
x:Name="ComboBoxHudBarType"
|
||||
Width="130"
|
||||
Margin="10,-4,0,0"
|
||||
FontSize="14"
|
||||
IsEnabled="{c:Binding '!ProfileData.ActiveProfile.IsLocked and ProfileData.ActiveProfile.ProfileSetting.HudBarConfig.IsEnabled',
|
||||
Mode=OneWay}"
|
||||
ItemsSource="{Binding HudBarTypes}"
|
||||
SelectedValue="{Binding ProfileData.ActiveProfile.ProfileSetting.HudBarConfig.HudBarType, Mode=TwoWay, Converter={StaticResource StringToHudBarTypeConverter}}"
|
||||
Style="{StaticResource CmbBoxDisableWhenLocked}" />
|
||||
</WrapPanel>
|
||||
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
</DockPanel>
|
||||
<StackPanel Grid.Row="2">
|
||||
<Separator Margin="0,-1,0,0" />
|
||||
<WrapPanel Margin="24,8,0,4">
|
||||
<TextBlock
|
||||
Width="750"
|
||||
Style="{StaticResource MaterialDesignBody1TextBlock}"
|
||||
Text="Pop Out Panels" />
|
||||
<ToggleButton
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="0,0,0,0"
|
||||
materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=CrosshairsGps,
|
||||
Size={StaticResource IconSize}}"
|
||||
Background="Transparent"
|
||||
Command="{Binding ToggleEditPanelSourceCommand}"
|
||||
IsChecked="{Binding ProfileData.ActiveProfile.IsEditingPanelSource, Mode=TwoWay}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Toggle editing of panel source">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="Crosshairs" />
|
||||
<ToggleButton.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignActionSecondaryToggleButton}" TargetType="ToggleButton">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProfileData.ActiveProfile.IsEditingPanelSource}" Value="True">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="8,0,0,0"
|
||||
Command="{Binding AddPanelCommand}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
ToolTip="Add pop out panel">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="PlusThick" />
|
||||
</Button>
|
||||
<ToggleButton
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="8,0,0,0"
|
||||
materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=LockOutline,
|
||||
Size={StaticResource IconSize}}"
|
||||
Background="Transparent"
|
||||
Command="{Binding ToggleLockProfileCommand}"
|
||||
IsChecked="{Binding ProfileData.ActiveProfile.IsLocked, Mode=TwoWay}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
ToolTip="Lock and unlock pop out panel settings">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="UnlockedOutline" />
|
||||
<ToggleButton.Style>
|
||||
<Style BasedOn="{StaticResource MaterialDesignActionSecondaryToggleButton}" TargetType="ToggleButton">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProfileData.ActiveProfile.IsLocked}" Value="True">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
</WrapPanel>
|
||||
<local:PopOutPanelListEmpty Visibility="{c:Binding 'ProfileData.ActiveProfile.PanelConfigs.Count == 0'}" />
|
||||
<local:PopOutPanelList Visibility="{c:Binding 'ProfileData.ActiveProfile.PanelConfigs.Count > 0'}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="3">
|
||||
<Separator Margin="0,5,0,0" />
|
||||
<Grid>
|
||||
<Button
|
||||
x:Name="BtnStartPopOut"
|
||||
Width="Auto"
|
||||
Margin="250,10,250,0"
|
||||
Command="{Binding StartPopOutCommand}"
|
||||
Content="Start Pop Out"
|
||||
Foreground="White"
|
||||
IsHitTestVisible="{c:Binding '!IsDisabledAppInput'}"
|
||||
KeyboardNavigation.AcceptsReturn="False"
|
||||
Style="{StaticResource MaterialDesignOutlinedButton}"
|
||||
ToolTip="Start pop out process" />
|
||||
<StackPanel>
|
||||
<materialDesign:Snackbar
|
||||
x:Name="SnackbarMessage"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="DimGray"
|
||||
Foreground="White"
|
||||
IsActive="{Binding ProfileData.ActiveProfile.IsEditingPanelSource}">
|
||||
<materialDesign:SnackbarMessage>
|
||||
<StackPanel
|
||||
Width="800"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock Margin="160,0,0,0" VerticalAlignment="Center">Please complete editing of source panel locations by clicking</TextBlock>
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Margin="5,0,5,0"
|
||||
Foreground="LightGreen"
|
||||
Kind="CrosshairsGps" />
|
||||
<TextBlock VerticalAlignment="Center">above to enable Start Pop Out</TextBlock>
|
||||
</StackPanel>
|
||||
</materialDesign:SnackbarMessage>
|
||||
</materialDesign:Snackbar>
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<materialDesign:Snackbar
|
||||
x:Name="SnackbarMessage2"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="DimGray"
|
||||
Foreground="White"
|
||||
IsActive="{Binding ProfileData.ActiveProfile.HasUnidentifiedPanelSource}">
|
||||
<materialDesign:SnackbarMessage>
|
||||
<StackPanel
|
||||
Width="800"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock Margin="250,0,0,0" VerticalAlignment="Center">Please identify all source panel locations to enable Start Pop Out</TextBlock>
|
||||
</StackPanel>
|
||||
</materialDesign:SnackbarMessage>
|
||||
</materialDesign:Snackbar>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</materialDesign:Card>
|
||||
</Grid>
|
||||
</UserControl>
|
72
MainApp/UserControl/ProfileCard.xaml.cs
Normal file
72
MainApp/UserControl/ProfileCard.xaml.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MSFSPopoutPanelManager.DomainModel.Profile;
|
||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class ProfileCard : UserControl
|
||||
{
|
||||
private ProfileCardViewModel? _viewModel;
|
||||
|
||||
public ProfileCard()
|
||||
{
|
||||
_viewModel = App.AppHost.Services.GetRequiredService<ProfileCardViewModel>();
|
||||
InitializeComponent();
|
||||
Loaded += (sender, e) => { DataContext = _viewModel; };
|
||||
}
|
||||
|
||||
private void ToggleButtonEditProfileTitle_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ToggleButton? toggleButton = sender as ToggleButton;
|
||||
|
||||
if (toggleButton != null && toggleButton.IsChecked != null && (bool)toggleButton.IsChecked)
|
||||
{
|
||||
TxtBoxProfileTitle.Dispatcher.BeginInvoke(new Action(() => TxtBoxProfileTitle.Focus()));
|
||||
TxtBoxProfileTitle.Dispatcher.BeginInvoke(new Action(() => TxtBoxProfileTitle.SelectAll()));
|
||||
}
|
||||
}
|
||||
|
||||
private void TxtBoxProfileTitle_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
ToggleButtonEditProfileTitle.IsChecked = false;
|
||||
Keyboard.ClearFocus();
|
||||
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(rootCard), rootCard as IInputElement);
|
||||
}
|
||||
}
|
||||
|
||||
private void IncludeInGamePanel_TargetUpdated(object sender, DataTransferEventArgs e)
|
||||
{
|
||||
_viewModel.IncludeInGamePanelUpdatedCommand.Execute(null);
|
||||
}
|
||||
|
||||
private void AddHudBar_TargetUpdated(object sender, DataTransferEventArgs e)
|
||||
{
|
||||
_viewModel.AddHudBarUpdatedCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[ValueConversion(typeof(DateTime), typeof(String))]
|
||||
public class StringToHudBarTypeConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value.ToString().Replace("_", " ");
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
string data = value.ToString();
|
||||
return Enum.Parse<HudBarType>(data.Replace(" ", "_"));
|
||||
}
|
||||
}
|
||||
}
|
44
MainApp/UserControl/ProfileCardEmpty.xaml
Normal file
44
MainApp/UserControl/ProfileCardEmpty.xaml
Normal file
|
@ -0,0 +1,44 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.ProfileCardEmpty"
|
||||
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Width="900"
|
||||
Height="535"
|
||||
mc:Ignorable="d">
|
||||
<Grid d:DataContext="{d:DesignInstance viewmodel:ProfileCardViewModel}">
|
||||
<materialDesign:Card
|
||||
Width="900"
|
||||
Height="535"
|
||||
UniformCornerRadius="16">
|
||||
<StackPanel>
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,16,5,0"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="gray">
|
||||
Click here to start
|
||||
</TextBlock>
|
||||
<materialDesign:PackIcon
|
||||
Width="40"
|
||||
Height="40"
|
||||
Margin="0,5,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Foreground="white"
|
||||
Kind="ArrowRightBoldOutline" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,210,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="24"
|
||||
Foreground="gray">
|
||||
Get started by adding a new aircraft profile
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
</Grid>
|
||||
</UserControl>
|
12
MainApp/UserControl/ProfileCardEmpty.xaml.cs
Normal file
12
MainApp/UserControl/ProfileCardEmpty.xaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.Windows.Controls;
|
||||
|
||||
namespace MSFSPopoutPanelManager.MainApp
|
||||
{
|
||||
public partial class ProfileCardEmpty : UserControl
|
||||
{
|
||||
public ProfileCardEmpty()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
148
MainApp/UserControl/ProfileCardList.xaml
Normal file
148
MainApp/UserControl/ProfileCardList.xaml
Normal file
|
@ -0,0 +1,148 @@
|
|||
<UserControl
|
||||
x:Class="MSFSPopoutPanelManager.MainApp.ProfileCardList"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dotNetKitControls="clr-namespace:DotNetKit.Windows.Controls;assembly=DotNetKit.Wpf.AutoCompleteComboBox"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||
Width="1024"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<system:Double x:Key="IconSize">22</system:Double>
|
||||
<system:Double x:Key="ButtonSize">28</system:Double>
|
||||
</UserControl.Resources>
|
||||
<StackPanel d:DataContext="{d:DesignInstance viewmodel:ProfileCardListViewModel}" Orientation="Horizontal">
|
||||
<DockPanel Width="62">
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="6,0,0,0"
|
||||
Command="{Binding PreviousProfileCommand}"
|
||||
IsEnabled="{c:Binding 'ProfileData.Profiles.Count > 1'}"
|
||||
Style="{StaticResource MaterialDesignFloatingActionDarkButton}"
|
||||
ToolTip="Previous aircraft profile">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="ChevronLeft" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
<DockPanel Width="900">
|
||||
<materialDesign:Transitioner x:Name="TransitionProfile" SelectedIndex="{Binding ProfileTransitionIndex}">
|
||||
<materialDesign:TransitionerSlide x:Name="Slide1" ClipToBounds="True">
|
||||
<materialDesign:TransitionerSlide.ForwardWipe>
|
||||
<materialDesign:SlideWipe Duration="0:0:0.8" />
|
||||
</materialDesign:TransitionerSlide.ForwardWipe>
|
||||
<materialDesign:TransitionerSlide.BackwardWipe>
|
||||
<materialDesign:SlideWipe Duration="0:0:0.8" />
|
||||
</materialDesign:TransitionerSlide.BackwardWipe>
|
||||
<materialDesign:TransitionerSlide.OpeningEffects>
|
||||
<materialDesign:TransitionEffect Kind="SlideInFromRight" Duration="0:0:0.8" />
|
||||
</materialDesign:TransitionerSlide.OpeningEffects>
|
||||
<StackPanel>
|
||||
<local:ProfileCardEmpty Visibility="{c:Binding 'ProfileData.Profiles.Count == 0'}" />
|
||||
<local:ProfileCard Visibility="{c:Binding 'ProfileData.Profiles.Count > 0'}" />
|
||||
</StackPanel>
|
||||
</materialDesign:TransitionerSlide>
|
||||
<materialDesign:TransitionerSlide x:Name="Slide2" ClipToBounds="True">
|
||||
<materialDesign:TransitionerSlide.ForwardWipe>
|
||||
<materialDesign:SlideWipe Duration="0:0:0.8" />
|
||||
</materialDesign:TransitionerSlide.ForwardWipe>
|
||||
<materialDesign:TransitionerSlide.BackwardWipe>
|
||||
<materialDesign:SlideWipe Duration="0:0:0.8" />
|
||||
</materialDesign:TransitionerSlide.BackwardWipe>
|
||||
<materialDesign:TransitionerSlide.OpeningEffects>
|
||||
<materialDesign:TransitionEffect Kind="SlideInFromRight" Duration="0:0:0.8" />
|
||||
</materialDesign:TransitionerSlide.OpeningEffects>
|
||||
<StackPanel>
|
||||
<local:ProfileCardEmpty Visibility="{c:Binding 'ProfileData.Profiles.Count == 0'}" />
|
||||
<local:ProfileCard Visibility="{c:Binding 'ProfileData.Profiles.Count > 0'}" />
|
||||
</StackPanel>
|
||||
</materialDesign:TransitionerSlide>
|
||||
</materialDesign:Transitioner>
|
||||
</DockPanel>
|
||||
<DockPanel Width="62" Margin="-5,10,0,0">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Command="{Binding AddProfileCommand}"
|
||||
Style="{StaticResource MaterialDesignFloatingActionDarkButton}"
|
||||
ToolTip="Add a new aircraft profile">
|
||||
<materialDesign:PackIcon
|
||||
Width="18"
|
||||
Height="18"
|
||||
Kind="FilePlusOutline" />
|
||||
</Button>
|
||||
<materialDesign:PopupBox
|
||||
x:Name="PopupBoxFinder"
|
||||
Margin="16,16,0,0"
|
||||
materialDesign:ElevationAssist.Elevation="Dp0"
|
||||
IsEnabled="{c:Binding 'ProfileData.Profiles.Count > 1'}"
|
||||
PlacementMode="LeftAndAlignMiddles"
|
||||
PopupHorizontalOffset="-10"
|
||||
PopupUniformCornerRadius="4"
|
||||
Style="{StaticResource MaterialDesignPopupBox}">
|
||||
<materialDesign:PopupBox.ToggleContent>
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
Click="BtnPopupBoxFinder_Click"
|
||||
Style="{StaticResource MaterialDesignFloatingActionDarkButton}"
|
||||
ToolTip="Find an aircraft profile">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Foreground="White"
|
||||
Kind="Magnify" />
|
||||
</Button>
|
||||
</materialDesign:PopupBox.ToggleContent>
|
||||
<dotNetKitControls:AutoCompleteComboBox
|
||||
x:Name="ComboBoxSearchProfile"
|
||||
Width="250"
|
||||
Margin="5,0,5,0"
|
||||
Padding="5,0,5,0"
|
||||
materialDesign:ComboBoxAssist.MaxLength="20"
|
||||
materialDesign:HintAssist.Hint="Search Profile"
|
||||
materialDesign:HintAssist.HintOpacity="0.3"
|
||||
DisplayMemberPath="Name"
|
||||
Foreground="White"
|
||||
ItemsSource="{Binding ProfileData.Profiles}"
|
||||
MaxDropDownHeight="400"
|
||||
SelectedItem="{Binding SearchProfileSelectedItem}"
|
||||
SelectedValuePath="Id"
|
||||
Style="{StaticResource MaterialDesignComboBox}"
|
||||
TextSearch.TextPath="Name">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<i:InvokeCommandAction Command="{Binding SearchProfileSelectedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</dotNetKitControls:AutoCompleteComboBox>
|
||||
</materialDesign:PopupBox>
|
||||
<Button
|
||||
Width="{StaticResource ButtonSize}"
|
||||
Height="{StaticResource ButtonSize}"
|
||||
Margin="0,170,0,0"
|
||||
Command="{Binding NextProfileCommand}"
|
||||
DockPanel.Dock="Top"
|
||||
IsEnabled="{c:Binding 'ProfileData.Profiles.Count > 1'}"
|
||||
Style="{StaticResource MaterialDesignFloatingActionDarkButton}"
|
||||
ToolTip="Next aircraft profile">
|
||||
<materialDesign:PackIcon
|
||||
Width="{StaticResource IconSize}"
|
||||
Height="{StaticResource IconSize}"
|
||||
Kind="ChevronRight" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue