734 lines
24 KiB
C#
734 lines
24 KiB
C#
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Shapes;
|
|
using WpfMaiTouchEmulator.Managers;
|
|
|
|
namespace WpfMaiTouchEmulator;
|
|
/// <summary>
|
|
/// Interaction logic for TouchPanel.xaml
|
|
/// </summary>
|
|
public partial class TouchPanel : Window
|
|
{
|
|
internal Action<TouchValue>? onTouch;
|
|
internal Action<TouchValue>? onRelease;
|
|
internal Action? onInitialReposition;
|
|
|
|
private readonly Dictionary<int, (Polygon polygon, Point lastPoint)> activeTouches = new();
|
|
private readonly TouchPanelPositionManager _positionManager;
|
|
private List<Polygon> buttons = [];
|
|
private bool isDebugEnabled = Properties.Settings.Default.IsDebugEnabled;
|
|
private bool isRingButtonEmulationEnabled = Properties.Settings.Default.IsRingButtonEmulationEnabled;
|
|
private bool hasRepositioned = false;
|
|
|
|
private enum ResizeDirection
|
|
{
|
|
BottomRight = 8,
|
|
}
|
|
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
private static extern bool ReleaseCapture();
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
private static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct RECT
|
|
{
|
|
public int Left;
|
|
public int Top;
|
|
public int Right;
|
|
public int Bottom;
|
|
}
|
|
|
|
public enum SizingEdge
|
|
{
|
|
Left = 1,
|
|
Right = 2,
|
|
Top = 3,
|
|
TopLeft = 4,
|
|
TopRight = 5,
|
|
Bottom = 6,
|
|
BottomLeft = 7,
|
|
BottomRight = 8
|
|
}
|
|
|
|
private const double FixedAspectRatio = 720.0 / 1280.0; // width / height
|
|
private const int MinWidth = 180;
|
|
private const int MinHeight = 320;
|
|
|
|
public TouchPanel()
|
|
{
|
|
InitializeComponent();
|
|
Topmost = true;
|
|
_positionManager = new TouchPanelPositionManager();
|
|
Loaded += Window_Loaded;
|
|
Touch.FrameReported += OnTouchFrameReported;
|
|
}
|
|
|
|
|
|
protected override void OnSourceInitialized(EventArgs e)
|
|
{
|
|
base.OnSourceInitialized(e);
|
|
var source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
|
source.AddHook(WndProc);
|
|
}
|
|
|
|
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
|
{
|
|
const int WM_SIZING = 0x0214;
|
|
if (msg == WM_SIZING)
|
|
{
|
|
var rect = Marshal.PtrToStructure<RECT>(lParam);
|
|
var edge = (SizingEdge)wParam.ToInt32();
|
|
EnforceAspectRatio(ref rect, edge);
|
|
Marshal.StructureToPtr(rect, lParam, true);
|
|
handled = true;
|
|
}
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
private void EnforceAspectRatio(ref RECT rect, SizingEdge edge)
|
|
{
|
|
var currentWidth = rect.Right - rect.Left;
|
|
var currentHeight = rect.Bottom - rect.Top;
|
|
int newWidth, newHeight;
|
|
|
|
if (edge == SizingEdge.BottomRight)
|
|
{
|
|
newWidth = (int)(currentHeight * FixedAspectRatio);
|
|
newHeight = currentHeight;
|
|
}
|
|
else
|
|
{
|
|
newHeight = (int)(currentWidth / FixedAspectRatio);
|
|
newWidth = currentWidth;
|
|
}
|
|
|
|
// Enforce minimum size while keeping the aspect ratio.
|
|
if (newWidth < MinWidth)
|
|
{
|
|
newWidth = MinWidth;
|
|
newHeight = (int)(newWidth / FixedAspectRatio);
|
|
}
|
|
if (newHeight < MinHeight)
|
|
{
|
|
newHeight = MinHeight;
|
|
newWidth = (int)(newHeight * FixedAspectRatio);
|
|
}
|
|
|
|
rect.Right = rect.Left + newWidth;
|
|
rect.Bottom = rect.Top + newHeight;
|
|
}
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
buttons = VisualTreeHelperExtensions.FindVisualChildren<Polygon>(this);
|
|
DeselectAllItems();
|
|
}
|
|
|
|
public void PositionTouchPanel()
|
|
{
|
|
var position = _positionManager.GetSinMaiWindowPosition();
|
|
if (position != null &&
|
|
(Top != position.Value.Top || Left != position.Value.Left || Width != position.Value.Width || Height != position.Value.Height)
|
|
)
|
|
{
|
|
Logger.Info("Touch panel not over sinmai window, repositioning");
|
|
Top = position.Value.Top;
|
|
Left = position.Value.Left;
|
|
Width = position.Value.Width;
|
|
Height = position.Value.Height;
|
|
|
|
if (!hasRepositioned)
|
|
{
|
|
hasRepositioned = true;
|
|
onInitialReposition?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DragBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
// This event is for the draggable bar, it calls DragMove to move the window
|
|
DragMove();
|
|
}
|
|
|
|
private void ResizeGrip_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (e.LeftButton == MouseButtonState.Pressed)
|
|
{
|
|
ResizeWindow(SizingEdge.BottomRight);
|
|
}
|
|
}
|
|
|
|
private void ResizeWindow(SizingEdge edge)
|
|
{
|
|
ReleaseCapture();
|
|
SendMessage(new WindowInteropHelper(this).Handle, 0x112, (IntPtr)(0xF000 + (int)edge), IntPtr.Zero);
|
|
}
|
|
|
|
private void OnTouchFrameReported(object sender, TouchFrameEventArgs e)
|
|
{
|
|
var currentTouchPoints = e.GetTouchPoints(this);
|
|
var currentIds = new HashSet<int>();
|
|
|
|
foreach (var touch in currentTouchPoints)
|
|
{
|
|
var id = touch.TouchDevice.Id;
|
|
|
|
// If the touch is released, process it as a TouchUp.
|
|
if (touch.Action == TouchAction.Up)
|
|
{
|
|
if (activeTouches.TryGetValue(id, out var touchInfo2))
|
|
{
|
|
if (activeTouches.Values.Count(v => v.polygon == touchInfo2.polygon) == 1)
|
|
{
|
|
HighlightElement(touchInfo2.polygon, false);
|
|
onRelease?.Invoke((TouchValue)touchInfo2.polygon.Tag);
|
|
if (isRingButtonEmulationEnabled)
|
|
{
|
|
RingButtonEmulator.ReleaseButton((TouchValue)touchInfo2.polygon.Tag);
|
|
}
|
|
}
|
|
activeTouches.Remove(id);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
currentIds.Add(id);
|
|
|
|
// New touch (TouchDown)
|
|
if (!activeTouches.TryGetValue(id, out var touchInfo))
|
|
{
|
|
if (VisualTreeHelper.HitTest(this, touch.Position)?.VisualHit is Polygon polygon)
|
|
{
|
|
HighlightElement(polygon, true);
|
|
activeTouches[id] = (polygon, touch.Position);
|
|
onTouch?.Invoke((TouchValue)polygon.Tag);
|
|
if (isRingButtonEmulationEnabled && RingButtonEmulator.HasRingButtonMapping((TouchValue)polygon.Tag))
|
|
{
|
|
RingButtonEmulator.PressButton((TouchValue)polygon.Tag);
|
|
}
|
|
}
|
|
}
|
|
// Existing touch (TouchMove)
|
|
else
|
|
{
|
|
var previousPosition = touchInfo.lastPoint;
|
|
var currentPosition = touch.Position;
|
|
var sampleCount = 10;
|
|
var changed = false;
|
|
|
|
for (var i = 1; i <= sampleCount; i++)
|
|
{
|
|
var t = (double)i / sampleCount;
|
|
var samplePoint = new Point(
|
|
previousPosition.X + (currentPosition.X - previousPosition.X) * t,
|
|
previousPosition.Y + (currentPosition.Y - previousPosition.Y) * t);
|
|
if (VisualTreeHelper.HitTest(this, samplePoint)?.VisualHit is Polygon polygon && polygon != touchInfo.polygon)
|
|
{
|
|
if (activeTouches.Values.Count(v => v.polygon == touchInfo.polygon) == 1)
|
|
{
|
|
HighlightElement(touchInfo.polygon, false);
|
|
onRelease?.Invoke((TouchValue)touchInfo.polygon.Tag);
|
|
}
|
|
HighlightElement(polygon, true);
|
|
onTouch?.Invoke((TouchValue)polygon.Tag);
|
|
activeTouches[id] = (polygon, samplePoint);
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!changed)
|
|
{
|
|
activeTouches[id] = (touchInfo.polygon, currentPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process any touches that might not be reported this frame.
|
|
var endedTouches = activeTouches.Keys.Except(currentIds).ToList();
|
|
foreach (var id in endedTouches)
|
|
{
|
|
var touchInfo = activeTouches[id];
|
|
if (activeTouches.Values.Count(v => v.polygon == touchInfo.polygon) == 1)
|
|
{
|
|
HighlightElement(touchInfo.polygon, false);
|
|
onRelease?.Invoke((TouchValue)touchInfo.polygon.Tag);
|
|
if (isRingButtonEmulationEnabled)
|
|
{
|
|
RingButtonEmulator.ReleaseButton((TouchValue)touchInfo.polygon.Tag);
|
|
}
|
|
}
|
|
activeTouches.Remove(id);
|
|
}
|
|
}
|
|
|
|
private void DeselectAllItems()
|
|
{
|
|
// Logic to deselect all items or the last touched item
|
|
foreach (var element in activeTouches.Values)
|
|
{
|
|
HighlightElement(element.polygon, false);
|
|
onRelease?.Invoke((TouchValue)element.polygon.Tag);
|
|
}
|
|
activeTouches.Clear();
|
|
RingButtonEmulator.ReleaseAllButtons();
|
|
}
|
|
|
|
public void SetDebugMode(bool enabled)
|
|
{
|
|
isDebugEnabled = enabled;
|
|
buttons.ForEach(button =>
|
|
{
|
|
button.Opacity = enabled ? 0.3 : 0;
|
|
});
|
|
}
|
|
|
|
public void SetLargeButtonMode(bool enabled)
|
|
{
|
|
TouchValue[] ringButtonsValues = {
|
|
TouchValue.A1,
|
|
TouchValue.A2,
|
|
TouchValue.A3,
|
|
TouchValue.A4,
|
|
TouchValue.A5,
|
|
TouchValue.A6,
|
|
TouchValue.A7,
|
|
TouchValue.A8,
|
|
TouchValue.D1,
|
|
TouchValue.D2,
|
|
TouchValue.D3,
|
|
TouchValue.D4,
|
|
TouchValue.D5,
|
|
TouchValue.D6,
|
|
TouchValue.D7,
|
|
TouchValue.D8,
|
|
};
|
|
|
|
var a1 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A1);
|
|
var a2 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A2);
|
|
var a3 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A3);
|
|
var a4 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A4);
|
|
var a5 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A5);
|
|
var a6 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A6);
|
|
var a7 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A7);
|
|
var a8 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A8);
|
|
var d1 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D1);
|
|
var d2 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D2);
|
|
var d3 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D3);
|
|
var d4 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D4);
|
|
var d5 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D5);
|
|
var d6 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D6);
|
|
var d7 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D7);
|
|
var d8 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D8);
|
|
|
|
if (enabled)
|
|
{
|
|
d1.Points = new PointCollection
|
|
{
|
|
new Point(-5, -50),
|
|
new Point(205, -50),
|
|
new Point(165, 253),
|
|
new Point(100, 188),
|
|
new Point(35, 253),
|
|
};
|
|
|
|
a1.Points = new PointCollection
|
|
{
|
|
new Point(495, -50),
|
|
new Point(208, 338),
|
|
new Point(145, 338),
|
|
new Point(49, 297),
|
|
new Point(0, 249),
|
|
new Point(42, -55),
|
|
};
|
|
d2.Points = new PointCollection
|
|
{
|
|
new Point(290, -182),
|
|
new Point(500, -180),
|
|
new Point(500, -5),
|
|
new Point(96, 297),
|
|
new Point(96, 205),
|
|
new Point(0, 205),
|
|
};
|
|
a2.Points = new PointCollection
|
|
{
|
|
new Point(405, 317),
|
|
new Point(91, 362),
|
|
new Point(42, 314),
|
|
new Point(0, 219),
|
|
new Point(0, 150),
|
|
new Point(405, -150),
|
|
};
|
|
d3.Points = new PointCollection
|
|
{
|
|
new Point(315, -10),
|
|
new Point(315, 208),
|
|
new Point(0, 165),
|
|
new Point(65, 100),
|
|
new Point(0, 35),
|
|
};
|
|
a3.Points = new PointCollection
|
|
{
|
|
new Point(406, 520),
|
|
new Point(0, 213),
|
|
new Point(0, 144),
|
|
new Point(41, 48),
|
|
new Point(89, 0),
|
|
new Point(406, 43),
|
|
};
|
|
d4.Points = new PointCollection
|
|
{
|
|
new Point(500, 309),
|
|
new Point(500, 491),
|
|
new Point(305, 491),
|
|
new Point(0, 92),
|
|
new Point(92, 92),
|
|
new Point(92, 0),
|
|
};
|
|
a4.Points = new PointCollection
|
|
{
|
|
new Point(45, 400),
|
|
new Point(0, 83),
|
|
new Point(48, 35),
|
|
new Point(144, 0),
|
|
new Point(212, 0),
|
|
new Point(515, 400),
|
|
};
|
|
d5.Points = new PointCollection
|
|
{
|
|
new Point(208, 317),
|
|
new Point(-10, 317),
|
|
new Point(34, 0),
|
|
new Point(99, 65),
|
|
new Point(164, 0),
|
|
};
|
|
|
|
a5.Points = new PointCollection
|
|
{
|
|
new Point(317, 400),
|
|
new Point(363, 83),
|
|
new Point(316, 35),
|
|
new Point(220, 0),
|
|
new Point(152, 0),
|
|
new Point(-150, 400),
|
|
};
|
|
d6.Points = new PointCollection
|
|
{
|
|
new Point(-10, 492),
|
|
new Point(-200, 492),
|
|
new Point(-200, 295),
|
|
new Point(199, 0),
|
|
new Point(199, 92),
|
|
new Point(291, 92),
|
|
};
|
|
a6.Points = new PointCollection
|
|
{
|
|
new Point(-67, 505),
|
|
new Point(333, 214),
|
|
new Point(333, 144),
|
|
new Point(296, 48),
|
|
new Point(248, 0),
|
|
new Point(-67, 45),
|
|
};
|
|
|
|
d7.Points = new PointCollection
|
|
{
|
|
new Point(-60, 207),
|
|
new Point(-60, -7),
|
|
new Point(253, 34),
|
|
new Point(188, 99),
|
|
new Point(253, 164),
|
|
};
|
|
|
|
a7.Points = new PointCollection
|
|
{
|
|
new Point(-65, 320),
|
|
new Point(248, 362),
|
|
new Point(297, 314),
|
|
new Point(333, 219),
|
|
new Point(333, 151),
|
|
new Point(-65, -150),
|
|
};
|
|
d8.Points = new PointCollection
|
|
{
|
|
new Point(-195, -10),
|
|
new Point(-195, -195),
|
|
new Point(-5, -195),
|
|
new Point(298, 199),
|
|
new Point(200, 199),
|
|
new Point(200, 291),
|
|
};
|
|
|
|
a8.Points = new PointCollection
|
|
{
|
|
new Point(-148, -55),
|
|
new Point(153, 338),
|
|
new Point(215, 338),
|
|
new Point(311, 297),
|
|
new Point(359, 249),
|
|
new Point(318, -55),
|
|
};
|
|
}
|
|
else
|
|
{
|
|
d1.Points = new PointCollection
|
|
{
|
|
new Point(0, 5),
|
|
new Point(50, 2),
|
|
new Point(100, 0),
|
|
new Point(150, 2),
|
|
new Point(200, 5),
|
|
new Point(165, 253),
|
|
new Point(100, 188),
|
|
new Point(35, 253),
|
|
};
|
|
|
|
a1.Points = new PointCollection
|
|
{
|
|
new Point(150, 28),
|
|
new Point(245, 65),
|
|
new Point(360, 133),
|
|
new Point(208, 338),
|
|
new Point(145, 338),
|
|
new Point(49, 297),
|
|
new Point(0, 249),
|
|
new Point(35, 0),
|
|
};
|
|
|
|
d2.Points = new PointCollection
|
|
{
|
|
new Point(153, 0),
|
|
new Point(187, 32),
|
|
new Point(225, 67),
|
|
new Point(259, 104),
|
|
new Point(295, 147),
|
|
new Point(96, 297),
|
|
new Point(96, 205),
|
|
new Point(0, 205),
|
|
};
|
|
|
|
a2.Points = new PointCollection
|
|
{
|
|
new Point(261, 101),
|
|
new Point(303, 195),
|
|
new Point(339, 327),
|
|
new Point(91, 362),
|
|
new Point(42, 314),
|
|
new Point(0, 219),
|
|
new Point(0, 150),
|
|
new Point(202, 0),
|
|
};
|
|
|
|
d3.Points = new PointCollection
|
|
{
|
|
new Point(248, 0),
|
|
new Point(251, 48),
|
|
new Point(253, 100),
|
|
new Point(251, 150),
|
|
new Point(247, 199),
|
|
new Point(0, 165),
|
|
new Point(65, 100),
|
|
new Point(0, 35),
|
|
};
|
|
|
|
a3.Points = new PointCollection
|
|
{
|
|
new Point(305, 150),
|
|
new Point(269, 246),
|
|
new Point(201, 364),
|
|
new Point(0, 213),
|
|
new Point(0, 144),
|
|
new Point(41, 48),
|
|
new Point(89, 0),
|
|
new Point(337, 34),
|
|
};
|
|
|
|
d4.Points = new PointCollection
|
|
{
|
|
new Point(292, 151),
|
|
new Point(260, 187),
|
|
new Point(225, 225),
|
|
new Point(188, 259),
|
|
new Point(151, 291),
|
|
new Point(0, 92),
|
|
new Point(92, 92),
|
|
new Point(92, 0),
|
|
};
|
|
|
|
a4.Points = new PointCollection
|
|
{
|
|
new Point(260, 259),
|
|
new Point(167, 301),
|
|
new Point(37, 335),
|
|
new Point(0, 83),
|
|
new Point(48, 35),
|
|
new Point(144, 0),
|
|
new Point(212, 0),
|
|
new Point(364, 200),
|
|
};
|
|
|
|
d5.Points = new PointCollection
|
|
{
|
|
new Point(199, 252),
|
|
new Point(151, 255),
|
|
new Point(99, 257),
|
|
new Point(49, 255),
|
|
new Point(0, 252),
|
|
new Point(34, 0),
|
|
new Point(99, 65),
|
|
new Point(164, 0),
|
|
};
|
|
|
|
a5.Points = new PointCollection
|
|
{
|
|
new Point(104, 259),
|
|
new Point(197, 301),
|
|
new Point(327, 335),
|
|
new Point(363, 83),
|
|
new Point(316, 35),
|
|
new Point(220, 0),
|
|
new Point(152, 0),
|
|
new Point(0, 201),
|
|
};
|
|
|
|
d6.Points = new PointCollection
|
|
{
|
|
new Point(140, 292),
|
|
new Point(104, 260),
|
|
new Point(66, 225),
|
|
new Point(32, 188),
|
|
new Point(0, 151),
|
|
new Point(199, 0),
|
|
new Point(199, 92),
|
|
new Point(291, 92),
|
|
};
|
|
|
|
a6.Points = new PointCollection
|
|
{
|
|
new Point(32, 150),
|
|
new Point(68, 246),
|
|
new Point(133, 365),
|
|
new Point(333, 214),
|
|
new Point(333, 144),
|
|
new Point(296, 48),
|
|
new Point(248, 0),
|
|
new Point(0, 35),
|
|
};
|
|
|
|
d7.Points = new PointCollection
|
|
{
|
|
new Point(5, 199),
|
|
new Point(2, 151),
|
|
new Point(0, 99),
|
|
new Point(2, 49),
|
|
new Point(6, 0),
|
|
new Point(253, 34),
|
|
new Point(188, 99),
|
|
new Point(253, 164),
|
|
};
|
|
|
|
a7.Points = new PointCollection
|
|
{
|
|
new Point(78, 101),
|
|
new Point(36, 195),
|
|
new Point(0, 327),
|
|
new Point(248, 362),
|
|
new Point(297, 314),
|
|
new Point(333, 219),
|
|
new Point(333, 151),
|
|
new Point(132, 0),
|
|
};
|
|
|
|
d8.Points = new PointCollection
|
|
{
|
|
new Point(0, 140),
|
|
new Point(32, 104),
|
|
new Point(67, 66),
|
|
new Point(104, 32),
|
|
new Point(145, 0),
|
|
new Point(298, 199),
|
|
new Point(200, 199),
|
|
new Point(200, 291),
|
|
};
|
|
|
|
a8.Points = new PointCollection
|
|
{
|
|
new Point(210, 28),
|
|
new Point(115, 65),
|
|
new Point(0, 138),
|
|
new Point(153, 338),
|
|
new Point(215, 338),
|
|
new Point(311, 297),
|
|
new Point(359, 249),
|
|
new Point(324, 0),
|
|
};
|
|
}
|
|
}
|
|
|
|
public void SetBorderMode(BorderSetting borderSetting, string borderColour)
|
|
{
|
|
if (borderSetting == BorderSetting.Rainbow)
|
|
{
|
|
var rotateTransform = new RotateTransform { CenterX = 0.5, CenterY = 0.5 };
|
|
touchPanelBorder.BorderBrush = new ImageBrush {
|
|
ImageSource = new BitmapImage(new Uri(@"pack://application:,,,/Assets/conicalGradient.png")),
|
|
ViewportUnits = BrushMappingMode.RelativeToBoundingBox,
|
|
Viewport = new Rect(0, 0, 1, 1),
|
|
TileMode = TileMode.Tile,
|
|
RelativeTransform = rotateTransform,
|
|
};
|
|
|
|
var animation = new DoubleAnimation
|
|
{
|
|
From = 0,
|
|
To = 360,
|
|
Duration = new Duration(TimeSpan.FromSeconds(10)),
|
|
RepeatBehavior = RepeatBehavior.Forever
|
|
};
|
|
|
|
rotateTransform.BeginAnimation(RotateTransform.AngleProperty, animation);
|
|
return;
|
|
}
|
|
else if (borderSetting == BorderSetting.Solid)
|
|
{
|
|
try
|
|
{
|
|
var colour = (Color)ColorConverter.ConvertFromString(borderColour);
|
|
touchPanelBorder.BorderBrush = new SolidColorBrush { Color = colour };
|
|
return;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Error("Failed to parse solid colour", ex);
|
|
}
|
|
}
|
|
touchPanelBorder.BorderBrush = null;
|
|
}
|
|
|
|
public void SetEmulateRingButton(bool enabled)
|
|
{
|
|
isRingButtonEmulationEnabled = enabled;
|
|
}
|
|
|
|
private void HighlightElement(Polygon element, bool highlight)
|
|
{
|
|
if (isDebugEnabled)
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
element.Opacity = highlight ? 0.8 : 0.3;
|
|
});
|
|
}
|
|
}
|
|
}
|