コード例 #1
0
 private static void MoveCaretKeyboardCallBack(InputTextContext textBox)
 {
     if (Keyboard.Instance.KeyDown(Key.Home))
     {
         textBox.SelectIndex = textBox.CaretIndex = 0;
     }
     if (Keyboard.Instance.KeyDown(Key.End))
     {
         textBox.SelectIndex = textBox.CaretIndex = (uint)textBox.Text.Length;
     }
     if (Keyboard.Instance.KeyPressed(Key.Left, true))
     {
         if (textBox.CaretIndex > 0)
         {
             textBox.CaretIndex -= 1;
         }
         if (!Keyboard.Instance.KeyDown(Key.LeftShift))
         {
             textBox.SelectIndex = textBox.CaretIndex;
         }
     }
     else if (Keyboard.Instance.KeyPressed(Key.Right, true))
     {
         if (textBox.CaretIndex < textBox.Text.Length)
         {
             textBox.CaretIndex += 1;
         }
         if (!Keyboard.Instance.KeyDown(Key.LeftShift))
         {
             textBox.SelectIndex = textBox.CaretIndex;
         }
     }
 }
コード例 #2
0
        /// <summary>
        /// Move state according to the command
        /// </summary>
        /// <param name="command">command</param>
        /// <param name="context">context</param>
        /// <returns>true:valid command/false:invalid command</returns>
        public bool MoveNext(string command, InputTextContext context)
        {
            Transition transition = new Transition(CurrentState, command);
            Result     result;

            if (!transitions.TryGetValue(transition, out result))
            {
                return(false);
            }
            CurrentState = result.State;
            result.CallBack?.Invoke(context);
            return(true);
        }
コード例 #3
0
        private static void MoveCaretCallBack(InputTextContext textBox)
        {
            var g = Form.current.uiContext;

            var          rect        = textBox.Rect;
            var          style       = GUIStyle.Basic;
            ITextContext textContext = TextMeshUtil.GetTextContext(textBox.Text, rect.Size, style, GUIState.Normal);

            var  contentRect      = style.GetContentRect(rect);
            var  mousePos         = Mouse.Instance.Position;
            var  offsetOfTextRect = contentRect.TopLeft;
            uint caretIndex;
            bool isInside;

            caretIndex = textContext.XyToIndex(
                (float)(mousePos.X - offsetOfTextRect.X),
                (float)(mousePos.Y - offsetOfTextRect.Y), out isInside);
            textBox.SelectIndex = textBox.CaretIndex = caretIndex;
        }
コード例 #4
0
        public static void DrawTextBox(Rect rect, int id, string text, InputTextContext context, GUIState state)
        {
            GUIContext    g      = Form.current.uiContext;
            WindowManager w      = g.WindowManager;
            Window        window = w.CurrentWindow;

            var d     = window.DrawList;
            var style = GUIStyle.Basic;
            // draw text, selection and caret
            var contentRect = style.GetContentRect(rect);

            d.PushClipRect(contentRect, true);
            if (g.ActiveId == id)
            {
                //Calculate positions and sizes
                var   textContext = TextMeshUtil.GetTextContext(context.Text, rect.Size, style, GUIState.Normal);
                var   offsetOfTextRect = contentRect.TopLeft;
                float pointX, pointY;
                float caretHeight;
                textContext.IndexToXY(context.CaretIndex, false, out pointX, out pointY, out caretHeight);
                var caretTopPoint    = new Point(pointX, pointY);
                var caretBottomPoint = new Point(pointX, pointY + caretHeight);
                caretTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                caretBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);

                byte caretAlpha = context.CaretAlpha;

                // Check if the caret is outside the rect. If so, move the text so the caret is always shown. FIXME this should be done in TextBoxBehaviour
                var caretX = caretTopPoint.X;
                if (caretX < contentRect.X || caretX > contentRect.Right)
                {
                    var offsetX = -(caretX - contentRect.Width - rect.X);
                    contentRect.Offset(offsetX, 0);
                    caretTopPoint.Offset(offsetX, 0);
                    caretBottomPoint.Offset(offsetX, 0);
                }

                //Draw text
                d.DrawText(contentRect, context.Text, style, GUIState.Normal);

                //Draw selection rect

                /*
                 * Note: Design
                 *
                 *  left bound            right bound
                 *     ↓                        ↓
                 *     |      A-----------------+
                 *     |      |CONTENT_CONTENT_C| => Line 1 => rect1
                 *     +------B                 |
                 *     |ONTENT_CONTENT_CONTENT_C| => Line 2 (represents inner lines) => rect2
                 *     |                 C------+
                 *     |ONTENT_CONTENT_CO| => Line 3 => rect3
                 *     +-----------------D
                 *
                 * left bound = l
                 * right bound = r
                 */
                if (context.SelectIndex != context.CaretIndex)
                {
                    float selectPointX, selectPointY;
                    textContext.IndexToXY(context.SelectIndex, false, out selectPointX, out selectPointY, out float dummyHeight);
                    var selectTopPoint    = new Point(selectPointX, selectPointY);
                    var selectBottomPoint = new Point(selectPointX, selectPointY + caretHeight);
                    selectTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                    selectBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                    var delta = Math.Abs(selectTopPoint.Y - caretTopPoint.Y);
                    if (delta < caretHeight) // single line
                    {
                        var selectionRect = new Rect(
                            new Point(pointX, pointY),
                            new Point(selectPointX, selectPointY + caretHeight));
                        selectionRect.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                        d.AddRectFilled(selectionRect.Min, selectionRect.Max, Color.Argb(100, 10, 102, 214));
                    }
                    else//mutiple line
                    {
                        var l = contentRect.Left;
                        var r = contentRect.Right;

                        Point A;
                        Point B;
                        Point C;
                        Point D;

                        if (selectTopPoint.Y > caretTopPoint.Y)
                        {
                            A = caretTopPoint;
                            B = caretBottomPoint;
                            C = selectTopPoint;
                            D = selectBottomPoint;
                        }
                        else
                        {
                            A = selectTopPoint;
                            B = selectBottomPoint;
                            C = caretTopPoint;
                            D = caretBottomPoint;
                        }


                        // Line 1
                        var rect1 = new Rect(A, r - A.X, caretHeight);
                        d.AddRectFilled(rect1, Color.Argb(100, 10, 102, 214), 12);
                        d.AddRect(rect1.Min, rect1.Max, Color.White, 12, 15, 2);

                        // Line 2
                        var rect2 = new Rect(new Point(l, B.Y), new Point(r, C.Y));
                        if (rect2.Height > 0.5 * caretHeight)//TODO There should more a more reasonable way to detect this: If it only has two lines, we don't draw the inner rectangle.
                        {
                            d.AddRectFilled(rect2, Color.Argb(100, 10, 102, 214), 12);
                            d.AddRect(rect2.Min, rect2.Max, Color.White, 12, 15, 2);
                        }

                        // Line 3
                        var rect3 = new Rect(new Point(l, C.Y), D);
                        d.AddRectFilled(rect3, Color.Argb(100, 10, 102, 214), 12);
                        d.AddRect(rect3.Min, rect3.Max, Color.White, 12, 15, 2);
                    }
                }

                //Draw caret
                d.PathMoveTo(caretTopPoint);
                d.PathLineTo(caretBottomPoint);
                d.PathStroke(Color.Argb(caretAlpha, 0, 0, 0), false, 2);
            }
            else
            {
                d.DrawText(contentRect, text, style, GUIState.Normal);
            }
            d.PopClipRect();

            // draw the box
            {
                d.AddRect(rect.Min, rect.Max, style.GetBorderColor(state));
            }
        }
コード例 #5
0
        public static string TextBoxBehavior(int id, Rect rect, string text, out bool hovered, out bool active, out InputTextContext context, InputTextFlags flags = 0, Func <char, bool> checker = null)
        {
            GUIContext g = Form.current.uiContext;

            active  = false;
            hovered = g.IsHovered(rect, id);
            if (hovered)
            {
                g.SetHoverID(id);

                if (Mouse.Instance.LeftButtonPressed)
                {
                    g.SetActiveID(id);
                }
            }
            else
            {
                if (Mouse.Instance.LeftButtonPressed)
                {
                    if (g.ActiveId == id)
                    {
                        g.SetActiveID(0);
                    }
                }
            }

            if (g.ActiveId == id && g.InputTextState.inputTextContext.Id != id)     //editing text box changed to TextBox<id>
            {
                g.InputTextState.stateMachine.CurrentState = "Active";              //reset state
                g.InputTextState.inputTextContext          = new InputTextContext() //reset input text context data
                {
                    Id            = id,
                    CaretIndex    = 0,
                    SelectIndex   = 0,
                    Selecting     = false,
                    CaretPosition = Point.Zero,
                    Flags         = flags,
                    Checker       = checker,
                    Rect          = rect,
                    Text          = text
                };
            }

            context = null;
            if (g.ActiveId == id)
            {
                active = true;

                var stateMachine = g.InputTextState.stateMachine;
                context      = g.InputTextState.inputTextContext;
                context.Rect = rect;

                // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
                // Down the line we should have a cleaner library-wide concept of Selected vs Active.
                g.ActiveIdAllowOverlap = !Mouse.Instance.LeftButtonPressed;

#if INSPECT_STATE
                var A = stateMachine.CurrentState;
#endif
                if (Mouse.Instance.LeftButtonPressed)
                {
                    stateMachine.MoveNext(TextBoxCommand.MoveCaret, context);
                }

                if (hovered && Mouse.Instance.LeftButtonState == KeyState.Down &&
                    stateMachine.CurrentState != TextBoxState.ActiveSelecting)
                {
                    stateMachine.MoveNext(TextBoxCommand.MoveCaret, context);
                    stateMachine.MoveNext(TextBoxCommand.BeginSelect, context);
                }

                if (hovered && Mouse.Instance.LeftButtonState == KeyState.Up)
                {
                    stateMachine.MoveNext(TextBoxCommand.EndSelect, context);
                }

                if (stateMachine.CurrentState == TextBoxState.Active)
                {
                    stateMachine.MoveNext(TextBoxCommand.DoEdit, context);
                }
                if (stateMachine.CurrentState == TextBoxState.ActiveSelecting)
                {
                    stateMachine.MoveNext(TextBoxCommand.DoSelect, context);
                }
                stateMachine.MoveNext(TextBoxCommand.MoveCaretKeyboard, context);
#if INSPECT_STATE
                var B = stateMachine.CurrentState;
                Debug.WriteLineIf(A != B,
                                  string.Format("TextBox<{0}> {1}=>{2} CaretIndex: {3}, SelectIndex: {4}",
                                                id, A, B, context.CaretIndex, context.SelectIndex));
#endif
                return(context.Text);
            }
            return(text);
        }
コード例 #6
0
 public InputTextState()
 {
     stateMachine     = new StateMachineEx(TextBoxState.Normal, states, callBacks);
     inputTextContext = new InputTextContext();
 }
コード例 #7
0
        private static void DoEditCallBack(InputTextContext textBox)
        {
            if (CurrentOS.IsDesktopPlatform)
            {
                var CaretIndex  = textBox.CaretIndex;
                var SelectIndex = textBox.SelectIndex;

                string textBeforeCaret;
                //Input characters
                if (Ime.ImeBuffer.Count != 0)
                {
                    char[] textSequence = ApplyFilter(Ime.ImeBuffer, textBox.Flags, textBox.Checker);
                    var    inputText    = new string(textSequence);
                    if (CaretIndex != SelectIndex) //Replace selected text with inputText
                    {
                        //TODO check whether convert int and uint back and forth is appropriate
                        var minIndex = (int)Math.Min(CaretIndex, SelectIndex);
                        var maxIndex = (int)Math.Max(CaretIndex, SelectIndex);

                        textBox.Text = textBox.Text.Substring(0, minIndex) + inputText + textBox.Text.Substring(maxIndex);
                        textBox.MoveCaret((uint)minIndex);
                        textBeforeCaret = textBox.Text.Substring(0, minIndex) + inputText;
                    }
                    else //Insert inputText into caret position
                    {
                        if (textBox.Text.Length == 0)
                        {
                            textBox.Text    = inputText;
                            textBeforeCaret = textBox.Text;
                        }
                        else
                        {
                            textBox.Text    = textBox.Text.Substring(0, (int)CaretIndex) + inputText + textBox.Text.Substring((int)CaretIndex);
                            textBeforeCaret = textBox.Text.Substring(0, (int)CaretIndex) + inputText;
                        }
                    }
                    textBox.MoveCaret((uint)textBeforeCaret.Length);
                    Ime.ImeBuffer.Clear();
                }
                //Backspace, delete one character before the caret
                else if (Keyboard.Instance.KeyPressed(Key.Back, true))
                {
                    if (CaretIndex != SelectIndex)
                    {
                        var minIndex = (int)Math.Min(CaretIndex, SelectIndex);
                        var maxIndex = (int)Math.Max(CaretIndex, SelectIndex);

                        textBox.Text = textBox.Text.Substring(0, minIndex) + textBox.Text.Substring(maxIndex);
                        textBox.MoveCaret((uint)minIndex);
                        textBeforeCaret = textBox.Text.Substring(0, minIndex);
                        textBox.MoveCaret((uint)textBeforeCaret.Length);
                    }
                    else if (CaretIndex > 0)
                    {
                        var newText = textBox.Text.Remove((int)(CaretIndex - 1), 1);
                        if (CaretIndex == 0)
                        {
                            textBeforeCaret = "";
                        }
                        else
                        {
                            textBeforeCaret = textBox.Text.Substring(0, (int)(CaretIndex - 1));
                        }
                        textBox.MoveCaret((uint)textBeforeCaret.Length);
                        textBox.Text = newText;
                    }
                }
                //Delete, delete one character after the caret
                else if (Keyboard.Instance.KeyPressed(Key.Delete, true))
                {
                    if (CaretIndex != SelectIndex)
                    {
                        var minIndex = (int)Math.Min(CaretIndex, SelectIndex);
                        var maxIndex = (int)Math.Max(CaretIndex, SelectIndex);

                        textBox.Text = textBox.Text.Substring(0, minIndex) + textBox.Text.Substring(maxIndex);
                        textBox.MoveCaret((uint)minIndex);
                        textBeforeCaret = textBox.Text.Substring(0, minIndex);
                        textBox.MoveCaret((uint)textBeforeCaret.Length);
                    }
                    else if (CaretIndex < textBox.Text.Length)
                    {
                        textBox.Text = textBox.Text.Remove((int)CaretIndex, 1);
                    }
                }
            }
            else
            {
                if (keyboardTask == null)
                {
                    keyboardTask = Keyboard.Show(textBox.Text);
                }
                else
                {
                    if (keyboardTask.IsCompleted)
                    {
                        var inputText = keyboardTask.Result;
                        textBox.Text = inputText;
                        keyboardTask = null;

                        // deactive the textbox we are editing
                        var g = Form.current.uiContext;
                        g.SetActiveID(0);
                    }
                }
            }
        }
コード例 #8
0
ファイル: TextBox.cs プロジェクト: ibrahim-elsakka/ImGui-1
        public static void DrawTextBox(Node node, int id, string text, InputTextContext context, GUIState state)
        {
            GUIContext g = Form.current.uiContext;

            Rect rect  = node.Rect;
            var  d     = node.RenderOpen();
            var  style = node.RuleSet;
            // draw text, selection and caret
            var contentRect = node.ContentRect;

            // clip text rendering to content-box
            //d.PushClip(contentRect);
            if (g.ActiveId == id)
            {
                //Calculate positions and sizes
                var   textContext = TextMeshUtil.GetTextContext(context.Text, rect.Size, style, GUIState.Normal);
                var   offsetOfTextRect = contentRect.TopLeft;
                float pointX, pointY;
                float caretHeight;
                textContext.IndexToXY(context.CaretIndex, false, out pointX, out pointY, out caretHeight);
                var caretTopPoint    = new Point(pointX, pointY);
                var caretBottomPoint = new Point(pointX, pointY + caretHeight);
                caretTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                caretBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);

                byte caretAlpha = context.CaretAlpha;

                // Check if the caret is outside the rect. If so, move the text so the caret is always shown. FIXME this should be done in TextBoxBehaviour
                var caretX = caretTopPoint.X;
                if (caretX < contentRect.X || caretX > contentRect.Right)
                {
                    var offsetX = -(caretX - contentRect.Width - rect.X);
                    contentRect.Offset(offsetX, 0);
                    caretTopPoint.Offset(offsetX, 0);
                    caretBottomPoint.Offset(offsetX, 0);
                }

                //Draw text
                d.DrawText(style, context.Text, contentRect);

                //Draw selection rect

                /*
                 * Note: Design
                 *
                 *  left bound            right bound
                 *     ↓                        ↓
                 *     |      A-----------------+
                 *     |      |CONTENT_CONTENT_C| => Line 1 => rect1
                 *     +------B                 |
                 *     |ONTENT_CONTENT_CONTENT_C| => Line 2 (represents inner lines) => rect2
                 *     |                 C------+
                 *     |ONTENT_CONTENT_CO| => Line 3 => rect3
                 *     +-----------------D
                 *
                 * left bound = l
                 * right bound = r
                 */
                if (context.SelectIndex != context.CaretIndex)
                {
                    float selectPointX, selectPointY;
                    textContext.IndexToXY(context.SelectIndex, false, out selectPointX, out selectPointY, out float dummyHeight);
                    var selectTopPoint    = new Point(selectPointX, selectPointY);
                    var selectBottomPoint = new Point(selectPointX, selectPointY + caretHeight);
                    selectTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                    selectBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                    var delta = Math.Abs(selectTopPoint.Y - caretTopPoint.Y);
                    if (delta < caretHeight) // single line
                    {
                        var selectionRect = new Rect(
                            new Point(pointX, pointY),
                            new Point(selectPointX, selectPointY + caretHeight));
                        selectionRect.Offset(offsetOfTextRect.X, offsetOfTextRect.Y);
                        d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, selectionRect);
                    }
                    else//multiple lines
                    {
                        var l = contentRect.Left;
                        var r = contentRect.Right;

                        Point A;
                        Point B;
                        Point C;
                        Point D;

                        if (selectTopPoint.Y > caretTopPoint.Y)
                        {
                            A = caretTopPoint;
                            B = caretBottomPoint;
                            C = selectTopPoint;
                            D = selectBottomPoint;
                        }
                        else
                        {
                            A = selectTopPoint;
                            B = selectBottomPoint;
                            C = caretTopPoint;
                            D = caretBottomPoint;
                        }


                        // Line 1
                        var rect1 = new Rect(A, r - A.X, caretHeight);
                        d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, rect1);
                        d.DrawRectangle(null, new Pen(Color.White, 2), rect1);

                        // Line 2
                        var rect2 = new Rect(new Point(l, B.Y), new Point(r, C.Y));
                        if (rect2.Height > 0.5 * caretHeight)//TODO There should more a more reasonable way to detect this: If it only has two lines, we don't draw the inner rectangle.
                        {
                            d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, rect2);
                            d.DrawRectangle(null, new Pen(Color.White, 2), rect2);
                        }

                        // Line 3
                        var rect3 = new Rect(new Point(l, C.Y), D);
                        d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, rect3);
                        d.DrawRectangle(null, new Pen(Color.White, 2), rect3);
                    }
                }

                //Draw caret
                d.DrawLine(new Pen(Color.Argb(caretAlpha, 0, 0, 0), 2), caretTopPoint, caretBottomPoint);
            }
            else
            {
                d.DrawText(style, text, contentRect);
            }
            //d.Pop();
            d.Close();
        }