added multilang and settings
This commit is contained in:
@@ -1,39 +1,38 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using CursorLang.Interop;
|
||||
using CursorLang.Services;
|
||||
using CursorLang.Models;
|
||||
using CursorLang.ViewModels;
|
||||
|
||||
namespace CursorLang.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Всплывающая подсказка у курсора с коротким именем раскладки.
|
||||
/// Отвечает только за показ: когда её убрать, решает <see cref="LayoutPopupService"/>.
|
||||
/// Всплывающая подсказка с коротким именем раскладки.
|
||||
/// Отвечает только за показ и место на экране: когда её убрать,
|
||||
/// решает <see cref="Services.LayoutPopupService"/>.
|
||||
/// </summary>
|
||||
public partial class LayoutPopupWindow : Window
|
||||
{
|
||||
private readonly double _cursorOffset;
|
||||
private PopupWindowNative.Point _cursor;
|
||||
private readonly AppSettings _settings;
|
||||
|
||||
public LayoutPopupWindow(LayoutPopupViewModel viewModel, PopupOptions options)
|
||||
public LayoutPopupWindow(LayoutPopupViewModel viewModel, AppSettings settings)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = viewModel;
|
||||
_cursorOffset = options.CursorOffset;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Показывает подсказку у текущего положения курсора.
|
||||
/// Показывает подсказку в месте, заданном настройками.
|
||||
/// </summary>
|
||||
public void ShowAtCursor()
|
||||
public void ShowPopup()
|
||||
{
|
||||
ResizeToContent();
|
||||
_cursor = PopupWindowNative.GetCursorPosition();
|
||||
|
||||
// Для уже созданного окна двигаем до показа; при самом первом вызове
|
||||
// хэндла ещё нет, и позиционирование выполнит OnSourceInitialized
|
||||
MoveToCursor();
|
||||
MoveToTargetPosition();
|
||||
Show();
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ public partial class LayoutPopupWindow : Window
|
||||
base.OnSourceInitialized(e);
|
||||
|
||||
PopupWindowNative.MakePassive(new WindowInteropHelper(this).Handle);
|
||||
MoveToCursor();
|
||||
MoveToTargetPosition();
|
||||
}
|
||||
|
||||
// Размер считаем сами, а не через SizeToContent: тот вычисляет его при создании
|
||||
@@ -59,7 +58,7 @@ public partial class LayoutPopupWindow : Window
|
||||
Height = content.DesiredSize.Height;
|
||||
}
|
||||
|
||||
private void MoveToCursor()
|
||||
private void MoveToTargetPosition()
|
||||
{
|
||||
IntPtr handle = new WindowInteropHelper(this).Handle;
|
||||
if (handle == IntPtr.Zero)
|
||||
@@ -67,9 +66,46 @@ public partial class LayoutPopupWindow : Window
|
||||
return;
|
||||
}
|
||||
|
||||
// Отступ задан в единицах WPF, а двигаем окно в пикселях: пересчитываем
|
||||
// его по масштабу монитора, на котором сейчас курсор
|
||||
int offset = (int)Math.Round(_cursorOffset * PopupWindowNative.GetScaleAt(_cursor));
|
||||
PopupWindowNative.MoveTo(handle, _cursor.X + offset, _cursor.Y + offset);
|
||||
(int x, int y) = _settings.PlacementMode == PopupPlacementMode.AtCursor
|
||||
? GetCursorPosition()
|
||||
: GetScreenPosition();
|
||||
|
||||
PopupWindowNative.MoveTo(handle, x, y);
|
||||
}
|
||||
|
||||
// Отступы и размеры заданы в единицах WPF, а окно двигаем в пикселях,
|
||||
// поэтому всё пересчитывается по масштабу нужного монитора
|
||||
private (int X, int Y) GetCursorPosition()
|
||||
{
|
||||
PopupWindowNative.Point cursor = PopupWindowNative.GetCursorPosition();
|
||||
double scale = PopupWindowNative.GetScaleAt(cursor);
|
||||
int offset = (int)Math.Round(_settings.CursorOffset * scale);
|
||||
|
||||
bool toRight = _settings.CursorCorner is CursorCorner.BottomRight or CursorCorner.TopRight;
|
||||
bool toBottom = _settings.CursorCorner is CursorCorner.BottomRight or CursorCorner.BottomLeft;
|
||||
|
||||
int x = toRight ? cursor.X + offset : cursor.X - offset - ToPixels(Width, scale);
|
||||
int y = toBottom ? cursor.Y + offset : cursor.Y - offset - ToPixels(Height, scale);
|
||||
return (x, y);
|
||||
}
|
||||
|
||||
private (int X, int Y) GetScreenPosition()
|
||||
{
|
||||
(PopupWindowNative.Rect work, double scale) = PopupWindowNative.GetActiveMonitorWorkArea();
|
||||
int margin = (int)Math.Round(_settings.ScreenMargin * scale);
|
||||
int width = ToPixels(Width, scale);
|
||||
int height = ToPixels(Height, scale);
|
||||
|
||||
return _settings.ScreenPosition switch
|
||||
{
|
||||
ScreenPosition.TopLeft => (work.Left + margin, work.Top + margin),
|
||||
ScreenPosition.TopRight => (work.Right - margin - width, work.Top + margin),
|
||||
ScreenPosition.BottomLeft => (work.Left + margin, work.Bottom - margin - height),
|
||||
ScreenPosition.BottomRight => (work.Right - margin - width, work.Bottom - margin - height),
|
||||
_ => (work.Left + ((work.Right - work.Left - width) / 2),
|
||||
work.Top + ((work.Bottom - work.Top - height) / 2)),
|
||||
};
|
||||
}
|
||||
|
||||
private static int ToPixels(double wpfUnits, double scale) => (int)Math.Round(wpfUnits * scale);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user