private void Selector_SlideLine(AppSelectorButton End)
        {
            /** how this place works
             *  // transform the line so it moves to underneath the sender
             *  // make sure it cant go less than the first button and past the last button
             *  //calculate move distance based on orientation and how many button widths away to move
             *** SPECIAL NOTE if u storyboard a  translatetransform with a double animation, the
             ***the translatetransform gets no value and the animation gets it instead in the To prop
             */
            double iDistanceInButtons   = End.ID;
            double iDistance            = 0;
            double VerticalLineOffset   = End.ID == 0 ? 0 : VERTICAL_LINE_OFFSET;
            double HorizontalLineOffset = End.ID == 0 ? 0 : HORIZONTAL_LINE_OFFSET;


            // move left or right
            if (this.MainOrientation == Orientation.Horizontal)
            {
                iDistance = iDistanceInButtons * (this.ButtonWidth) + (iDistanceInButtons * (WIDTH_GRID_COLUMNSPACING) + HorizontalLineOffset);
            }

            // move up or down
            else // orientation must be vertical
            {
                iDistance = iDistanceInButtons * (this.ButtonHeight) + (iDistanceInButtons * WIDTH_GRID_ROWSPACING) + VerticalLineOffset;
            }
            daAnimation.To = iDistance;
            this.storyboard.Begin();
        }
        private void Selector_UpdateSelectedState(AppSelectorButton sbButton)
        {
            foreach (AppSelectorButton button in _buttonList)
            {
                if (((Panel)button.Content).Children[2] is TextBlockEx)
                {
                    TextBlockEx text = (TextBlockEx)((Panel)button.Content).Children[2];

                    if (button.ID == sbButton.ID)
                    {
                        text.ShowBoldText(true);
                        //if (IsListView)
                        //{
                        //    button.Background = new SolidColorBrush(Colors.Blue);
                        //}
                    }
                    else
                    {
                        text.ShowBoldText(false);
                        //if (IsListView)
                        //{
                        //    button.Background = button.NormalBackground;
                        //}
                    }
                }
            }
        }
        private void Selector_ClearButtonClick(object sender, PointerRoutedEventArgs e)
        {
            if (IsPenOnly && e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Pen)
            {
                return;
            }
            AppSelectorButton sbButton = (AppSelectorButton)sender;

            // raise event clear clicked
            // raise the selected color changed event
            this.RaiseClearClickedEvent(this);
            // telemetry
            //TelemetryService.Current?.SendTelemetry(this.TelemetryId, System.DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss tt", CultureInfo.InvariantCulture), true, 0);
        }
        private void Selector_ButtonClick(object sender, PointerRoutedEventArgs e)
        {
            if (IsPenOnly && e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Pen)
            {
                return;
            }

            AppSelectorButton sbButton = (AppSelectorButton)sender;

            if (this.ShowSelectedLine && this.SelectedButton.ID != sbButton.ID)
            {// transform the line so it moves to underneath the sender
                this.Selector_SlideLine(sbButton);
                this.Selector_UpdateSelectedState(sbButton);
            }
            this.SelectedID     = sbButton.ID;
            this.SelectedButton = sbButton;
            this.Selector_UpdateSelectedState(sbButton);

            // telemetry
            //TelemetryService.Current?.SendTelemetry(this.TelemetryId, System.DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss tt", CultureInfo.InvariantCulture), true, 0);
        }
        private void GenerateButton(ImagePair imagePair, int i, int position)
        {
            Grid grid = new Grid()
            {
                Margin  = new Thickness(0),
                Padding = new Thickness(0)
            };

            if (this.ShowMessages && this.MainOrientation == Orientation.Vertical)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition()
                {
                    Width = new GridLength(.5, GridUnitType.Star)
                });
                grid.ColumnDefinitions.Add(new ColumnDefinition()
                {
                    Width = new GridLength(.5, GridUnitType.Star)
                });
                grid.ColumnSpacing = WIDTH_GRID_COLUMNSPACING;
            }

            Grid.SetRow(imagePair.NotSelected, 0);
            Grid.SetColumn(imagePair.NotSelected, 0);
            grid.Children.Add(imagePair.NotSelected);
            Grid.SetRow(imagePair.Selected, 0);
            Grid.SetColumn(imagePair.Selected, 0);
            grid.Children.Add(imagePair.Selected);

            HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center;

            // if we need to show messages then align left
            if (this.MainOrientation == Orientation.Vertical && this.ShowMessages && !string.IsNullOrWhiteSpace(imagePair.Message))
            {
                horizontalAlignment = HorizontalAlignment.Left;
                TextBlockEx tbMessage = new TextBlockEx()
                {
                    Name              = "TheText",
                    Text              = imagePair.Message,
                    TextStyle         = TextStyles.AppSelectorText,
                    FontSize          = 20,
                    Opacity           = 1,
                    VerticalAlignment = VerticalAlignment.Center,
                    TextStyleBold     = TextStyles.AppSelectorTextBold
                };

                if (i == 0)
                {
                    tbMessage.ShowBoldText(true);
                }

                Grid.SetRow(tbMessage, 0);
                Grid.SetColumn(tbMessage, 1);// kk this isnt working just yet.
                grid.Children.Add(tbMessage);
            }

            AppSelectorButton sbButton = new AppSelectorButton()
            {
                ID = i,
                HorizontalAlignment = horizontalAlignment,
                VerticalAlignment   = VerticalAlignment.Center,
                Content             = grid
            };

            //if (!IsListView)
            //{
            //    sbButton.Background = new SolidColorBrush(Colors.Transparent);
            //}
            //else
            //{
            //    sbButton.NormalBackground = (i % 2 == 0 ? BackGroundWhiteAcrylic : BackGroundGrayAcrylic);
            //    if (i == 0)
            //    {
            //        sbButton.Background = new SolidColorBrush(Colors.Blue);
            //    }
            //    else
            //    {
            //        sbButton.Background = sbButton.NormalBackground;
            //    }

            //}

            //only set the dimensions of the button if the control variables are passed in
            // and the orientation is correct
            if (this.ButtonHeight > 0)
            {
                sbButton.Height = this.ButtonHeight;
            }

            // if u need to show messages, dont set the width b/c theres no way to figure out the width
            // if there is text
            if (this.ButtonWidth > 0 && (!this.ShowMessages && !(this.MainOrientation == Orientation.Vertical)))
            {
                sbButton.Width = this.ButtonWidth;
            }
            if (null != _buttonStyle)
            {
                sbButton.Style = _buttonStyle;
            }
            ;

            if (imagePair.IsClearButton)
            {// these buttons get their own handler and dont change the selection of the app selector
                sbButton.AddHandler(PointerReleasedEvent, new PointerEventHandler(Selector_ClearButtonClick), true);
            }
            else
            {
                sbButton.AddHandler(PointerReleasedEvent, new PointerEventHandler(Selector_ButtonClick), true);
            }
            grid.PointerEntered += pointerEntered;


            if (this.MainOrientation == Orientation.Horizontal)
            {
                Grid.SetRow(sbButton, 0);
                Grid.SetColumn(sbButton, position);
            }
            else // vertical
            {
                Grid.SetColumn(sbButton, 0);
                Grid.SetRow(sbButton, position);
            }
            if (!imagePair.IsClearButton)
            {// clear button is not a part of the regular buttons
                this.Buttons.Add(sbButton);
            }
            _layoutRoot.Children.Add(sbButton);
            _buttonList.Add(sbButton);
        }
        private void GenerateButton(AppSelectorData AppSelectorData, int index)
        {
            btnGrid = new Grid()
            {
                Margin  = new Thickness(0),
                Padding = new Thickness(0)
            };
            if (this.ShowMessages && this.MainOrientation == Orientation.Vertical)
            {
                btnGrid.ColumnDefinitions.Add(new ColumnDefinition()
                {
                    Width = new GridLength(.5, GridUnitType.Star)
                });
                btnGrid.ColumnDefinitions.Add(new ColumnDefinition()
                {
                    Width = new GridLength(.5, GridUnitType.Star)
                });
                btnGrid.ColumnSpacing = WIDTH_GRID_COLUMNSPACING;
            }

            ImagePair images = new ImagePair()
            {
                //ID = i,
                Selected = new Image()
                {
                    Width = this.ButtonWidth,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment   = VerticalAlignment.Center,
                    Opacity             = 1.0
                },
                NotSelected = new Image()
                {
                    Width = this.ButtonWidth,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment   = VerticalAlignment.Center,
                    Opacity             = 1.0
                }
            };

            if (!string.IsNullOrEmpty(AppSelectorData.Source_NotSelectedImage))
            {
                images.NotSelected.Source = new BitmapImage()
                {
                    UriSource = new Uri(AppSelectorData.Source_NotSelectedImage), DecodePixelWidth = (int)this.ButtonWidth
                };
            }
            else if (!string.IsNullOrEmpty(AppSelectorData.SourceSVG_NotSelectedImage))
            {
                images.NotSelected.Source = new SvgImageSource(new Uri(AppSelectorData.SourceSVG_NotSelectedImage));
            }

            if (!string.IsNullOrEmpty(AppSelectorData.Source_SelectedImage))
            {
                images.Selected.Source = new BitmapImage()
                {
                    UriSource = new Uri(AppSelectorData.Source_SelectedImage), DecodePixelWidth = (int)this.ButtonWidth
                };
            }
            else if (!string.IsNullOrEmpty(AppSelectorData.SourceSVG_SelectedImage))
            {
                images.Selected.Source = new SvgImageSource(new Uri(AppSelectorData.SourceSVG_SelectedImage));
            }
            //images.Selected.Source
            Grid.SetRow(images.NotSelected, 0);
            Grid.SetColumn(images.NotSelected, 0);
            btnGrid.Children.Add(images.NotSelected);
            Grid.SetRow(images.Selected, 0);
            Grid.SetColumn(images.Selected, 0);
            btnGrid.Children.Add(images.Selected);

            if (this.MainOrientation == Orientation.Vertical && this.ShowMessages)
            {
                TextBlockEx tbMessage = new TextBlockEx()
                {
                    Name              = "Text",
                    Text              = AppSelectorData.Message,
                    TextStyle         = TextStyles.AppSelectorText,
                    FontSize          = 20,
                    Opacity           = 1,
                    VerticalAlignment = VerticalAlignment.Center,
                    TextStyleBold     = TextStyles.AppSelectorTextBold
                                        //TextStyleBold = (IsListView ? TextStyles.AppSelectorTextDarkBold: TextStyles.AppSelectorTextBold)
                };

                if (index == 0)
                {
                    tbMessage.ShowBoldText(true);
                }

                Grid.SetRow(tbMessage, 0);
                Grid.SetColumn(tbMessage, 1);// kk this isnt working just yet.
                btnGrid.Children.Add(tbMessage);
            }
            if (!AppSelectorData.IsClearButton)
            {
                this.ImagePairs.Add(index, images);
            }

            HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center;

            // if we need to show messages then align left
            if (this.MainOrientation == Orientation.Vertical && this.ShowMessages)
            {
                horizontalAlignment = HorizontalAlignment.Left;
            }

            AppSelectorButton sbButton = new AppSelectorButton()
            {
                ID                  = index,
                Background          = new SolidColorBrush(Colors.Transparent),
                HorizontalAlignment = horizontalAlignment,
                VerticalAlignment   = VerticalAlignment.Center,
                Content             = btnGrid
            };

            //if (!IsListView)
            //{
            //    sbButton.Background = new SolidColorBrush(Colors.Transparent);
            //}
            //else
            //{
            //    sbButton.NormalBackground = (index % 2 == 0 ? BackGroundWhiteAcrylic : BackGroundGrayAcrylic);
            //    if (index == 0)
            //    {
            //        sbButton.Background = new SolidColorBrush(Colors.Blue);
            //    }
            //    else
            //    {
            //        sbButton.Background = sbButton.NormalBackground;
            //    }

            //}

            //only set the dimensions of the button if the control variables are passed in
            // and the orientation is correct
            if (this.ButtonHeight > 0)
            {
                sbButton.Height = this.ButtonHeight;
            }

            // if u need to show messages, dont set the width b/c theres no way to figure out the width
            // if there is text
            if (this.ButtonWidth > 0 && (!this.ShowMessages && !(this.MainOrientation == Orientation.Vertical)))
            {
                sbButton.Width = this.ButtonWidth;
            }
            if (null != _buttonStyle)
            {
                sbButton.Style = _buttonStyle;
            }
            ;

            if (AppSelectorData.IsClearButton)
            {// these buttons get their own handler and dont change the selection of the app selector
                sbButton.AddHandler(PointerReleasedEvent, new PointerEventHandler(Selector_ClearButtonClick), true);
            }
            else
            {
                sbButton.AddHandler(PointerReleasedEvent, new PointerEventHandler(Selector_ButtonClick), true);
            }
            btnGrid.PointerEntered += pointerEntered;


            if (this.MainOrientation == Orientation.Horizontal)
            {
                Grid.SetRow(sbButton, 0);
                Grid.SetColumn(sbButton, index);
            }
            else // vertical
            {
                Grid.SetColumn(sbButton, 0);
                Grid.SetRow(sbButton, index);
            }
            if (!AppSelectorData.IsClearButton)
            {// clear button is not a part of the regular buttons
                this.Buttons.Add(sbButton);
            }
            _layoutRoot.Children.Add(sbButton);
            _buttonList.Add(sbButton);
        }
        private void RenderUI()
        {
            // get the layout base (a canvas here)
            _layoutRoot = (Grid)this.GetTemplateChild("LayoutRoot");


            // if we can't get the layout root, we can't do anything
            if (null == _layoutRoot)
            {
                return;
            }

            // update the grid
            _layoutRoot.Name = "AppSelectorGrid";



            // must construct additional columns or rows based on orientation and number
            // keep 1.0 so it creates a ratio (double) for the width/height definitions
            // coloring book will pass in image pairs, otherwise its a regular URI count from a normal app selector
            int iButtonCount = this.ImagePairs.Count > 0 ? this.ImagePairs.Count + 1: URIs.Count;

            double ratio = 1.0 / iButtonCount;

            if (this.MainOrientation == Orientation.Horizontal)
            {
                _layoutRoot.ColumnSpacing = WIDTH_GRID_COLUMNSPACING;
                _layoutRoot.RowDefinitions.Add(new RowDefinition());
                for (int i = 0; i < iButtonCount; i++)
                {
                    _layoutRoot.ColumnDefinitions.Add(new ColumnDefinition()
                    {
                        Width = new GridLength(ratio, GridUnitType.Star)
                    });
                }
            }
            else
            {
                //_layoutRoot.RowSpacing = (!IsListView ? WIDTH_GRID_ROWSPACING: 0);
                _layoutRoot.RowSpacing = WIDTH_GRID_ROWSPACING;
                _layoutRoot.ColumnDefinitions.Add(new ColumnDefinition());
                for (int i = 0; i < iButtonCount; i++)
                {
                    _layoutRoot.RowDefinitions.Add(new RowDefinition()
                    {
                        Height = new GridLength(ratio, GridUnitType.Star)
                    });
                }
            }

            // create the button style
            //if (IsListView)
            //{
            //    _buttonStyle = StyleHelper.GetApplicationStyle("ListViewButton");
            //}
            //else
            //{
            _buttonStyle = StyleHelper.GetApplicationStyle("AppSelectorButton");
            //}

            // JN loop this area to create images and buttons based on list
            int index = 0;

            if (this.ImagePairs.Count != 0)
            {// hubris! dont add clearbutton image pair unless it has a value. should only have a value on colorbook
                if (this.ClearButtonImagePair != null)
                {
                    GenerateButton(this.ClearButtonImagePair, 0, 0);
                    index = 1;
                }
                else
                {
                    index = 0;
                }

                for (int i = 0; i < this.ImagePairs.Count; i++, index++)
                {
                    GenerateButton(this.ImagePairs[i], i, index);
                }
            }
            else
            {
                for (int i = 0; i < this.URIs.Count; i++)
                {
                    GenerateButton(this.URIs[i], i);
                }
            }


            if (this.ShowSelectedLine)
            {
                selectedLine.StrokeThickness = 5;
                double LineRightMargin  = StyleHelper.GetApplicationDouble("AppSelectorLineBottomMargin");
                double LineBottomMargin = StyleHelper.GetApplicationDouble("AppSelectorLineBottomMargin");

                if (this.MainOrientation == Orientation.Vertical)
                {
                    selectedLine.X1 = -LineRightMargin;
                    selectedLine.Y1 = VERTICAL_LINE_OFFSET;

                    selectedLine.X2 = -LineRightMargin;
                    selectedLine.Y2 = this.ButtonHeight + VERTICAL_LINE_OFFSET;
                }
                if (this.MainOrientation == Orientation.Horizontal)
                {
                    selectedLine.X1 = 3;
                    selectedLine.Y1 = this.ButtonHeight + 5 + LineBottomMargin;

                    selectedLine.X2 = this.ButtonWidth + 4;// border thickness for some reason 2 on both sides
                    selectedLine.Y2 = this.ButtonHeight + 5 + LineBottomMargin;
                }

                SolidColorBrush SelectedLineColor = RadiatingButton.GetSolidColorBrush("#FF0078D4");

                selectedLine.Stroke = SelectedLineColor;
                selectedLine.Fill   = SelectedLineColor;
                _layoutRoot.Children.Add(selectedLine);

                this.SelectedButton = this.Buttons[0];// set the first button as the selected button for line moving

                // need sine easing
                SineEase sineEaseIn = new SineEase()
                {
                    EasingMode = EasingMode.EaseIn
                };
                // set this once here and forget it.
                this.selectedLine.RenderTransform = this.translateTransform;
                Duration duration = new Duration(new TimeSpan(0, 0, 0, 0, 400));
                daAnimation = new DoubleAnimation()
                {
                    Duration       = duration,
                    EasingFunction = sineEaseIn
                };

                this.storyboard.Children.Add(daAnimation);
                Storyboard.SetTarget(daAnimation, this.translateTransform);
                if (this.MainOrientation == Orientation.Horizontal)
                {
                    Storyboard.SetTargetProperty(daAnimation, "X");
                }
                if (this.MainOrientation == Orientation.Vertical)
                {
                    Storyboard.SetTargetProperty(daAnimation, "Y");
                }
            }

            // set up animations
            _storyboardFadeIn  = AnimationHelper.CreateEasingAnimation(_layoutRoot, "Opacity", 0.0, 0.0, 1.0, this.DurationInMilliseconds, this.StaggerDelayInMilliseconds, false, false, new RepeatBehavior(1d));
            _storyboardFadeOut = AnimationHelper.CreateEasingAnimation(_layoutRoot, "Opacity", 1.0, 1.0, 0.0, this.DurationInMilliseconds, this.StaggerDelayInMilliseconds, false, false, new RepeatBehavior(1d));

            this.UpdateUI();
        }