Exemple #1
0
        internal override ConsoleControl GetContent()
        {
            ConsolePanel content = new ConsolePanel();

            content.Width  = ConsoleApp.Current.LayoutRoot.Width / 2;
            content.Height = ConsoleApp.Current.LayoutRoot.Height / 2;

            Label messageLabel = content.Add(new Label()
            {
                Text = Message, X = 2, Y = 2
            });

            TextBox = TextBox ?? new TextBox()
            {
                Foreground = ConsoleColor.Black, Background = ConsoleColor.White
            };
            content.Add(TextBox).CenterHorizontally();
            TextBox.Y = 4;

            content.SynchronizeForLifetime(nameof(content.Bounds), () => { TextBox.Width = content.Width - 4; }, content);

            TextBox.KeyInputReceived.SubscribeForLifetime((k) =>
            {
                if (k.Key == ConsoleKey.Enter)
                {
                    Dialog.Dismiss();
                }
            }, TextBox);

            TextBox.AddedToVisualTree.SubscribeOnce(() => TextBox.Application.QueueAction(() => TextBox.TryFocus()));
            return(content);
        }
Exemple #2
0
        internal override ConsoleControl GetContent()
        {
            if (Options == null || Options.Count == 0)
            {
                throw new ArgumentException("You need to specify at least one button");
            }

            if (Mode == DialogButtonsPresentationMode.Buttons)
            {
                ConsolePanel    dialogContent = new ConsolePanel();
                ScrollablePanel messagePanel  = dialogContent.Add(new ScrollablePanel()).Fill(padding: new Thickness(0, 0, 1, 3));
                Label           messageLabel  = messagePanel.ScrollableContent.Add(new Label()
                {
                    Mode = LabelRenderMode.MultiLineSmartWrap, Text = Message
                }).FillHorizontally(padding: new Thickness(3, 3, 0, 0));
                StackPanel buttonPanel = dialogContent.Add(new StackPanel()
                {
                    Margin = 1, Height = 1, Orientation = Orientation.Horizontal
                }).FillHorizontally(padding: new Thickness(1, 0, 0, 0)).DockToBottom(padding: 1);

                foreach (var option in Options)
                {
                    var    myOption = option;
                    Button b        = new Button()
                    {
                        Text = option.DisplayText
                    };
                    b.Pressed.SubscribeOnce(() =>
                    {
                        SelectedOption = myOption;
                        Dialog.Dismiss();
                    });
                    buttonPanel.Controls.Add(b);
                }

                buttonPanel.Controls.Last().AddedToVisualTree.SubscribeOnce(() => buttonPanel.Application.QueueAction(() => { buttonPanel.Controls.Last().TryFocus(); }));
                return(dialogContent);
            }
            else
            {
                Grid optionsGrid = new Grid(Options.Select(o => o as object).ToList());
                optionsGrid.MoreDataMessage  = "More options below".ToYellow();
                optionsGrid.EndOfDataMessage = "End of menu";

                optionsGrid.VisibleColumns.Remove(optionsGrid.VisibleColumns.Where(v => v.ColumnName.ToString() == nameof(DialogOption.Id)).Single());
                optionsGrid.VisibleColumns[0].WidthPercentage   = 1;
                optionsGrid.VisibleColumns[0].ColumnDisplayName = Message.IsUnstyled ? Message.ToYellow() : Message;
                optionsGrid.VisibleColumns[0].OverflowBehavior  = new TruncateOverflowBehavior();
                (optionsGrid.VisibleColumns[0].OverflowBehavior as TruncateOverflowBehavior).ColumnWidth = 0;
                optionsGrid.SelectedItemActivated += () =>
                {
                    this.SelectedOption = optionsGrid.SelectedItem as DialogOption;
                    Dialog.Dismiss();
                };

                optionsGrid.AddedToVisualTree.SubscribeOnce(() => optionsGrid.Application.QueueAction(() => { optionsGrid.TryFocus(); }));

                return(optionsGrid);
            }
        }
Exemple #3
0
        public static void ShowRichTextInput(ConsoleString message, Action <ConsoleString> resultCallback, Action cancelCallback = null, bool allowEscapeToCancel = true, int maxHeight = 12, TextBox inputBox = null, ConsoleString initialValue = null)
        {
            ConsoleApp.AssertAppThread();
            if (ConsoleApp.Current == null)
            {
                throw new InvalidOperationException("There is no console app running");
            }

            ConsolePanel content = new ConsolePanel();

            content.Width  = ConsoleApp.Current.LayoutRoot.Width / 2;
            content.Height = ConsoleApp.Current.LayoutRoot.Height / 2;

            var dialog = new Dialog(content);

            dialog.MaxHeight           = maxHeight;
            dialog.AllowEscapeToCancel = allowEscapeToCancel;
            dialog.Cancelled.SubscribeForLifetime(() => { if (cancelCallback != null)
                                                          {
                                                              cancelCallback();
                                                          }
                                                  }, dialog);

            Label messageLabel = content.Add(new Label()
            {
                Text = message, X = 2, Y = 2
            });

            if (inputBox == null)
            {
                inputBox = new TextBox()
                {
                    Foreground = ConsoleColor.Black, Background = ConsoleColor.White
                };
            }

            if (initialValue != null)
            {
                inputBox.Value = initialValue;
            }

            content.Add(inputBox).CenterHorizontally();
            inputBox.Y = 4;

            content.SynchronizeForLifetime(nameof(Bounds), () => { inputBox.Width = content.Width - 4; }, content);

            inputBox.KeyInputReceived.SubscribeForLifetime((k) =>
            {
                if (k.Key == ConsoleKey.Enter)
                {
                    ConsoleApp.Current.LayoutRoot.Controls.Remove(dialog);
                    resultCallback(inputBox.Value);
                }
            }, inputBox);

            ConsoleApp.Current.LayoutRoot.Controls.Add(dialog);
            inputBox.TryFocus();
        }
Exemple #4
0
        private static void ParsePanel(ParserContext context, ConsolePanel panel)
        {
            var myElement = context.CurrentElement;

            context.CurrentControl = panel;
            ParseControlAttributes(panel, context);

            foreach (var childElement in context.CurrentElement.Elements)
            {
                context.CurrentElement = childElement;
                var childControl = CreateControl(context);
                context.CurrentControl = childControl;
                panel.Add(childControl);

                if (childControl is ConsolePanel)
                {
                    ParsePanel(context, childControl as ConsolePanel);
                }
                else
                {
                    ParseControlAttributes(childControl, context);
                }
            }

            context.CurrentElement = myElement;
            context.CurrentControl = panel;
        }
Exemple #5
0
        private void SetupMinimumSizeExperience()
        {
            ConsolePanel   shield = null;
            ConsoleControl min    = null;

            min = ProtectedPanel.Add(new MinimumSizeEnforcerPanel(new MinimumSizeEnforcerPanelOptions()
            {
                MinWidth            = MinWidth,
                MinHeight           = MinHeight,
                OnMinimumSizeNotMet = () =>
                {
                    if (min == null)
                    {
                        return;
                    }
                    min.IsVisible = false;
                    shield        = ProtectedPanel.Add(new ConsolePanel()
                    {
                        Background = Foreground
                    }).Fill();
                    var date = new DateTime(Options.Year, Options.Month, 1);
                    shield.Add(new Label()
                    {
                        Text = date.ToString("Y").ToConsoleString(Background, Foreground)
                    }).CenterBoth();
                },
                OnMinimumSizeMet = () => shield?.Dispose()
            })).Fill();
        }
        /// <summary>
        /// Shows a dialog on top of the current ConsoleApp.
        /// </summary>
        /// <param name="contentFactory">A callback where you are given a handle that can be used to configure the dialog.
        /// It also has a method that lets you close the dialog. This callback should return the dialog content.</param>
        public static async void Show(Func <DialogHandle, ConsolePanel> contentFactory, ConsolePanel parent = null, bool pushPop = true)
        {
            parent = parent ?? ConsoleApp.Current.LayoutRoot;
            using (var dialogLt = new Lifetime())
            {
                if (pushPop)
                {
                    ConsoleApp.Current.FocusManager.Push();
                    dialogLt.OnDisposed(ConsoleApp.Current.FocusManager.Pop);
                }
                var handle  = new DialogHandle();
                var content = contentFactory(handle);
                content.IsVisible = false;
                var dialogContainer = parent.Add(new BorderPanel(content)
                {
                    ZIndex = int.MaxValue, BorderColor = handle.BorderColor, Background = content.Background, Width = 1, Height = 1
                }).CenterBoth();
                await Forward(300, dialogLt, percentage => dialogContainer.Width  = Math.Max(1, (int)Math.Round((4 + content.Width) * percentage)));
                await Forward(200, dialogLt, percentage => dialogContainer.Height = Math.Max(1, (int)Math.Round((2 + content.Height) * percentage)));

                content.IsVisible = true;
                await handle.CallerLifetime.AwaitEndOfLifetime();

                content.IsVisible = false;
                await Reverse(150, dialogLt, percentage => dialogContainer.Height = Math.Max(1, (int)Math.Floor((2 + content.Height) * percentage)));

                await Task.Delay(200);
                await Reverse(200, dialogLt, percentage => dialogContainer.Width = Math.Max(1, (int)Math.Round((4 + content.Width) * percentage)));

                dialogContainer.Dispose();
            }
        }
Exemple #7
0
        public static void ShowMessage(ConsoleString message, Action <DialogButton> resultCallback, bool allowEscapeToCancel = true, int maxHeight = 10, params DialogButton [] buttons)
        {
            ConsoleApp.AssertAppThread();
            if (buttons.Length == 0)
            {
                throw new ArgumentException("You need to specify at least one button");
            }

            ConsolePanel dialogContent = new ConsolePanel();

            Dialog dialog = new Dialog(dialogContent);

            dialog.MaxHeight           = maxHeight;
            dialog.AllowEscapeToCancel = allowEscapeToCancel;
            dialog.Cancelled.SubscribeForLifetime(() => { resultCallback(null); }, dialog);

            ScrollablePanel messagePanel = dialogContent.Add(new ScrollablePanel()).Fill(padding: new Thickness(0, 0, 1, 3));
            Label           messageLabel = messagePanel.ScrollableContent.Add(new Label()
            {
                Mode = LabelRenderMode.MultiLineSmartWrap, Text = message
            }).FillHorizontally(padding: new Thickness(3, 3, 0, 0));

            StackPanel buttonPanel = dialogContent.Add(new StackPanel()
            {
                Margin = 1, Height = 1, Orientation = Orientation.Horizontal
            }).FillHorizontally(padding: new Thickness(1, 0, 0, 0)).DockToBottom(padding: 1);

            Button firstButton = null;

            foreach (var buttonInfo in buttons)
            {
                var    myButtonInfo = buttonInfo;
                Button b            = new Button()
                {
                    Text = buttonInfo.DisplayText
                };
                b.Pressed.SubscribeForLifetime(() =>
                {
                    ConsoleApp.Current.LayoutRoot.Controls.Remove(dialog);
                    resultCallback(myButtonInfo);
                }, dialog);
                buttonPanel.Controls.Add(b);
                firstButton = firstButton ?? b;
            }
            ConsoleApp.Current.LayoutRoot.Controls.Add(dialog);
        }
Exemple #8
0
        public static ConsolePanel CreatePanelWithCenteredLabel(ConsoleString str)
        {
            var ret = new ConsolePanel();

            ret.Add(new Label()
            {
                Text = str
            }).CenterBoth();
            return(ret);
        }
 private void ComposeLoadingUX()
 {
     loadingPanel = ProtectedPanel.Add(new ConsolePanel()
     {
         ZIndex = int.MaxValue
     }).Fill();
     loadingPanel.Add(new Label()
     {
         Text = Options.LoadingMessage
     }).CenterBoth();
 }
Exemple #10
0
        /// <summary>
        /// create content panels for each cell so that other pieces of code don't need to worry about
        /// the grid layout implementation
        /// </summary>
        private void InitCellContainers()
        {
            for (var x = 0; x < gridLayout.Options.Columns.Count; x++)
            {
                // start at 1 since the first row is for day of week labels
                for (var y = 1; y < gridLayout.Options.Rows.Count; y++)
                {
                    var key        = GetKeyForCoordinates(y, x);
                    var outerPanel = new ConsolePanel()
                    {
                        Background = Foreground
                    };
                    var innerPanel = outerPanel.Add(new ConsolePanel()
                    {
                        Background = Foreground
                    }).Fill(padding: new Thickness(x == 0 ? 2 : 0, 1, 0, 1));
                    dateCells.Add(key, innerPanel);
                    gridLayout.Add(outerPanel, x, y);

                    // the first row gets an outer border
                    if (x == 0)
                    {
                        outerPanel.Add(new ConsolePanel()
                        {
                            Width = 2, Background = Foreground
                        }).FillVertically().DockToLeft();
                    }

                    outerPanel.Add(new ConsolePanel()
                    {
                        Width = 2, Background = Foreground
                    }).FillVertically().DockToRight();
                    outerPanel.Add(new ConsolePanel()
                    {
                        Height = 1, Background = Foreground
                    }).FillHorizontally().DockToBottom();
                }
            }
            gridLayout.RefreshLayout();
        }
Exemple #11
0
 private void ComposeLoadingUX()
 {
     using (var modifyLock = Unlock())
     {
         loadingPanel = Add(new ConsolePanel()
         {
             ZIndex = int.MaxValue
         }).Fill();
         loadingPanel.Add(new Label()
         {
             Text = Options.LoadingMessage
         }).CenterBoth();
     }
 }
        public void ConsoleAppLifecycleTestBasic()
        {
            ConsoleProvider.Current = new CliUnitTestConsole();
            ConsoleApp app = new ConsoleApp(0, 0, 80, 10);

            int addCounter = 0, removeCounter = 0;

            app.ControlAdded.SubscribeForLifetime((c) => { addCounter++; }, app.LifetimeManager);
            app.ControlRemoved.SubscribeForLifetime((c) => { removeCounter++; }, app.LifetimeManager);
            app.LayoutRoot.Id = "LayoutRoot";
            ConsolePanel panel = app.LayoutRoot.Add(new ConsolePanel() { Id = "First panel" });
            // direct child
            Assert.AreEqual(1, addCounter);
            Assert.AreEqual(0, removeCounter);

            var button = panel.Add(new Button() { Id = "Button on first panel" });

            // grandchild
            Assert.AreEqual(2, addCounter);
            Assert.AreEqual(0, removeCounter);

            var innerPanel = new ConsolePanel() { Id="InnerPanel" };
            var innerInnerPanel = innerPanel.Add(new ConsolePanel() { Id = "Inner Inner Panel"});

            // no change since not added to the app yet
            Assert.AreEqual(2, addCounter);
            Assert.AreEqual(0, removeCounter);

            panel.Add(innerPanel);

            // both child and grandchild found on add
            Assert.AreEqual(4, addCounter);
            Assert.AreEqual(0, removeCounter);

            // remove a nested child
            innerPanel.Controls.Remove(innerInnerPanel);
            Assert.AreEqual(4, addCounter);
            Assert.AreEqual(1, removeCounter);

            app.LayoutRoot.Controls.Clear();
            Assert.AreEqual(4, addCounter);
            Assert.AreEqual(4, removeCounter);
        }
Exemple #13
0
        private void PopulateDayOfWeekLabels()
        {
            var dayLabels = new List <Label>();

            for (var day = 0; day < 7; day++)
            {
                var dayOfWeek = (DayOfWeek)day;
                var panel     = new ConsolePanel();
                panel.Background = Foreground;
                var label = panel.Add(new Label()
                {
                    Mode = LabelRenderMode.ManualSizing, Background = Foreground
                }).FillHorizontally(padding: new Thickness(day == 0 ? 2 : 0, 0, 0, 0)).CenterVertically();
                dayLabels.Add(label);
                gridLayout.Add(panel, day, 0);
                Func <int> smallestDayLabelWidth = () => dayLabels.Select(l => l.Width).Min();
                this.SynchronizeForLifetime(nameof(Bounds), () => label.Text = GetDayOfWeekDisplay(dayOfWeek, smallestDayLabelWidth()), this);
            }
        }
Exemple #14
0
        private void ComposePager()
        {
            pagerContainer = gridLayout.Add(new ConsolePanel(), 0, Height - 1, gridLayout.Options.Columns.Count, 1);
            recomposableControls.Add(pagerContainer);
            pager           = pagerContainer.Add(new RandomAccessPager()).CenterHorizontally();
            pager.IsVisible = Options.ShowPager;
            pager.FirstPageButton.Pressed.SubscribeForLifetime(FirstPageClicked.Fire, pager);
            pager.PreviousPageButton.Pressed.SubscribeForLifetime(PreviousPageClicked.Fire, pager);
            pager.NextPageButton.Pressed.SubscribeForLifetime(NextPageClicked.Fire, pager);
            pager.LastPageButton.Pressed.SubscribeForLifetime(LastPageClicked.Fire, pager);
            pager.FirstPageButton.CanFocus    = Options.PagerState.CanGoBackwards;
            pager.PreviousPageButton.CanFocus = Options.PagerState.CanGoBackwards;
            pager.NextPageButton.CanFocus     = Options.PagerState.CanGoForwards;
            pager.LastPageButton.CanFocus     = Options.PagerState.CanGoForwards;
            pager.CurrentPageLabel.Text       = Options.PagerState.CurrentPageLabelValue;
            if (Options.PagerState.AllowRandomAccess == false)
            {
                pager.Controls.Remove(pager.LastPageButton);
            }

            if (firstButtonFocused)
            {
                pager.FirstPageButton.TryFocus();
            }
            else if (previousButtonFocused)
            {
                pager.PreviousPageButton.TryFocus();
            }
            else if (nextButtonFocused)
            {
                pager.NextPageButton.TryFocus();
            }
            else if (lastButtonFocused)
            {
                pager.LastPageButton.TryFocus();
            }
        }
Exemple #15
0
        private void InitFramePanel()
        {
            // vertical divider
            framePanel.Add(new ConsolePanel()
            {
                Width = 1, Background = RGB.White
            }).DockToRight().FillVertically();

            var options = new ListGridOptions <InMemoryConsoleBitmapFrame>()
            {
                DataSource = new SyncList <InMemoryConsoleBitmapFrame>(animation.Frames),
                Columns    = new List <ListGridColumnDefinition <InMemoryConsoleBitmapFrame> >()
                {
                    new ListGridColumnDefinition <InMemoryConsoleBitmapFrame>()
                    {
                        Width     = framePanel.Width - 2,
                        Type      = GridValueType.Pixels,
                        Formatter = f => new Label()
                        {
                            Text = $"Frame {animation.Frames.IndexOf(f)+1}".ToWhite()
                        },
                        Header = "Frame".ToYellow(),
                    }
                },
                ShowColumnHeaders            = false,
                ShowPager                    = false,
                EnablePagerKeyboardShortcuts = false,
            };

            frameList = framePanel.Add(new ListGrid <InMemoryConsoleBitmapFrame>(options)).Fill(padding: new Thickness(1, 1, 0, 0));

            refreshed.SubscribeForLifetime(() =>
            {
                frameList.Refresh();
            }, frameList);

            BorderPanel fakeDialog      = null;
            Label       fakeDialogLabel = null;

            frameList.SelectionChanged.SubscribeForLifetime(() =>
            {
                CurrentFrameIndex = frameList.SelectedRowIndex;
                Refresh();
                if (fakeDialog != null)
                {
                    fakeDialog.X         = frameList.AbsoluteX + frameList.Width - 2;
                    fakeDialog.Y         = frameList.Y + 1 + frameList.SelectedRowIndex;
                    fakeDialogLabel.Text = FormatTimespanForFramePopup(CurrentFrame.FrameTime);
                }
            }, frameList);

            frameList.Focused.SubscribeForLifetime(() =>
            {
                var fakeDialogContent = new ConsolePanel()
                {
                    Background = TimespanPopupBGColor
                };

                fakeDialog             = ConsoleApp.Current.LayoutRoot.Add(new BorderPanel(fakeDialogContent));
                fakeDialog.BorderColor = RGB.Blue;
                fakeDialog.Width       = 30;
                fakeDialog.Height      = 5;
                fakeDialog.X           = frameList.AbsoluteX + frameList.Width - 2;
                fakeDialog.Y           = frameList.Y + 1 + frameList.SelectedRowIndex;
                fakeDialogContent.Fill();

                fakeDialogLabel = fakeDialogContent.Add(new Label()
                {
                    Text = FormatTimespanForFramePopup(CurrentFrame.FrameTime)
                }).CenterBoth();

                refreshed.SubscribeForLifetime(() =>
                {
                    fakeDialogLabel.Text = FormatTimespanForFramePopup(CurrentFrame.FrameTime);
                }, fakeDialogLabel);

                ConsoleApp.Current.FocusManager.GlobalKeyHandlers.PushForLifetime(ConsoleKey.OemPlus, null, () =>
                {
                    undoRedo.Do(new ShiftTimeStampForwardAction(this, CurrentFrameIndex, 50));
                }, fakeDialog);

                ConsoleApp.Current.FocusManager.GlobalKeyHandlers.PushForLifetime(ConsoleKey.OemMinus, null, () =>
                {
                    undoRedo.Do(new ShiftTimeStampBackwardAction(this, CurrentFrameIndex, 50));
                }, fakeDialog);

                ConsoleApp.Current.FocusManager.GlobalKeyHandlers.PushForLifetime(ConsoleKey.OemPlus, ConsoleModifiers.Shift, () =>
                {
                    undoRedo.Do(new ShiftTimeStampForwardAction(this, CurrentFrameIndex, 10));
                }, fakeDialog);

                ConsoleApp.Current.FocusManager.GlobalKeyHandlers.PushForLifetime(ConsoleKey.OemMinus, ConsoleModifiers.Shift, () =>
                {
                    undoRedo.Do(new ShiftTimeStampBackwardAction(this, CurrentFrameIndex, 10));
                }, fakeDialog);
            }, frameList);

            frameList.Unfocused.SubscribeForLifetime(() =>
            {
                fakeDialog?.Dispose();
                fakeDialogLabel = null;
                fakeDialog      = null;
            }, frameList);
        }
Exemple #16
0
        public static void ShowRichTextInput(ConsoleString message, Action<ConsoleString> resultCallback, Action cancelCallback = null, bool allowEscapeToCancel = true, int maxHeight = 12, TextBox inputBox = null)
        {
            if (ConsoleApp.Current == null)
            {
                throw new InvalidOperationException("There is no console app running");
            }

            ConsolePanel content = new ConsolePanel();

            content.Width = ConsoleApp.Current.LayoutRoot.Width / 2;
            content.Height = ConsoleApp.Current.LayoutRoot.Height / 2;

            var dialog = new Dialog(content);
            dialog.MaxHeight = maxHeight;
            dialog.AllowEscapeToCancel = allowEscapeToCancel;
            dialog.Cancelled.SubscribeForLifetime(() => { if (cancelCallback != null) cancelCallback(); }, dialog.LifetimeManager);

            Label messageLabel = content.Add(new Label() { Text = message,  X = 2, Y = 2 });
            if (inputBox == null)
            {
                inputBox = new TextBox() { Foreground = ConsoleColor.Black, Background = ConsoleColor.White };
            }

            content.Add(inputBox).CenterHorizontally();
            inputBox.Y = 4;

            content.SynchronizeForLifetime(nameof(Bounds), () => { inputBox.Width = content.Width - 4; }, content.LifetimeManager);

            inputBox.KeyInputReceived.SubscribeForLifetime((k) =>
            {
                if (k.Key == ConsoleKey.Enter)
                {
                    resultCallback(inputBox.Value);
                    ConsoleApp.Current.LayoutRoot.Controls.Remove(dialog);
                }
            }, inputBox.LifetimeManager);

            ConsoleApp.Current.LayoutRoot.Controls.Add(dialog);
            inputBox.TryFocus();
        }
Exemple #17
0
        public static void ShowMessage(ConsoleString message, Action<DialogButton> resultCallback, bool allowEscapeToCancel = true, int maxHeight = 6, params DialogButton [] buttons)
        {
            if(buttons.Length == 0)
            {
                throw new ArgumentException("You need to specify at least one button");
            }

            ConsolePanel dialogContent = new ConsolePanel();

            Dialog dialog = new Dialog(dialogContent);
            dialog.MaxHeight = maxHeight;
            dialog.AllowEscapeToCancel = allowEscapeToCancel;
            dialog.Cancelled.SubscribeForLifetime(() => { resultCallback(null); }, dialog.LifetimeManager);

            ScrollablePanel messagePanel = dialogContent.Add(new ScrollablePanel()).Fill(padding: new Thickness(0, 0, 1, 3));
            Label messageLabel = messagePanel.ScrollableContent.Add(new Label() { Mode = LabelRenderMode.MultiLineSmartWrap, Text = message }).FillHoriontally(padding: new Thickness(3,3,0,0) );

            StackPanel buttonPanel = dialogContent.Add(new StackPanel() { Margin = 1, Height = 1, Orientation = Orientation.Horizontal }).FillHoriontally(padding: new Thickness(1,0,0,0)).DockToBottom(padding: 1);

            Button firstButton = null;
            foreach (var buttonInfo in buttons)
            {
                var myButtonInfo = buttonInfo;
                Button b = new Button() { Text = buttonInfo.DisplayText };
                b.Pressed.SubscribeForLifetime(() =>
                {
                    ConsoleApp.Current.LayoutRoot.Controls.Remove(dialog);
                    resultCallback(myButtonInfo);
                }, dialog.LifetimeManager);
                buttonPanel.Controls.Add(b);
                firstButton = firstButton ?? b;
            }
            ConsoleApp.Current.LayoutRoot.Controls.Add(dialog);
        }
        private static void ParsePanel(ParserContext context, ConsolePanel panel)
        {
            var myElement = context.CurrentElement;
            context.CurrentControl = panel;
            ParseControlAttributes(panel, context);

            foreach (var childElement in context.CurrentElement.Elements)
            {
                context.CurrentElement = childElement;
                var childControl = CreateControl(context);
                context.CurrentControl = childControl;
                panel.Add(childControl);

                if (childControl is ConsolePanel)
                {
                    ParsePanel(context, childControl as ConsolePanel);
                }
                else
                {
                    ParseControlAttributes(childControl, context);
                }
            }

            context.CurrentElement = myElement;
            context.CurrentControl = panel;
        }