diff --git a/YJMPD-UWP/App.xaml b/YJMPD-UWP/App.xaml
index 17f7ca0..0331a6b 100644
--- a/YJMPD-UWP/App.xaml
+++ b/YJMPD-UWP/App.xaml
@@ -2,7 +2,18 @@
x:Class="YJMPD_UWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:YJMPD_UWP"
- RequestedTheme="Light">
+ xmlns:local="using:YJMPD_UWP">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/YJMPD-UWP/App.xaml.cs b/YJMPD-UWP/App.xaml.cs
index c256890..5c55a17 100644
--- a/YJMPD-UWP/App.xaml.cs
+++ b/YJMPD-UWP/App.xaml.cs
@@ -1,27 +1,88 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
+using YJMPD_UWP.Model;
+using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
-using Windows.Foundation.Collections;
+using Windows.Globalization;
+using Windows.Graphics.Display;
+using Windows.UI.Core;
+using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace YJMPD_UWP
{
- ///
- /// Provides application-specific behavior to supplement the default Application class.
- ///
sealed partial class App : Application
{
+
+ public static Frame rootFrame;
+
+
+ // =======================
+ // SINGLETONS
+ // =======================
+ private static GeoTracker geo = new GeoTracker();
+
+ public static GeoTracker Geo
+ {
+ get
+ {
+ return geo;
+ }
+ }
+
+ private static CompassTracker cm = new CompassTracker();
+
+ public static CompassTracker CompassTracker
+ {
+ get
+ {
+ return cm;
+ }
+ }
+
+ public static CoreDispatcher Dispatcher
+ {
+ get
+ {
+ return Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
+ }
+ }
+
+
+ // =========================
+ // STATIC HELPER FUNCTIONS
+ // =========================
+
+ public static Size ScreenSize
+ {
+ get
+ {
+ var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
+ var scaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
+ Size size = new Size(bounds.Width * scaleFactor, bounds.Height * scaleFactor);
+ return size;
+ }
+ }
+
+ public static MainPage MainPage
+ {
+ get
+ {
+ Frame f = Window.Current.Content as Frame;
+ MainPage mp = f.Content as MainPage;
+ return mp;
+ }
+ }
+
+
+
+ // ===============================
+ // NORMAL STUFF
+ // ===============================
+
+
///
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
@@ -29,6 +90,7 @@ namespace YJMPD_UWP
public App()
{
this.InitializeComponent();
+
this.Suspending += OnSuspending;
}
@@ -43,11 +105,11 @@ namespace YJMPD_UWP
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
- this.DebugSettings.EnableFrameRateCounter = true;
+ this.DebugSettings.EnableFrameRateCounter = false;
}
#endif
- Frame rootFrame = Window.Current.Content as Frame;
+ rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
@@ -74,6 +136,7 @@ namespace YJMPD_UWP
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
+
// Ensure the current window is active
Window.Current.Activate();
}
diff --git a/YJMPD-UWP/Helpers/Extensions.cs b/YJMPD-UWP/Helpers/Extensions.cs
new file mode 100644
index 0000000..c017007
--- /dev/null
+++ b/YJMPD-UWP/Helpers/Extensions.cs
@@ -0,0 +1,17 @@
+using Newtonsoft.Json.Linq;
+using System;
+
+namespace YJMPD_UWP.Helpers
+{
+ public static class Extensions
+ {
+ public static bool NullOrEmpty(this JToken token)
+ {
+ return (token == null) ||
+ (token.Type == JTokenType.Array && !token.HasValues) ||
+ (token.Type == JTokenType.Object && !token.HasValues) ||
+ (token.Type == JTokenType.String && token.ToString() == String.Empty) ||
+ (token.Type == JTokenType.Null);
+ }
+ }
+}
diff --git a/YJMPD-UWP/Helpers/Settings.cs b/YJMPD-UWP/Helpers/Settings.cs
new file mode 100644
index 0000000..6f8a321
--- /dev/null
+++ b/YJMPD-UWP/Helpers/Settings.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Threading.Tasks;
+using Windows.Globalization;
+using Windows.Storage;
+
+namespace YJMPD_UWP.Helpers
+{
+ static class Settings
+ {
+ private static ApplicationDataContainer LOCAL_SETTINGS = ApplicationData.Current.LocalSettings;
+
+ public delegate void OnLanguageUpdateHandler(EventArgs e);
+ public static event OnLanguageUpdateHandler OnLanguageUpdate;
+
+ public static bool Tracking
+ {
+ get
+ {
+ return (bool)LOCAL_SETTINGS.Values["tracking"];
+ }
+ set
+ {
+ LOCAL_SETTINGS.Values["tracking"] = value;
+ }
+ }
+
+ static Settings()
+ {
+ LOCAL_SETTINGS.Values["tracking"] = true;
+
+ if (CurrentLanguage == "")
+ ApplicationLanguages.PrimaryLanguageOverride = "en";
+ }
+
+ public static async void ChangeLanguage(string lang)
+ {
+ ApplicationLanguages.PrimaryLanguageOverride = lang;
+ await Task.Delay(TimeSpan.FromMilliseconds(100));
+ //App.rootFrame.Navigate(typeof(MainPage));
+ OnLanguageUpdate(new EventArgs());
+ }
+
+ public static string CurrentLanguage { get { return ApplicationLanguages.PrimaryLanguageOverride; } }
+ }
+}
diff --git a/YJMPD-UWP/Helpers/Util.cs b/YJMPD-UWP/Helpers/Util.cs
new file mode 100644
index 0000000..2cdebb2
--- /dev/null
+++ b/YJMPD-UWP/Helpers/Util.cs
@@ -0,0 +1,269 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.ApplicationModel.Resources;
+using Windows.Data.Xml.Dom;
+using Windows.Devices.Geolocation;
+using Windows.Services.Maps;
+using Windows.UI;
+using Windows.UI.Notifications;
+using Windows.UI.Popups;
+using Windows.UI.Xaml.Controls.Maps;
+
+namespace YJMPD_UWP.Helpers
+{
+ class Util
+ {
+ public enum DialogType { YESNO, OKCANCEL }
+
+ public static ResourceLoader Loader
+ {
+ get
+ {
+ return new Windows.ApplicationModel.Resources.ResourceLoader();
+ }
+ }
+
+ public static double Now { get { return (DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; } }
+
+ public static string MillisecondsToTime(double millis)
+ {
+ DateTime time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ string timestr = time.AddMilliseconds(millis) + "";
+ return timestr;
+ }
+
+ public static async Task FindLocation(string location, Geopoint reference)
+ {
+ MapLocationFinderResult result = await MapLocationFinder.FindLocationsAsync(location, reference);
+ MapLocation from = result.Locations.FirstOrDefault();
+ Geopoint p = from.Point;
+ return p;
+ }
+
+ public static async Task FindWalkingRoute(Geopoint from, Geopoint to)
+ {
+ MapRouteFinderResult routeResult = await MapRouteFinder.GetWalkingRouteAsync(from, to);
+ MapRoute b = routeResult.Route;
+ return b;
+ }
+
+ public static async Task FindWalkingRoute(List points)
+ {
+ MapRouteFinderResult routeResult = await MapRouteFinder.GetWalkingRouteFromWaypointsAsync(points);
+ MapRoute b = routeResult.Route;
+ return b;
+ }
+
+ public static async Task FindWalkingRoute(string from, string to, Geopoint reference)
+ {
+ Geopoint f = await FindLocation(from, reference);
+ Geopoint t = await FindLocation(to, reference);
+ MapRoute m = await FindWalkingRoute(f, t);
+ return m;
+ }
+
+ public static async Task FindAddress(Geopoint p)
+ {
+ // Reverse geocode the specified geographic location.
+ MapLocationFinderResult result =
+ await MapLocationFinder.FindLocationsAtAsync(p);
+
+ string returnstring = "";
+
+ // If the query returns results, display the name of the town
+ // contained in the address of the first result.
+ if (result.Status == MapLocationFinderStatus.Success)
+ {
+ MapAddress address = result.Locations[0].Address;
+
+ //returnstring = address.Street + " " + address.StreetNumber + ", " + address.Town;
+ returnstring += (address.BuildingName == "" ? "" : address.BuildingName + ", ");
+ returnstring += (address.Street == "" ? "" : address.Street + (address.StreetNumber == "" ? ", " : " " + address.StreetNumber + ", "));
+ returnstring += address.Town;
+ }
+
+ return returnstring;
+ }
+
+ public static async Task FindAddress(double latitude, double longitude)
+ {
+ Geopoint p = new Geopoint(new BasicGeoposition() { Latitude = latitude, Longitude = longitude });
+ string address = await FindAddress(p);
+ return address;
+ }
+
+ public static MapPolyline GetRouteLine(MapRoute m, Color color, int zindex, int thickness = 5)
+ {
+ var line = new MapPolyline
+ {
+ StrokeThickness = thickness,
+ StrokeColor = color,
+ StrokeDashed = false,
+ ZIndex = zindex
+ };
+
+ if (m != null)
+ line.Path = new Geopath(m.Path.Positions);
+
+ return line;
+ }
+
+ public static MapPolyline GetRouteLine(List positions, Color color, int zindex, int thickness = 5)
+ {
+ var line = new MapPolyline
+ {
+ StrokeThickness = thickness,
+ StrokeColor = color,
+ StrokeDashed = false,
+ ZIndex = zindex
+ };
+
+ line.Path = new Geopath(positions);
+
+ return line;
+ }
+
+ public static MapPolyline GetRouteLine(BasicGeoposition p1, BasicGeoposition p2, Color color, int zindex, int thickness = 5)
+ {
+ var line = new MapPolyline
+ {
+ StrokeThickness = thickness,
+ StrokeColor = color,
+ StrokeDashed = false,
+ ZIndex = zindex
+ };
+
+ List plist = new List();
+ plist.Add(p1);
+ plist.Add(p2);
+
+ line.Path = new Geopath(plist);
+
+ return line;
+ }
+
+ public static void ShowToastNotification(string title, string text)
+ {
+ ToastTemplateType toastTemplate = ToastTemplateType.ToastText02;
+ XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
+
+ XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
+ toastTextElements[0].AppendChild(toastXml.CreateTextNode(title));
+ toastTextElements[1].AppendChild(toastXml.CreateTextNode(text));
+
+ IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
+ XmlElement audio = toastXml.CreateElement("audio");
+
+ audio.SetAttribute("src", "ms-winsoundevent:Notification.IM");
+
+ toastNode.AppendChild(audio);
+
+ ToastNotification toast = new ToastNotification(toastXml);
+ ToastNotificationManager.CreateToastNotifier().Show(toast);
+ }
+
+ public static async Task ShowConfirmDialog(string title, string content, DialogType type)
+ {
+ MessageDialog dlg = new MessageDialog(content, title);
+ if (type == DialogType.YESNO)
+ {
+ dlg.Commands.Add(new UICommand(Util.Loader.GetString("Yes")) { Id = 0 });
+ dlg.Commands.Add(new UICommand(Util.Loader.GetString("No")) { Id = 1 });
+ }
+ else if (type == DialogType.OKCANCEL)
+ {
+ dlg.Commands.Add(new UICommand(Util.Loader.GetString("Ok")) { Id = 0 });
+ dlg.Commands.Add(new UICommand(Util.Loader.GetString("Cancel")) { Id = 1 });
+ }
+
+ dlg.DefaultCommandIndex = 0;
+ dlg.CancelCommandIndex = 1;
+
+ var result = await dlg.ShowAsync();
+
+ if ((int)result.Id == 0)
+ return true;
+ else
+ return false;
+ }
+
+ public static string TranslatedManeuver(MapRouteManeuver maneuver, int distance)
+ {
+ string response = "";
+ bool onstreet = false;
+ bool meters = true;
+
+ distance = (int)Math.Round(distance / 5.0) * 5;
+
+ switch (maneuver.Kind)
+ {
+ default:
+ response = Util.Loader.GetString("RouteSeeMap");
+ meters = false;
+ break;
+ case MapRouteManeuverKind.End:
+ response = Util.Loader.GetString("RouteEnd");
+ break;
+ case MapRouteManeuverKind.GoStraight:
+ response = Util.Loader.GetString("RouteGoStraight");
+ onstreet = true;
+ break;
+ case MapRouteManeuverKind.None:
+ response = Util.Loader.GetString("RouteNone");
+ meters = false;
+ break;
+ case MapRouteManeuverKind.Start:
+ response = Util.Loader.GetString("RouteStart");
+ meters = false;
+ break;
+ case MapRouteManeuverKind.TurnHardLeft:
+ case MapRouteManeuverKind.TurnLeft:
+ response = Util.Loader.GetString("RouteLeft");
+ onstreet = true;
+ break;
+ case MapRouteManeuverKind.TurnHardRight:
+ case MapRouteManeuverKind.TurnRight:
+ response = Util.Loader.GetString("RouteRight");
+ onstreet = true;
+ break;
+ case MapRouteManeuverKind.TrafficCircleLeft:
+ response = Util.Loader.GetString("RouteTrafficCircleLeft");
+ onstreet = true;
+ break;
+ case MapRouteManeuverKind.TrafficCircleRight:
+ response = Util.Loader.GetString("RouteTrafficCircleRight");
+ onstreet = true;
+ break;
+ case MapRouteManeuverKind.TurnKeepLeft:
+ case MapRouteManeuverKind.TurnLightLeft:
+ response = Util.Loader.GetString("RouteKeepLeft");
+ break;
+ case MapRouteManeuverKind.TurnKeepRight:
+ case MapRouteManeuverKind.TurnLightRight:
+ response = Util.Loader.GetString("RouteKeepRight");
+ break;
+ case MapRouteManeuverKind.UTurnLeft:
+ case MapRouteManeuverKind.UTurnRight:
+ response = Util.Loader.GetString("RouteUTurn");
+ break;
+ }
+
+ if (maneuver.StreetName == "")
+ onstreet = false;
+
+ if (distance < 10)
+ meters = false;
+
+
+ if (onstreet)
+ response += " " + Util.Loader.GetString("RouteOn") + " " + maneuver.StreetName;
+
+ if (meters)
+ response = Util.Loader.GetString("RouteIn") + " " + distance + "m" + " " + response.ToLower();
+
+ return response;
+ }
+ }
+}
diff --git a/YJMPD-UWP/MainPage.xaml b/YJMPD-UWP/MainPage.xaml
index 9cf4bef..cd52771 100644
--- a/YJMPD-UWP/MainPage.xaml
+++ b/YJMPD-UWP/MainPage.xaml
@@ -7,7 +7,150 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/YJMPD-UWP/MainPage.xaml.cs b/YJMPD-UWP/MainPage.xaml.cs
index b53366e..726dc00 100644
--- a/YJMPD-UWP/MainPage.xaml.cs
+++ b/YJMPD-UWP/MainPage.xaml.cs
@@ -1,30 +1,149 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
+using YJMPD_UWP.Helpers;
+using YJMPD_UWP.ViewModels;
+using YJMPD_UWP.Views;
+using System;
using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
+using System.Threading.Tasks;
+using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
-// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
-
namespace YJMPD_UWP
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
public sealed partial class MainPage : Page
{
+ double bptime;
+ double lastbptime;
+
public MainPage()
{
this.InitializeComponent();
+ Frame.Navigated += Frame_Navigated;
+ SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
+
+ bptime = Util.Now;
+
+ this.DataContext = new MainPageVM();
+ Frame.Navigate(typeof(MapView));
+ }
+
+ private void OnBackRequested(object sender, BackRequestedEventArgs e)
+ {
+ if (e.Handled) return;
+
+ if (Frame.CanGoBack)
+ {
+ e.Handled = true;
+ Frame.GoBack();
+ return;
+ }
+
+ lastbptime = bptime;
+ bptime = Util.Now;
+
+ if (bptime - lastbptime > 2000)
+ {
+ ShowHideBackMessage();
+ e.Handled = true;
+ }
+ }
+
+ public async Task ShowHideBackMessage()
+ {
+ BackMessage.Visibility = Visibility.Visible;
+ await Task.Delay(TimeSpan.FromSeconds(2));
+ BackMessage.Visibility = Visibility.Collapsed;
+ return "success";
+ }
+
+ public void Navigate(Type type)
+ {
+ Frame.Navigate(type);
+ }
+
+ public void Navigate(Type type, object param)
+ {
+ Frame.Navigate(type, param);
+ }
+
+ public string Title { get { return PageTitle.Text; } set { PageTitle.Text = value; } }
+
+ public void NavButton_Click(object sender, RoutedEventArgs arg)
+ {
+ NavView.IsPaneOpen = !NavView.IsPaneOpen;
+ }
+
+ private void Frame_Navigated(object sender, NavigationEventArgs e)
+ {
+ //Dirty Hack
+ string pagename = e.SourcePageType.ToString().Split('.').Last();
+
+ NavList.SelectedIndex = -1;
+
+ switch (pagename.ToLower())
+ {
+ default:
+ PageTitle.Text = "Nav City Breda";
+ break;
+ case "helpview":
+ NavList.SelectedIndex = 3;
+ break;
+ case "settingsview":
+ NavList.SelectedIndex = 5;
+ break;
+ case "mapview":
+ NavList.SelectedIndex = 0;
+ break;
+ case "routeview":
+ case "routedetailview":
+ NavList.SelectedIndex = 1;
+ break;
+ case "landmarkdetailview":
+ case "landmarkview":
+ NavList.SelectedIndex = 2;
+ break;
+ case "searchview":
+ NavList.SelectedIndex = 4;
+ break;
+ }
+
+ SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
+ Frame.CanGoBack ?
+ AppViewBackButtonVisibility.Visible :
+ AppViewBackButtonVisibility.Collapsed;
+ }
+
+ private void NavList_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ NavView.IsPaneOpen = false;
+ }
+
+ private void NavList_Tapped(object sender, TappedRoutedEventArgs e)
+ {
+ NavView.IsPaneOpen = false;
+ }
+
+ private void Content_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
+ {
+ if (e.Cumulative.Translation.X > 20)
+ {
+ NavView.IsPaneOpen = true;
+ }
+ }
+
+ private void Pane_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
+ {
+ if (e.Cumulative.Translation.X < -20)
+ {
+ NavView.IsPaneOpen = false;
+ }
+ }
+
+ private void GPSRefresh_Tapped(object sender, TappedRoutedEventArgs e)
+ {
+ App.Geo.ForceRefresh();
}
}
}
diff --git a/YJMPD-UWP/Model/CompassTracker.cs b/YJMPD-UWP/Model/CompassTracker.cs
new file mode 100644
index 0000000..d3b43f2
--- /dev/null
+++ b/YJMPD-UWP/Model/CompassTracker.cs
@@ -0,0 +1,81 @@
+using YJMPD_UWP.Helpers;
+using System;
+using Windows.Devices.Sensors;
+
+namespace YJMPD_UWP.Model
+{
+ public class CompassTracker
+ {
+ public delegate void OnHeadingUpdateHandler(object sender, HeadingUpdatedEventArgs e);
+ public event OnHeadingUpdateHandler OnHeadingUpdate;
+
+ public delegate void OnHeadingUpdateSlowHandler(object sender, HeadingUpdatedEventArgs e);
+ public event OnHeadingUpdateSlowHandler OnSlowHeadingUpdated;
+
+ private Compass comp;
+
+ private CompassReading hdn;
+ public CompassReading Heading { get { return hdn; } }
+
+ private CompassReading lastreading;
+ private double lastreadingtime;
+
+ public CompassTracker()
+ {
+ comp = Compass.GetDefault();
+
+ // Assign an event handler for the compass reading-changed event
+ if (comp != null)
+ {
+ // Establish the report interval for all scenarios
+ uint minReportInterval = comp.MinimumReportInterval;
+ uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
+ comp.ReportInterval = reportInterval;
+ comp.ReadingChanged += Comp_ReadingChanged;
+ hdn = comp.GetCurrentReading();
+ }
+ }
+
+ private void Comp_ReadingChanged(Compass sender, CompassReadingChangedEventArgs args)
+ {
+ UpdateHeading(args.Reading);
+ UpdateSlowHeading(args.Reading);
+ }
+
+ private void UpdateHeading(CompassReading r)
+ {
+ hdn = r;
+
+ //Make sure someone is listening
+ if (OnHeadingUpdate == null) return;
+
+ OnHeadingUpdate(this, new HeadingUpdatedEventArgs(r));
+ }
+
+ private void UpdateSlowHeading(CompassReading r)
+ {
+ if (lastreading == null) { lastreading = r; lastreadingtime = Util.Now; }
+
+ if (Math.Abs(r.HeadingMagneticNorth - lastreading.HeadingMagneticNorth) > 10 && Util.Now - lastreadingtime > 25)
+ {
+ lastreading = r;
+ lastreadingtime = Util.Now;
+
+ //Make sure someone is listening
+ if (OnSlowHeadingUpdated == null) return;
+
+ OnSlowHeadingUpdated(this, new HeadingUpdatedEventArgs(r));
+ }
+ }
+ }
+
+ public class HeadingUpdatedEventArgs : EventArgs
+ {
+ public CompassReading Heading;
+
+ public HeadingUpdatedEventArgs(CompassReading heading)
+ {
+ Heading = heading;
+ }
+ }
+}
diff --git a/YJMPD-UWP/Model/GeoTracker.cs b/YJMPD-UWP/Model/GeoTracker.cs
new file mode 100644
index 0000000..2e3aec0
--- /dev/null
+++ b/YJMPD-UWP/Model/GeoTracker.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Devices.Geolocation;
+using Windows.Devices.Geolocation.Geofencing;
+using Windows.System;
+
+namespace YJMPD_UWP.Model
+{
+ public class GeoTracker
+ {
+ private Geolocator geo;
+
+ private PositionStatus _status;
+ public PositionStatus Status { get { return _status; } }
+
+ private Geoposition _position;
+ public Geoposition Position { get { return _position; } }
+
+ public bool? Connected { get; private set; }
+
+ private List _history;
+ public List History
+ {
+ get
+ {
+ return _history;
+ }
+ }
+
+ //Events
+ public delegate void PositionUpdateHandler(object sender, PositionUpdatedEventArgs e);
+ public event PositionUpdateHandler OnPositionUpdate;
+
+ public delegate void StatusUpdateHandler(object sender, StatusUpdatedEventArgs e);
+ public event StatusUpdateHandler OnStatusUpdate;
+
+ public GeoTracker()
+ {
+ _status = PositionStatus.NotInitialized;
+ Connected = false;
+ _history = new List();
+ StartTracking();
+ }
+
+ public async void ForceRefresh()
+ {
+ if (geo == null)
+ await StartTracking();
+ else
+ _position = await geo.GetGeopositionAsync();
+ }
+
+ public async void TryConnectIfNull()
+ {
+ if (geo == null)
+ await StartTracking();
+ }
+
+ public void ClearHistory()
+ {
+ _history.Clear();
+ }
+
+ public async Task StartTracking()
+ {
+ // Request permission to access location
+ if (Status != PositionStatus.NotAvailable && Status != PositionStatus.NotInitialized)
+ return "Already Connected";
+
+ var accessStatus = await Geolocator.RequestAccessAsync();
+
+ switch (accessStatus)
+ {
+ case GeolocationAccessStatus.Allowed:
+ geo = new Geolocator
+ {
+ DesiredAccuracy = PositionAccuracy.High,
+ MovementThreshold = 3
+ //ReportInterval = 1500
+ };
+
+ ClearHistory();
+
+ Connected = true;
+
+ geo.PositionChanged += Geo_PositionChanged;
+ geo.StatusChanged += Geo_StatusChanged;
+
+ GeofenceMonitor.Current.Geofences.Clear();
+
+ _position = await geo.GetGeopositionAsync();
+
+ return "Connected";
+
+ case GeolocationAccessStatus.Denied:
+ Connected = false;
+ _status = PositionStatus.NotAvailable;
+ bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));
+ return "Denied";
+
+ default:
+ case GeolocationAccessStatus.Unspecified:
+ Connected = false;
+ _status = PositionStatus.NotAvailable;
+ return "Error";
+ }
+ }
+
+ private void Geo_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
+ {
+ if (args.Status == PositionStatus.Disabled)
+ {
+ Connected = false;
+ _position = null;
+ }
+ else if (!(bool)Connected)
+ Connected = true;
+
+ UpdateStatus(args.Status);
+ }
+
+ private void Geo_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
+ {
+ if (_history.Count > 0)
+ UpdatePosition(_history.Last(), args.Position);
+ else
+ {
+ _position = args.Position;
+ UpdatePosition(args.Position, args.Position);
+ }
+
+ _history.Add(args.Position);
+ }
+
+ private void UpdateStatus(PositionStatus s)
+ {
+ _status = s;
+
+ if (OnStatusUpdate == null) return;
+
+ OnStatusUpdate(this, new StatusUpdatedEventArgs(s));
+ }
+
+ private void UpdatePosition(Geoposition old, Geoposition newp)
+ {
+ _position = newp;
+
+ if (OnPositionUpdate == null) return;
+
+ OnPositionUpdate(this, new PositionUpdatedEventArgs(old, newp));
+ }
+ }
+
+ public class PositionUpdatedEventArgs : EventArgs
+ {
+ public Geoposition Old { get; private set; }
+ public Geoposition New { get; private set; }
+
+ public PositionUpdatedEventArgs(Geoposition old, Geoposition notold)
+ {
+ Old = old;
+ New = notold;
+ }
+ }
+
+ public class StatusUpdatedEventArgs : EventArgs
+ {
+ public PositionStatus Status { get; private set; }
+
+ public StatusUpdatedEventArgs(PositionStatus status)
+ {
+ Status = status;
+ }
+ }
+}
diff --git a/YJMPD-UWP/Themes/DarkTheme.xaml b/YJMPD-UWP/Themes/DarkTheme.xaml
new file mode 100644
index 0000000..cb787b1
--- /dev/null
+++ b/YJMPD-UWP/Themes/DarkTheme.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/YJMPD-UWP/Themes/DefaultStyles.xaml b/YJMPD-UWP/Themes/DefaultStyles.xaml
new file mode 100644
index 0000000..aa29630
--- /dev/null
+++ b/YJMPD-UWP/Themes/DefaultStyles.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/YJMPD-UWP/Themes/LightTheme.xaml b/YJMPD-UWP/Themes/LightTheme.xaml
new file mode 100644
index 0000000..c6e196e
--- /dev/null
+++ b/YJMPD-UWP/Themes/LightTheme.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/YJMPD-UWP/ViewModels/HelpVM.cs b/YJMPD-UWP/ViewModels/HelpVM.cs
new file mode 100644
index 0000000..446dd67
--- /dev/null
+++ b/YJMPD-UWP/ViewModels/HelpVM.cs
@@ -0,0 +1,72 @@
+using YJMPD_UWP.Helpers;
+
+namespace YJMPD_UWP.ViewModels
+{
+ public class HelpVM : TemplateVM
+ {
+ public HelpVM() : base(Util.Loader.GetString("Help"))
+ {
+
+ }
+
+ protected override void UpdatePropertiesToNewLanguage()
+ {
+ NotifyPropertyChanged(nameof(HelpItem1Header));
+ NotifyPropertyChanged(nameof(HelpItem1Text));
+
+ NotifyPropertyChanged(nameof(HelpItem2Header));
+ NotifyPropertyChanged(nameof(HelpItem2Text));
+
+ NotifyPropertyChanged(nameof(HelpItem3Header));
+ NotifyPropertyChanged(nameof(HelpItem3Text));
+ }
+
+ public string HelpItem1Header
+ {
+ get
+ {
+ return Util.Loader.GetString("HelpItem1Header");
+ }
+ }
+
+ public string HelpItem1Text
+ {
+ get
+ {
+ return Util.Loader.GetString("HelpItem1Text");
+ }
+ }
+
+ public string HelpItem2Header
+ {
+ get
+ {
+ return Util.Loader.GetString("HelpItem2Header");
+ }
+ }
+
+ public string HelpItem2Text
+ {
+ get
+ {
+ return Util.Loader.GetString("HelpItem2Text");
+ }
+ }
+
+ public string HelpItem3Header
+ {
+ get
+ {
+ return Util.Loader.GetString("HelpItem3Header");
+ }
+ }
+
+ public string HelpItem3Text
+ {
+ get
+ {
+ return Util.Loader.GetString("HelpItem3Text");
+ }
+ }
+ }
+}
diff --git a/YJMPD-UWP/ViewModels/MainPageVM.cs b/YJMPD-UWP/ViewModels/MainPageVM.cs
new file mode 100644
index 0000000..f6e1051
--- /dev/null
+++ b/YJMPD-UWP/ViewModels/MainPageVM.cs
@@ -0,0 +1,184 @@
+using System;
+using Windows.Devices.Geolocation;
+using Windows.UI.Core;
+using YJMPD_UWP;
+using YJMPD_UWP.Helpers;
+using YJMPD_UWP.ViewModels;
+
+namespace YJMPD_UWP.ViewModels
+{
+ public class MainPageVM : TemplateVM
+ {
+ public MainPageVM() : base(Util.Loader.GetString("Loading"))
+ {
+ App.Geo.OnPositionUpdate += Geo_OnPositionUpdate;
+ App.Geo.OnStatusUpdate += Geo_OnStatusUpdate;
+ }
+
+ protected override void UpdatePropertiesToNewLanguage()
+ {
+ NotifyPropertyChanged(nameof(Map));
+ NotifyPropertyChanged(nameof(Help));
+ NotifyPropertyChanged(nameof(Route));
+ NotifyPropertyChanged(nameof(Landmarks));
+ NotifyPropertyChanged(nameof(Search));
+ NotifyPropertyChanged(nameof(Settings));
+ NotifyPropertyChanged(nameof(Status));
+ NotifyPropertyChanged(nameof(Source));
+ NotifyPropertyChanged(nameof(Accuracy));
+ NotifyPropertyChanged(nameof(GPSInfo));
+ NotifyPropertyChanged(nameof(BackText));
+ }
+
+ public string BackText
+ {
+ get
+ {
+ return Util.Loader.GetString("BackTwiceText");
+ }
+ }
+
+
+ public string Map
+ {
+ get
+ {
+ return Util.Loader.GetString("Map");
+ }
+ }
+
+ public string Help
+ {
+ get
+ {
+ return Util.Loader.GetString("Help");
+ }
+ }
+
+ public string Route
+ {
+ get
+ {
+ return Util.Loader.GetString("Route");
+ }
+ }
+
+ public string Landmarks
+ {
+ get
+ {
+ return Util.Loader.GetString("Landmarks");
+ }
+ }
+
+ public string Search
+ {
+ get
+ {
+ return Util.Loader.GetString("Search");
+ }
+ }
+
+ public string Settings
+ {
+ get
+ {
+ return Util.Loader.GetString("Settings");
+ }
+ }
+
+ private void Geo_OnStatusUpdate(object sender, YJMPD_UWP.Model.StatusUpdatedEventArgs e)
+ {
+ dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ NotifyPropertyChanged(nameof(Status));
+ });
+ }
+
+ private void Geo_OnPositionUpdate(object sender, YJMPD_UWP.Model.PositionUpdatedEventArgs e)
+ {
+ dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ NotifyPropertyChanged(nameof(Source));
+ NotifyPropertyChanged(nameof(Accuracy));
+ });
+ }
+
+ public string GPSInfo
+ {
+ get
+ {
+ return Util.Loader.GetString("GPSInfo");
+ }
+ }
+
+ public string Status
+ {
+ get
+ {
+ switch (App.Geo.Status)
+ {
+ case PositionStatus.Disabled:
+ return Util.Loader.GetString("Disabled");
+ case PositionStatus.Initializing:
+ return Util.Loader.GetString("Initializing");
+ case PositionStatus.NoData:
+ return Util.Loader.GetString("NoData");
+ default:
+ case PositionStatus.NotAvailable:
+ return Util.Loader.GetString("NotAvailable");
+ case PositionStatus.NotInitialized:
+ return Util.Loader.GetString("NotInitialized");
+ case PositionStatus.Ready:
+ return Util.Loader.GetString("Ready");
+ }
+ }
+ }
+
+ public string Source
+ {
+ get
+ {
+ if (App.Geo.Connected == true && App.Geo.Position != null)
+ switch (App.Geo.Position.Coordinate.PositionSource)
+ {
+ case PositionSource.Cellular:
+ return Util.Loader.GetString("Cellular");
+ case PositionSource.IPAddress:
+ return Util.Loader.GetString("IPAddress");
+ case PositionSource.Satellite:
+ return Util.Loader.GetString("Satellite");
+ case PositionSource.WiFi:
+ return Util.Loader.GetString("WiFi");
+ default:
+ case PositionSource.Unknown:
+ return Util.Loader.GetString("Unknown");
+
+ }
+ else
+ return Util.Loader.GetString("Unknown");
+ }
+ }
+
+ public string Accuracy
+ {
+ get
+ {
+
+ if (App.Geo.Connected == true && App.Geo.Position != null)
+ return App.Geo.Position.Coordinate.Accuracy.ToString() + "m";
+ else
+ return Util.Loader.GetString("Unknown");
+ }
+ }
+
+ public string Year
+ {
+ get
+ {
+ int year = DateTime.Now.Year;
+ return year.ToString();
+ }
+ }
+ }
+}
diff --git a/YJMPD-UWP/ViewModels/SettingsVM.cs b/YJMPD-UWP/ViewModels/SettingsVM.cs
new file mode 100644
index 0000000..456f7f8
--- /dev/null
+++ b/YJMPD-UWP/ViewModels/SettingsVM.cs
@@ -0,0 +1,45 @@
+using YJMPD_UWP.Helpers;
+
+namespace YJMPD_UWP.ViewModels
+{
+ public class SettingsVM : TemplateVM
+ {
+
+ public SettingsVM() : base(Util.Loader.GetString("Settings"))
+ {
+
+ }
+
+ protected override void UpdatePropertiesToNewLanguage()
+ {
+ NotifyPropertyChanged(nameof(Language));
+ NotifyPropertyChanged(nameof(Reset));
+ NotifyPropertyChanged(nameof(ResetHeader));
+ App.MainPage.Title = Util.Loader.GetString("Settings");
+ }
+
+ public string Language
+ {
+ get
+ {
+ return Util.Loader.GetString("Language");
+ }
+ }
+
+ public string ResetHeader
+ {
+ get
+ {
+ return Util.Loader.GetString("Reset");
+ }
+ }
+
+ public string Reset
+ {
+ get
+ {
+ return Util.Loader.GetString("Reset") + " " + Util.Loader.GetString("Application");
+ }
+ }
+ }
+}
diff --git a/YJMPD-UWP/ViewModels/TemplateVM.cs b/YJMPD-UWP/ViewModels/TemplateVM.cs
new file mode 100644
index 0000000..bffa9a4
--- /dev/null
+++ b/YJMPD-UWP/ViewModels/TemplateVM.cs
@@ -0,0 +1,41 @@
+using YJMPD_UWP.Helpers;
+using System;
+using System.ComponentModel;
+using Windows.UI.Core;
+
+namespace YJMPD_UWP.ViewModels
+{
+ public class TemplateVM : INotifyPropertyChanged
+ {
+ protected CoreDispatcher dispatcher;
+
+ public TemplateVM(string title)
+ {
+ dispatcher = App.Dispatcher;
+ Settings.OnLanguageUpdate += Settings_OnLanguageUpdate;
+
+ if (App.MainPage != null)
+ App.MainPage.Title = title;
+ }
+
+ private void Settings_OnLanguageUpdate(EventArgs e)
+ {
+ dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ UpdatePropertiesToNewLanguage();
+ });
+ }
+
+ protected virtual void UpdatePropertiesToNewLanguage()
+ {
+ //to implement in underlying class
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected void NotifyPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/YJMPD-UWP/Views/HelpView.xaml b/YJMPD-UWP/Views/HelpView.xaml
new file mode 100644
index 0000000..8ec6c7b
--- /dev/null
+++ b/YJMPD-UWP/Views/HelpView.xaml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/YJMPD-UWP/Views/HelpView.xaml.cs b/YJMPD-UWP/Views/HelpView.xaml.cs
new file mode 100644
index 0000000..db8150b
--- /dev/null
+++ b/YJMPD-UWP/Views/HelpView.xaml.cs
@@ -0,0 +1,17 @@
+using YJMPD_UWP.ViewModels;
+using Windows.UI.Xaml.Controls;
+
+namespace YJMPD_UWP.Views
+{
+ public sealed partial class HelpView : Page
+ {
+ HelpVM helpvm;
+
+ public HelpView()
+ {
+ helpvm = new HelpVM();
+ this.DataContext = helpvm;
+ this.InitializeComponent();
+ }
+ }
+}
diff --git a/YJMPD-UWP/Views/SettingsView.xaml b/YJMPD-UWP/Views/SettingsView.xaml
new file mode 100644
index 0000000..3e2556e
--- /dev/null
+++ b/YJMPD-UWP/Views/SettingsView.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+ English
+ Nederlands
+ Deutsch
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/YJMPD-UWP/Views/SettingsView.xaml.cs b/YJMPD-UWP/Views/SettingsView.xaml.cs
new file mode 100644
index 0000000..c0ab959
--- /dev/null
+++ b/YJMPD-UWP/Views/SettingsView.xaml.cs
@@ -0,0 +1,82 @@
+using YJMPD_UWP.Helpers;
+using YJMPD_UWP.ViewModels;
+using System.Diagnostics;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace YJMPD_UWP.Views
+{
+ public sealed partial class SettingsView : Page
+ {
+ SettingsVM settingsvm;
+
+ public SettingsView()
+ {
+ this.InitializeComponent();
+ settingsvm = new SettingsVM();
+ this.DataContext = settingsvm;
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ switch (Settings.CurrentLanguage)
+ {
+ default:
+ Debug.WriteLine("Unsupported language: " + Settings.CurrentLanguage);
+ Language.SelectedIndex = 0;
+ break;
+ case "en":
+ Language.SelectedIndex = 0;
+ break;
+ case "nl":
+ Language.SelectedIndex = 1;
+ break;
+ case "de":
+ Language.SelectedIndex = 2;
+ break;
+ case "ja":
+ Language.SelectedIndex = 3;
+ break;
+ }
+ }
+
+ private void Language_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ switch (Language.SelectedIndex)
+ {
+ default:
+ Language.SelectedIndex = 0;
+ break;
+ case 0:
+ if (Settings.CurrentLanguage != "en")
+ Settings.ChangeLanguage("en");
+ break;
+ case 1:
+ if (Settings.CurrentLanguage != "nl")
+ Settings.ChangeLanguage("nl");
+ break;
+ case 2:
+ if (Settings.CurrentLanguage != "de")
+ Settings.ChangeLanguage("de");
+ break;
+ case 3:
+ if (Settings.CurrentLanguage != "ja")
+ Settings.ChangeLanguage("ja");
+ break;
+ }
+ }
+
+ private async void ResetButton_Click(object sender, RoutedEventArgs e)
+ {
+ bool confirm = await Util.ShowConfirmDialog(Util.Loader.GetString("Reset"), Util.Loader.GetString("ResetConfirmation"), Util.DialogType.YESNO);
+
+ if (confirm)
+ {
+ ResetProgress.IsActive = true;
+ Language.SelectedIndex = 0;
+ ResetProgress.IsActive = false;
+ }
+ }
+ }
+}
diff --git a/YJMPD-UWP/YJMPD-UWP.csproj b/YJMPD-UWP/YJMPD-UWP.csproj
index e444ad5..cc60dd0 100644
--- a/YJMPD-UWP/YJMPD-UWP.csproj
+++ b/YJMPD-UWP/YJMPD-UWP.csproj
@@ -1,10 +1,10 @@
-
+
Debug
x86
- {7be4d70c-7653-4757-800b-73dc1f8d19f7}
+ {7BE4D70C-7653-4757-800B-73DC1F8D19F7}
AppContainerExe
Properties
YJMPD_UWP
@@ -16,9 +16,7 @@
14
512
{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
-
YJMPD-UWP_TemporaryKey.pfx
-
true
@@ -97,18 +95,73 @@
App.xaml
+
+
+
+
+
+
+
+
+
+
+
+
MainPage.xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HelpView.xaml
+
+
+ LandmarkDetailView.xaml
+
+
+ LandmarkView.xaml
+
+
+ MapView.xaml
+
+
+ RouteDetailView.xaml
+
+
+ RouteView.xaml
+
+
+ SearchView.xaml
+
+
+ SettingsView.xaml
+
Designer
-
-
@@ -129,12 +182,54 @@
MSBuild:Compile
Designer
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
-
14.0
-
-
+
\ No newline at end of file
diff --git a/YJMPD-UWP/project.json b/YJMPD-UWP/project.json
index c594939..2c3ee60 100644
--- a/YJMPD-UWP/project.json
+++ b/YJMPD-UWP/project.json
@@ -1,6 +1,7 @@
{
"dependencies": {
- "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0",
+ "Newtonsoft.Json": "8.0.2"
},
"frameworks": {
"uap10.0": {}