public static void FlashBackground(this GuiWidget widget, Color hightlightColor)
        {
            double displayTime     = 2;
            double pulseTime       = .5;
            double totalSeconds    = 0;
            Color  backgroundColor = widget.BackgroundColor;

            // Show a highlight on the button as the user did not click it
            var flashBackground = new Animation()
            {
                DrawTarget      = widget,
                FramesPerSecond = 10,
            };

            flashBackground.Update += (s1, updateEvent) =>
            {
                totalSeconds += updateEvent.SecondsPassed;

                if (totalSeconds < displayTime)
                {
                    double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                    widget.BackgroundColor = new Color(hightlightColor, (int)(blend * 255));
                }
                else
                {
                    widget.BackgroundColor = backgroundColor;
                    flashBackground.Stop();
                }
            };

            flashBackground.Start();
        }
Exemplo n.º 2
0
        private void ShowUpdateAvailableAnimation()
        {
            double displayTime  = 2;
            double pulseTime    = 1;
            double totalSeconds = 0;

            var   textWidgets = updateAvailableButton.Descendants <TextWidget>().Where((w) => w.Visible == true).ToArray();
            Color startColor  = theme.TextColor;

            // Show a highlight on the button as the user did not click it
            var flashBackground = new Animation()
            {
                DrawTarget      = updateAvailableButton,
                FramesPerSecond = 10,
            };

            flashBackground.Update += (s1, updateEvent) =>
            {
                totalSeconds += updateEvent.SecondsPassed;
                if (totalSeconds < displayTime)
                {
                    double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                    var    color = new Color(startColor, (int)((1 - blend) * 255));
                    foreach (var textWidget in textWidgets)
                    {
                        textWidget.TextColor = color;
                    }
                }
                else
                {
                    foreach (var textWidget in textWidgets)
                    {
                        textWidget.TextColor = startColor;
                    }

                    flashBackground.Stop();
                }
            };

            flashBackground.Start();
        }
Exemplo n.º 3
0
        public PartPreviewContent(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.AnchorAll();

            var extensionArea = new LeftClipFlowLayoutWidget()
            {
                BackgroundColor = theme.TabBarBackground,
                VAnchor         = VAnchor.Stretch,
                Padding         = new BorderDouble(left: 8)
            };

            tabControl = new ChromeTabs(extensionArea, theme)
            {
                VAnchor         = VAnchor.Stretch,
                HAnchor         = HAnchor.Stretch,
                BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor,
                BorderColor     = theme.MinimalShade,
                Border          = new BorderDouble(left: 1),
                NewTabPage      = () =>
                {
                    return(new StartTabPage(this, theme));
                }
            };
            tabControl.ActiveTabChanged += (s, e) =>
            {
                if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage)
                {
                    var dragDropData = ApplicationController.Instance.DragDropData;

                    // Set reference on tab change
                    dragDropData.View3DWidget = tabPage.view3DWidget;
                    dragDropData.SceneContext = tabPage.sceneContext;
                }
            };

            // Force the ActionArea to be as high as ButtonHeight
            tabControl.TabBar.ActionArea.MinimumSize = new Vector2(0, theme.ButtonHeight);
            tabControl.TabBar.BackgroundColor        = theme.TabBarBackground;
            tabControl.TabBar.BorderColor            = theme.ActiveTabColor;

            // Force common padding into top region
            tabControl.TabBar.Padding = theme.TabbarPadding.Clone(top: theme.TabbarPadding.Top * 2, bottom: 0);

            // add in a what's new button
            var seeWhatsNewButton = new LinkLabel("What's New...".Localize(), theme)
            {
                Name        = "What's New Link",
                ToolTipText = "See what's new in this version of MatterControl".Localize(),
                VAnchor     = VAnchor.Center,
                Margin      = new BorderDouble(10, 0),
                TextColor   = theme.Colors.PrimaryTextColor
            };

            seeWhatsNewButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                UserSettings.Instance.set(UserSettingsKey.LastReadWhatsNew, JsonConvert.SerializeObject(DateTime.Now));
                DialogWindow.Show(new HelpPage("What's New"));
            });

            tabControl.TabBar.ActionArea.AddChild(seeWhatsNewButton);

            // add in the update available button
            var updateAvailableButton = new LinkLabel("Update Available".Localize(), theme)
            {
                Visible = false,
            };

            // make the function inline so we don't have to create members for the buttons
            EventHandler SetLinkButtonsVisibility = (s, e) =>
            {
                if (UserSettings.Instance.HasLookedAtWhatsNew())
                {
                    // hide it
                    seeWhatsNewButton.Visible = false;
                }

                if (UpdateControlData.Instance.UpdateStatus == UpdateControlData.UpdateStatusStates.UpdateAvailable)
                {
                    updateAvailableButton.Visible = true;
                    // if we are going to show the update link hide the whats new link no matter what
                    seeWhatsNewButton.Visible = false;
                }
                else
                {
                    updateAvailableButton.Visible = false;
                }
            };

            UserSettings.Instance.Changed += SetLinkButtonsVisibility;
            Closed += (s, e) => UserSettings.Instance.Changed -= SetLinkButtonsVisibility;

            RunningInterval showUpdateInterval = null;

            updateAvailableButton.VisibleChanged += (s, e) =>
            {
                if (!updateAvailableButton.Visible)
                {
                    if (showUpdateInterval != null)
                    {
                        showUpdateInterval.Continue = false;
                        showUpdateInterval          = null;
                    }
                    return;
                }

                showUpdateInterval = UiThread.SetInterval(() =>
                {
                    double displayTime  = 1;
                    double pulseTime    = 1;
                    double totalSeconds = 0;
                    var textWidgets     = updateAvailableButton.Descendants <TextWidget>().Where((w) => w.Visible == true).ToArray();
                    Color startColor    = theme.Colors.PrimaryTextColor;
                    // Show a highlight on the button as the user did not click it
                    Animation flashBackground = null;
                    flashBackground           = new Animation()
                    {
                        DrawTarget      = updateAvailableButton,
                        FramesPerSecond = 10,
                        Update          = (s1, updateEvent) =>
                        {
                            totalSeconds += updateEvent.SecondsPassed;
                            if (totalSeconds < displayTime)
                            {
                                double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                                var color    = new Color(startColor, (int)((1 - blend) * 255));
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = color;
                                }
                            }
                            else
                            {
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = startColor;
                                }
                                flashBackground.Stop();
                            }
                        }
                    };
                    flashBackground.Start();
                }, 120);
            };

            updateAvailableButton.Name = "Update Available Link";
            SetLinkButtonsVisibility(this, null);
            updateAvailableButton.ToolTipText = "There is a new update available for download".Localize();
            updateAvailableButton.VAnchor     = VAnchor.Center;
            updateAvailableButton.Margin      = new BorderDouble(10, 0);
            updateAvailableButton.Click      += (s, e) => UiThread.RunOnIdle(() =>
            {
                UiThread.RunOnIdle(() =>
                {
                    UpdateControlData.Instance.CheckForUpdate();
                    DialogWindow.Show <CheckForUpdatesPage>();
                });
            });

            tabControl.TabBar.ActionArea.AddChild(updateAvailableButton);

            UpdateControlData.Instance.UpdateStatusChanged.RegisterEvent(SetLinkButtonsVisibility, ref unregisterEvents);

            this.AddChild(tabControl);

            ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
            {
                if (e is StringEventArgs stringEvent &&
                    stringEvent.Data == SettingsKey.printer_name &&
                    printerTab != null)
                {
                    printerTab.Text = ActiveSliceSettings.Instance.GetValue(SettingsKey.printer_name);
                }
            }, ref unregisterEvents);

            ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
            {
                var activePrinter = ApplicationController.Instance.ActivePrinter;

                // If ActivePrinter has been nulled and a printer tab is open, close it
                var tab1 = tabControl.AllTabs.Skip(1).FirstOrDefault();
                if ((activePrinter == null || !activePrinter.Settings.PrinterSelected) &&
                    tab1?.TabContent is PrinterTabPage)
                {
                    tabControl.RemoveTab(tab1);
                }
                else
                {
                    this.CreatePrinterTab(activePrinter, theme);
                }
            }, ref unregisterEvents);

            ApplicationController.Instance.NotifyPrintersTabRightElement(extensionArea);

            // Show fixed start page
            tabControl.AddTab(
                new ChromeTab("Start".Localize(), tabControl, tabControl.NewTabPage(), theme, hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Start Tab",
                Padding     = new BorderDouble(15, 0)
            });

            // Add a tab for the current printer
            if (ActiveSliceSettings.Instance.PrinterSelected)
            {
                this.CreatePrinterTab(ApplicationController.Instance.ActivePrinter, theme);
            }

            // Restore active tabs
            foreach (var bed in ApplicationController.Instance.Workspaces)
            {
                this.CreatePartTab("New Part", bed, theme);
            }
        }
        public MainViewWidget(ThemeConfig theme)
            : base(FlowDirection.TopToBottom)
        {
            this.AnchorAll();
            this.theme           = theme;
            this.Name            = "PartPreviewContent";
            this.BackgroundColor = theme.BackgroundColor;

            // Push TouchScreenMode into GuiWidget
            GuiWidget.TouchScreenMode = UserSettings.Instance.IsTouchScreen;

            var extensionArea = new LeftClipFlowLayoutWidget()
            {
                BackgroundColor = theme.TabBarBackground,
                VAnchor         = VAnchor.Stretch,
                Padding         = new BorderDouble(left: 8)
            };

            tabControl = new ChromeTabs(extensionArea, theme)
            {
                VAnchor         = VAnchor.Stretch,
                HAnchor         = HAnchor.Stretch,
                BackgroundColor = theme.BackgroundColor,
                BorderColor     = theme.MinimalShade,
                Border          = new BorderDouble(left: 1),
            };

            tabControl.PlusClicked += (s, e) =>
            {
                UiThread.RunOnIdle(() =>
                {
                    this.CreatePartTab().ConfigureAwait(false);
                });
            };

            tabControl.ActiveTabChanged += (s, e) =>
            {
                if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage)
                {
                    var dragDropData = ApplicationController.Instance.DragDropData;

                    // Set reference on tab change
                    dragDropData.View3DWidget = tabPage.view3DWidget;
                    dragDropData.SceneContext = tabPage.sceneContext;

                    ApplicationController.Instance.PrinterTabSelected = true;
                }
                else
                {
                    ApplicationController.Instance.PrinterTabSelected = false;
                }

                ApplicationController.Instance.MainTabKey = tabControl.SelectedTabKey;
            };

            // Force the ActionArea to be as high as ButtonHeight
            tabControl.TabBar.ActionArea.MinimumSize = new Vector2(0, theme.ButtonHeight);
            tabControl.TabBar.BackgroundColor        = theme.TabBarBackground;
            tabControl.TabBar.BorderColor            = theme.BackgroundColor;

            // Force common padding into top region
            tabControl.TabBar.Padding = theme.TabbarPadding.Clone(top: theme.TabbarPadding.Top * 2, bottom: 0);

            // add in a what's new button
            seeWhatsNewButton = new LinkLabel("What's New...".Localize(), theme)
            {
                Name        = "What's New Link",
                ToolTipText = "See what's new in this version of MatterControl".Localize(),
                VAnchor     = VAnchor.Center,
                Margin      = new BorderDouble(10, 0),
                TextColor   = theme.TextColor
            };
            seeWhatsNewButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                UserSettings.Instance.set(UserSettingsKey.LastReadWhatsNew, JsonConvert.SerializeObject(DateTime.Now));
                DialogWindow.Show(new HelpPage("What's New"));
            });

            tabControl.TabBar.ActionArea.AddChild(seeWhatsNewButton);

            // add in the update available button
            updateAvailableButton = new LinkLabel("Update Available".Localize(), theme)
            {
                Visible     = false,
                Name        = "Update Available Link",
                ToolTipText = "There is a new update available for download".Localize(),
                VAnchor     = VAnchor.Center,
                Margin      = new BorderDouble(10, 0)
            };

            // Register listeners
            UserSettings.Instance.SettingChanged += SetLinkButtonsVisibility;

            RunningInterval showUpdateInterval = null;

            updateAvailableButton.VisibleChanged += (s, e) =>
            {
                if (!updateAvailableButton.Visible)
                {
                    if (showUpdateInterval != null)
                    {
                        UiThread.ClearInterval(showUpdateInterval);
                        showUpdateInterval = null;
                    }
                    return;
                }

                showUpdateInterval = UiThread.SetInterval(() =>
                {
                    double displayTime  = 1;
                    double pulseTime    = 1;
                    double totalSeconds = 0;
                    var textWidgets     = updateAvailableButton.Descendants <TextWidget>().Where((w) => w.Visible == true).ToArray();
                    Color startColor    = theme.TextColor;
                    // Show a highlight on the button as the user did not click it
                    Animation flashBackground = null;
                    flashBackground           = new Animation()
                    {
                        DrawTarget      = updateAvailableButton,
                        FramesPerSecond = 10,
                        Update          = (s1, updateEvent) =>
                        {
                            totalSeconds += updateEvent.SecondsPassed;
                            if (totalSeconds < displayTime)
                            {
                                double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                                var color    = new Color(startColor, (int)((1 - blend) * 255));
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = color;
                                }
                            }
                            else
                            {
                                foreach (var textWidget in textWidgets)
                                {
                                    textWidget.TextColor = startColor;
                                }
                                flashBackground.Stop();
                            }
                        }
                    };
                    flashBackground.Start();
                }, 120);
            };

            SetLinkButtonsVisibility(this, null);
            updateAvailableButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                UpdateControlData.Instance.CheckForUpdate();
                DialogWindow.Show <CheckForUpdatesPage>();
            });

            tabControl.TabBar.ActionArea.AddChild(updateAvailableButton);

            this.AddChild(tabControl);

            ApplicationController.Instance.NotifyPrintersTabRightElement(extensionArea);

            // Store tab
            tabControl.AddTab(
                new ChromeTab("Store", "Store".Localize(), tabControl, new StoreTabPage(theme), theme, hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Store Tab",
                Padding     = new BorderDouble(15, 0),
            });

            // Library tab
            var libraryWidget = new LibraryWidget(this, theme)
            {
                BackgroundColor = theme.BackgroundColor
            };

            tabControl.AddTab(
                new ChromeTab("Library", "Library".Localize(), tabControl, libraryWidget, theme, hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Library Tab",
                Padding     = new BorderDouble(15, 0),
            });

            // Hardware tab
            tabControl.AddTab(
                new ChromeTab(
                    "Hardware",
                    "Hardware".Localize(),
                    tabControl,
                    new HardwareTabPage(theme)
            {
                BackgroundColor = theme.BackgroundColor
            },
                    theme,
                    hasClose: false)
            {
                MinimumSize = new Vector2(0, theme.TabButtonHeight),
                Name        = "Hardware Tab",
                Padding     = new BorderDouble(15, 0),
            });

            if (ApplicationController.Instance.Workspaces.Count == 0)
            {
                this.CreatePartTab().ConfigureAwait(false);
            }

            string tabKey = ApplicationController.Instance.MainTabKey;

            if (string.IsNullOrEmpty(tabKey))
            {
                tabKey = "Hardware";
            }

            // HACK: Restore to the first printer tab if PrinterTabSelected and tabKey not found. This allows sign in/out to remain on the printer tab across different users
            if (!tabControl.AllTabs.Any(t => t.Key == tabKey) &&
                ApplicationController.Instance.PrinterTabSelected)
            {
                var key = tabControl.AllTabs.Where(t => t.TabContent is PrinterTabPage).FirstOrDefault()?.Key;
                if (key != null)
                {
                    tabKey = key;
                }
            }

            var brandMenu = new BrandMenuButton(theme)
            {
                HAnchor         = HAnchor.Fit,
                VAnchor         = VAnchor.Fit,
                BackgroundColor = theme.TabBarBackground,
                Padding         = theme.TabbarPadding.Clone(right: theme.DefaultContainerPadding)
            };

            tabControl.TabBar.ActionArea.AddChild(brandMenu, 0);

            // Restore active tabs
            foreach (var workspace in ApplicationController.Instance.Workspaces)
            {
                this.CreatePartTab(workspace);
            }

            tabControl.SelectedTabKey = tabKey;

            statusBar = new Toolbar(theme)
            {
                HAnchor         = HAnchor.Stretch,
                VAnchor         = VAnchor.Absolute,
                Padding         = 1,
                Height          = 22,
                BackgroundColor = theme.BackgroundColor,
                Border          = new BorderDouble(top: 1),
                BorderColor     = theme.BorderColor20,
            };
            this.AddChild(statusBar);

            statusBar.ActionArea.VAnchor = VAnchor.Stretch;

            tasksContainer = new FlowLayoutWidget(FlowDirection.LeftToRight)
            {
                HAnchor         = HAnchor.Fit,
                VAnchor         = VAnchor.Stretch,
                BackgroundColor = theme.MinimalShade,
                Name            = "runningTasksPanel"
            };
            statusBar.AddChild(tasksContainer);

            var tasks = ApplicationController.Instance.Tasks;

            tasks.TasksChanged += (s, e) =>
            {
                RenderRunningTasks(theme, tasks);
            };

            stretchStatusPanel = new GuiWidget()
            {
                HAnchor         = HAnchor.Stretch,
                VAnchor         = VAnchor.Stretch,
                Padding         = new BorderDouble(right: 3),
                Margin          = new BorderDouble(right: 2, top: 1, bottom: 1),
                Border          = new BorderDouble(1),
                BackgroundColor = theme.MinimalShade.WithAlpha(10),
                BorderColor     = theme.SlightShade,
                Width           = 200
            };
            statusBar.AddChild(stretchStatusPanel);

            var panelBackgroundColor = theme.MinimalShade.WithAlpha(10);

            statusBar.AddChild(
                this.CreateThemeStatusPanel(theme, panelBackgroundColor));

            statusBar.AddChild(
                this.CreateNetworkStatusPanel(theme));

            this.RenderRunningTasks(theme, tasks);

            // Register listeners
            PrinterSettings.AnyPrinterSettingChanged           += Printer_SettingChanged;
            ApplicationController.Instance.OpenPrintersChanged += OpenPrinters_Changed;

            UpdateControlData.Instance.UpdateStatusChanged.RegisterEvent((s, e) =>
            {
                SetLinkButtonsVisibility(s, new StringEventArgs("Unknown"));
            }, ref unregisterEvents);

            ApplicationController.Instance.MainView = this;
        }
        public PrinterActionsBar(PrinterConfig printer, PrinterTabPage printerTabPage, ThemeConfig theme)
            : base(theme)
        {
            this.printer        = printer;
            this.printerTabPage = printerTabPage;

            this.HAnchor = HAnchor.Stretch;
            this.VAnchor = VAnchor.Fit;

            var defaultMargin = theme.ButtonSpacing;

            // add the reset button first (if there is one)
            if (ActiveSliceSettings.Instance.GetValue <bool>(SettingsKey.show_reset_connection))
            {
                var resetConnectionButton = new TextIconButton(
                    "Reset".Localize(),
                    AggContext.StaticData.LoadIcon("e_stop.png", 14, 14, theme.InvertIcons),
                    theme)
                {
                    ToolTipText = "Reboots the firmware on the controller".Localize(),
                    Margin      = defaultMargin
                };
                resetConnectionButton.Click += (s, e) =>
                {
                    UiThread.RunOnIdle(printer.Connection.RebootBoard);
                };
                this.AddChild(resetConnectionButton);
            }

            this.AddChild(new PrinterConnectButton(printer, theme));
            this.AddChild(new PrintButton(printer, theme));

            this.AddChild(new SliceButton(printer, printerTabPage, theme)
            {
                Name   = "Generate Gcode Button",
                Margin = theme.ButtonSpacing,
            });

            // Add vertical separator
            this.AddChild(new ToolbarSeparator(theme)
            {
                VAnchor = VAnchor.Absolute,
                Height  = theme.ButtonHeight,
            });

            var buttonGroupB = new ObservableCollection <GuiWidget>();

            var iconPath = Path.Combine("ViewTransformControls", "model.png");

            modelViewButton = new RadioIconButton(AggContext.StaticData.LoadIcon(iconPath, 16, 16, theme.InvertIcons), theme)
            {
                SiblingRadioButtonList = buttonGroupB,
                Name        = "Model View Button",
                Checked     = printer?.ViewState.ViewMode == PartViewMode.Model || printer == null,
                ToolTipText = "Model View".Localize(),
                Margin      = theme.ButtonSpacing
            };
            modelViewButton.Click += SwitchModes_Click;
            buttonGroupB.Add(modelViewButton);
            AddChild(modelViewButton);

            iconPath       = Path.Combine("ViewTransformControls", "gcode_3d.png");
            layers3DButton = new RadioIconButton(AggContext.StaticData.LoadIcon(iconPath, 16, 16, theme.InvertIcons), theme)
            {
                SiblingRadioButtonList = buttonGroupB,
                Name        = "Layers3D Button",
                Checked     = printer?.ViewState.ViewMode == PartViewMode.Layers3D,
                ToolTipText = "3D Layer View".Localize(),
                Margin      = theme.ButtonSpacing
            };
            layers3DButton.Click += SwitchModes_Click;
            buttonGroupB.Add(layers3DButton);

            if (!UserSettings.Instance.IsTouchScreen)
            {
                this.AddChild(layers3DButton);
            }

            iconPath       = Path.Combine("ViewTransformControls", "gcode_2d.png");
            layers2DButton = new RadioIconButton(AggContext.StaticData.LoadIcon(iconPath, 16, 16, theme.InvertIcons), theme)
            {
                SiblingRadioButtonList = buttonGroupB,
                Name        = "Layers2D Button",
                Checked     = printer?.ViewState.ViewMode == PartViewMode.Layers2D,
                ToolTipText = "2D Layer View".Localize(),
                Margin      = theme.ButtonSpacing,
            };
            layers2DButton.Click += SwitchModes_Click;
            buttonGroupB.Add(layers2DButton);
            this.AddChild(layers2DButton);

            this.AddChild(new HorizontalSpacer());

            bool shareTemp     = printer.Settings.GetValue <bool>(SettingsKey.extruders_share_temperature);
            int  extruderCount = shareTemp ? 1 : printer.Settings.GetValue <int>(SettingsKey.extruder_count);

            if (!printer.Settings.GetValue <bool>(SettingsKey.sla_printer))
            {
                for (int extruderIndex = 0; extruderIndex < extruderCount; extruderIndex++)
                {
                    this.AddChild(new TemperatureWidgetHotend(printer, extruderIndex, theme)
                    {
                        Margin = new BorderDouble(right: 10)
                    });
                }
            }

            if (printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed))
            {
                this.AddChild(new TemperatureWidgetBed(printer, theme));
            }

            this.OverflowButton.Name = "Printer Overflow Menu";
            this.ExtendOverflowMenu  = (popupMenu) =>
            {
                this.GeneratePrinterOverflowMenu(popupMenu, ApplicationController.Instance.MenuTheme);
            };

            printer.ViewState.ViewModeChanged += (s, e) =>
            {
                RadioIconButton activeButton = null;
                if (e.ViewMode == PartViewMode.Layers2D)
                {
                    activeButton = layers2DButton;
                }
                else if (e.ViewMode == PartViewMode.Layers3D)
                {
                    activeButton = layers3DButton;
                }
                else
                {
                    activeButton = modelViewButton;
                }

                if (activeButton != null)
                {
                    activeButton.Checked = true;

                    if (!buttonIsBeingClicked)
                    {
                        double displayTime     = 2;
                        double pulseTime       = .5;
                        double totalSeconds    = 0;
                        Color  backgroundColor = activeButton.BackgroundColor;
                        Color  hightlightColor = theme.Colors.PrimaryAccentColor.AdjustContrast(theme.Colors.PrimaryTextColor, 6).ToColor();
                        // Show a highlight on the button as the user did not click it
                        Animation flashBackground = null;
                        flashBackground = new Animation()
                        {
                            DrawTarget      = activeButton,
                            FramesPerSecond = 10,
                            Update          = (s1, updateEvent) =>
                            {
                                totalSeconds += updateEvent.SecondsPassed;
                                if (totalSeconds < displayTime)
                                {
                                    double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime);
                                    activeButton.BackgroundColor = new Color(hightlightColor, (int)(blend * 255));
                                }
                                else
                                {
                                    activeButton.BackgroundColor = backgroundColor;
                                    flashBackground.Stop();
                                }
                            }
                        };
                        flashBackground.Start();
                    }
                }
            };

            printer.Connection.ConnectionSucceeded.RegisterEvent((s, e) =>
            {
                UiThread.RunOnIdle(() =>
                {
                    PrintRecovery.CheckIfNeedToRecoverPrint(printer);
                });
            }, ref unregisterEvents);
        }