Browse Source

add context menu

pull/4531/head
Jumar Macato 6 years ago
committed by Dan Walmsley
parent
commit
e6e2319dc3
  1. 74
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  2. 74
      src/Avalonia.Controls/TextBox.cs

74
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -1,61 +1,57 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.Pages.TextBoxPage">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ControlCatalog.Pages.TextBoxPage">
<StackPanel Orientation="Vertical" Spacing="4">
<StackPanel.Resources>
<ContextMenu x:Key="DefaultTextBoxContextMenu">
<MenuItem Header="Cut" Command="{Binding $parent[TextBox].Cut}" IsEnabled="{Binding $parent[TextBox].CanCut}"/>
<MenuItem Header="Copy" Command="{Binding $parent[TextBox].Copy}" IsEnabled="{Binding $parent[TextBox].CanCopy}"/>
<MenuItem Header="Paste" Command="{Binding $parent[TextBox].Paste}" IsEnabled="{Binding $parent[TextBox].CanPaste}"/>
</ContextMenu>
</StackPanel.Resources>
<StackPanel.Styles>
<Style Selector=":is(TextBox)">
<Setter Property="ContextMenu" Value="{StaticResource DefaultTextBoxContextMenu}" />
</Style>
</StackPanel.Styles>
<TextBlock Classes="h1">TextBox</TextBlock>
<TextBlock Classes="h2">A control into which the user can input text</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Spacing="16">
<StackPanel Orientation="Horizontal" Margin="0,16,0,0" HorizontalAlignment="Center" Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8">
<TextBox Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit." Width="200" />
<TextBox Watermark="ReadOnly" IsReadOnly="True" Text="This is read only"/>
<TextBox Width="200" Watermark="Watermark" />
<TextBox Width="200"
Watermark="Floating Watermark"
UseFloatingWatermark="True"
Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/>
<TextBox Width="200" Watermark="Floating Watermark" UseFloatingWatermark="True" Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/>
<TextBox Width="200"
Watermark="Password Box"
Classes="revealPasswordButton"
UseFloatingWatermark="True"
PasswordChar="*"
Text="Password" />
<TextBox Width="200" Watermark="Password Box" Classes="revealPasswordButton" UseFloatingWatermark="True" PasswordChar="*" Text="Password" />
<TextBox Width="200" Text="Left aligned text" TextAlignment="Left" />
<TextBox Width="200" Text="Center aligned text" TextAlignment="Center" />
<TextBox Width="200" Text="Right aligned text" TextAlignment="Right" />
<TextBox Width="200" Text="Custom selection brush"
SelectionStart="5" SelectionEnd="22"
SelectionBrush="Green" SelectionForegroundBrush="Yellow"/>
<TextBox Width="200" Text="Custom selection brush" SelectionStart="5" SelectionEnd="22" SelectionBrush="Green" SelectionForegroundBrush="Yellow"/>
<TextBox Width="200" Text="Custom caret brush" CaretBrush="DarkOrange"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Width="200" Height="125"
Text="Multiline TextBox with TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox AcceptsReturn="True" Width="200" Height="125"
Text="Multiline TextBox with no TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Width="200" Height="125" Text="Multiline TextBox with TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox AcceptsReturn="True" Width="200" Height="125" Text="Multiline TextBox with no TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox Classes="clearButton" Text="Clear Content" Width="200" FontWeight="Normal" FontStyle="Normal" Watermark="Watermark" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">resm fonts</TextBlock>
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-Italic.ttf?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-*.ttf?assembly=ControlCatalog#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">res fonts</TextBlock>
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-Italic.ttf#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-*.ttf#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">resm fonts</TextBlock>
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-Italic.ttf?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-*.ttf?assembly=ControlCatalog#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">res fonts</TextBlock>
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-Italic.ttf#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-*.ttf#Source Sans Pro"/>
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

74
src/Avalonia.Controls/TextBox.cs

@ -1,3 +1,4 @@
using System.Windows.Input;
using Avalonia.Input.Platform;
using System;
using System.Collections.Generic;
@ -103,6 +104,21 @@ namespace Avalonia.Controls
public static readonly StyledProperty<bool> RevealPasswordProperty =
AvaloniaProperty.Register<TextBox, bool>(nameof(RevealPassword));
public static readonly DirectProperty<TextBox, bool> CanCutProperty =
AvaloniaProperty.RegisterDirect<TextBox, bool>(
nameof(CanCut),
o => o.CanCut);
public static readonly DirectProperty<TextBox, bool> CanCopyProperty =
AvaloniaProperty.RegisterDirect<TextBox, bool>(
nameof(CanCopy),
o => o.CanCopy);
public static readonly DirectProperty<TextBox, bool> CanPasteProperty =
AvaloniaProperty.RegisterDirect<TextBox, bool>(
nameof(CanPaste),
o => o.CanPaste);
struct UndoRedoState : IEquatable<UndoRedoState>
{
@ -126,6 +142,9 @@ namespace Avalonia.Controls
private UndoRedoHelper<UndoRedoState> _undoRedoHelper;
private bool _isUndoingRedoing;
private bool _ignoreTextChanges;
private bool _canCut;
private bool _canCopy;
private bool _canPaste;
private string _newLine = Environment.NewLine;
private static readonly string[] invalidCharacters = new String[1] { "\u007f" };
@ -378,6 +397,33 @@ namespace Avalonia.Controls
SelectionStart = SelectionEnd = CaretIndex;
}
/// <summary>
/// Property for determining if the Cut command can be executed.
/// </summary>
public bool CanCut
{
get { return _canCut; }
private set { SetAndRaise(CanCutProperty, ref _canCut, value); }
}
/// <summary>
/// Property for determining if the Copy command can be executed.
/// </summary>
public bool CanCopy
{
get { return _canCopy; }
private set { SetAndRaise(CanCopyProperty, ref _canCopy, value); }
}
/// <summary>
/// Property for determining if the Paste command can be executed.
/// </summary>
public bool CanPaste
{
get { return _canPaste; }
private set { SetAndRaise(CanPasteProperty, ref _canPaste, value); }
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
_presenter = e.NameScope.Get<TextPresenter>("PART_TextPresenter");
@ -395,9 +441,19 @@ namespace Avalonia.Controls
if (change.Property == TextProperty)
{
UpdatePseudoclasses();
UpdateCommandStates();
}
}
private void UpdateCommandStates()
{
var text = GetSelection();
var b1 = string.IsNullOrEmpty(text);
CanCopy = !b1;
CanCut = !b1;
CanPaste = !IsReadOnly;
}
protected override void OnGotFocus(GotFocusEventArgs e)
{
base.OnGotFocus(e);
@ -412,6 +468,8 @@ namespace Avalonia.Controls
SelectAll();
}
UpdateCommandStates();
_presenter?.ShowCaret();
}
@ -425,6 +483,8 @@ namespace Avalonia.Controls
RevealPassword = false;
}
UpdateCommandStates();
_presenter?.HideCaret();
}
@ -469,6 +529,9 @@ namespace Avalonia.Controls
public async void Cut()
{
var text = GetSelection();
if (text is null) return;
_undoRedoHelper.Snapshot();
Copy();
DeleteSelection();
@ -477,17 +540,18 @@ namespace Avalonia.Controls
public async void Copy()
{
var text = GetSelection();
if (text is null) return;
await ((IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)))
.SetTextAsync(GetSelection());
.SetTextAsync(text);
}
public async void Paste()
{
var text = await ((IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))).GetTextAsync();
if (text == null)
{
return;
}
if (text is null) return;
_undoRedoHelper.Snapshot();
HandleTextInput(text);

Loading…
Cancel
Save