MinimumSize = "60,22";
Height = "Fit";
Width = "Fit";
+ BubbleEvents= "None";
}
ButtonBorder {
BorderWidth="1";
MouseEnter="{Background=${ControlHighlight}}"
MouseLeave="{Background=Transparent}"/>
</Template>
-</Button>
+</Button>
\ No newline at end of file
Foreground = "{./Foreground}" BubbleEvents="All"
IsPopped="{²./IsOpened}" PopWidth="{./PopWidth}" PopHeight="{./PopHeight}">
<Template>
-
- <Border Name="border1"
- MinimumSize = "60,0"
- Foreground="Transparent"
- Background="{./Background}">
- <Label Text="{./Caption}"
- Foreground="{./Foreground}"
- Margin="2" HorizontalAlignment="Left"
- Font="{./Font}" />
- </Border>
-
+ <Border Name="border1"
+ MinimumSize = "60,0"
+ Foreground="Transparent"
+ Background="{./Background}">
+ <Label Text="{./Caption}"
+ Foreground="{./Foreground}"
+ Margin="2" HorizontalAlignment="Left"
+ Font="{./Font}" />
+ </Border>
</Template>
<Border Foreground="DimGrey" Width="{../PopWidth}" Height="{../PopHeight}" Background="${MenuBackground}">
<VerticalStack Name="ItemsContainer" Width="Stretched" />
namespace Crow
{
+ /// <summary>
+ /// Occurs when the selection has changed.
+ /// </summary>
public class SelectionChangeEventArgs: EventArgs
- {
+ {
public object NewValue;
public SelectionChangeEventArgs (object _newValue) : base()
--- /dev/null
+// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using Crow.Text;
+using System;
+
+namespace Crow
+{
+ /// <summary>
+ /// Occurs in the TextBox widget and Label when the current selected text has changed.
+ /// </summary>
+ public class TextSelectionChangeEventArgs: EventArgs
+ {
+ /// <summary>
+ /// The text span of the current selection.
+ /// </summary>
+ public TextSpan Selection;
+
+ public TextSelectionChangeEventArgs (TextSpan newSelection) : base()
+ {
+ Selection = newSelection;
+ }
+ }
+}
+
public override void onMouseClick (object sender, MouseButtonEventArgs e)
{
command?.Execute (this);
- e.Handled = true;
+ //e.Handled = true;
base.onMouseClick (sender, e);
}
/// Occurs when Text has changed.
/// </summary>
public event EventHandler<TextChangeEventArgs> TextChanged;
+ /// <summary>
+ /// Occurs when the current selected text has changed
+ /// </summary>
+ public event EventHandler<TextSelectionChangeEventArgs> SelectionChanged;
public virtual void OnTextChanged(Object sender, TextChangeEventArgs e)
{
TextChanged.Raise (this, e);
}
+ public virtual void OnSelectionChanged(Object sender, TextSelectionChangeEventArgs e)
+ {
+ SelectionChanged.Raise (this, e);
+ }
//TODO:change protected to private
#region private and protected fields
currentLoc = value;
NotifyValueChanged ("CurrentLine", CurrentLine);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ if (SelectionChanged != null)
+ OnSelectionChanged (this, new TextSelectionChangeEventArgs (Selection));
}
}
public virtual int CurrentLine {
_textAlignment = value;
CurrentLoc?.ResetVisualX ();
- selectionStart?.ResetVisualX ();
+ SelectionStart?.ResetVisualX ();
RegisterForRedraw ();
NotifyValueChangedAuto (_textAlignment);
}
void constraintsLocations () {
- if (selectionStart.HasValue) {
+ if (SelectionStart.HasValue) {
CharLocation loc = CurrentLoc.Value;
int l = Math.Min (loc.Line, lines.Count - 1);
- selectionStart = new CharLocation (l, Math.Min (loc.Column, lines[l].Length - 1));
+ SelectionStart = new CharLocation (l, Math.Min (loc.Column, lines[l].Length - 1));
}
if (CurrentLoc.HasValue) {
CharLocation loc = CurrentLoc.Value;
public TextSpan Selection {
set {
if (value.IsEmpty)
- selectionStart = null;
+ SelectionStart = null;
else
- selectionStart = lines.GetLocation (value.Start);
+ SelectionStart = lines.GetLocation (value.Start);
CurrentLoc = lines.GetLocation (value.End);
}
get {
if (CurrentLoc == null)
return default;
CharLocation selStart = CurrentLoc.Value, selEnd = CurrentLoc.Value;
- if (selectionStart.HasValue) {
- if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
+ if (SelectionStart.HasValue) {
+ if (CurrentLoc.Value.Line < SelectionStart.Value.Line) {
selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
- selStart = selectionStart.Value;
+ selEnd = SelectionStart.Value;
+ } else if (CurrentLoc.Value.Line > SelectionStart.Value.Line) {
+ selStart = SelectionStart.Value;
selEnd = CurrentLoc.Value;
- } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
+ } else if (CurrentLoc.Value.Column < SelectionStart.Value.Column) {
selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
+ selEnd = SelectionStart.Value;
} else {
- selStart = selectionStart.Value;
+ selStart = SelectionStart.Value;
selEnd = CurrentLoc.Value;
}
}
return selection.IsEmpty ? "" : Text.AsSpan (selection.Start, selection.Length).ToString ();
}
}
- public bool SelectionIsEmpty => selectionStart.HasValue ? Selection.IsEmpty : true;
+ public bool SelectionIsEmpty => SelectionStart.HasValue ? Selection.IsEmpty : true;
+ public CharLocation? SelectionStart {
+ get => selectionStart;
+ set {
+ if (selectionStart == value)
+ return;
+ selectionStart = value;
+ if (SelectionChanged != null)
+ OnSelectionChanged (this, new TextSelectionChangeEventArgs (Selection));
+ }
+ }
protected virtual void measureTextBounds (Context gr) {
fe = gr.FontExtents;
NotifyValueChanged ("CurrentColumn", CurrentColumn);
} else
updateLocation (gr, cb.Width, ref currentLoc);
- if (selectionStart.HasValue) {
+ if (SelectionStart.HasValue) {
updateLocation (gr, cb.Width, ref selectionStart);
- if (CurrentLoc.Value != selectionStart.Value)
+ if (CurrentLoc.Value != SelectionStart.Value)
selectionNotEmpty = true;
}
if (selectionNotEmpty) {
- if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
+ if (CurrentLoc.Value.Line < SelectionStart.Value.Line) {
selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
- selStart = selectionStart.Value;
+ selEnd = SelectionStart.Value;
+ } else if (CurrentLoc.Value.Line > SelectionStart.Value.Line) {
+ selStart = SelectionStart.Value;
selEnd = CurrentLoc.Value;
- } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
+ } else if (CurrentLoc.Value.Column < SelectionStart.Value.Column) {
selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
+ selEnd = SelectionStart.Value;
} else {
- selStart = selectionStart.Value;
+ selStart = SelectionStart.Value;
selEnd = CurrentLoc.Value;
}
} else
}
protected void checkShift (Modifier modifier) {
if (modifier.HasFlag (Modifier.Shift)) {
- if (!selectionStart.HasValue)
- selectionStart = CurrentLoc;
+ if (!SelectionStart.HasValue)
+ SelectionStart = CurrentLoc;
} else
- selectionStart = null;
+ SelectionStart = null;
}
#region Widget overrides
{
base.onFocused (sender, e);
if (CurrentLoc == null) {
- selectionStart = new CharLocation (0, 0);
+ SelectionStart = new CharLocation (0, 0);
CurrentLoc = new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length);
}
RegisterForRedraw ();
targetColumn = -1;
if (HasFocus) {
if (!IFace.Shift)
- selectionStart = hoverLoc;
- else if (!selectionStart.HasValue)
- selectionStart = CurrentLoc;
+ SelectionStart = hoverLoc;
+ else if (!SelectionStart.HasValue)
+ SelectionStart = CurrentLoc;
CurrentLoc = hoverLoc;
IFace.forceTextCursor = true;
RegisterForRedraw ();
public override void onMouseUp (object sender, MouseButtonEventArgs e)
{
base.onMouseUp (sender, e);
- if (e.Button != MouseButton.Left || !HasFocus || !selectionStart.HasValue)
+ if (e.Button != MouseButton.Left || !HasFocus || !SelectionStart.HasValue)
return;
- if (selectionStart.Value == CurrentLoc.Value)
- selectionStart = null;
+ if (SelectionStart.Value == CurrentLoc.Value)
+ SelectionStart = null;
}
public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e)
{
return;
GotoWordStart ();
- selectionStart = CurrentLoc;
+ SelectionStart = CurrentLoc;
GotoWordEnd ();
RegisterForRedraw ();
}
switch (e.Key) {
case Key.Escape:
- selectionStart = null;
+ SelectionStart = null;
RegisterForRedraw ();
break;
case Key.Home:
-// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
#region Public properties
[DefaultValue(false)]
public bool IsOpened {
- get { return isOpened; }
+ get => isOpened;
set {
if (isOpened == value)
return;
{
if (command != null) {
command.Execute (this);
- closeMenu ();
+ CloseMenu ();
}
if (hasClick)
base.onMouseClick (sender, e);
m.AutomaticOpening = false;
}
- void closeMenu () {
- MenuItem tmp = LogicalParent as MenuItem;
+ public void CloseMenu () {
+ MenuItem tmp = this;
while (tmp != null) {
tmp.IsOpened = false;
tmp.Background = Colors.Transparent;
OnValidate (this, new ValidateEventArgs (_text));
break;
case Key.Escape:
- selectionStart = null;
+ SelectionStart = null;
CurrentLoc = lines.GetLocation (selection.Start);
RegisterForRedraw ();
break;
_text = tmp.ToString ();
lines.Update (change);
//lines.Update (_text);
- selectionStart = null;
+ SelectionStart = null;
CurrentLoc = lines.GetLocation (change.Start + change.ChangedText.Length);
textMeasureIsUpToDate = false;
}
void showError (Exception ex) {
- Console.WriteLine (ex);
+ Debug.WriteLine (ex);
NotifyValueChanged ("ErrorMessage", ex);
NotifyValueChanged ("ShowError", true);
}
Load ("#ShowCase.showcase.crow").DataSource = this;
crowContainer = FindByName ("CrowContainer") as Container;
- editor = FindByName ("tb") as TextBox;
+ editor = FindByName ("tb") as Editor;
if (!File.Exists (CurrentFile))
newFile ();
<Button Style="IcoButton" Command="{CMDSaveAs}" />
<Button Style="IcoButton" Command="{CMDUndo}" />
<Button Style="IcoButton" Command="{CMDRedo}" />
- <!--<Button Style="IcoButton" Command="{CMDCut}" />
+ <Button Style="IcoButton" Command="{CMDCut}" />
<Button Style="IcoButton" Command="{CMDCopy}" />
- <Button Style="IcoButton" Command="{CMDPaste}" />-->
+ <Button Style="IcoButton" Command="{CMDPaste}" />
<Popper RootDataLevel="true" IsVisible="{DebugLoggingEnabled}" Fit="true">
<Template>
<CheckBox IsChecked="{²./IsPopped}">
</Border>
</Template>
<VerticalStack Width="200" Height="200" Background="Jet" Margin="5">
- <CheckBox Caption="Embed source in templated control" IsChecked="{²EncloseInTemplatedControl}"/>
+ <CheckBox Caption="Embed source in template" IsChecked="{²EncloseInTemplatedControl}"/>
<TextBox BubbleEvents="None" Text="{²TemplateContainerSource}" Width="Stretched" Height="Stretched" Multiline="true"
Tooltip="Add '*source* where you want to load the source in the editor."/>
</VerticalStack>
<HorizontalStack>
<Editor Name="tb" Text="{Source}" Multiline="true" Font="consolas, 12" Focusable="true" Height="Stretched" Width="Stretched"
TextChanged="onTextChanged" KeyDown="textView_KeyDown" ContextCommands="{EditorCommands}"
+ SelectionChanged="onEditorSelectionChanged"
Foreground="DarkGrey" Background="White" MouseWheelSpeed="20"/>
- <!--SelectionChanged="onSelectedTextChanged"-->
<ScrollBar Value="{²../tb.ScrollY}"
LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
CursorRatio="{../tb.ChildHeightRatio}" Maximum="{../tb.MaxScrollY}" />
if (attrib.ValueToken.HasValue) {
TextChange tc = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
update (tc);
- selectionStart = lines.GetLocation (attrib.ValueToken.Value.Start + tc.CharDiff + 1);
+ SelectionStart = lines.GetLocation (attrib.ValueToken.Value.Start + tc.CharDiff + 1);
CurrentLoc = lines.GetLocation (attrib.ValueToken.Value.End + tc.CharDiff - 1);
} else {
update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\""));
hideOverlay ();
base.onMouseDown (sender, e);
}
-
+ public override void onMouseEnter(object sender, MouseMoveEventArgs e) {
+ base.onMouseEnter (sender, e);
+ HasFocus = true;
+ }
public override void onKeyDown(object sender, KeyEventArgs e)
{
TextSpan selection = Selection;
update (new TextChange (lines[l].Start, 0, "\t"));
}
- selectionStart = new CharLocation (lineStart, 0);
+ SelectionStart = new CharLocation (lineStart, 0);
CurrentLoc = new CharLocation (lineEnd, lines[lineEnd].Length);
disableSuggestions = false;
CharLocation selStart = default, selEnd = default;
bool selectionNotEmpty = false;
- if (HasFocus) {
+ //if (HasFocus) {
if (currentLoc?.Column < 0) {
updateLocation (gr, cb.Width, ref currentLoc);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
overlay.Top = p.Y;
}
}
- if (selectionStart.HasValue) {
+ if (SelectionStart.HasValue) {
updateLocation (gr, cb.Width, ref selectionStart);
- if (CurrentLoc.Value != selectionStart.Value)
+ if (CurrentLoc.Value != SelectionStart.Value)
selectionNotEmpty = true;
}
if (selectionNotEmpty) {
- if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
+ if (CurrentLoc.Value.Line < SelectionStart.Value.Line) {
selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
- selStart = selectionStart.Value;
+ selEnd = SelectionStart.Value;
+ } else if (CurrentLoc.Value.Line > SelectionStart.Value.Line) {
+ selStart = SelectionStart.Value;
selEnd = CurrentLoc.Value;
- } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
+ } else if (CurrentLoc.Value.Column < SelectionStart.Value.Column) {
selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
+ selEnd = SelectionStart.Value;
} else {
- selStart = selectionStart.Value;
+ selStart = SelectionStart.Value;
selEnd = CurrentLoc.Value;
}
} else
IFace.forceTextCursor = true;
- }
+ //}
double spacePixelWidth = gr.TextExtents (" ").XAdvance;
int x = 0, y = 0;
tok = source.Tokens[tokPtr];
}
- if (HasFocus && selectionNotEmpty) {
+ if (selectionNotEmpty) {
RectangleD lineRect = new RectangleD (cb.X, lineHeight * y + cb.Top, pixX, lineHeight);
RectangleD selRect = lineRect;
if (string.IsNullOrEmpty (CurrentDir))
CurrentDir = Path.Combine (Directory.GetCurrentDirectory (), "Interfaces");
-
}
protected const string _defaultFileName = "unnamed.txt";
protected string source = "", origSource;
- protected TextBox editor;
+ protected Editor editor;
bool debugLogRecording;
protected TextSpan selection;
protected string SelectedText =>
selection.IsEmpty ? "" : Source.AsSpan (selection.Start, selection.Length).ToString ();
-
+ public void onEditorSelectionChanged(Object sender, TextSelectionChangeEventArgs e) {
+ selection = e.Selection;
+ CMDCut.CanExecute = CMDCopy.CanExecute = !selection.IsEmpty;
+ }
protected void undo () {
if (undoStack.TryPop (out TextChange tch)) {
redoStack.Push (tch.Inverse (source));
}
protected void copy () {
Clipboard = SelectedText;
+ CMDPaste.CanExecute = !string.IsNullOrEmpty (Clipboard);
}
protected void paste () {
applyChange (new TextChange (selection.Start, selection.Length, Clipboard));
disableTextChangedEvent = true;
Source = tmp.ToString ();
disableTextChangedEvent = false;
+ editor.SelectionStart = null;
+ editor.SetCursorPosition (change.Start + change.ChangedText.Length);
+
+ forceTextCursor = true;
}
protected void applyChange (TextChange change) {
undoStack.Push (change.Inverse (source));
return;
applyChange (e.Change);
}
-
- protected void onSelectedTextChanged (object sender, EventArgs e) {
- selection = (sender as Label).Selection;
- Console.WriteLine($"selection:{selection.Start} length:{selection.Length}");
- CMDCut.CanExecute = CMDCopy.CanExecute = !selection.IsEmpty;
- }
protected void textView_KeyDown (object sender, Crow.KeyEventArgs e) {
if (Ctrl) {
if (e.Key == Glfw.Key.W) {
</Template>
<VerticalStack Margin="0" Name="ItemsContainer" Fit="true" Background="Jet"/>
</Popper>
- </Template>
+ </Template>
<ItemTemplate DataType="Crow.Command" Path="#Crow.MenuButton.template"/>
<ItemTemplate DataType="Crow.CommandGroup" Data="Commands">
<Popper PopDirection="Right" Caption="{Caption}" IsEnabled="{CanExecute}" Width="Stretched"
<Label Text="{./Caption}" Width="Fit" Height="Stretched"/>
<Label Text="..."/>
</HorizontalStack>
- </Template>
+ </Template>
<VerticalStack Margin="0" Name="ItemsContainer" Width="{../PopWidth}" Height="{../PopHeight}" Background="${MenuBackground}"/>
</Popper>
- </ItemTemplate>
+ </ItemTemplate>
</MenuItem>
</ItemTemplate>
</Menu>
\ No newline at end of file