From c914cc7d996d646159ba19784d8c6417b142d85a Mon Sep 17 00:00:00 2001 From: Rita Zhang Date: Mon, 5 Oct 2015 11:26:49 -0700 Subject: [PATCH] feat #16 - add list menu --- .../Components/RadialMenuButton.xaml.cs | 75 ++-- RadialMenuControl/RadialMenuControl.csproj | 331 +++++++++--------- RadialMenuControl/UserControl/ListMenu.xaml | 16 + .../UserControl/ListMenu.xaml.cs | 54 +++ RadialMenuControl/UserControl/Pie.xaml.cs | 5 +- .../UserControl/PieSlice.xaml.cs | 10 +- RadialMenuControl/UserControl/RadialMenu.xaml | 5 +- .../UserControl/RadialMenu.xaml.cs | 90 ++++- RadialMenuDemo/MainPage.xaml.cs | 65 +++- 9 files changed, 424 insertions(+), 227 deletions(-) create mode 100644 RadialMenuControl/UserControl/ListMenu.xaml create mode 100644 RadialMenuControl/UserControl/ListMenu.xaml.cs diff --git a/RadialMenuControl/Components/RadialMenuButton.xaml.cs b/RadialMenuControl/Components/RadialMenuButton.xaml.cs index 1741d27..8613606 100644 --- a/RadialMenuControl/Components/RadialMenuButton.xaml.cs +++ b/RadialMenuControl/Components/RadialMenuButton.xaml.cs @@ -9,12 +9,13 @@ using Windows.UI.Xaml.Media; public partial class RadialMenuButton : Button - { + { public enum ButtonType { SIMPLE = 0, RADIO, - TOGGLE + TOGGLE, + LIST }; // Label @@ -72,29 +73,29 @@ public int? IconSize { get { return (int?)GetValue(IconSizeProperty); } set { SetValue(IconProperty, value); } - } - + } + public bool MenuSelected { get { return (bool)GetValue(MenuSeletedProperty); } set { SetValue(MenuSeletedProperty, value); } - } - - public bool Value { - get { return (bool)GetValue(ValueProperty); } - set { - if(this.Type == ButtonType.SIMPLE) - { - throw new Exception("A button of type SIMPLE should not have any value."); - } - else - { - SetValue(ValueProperty, value); - } + } + + public object Value { + get { return (object)GetValue(ValueProperty); } + set { + if(this.Type == ButtonType.SIMPLE) + { + throw new Exception("A button of type SIMPLE should not have any value."); + } + else + { + SetValue(ValueProperty, value); + } } - } - - + } + + public ButtonType Type { get { return (ButtonType)GetValue(ButtonTypeProperty); } @@ -115,8 +116,8 @@ public ImageSource IconImage DependencyProperty.Register("InnerHoverColor", typeof(Color?), typeof(RadialMenuButton), null); public static readonly DependencyProperty InnerTappedColorProperty = - DependencyProperty.Register("InnerTappedColor", typeof(Color?), typeof(RadialMenuButton), null); - + DependencyProperty.Register("InnerTappedColor", typeof(Color?), typeof(RadialMenuButton), null); + public static readonly DependencyProperty InnerReleasedColorProperty = DependencyProperty.Register("InnerReleasedColor", typeof(Color?), typeof(RadialMenuButton), null); @@ -136,7 +137,7 @@ public Color? InnerTappedColor { get { return (Color?)GetValue(InnerTappedColorProperty); } set { SetValue(InnerTappedColorProperty, value); } - } + } public Color? InnerReleasedColor { get { return (Color?)GetValue(InnerReleasedColorProperty); } @@ -211,15 +212,15 @@ public void OnInnerArcReleased(Windows.UI.Xaml.Input.PointerRoutedEventArgs e) if (InnerArcReleasedEvent != null) { InnerArcReleasedEvent(this, e); - } - - if (this.Type != ButtonType.SIMPLE) - { - this.MenuSelected = true; } - if(this.Type == ButtonType.TOGGLE) - { - this.Value = this.Value ? false : true; + + if (this.Type != ButtonType.SIMPLE) + { + this.MenuSelected = true; + } + if(this.Type == ButtonType.TOGGLE) + { + this.Value = (bool)this.Value ? false : true; } } @@ -232,8 +233,8 @@ public void OnOuterArcReleased(Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { OuterArcReleasedEvent(this, e); } - } - + } + /// /// Does this radial menu button have events on the outer arc? /// @@ -243,13 +244,13 @@ public bool HasOuterArcEvents() return (OuterArcPressedEvent != null || OuterArcReleasedEvent != null); } - // SubMenu + // SubMenu can be a RadialMenu or a ListMenu public static readonly DependencyProperty SubmenuProperty = - DependencyProperty.Register("Submenu", typeof(RadialMenu), typeof(RadialMenuButton), null); + DependencyProperty.Register("Submenu", typeof(UserControl), typeof(RadialMenuButton), null); - public RadialMenu Submenu + public UserControl Submenu { - get { return (RadialMenu)GetValue(SubmenuProperty); } + get { return (UserControl)GetValue(SubmenuProperty); } set { SetValue(SubmenuProperty, value); } } diff --git a/RadialMenuControl/RadialMenuControl.csproj b/RadialMenuControl/RadialMenuControl.csproj index f552406..afbfd87 100644 --- a/RadialMenuControl/RadialMenuControl.csproj +++ b/RadialMenuControl/RadialMenuControl.csproj @@ -1,169 +1,176 @@ - - - - - Debug - AnyCPU - {A10EE2D6-D98A-4074-8B29-19A7702F9493} - Library - Properties - RadialMenuControl - RadialMenuControl - en-US - UAP - 10.0.10240.0 - 10.0.10240.0 - 14 - 512 - {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - false - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - prompt - 4 - - - ARM - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - ARM - false - prompt - - - ARM - bin\ARM\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - ARM - false - prompt - - - x64 - true - bin\x64\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - x64 - false - prompt - - - x64 - bin\x64\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - x64 - false - prompt - - - x86 - true - bin\x86\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - x86 - false - prompt - - - x86 - bin\x86\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - x86 - false - prompt - - - - - - - - RadialMenuButton.xaml - - - - - - - - - PieSlice.xaml - - - - Pie.xaml - - - RadialMenu.xaml - - - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - - - 14.0 - - - - - - + + + + + Debug + AnyCPU + {A10EE2D6-D98A-4074-8B29-19A7702F9493} + Library + Properties + RadialMenuControl + RadialMenuControl + en-US + UAP + 10.0.10240.0 + 10.0.10240.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + false + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + ARM + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + + + ARM + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + + + x64 + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + + + x64 + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + + + x86 + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + + + x86 + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + + + + + + + + RadialMenuButton.xaml + + + + + + + + + ListMenu.xaml + + + PieSlice.xaml + + + + Pie.xaml + + + RadialMenu.xaml + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + 14.0 + + + + + + + --> \ No newline at end of file diff --git a/RadialMenuControl/UserControl/ListMenu.xaml b/RadialMenuControl/UserControl/ListMenu.xaml new file mode 100644 index 0000000..4e0cf0d --- /dev/null +++ b/RadialMenuControl/UserControl/ListMenu.xaml @@ -0,0 +1,16 @@ + + + + + diff --git a/RadialMenuControl/UserControl/ListMenu.xaml.cs b/RadialMenuControl/UserControl/ListMenu.xaml.cs new file mode 100644 index 0000000..95f9fd1 --- /dev/null +++ b/RadialMenuControl/UserControl/ListMenu.xaml.cs @@ -0,0 +1,54 @@ +namespace RadialMenuControl.UserControl +{ + using RadialMenuControl.UserControl; + using RadialMenuControl.Components; + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.ComponentModel; + using System.Diagnostics; + using System.Runtime.CompilerServices; + using Windows.UI; + using Windows.UI.Xaml; + using Windows.UI.Xaml.Controls; + using Windows.UI.Xaml.Media; + using Windows.UI.Xaml.Automation.Peers; + using Windows.UI.Xaml.Automation.Provider; + + public sealed partial class ListMenu : UserControl + { + + private IList _listItems = new List(); + public IList ListItems + { + get { return _listItems; } + set + { + SetField(ref _listItems, value); + } + } + + public void AddButton(RadialMenuButton button) + { + _listItems.Add(button); + } + + public event PropertyChangedEventHandler PropertyChanged; + + public ListMenu() + { + this.InitializeComponent(); + layoutRoot.DataContext = this; + } + + private void SetField(ref T field, T value, [CallerMemberName] string propertyName = null) + { + if (!value.Equals(field)) + { + field = value; + var eventHandler = PropertyChanged; + eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +} diff --git a/RadialMenuControl/UserControl/Pie.xaml.cs b/RadialMenuControl/UserControl/Pie.xaml.cs index 3e4df7e..67eb8f7 100644 --- a/RadialMenuControl/UserControl/Pie.xaml.cs +++ b/RadialMenuControl/UserControl/Pie.xaml.cs @@ -201,17 +201,18 @@ public void Draw() } } - private void PieSlice_ChangeSelectedEvent(object sender, PieSlice slice) + private void PieSlice_ChangeSelectedEvent(object sender, PieSlice selectedSlice) { foreach(PieSlice ps in _pieSlices) { // find any previously selected Radio button to de-select - if(ps._radialMenuButton.Type == RadialMenuButton.ButtonType.RADIO && ps._radialMenuButton.MenuSelected && ps.StartAngle != slice.StartAngle) + if(ps._radialMenuButton.Type == RadialMenuButton.ButtonType.RADIO && ps._radialMenuButton.MenuSelected && ps.StartAngle != selectedSlice.StartAngle) { ps._radialMenuButton.MenuSelected = false; ps.updateSliceForRadio(); } } + this.SelectedItem = selectedSlice; } private void SetField(ref T field, T value, [CallerMemberName] string propertyName = null) diff --git a/RadialMenuControl/UserControl/PieSlice.xaml.cs b/RadialMenuControl/UserControl/PieSlice.xaml.cs index 7a82ef1..e8b9b54 100644 --- a/RadialMenuControl/UserControl/PieSlice.xaml.cs +++ b/RadialMenuControl/UserControl/PieSlice.xaml.cs @@ -195,10 +195,10 @@ public Visibility TextBlockVisibility DependencyProperty.Register("_radialMenuButton", typeof(Components.RadialMenuButton), typeof(PieSlice), null); // Change Menu - public delegate void ChangeMenuRequestHandler(object sender, RadialMenu submenu); + public delegate void ChangeMenuRequestHandler(object sender, UserControl submenu); public event ChangeMenuRequestHandler ChangeMenuRequestEvent; - private void OnChangeMenuRequest(object s, RadialMenu sm) + private void OnChangeMenuRequest(object s, UserControl sm) { if (ChangeMenuRequestEvent != null) { @@ -288,7 +288,7 @@ private void innerPieSlicePath_PointerEntered(object sender, Windows.UI.Xaml.Inp { if (_radialMenuButton.Type == Components.RadialMenuButton.ButtonType.TOGGLE) { - if (_radialMenuButton.Value) + if ((bool)_radialMenuButton.Value) { VisualStateManager.GoToState(this, "InnerReleased", true); } @@ -318,7 +318,7 @@ private void innerPieSlicePath_PointerExited(object sender, Windows.UI.Xaml.Inpu { if (_radialMenuButton.Type == Components.RadialMenuButton.ButtonType.TOGGLE) { - if (_radialMenuButton.Value) + if ((bool)_radialMenuButton.Value) { VisualStateManager.GoToState(this, "InnerReleased", true); } @@ -350,7 +350,7 @@ private void innerPieSlicePath_PointerReleased(object sender, Windows.UI.Xaml.In _radialMenuButton.OnInnerArcReleased(e); if(_radialMenuButton.Type == Components.RadialMenuButton.ButtonType.TOGGLE) { - if (_radialMenuButton.Value) + if ((bool)_radialMenuButton.Value) { VisualStateManager.GoToState(this, "InnerReleased", true); } diff --git a/RadialMenuControl/UserControl/RadialMenu.xaml b/RadialMenuControl/UserControl/RadialMenu.xaml index 61fb8d1..1072559 100644 --- a/RadialMenuControl/UserControl/RadialMenu.xaml +++ b/RadialMenuControl/UserControl/RadialMenu.xaml @@ -73,7 +73,10 @@ Background="{Binding CenterButtonBackgroundFill}" Height="{Binding CenterButtonSize}" BorderBrush="{Binding CenterButtonBorder}" - Opacity="1" /> + Opacity="1" + > + + diff --git a/RadialMenuControl/UserControl/RadialMenu.xaml.cs b/RadialMenuControl/UserControl/RadialMenu.xaml.cs index 8f405ff..fdd80e7 100644 --- a/RadialMenuControl/UserControl/RadialMenu.xaml.cs +++ b/RadialMenuControl/UserControl/RadialMenu.xaml.cs @@ -9,8 +9,10 @@ using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; - using Windows.UI.Xaml.Media; - + using Windows.UI.Xaml.Media; + using Windows.UI.Xaml.Automation.Peers; + using Windows.UI.Xaml.Automation.Provider; + public partial class RadialMenu : UserControl, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; @@ -264,12 +266,86 @@ private void OnCenterButtonTapped(object s, Windows.UI.Xaml.Input.TappedRoutedEv /// /// Sending object /// Menu to change to - public void ChangeMenu(object s, RadialMenu menu) + public void ChangeMenu(object s, UserControl menu) { - ChangePie(s, menu.pie, true); - ChangeCenterButton(s, Helpers.ButtonToShim(menu.centerButton), true); - } - + // If submenu is a Radial menu + if(menu.GetType() == typeof(RadialMenu)) + { + ChangePie(s, ((RadialMenu)menu).pie, true); + ChangeCenterButton(s, Helpers.ButtonToShim(((RadialMenu)menu).centerButton), true); + } + else // If submenu is a list menu + { + listmenu = (ListMenu)menu; + IList ListItems = listmenu.ListItems; + + TogglePie(); + centerButton.Visibility = Visibility.Collapsed; + + Style menuStyle = new Windows.UI.Xaml.Style { TargetType = typeof(MenuFlyoutPresenter) }; + menuStyle.Setters.Add(new Setter(WidthProperty, this.Width)); + menuStyle.Setters.Add(new Setter(MaxHeightProperty, this.Height/2)); + menuStyle.Setters.Add(new Setter(MarginProperty, new Thickness(0, 150, 0, 0))); + MenuFlyout flyoutMenu = new MenuFlyout(); + flyoutMenu.MenuFlyoutPresenterStyle = menuStyle; + + ToggleMenuFlyoutItem toggle = new ToggleMenuFlyoutItem(); + toggle.Text = "◀ Back"; + toggle.Click += ToggleMenu_Click; + flyoutMenu.Items.Add(toggle); + + flyoutMenu.Items.Add(new MenuFlyoutSeparator()); + foreach(RadialMenuButton btn in ListItems) + { + MenuFlyoutItem menuItem = new MenuFlyoutItem(); + menuItem.Text = btn.Label; + menuItem.Margin = new Thickness(0, 0, 50, 0); + flyoutMenu.Items.Add(menuItem); + if (btn.MenuSelected) + { + menuItem.Background = new SolidColorBrush (Colors.Gray); + } + menuItem.Click += MenuItem_Click; + } + RadialMenuButton pieButton = (RadialMenuButton)s; + centerButton.Flyout = flyoutMenu; + flyoutMenu.ShowAt(centerButton); + + ButtonAutomationPeer peer = new ButtonAutomationPeer(centerButton); + IInvokeProvider invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider; + invokeProv.Invoke(); + } + + } + + private void ToggleMenu_Click(object sender, RoutedEventArgs e) + { + centerButton.Visibility = Visibility.Visible; + TogglePie(); + centerButton.Flyout = null; + } + + private void MenuItem_Click(object sender, RoutedEventArgs e) + { + MenuFlyoutItem selectedItem = (MenuFlyoutItem)sender; + foreach(RadialMenuButton btn in listmenu.ListItems) + { + if(btn.Label == selectedItem.Text) + { + btn.MenuSelected = true; + + } + else if(btn.MenuSelected) + { + btn.MenuSelected = false; + } + } + centerButton.Visibility = Visibility.Visible; + TogglePie(); + centerButton.Flyout = null; + } + + /// /// Change the current pie - aka update the current radial menu buttons /// diff --git a/RadialMenuDemo/MainPage.xaml.cs b/RadialMenuDemo/MainPage.xaml.cs index 4620f0f..4598f43 100644 --- a/RadialMenuDemo/MainPage.xaml.cs +++ b/RadialMenuDemo/MainPage.xaml.cs @@ -13,15 +13,17 @@ public sealed partial class MainPage : Page { public MainPage() { + this.InitializeComponent(); + RadialMenuButton button1 = new RadialMenuButton(); button1.Label = "Rainbow Simple"; button1.Icon = "🌈"; button1.Type = RadialMenuButton.ButtonType.SIMPLE; button1.InnerArcPressedEvent += Button1_InnerArcPressedEvent; button1.OuterArcReleasedEvent += Button1_OuterArcReleasedEvent; - - button1.Submenu = new RadialMenu(); - button1.Submenu.CenterButtonIcon = ""; + + RadialMenu button1Submenu = new RadialMenu(); + button1Submenu.CenterButtonIcon = ""; RadialMenuButton button11 = new RadialMenuButton { Label = "World", Icon = "🌍" }; button11.Type = RadialMenuButton.ButtonType.RADIO; RadialMenuButton button12 = new RadialMenuButton { Label = "Sun", Icon = "🌞" }; @@ -30,12 +32,14 @@ public MainPage() button13.Type = RadialMenuButton.ButtonType.RADIO; RadialMenuButton button14 = new RadialMenuButton { Label = "Bento", Icon = "🍱" }; button14.Type = RadialMenuButton.ButtonType.RADIO; - button1.Submenu.AddButton(button11); - button1.Submenu.AddButton(button12); - button1.Submenu.AddButton(button13);; - button1.Submenu.AddButton(button14); - - + button1Submenu.AddButton(button11); + button1Submenu.AddButton(button12); + button1Submenu.AddButton(button13);; + button1Submenu.AddButton(button14); + button1.Submenu = button1Submenu; + + + RadialMenuButton button2 = new RadialMenuButton(); button2.Label = "Stop"; button2.IconImage = new BitmapImage(new Uri("ms-appx:///Assets/button_blue_stop.png")); @@ -61,10 +65,45 @@ public MainPage() button6.Icon = "💸"; button6.Type = RadialMenuButton.ButtonType.TOGGLE; - this.InitializeComponent(); + RadialMenuButton button7 = new RadialMenuButton(); + button7.Label = "Text Font Type"; + button7.Icon = "✎"; + button7.Type = RadialMenuButton.ButtonType.SIMPLE; + + ListMenu button7SubMenu = new ListMenu(); + RadialMenuButton button71 = new RadialMenuButton { Label = "Arial" }; + button71.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button72 = new RadialMenuButton { Label = "Calibri" }; + button72.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button73 = new RadialMenuButton { Label = "Cambria" }; + button73.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button74 = new RadialMenuButton { Label = "Courier" }; + button74.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button75 = new RadialMenuButton { Label = "Georgia" }; + button75.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button76 = new RadialMenuButton { Label = "Helvetica" }; + button76.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button77 = new RadialMenuButton { Label = "Tahoma" }; + button77.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button78 = new RadialMenuButton { Label = "Times New Roman" }; + button78.Type = RadialMenuButton.ButtonType.LIST; + RadialMenuButton button79 = new RadialMenuButton { Label = "Verdana" }; + button79.Type = RadialMenuButton.ButtonType.LIST; + button7SubMenu.AddButton(button71); + button7SubMenu.AddButton(button72); + button7SubMenu.AddButton(button73); + button7SubMenu.AddButton(button74); + button7SubMenu.AddButton(button75); + button7SubMenu.AddButton(button76); + button7SubMenu.AddButton(button77); + button7SubMenu.AddButton(button78); + button7SubMenu.AddButton(button79); + button7.Submenu = button7SubMenu; + radialMenu.AddButton(button1); radialMenu.AddButton(button2); - radialMenu.AddButton(button3); + radialMenu.AddButton(button3); + radialMenu.AddButton(button7); radialMenu.AddButton(button4); radialMenu.AddButton(button5); radialMenu.AddButton(button6); @@ -73,8 +112,8 @@ public MainPage() layoutRoot.DataContext = this; radialMenu.PropertyChanged += RadialMenu_PropertyChanged; - } - + } + private void RadialMenu_CenterButtonTappedEvent(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { Debug.WriteLine("Hi from center button!");