├── .gitignore
├── LICENSE
├── README.md
├── RadialMenu.sln
├── RadialMenuControl
├── Components
│ ├── CenterButton.xaml
│ ├── CenterButton.xaml.cs
│ ├── RadialMenuButton.xaml
│ └── RadialMenuButton.xaml.cs
├── Extensions
│ ├── ColorExtensions.cs
│ └── StoryboardExtension.cs
├── InnerPieSlicePath.cs
├── Properties
│ └── AssemblyInfo.cs
├── RadialMenuControl.csproj
├── RadialMenuControl.nuspec
├── Shims
│ └── Shims.cs
├── Themes
│ ├── Colors.cs
│ ├── Generic.xaml
│ └── Styles.xaml
├── UserControl
│ ├── Floating.cs
│ ├── ListSubMenu.xaml
│ ├── ListSubMenu.xaml.cs
│ ├── MenuBase.cs
│ ├── MeterSubMenu.xaml
│ ├── MeterSubmenu.xaml.cs
│ ├── MeterSubmenuPath.cs
│ ├── OuterPieSlicePath.cs
│ ├── PathBase.cs
│ ├── Pie.xaml
│ ├── Pie.xaml.cs
│ ├── PieSlice.xaml
│ ├── PieSlice.xaml.cs
│ ├── RadialMenu.xaml
│ └── RadialMenu.xaml.cs
├── nuget
│ └── RadialMenuControl.targets
├── project.json
└── project.lock.json
├── RadialMenuDemo
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── LockScreenLogo.scale-200.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── StoreLogo.png
│ ├── Wide310x150Logo.scale-200.png
│ ├── background.jpg
│ ├── background2.jpg
│ └── button_blue_stop.png
├── Icons
│ ├── Chisel Tip Marker-50.png
│ ├── Cursor-50.png
│ ├── Delete-50.png
│ ├── Hand Cursor-50.png
│ ├── Icons License.txt
│ ├── Polygon-50.png
│ ├── Strikethrough-50.png
│ ├── Text Cursor-50.png
│ ├── Underline-50.png
│ ├── opacity.png
│ └── stroke.png
├── MainPage.xaml
├── MainPage.xaml.cs
├── Melbourne.xaml
├── Melbourne.xaml.cs
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── RadialMenuDemo.csproj
├── project.json
└── project.lock.json
└── RadialMenuUITests
├── CodedUITest1.cs
├── Properties
└── AssemblyInfo.cs
└── RadialMenuUITests.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | *_i.c
42 | *_p.c
43 | *_i.h
44 | *.ilk
45 | *.meta
46 | *.obj
47 | *.pch
48 | *.pdb
49 | *.pgc
50 | *.pgd
51 | *.rsp
52 | *.sbr
53 | *.tlb
54 | *.tli
55 | *.tlh
56 | *.tmp
57 | *.tmp_proj
58 | *.log
59 | *.vspscc
60 | *.vssscc
61 | .builds
62 | *.pidb
63 | *.svclog
64 | *.scc
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 | # TODO: Comment the next line if you want to checkin your web deploy settings
133 | # but database connection strings (with potential passwords) will be unencrypted
134 | *.pubxml
135 | *.publishproj
136 |
137 | # NuGet Packages
138 | *.nupkg
139 | # The packages folder can be ignored because of Package Restore
140 | **/packages/*
141 | # except build/, which is used as an MSBuild target.
142 | !**/packages/build/
143 | # Uncomment if necessary however generally it will be regenerated when needed
144 | #!**/packages/repositories.config
145 |
146 | # Windows Azure Build Output
147 | csx/
148 | *.build.csdef
149 |
150 | # Windows Store app package directory
151 | AppPackages/
152 |
153 | # Others
154 | *.[Cc]ache
155 | ClientBin/
156 | [Ss]tyle[Cc]op.*
157 | ~$*
158 | *~
159 | *.dbmdl
160 | *.dbproj.schemaview
161 | *.pfx
162 | *.publishsettings
163 | node_modules/
164 | bower_components/
165 |
166 | # RIA/Silverlight projects
167 | Generated_Code/
168 |
169 | # Backup & report files from converting an old project file
170 | # to a newer Visual Studio version. Backup files are not needed,
171 | # because we have git ;-)
172 | _UpgradeReport_Files/
173 | Backup*/
174 | UpgradeLog*.XML
175 | UpgradeLog*.htm
176 |
177 | # SQL Server files
178 | *.mdf
179 | *.ldf
180 |
181 | # Business Intelligence projects
182 | *.rdl.data
183 | *.bim.layout
184 | *.bim_*.settings
185 |
186 | # Microsoft Fakes
187 | FakesAssemblies/
188 |
189 | # Node.js Tools for Visual Studio
190 | .ntvs_analysis.dat
191 |
192 | # Visual Studio 6 build log
193 | *.plg
194 |
195 | # Visual Studio 6 workspace options file
196 | *.opt
197 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Catalyst Code
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Radial Menu
2 | A Radial Menu for Windows UWP Applications, as made popular by the first versions of the modern OneNote App for Windows. Create radial menus floating op top of your application. The control supports variable numbers of buttons, toggle & radio buttons, a selector for long lists, and a fancy metered
3 | menu for intuitive selection of numbers.
4 |
5 | 
6 |
7 | ## Installation
8 |
9 | Install this component via nuget by doing:
10 |
11 | ```
12 | PM> Install-Package RadialMenuControl
13 | ```
14 |
15 | Or add it to your project directly by searching for `RadialMenuControl` in Nuget Package Manager for Visual Studio.
16 |
17 | ## Documentation
18 |
19 | Want to learn how to place this control into your application? It's pretty easy to do - just head over to our [documentation wiki](https://github.com/CatalystCode/radial-menu/wiki) to find out how!
20 |
21 | ## Special Thanks
22 | A bunch of thanks to [Jason Poon](https://github.com/jpoon), who wrote an early version of this code (and helpes us all a lot).
23 |
24 | ## License
25 |
26 | Copyright (C) 2015 Microsoft, licensed MIT. Please check `LICENSE` for details.
27 |
--------------------------------------------------------------------------------
/RadialMenu.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RadialMenuDemo", "RadialMenuDemo\RadialMenuDemo.csproj", "{F2169718-9CB4-4A32-BCAB-92E254B74213}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RadialMenuControl", "RadialMenuControl\RadialMenuControl.csproj", "{A10EE2D6-D98A-4074-8B29-19A7702F9493}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|ARM = Debug|ARM
14 | Debug|x64 = Debug|x64
15 | Debug|x86 = Debug|x86
16 | Release|Any CPU = Release|Any CPU
17 | Release|ARM = Release|ARM
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|Any CPU.ActiveCfg = Debug|x86
23 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|Any CPU.Build.0 = Debug|x86
24 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|Any CPU.Deploy.0 = Debug|x86
25 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|ARM.ActiveCfg = Debug|ARM
26 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|ARM.Build.0 = Debug|ARM
27 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|ARM.Deploy.0 = Debug|ARM
28 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|x64.ActiveCfg = Debug|x64
29 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|x64.Build.0 = Debug|x64
30 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|x64.Deploy.0 = Debug|x64
31 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|x86.ActiveCfg = Debug|x86
32 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|x86.Build.0 = Debug|x86
33 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Debug|x86.Deploy.0 = Debug|x86
34 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|Any CPU.ActiveCfg = Release|x86
35 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|ARM.ActiveCfg = Release|ARM
36 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|ARM.Build.0 = Release|ARM
37 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|ARM.Deploy.0 = Release|ARM
38 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|x64.ActiveCfg = Release|x64
39 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|x64.Build.0 = Release|x64
40 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|x64.Deploy.0 = Release|x64
41 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|x86.ActiveCfg = Release|x86
42 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|x86.Build.0 = Release|x86
43 | {F2169718-9CB4-4A32-BCAB-92E254B74213}.Release|x86.Deploy.0 = Release|x86
44 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
47 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|ARM.ActiveCfg = Debug|ARM
48 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|ARM.Build.0 = Debug|ARM
49 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|x64.ActiveCfg = Debug|x64
50 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|x64.Build.0 = Debug|x64
51 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|x86.ActiveCfg = Debug|x86
52 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Debug|x86.Build.0 = Debug|x86
53 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|Any CPU.Build.0 = Release|Any CPU
55 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|ARM.ActiveCfg = Release|ARM
56 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|ARM.Build.0 = Release|ARM
57 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|x64.ActiveCfg = Release|x64
58 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|x64.Build.0 = Release|x64
59 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|x86.ActiveCfg = Release|x86
60 | {A10EE2D6-D98A-4074-8B29-19A7702F9493}.Release|x86.Build.0 = Release|x86
61 | EndGlobalSection
62 | GlobalSection(SolutionProperties) = preSolution
63 | HideSolutionNode = FALSE
64 | EndGlobalSection
65 | EndGlobal
66 |
--------------------------------------------------------------------------------
/RadialMenuControl/Components/CenterButton.xaml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/RadialMenuControl/Components/CenterButton.xaml.cs:
--------------------------------------------------------------------------------
1 | using Windows.UI.Xaml.Controls;
2 |
3 | namespace RadialMenuControl.Components
4 | {
5 | public partial class CenterButton : Button
6 | {
7 | ///
8 | /// The Canvas Top of the center button
9 | ///
10 | public double? Top { get; set; }
11 | ///
12 | /// The Canvas Left of the center button
13 | ///
14 | public double? Left { get; set; }
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RadialMenuControl/Components/RadialMenuButton.xaml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/RadialMenuControl/Components/RadialMenuButton.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reflection;
4 | using Windows.UI;
5 | using Windows.UI.Xaml;
6 | using Windows.UI.Xaml.Controls;
7 | using Windows.UI.Xaml.Input;
8 | using Windows.UI.Xaml.Media;
9 | using RadialMenuControl.UserControl;
10 |
11 | namespace RadialMenuControl.Components
12 | {
13 | public partial class RadialMenuButton : Button
14 | {
15 | public enum ButtonType
16 | {
17 | Simple = 0,
18 | Radio,
19 | Toggle,
20 | Custom
21 | };
22 |
23 | // SubMenu
24 | public static readonly DependencyProperty SubmenuProperty =
25 | DependencyProperty.Register("Submenu", typeof (RadialMenu), typeof (RadialMenuButton), null);
26 |
27 | public RadialMenuButton()
28 | {
29 | InitializeComponent();
30 | }
31 |
32 | ///
33 | /// A RadialMenu that is opened when the user presses the button
34 | ///
35 | public RadialMenu Submenu
36 | {
37 | get { return (RadialMenu) GetValue(SubmenuProperty); }
38 | set { SetValue(SubmenuProperty, value); }
39 | }
40 |
41 | ///
42 | /// Allows the use of key/value pairs to set the colors
43 | ///
44 | /// Dictionary containing colors in a key/value pair
45 | public void SetColors(Dictionary colors)
46 | {
47 | foreach (var colorVariable in colors)
48 | {
49 | if (GetType().GetProperty(colorVariable.Key) != null)
50 | {
51 | var prop = GetType().GetProperty(colorVariable.Key);
52 | prop.SetValue(this, colorVariable.Value);
53 | }
54 | }
55 | }
56 |
57 | # region properties
58 |
59 | // Label
60 | public static readonly DependencyProperty LabelProperty =
61 | DependencyProperty.Register("Label", typeof (string), typeof (RadialMenuButton), new PropertyMetadata(""));
62 |
63 | public static readonly DependencyProperty LabelSizeProperty =
64 | DependencyProperty.Register("LabelSize", typeof (int), typeof (RadialMenuButton), new PropertyMetadata(10));
65 |
66 | public static readonly DependencyProperty IsLabelHiddenProperty =
67 | DependencyProperty.Register("IsLabelHidden", typeof (bool), typeof (RadialMenuButton), null);
68 |
69 | public static readonly DependencyProperty IconProperty =
70 | DependencyProperty.Register("Icon", typeof (string), typeof (RadialMenuButton), new PropertyMetadata(""));
71 |
72 | public static readonly DependencyProperty IconFontFamilyProperty =
73 | DependencyProperty.Register("IconFontFamily", typeof (FontFamily), typeof (RadialMenuButton),
74 | new PropertyMetadata(new FontFamily("Segoe UI")));
75 |
76 | public static readonly DependencyProperty IconForegroundBrushProperty =
77 | DependencyProperty.Register("IconForegroundBrush", typeof (Brush), typeof (RadialMenuButton),
78 | new PropertyMetadata(new SolidColorBrush(Colors.Black)));
79 |
80 | public static readonly DependencyProperty IconSizeProperty =
81 | DependencyProperty.Register("IconSize", typeof (int), typeof (RadialMenuButton), new PropertyMetadata(26));
82 |
83 | public static readonly DependencyProperty IconImageProperty =
84 | DependencyProperty.Register("IconImage", typeof (ImageSource), typeof (RadialMenuButton), null);
85 |
86 | public static readonly DependencyProperty MenuSeletedProperty =
87 | DependencyProperty.Register("MenuSelected", typeof (bool), typeof (RadialMenuButton), null);
88 |
89 | public static readonly DependencyProperty ButtonTypeProperty =
90 | DependencyProperty.Register("ButtonType", typeof (ButtonType), typeof (RadialMenuButton),
91 | new PropertyMetadata(ButtonType.Simple));
92 |
93 | public static readonly DependencyProperty ValueProperty =
94 | DependencyProperty.Register("Value", typeof (object), typeof (RadialMenuButton), null);
95 |
96 | ///
97 | /// Label, displayed in the inner portion of the button
98 | ///
99 | public string Label
100 | {
101 | get { return (string) GetValue(LabelProperty) ?? ""; }
102 | set { SetValue(LabelProperty, value); }
103 | }
104 |
105 | ///
106 | /// Font Size for the label
107 | ///
108 | public int LabelSize
109 | {
110 | get { return (int) GetValue(LabelSizeProperty); }
111 | set { SetValue(LabelProperty, value); }
112 | }
113 |
114 | ///
115 | /// Should the label be hidden?
116 | ///
117 | public bool IsLabelHidden
118 | {
119 | get { return (bool) GetValue(IsLabelHiddenProperty); }
120 | set { SetValue(IsLabelHiddenProperty, value); }
121 | }
122 |
123 | ///
124 | /// Text-based icon, displayed in a TextBox (usually used with icon fonts)
125 | ///
126 | public string Icon
127 | {
128 | get { return (string) GetValue(IconProperty); }
129 | set { SetValue(IconProperty, value); }
130 | }
131 |
132 | ///
133 | /// Font for the text-based icon
134 | ///
135 | public FontFamily IconFontFamily
136 | {
137 | get { return (FontFamily) GetValue(IconFontFamilyProperty); }
138 | set { SetValue(IconFontFamilyProperty, value); }
139 | }
140 |
141 | ///
142 | /// Font size for the text-based icon
143 | ///
144 | public int IconSize
145 | {
146 | get { return (int) GetValue(IconSizeProperty); }
147 | set { SetValue(IconProperty, value); }
148 | }
149 |
150 | ///
151 | /// ForegroundBrush for the text-based icon
152 | ///
153 | public Brush IconForegroundBrush
154 | {
155 | get { return (Brush) GetValue(IconForegroundBrushProperty); }
156 | set { SetValue(IconForegroundBrushProperty, value); }
157 | }
158 |
159 | ///
160 | /// A ImageSource for the icon. If set, the text-based icon will be hidden.
161 | ///
162 | public ImageSource IconImage
163 | {
164 | get { return (ImageSource) GetValue(IconImageProperty); }
165 | set { SetValue(IconImageProperty, value); }
166 | }
167 |
168 | // Values & Button Type
169 | ///
170 | /// If the button is a radio button and selected on behalf of the whole RadialMenu, this value will be true (false
171 | /// otherwise)
172 | ///
173 | public bool MenuSelected
174 | {
175 | get { return (bool) GetValue(MenuSeletedProperty); }
176 | set { SetValue(MenuSeletedProperty, value); }
177 | }
178 |
179 | ///
180 | /// Value of this button
181 | ///
182 | public object Value
183 | {
184 | get { return GetValue(ValueProperty); }
185 | set
186 | {
187 | if (Type == ButtonType.Simple)
188 | {
189 | throw new Exception("A button of type SIMPLE should not have any value.");
190 | }
191 | SetValue(ValueProperty, value);
192 | }
193 | }
194 |
195 | ///
196 | /// Button type, indicating the way users can interact with this button
197 | ///
198 | public ButtonType Type
199 | {
200 | get { return (ButtonType) GetValue(ButtonTypeProperty); }
201 | set { SetValue(ButtonTypeProperty, value); }
202 | }
203 |
204 | // Inner Arc Colors
205 | public static readonly DependencyProperty InnerNormalColorProperty =
206 | DependencyProperty.Register("InnerNormalColor", typeof (Color?), typeof (RadialMenuButton), null);
207 |
208 | public static readonly DependencyProperty InnerHoverColorProperty =
209 | DependencyProperty.Register("InnerHoverColor", typeof (Color?), typeof (RadialMenuButton), null);
210 |
211 | public static readonly DependencyProperty InnerTappedColorProperty =
212 | DependencyProperty.Register("InnerTappedColor", typeof (Color?), typeof (RadialMenuButton), null);
213 |
214 | public static readonly DependencyProperty InnerReleasedColorProperty =
215 | DependencyProperty.Register("InnerReleasedColor", typeof (Color?), typeof (RadialMenuButton), null);
216 |
217 | ///
218 | /// Hover color for the inner portion of the button
219 | ///
220 | public Color? InnerHoverColor
221 | {
222 | get { return (Color?) GetValue(InnerHoverColorProperty); }
223 | set { SetValue(InnerHoverColorProperty, value); }
224 | }
225 |
226 | ///
227 | /// Normal color for the inner portion of the button
228 | ///
229 | public Color? InnerNormalColor
230 | {
231 | get { return (Color?) GetValue(InnerNormalColorProperty); }
232 | set { SetValue(InnerNormalColorProperty, value); }
233 | }
234 |
235 | ///
236 | /// Tapped color for the inner portion of the button
237 | ///
238 | public Color? InnerTappedColor
239 | {
240 | get { return (Color?) GetValue(InnerTappedColorProperty); }
241 | set { SetValue(InnerTappedColorProperty, value); }
242 | }
243 |
244 | ///
245 | /// Released color for the inner portion of the button
246 | ///
247 | public Color? InnerReleasedColor
248 | {
249 | get { return (Color?) GetValue(InnerReleasedColorProperty); }
250 | set { SetValue(InnerReleasedColorProperty, value); }
251 | }
252 |
253 | // Outer Arc Colors
254 | public static readonly DependencyProperty OuterNormalColorProperty =
255 | DependencyProperty.Register("OuterNormalColor", typeof (Color?), typeof (RadialMenuButton), null);
256 |
257 | public static readonly DependencyProperty OuterDisabledColorProperty =
258 | DependencyProperty.Register("OuterDisabledColor", typeof (Color?), typeof (RadialMenuButton), null);
259 |
260 | public static readonly DependencyProperty OuterHoverColorProperty =
261 | DependencyProperty.Register("OuterHoverColor", typeof (Color?), typeof (RadialMenuButton), null);
262 |
263 | public static readonly DependencyProperty OuterTappedColorProperty =
264 | DependencyProperty.Register("OuterTappedColor", typeof (Color?), typeof (RadialMenuButton), null);
265 |
266 | public static readonly DependencyProperty OuterThicknessProperty =
267 | DependencyProperty.Register("OuterThickness", typeof (double?), typeof (RadialMenuButton), null);
268 |
269 | public static readonly DependencyProperty StrokeColorProperty =
270 | DependencyProperty.Register("StrokeColor", typeof (Color?), typeof (RadialMenuButton), null);
271 |
272 | public static readonly DependencyProperty StrokeThicknessProperty =
273 | DependencyProperty.Register("StrokeThickness", typeof (double?), typeof (RadialMenuButton), null);
274 |
275 | // Indication Arc
276 | public static readonly DependencyProperty UseIndicationArcProperty =
277 | DependencyProperty.Register("UseIndicationArcProperty", typeof (bool?), typeof (RadialMenuButton), null);
278 |
279 | public static readonly DependencyProperty IndicationArcColorProperty =
280 | DependencyProperty.Register("IndicationArcColor", typeof (Color?), typeof (RadialMenuButton), null);
281 |
282 | public static readonly DependencyProperty IndicationArcStrokeThicknessProperty =
283 | DependencyProperty.Register("IndicationArcStrokeThickness", typeof (double?), typeof (RadialMenuButton),
284 | null);
285 |
286 | public static readonly DependencyProperty IndicationArcDistanceFromEdgeProperty =
287 | DependencyProperty.Register("IndicationArcDistanceFromEdge", typeof (double?), typeof (RadialMenuButton),
288 | null);
289 |
290 | ///
291 | /// Distance from the inner part of the outer band to the indication arc
292 | ///
293 | public double? IndicationArcDistanceFromEdge
294 | {
295 | get { return (double?) GetValue(IndicationArcDistanceFromEdgeProperty); }
296 | set { SetValue(IndicationArcDistanceFromEdgeProperty, value); }
297 | }
298 |
299 | ///
300 | /// When set to true, an indication arc will be placed on this button
301 | ///
302 | public bool? UseIndicationArc
303 | {
304 | get { return (bool?) GetValue(UseIndicationArcProperty); }
305 | set { SetValue(UseIndicationArcProperty, value); }
306 | }
307 |
308 | public Color? IndicationArcColor
309 | {
310 | get { return (Color?) GetValue(IndicationArcColorProperty); }
311 | set { SetValue(IndicationArcColorProperty, value); }
312 | }
313 |
314 | ///
315 | /// The Stroke thickness of the indication arc
316 | ///
317 | public double? IndicationArcStrokeThickness
318 | {
319 | get { return (double?) GetValue(IndicationArcStrokeThicknessProperty); }
320 | set { SetValue(IndicationArcStrokeThicknessProperty, value); }
321 | }
322 |
323 | ///
324 | /// Hover color for the outer portion of the button
325 | ///
326 | public Color? OuterHoverColor
327 | {
328 | get { return (Color?) GetValue(OuterHoverColorProperty); }
329 | set { SetValue(OuterHoverColorProperty, value); }
330 | }
331 |
332 | ///
333 | /// Normal color for the outer portion of the button
334 | ///
335 | public Color? OuterNormalColor
336 | {
337 | get { return (Color?) GetValue(OuterNormalColorProperty); }
338 | set { SetValue(OuterNormalColorProperty, value); }
339 | }
340 |
341 | ///
342 | /// Disabled color for the outer portion of the button
343 | ///
344 | public Color? OuterDisabledColor
345 | {
346 | get { return (Color?) GetValue(OuterDisabledColorProperty); }
347 | set { SetValue(OuterDisabledColorProperty, value); }
348 | }
349 |
350 | ///
351 | /// Tapped color for the outer portion of the button
352 | ///
353 | public Color? OuterTappedColor
354 | {
355 | get { return (Color?) GetValue(OuterTappedColorProperty); }
356 | set { SetValue(OuterTappedColorProperty, value); }
357 | }
358 |
359 | // Stroke
360 | ///
361 | /// Color of the stroke around the PieSLice
362 | ///
363 | public Color? StrokeColor
364 | {
365 | get { return (Color?) GetValue(StrokeColorProperty); }
366 | set { SetValue(StrokeColorProperty, value); }
367 | }
368 |
369 | ///
370 | /// Thickness of the stroke around the PieSlice
371 | ///
372 | public double? StrokeThickness
373 | {
374 | get { return (double?) GetValue(StrokeThicknessProperty); }
375 | set { SetValue(StrokeThicknessProperty, value); }
376 | }
377 |
378 | ///
379 | /// Thickness of the outer arc, on the outer side of the button
380 | ///
381 | public double? OuterThickness
382 | {
383 | get { return (double?) GetValue(OuterThicknessProperty); }
384 | set { SetValue(OuterThicknessProperty, value); }
385 | }
386 |
387 | // CustomMenu
388 | public static readonly DependencyProperty CustomMenuProperty =
389 | DependencyProperty.Register("Submenu", typeof (MenuBase), typeof (RadialMenuButton), null);
390 |
391 | ///
392 | /// CustomMenu behind the button
393 | ///
394 | public MenuBase CustomMenu
395 | {
396 | get { return (MenuBase) GetValue(CustomMenuProperty); }
397 | set { SetValue(CustomMenuProperty, value); }
398 | }
399 |
400 | // Access Keys
401 | ///
402 | /// Outer slice path access key
403 | ///
404 | public string OuterAccessKey
405 | {
406 | get { return (string)GetValue(OuterAccessKeyProperty); }
407 | set { SetValue(OuterAccessKeyProperty, value); }
408 | }
409 |
410 | ///
411 | /// Inner slice path access key
412 | ///
413 | public string InnerAccessKey
414 | {
415 | get { return (string)GetValue(InnerAccessKeyProperty); }
416 | set { SetValue(InnerAccessKeyProperty, value); }
417 | }
418 |
419 | #endregion properties
420 |
421 | #region events
422 |
423 | ///
424 | /// Delegate for the ValueChangedEvent, fired whenever the value of this button is changed
425 | ///
426 | ///
427 | ///
428 | public delegate void ValueChangedHandler(object sender, RoutedEventArgs args);
429 |
430 | public event ValueChangedHandler ValueChanged;
431 |
432 | public void OnValueChanged(RoutedEventArgs e)
433 | {
434 | ValueChanged?.Invoke(this, e);
435 | }
436 |
437 | public static readonly DependencyProperty InnerAccessKeyProperty =
438 | DependencyProperty.Register("InnerAccessKey", typeof (string), typeof (RadialMenuButton), null);
439 |
440 | public static readonly DependencyProperty OuterAccessKeyProperty =
441 | DependencyProperty.Register("OuterAccessKey", typeof (string), typeof (RadialMenuButton), null);
442 |
443 | ///
444 | /// Does this radial menu button have events on the outer arc?
445 | ///
446 | ///
447 | public bool HasOuterArcEvents => (OuterArcPressed != null || OuterArcReleased != null);
448 |
449 | ///
450 | /// Does this radial menu button have actions on the outer arc?
451 | ///
452 | ///
453 | public bool HasOuterArcAction => (Submenu != null || CustomMenu != null || HasOuterArcEvents);
454 |
455 | public delegate void InnerArcPressedEventHandler(object sender, PointerRoutedEventArgs e);
456 |
457 | ///
458 | /// Invoked when the inner arc of the button has been pressed (mouse, touch, stylus)
459 | ///
460 | public event InnerArcPressedEventHandler InnerArcPressed;
461 |
462 | public void OnInnerArcPressed(PointerRoutedEventArgs e)
463 | {
464 | InnerArcPressed?.Invoke(this, e);
465 |
466 | if (Type != ButtonType.Simple)
467 | {
468 | MenuSelected = true;
469 | }
470 | if (Type == ButtonType.Toggle)
471 | {
472 | Value = (Value == null || !(bool) Value);
473 | }
474 | }
475 |
476 | public delegate void OuterArcPressedEventHandler(object sender, PointerRoutedEventArgs e);
477 |
478 | ///
479 | /// Invoked when the outer arc of the button has been pressed (mouse, touch, stylus)
480 | ///
481 | public event OuterArcPressedEventHandler OuterArcPressed;
482 |
483 | public void OnOuterArcPressed(PointerRoutedEventArgs e)
484 | {
485 | OuterArcPressed?.Invoke(this, e);
486 | }
487 |
488 | public delegate void InnerArcReleasedEventHandler(object sender, PointerRoutedEventArgs e);
489 |
490 | ///
491 | /// Invoked when the inner arc of the button has been released (mouse, touch, stylus)
492 | ///
493 | public event InnerArcReleasedEventHandler InnerArcReleased;
494 |
495 | public void OnInnerArcReleased(PointerRoutedEventArgs e)
496 | {
497 | InnerArcReleased?.Invoke(this, e);
498 | }
499 |
500 | public delegate void OuterArcReleasedEventHandler(object sender, PointerRoutedEventArgs e);
501 |
502 | ///
503 | /// Invoked when the outer arc of the button has been pressed (mouse, touch, stylus)
504 | ///
505 | public event OuterArcReleasedEventHandler OuterArcReleased;
506 |
507 | public void OnOuterArcReleased(PointerRoutedEventArgs e)
508 | {
509 | OuterArcReleased?.Invoke(this, e);
510 | }
511 |
512 | #endregion
513 | }
514 | }
--------------------------------------------------------------------------------
/RadialMenuControl/Extensions/ColorExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace RadialMenuControl.Extensions
2 | {
3 | using Windows.UI;
4 |
5 | public static class ColorExtensions
6 | {
7 | private const float DefaultCorrectionFactor = 0.1f;
8 |
9 | ///
10 | /// Lightens a given color
11 | ///
12 | /// The source Color
13 | /// The correction factor to use when ligtening
14 | ///
15 | public static Color Lighten(this Color source, float correctionFactor = DefaultCorrectionFactor)
16 | {
17 | var red = (255 - source.R) * correctionFactor + source.R;
18 | var green = (255 - source.G) * correctionFactor + source.G;
19 | var blue = (255 - source.B) * correctionFactor + source.B;
20 | return Color.FromArgb(source.A, (byte)red, (byte)green, (byte)blue);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/RadialMenuControl/Extensions/StoryboardExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Windows.UI.Xaml.Media.Animation;
4 |
5 | namespace RadialMenuControl.Extensions
6 | {
7 | public static class StoryboardExtension
8 | {
9 | ///
10 | /// Plays the storyboard and returns an awaitable Task
11 | ///
12 | ///
13 | ///
14 | public static Task PlayAsync(this Storyboard storyboard)
15 | {
16 | var tcs = new TaskCompletionSource();
17 | if (storyboard == null)
18 | tcs.SetException(new ArgumentNullException());
19 | else
20 | {
21 | EventHandler