added feature - show tootip near careet
This commit is contained in:
@@ -6,13 +6,21 @@ using System.Windows.Media;
|
||||
namespace CursorLang.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Показывает элемент, только если значение совпадает с параметром.
|
||||
/// Нужен, чтобы настройки курсора и экрана не показывались одновременно.
|
||||
/// Показывает элемент, если значение совпадает с одним из перечисленных
|
||||
/// в параметре через запятую. Нужен, чтобы настройки точки привязки
|
||||
/// и настройки экрана не показывались одновременно.
|
||||
/// </summary>
|
||||
public sealed class EnumToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
value?.ToString() == parameter?.ToString() ? Visibility.Visible : Visibility.Collapsed;
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
string? current = value?.ToString();
|
||||
bool matches = parameter?.ToString()?
|
||||
.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||
.Any(expected => expected == current) ?? false;
|
||||
|
||||
return matches ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
Binding.DoNothing;
|
||||
|
||||
@@ -22,6 +22,10 @@ public partial class LayoutPopupWindow : Window
|
||||
|
||||
DataContext = viewModel;
|
||||
_settings = settings;
|
||||
|
||||
// Создаём окно заранее, чтобы задать его границы до первого показа:
|
||||
// иначе оно на мгновение появляется в размере по умолчанию
|
||||
new WindowInteropHelper(this).EnsureHandle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,20 +74,40 @@ public partial class LayoutPopupWindow : Window
|
||||
return;
|
||||
}
|
||||
|
||||
if (_settings.PlacementMode == PopupPlacementMode.AtCursor)
|
||||
{
|
||||
ApplyBoundsAtCursor(handle);
|
||||
}
|
||||
else
|
||||
if (_settings.PlacementMode == PopupPlacementMode.FixedPoint)
|
||||
{
|
||||
ApplyBoundsOnScreen(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyBoundsNearAnchor(handle, GetAnchor());
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyBoundsAtCursor(IntPtr handle)
|
||||
// Точка привязки: каретка в поле ввода либо курсор мыши. Курсор — это
|
||||
// прямоугольник нулевого размера, поэтому расчёт углов у них общий
|
||||
private PopupWindowNative.Rect GetAnchor()
|
||||
{
|
||||
if (_settings.PlacementMode == PopupPlacementMode.AtCaret &&
|
||||
CaretNative.TryGetCaretRect() is { } caret)
|
||||
{
|
||||
return caret;
|
||||
}
|
||||
|
||||
PopupWindowNative.Point cursor = PopupWindowNative.GetCursorPosition();
|
||||
double scale = PopupWindowNative.GetScaleAt(cursor);
|
||||
return new PopupWindowNative.Rect
|
||||
{
|
||||
Left = cursor.X,
|
||||
Top = cursor.Y,
|
||||
Right = cursor.X,
|
||||
Bottom = cursor.Y,
|
||||
};
|
||||
}
|
||||
|
||||
private void ApplyBoundsNearAnchor(IntPtr handle, PopupWindowNative.Rect anchor)
|
||||
{
|
||||
var anchorPoint = new PopupWindowNative.Point { X = anchor.Left, Y = anchor.Top };
|
||||
double scale = PopupWindowNative.GetScaleAt(anchorPoint);
|
||||
|
||||
int width = ToPixels(_contentSize.Width, scale);
|
||||
int height = ToPixels(_contentSize.Height, scale);
|
||||
@@ -92,8 +116,8 @@ public partial class LayoutPopupWindow : Window
|
||||
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 - width;
|
||||
int y = toBottom ? cursor.Y + offset : cursor.Y - offset - height;
|
||||
int x = toRight ? anchor.Right + offset : anchor.Left - offset - width;
|
||||
int y = toBottom ? anchor.Bottom + offset : anchor.Top - offset - height;
|
||||
|
||||
PopupWindowNative.SetBounds(handle, x, y, width, height);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:CursorLang.Views"
|
||||
xmlns:models="clr-namespace:CursorLang.Models"
|
||||
xmlns:vm="clr-namespace:CursorLang.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=vm:SettingsViewModel}"
|
||||
@@ -82,13 +81,13 @@
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.PlacementMode}" />
|
||||
|
||||
<!-- Режим «у курсора» -->
|
||||
<!-- Привязка к точке: курсор или каретка -->
|
||||
<TextBlock Grid.Row="1" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorCornerLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.AtCursor}}" />
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding CursorCorners}"
|
||||
DisplayMemberPath="Display"
|
||||
@@ -96,26 +95,26 @@
|
||||
SelectedValue="{Binding Settings.CursorCorner}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.AtCursor}}" />
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorOffsetLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.AtCursor}}" />
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
<Slider Grid.Row="2" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0" Maximum="80" TickFrequency="1"
|
||||
Value="{Binding Settings.CursorOffset}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.AtCursor}}" />
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.CursorOffset, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.AtCursor}}" />
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
|
||||
<!-- Режим «фиксированная точка» -->
|
||||
<TextBlock Grid.Row="3" Margin="0,12,12,0"
|
||||
@@ -123,7 +122,7 @@
|
||||
Text="{Binding Localization[ScreenPositionLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.FixedPoint}}" />
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding ScreenPositions}"
|
||||
DisplayMemberPath="Display"
|
||||
@@ -131,26 +130,26 @@
|
||||
SelectedValue="{Binding Settings.ScreenPosition}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.FixedPoint}}" />
|
||||
ConverterParameter=FixedPoint}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[ScreenMarginLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.FixedPoint}}" />
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<Slider Grid.Row="4" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0" Maximum="200" TickFrequency="1"
|
||||
Value="{Binding Settings.ScreenMargin}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.FixedPoint}}" />
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.ScreenMargin, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter={x:Static models:PopupPlacementMode.FixedPoint}}" />
|
||||
ConverterParameter=FixedPoint}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user