modified each other mode has own side and offset
This commit is contained in:
@@ -17,13 +17,23 @@ public sealed partial class AppSettings : ObservableObject
|
||||
[ObservableProperty]
|
||||
private PopupPlacementMode _placementMode = PopupPlacementMode.AtCursor;
|
||||
|
||||
// Сторона и отступ хранятся отдельно для каждого режима: у курсора и у
|
||||
// каретки удобны разные настройки, и переключение режима их не сбрасывает
|
||||
|
||||
[ObservableProperty]
|
||||
private CursorCorner _cursorCorner = CursorCorner.BottomRight;
|
||||
private AnchorSide _cursorSide = AnchorSide.BottomRight;
|
||||
|
||||
/// <summary>Отступ от курсора в единицах WPF.</summary>
|
||||
[ObservableProperty]
|
||||
private double _cursorOffset = 16;
|
||||
|
||||
[ObservableProperty]
|
||||
private AnchorSide _caretSide = AnchorSide.BottomRight;
|
||||
|
||||
/// <summary>Отступ от каретки в единицах WPF.</summary>
|
||||
[ObservableProperty]
|
||||
private double _caretOffset = 16;
|
||||
|
||||
[ObservableProperty]
|
||||
private ScreenPosition _screenPosition = ScreenPosition.BottomRight;
|
||||
|
||||
|
||||
@@ -21,13 +21,14 @@ public enum PopupPlacementMode
|
||||
/// <summary>
|
||||
/// С какой стороны от курсора или каретки показывать подсказку.
|
||||
/// </summary>
|
||||
|
||||
public enum CursorCorner
|
||||
public enum AnchorSide
|
||||
{
|
||||
BottomRight,
|
||||
BottomLeft,
|
||||
TopRight,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
Left,
|
||||
Right,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -85,18 +85,24 @@
|
||||
<data name="CursorCornerLabel" xml:space="preserve">
|
||||
<value>Side</value>
|
||||
</data>
|
||||
<data name="CursorCorner_BottomRight" xml:space="preserve">
|
||||
<data name="AnchorSide_BottomRight" xml:space="preserve">
|
||||
<value>Bottom right</value>
|
||||
</data>
|
||||
<data name="CursorCorner_BottomLeft" xml:space="preserve">
|
||||
<data name="AnchorSide_BottomLeft" xml:space="preserve">
|
||||
<value>Bottom left</value>
|
||||
</data>
|
||||
<data name="CursorCorner_TopRight" xml:space="preserve">
|
||||
<data name="AnchorSide_TopRight" xml:space="preserve">
|
||||
<value>Top right</value>
|
||||
</data>
|
||||
<data name="CursorCorner_TopLeft" xml:space="preserve">
|
||||
<data name="AnchorSide_TopLeft" xml:space="preserve">
|
||||
<value>Top left</value>
|
||||
</data>
|
||||
<data name="AnchorSide_Left" xml:space="preserve">
|
||||
<value>Left</value>
|
||||
</data>
|
||||
<data name="AnchorSide_Right" xml:space="preserve">
|
||||
<value>Right</value>
|
||||
</data>
|
||||
<data name="CursorOffsetLabel" xml:space="preserve">
|
||||
<value>Offset</value>
|
||||
</data>
|
||||
|
||||
@@ -85,18 +85,24 @@
|
||||
<data name="CursorCornerLabel" xml:space="preserve">
|
||||
<value>Сторона</value>
|
||||
</data>
|
||||
<data name="CursorCorner_BottomRight" xml:space="preserve">
|
||||
<data name="AnchorSide_BottomRight" xml:space="preserve">
|
||||
<value>Справа снизу</value>
|
||||
</data>
|
||||
<data name="CursorCorner_BottomLeft" xml:space="preserve">
|
||||
<data name="AnchorSide_BottomLeft" xml:space="preserve">
|
||||
<value>Слева снизу</value>
|
||||
</data>
|
||||
<data name="CursorCorner_TopRight" xml:space="preserve">
|
||||
<data name="AnchorSide_TopRight" xml:space="preserve">
|
||||
<value>Справа сверху</value>
|
||||
</data>
|
||||
<data name="CursorCorner_TopLeft" xml:space="preserve">
|
||||
<data name="AnchorSide_TopLeft" xml:space="preserve">
|
||||
<value>Слева сверху</value>
|
||||
</data>
|
||||
<data name="AnchorSide_Left" xml:space="preserve">
|
||||
<value>Слева</value>
|
||||
</data>
|
||||
<data name="AnchorSide_Right" xml:space="preserve">
|
||||
<value>Справа</value>
|
||||
</data>
|
||||
<data name="CursorOffsetLabel" xml:space="preserve">
|
||||
<value>Отступ</value>
|
||||
</data>
|
||||
|
||||
@@ -63,7 +63,7 @@ public sealed partial class SettingsViewModel : ObservableObject, IDisposable
|
||||
Localization.PropertyChanged += OnLocalizationChanged;
|
||||
|
||||
PlacementModes = CreateOptions<PopupPlacementMode>();
|
||||
CursorCorners = CreateOptions<CursorCorner>();
|
||||
AnchorSides = CreateOptions<AnchorSide>();
|
||||
ScreenPositions = CreateOptions<ScreenPosition>();
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public sealed partial class SettingsViewModel : ObservableObject, IDisposable
|
||||
|
||||
public IReadOnlyList<EnumOption<PopupPlacementMode>> PlacementModes { get; }
|
||||
|
||||
public IReadOnlyList<EnumOption<CursorCorner>> CursorCorners { get; }
|
||||
public IReadOnlyList<EnumOption<AnchorSide>> AnchorSides { get; }
|
||||
|
||||
public IReadOnlyList<EnumOption<ScreenPosition>> ScreenPositions { get; }
|
||||
|
||||
@@ -103,7 +103,7 @@ public sealed partial class SettingsViewModel : ObservableObject, IDisposable
|
||||
}
|
||||
|
||||
Translate(PlacementModes);
|
||||
Translate(CursorCorners);
|
||||
Translate(AnchorSides);
|
||||
Translate(ScreenPositions);
|
||||
}
|
||||
|
||||
|
||||
@@ -109,15 +109,30 @@ public partial class LayoutPopupWindow : Window
|
||||
var anchorPoint = new PopupWindowNative.Point { X = anchor.Left, Y = anchor.Top };
|
||||
double scale = PopupWindowNative.GetScaleAt(anchorPoint);
|
||||
|
||||
// У каждого режима привязки своя сторона и свой отступ
|
||||
bool atCaret = _settings.PlacementMode == PopupPlacementMode.AtCaret;
|
||||
AnchorSide side = atCaret ? _settings.CaretSide : _settings.CursorSide;
|
||||
int offset = ToPixels(atCaret ? _settings.CaretOffset : _settings.CursorOffset, scale);
|
||||
|
||||
int width = ToPixels(_contentSize.Width, scale);
|
||||
int height = ToPixels(_contentSize.Height, scale);
|
||||
int offset = ToPixels(_settings.CursorOffset, scale);
|
||||
|
||||
bool toRight = _settings.CursorCorner is CursorCorner.BottomRight or CursorCorner.TopRight;
|
||||
bool toBottom = _settings.CursorCorner is CursorCorner.BottomRight or CursorCorner.BottomLeft;
|
||||
int toLeftOf = anchor.Left - offset - width;
|
||||
int toRightOf = anchor.Right + offset;
|
||||
int above = anchor.Top - offset - height;
|
||||
int below = anchor.Bottom + offset;
|
||||
// Для сторон «слева» и «справа» подсказка встаёт вровень с точкой привязки
|
||||
int middle = anchor.Top + (((anchor.Bottom - anchor.Top) - height) / 2);
|
||||
|
||||
int x = toRight ? anchor.Right + offset : anchor.Left - offset - width;
|
||||
int y = toBottom ? anchor.Bottom + offset : anchor.Top - offset - height;
|
||||
(int x, int y) = side switch
|
||||
{
|
||||
AnchorSide.TopLeft => (toLeftOf, above),
|
||||
AnchorSide.TopRight => (toRightOf, above),
|
||||
AnchorSide.Left => (toLeftOf, middle),
|
||||
AnchorSide.Right => (toRightOf, middle),
|
||||
AnchorSide.BottomLeft => (toLeftOf, below),
|
||||
_ => (toRightOf, below),
|
||||
};
|
||||
|
||||
PopupWindowNative.SetBounds(handle, x, y, width, height);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource FieldLabel}"
|
||||
@@ -81,49 +83,84 @@
|
||||
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='AtCursor,AtCaret'}" />
|
||||
ConverterParameter=AtCursor}" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding CursorCorners}"
|
||||
ItemsSource="{Binding AnchorSides}"
|
||||
DisplayMemberPath="Display"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.CursorCorner}"
|
||||
SelectedValue="{Binding Settings.CursorSide}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
ConverterParameter=AtCursor}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorOffsetLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter='AtCursor,AtCaret'}" />
|
||||
ConverterParameter=AtCursor}" />
|
||||
<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='AtCursor,AtCaret'}" />
|
||||
ConverterParameter=AtCursor}" />
|
||||
<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='AtCursor,AtCaret'}" />
|
||||
ConverterParameter=AtCursor}" />
|
||||
|
||||
<!-- Режим «у каретки»: свои сторона и отступ -->
|
||||
<TextBlock Grid.Row="3" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorCornerLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding AnchorSides}"
|
||||
DisplayMemberPath="Display"
|
||||
SelectedValuePath="Value"
|
||||
SelectedValue="{Binding Settings.CaretSide}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[CursorOffsetLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
<Slider Grid.Row="4" Grid.Column="1" Margin="0,12,0,0"
|
||||
Minimum="0" Maximum="80" TickFrequency="1"
|
||||
Value="{Binding Settings.CaretOffset}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.CaretOffset, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=AtCaret}" />
|
||||
|
||||
<!-- Режим «фиксированная точка» -->
|
||||
<TextBlock Grid.Row="3" Margin="0,12,12,0"
|
||||
<TextBlock Grid.Row="5" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[ScreenPositionLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
<ComboBox Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,12,0,0"
|
||||
ItemsSource="{Binding ScreenPositions}"
|
||||
DisplayMemberPath="Display"
|
||||
SelectedValuePath="Value"
|
||||
@@ -132,19 +169,19 @@
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Margin="0,12,12,0"
|
||||
<TextBlock Grid.Row="6" Margin="0,12,12,0"
|
||||
Style="{StaticResource FieldLabel}"
|
||||
Text="{Binding Localization[ScreenMarginLabel]}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
Converter={StaticResource EnumToVisibility},
|
||||
ConverterParameter=FixedPoint}" />
|
||||
<Slider Grid.Row="4" Grid.Column="1" Margin="0,12,0,0"
|
||||
<Slider Grid.Row="6" 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=FixedPoint}" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="2" Margin="12,12,0,0"
|
||||
<TextBlock Grid.Row="6" Grid.Column="2" Margin="12,12,0,0"
|
||||
Style="{StaticResource FieldValue}"
|
||||
Text="{Binding Settings.ScreenMargin, StringFormat={}{0:F0}}"
|
||||
Visibility="{Binding Settings.PlacementMode,
|
||||
|
||||
Reference in New Issue
Block a user