protected override void OnFocusLost(InputState state) { unbindInput(); Caret.ClearTransforms(); Caret.FadeOut(200); if (state.Keyboard.Keys.Contains(Key.Enter)) { Background.Colour = BackgroundUnfocused; Background.ClearTransforms(); Background.FlashColour(BackgroundCommit, 400); audio.Sample.Get(@"Keyboard/key-confirm")?.Play(); OnCommit?.Invoke(this, true); } else { Background.ClearTransforms(); Background.FadeColour(BackgroundUnfocused, 200, EasingTypes.OutExpo); } cursorAndLayout.Invalidate(); }
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { if (!HasFocus) { return(false); } if (textInput?.ImeActive == true) { return(true); } if (args.Key >= Key.F1 && args.Key <= Key.F35) { return(false); } if (HandlePendingText(state)) { return(true); } if (ReadOnly) { return(true); } if (state.Keyboard.AltPressed) { return(false); } switch (args.Key) { case Key.Tab: return(base.OnKeyDown(state, args)); case Key.End: moveSelection(text.Length, state.Keyboard.ShiftPressed); return(true); case Key.Home: moveSelection(-text.Length, state.Keyboard.ShiftPressed); return(true); case Key.Left: { if (!HandleLeftRightArrows) { return(false); } if (selectionEnd == 0) { //we only clear if you aren't holding shift if (!state.Keyboard.ShiftPressed) { resetSelection(); } return(true); } int amount = 1; if (state.Keyboard.ControlPressed) { int lastSpace = text.LastIndexOf(' ', Math.Max(0, selectionEnd - 2)); if (lastSpace >= 0) { //if you have something selected and shift is not held down //A selection reset is required to select a word inside the current selection if (!state.Keyboard.ShiftPressed) { resetSelection(); } amount = selectionEnd - lastSpace - 1; } else { amount = selectionEnd; } } moveSelection(-amount, state.Keyboard.ShiftPressed); return(true); } case Key.Right: { if (!HandleLeftRightArrows) { return(false); } if (selectionEnd == text.Length) { if (!state.Keyboard.ShiftPressed) { resetSelection(); } return(true); } int amount = 1; if (state.Keyboard.ControlPressed) { int nextSpace = text.IndexOf(' ', selectionEnd + 1); if (nextSpace >= 0) { if (!state.Keyboard.ShiftPressed) { resetSelection(); } amount = nextSpace - selectionEnd; } else { amount = text.Length - selectionEnd; } } moveSelection(amount, state.Keyboard.ShiftPressed); return(true); } case Key.KeypadEnter: case Key.Enter: if (HasFocus) { if (ReleaseFocusOnCommit) { inputManager.ChangeFocus(null); } Background.Colour = ReleaseFocusOnCommit ? BackgroundUnfocused : BackgroundFocused; Background.ClearTransforms(); Background.FlashColour(BackgroundCommit, 400); audio.Sample.Get(@"Keyboard/key-confirm")?.Play(); OnCommit?.Invoke(this, true); } return(true); case Key.Delete: if (selectionLength == 0) { if (text.Length == selectionStart) { return(true); } if (state.Keyboard.ControlPressed) { int spacePos = selectionStart; while (text[spacePos] == ' ' && spacePos < text.Length) { spacePos++; } spacePos = MathHelper.Clamp(text.IndexOf(' ', spacePos), 0, text.Length); selectionEnd = spacePos; if (selectionStart == 0 && spacePos == 0) { selectionEnd = text.Length; } if (selectionLength == 0) { return(true); } } else { //we're deleting in front of the cursor, so move the cursor forward once first selectionStart = selectionEnd = selectionStart + 1; } } removeCharacterOrSelection(); return(true); case Key.Back: if (selectionLength == 0 && state.Keyboard.ControlPressed) { int spacePos = selectionLeft >= 2 ? Math.Max(0, text.LastIndexOf(' ', selectionLeft - 2) + 1) : 0; selectionStart = spacePos; } removeCharacterOrSelection(); return(true); } if (state.Keyboard.ControlPressed) { //handling of function keys switch (args.Key) { case Key.A: selectionStart = 0; selectionEnd = text.Length; cursorAndLayout.Invalidate(); return(true); case Key.C: if (string.IsNullOrEmpty(SelectedText) || !AllowClipboardExport) { return(true); } clipboard?.SetText(SelectedText); return(true); case Key.X: if (string.IsNullOrEmpty(SelectedText) || !AllowClipboardExport) { return(true); } clipboard?.SetText(SelectedText); removeCharacterOrSelection(); return(true); case Key.V: //the text may get pasted into the hidden textbox, so we don't need any direct clipboard interaction here. string pending = textInput?.GetPendingText(); if (string.IsNullOrEmpty(pending)) { pending = clipboard?.GetText(); } insertString(pending); return(true); } return(false); } return(true); }
protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); //have to run this after children flow cursorAndLayout.Refresh(delegate { Placeholder.TextSize = CalculatedTextSize; textUpdateScheduler.Update(); Vector2 cursorPos = Vector2.Zero; if (text?.Length > 0) { cursorPos.X = getPositionAt(selectionLeft); } float cursorPosEnd = getPositionAt(selectionEnd); float cursorWidth = 2; if (selectionLength > 0) { cursorWidth = getPositionAt(selectionRight) - cursorPos.X; } float cursorRelativePositionAxesInBox = (cursorPosEnd - textContainerPosX) / DrawWidth; //we only want to reposition the view when the cursor reaches near the extremities. if (cursorRelativePositionAxesInBox < 0.1 || cursorRelativePositionAxesInBox > 0.9) { textContainerPosX = cursorPosEnd - DrawWidth / 2 + LeftRightPadding * 2; } textContainerPosX = MathHelper.Clamp(textContainerPosX, 0, Math.Max(0, TextFlow.DrawWidth - DrawWidth + LeftRightPadding * 2)); TextContainer.MoveToX(LeftRightPadding - textContainerPosX, 300, EasingTypes.OutExpo); if (HasFocus) { Caret.ClearTransforms(); Caret.MoveTo(cursorPos, 60, EasingTypes.Out); Caret.ScaleTo(new Vector2(cursorWidth, 1), 60, EasingTypes.Out); if (selectionLength > 0) { Caret.FadeTo(0.5f, 200, EasingTypes.Out); Caret.FadeColour(new Color4(249, 90, 255, 255), 200, EasingTypes.Out); } else { Caret.FadeTo(0.7f, 200, EasingTypes.Out); Caret.FadeColour(Color4.White, 200, EasingTypes.Out); Caret.Transforms.Add(new TransformAlpha { StartValue = 0.7f, EndValue = 0.4f, StartTime = Time.Current, EndTime = Time.Current + 500, Easing = EasingTypes.InOutSine, LoopCount = -1, }); } } OnChange?.Invoke(this, textAtLastLayout != text); if (textAtLastLayout.Length == 0 || text.Length == 0) { Placeholder.FadeTo(text.Length == 0 ? 1 : 0, 200); } textAtLastLayout = text; return(cursorPos); }); }