├── Licence.txt ├── README.md ├── bin └── Protractor_v1_1.xap ├── doc ├── ApplicationIcon.xcf ├── ApplicationIconLarge.xcf ├── length_measure.jpg ├── length_measure_small.png └── settings.jpg └── src ├── Protractor.sln └── Protractor ├── App.xaml ├── App.xaml.cs ├── ApplicationIcon.png ├── Background.png ├── BrowserMouseHelper.cs ├── MainPage.xaml ├── MainPage.xaml.cs ├── Properties ├── AppManifest.xml ├── AssemblyInfo.cs └── WMAppManifest.xml ├── Protractor.csproj ├── SplashScreenImage.jpg ├── html ├── index.html ├── papergrid.png ├── script.js ├── settings.png └── style.css ├── index.html ├── script.js └── style.css /Licence.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2012-2014 Microsoft Mobile Oy. All rights reserved. 2 | 3 | Microsoft is a registered trademark of Microsoft Corporation. Nokia and HERE are 4 | trademarks and/or registered trademarks of Nokia Corporation. Other product and 5 | company names mentioned herein may be trademarks or trade names of their 6 | respective owners. 7 | 8 | 9 | License 10 | 11 | Subject to the conditions below, you may use, copy, modify and/or merge copies 12 | of this software and associated content and documentation files (the ”Software”) 13 | to test, develop, publish, distribute, sub-license and/or sell new software 14 | derived from or incorporating the Software, solely in connection with Microsoft 15 | Mobile devices (however branded). Some of the documentation, content and/or 16 | software may be licensed under open source software or other licenses. To the 17 | extent such documentation, content and/or software are included, those licenses 18 | and/or other terms and conditions shall apply in addition and/or instead of this 19 | notice. The exact terms of the licenses, disclaimers, acknowledgements and 20 | notices are reproduced in the materials provided, or in other obvious locations. 21 | No other license to any other intellectual property rights is granted herein. 22 | 23 | This file, unmodified, shall be included with all copies or substantial portions 24 | of the Software that are distributed in source code form. 25 | 26 | The Software cannot constitute the primary value of any new software derived 27 | from or incorporating the Software. 28 | 29 | Any person dealing with the Software shall not misrepresent the source of the 30 | Software. 31 | 32 | 33 | Disclaimer 34 | 35 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 36 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 37 | FOR A PARTICULAR PURPOSE, QUALITY AND NONINFRINGEMENT. IN NO EVENT SHALL THE 38 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES (INCLUDING, 39 | WITHOUT LIMITATION, DIRECT, SPECIAL, INDIRECT, PUNITIVE, CONSEQUENTIAL, 40 | EXEMPLARY AND/ OR INCIDENTAL DAMAGES) OR OTHER LIABILITY, WHETHER IN AN ACTION 41 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 42 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 43 | 44 | Microsoft Mobile Oy retains the right to make changes to this document at any 45 | time, without notice. 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Protractor 2 | ========== 3 | 4 | HTML5 application for Windows Phone that allows the screen to be used as 5 | protractor/ruler to measure lengths and angles. The Protractor application 6 | utilizes HTML5 Canvas element to do all of the drawing. The HTML content is 7 | run in the WebBrowser element in Silverlight. 8 | 9 | ![Screenshot](doc/length_measure_small.png?raw=true) 10 | 11 | This project is hosted in GitHub: https://github.com/Microsoft/protractor 12 | 13 | Developed with Microsoft Visual Studio 2010 Express for Windows Phone. Tested 14 | with Nokia Lumia 800. 15 | 16 | **What's new in version 1.1** 17 | 18 | The Protractor now supports wider range of Windows Phones that just Nokia Lumia 19 | 800, as it is possible to adjust the screen length to set the correct spacing to 20 | ruler. Now it is also possible to set the ruler length units between inches and 21 | millimeters. 22 | 23 | 24 | License 25 | -------------------------------------------------------------------------------- 26 | 27 | See the license text file delivered with this project. The license is also 28 | available online at 29 | https://github.com/Microsoft/protractor/blob/master/Licence.txt 30 | 31 | 32 | Version history 33 | -------------------------------------------------------------------------------- 34 | 35 | * Version 1.1: Wider device support. The units of measures expanded. 36 | * Version 1.0: The initial release. 37 | -------------------------------------------------------------------------------- /bin/Protractor_v1_1.xap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/bin/Protractor_v1_1.xap -------------------------------------------------------------------------------- /doc/ApplicationIcon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/doc/ApplicationIcon.xcf -------------------------------------------------------------------------------- /doc/ApplicationIconLarge.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/doc/ApplicationIconLarge.xcf -------------------------------------------------------------------------------- /doc/length_measure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/doc/length_measure.jpg -------------------------------------------------------------------------------- /doc/length_measure_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/doc/length_measure_small.png -------------------------------------------------------------------------------- /doc/settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/doc/settings.jpg -------------------------------------------------------------------------------- /src/Protractor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 Express for Windows Phone 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Protractor", "Protractor\Protractor.csproj", "{580079E8-E581-4310-869D-A0924A5BBEB0}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {580079E8-E581-4310-869D-A0924A5BBEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {580079E8-E581-4310-869D-A0924A5BBEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {580079E8-E581-4310-869D-A0924A5BBEB0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 15 | {580079E8-E581-4310-869D-A0924A5BBEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {580079E8-E581-4310-869D-A0924A5BBEB0}.Release|Any CPU.Build.0 = Release|Any CPU 17 | {580079E8-E581-4310-869D-A0924A5BBEB0}.Release|Any CPU.Deploy.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /src/Protractor/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Protractor/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Documents; 8 | using System.Windows.Input; 9 | using System.Windows.Media; 10 | using System.Windows.Media.Animation; 11 | using System.Windows.Navigation; 12 | using System.Windows.Shapes; 13 | using Microsoft.Phone.Controls; 14 | using Microsoft.Phone.Shell; 15 | 16 | namespace Protractor_WP 17 | { 18 | public partial class App : Application 19 | { 20 | /// 21 | /// Provides easy access to the root frame of the Phone Application. 22 | /// 23 | /// The root frame of the Phone Application. 24 | public PhoneApplicationFrame RootFrame { get; private set; } 25 | 26 | /// 27 | /// Constructor for the Application object. 28 | /// 29 | public App() 30 | { 31 | // Global handler for uncaught exceptions. 32 | UnhandledException += Application_UnhandledException; 33 | 34 | // Standard Silverlight initialization 35 | InitializeComponent(); 36 | 37 | // Phone-specific initialization 38 | InitializePhoneApplication(); 39 | 40 | // Show graphics profiling information while debugging. 41 | if (System.Diagnostics.Debugger.IsAttached) 42 | { 43 | // Display the current frame rate counters. 44 | Application.Current.Host.Settings.EnableFrameRateCounter = false; 45 | 46 | // Show the areas of the app that are being redrawn in each frame. 47 | //Application.Current.Host.Settings.EnableRedrawRegions = true; 48 | 49 | // Enable non-production analysis visualization mode, 50 | // which shows areas of a page that are handed off to GPU with a colored overlay. 51 | //Application.Current.Host.Settings.EnableCacheVisualization = true; 52 | 53 | // Disable the application idle detection by setting the UserIdleDetectionMode property of the 54 | // application's PhoneApplicationService object to Disabled. 55 | // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run 56 | // and consume battery power when the user is not using the phone. 57 | PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; 58 | } 59 | } 60 | 61 | // Code to execute when the application is launching (eg, from Start) 62 | // This code will not execute when the application is reactivated 63 | private void Application_Launching(object sender, LaunchingEventArgs e) 64 | { 65 | } 66 | 67 | // Code to execute when the application is activated (brought to foreground) 68 | // This code will not execute when the application is first launched 69 | private void Application_Activated(object sender, ActivatedEventArgs e) 70 | { 71 | } 72 | 73 | // Code to execute when the application is deactivated (sent to background) 74 | // This code will not execute when the application is closing 75 | private void Application_Deactivated(object sender, DeactivatedEventArgs e) 76 | { 77 | } 78 | 79 | // Code to execute when the application is closing (eg, user hit Back) 80 | // This code will not execute when the application is deactivated 81 | private void Application_Closing(object sender, ClosingEventArgs e) 82 | { 83 | } 84 | 85 | // Code to execute if a navigation fails 86 | private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e) 87 | { 88 | if (System.Diagnostics.Debugger.IsAttached) 89 | { 90 | // A navigation has failed; break into the debugger 91 | System.Diagnostics.Debugger.Break(); 92 | } 93 | } 94 | 95 | // Code to execute on Unhandled Exceptions 96 | private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) 97 | { 98 | if (System.Diagnostics.Debugger.IsAttached) 99 | { 100 | // An unhandled exception has occurred; break into the debugger 101 | System.Diagnostics.Debugger.Break(); 102 | } 103 | } 104 | 105 | #region Phone application initialization 106 | 107 | // Avoid double-initialization 108 | private bool phoneApplicationInitialized = false; 109 | 110 | // Do not add any additional code to this method 111 | private void InitializePhoneApplication() 112 | { 113 | if (phoneApplicationInitialized) 114 | return; 115 | 116 | // Create the frame but don't set it as RootVisual yet; this allows the splash 117 | // screen to remain active until the application is ready to render. 118 | RootFrame = new PhoneApplicationFrame(); 119 | RootFrame.Navigated += CompleteInitializePhoneApplication; 120 | 121 | // Handle navigation failures 122 | RootFrame.NavigationFailed += RootFrame_NavigationFailed; 123 | 124 | // Ensure we don't initialize again 125 | phoneApplicationInitialized = true; 126 | } 127 | 128 | // Do not add any additional code to this method 129 | private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e) 130 | { 131 | // Set the root visual to allow the application to render 132 | if (RootVisual != RootFrame) 133 | RootVisual = RootFrame; 134 | 135 | // Remove this handler since it is no longer needed 136 | RootFrame.Navigated -= CompleteInitializePhoneApplication; 137 | } 138 | 139 | #endregion 140 | } 141 | } -------------------------------------------------------------------------------- /src/Protractor/ApplicationIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/ApplicationIcon.png -------------------------------------------------------------------------------- /src/Protractor/Background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/Background.png -------------------------------------------------------------------------------- /src/Protractor/BrowserMouseHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using Microsoft.Phone.Controls; 5 | using System.Windows.Input; 6 | using System.Diagnostics; 7 | using System.Windows.Media; 8 | using System; 9 | using System.Collections.Generic; 10 | 11 | namespace Protractor_WP 12 | { 13 | public class BrowserMouseHelper 14 | { 15 | /** 16 | * 17 | * Full Script below, in use it is minified. 18 | */ 19 | /* 20 | private static string mouseScript = 21 | @"(function(win,doc){ 22 | Object.defineProperty( MouseEvent.prototype, 'pageX', { 23 | configurable: true, 24 | get: function(){ return this.clientX } 25 | }); 26 | Object.defineProperty( MouseEvent.prototype, 'pageY', { 27 | configurable: true, 28 | get: function(){ return this.clientY } 29 | }); 30 | 31 | win.onNativeMouseEvent = function(type,x,y){ 32 | try { 33 | var xMod = screen.logicalXDPI / screen.deviceXDPI; 34 | var yMod = screen.logicalYDPI / screen.deviceYDPI; 35 | var evt = doc.createEvent('MouseEvents'); 36 | var xPos = doc.body.scrollLeft + Math.round(xMod * x); 37 | var yPos = doc.body.scrollTop + Math.round(yMod * y); 38 | var element = doc.elementFromPoint(xPos,yPos); 39 | evt.initMouseEvent(type, true, true, win, 1, xPos, yPos, xPos, yPos, false, false, false, false, 0, element); 40 | var canceled = element ? !element.dispatchEvent(evt) : !doc.dispatchEvent(evt); 41 | return canceled ? 'true' : 'false'; 42 | } 43 | catch(e) { return e;} 44 | } 45 | })(window,document);"; 46 | */ 47 | 48 | private static string MinifiedMouseScript = "(function(f,a){Object.defineProperty(MouseEvent.prototype,'pageX',{configurable:!0,get:function(){return this.clientX}});Object.defineProperty(MouseEvent.prototype,'pageY',{configurable:!0,get:function(){return this.clientY}});f.onNativeMouseEvent=function(g,h,i)" 49 | + "{try{var j=screen.logicalXDPI/screen.deviceXDPI,k=screen.logicalYDPI/screen.deviceYDPI,b=a.createEvent('MouseEvents'),c=a.body.scrollLeft+Math.round(j*h),d=a.body.scrollTop+Math.round(k*i),e=a.elementFromPoint(c,d);b.initMouseEvent(g,!0,!0," 50 | + "f,1,c,d,c,d,!1,!1,!1,!1,0,e);return(e?!e.dispatchEvent(b):!a.dispatchEvent(b))?'true':'false'}catch(l){return l}}})(window,document);"; 51 | 52 | 53 | private WebBrowser _browser; 54 | 55 | /// 56 | /// Gets or sets whether to suppress the scrolling of 57 | /// the WebBrowser control; 58 | /// 59 | public bool ScrollDisabled { get; set; } 60 | 61 | private bool userScalable = true; 62 | private double maxScale = 2.0; 63 | private double minScale = 0.5; 64 | protected Border border; 65 | private bool firstMouseMove = false; 66 | 67 | 68 | public BrowserMouseHelper(ref WebBrowser browser) 69 | { 70 | _browser = browser; 71 | browser.Loaded += new RoutedEventHandler(browser_Loaded); 72 | } 73 | 74 | private void browser_Loaded(object sender, RoutedEventArgs e) 75 | { 76 | var border0 = VisualTreeHelper.GetChild(_browser, 0); 77 | var border1 = VisualTreeHelper.GetChild(border0, 0); 78 | var panZoom = VisualTreeHelper.GetChild(border1, 0); 79 | var grid = VisualTreeHelper.GetChild(panZoom, 0); 80 | border = VisualTreeHelper.GetChild(grid, 0) as Border; 81 | 82 | if (border != null) 83 | { 84 | border.ManipulationStarted += Border_ManipulationStarted; 85 | border.ManipulationDelta += Border_ManipulationDelta; 86 | border.ManipulationCompleted += Border_ManipulationCompleted; 87 | border.DoubleTap += Border_DoubleTap; 88 | border.Hold += Border_Hold; 89 | border.MouseLeftButtonDown += Border_MouseLeftButtonDown; 90 | } 91 | 92 | _browser.LoadCompleted += Browser_LoadCompleted; 93 | } 94 | 95 | void ParseViewportMeta() 96 | { 97 | string metaScript = "(function() { return document.querySelector('meta[name=viewport]').content; })()"; 98 | 99 | try 100 | { 101 | string metaContent = _browser.InvokeScript("eval", new string[] { metaScript }) as string; 102 | string[] arr = metaContent.Split(new[] { ' ', ',', ';' }, StringSplitOptions.RemoveEmptyEntries); 103 | Dictionary metaDictionary = new Dictionary(); 104 | foreach (string val in arr) 105 | { 106 | string[] keyVal = val.Split('='); 107 | metaDictionary.Add(keyVal[0], keyVal[1]); 108 | } 109 | 110 | this.userScalable = false; // reset to default 111 | if (metaDictionary.ContainsKey("user-scalable")) 112 | { 113 | this.userScalable = metaDictionary["user-scalable"] == "yes"; 114 | } 115 | 116 | this.maxScale = 1.0;// reset to default 117 | if (metaDictionary.ContainsKey("maximum-scale")) 118 | { 119 | this.maxScale = double.Parse(metaDictionary["maximum-scale"]); 120 | } 121 | 122 | this.minScale = 1.0;// reset to default 123 | if (metaDictionary.ContainsKey("minimum-scale")) 124 | { 125 | this.minScale = double.Parse(metaDictionary["minimum-scale"]); 126 | } 127 | } 128 | catch (Exception) 129 | { 130 | 131 | } 132 | } 133 | 134 | void Browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e) 135 | { 136 | ParseViewportMeta(); 137 | 138 | try 139 | { 140 | _browser.InvokeScript("execScript", MinifiedMouseScript); 141 | } 142 | catch (Exception) 143 | { 144 | Debug.WriteLine("BrowserHelper Failed to install mouse script in WebBrowser"); 145 | } 146 | } 147 | 148 | bool InvokeSimulatedMouseEvent(string eventName, Point pos) 149 | { 150 | bool bCancelled = false; 151 | try 152 | { 153 | System.Diagnostics.Debug.WriteLine("Simulating " + eventName + " to position: " + pos.ToString()); 154 | 155 | string strCancelled = _browser.InvokeScript("onNativeMouseEvent", new string[] { eventName, pos.X.ToString(), pos.Y.ToString() }) as string; 156 | if (bool.TryParse(strCancelled, out bCancelled)) 157 | { 158 | return bCancelled; 159 | } 160 | } 161 | catch (Exception) 162 | { 163 | // script error 164 | } 165 | 166 | return bCancelled; 167 | } 168 | 169 | #region Hold 170 | 171 | void Border_Hold(object sender, GestureEventArgs e) 172 | { 173 | e.Handled = true; 174 | } 175 | 176 | #endregion 177 | 178 | #region DoubleTap 179 | 180 | void Border_DoubleTap(object sender, GestureEventArgs e) 181 | { 182 | e.Handled = true; 183 | } 184 | 185 | #endregion 186 | 187 | #region MouseEvents 188 | 189 | void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 190 | { 191 | border.MouseMove += new MouseEventHandler(Border_MouseMove); 192 | border.MouseLeftButtonUp += new MouseButtonEventHandler(Border_MouseLeftButtonUp); 193 | 194 | firstMouseMove = true; 195 | 196 | Point pos = e.GetPosition(_browser); 197 | InvokeSimulatedMouseEvent("mousedown", pos); 198 | } 199 | 200 | void Border_MouseMove(object sender, MouseEventArgs e) 201 | { 202 | Point pos = e.GetPosition(_browser); 203 | bool retVal = InvokeSimulatedMouseEvent("mousemove", pos); 204 | 205 | // only the return value from the first mouse move event should be used to determine if scrolling is prevented. 206 | if (firstMouseMove) 207 | { 208 | //ScrollDisabled = retVal; 209 | } 210 | } 211 | 212 | void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 213 | { 214 | border.MouseMove -= new MouseEventHandler(Border_MouseMove); 215 | border.MouseLeftButtonUp -= new MouseButtonEventHandler(Border_MouseLeftButtonUp); 216 | Point pos = e.GetPosition(_browser); 217 | e.Handled = InvokeSimulatedMouseEvent("mouseup", pos); 218 | //ScrollDisabled = false; 219 | } 220 | 221 | 222 | #endregion 223 | 224 | #region ManipulationEvents 225 | 226 | void Border_ManipulationStarted(object sender, ManipulationStartedEventArgs e) 227 | { 228 | if (ScrollDisabled) 229 | { 230 | e.Handled = true; 231 | e.Complete(); 232 | } 233 | } 234 | 235 | private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) 236 | { 237 | // optionally suppress zoom 238 | if ((ScrollDisabled || !userScalable) && (e.DeltaManipulation.Scale.X != 0.0 || e.DeltaManipulation.Scale.Y != 0.0)) 239 | { 240 | e.Handled = true; 241 | e.Complete(); 242 | } 243 | // optionally suppress scrolling 244 | if (ScrollDisabled && (e.DeltaManipulation.Translation.X != 0.0 || e.DeltaManipulation.Translation.Y != 0.0)) 245 | { 246 | e.Handled = true; 247 | e.Complete(); 248 | } 249 | } 250 | 251 | private void Border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) 252 | { 253 | // suppress zoom 254 | if (!userScalable && e.FinalVelocities != null) 255 | { 256 | if (e.FinalVelocities.ExpansionVelocity.X != 0.0 || 257 | e.FinalVelocities.ExpansionVelocity.Y != 0.0) 258 | { 259 | e.Handled = true; 260 | } 261 | } 262 | } 263 | 264 | #endregion 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /src/Protractor/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Protractor/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Documents; 8 | using System.Windows.Input; 9 | using System.Windows.Media; 10 | using System.Windows.Media.Animation; 11 | using System.Windows.Shapes; 12 | using Microsoft.Phone.Controls; 13 | using System.IO; 14 | using System.IO.IsolatedStorage; 15 | using System.Windows.Resources; 16 | using System.ComponentModel; 17 | 18 | 19 | namespace Protractor_WP 20 | { 21 | public partial class MainPage : PhoneApplicationPage 22 | { 23 | protected BrowserMouseHelper m_helper; 24 | protected IsolatedStorageSettings m_settings = IsolatedStorageSettings.ApplicationSettings; 25 | 26 | protected const string MEASURED_LENGTH_KEY = "measuredLength"; 27 | protected const string MEASURED_ANLGE_RADIANS_KEY = "measuredAngleRadians"; 28 | protected const string SCREEN_WIDTH_MM = "screenWidthMM"; 29 | protected const string USE_MM = "useMM"; 30 | 31 | // Constructor 32 | public MainPage() 33 | { 34 | InitializeComponent(); 35 | 36 | m_helper = new BrowserMouseHelper(ref webBrowser); 37 | m_helper.ScrollDisabled = true; 38 | 39 | SaveFilesToIsoStore(); 40 | 41 | webBrowser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(webBrowser_LoadCompleted); 42 | } 43 | 44 | /// 45 | /// Loads the stored values from the isolated storage and sets them to the HTML5 UI. 46 | /// 47 | /// 48 | /// 49 | void webBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e) 50 | { 51 | string measuredLength = "-1"; 52 | string measuredAngleRadians = "-1"; 53 | string screenWidthMM = "81"; // Default for Lumia 800 54 | string useMM = "true"; 55 | 56 | if (m_settings.Contains(MEASURED_LENGTH_KEY)) 57 | { 58 | measuredLength = (string)m_settings[MEASURED_LENGTH_KEY]; 59 | } 60 | 61 | if (m_settings.Contains(MEASURED_ANLGE_RADIANS_KEY)) 62 | { 63 | measuredAngleRadians = (string)m_settings[MEASURED_ANLGE_RADIANS_KEY]; 64 | } 65 | 66 | if (m_settings.Contains(SCREEN_WIDTH_MM)) 67 | { 68 | screenWidthMM = (string)m_settings[SCREEN_WIDTH_MM]; 69 | } 70 | 71 | if (m_settings.Contains(USE_MM)) 72 | { 73 | useMM = (string)m_settings[USE_MM]; 74 | } 75 | 76 | webBrowser.InvokeScript("eval", string.Format("measuredLength = {0};", measuredLength)); 77 | webBrowser.InvokeScript("eval", string.Format("measuredAngleRadians = {0};", measuredAngleRadians)); 78 | webBrowser.InvokeScript("eval", string.Format("screenWidthMM = {0};", screenWidthMM)); 79 | webBrowser.InvokeScript("eval", string.Format("useMM = {0};", useMM)); 80 | webBrowser.InvokeScript("eval", "init();"); 81 | } 82 | 83 | /// 84 | /// Called when the main page is shown. Navigates the webbrowser to the local HTML page. 85 | /// 86 | /// 87 | protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 88 | { 89 | webBrowser.Navigate(new Uri("html\\index.html", UriKind.Relative)); 90 | } 91 | 92 | /// 93 | /// Called when the main page is navigated away, basically when the application is sent to background or the application is closed. 94 | /// Gets the some variables from the JavaScript to store the state of the application into the isolated storage. 95 | /// 96 | /// 97 | protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e) 98 | { 99 | string measuredLength = webBrowser.InvokeScript("eval", "var value = measuredLength; value.toString();") as string; 100 | string measuredAngleRadians = webBrowser.InvokeScript("eval", "var value = measuredAngleRadians; value.toString();") as string; 101 | string screenWidthMM = webBrowser.InvokeScript("eval", "var value = screenWidthMM; value.toString();") as string; 102 | string useMM = webBrowser.InvokeScript("eval", "var value = useMM; value.toString();") as string; 103 | 104 | m_settings[MEASURED_LENGTH_KEY] = measuredLength; 105 | m_settings[MEASURED_ANLGE_RADIANS_KEY] = measuredAngleRadians; 106 | m_settings[SCREEN_WIDTH_MM] = screenWidthMM; 107 | m_settings[USE_MM] = useMM; 108 | } 109 | 110 | /// 111 | /// Handles back key press. If the HTML5 UI is on config screen the back key will close it. 112 | /// 113 | /// 114 | protected override void OnBackKeyPress(CancelEventArgs e) 115 | { 116 | string inConfig = webBrowser.InvokeScript("eval", "var value = inConfig; value.toString();") as string; 117 | if (inConfig == "true") 118 | { 119 | webBrowser.InvokeScript("eval", "inConfig = false;"); 120 | webBrowser.InvokeScript("eval", "draw();"); 121 | e.Cancel = true; 122 | } 123 | } 124 | 125 | 126 | /// 127 | /// Saves the HTML files to isolated storage as files in order them to be viewer by the webbrowser component. 128 | /// 129 | private void SaveFilesToIsoStore() 130 | { 131 | // These files must match what is included in the application package, 132 | // or BinaryStream.Dispose below will throw an exception. 133 | string[] files = { 134 | "html/index.html", 135 | "html/script.js", 136 | "html/style.css", 137 | "html/papergrid.png", 138 | "html/settings.png" 139 | }; 140 | 141 | IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication(); 142 | 143 | foreach (string f in files) 144 | { 145 | StreamResourceInfo sr = Application.GetResourceStream(new Uri(f, UriKind.Relative)); 146 | using (BinaryReader br = new BinaryReader(sr.Stream)) 147 | { 148 | byte[] data = br.ReadBytes((int)sr.Stream.Length); 149 | SaveToIsoStore(f, data); 150 | } 151 | } 152 | } 153 | 154 | /// 155 | /// Saves a single file to the isolated storage. 156 | /// 157 | /// 158 | /// 159 | private void SaveToIsoStore(string fileName, byte[] data) 160 | { 161 | string strBaseDir = string.Empty; 162 | string delimStr = "/"; 163 | char[] delimiter = delimStr.ToCharArray(); 164 | string[] dirsPath = fileName.Split(delimiter); 165 | 166 | // Get the IsoStore. 167 | IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication(); 168 | 169 | // Re-create the directory structure. 170 | for (int i = 0; i < dirsPath.Length - 1; i++) 171 | { 172 | strBaseDir = System.IO.Path.Combine(strBaseDir, dirsPath[i]); 173 | isoStore.CreateDirectory(strBaseDir); 174 | } 175 | 176 | // Remove the existing file. 177 | if (isoStore.FileExists(fileName)) 178 | { 179 | isoStore.DeleteFile(fileName); 180 | } 181 | 182 | // Write the file. 183 | using (BinaryWriter bw = new BinaryWriter(isoStore.CreateFile(fileName))) 184 | { 185 | bw.Write(data); 186 | bw.Close(); 187 | } 188 | } 189 | } 190 | } -------------------------------------------------------------------------------- /src/Protractor/Properties/AppManifest.xml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Protractor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using System.Resources; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Protractor")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Microsoft")] 13 | [assembly: AssemblyProduct("Protractor")] 14 | [assembly: AssemblyCopyright("Copyright © Microsoft 2012")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid("4510ac17-3a46-473b-acf0-4f0ac31f57b2")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Revision and Build Numbers 34 | // by using the '*' as shown below: 35 | [assembly: AssemblyVersion("1.1.0")] 36 | [assembly: AssemblyFileVersion("1.1.0")] 37 | [assembly: NeutralResourcesLanguageAttribute("en-US")] 38 | -------------------------------------------------------------------------------- /src/Protractor/Properties/WMAppManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | ApplicationIcon.png 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Background.png 29 | 0 30 | Protractor 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/Protractor/Protractor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.20506 7 | 2.0 8 | {580079E8-E581-4310-869D-A0924A5BBEB0} 9 | {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 10 | Library 11 | Properties 12 | Protractor_WP 13 | Protractor-WP 14 | v4.0 15 | $(TargetFrameworkVersion) 16 | WindowsPhone71 17 | Silverlight 18 | true 19 | 20 | 21 | true 22 | true 23 | Protractor.xap 24 | Properties\AppManifest.xml 25 | Protractor_WP.App 26 | true 27 | true 28 | 29 | 30 | true 31 | full 32 | false 33 | Bin\Debug 34 | DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE 35 | true 36 | true 37 | prompt 38 | 4 39 | 40 | 41 | pdbonly 42 | true 43 | Bin\Release 44 | TRACE;SILVERLIGHT;WINDOWS_PHONE 45 | true 46 | true 47 | prompt 48 | 4 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | App.xaml 63 | 64 | 65 | 66 | MainPage.xaml 67 | 68 | 69 | 70 | 71 | 72 | Designer 73 | MSBuild:Compile 74 | 75 | 76 | Designer 77 | MSBuild:Compile 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | PreserveNewest 87 | 88 | 89 | PreserveNewest 90 | 91 | 92 | Designer 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 109 | 110 | -------------------------------------------------------------------------------- /src/Protractor/SplashScreenImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/SplashScreenImage.jpg -------------------------------------------------------------------------------- /src/Protractor/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Protractor 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /src/Protractor/html/papergrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/html/papergrid.png -------------------------------------------------------------------------------- /src/Protractor/html/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/html/script.js -------------------------------------------------------------------------------- /src/Protractor/html/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/html/settings.png -------------------------------------------------------------------------------- /src/Protractor/html/style.css: -------------------------------------------------------------------------------- 1 | #canvas { 2 | position: absolute; 3 | } 4 | 5 | #dpi { 6 | position: absolute; 7 | width: 1in; 8 | height: 1in; 9 | top: -100%; 10 | left: -100%; 11 | } -------------------------------------------------------------------------------- /src/Protractor/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Protractor 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /src/Protractor/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/protractor/45a57256f7ae7c342bcb4a5abd051282ff9d3a8b/src/Protractor/script.js -------------------------------------------------------------------------------- /src/Protractor/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | width: 100%; 4 | height: 100%; 5 | position: absolute; 6 | } 7 | 8 | #canvas { 9 | position: absolute; 10 | } 11 | 12 | #dpi { 13 | position: absolute; 14 | width: 1in; 15 | height: 1in; 16 | top: -100%; 17 | left: -100%; 18 | } --------------------------------------------------------------------------------