Updated to use latest Lumia SensorCore SDK 1.1 Preview

This commit is contained in:
Satyam Bandarapu 2015-03-03 16:58:17 +02:00
Родитель 034deb40f0
Коммит 5adca97155
28 изменённых файлов: 1691 добавлений и 373 удалений

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -59,7 +60,7 @@ namespace Places
this.Loaded += (sender, args) =>
{
var ver = Windows.ApplicationModel.Package.Current.Id.Version;
VersionNumber.Text = string.Format("{0}.{1}.{2}", ver.Major, ver.Minor, ver.Revision);
VersionNumber.Text = string.Format("{0}.{1}.{2}.{3}", ver.Major, ver.Minor,ver.Build, ver.Revision);
};
}

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -29,27 +30,17 @@ using Windows.UI.Xaml.Navigation;
namespace Places.Common
{
/// <summary>
/// Represents the method that will handle the <see cref="NavigationHelper.LoadState"/> event.
/// </summary>
public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e);
/// <summary>
/// Represents the method that will handle the <see cref="NavigationHelper.SaveState"/> event.
/// </summary>
public delegate void SaveStateEventHandler(object sender, SaveStateEventArgs e);
/// <summary>
/// NavigationHelper aids in navigation between pages. It provides commands used to
/// navigate back and forward as well as registers for standard mouse and keyboard
/// shortcuts used to go back and forward. In addition it integrates SuspensionManger
/// to handle process lifetime management and state management when navigating between
/// pages.
/// shortcuts used to go back and forward in Windows and the hardware back button in
/// Windows Phone. In addition it integrates SuspensionManger to handle process lifetime
/// management and state management when navigating between pages.
/// </summary>
/// <example>
/// To make use of NavigationHelper, follow these two steps or start with a BasicPage
/// or any other Page item template other than BlankPage.
/// <para>
/// To make use of NavigationHelper, follow these two steps or
/// start with a BasicPage or any other Page item template other than BlankPage.
///
/// 1) Create an instance of the NavigationHelper somewhere such as in the
/// constructor for the page and register a callback for the LoadState and
/// SaveState events.
@ -62,14 +53,13 @@ namespace Places.Common
/// this.navigationHelper.SaveState += navigationHelper_SaveState;
/// }
///
/// async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
/// private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
/// { }
/// private async void navigationHelper_SaveState(object sender, LoadStateEventArgs e)
/// { }
/// </code>
/// </para>
/// <para>
/// 2) Register the page to call into the NavigationManager whenever the page participates
///
/// 2) Register the page to call into the NavigationHelper whenever the page participates
/// in navigation by overriding the <see cref="Windows.UI.Xaml.Controls.Page.OnNavigatedTo"/>
/// and <see cref="Windows.UI.Xaml.Controls.Page.OnNavigatedFrom"/> events.
/// <code>
@ -83,156 +73,127 @@ namespace Places.Common
/// navigationHelper.OnNavigatedFrom(e);
/// }
/// </code>
/// </para>
/// </example>
[Windows.Foundation.Metadata.WebHostHidden]
public class NavigationHelper : DependencyObject
{
#region Private constants
/// <summary>
/// Page instance
/// </summary>
private readonly Page page;
/// <summary>
/// RelayCommand instance for go back command
/// </summary>
private RelayCommand goBackCommand;
/// <summary>
/// RelayCommand instance for go forward command
/// </summary>
private RelayCommand goForwardCommand;
/// <summary>
/// Page key
/// </summary>
private string pageKey;
#endregion
private Page Page { get; set; }
private Frame Frame { get { return this.Page.Frame; } }
/// <summary>
/// Initializes a new instance of the <see cref="NavigationHelper"/> class.
/// </summary>
/// <param name="page">
/// A reference to the current page used for navigation.
/// <param name="page">A reference to the current page used for navigation.
/// This reference allows for frame manipulation and to ensure that keyboard
/// navigation requests only occur when the page is occupying the entire window.
/// </param>
/// navigation requests only occur when the page is occupying the entire window.</param>
public NavigationHelper(Page page)
{
this.page = page;
this.Page = page;
// When this page is part of the visual tree make two changes:
// 1) Map application view state to visual state for the page
// 2) Handle keyboard and mouse navigation requests
this.page.Loaded += (sender, e) =>
// 2) Handle hardware navigation requests
this.Page.Loaded += (sender, e) =>
{
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#else
// Keyboard and mouse navigation only apply when occupying the entire window
if (this.page.ActualHeight == Window.Current.Bounds.Height && this.page.ActualWidth == Window.Current.Bounds.Width)
if (this.Page.ActualHeight == Window.Current.Bounds.Height &&
this.Page.ActualWidth == Window.Current.Bounds.Width)
{
// Listen to the window directly so focus isn't required
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += CoreDispatcher_AcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed += this.CoreWindow_PointerPressed;
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated +=
CoreDispatcher_AcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed +=
this.CoreWindow_PointerPressed;
}
#endif
};
// Undo the same changes when the page is no longer visible
this.page.Unloaded += (sender, e) =>
this.Page.Unloaded += (sender, e) =>
{
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated -= CoreDispatcher_AcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed -= this.CoreWindow_PointerPressed;
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
#else
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated -=
CoreDispatcher_AcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed -=
this.CoreWindow_PointerPressed;
#endif
};
}
/// <summary>
/// Register this event on the current page to populate the page
/// with content passed during navigation as well as any saved
/// state provided when recreating a page from a prior session.
/// </summary>
public event LoadStateEventHandler LoadState;
#region Navigation support
RelayCommand _goBackCommand;
RelayCommand _goForwardCommand;
/// <summary>
/// Register this event on the current page to preserve
/// state associated with the current page in case the
/// application is suspended or the page is discarded from
/// the navigation cache.
/// </summary>
public event SaveStateEventHandler SaveState;
/// <summary>
/// Gets or sets the <see cref="RelayCommand"/> used to bind to the back Button's Command
/// property for navigating to the most recent item in back navigation history, if a Frame
/// <see cref="RelayCommand"/> used to bind to the back Button's Command property
/// for navigating to the most recent item in back navigation history, if a Frame
/// manages its own navigation history.
/// <para>
///
/// The <see cref="RelayCommand"/> is set up to use the virtual method <see cref="GoBack"/>
/// as the Execute Action and <see cref="CanGoBack"/> for CanExecute.
/// </para>
/// </summary>
public RelayCommand GoBackCommand
{
get
{
if (this.goBackCommand == null)
if (_goBackCommand == null)
{
this.goBackCommand = new RelayCommand(
_goBackCommand = new RelayCommand(
() => this.GoBack(),
() => this.CanGoBack());
}
return this.goBackCommand;
return _goBackCommand;
}
set
{
this.goBackCommand = value;
_goBackCommand = value;
}
}
/// <summary>
/// Gets the <see cref="RelayCommand"/> used for navigating to the most recent item in
/// <see cref="RelayCommand"/> used for navigating to the most recent item in
/// the forward navigation history, if a Frame manages its own navigation history.
/// <para>
///
/// The <see cref="RelayCommand"/> is set up to use the virtual method <see cref="GoForward"/>
/// as the Execute Action and <see cref="CanGoForward"/> for CanExecute.
/// </para>
/// </summary>
public RelayCommand GoForwardCommand
{
get
{
if (this.goForwardCommand == null)
if (_goForwardCommand == null)
{
this.goForwardCommand = new RelayCommand(
_goForwardCommand = new RelayCommand(
() => this.GoForward(),
() => this.CanGoForward());
}
return this.goForwardCommand;
return _goForwardCommand;
}
}
/// <summary>
/// Gets the current page
/// </summary>
private Frame Frame
{
get { return this.page.Frame; }
}
/// <summary>
/// Virtual method used by the <see cref="GoBackCommand"/> property
/// to determine if the <see cref="Frame"/> can go back.
/// </summary>
/// <returns>
/// True if the <see cref="Frame"/> has at least one entry
/// true if the <see cref="Frame"/> has at least one entry
/// in the back navigation history.
/// </returns>
public virtual bool CanGoBack()
{
return this.Frame != null && this.Frame.CanGoBack;
}
/// <summary>
/// Virtual method used by the <see cref="GoForwardCommand"/> property
/// to determine if the <see cref="Frame"/> can go forward.
/// </summary>
/// <returns>
/// True if the <see cref="Frame"/> has at least one entry
/// true if the <see cref="Frame"/> has at least one entry
/// in the forward navigation history.
/// </returns>
public virtual bool CanGoForward()
@ -246,80 +207,32 @@ namespace Places.Common
/// </summary>
public virtual void GoBack()
{
if (this.Frame != null && this.Frame.CanGoBack)
{
this.Frame.GoBack();
if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack();
}
}
/// <summary>
/// Virtual method used by the <see cref="GoForwardCommand"/> property
/// to invoke the <see cref="Windows.UI.Xaml.Controls.Frame.GoForward"/> method.
/// </summary>
public virtual void GoForward()
{
if (this.Frame != null && this.Frame.CanGoForward)
{
this.Frame.GoForward();
}
if (this.Frame != null && this.Frame.CanGoForward) this.Frame.GoForward();
}
#if WINDOWS_PHONE_APP
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// This method calls <see cref="LoadState"/>, where all page specific
/// navigation and process lifetime management logic should be placed.
/// Invoked when the hardware back button is pressed. For Windows Phone only.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
public void OnNavigatedTo(NavigationEventArgs e)
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
this.pageKey = "Page-" + this.Frame.BackStackDepth;
if (e.NavigationMode == NavigationMode.New)
if (this.GoBackCommand.CanExecute(null))
{
// Clear existing state for forward navigation when adding a new page to the
// navigation stack
var nextPageKey = this.pageKey;
int nextPageIndex = this.Frame.BackStackDepth;
while (frameState.Remove(nextPageKey))
{
nextPageIndex++;
nextPageKey = "Page-" + nextPageIndex;
}
// Pass the navigation parameter to the new page
if (this.LoadState != null)
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, null));
e.Handled = true;
this.GoBackCommand.Execute(null);
}
}
else
{
// Pass the navigation parameter and preserved page state to the page, using
// the same strategy for loading suspended state and recreating pages discarded
// from cache
if (this.LoadState != null)
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary<string, object>)frameState[this.pageKey]));
}
}
}
/// <summary>
/// Invoked when this page will no longer be displayed in a Frame.
/// This method calls <see cref="SaveState"/>, where all page specific
/// navigation and process lifetime management logic should be placed.
/// </summary>
public void OnNavigatedFrom(NavigationEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
var pageState = new Dictionary<string, object>();
if (this.SaveState != null)
{
this.SaveState(this, new SaveStateEventArgs(pageState));
}
frameState[this.pageKey] = pageState;
}
#else
/// <summary>
/// Invoked on every keystroke, including system keys such as Alt key combinations, when
/// this page is active and occupies the entire window. Used to detect keyboard navigation
@ -327,9 +240,11 @@ namespace Places.Common
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs e)
private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender,
AcceleratorKeyEventArgs e)
{
var virtualKey = e.VirtualKey;
// Only investigate further when Left, Right, or the dedicated Previous or Next keys
// are pressed
if ((e.EventType == CoreAcceleratorKeyEventType.SystemKeyDown ||
@ -344,13 +259,16 @@ namespace Places.Common
bool shiftKey = (coreWindow.GetKeyState(VirtualKey.Shift) & downState) == downState;
bool noModifiers = !menuKey && !controlKey && !shiftKey;
bool onlyAlt = menuKey && !controlKey && !shiftKey;
if (((int)virtualKey == 166 && noModifiers) || (virtualKey == VirtualKey.Left && onlyAlt))
if (((int)virtualKey == 166 && noModifiers) ||
(virtualKey == VirtualKey.Left && onlyAlt))
{
// When the previous key or Alt+Left are pressed navigate back
e.Handled = true;
this.GoBackCommand.Execute(null);
}
else if (((int)virtualKey == 167 && noModifiers) || (virtualKey == VirtualKey.Right && onlyAlt))
else if (((int)virtualKey == 167 && noModifiers) ||
(virtualKey == VirtualKey.Right && onlyAlt))
{
// When the next key or Alt+Right are pressed navigate forward
e.Handled = true;
@ -366,37 +284,135 @@ namespace Places.Common
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
private void CoreWindow_PointerPressed(CoreWindow sender, PointerEventArgs e)
private void CoreWindow_PointerPressed(CoreWindow sender,
PointerEventArgs e)
{
var properties = e.CurrentPoint.Properties;
// Ignore button chords with the left, right, and middle buttons
if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed || properties.IsMiddleButtonPressed)
{
return;
}
if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed ||
properties.IsMiddleButtonPressed) return;
// If back or foward are pressed (but not both) navigate appropriately
bool backPressed = properties.IsXButton1Pressed;
bool forwardPressed = properties.IsXButton2Pressed;
if (backPressed ^ forwardPressed)
{
e.Handled = true;
if (backPressed)
{
this.GoBackCommand.Execute(null);
if (backPressed) this.GoBackCommand.Execute(null);
if (forwardPressed) this.GoForwardCommand.Execute(null);
}
if (forwardPressed)
{
this.GoForwardCommand.Execute(null);
}
#endif
#endregion
#region Process lifetime management
private String _pageKey;
/// <summary>
/// Register this event on the current page to populate the page
/// with content passed during navigation as well as any saved
/// state provided when recreating a page from a prior session.
/// </summary>
public event LoadStateEventHandler LoadState;
/// <summary>
/// Register this event on the current page to preserve
/// state associated with the current page in case the
/// application is suspended or the page is discarded from
/// the navigaqtion cache.
/// </summary>
public event SaveStateEventHandler SaveState;
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// This method calls <see cref="LoadState"/>, where all page specific
/// navigation and process lifetime management logic should be placed.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property provides the group to be displayed.</param>
public void OnNavigatedTo(NavigationEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
this._pageKey = "Page-" + this.Frame.BackStackDepth;
if (e.NavigationMode == NavigationMode.New)
{
// Clear existing state for forward navigation when adding a new page to the
// navigation stackOnLaunched
var nextPageKey = this._pageKey;
int nextPageIndex = this.Frame.BackStackDepth;
while (frameState.Remove(nextPageKey))
{
nextPageIndex++;
nextPageKey = "Page-" + nextPageIndex;
}
// Pass the navigation parameter to the new page
if (this.LoadState != null)
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, null));
}
}
else
{
// Pass the navigation parameter and preserved page state to the page, using
// the same strategy for loading suspended state and recreating pages discarded
// from cache
if (this.LoadState != null)
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey]));
}
}
}
/// <summary>
/// Holds the event data required when a page attempts to load state.
/// Invoked when this page will no longer be displayed in a Frame.
/// This method calls <see cref="SaveState"/>, where all page specific
/// navigation and process lifetime management logic should be placed.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property provides the group to be displayed.</param>
public void OnNavigatedFrom(NavigationEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
var pageState = new Dictionary<String, Object>();
if (this.SaveState != null)
{
this.SaveState(this, new SaveStateEventArgs(pageState));
}
frameState[_pageKey] = pageState;
}
#endregion
}
/// <summary>
/// Represents the method that will handle the <see cref="NavigationHelper.LoadState"/>event
/// </summary>
public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e);
/// <summary>
/// Represents the method that will handle the <see cref="NavigationHelper.SaveState"/>event
/// </summary>
public delegate void SaveStateEventHandler(object sender, SaveStateEventArgs e);
/// <summary>
/// Class used to hold the event data required when a page attempts to load state.
/// </summary>
public class LoadStateEventArgs : EventArgs
{
/// <summary>
/// The parameter value passed to <see cref="Frame.Navigate(Type, Object)"/>
/// when this page was initially requested.
/// </summary>
public Object NavigationParameter { get; private set; }
/// <summary>
/// A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.
/// </summary>
public Dictionary<string, Object> PageState { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="LoadStateEventArgs"/> class.
/// </summary>
@ -408,42 +424,31 @@ namespace Places.Common
/// A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.
/// </param>
public LoadStateEventArgs(object navigationParameter, Dictionary<string, object> pageState): base()
public LoadStateEventArgs(Object navigationParameter, Dictionary<string, Object> pageState)
: base()
{
this.NavigationParameter = navigationParameter;
this.PageState = pageState;
}
/// <summary>
/// Gets the parameter value passed to <see cref="Frame.Navigate(Type, Object)"/>
/// when this page was initially requested.
/// </summary>
public object NavigationParameter { get; private set; }
/// <summary>
/// Gets a dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.
/// </summary>
public Dictionary<string, object> PageState { get; private set; }
}
/// <summary>
/// Holds the event data required when a page attempts to save state.
/// Class used to hold the event data required when a page attempts to save state.
/// </summary>
public class SaveStateEventArgs : EventArgs
{
/// <summary>
/// An empty dictionary to be populated with serializable state.
/// </summary>
public Dictionary<string, Object> PageState { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="SaveStateEventArgs"/> class.
/// </summary>
/// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
public SaveStateEventArgs(Dictionary<string, object> pageState): base()
public SaveStateEventArgs(Dictionary<string, Object> pageState)
: base()
{
this.PageState = pageState;
}
/// <summary>
/// Gets an empty dictionary to be populated with serializable state.
/// </summary>
public Dictionary<string, object> PageState { get; private set; }
}
}

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Двоичные данные
Places/Help/LumiaSensorCoreSDK.chm

Двоичный файл не отображается.

Двоичные данные
Places/Help/SensorCoreSDK.chw

Двоичный файл не отображается.

125
Places/HistoryPage.xaml Normal file
Просмотреть файл

@ -0,0 +1,125 @@
<Page
x:Class="Places.HistoryPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Places"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="#A4C400">
<!-- Set properties of ListBox control -->
<Page.Resources>
<Style TargetType="ListBoxItem" x:Key="ItemContainerStyle">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Margin" Value="12,0,12,0" />
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver"/>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PressedBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="InnerGrid"
Background="Transparent">
<Rectangle x:Name="PressedBackground"
Fill="{ThemeResource ListBoxItemPressedBackgroundThemeBrush}"
Opacity="0" />
<ContentPresenter x:Name="ContentPresenter"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid x:Name ="LayoutRoot">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitlePanel -->
<StackPanel Grid.Row="0" Margin="24,17,0,28">
<TextBlock x:Uid="Application"
Text=""
Style="{ThemeResource TitleTextBlockStyle}"
Typography.Capitals="SmallCaps"
Foreground="Black"/>
<TextBlock x:Uid="HistoryPage"
Text=""
Margin="0,12,0,0"
FontSize="60"
Style="{ThemeResource HeaderTextBlockStyle}"
Foreground="Black"/>
</StackPanel>
<!-- ListBox for places history -->
<ScrollViewer Grid.Row="1">
<StackPanel x:Name="ContentPanel" Margin="12,0,12,0">
<ListBox x:Name="PlacesSummary"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Background="Transparent"
ItemContainerStyle="{StaticResource ItemContainerStyle}"
ItemsSource ="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding ImagePath}"/>
<TextBlock Text="{Binding Text}"
TextWrapping="Wrap"
HorizontalAlignment="Center"
Padding="3"
Grid.Column="1"/>
</Grid>
<Rectangle Grid.Row="1"
Fill="LightGray"
Height="3"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>

118
Places/HistoryPage.xaml.cs Normal file
Просмотреть файл

@ -0,0 +1,118 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Places.Utilities;
/// <summary>
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkID=390556
/// </summary>
namespace Places
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class HistoryPage : Page
{
#region Private members
/// <summary>
/// List with place history
/// </summary>
private List<string> _myData;
/// <summary>
/// Image Path for the place type image
/// </summary>
private string _imagePath;
#endregion
/// <summary>
/// Constructor
/// </summary>
public HistoryPage()
{
this.InitializeComponent();
this.Loaded += HistoryPage_Loaded;
}
/// <summary>
/// Is called when page loading is done
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">Contains state information and event data associated with a routed event.</param>
void HistoryPage_Loaded(object sender, RoutedEventArgs e)
{
// Find the Image control inside the ListBox Data Template
CreatePlacesHistory();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Get the list of history data passed from previous page
_myData = e.Parameter as List<string>;
}
/// <summary>
/// Add places to listbox
/// </summary>
/// <param name="targetElement"></param>
private void CreatePlacesHistory()
{
var places = new List<PlaceHistory>();
// Set image source for each type of place
foreach (var p in _myData)
{
if (p.Contains("Home"))
{
_imagePath = "ms-appx:///Assets/show-home.png";
}
if (p.Contains("Work"))
{
_imagePath = "ms-appx:///Assets/show-work.png";
}
if (p.Contains("Frequent"))
{
_imagePath = "ms-appx:///Assets/show-current-location.png";
}
if (p.Contains("Known"))
{
_imagePath = "ms-appx:///Assets/show-current-location.png";
}
if (p.Contains("Frequent"))
{
_imagePath = "ms-appx:///Assets/show-next-favorite.png";
}
PlaceHistory placeHistory = new PlaceHistory() { Text = p, ImagePath = _imagePath };
places.Add(placeHistory);
}
this.PlacesSummary.DataContext = places;
}
}
}

Просмотреть файл

@ -8,6 +8,9 @@
x:Class="Places.MapPage"
mc:Ignorable="d"
Background="#A4C400">
<Page.Resources>
<CollectionViewSource x:Name="listSource"/>
</Page.Resources>
<Grid x:Name="LayoutRoot">
<Grid.ChildrenTransitions>
<TransitionCollection>
@ -26,7 +29,8 @@
<!--Content should be placed within the following grid-->
<Grid Grid.Row="1" x:Name="ContentRoot" >
<maps:MapControl x:Name="PlacesMap" Margin="0,0,0,0"
MapTapped="OnTapped" ZoomLevel="12"/>
ZoomLevel="13"/>
<TextBlock x:Name="FilterTime" FontSize="24" TextAlignment="Right" Width="480" Height="30" HorizontalAlignment="Right" VerticalAlignment="Top" Foreground="#7F000000" Margin="5,5"/>
<SymbolIcon x:Name="FullScreeButton" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,15,31" Symbol="FullScreen" Tapped="FullScreeButton_OnTapped" RenderTransformOrigin="0.5,0.5" Grid.Column="1">
<SymbolIcon.RenderTransform>
<CompositeTransform ScaleX="2" ScaleY="2"/>
@ -58,6 +62,18 @@
</AppBarButton>
<CommandBar.SecondaryCommands>
<AppBarButton x:Uid="AboutButton" x:Name="AboutButton" Label="" Click="OnAboutClicked"/>
<AppBarButton x:Uid="HistoryButton" x:Name="HistoryButton" Label="" Click="OnPollHistory"/>
<AppBarButton x:Uid="FilterButton" x:Name="FilterButton" Label="" Click="SelectButton_Click">
<MenuFlyout x:Name="menuFlyout">
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="5"/>
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
<MenuFlyoutItem x:Name="flyoutItem" Background="Black" Click="flyoutItem_Click" Margin="0,0,20.833,0"/>
</MenuFlyout>
</AppBarButton>
</CommandBar.SecondaryCommands>
</CommandBar>
</Page.BottomAppBar>

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -39,6 +40,9 @@ using Windows.Devices.Geolocation.Geofencing;
using System.Collections.Generic;
using Monitor = Lumia.Sense.PlaceMonitor;
using Windows.ApplicationModel.Resources;
using Windows.Storage.Streams;
using System.Globalization;
using Windows.Foundation;
/// <summary>
/// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkID=390556
@ -57,6 +61,11 @@ namespace Places
/// </summary>
private readonly Color PlacesColorHome = Color.FromArgb(AlphaLevelOfPlacesCircle, 31, 127, 31);
/// <summary>
/// holds all the pushpins in the map
/// </summary>
List<PushPin> pins = null;
/// <summary>
/// Work color mapping
/// </summary>
@ -115,16 +124,31 @@ namespace Places
/// </summary>
private Places.App _app = Application.Current as Places.App;
/// <summary>
/// List of places
/// </summary>
private List<string> resultStr = new List<string>();
/// <summary>
/// Place monitor instance
/// </summary>
private Monitor _placeMonitor;
/// <summary>
/// check to see launching finished or not
/// </summary>
private bool iLaunched = false;
/// <summary>
/// Geolocator instance
/// </summary>
private Geolocator _geoLocator;
/// <summary>
/// List of activities for a place
/// </summary>
List<Activity> activitiesToShow = new List<Activity>();
/// <summary>
/// CancellationToken Source instance
/// </summary>
@ -149,12 +173,52 @@ namespace Places
/// <summary>
/// Initialize SensorCore and find the current position
/// </summary>
private async void InitCore()
private async Task InitCore()
{
if (_placeMonitor == null)
try
{
// Following code assumes that device has new software(SensorCoreSDK1.1 based)
if (!(await PlaceMonitor.IsSupportedAsync()))
{
MessageDialog dlg = new MessageDialog("Unfortunately this device does not support viewing visited places");
await dlg.ShowAsync();
Application.Current.Exit();
}
else
{
uint apiSet = await SenseHelper.GetSupportedApiSetAsync();
MotionDataSettings settings = await SenseHelper.GetSettingsAsync();
if (!settings.LocationEnabled)
{
MessageDialog dlg = new MessageDialog("In order to collect and view visited places you need to enable location in system settings. Do you want to open settings now? if no, applicatoin will exit", "Information");
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchLocationSettingsAsync())));
dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler((cmd) => { Application.Current.Exit(); })));
await dlg.ShowAsync();
}
if (!settings.PlacesVisited)
{
MessageDialog dlg = null;
if (settings.Version < 2)
{
//device which has old motion data settings.
//this is equal to motion data settings on/off in old system settings(SDK1.0 based)
dlg = new MessageDialog("In order to collect and view visited places you need to enable Motion data in Motion data settings. Do you want to open settings now? if no, application will exit", "Information");
}
else
{
dlg = new MessageDialog("In order to collect and view visited places you need to 'enable Places visited' and 'DataQuality to detailed' in Motion data settings. Do you want to open settings now? if no, application will exit", "Information");
}
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchSenseSettingsAsync())));
dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler((cmd) =>{ Application.Current.Exit(); })));
await dlg.ShowAsync();
}
}
}
catch (Exception)
{
}
// This is not implemented by the simulator, uncomment for the PlaceMonitor
if (await Monitor.IsSupportedAsync())
if (_placeMonitor == null)
{
// Init SensorCore
if (await CallSensorcoreApiAsync(async () => { _placeMonitor = await Monitor.GetDefaultAsync(); }))
@ -166,6 +230,8 @@ namespace Places
WorkButton.IsEnabled = true;
FrequentButton.IsEnabled = true;
CurrentButton.IsEnabled = true;
await ActivityReader.Instance().Initialize();
resultStr = await GetPlacesHistory();
}
else return;
}
@ -224,7 +290,6 @@ namespace Places
{
_cancellationTokenSource = null;
}
}
// Activate and deactivate the SensorCore when the visibility of the app changes
Window.Current.VisibilityChanged += async (oo, ee) =>
{
@ -284,7 +349,7 @@ namespace Places
{
if (GeofenceMonitor.Current.Geofences.All(v => v.Id != fenceKey))
{
var position = new BasicGeoposition {Latitude = latitude, Longitude = longitude, Altitude = 0.0};
var position = new BasicGeoposition { Latitude = latitude, Longitude = longitude, Altitude = 0.0 };
CreateCircle(position, radius, fenceColor);
// The geofence is a circular region
var geocircle = new Geocircle(position, radius);
@ -406,18 +471,40 @@ namespace Places
{
_app.Places = null;
PlacesMap.MapElements.Clear();
if (await CallSensorcoreApiAsync(async () => { _app.Places = await _placeMonitor.GetKnownPlacesAsync();}))
PlacesMap.Children.Clear();
if (await CallSensorcoreApiAsync(async () =>
{ // Get selected day places, else all places
if (_selectedDay != null && !_selectedDay.Name.Equals("All", StringComparison.CurrentCultureIgnoreCase))
{
if (_app.Places.Count > 0)
System.Diagnostics.Debug.WriteLine("GetPlace: " + _selectedDay.Name);
_app.Places = await _placeMonitor.GetPlaceHistoryAsync(_selectedDay.Day, TimeSpan.FromHours(24));
}
else
{
System.Diagnostics.Debug.WriteLine("Places: Get all known places");
_app.Places = await _placeMonitor.GetKnownPlacesAsync();
}
}))
{
// Make sure that there were Places for the timespan
if (_app.Places != null && _app.Places.Count > 0)
{
PlacesMap.Children.Clear();
if (pins != null)
{
pins.Clear();
pins = null;
}
pins = new List<PushPin>();
int i = 0;
foreach (var p in _app.Places)
{
System.Diagnostics.Debug.WriteLine("Place {0} radius {1} Latitude {2} Longitude {3} ", p.Kind, p.Radius, p.Position.Latitude, p.Position.Longitude);
var mapIcon = new MapIcon();
MapExtensions.SetValue(mapIcon, p);
mapIcon.NormalizedAnchorPoint = new Windows.Foundation.Point(0.5, 0.5);
mapIcon.Location = new Geopoint(p.Position);
mapIcon.Title = p.Kind.ToString();
System.Diagnostics.Debug.WriteLine("Place {0} radius {1} Latitude {2} Longitude {3} Total visit count {4} Total length of stay {5} Length of stay {6} Kind {7} ", p.Kind, p.Radius, p.Position.Latitude, p.Position.Longitude, p.TotalVisitCount, p.TotalLengthOfStay, p.LengthOfStay, p.Kind);
pins.Add(new PushPin(p, p.Kind.ToString()));
MapControl.SetLocation(pins[i], new Geopoint(p.Position));
MapControl.SetNormalizedAnchorPoint(pins[i], new Point(0.15, 1));
PlacesMap.Children.Add(pins[i]);
i = i + 1;
Color placesColor;
//Set for each type of a place a certain color and set custom image for the MapIcon
switch (p.Kind)
@ -438,8 +525,6 @@ namespace Places
placesColor = PlacesColorUnknown;
break;
}
// Use MapElements collection to add a custom image, text and location to MapIcon
PlacesMap.MapElements.Add(mapIcon);
CreateGeofence(p.Id.ToString(), p.Position.Latitude, p.Position.Longitude, p.Radius, placesColor);
}
}
@ -453,7 +538,7 @@ namespace Places
/// </summary>
/// <param name="action">The function delegate to execute asynchronously when one task in the tasks completes.</param>
/// <returns><c>true</c> if call was successful, <c>false</c> otherwise</returns>
private async Task<bool> CallSensorcoreApiAsync(Func<Task> action)
public async Task<bool> CallSensorcoreApiAsync(Func<Task> action)
{
Exception failure = null;
try
@ -475,9 +560,13 @@ namespace Places
this.Frame.Navigate(typeof(ActivateSensorCore));
}
return false;
case SenseError.GeneralFailure:
return false;
case SenseError.IncompatibleSDK:
MessageDialog dialog2 = new MessageDialog("This application has become outdated. Please update to the latest version.", "Information");
await dialog2.ShowAsync();
return false;
default:
MessageDialog dialog = new MessageDialog("Failure: " + SenseHelper.GetSenseError(failure.HResult) + " while initializing Motion data. Application will exit.", "");
await dialog.ShowAsync();
return false;
}
}
@ -505,5 +594,73 @@ namespace Places
FullScreeButton.Symbol = Symbol.FullScreen;
}
}
/// <summary>
/// Retrieves the places history
/// </summary>
/// <returns>String of all places history</returns>
private async Task<List<string>> GetPlacesHistory()
{
IList<string> resultStrFinal = new List<string>();
IList<Place> result = null;
if (_placeMonitor != null)
{
// Returns time ordered list of places visited during given time period
await CallSensorcoreApiAsync(async () =>
{
result = await _placeMonitor.GetPlaceHistoryAsync(DateTime.Today - TimeSpan.FromDays(10), TimeSpan.FromDays(10));
});
// Returns list of activies occured during given time period
await CallSensorcoreApiAsync(async () =>
{
ActivityReader.Instance().History = await ActivityReader.Instance().ActivityMonitorProperty.GetActivityHistoryAsync(DateTime.Today - TimeSpan.FromDays(10), TimeSpan.FromDays(10));
});
if (result != null)
{
IEnumerable<Place> reverse = result.AsEnumerable().Reverse();
for (int i = 1; i < reverse.Count(); i++)
{
activitiesToShow.Clear();
for (int j = 1; j < ActivityReader.Instance().History.Count; j++)
{
// Compare time of entry to the last location and the current location with the activity timestamp
// Retrieve the activities in a list
if ((ActivityReader.Instance().History.ElementAt(j).Timestamp.ToLocalTime() >= reverse.ElementAt(i - 1).Timestamp.ToLocalTime()) && (ActivityReader.Instance().History.ElementAt(j).Timestamp.ToLocalTime() < reverse.ElementAt(i).Timestamp.ToLocalTime()))
{
if (!activitiesToShow.Contains(ActivityReader.Instance().History.ElementAt(j).Mode))
{
//Add the activity to the list
activitiesToShow.Add(ActivityReader.Instance().History.ElementAt(j).Mode);
}
}
}
string time = reverse.ElementAt(i).Timestamp.ToString("MMM dd yyyy HH:mm:ss", CultureInfo.InvariantCulture);
var resultStr = "Place : " + reverse.ElementAt(i).Kind.ToString() + "\nTimestamp : " + time + "\nLenght Of Stay : " + reverse.ElementAt(i).LengthOfStay.ToString() + "\nTotal Lenght Of Stay : " + reverse.ElementAt(i).TotalLengthOfStay.ToString() + "\nTotal Visit Count : " + reverse.ElementAt(i).TotalVisitCount.ToString() + DisplayMembers(activitiesToShow);
resultStrFinal.Add(resultStr);
}
}
}
// Returns a list with details of the places history
return resultStrFinal.ToList();
}
/// <summary>
/// Display activities for given list
/// </summary>
/// <param name="activities">List of activities</param>
/// <returns>String item</returns>
public string DisplayMembers(List<Activity> activities)
{
string displayActivities = string.Empty;
if (activities.Count != 0)
{
displayActivities = "\nActivities: " + string.Join(", ", activities.ToList());
}
else
{
displayActivities = "\nActivities: Idle";
}
return displayActivities;
}
}
}

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -31,6 +32,10 @@ using Windows.UI.Xaml.Controls.Maps;
using Windows.UI.Xaml.Navigation;
using Lumia.Sense;
using Places.Common;
using System.Collections.Generic;
using Windows.Globalization;
using Places.Utilities;
using System.Threading;
/// <summary>
/// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkID=390556
@ -49,6 +54,11 @@ namespace Places
/// </summary>
private NavigationHelper _navigationHelper;
/// <summary>
/// Map Page instance
/// </summary>
public static MapPage _instanceMap;
/// <summary>
/// View model instance
/// This can be changed to a strongly typed view model
@ -64,6 +74,16 @@ namespace Places
/// Constructs a new ResourceLoader object
/// </summary>
private ResourceLoader _resourceLoader = new ResourceLoader();
/// <summary>
/// List with days for the filter option
/// </summary>
private readonly List<DaySelectionItem> _optionList = new List<DaySelectionItem>();
/// <summary>
/// Selected day for filter option
/// </summary>
private DaySelectionItem _selectedDay;
#endregion
/// <summary>
@ -72,10 +92,16 @@ namespace Places
public MapPage()
{
this.InitializeComponent();
if(_instanceMap == null)
_instanceMap = this;
this.menuFlyout = new MenuFlyout();
this._navigationHelper = new NavigationHelper(this);
this._navigationHelper.LoadState += this.NavigationHelper_LoadState;
this._navigationHelper.SaveState += this.NavigationHelper_SaveState;
PlacesMap.MapServiceToken = "xxx";
FillDateList();
this.listSource.Source = _optionList;
_selectedDay = _optionList.Last();
}
/// <summary>
@ -143,7 +169,20 @@ namespace Places
Application.Current.Exit();
}
}
InitCore();
PlacesMap.Center = new Geopoint(new BasicGeoposition()
{
Latitude = 60.17,
Longitude = 24.83
});
if (ActivityReader.Instance().ActivityMonitorProperty != null)
{
ActivityReader.Instance().ActivityMonitorProperty.ReadingChanged += ActivityReader.Instance().activityMonitor_ReadingChanged;
}
if (!iLaunched)
{
iLaunched = true;
await InitCore();
}
}
/// <summary>
@ -153,35 +192,95 @@ namespace Places
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
this._navigationHelper.OnNavigatedFrom(e);
}
/// <summary>
/// Navigates to details page for the selected place
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="args">Provides data about user input for the map tapped</param>
private void OnTapped(MapControl sender, MapInputEventArgs args)
if (ActivityReader.Instance().ActivityMonitorProperty != null)
{
try
{
var elementList = PlacesMap.FindMapElementsAtOffset(args.Position);
foreach (var element in elementList)
{
var mapIcon = element as MapIcon;
if (mapIcon != null)
{
this.Frame.Navigate(typeof(PivotPage), mapIcon);
break;
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
ActivityReader.Instance().ActivityMonitorProperty.ReadingChanged -= ActivityReader.Instance().activityMonitor_ReadingChanged;
}
}
#endregion
/// <summary>
/// Fill the list with current day of week, and in descending order rest of the weekdays
/// </summary>
private void FillDateList()
{
int today = (int)DateTime.Now.DayOfWeek; // Current day
int count = 0;
for (int i = today; i >= 0; i--)
{
var item = new DaySelectionItem { Day = DateTime.Now.Date - TimeSpan.FromDays(count) };
var nameOfDay = System.Globalization.DateTimeFormatInfo.CurrentInfo.DayNames[i];
// Add an indicator to current day
if (count == 0)
{
nameOfDay += " " + _resourceLoader.GetString("Today");
}
GeographicRegion userRegion = new GeographicRegion();
var userDateFormat = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("shortdate", new[] { userRegion.Code });
var dateDefault = userDateFormat.Format(item.Day);
item.Name = nameOfDay + " " + dateDefault;
_optionList.Add(item);
count++;
// First day of the week, but not all weekdays still listed,
// continue from the last weekday
if (i == 0 && count <= 6)
{
i = 7;
}
else if (count == 10) // All weekdays listed, exit the loop
{
i = 0;
}
}
// Add the option to show everything
_optionList.Add(new DaySelectionItem { Name = _resourceLoader.GetString("All") });
}
/// <summary>
/// Opens a menu flyout with options to choose from
/// </summary>
/// <param name="sender">The control that the action is for.</param>
/// <param name="args">Parameter that contains the event data.</param>
private void SelectButton_Click(object sender, RoutedEventArgs e)
{
if (menuFlyout != null)
{
menuFlyout.Items.Clear();
for (int i = 0; i < listSource.View.Count; i++)
{
flyoutItem = new MenuFlyoutItem();
flyoutItem.Text = this.listSource.View[i].ToString();
flyoutItem.FontSize = 22;
flyoutItem.FlowDirection = Windows.UI.Xaml.FlowDirection.LeftToRight;
flyoutItem.Click += flyoutItem_Click;
menuFlyout.Items.Add(flyoutItem);
}
menuFlyout.Items.Add(new MenuFlyoutItem());
menuFlyout.ShowAt(CmdBar);
}
}
/// <summary>
/// Draws the route for all the tracks in the selected day.
/// </summary>
/// <param name="sender">The control that the action is for.</param>
/// <param name="args">Parameter that contains the event data.</param>
private async void flyoutItem_Click(object sender, RoutedEventArgs e)
{
var flyoutItem = e.OriginalSource as MenuFlyoutItem;
try
{
for (int i = 0; i < listSource.View.Count; i++)
if (flyoutItem.Text.Contains(listSource.View[i].ToString()))
_selectedDay = (DaySelectionItem)listSource.View[i];
await UpdateKnownPlacesAsync();
FilterTime.Text = _selectedDay.Name;
}
catch (Exception)
{
}
}
/// <summary>
/// Display home on the map, if is recognised
/// </summary>
@ -197,7 +296,7 @@ namespace Places
if (place.Kind == PlaceKind.Home)
{
PlacesMap.Center = new Geopoint(place.Position);
PlacesMap.ZoomLevel = 16;
PlacesMap.ZoomLevel = 13;
foundPlace = true;
break;
}
@ -221,16 +320,19 @@ namespace Places
private async void OnWorkClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
bool foundPlace = false;
if (_app.Places != null)
{
foreach (Place place in _app.Places)
{
if (place.Kind == PlaceKind.Work)
{
PlacesMap.Center = new Geopoint(place.Position);
PlacesMap.ZoomLevel = 16;
PlacesMap.ZoomLevel = 13;
foundPlace = true;
break;
}
}
}
// It takes some time for SensorCore SDK to figure out your known locations
if (!foundPlace)
{
@ -246,10 +348,20 @@ namespace Places
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">Contains state information and event data associated with a routed event.</param>
private void OnCurrentClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
private async void OnCurrentClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
if (_currentLocation == null)
{
var text = _resourceLoader.GetString("CurrentNotFound") + " " + _resourceLoader.GetString("DontWorry/Text");
var header = _resourceLoader.GetString("LocationNotDefined");
var dialog = new MessageDialog(text, header);
await dialog.ShowAsync();
}
else
{
PlacesMap.Center = _currentLocation;
PlacesMap.ZoomLevel = 16;
PlacesMap.ZoomLevel = 13;
}
}
/// <summary>
@ -257,7 +369,9 @@ namespace Places
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">Contains state information and event data associated with a routed event.</param>
private void OnFrequentClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
private async void OnFrequentClicked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
if (_app.Places != null)
{
var notHomeNorWork =
from place in _app.Places
@ -266,6 +380,10 @@ namespace Places
select place;
if (notHomeNorWork.Count() == 0)
{
var text = _resourceLoader.GetString("FrequentNotFound") + " " + _resourceLoader.GetString("DontWorry/Text");
var header = _resourceLoader.GetString("LocationNotDefined");
var dialog = new MessageDialog(text, header);
await dialog.ShowAsync();
return;
}
_chosenFrequentId++;
@ -274,7 +392,38 @@ namespace Places
_chosenFrequentId = 0;
}
PlacesMap.Center = new Geopoint(notHomeNorWork.ElementAt(_chosenFrequentId).Position);
PlacesMap.ZoomLevel = 16;
PlacesMap.ZoomLevel = 13;
}
else
{
var text = _resourceLoader.GetString("FrequentNotFound") + " " + _resourceLoader.GetString("DontWorry/Text");
var header = _resourceLoader.GetString("LocationNotDefined");
var dialog = new MessageDialog(text, header);
await dialog.ShowAsync();
return;
}
}
/// <summary>
/// Get history button click event handler
/// </summary>
/// <param name="sender">Sender object</param>
/// <param name="e">Event arguments</param>
private async void OnPollHistory(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
// Fetch complete stack of places
if (resultStr.Count != 0)
{
// Pass list of places to HistoryPage
this.Frame.Navigate(typeof(HistoryPage), resultStr);
}
else
{
// Show message if no history data
MessageDialog dialog = new MessageDialog(_resourceLoader.GetString("NoHistoryData/Text"));
dialog.Commands.Add(new UICommand(_resourceLoader.GetString("OkButton/Text")));
await dialog.ShowAsync();
}
}
/// <summary>

Просмотреть файл

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
<Identity Name="NokiaDeveloper.PlacesLumiaSensorCoreSDKsample" Publisher="CN=4AD6DA08-6C39-4A10-98CC-3243374DA59C" Version="1.2.0.1" />
<Identity Name="NokiaDeveloper.PlacesLumiaSensorCoreSDKsample" Publisher="CN=4AD6DA08-6C39-4A10-98CC-3243374DA59C" Version="1.2.0.5" />
<mp:PhoneIdentity PhoneProductId="4a76e963-c4fa-4884-a385-3e12c6ea994d" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>Places – Lumia SensorCore SDK sample</DisplayName>

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -23,12 +24,11 @@ using System;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Maps;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Places.Common;
using Places.Utilities;
using Lumia.Sense;
using Windows.Devices.Geolocation;
/// <summary>
/// The Pivot Application template is documented at http://go.microsoft.com/fwlink/?LinkID=391641
@ -45,6 +45,11 @@ namespace Places
/// Navigation Helper instance
/// </summary>
private readonly NavigationHelper _navigationHelper;
/// <summary>
/// Address of a Geopoint location
/// </summary>
private string _addressString;
#endregion
/// <summary>
@ -56,7 +61,6 @@ namespace Places
this.NavigationCacheMode = NavigationCacheMode.Required;
this._navigationHelper = new NavigationHelper(this);
this._navigationHelper.LoadState += this.NavigationHelper_LoadState;
this._navigationHelper.SaveState += this.NavigationHelper_SaveState;
}
/// <summary>
@ -82,10 +86,11 @@ namespace Places
{
if (e.NavigationParameter != null)
{
var mapIcon = e.NavigationParameter as MapIcon;
var mapIcon = e.NavigationParameter.ToString();
if (mapIcon != null)
{
CreatePivotItem(MapExtensions.GetValue(mapIcon));
CreatePivotItem(mapIcon);
}
}
}
@ -94,18 +99,33 @@ namespace Places
/// Create a Pivot and PivotItem, and fill with place info
/// </summary>
/// <param name="place">Place instance</param>
private void CreatePivotItem(Place place)
private async void CreatePivotItem(string place)
{
// Get address of a Geopoint location
MainGrid.Children.Clear();
string[] split = place.Split(new Char[] { '\n', ',' });
Geopoint geoPoint = new Geopoint(new BasicGeoposition()
{
Latitude = Convert.ToDouble(split[1]),
Longitude = Convert.ToDouble(split[2])
});
var newPivot = new Pivot { Title = "MICROSOFT SENSORCORE SAMPLE", Margin = new Thickness(0, 12, 0, 0), Foreground = new SolidColorBrush(Colors.Black) };
var pivotItem = new PivotItem { Header = place.Kind.ToString(), Foreground = new SolidColorBrush(Colors.Black)};
var pivotItem = new PivotItem { Header = split[0].ToString(), Foreground = new SolidColorBrush(Colors.Black), FontSize = 20 };
var stackPanel = new StackPanel();
stackPanel.Children.Add(CreateTextBlock("Latitude:", place.Position.Latitude.ToString()));
stackPanel.Children.Add(CreateTextBlock("Longitude:", place.Position.Longitude.ToString()));
stackPanel.Children.Add(CreateTextBlock("Radius:", place.Radius.ToString() + " m"));
// Get address of a Geopoint location
var addressTask = GeoLocationHelper.GetAddress(geoPoint);
stackPanel.Children.Add(CreateTextBlock("Latitude:", split[1].ToString()));
stackPanel.Children.Add(CreateTextBlock("Longitude:", split[2].ToString()));
stackPanel.Children.Add(CreateTextBlock("Radius:", split[3].ToString() + " m"));
stackPanel.Children.Add(CreateTextBlock("Length of stay:", split[4].ToString()));
stackPanel.Children.Add(CreateTextBlock("Total length of stay:", split[5].ToString()));
stackPanel.Children.Add(CreateTextBlock("Total visit count:", split[6].ToString()));
pivotItem.Content = stackPanel;
newPivot.Items.Add(pivotItem);
MainGrid.Children.Add(newPivot);
_addressString = await addressTask;
//Add address to the pivot
stackPanel.Children.Add(CreateTextBlock("Address:", _addressString));
}
/// <summary>

Просмотреть файл

@ -74,6 +74,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="HistoryPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MapPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -82,6 +86,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="PushPin.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="AboutPage.xaml.cs">
@ -98,6 +106,9 @@
<Compile Include="Common\ObservableDictionary.cs" />
<Compile Include="Common\RelayCommand.cs" />
<Compile Include="Common\SuspensionManager.cs" />
<Compile Include="HistoryPage.xaml.cs">
<DependentUpon>HistoryPage.xaml</DependentUpon>
</Compile>
<Compile Include="MapPage.xaml.cs">
<DependentUpon>MapPage.xaml</DependentUpon>
</Compile>
@ -108,7 +119,14 @@
<DependentUpon>PivotPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PushPin.xaml.cs">
<DependentUpon>PushPin.xaml</DependentUpon>
</Compile>
<Compile Include="Utilities\ActivityReader.cs" />
<Compile Include="Utilities\DaySelectionItem.cs" />
<Compile Include="Utilities\GeoLocationHelper.cs" />
<Compile Include="Utilities\MapExtensions.cs" />
<Compile Include="Utilities\PlaceHistory.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
@ -127,8 +145,6 @@
<Content Include="Assets\StoreLogo.scale-240.png" />
<Content Include="Assets\WideLogo.scale-240.png" />
<Content Include="Common\ReadMe.txt" />
<None Include="Help\LumiaSensorCoreSDK.chm" />
<None Include="packages.config" />
<PRIResource Include="Strings\en-US\ActivateSensorCore.resw" />
</ItemGroup>
<ItemGroup>
@ -167,12 +183,6 @@
<Name>Microsoft Visual C++ 2013 Runtime Package for Windows Phone</Name>
</SDKReference>
</ItemGroup>
<ItemGroup>
<Reference Include="Lumia.Sense, Version=255.255.255.255, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\LumiaSensorCoreSDK.1.0.3.263\lib\portable-wpa81+wp81\x86\Lumia.Sense.winmd</HintPath>
</Reference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
<VisualStudioVersion>12.0</VisualStudioVersion>
</PropertyGroup>
@ -180,13 +190,4 @@
<TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\$(TargetPlatformVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<Import Project="..\packages\LumiaSensorCoreSDK.1.0.3.263\build\wpa81\LumiaSensorCoreSDK.targets" Condition="Exists('..\packages\LumiaSensorCoreSDK.1.0.3.263\build\wpa81\LumiaSensorCoreSDK.targets')" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

28
Places/PushPin.xaml Normal file
Просмотреть файл

@ -0,0 +1,28 @@
<UserControl
x:Class="Places.PushPin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Places"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Background="Transparent">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Border Background="#FF8330" CornerRadius="10" Height="65" Width="170" x:Name="imgborder" HorizontalAlignment="Center" >
<TextBlock x:Name="Lbltext" Tapped="PushPinTapped" VerticalAlignment="Center"
FontSize="20" Text="" TextWrapping="Wrap" Margin="5,5,5,5" >
</TextBlock>
</Border>
<Path Data="M0,0 L0,1 L1,0"
Fill="#FF8330"
Stretch="Fill"
Margin="32,0"
Height="12"
Width="18"
HorizontalAlignment="Left" x:Name="imgpath" />
</StackPanel>
</Grid>
</UserControl>

80
Places/PushPin.xaml.cs Normal file
Просмотреть файл

@ -0,0 +1,80 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Lumia.Sense;
using System.Globalization;
/// <summary>
/// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
/// </summary>
namespace Places
{
/// <summary>
/// class to display the popup(pushpin) on the map.
/// </summary>
public partial class PushPin : UserControl
{
/// <summary>
/// holds address of the place.
/// </summary>
private string _placeKind;
/// <summary>
/// Place Instance
/// </summary>
private Place _place ;
/// <summary>
/// constructor
/// </summary>
public PushPin(Place place, string placeKind)
{
InitializeComponent();
_place = place;
_placeKind = placeKind;
Loaded += PushPin_Loaded;
}
// <summary>
// page load event. sets the pushpin text.
// </summary>
// <param name="sender">event details</param>
// <param name="e">event sender</param>
void PushPin_Loaded( object sender, RoutedEventArgs e )
{
Lbltext.Text = "'" + _placeKind + "'" + " place";
}
/// <summary>
/// Tapped event on the pushpin to display details.
/// </summary>
/// <param name="sender">event details</param>
/// <param name="e">event sender</param>
private void PushPinTapped( object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e )
{
var frame = Window.Current.Content as Frame;
var resultStr = _place.Kind + "\n" + _place.Position.Latitude.ToString() + "\n"+_place.Position.Longitude.ToString() + "\n" +
_place.Radius.ToString() +"\n" + _place.LengthOfStay.ToString() + "\n" + _place.TotalLengthOfStay.ToString() + "\n" + _place.TotalVisitCount.ToString();
frame.Navigate(typeof(PivotPage),resultStr);
}
}
}

Просмотреть файл

@ -132,33 +132,66 @@
<data name="AddAppBarButton.Label" xml:space="preserve">
<value>add</value>
</data>
<data name="AdressNotFound" xml:space="preserve">
<value>A street address could not be found.</value>
</data>
<data name="All" xml:space="preserve">
<value>All</value>
</data>
<data name="Application.Text" xml:space="preserve">
<value>LUMIA SENSORCORE SAMPLE</value>
</data>
<data name="ApplicationName.Text" xml:space="preserve">
<value>Places</value>
</data>
<data name="CurrentNotFound" xml:space="preserve">
<value>The current location has not been resolved yet.</value>
</data>
<data name="DetailedSetting.DataCollectionQuality" xml:space="preserve">
<value>To get more accurate data you need to enable detailed data collection in Motion data settings. Do you want to open settings now?</value>
</data>
<data name="DontWorry.Text" xml:space="preserve">
<value>Don't worry, just give your phone some time to determine this location.</value>
</data>
<data name="FeatureDisabled.Title" xml:space="preserve">
<value>Information</value>
</data>
<data name="FilterButton.Label" xml:space="preserve">
<value>day filter</value>
</data>
<data name="FrequentNotFound" xml:space="preserve">
<value>Frequent place has not been recognised yet.</value>
</data>
<data name="Header.Text" xml:space="preserve">
<value>PLACES</value>
</data>
<data name="HideAppBarButton.Label" xml:space="preserve">
<value>hide</value>
</data>
<data name="HistoryButton.Label" xml:space="preserve">
<value>places history</value>
</data>
<data name="HistoryPage.Text" xml:space="preserve">
<value>places summary</value>
</data>
<data name="HomeNotFound" xml:space="preserve">
<value>The location of your home has not been figured out yet.</value>
</data>
<data name="Information.Text" xml:space="preserve">
<value>Information</value>
</data>
<data name="KnwonNotFound" xml:space="preserve">
<value>Known place has not been recognised yet.</value>
</data>
<data name="LocationNotDefined" xml:space="preserve">
<value>Location not defined</value>
</data>
<data name="NavigationFailedExceptionMessage" xml:space="preserve">
<value>Navigation failed.</value>
</data>
<data name="NoHistoryData.Text" xml:space="preserve">
<value>No places found</value>
</data>
<data name="NoLocationOrMotionDataError.Text" xml:space="preserve">
<value>This application does not function without location and motion data. The application will be closed.</value>
</data>
@ -171,6 +204,12 @@
<data name="Pivot.Title" xml:space="preserve">
<value>PLACES</value>
</data>
<data name="PlaceVisitedSetting" xml:space="preserve">
<value>In order to collect and view visited places you need to enable Places visited in Motion data settings. Do you want to open settings now?</value>
</data>
<data name="Today" xml:space="preserve">
<value>(Today)</value>
</data>
<data name="Version.Text" xml:space="preserve">
<value>version</value>
<comment>.</comment>

Просмотреть файл

@ -0,0 +1,402 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using Lumia.Sense;
using System.Threading.Tasks;
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
namespace Places.Utilities
{
/// <summary>
/// Data class for getting users activities
/// </summary>
public class ActivityReader : INotifyPropertyChanged
{
#region Private members
/// <summary>
/// List of activities and durations
/// </summary>
private List<MyQuantifiedData> _listData = null;
/// <summary>
/// Data instance
/// </summary>
private static ActivityReader _activityReader;
/// <summary>
/// List of history data
/// </summary
private IList<ActivityMonitorReading> _historyData;
/// <summary>
/// Activity monitor instance
/// </summary>
private IActivityMonitor _activityMonitor = null;
/// <summary>
/// Activity instance
/// </summary>
private Activity _activityMode = Activity.Idle;
/// <summary>
/// Time window index, 0 = today, -1 = yesterday
/// </summary>
private double _timeWindowIndex = 0;
#endregion
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// This method is called by the Set accessor of each property.
/// The CallerMemberName attribute that is applied to the optional propertyName
/// parameter causes the property name of the caller to be substituted as an argument.
/// </summary>
/// <param name="propertyName"></param>
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
/// <summary>
/// Constructor
/// </summary>
public ActivityReader()
{
_listData = new List<MyQuantifiedData>();
}
/// <summary>
/// Activity monitor property. Gets and sets the activity monitor
/// </summary>
public IActivityMonitor ActivityMonitorProperty
{
get
{
return _activityMonitor;
}
set
{
_activityMonitor = value;
}
}
/// <summary>
/// Create new instance of the class
/// </summary>
/// <returns>Data instance</returns>
static public ActivityReader Instance()
{
if (_activityReader == null)
_activityReader = new ActivityReader();
return _activityReader;
}
/// <summary>
/// Called when activity changes
/// </summary>
/// <param name="sender">Sender object</param>
/// <param name="args">Event arguments</param>
public async void activityMonitor_ReadingChanged(IActivityMonitor sender, ActivityMonitorReading args)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
this.ActivityEnum = args.Mode;
});
}
/// <summary>
/// Initializes activity monitor
/// </summary>
public async Task Initialize()
{
if (ActivityMonitorProperty == null)
{
if (await MapPage._instanceMap.CallSensorcoreApiAsync(async () => { ActivityMonitorProperty = await ActivityMonitor.GetDefaultAsync(); }))
{
Debug.WriteLine("ActivityMonitorSimulator initialized.");
}
if (ActivityMonitorProperty != null)
{
// Set activity observer
ActivityMonitorProperty.ReadingChanged += activityMonitor_ReadingChanged;
ActivityMonitorProperty.Enabled = true;
// read current activity
ActivityMonitorReading reading = null;
if (await MapPage._instanceMap.CallSensorcoreApiAsync(async () => { reading = await ActivityMonitorProperty.GetCurrentReadingAsync(); }))
{
if (reading != null)
{
this.ActivityEnum = reading.Mode;
}
}
}
else
{
// nothing to do if we cannot use the API
// in a real app do make an effort to make the user experience better
return;
}
// Must call DeactivateAsync() when the application goes to background
Window.Current.VisibilityChanged += async (sender, args) =>
{
if (_activityMonitor != null)
{
await MapPage._instanceMap.CallSensorcoreApiAsync(async () =>
{
if (!args.Visible)
{
await _activityMonitor.DeactivateAsync();
}
else
{
await _activityMonitor.ActivateAsync();
}
});
}
};
}
}
/// <summary>
/// Get the current activity
/// </summary>
public string CurrentActivity
{
get
{
return _activityMode.ToString().ToLower();
}
}
/// <summary>
/// Set the current activity
/// </summary>
public Activity ActivityEnum
{
set
{
_activityMode = value;
NotifyPropertyChanged("CurrentActivity");
}
}
/// <summary>
/// Get the time window
/// </summary>
public double TimeWindow
{
get
{
return _timeWindowIndex;
}
}
/// <summary>
/// Set the time window to today
/// </summary>
public void NextDay()
{
if (_timeWindowIndex < 0)
{
_timeWindowIndex++;
NotifyPropertyChanged("TimeWindow");
}
}
/// <summary>
/// Set the time window to previous day
/// </summary>
public void PreviousDay()
{
if (_timeWindowIndex >= -9)
{
_timeWindowIndex--;
NotifyPropertyChanged("TimeWindow");
}
}
/// <summary>
/// List of activities occured during given time period.
/// </summary>
public IList<ActivityMonitorReading> History
{
get
{
return _historyData;
}
set
{
if (_historyData == null)
{
_historyData = new List<ActivityMonitorReading>();
}
else
{
_historyData.Clear();
}
_historyData = value;
QuantifyData();
}
}
/// <summary>
/// Get the list of activities and durations
/// </summary>
public List<MyQuantifiedData> ListData
{
get
{
return _listData;
}
}
/// <summary>
/// Populate the list of activities and durations to display in the UI
/// </summary>
private void QuantifyData()
{
if (_listData != null)
{
_listData.Clear();
}
_listData = new List<MyQuantifiedData>();
if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
List<string> _activitiesList = new List<string>(Enum.GetNames(typeof(Activity)));
Dictionary<Activity, int> indexer = new Dictionary<Activity, int>();
TimeSpan[] _durations = new TimeSpan[_activitiesList.Count];
Activity[] values = (Activity[])Enum.GetValues(typeof(Activity));
for (int i = 0; i < values.Length; i++)
{
indexer.Add(values[i], i);
}
// there could be days with no data (e.g. of phone was turned off
if (_historyData.Count > 0)
{
// first entry may be from previous time window, is there any data from current time window?
bool hasDataInTimeWindow = false;
// insert new fist entry, representing the last activity of the previous time window
// this helps capture that activity's duration but only from the start of current time window
ActivityMonitorReading first = _historyData[0];
if (first.Timestamp <= DateTime.Now.Date.AddDays(_timeWindowIndex))
{
// create new "first" entry, with the same mode but timestamp set as 0:00h in current time window
_historyData.Insert(1, new ActivityMonitorReading(first.Mode, DateTime.Now.Date.AddDays(_timeWindowIndex)));
// remove previous entry
_historyData.RemoveAt(0);
hasDataInTimeWindow = _historyData.Count > 1;
}
else
{
// the first entry belongs to the current time window
// there is no known activity before it
hasDataInTimeWindow = true;
}
// if at least one activity is recorded in this time window
if (hasDataInTimeWindow)
{
// insert a last activity, marking the begining of the next time window
// this helps capturing the correct duration of the last activity stated in this time window
ActivityMonitorReading last = _historyData.Last();
if (last.Timestamp < DateTime.Now.Date.AddDays(_timeWindowIndex + 1))
{
// is this today's time window
if (_timeWindowIndex == 0)
{
// last activity duration measured until this instant time
_historyData.Add(new ActivityMonitorReading(last.Mode, DateTime.Now));
}
else
{
// last activity measured until the begining of the next time index
_historyData.Add(new ActivityMonitorReading(last.Mode, DateTime.Now.Date.AddDays(_timeWindowIndex + 1)));
}
}
// calculate duration for each current activity by subtracting its timestamp from that of the next one
for (int i = 0; i < _historyData.Count - 1; i++)
{
ActivityMonitorReading current = _historyData[i];
ActivityMonitorReading next = _historyData[i + 1];
_durations[indexer[current.Mode]] += next.Timestamp - current.Timestamp;
}
}
}
// populate the list to be displayed in the UI
for (int i = 0; i < _activitiesList.Count; i++)
{
_listData.Add(new MyQuantifiedData(_activitiesList[i], _durations[i]));
}
}
NotifyPropertyChanged("ListData");
}
}
/// <summary>
/// Helper class to create a list of activities and their timestamp
/// </summary>
public class MyQuantifiedData
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="s">Activity name</param>
/// <param name="i">Activity time</param>
public MyQuantifiedData(string s, TimeSpan i)
{
//split activity string by capital letter
ActivityName = System.Text.RegularExpressions.Regex.Replace(s, @"([A-Z])(?<=[a-z]\1|[A-Za-z]\1(?=[a-z]))", " $1");
ActivityTime = i;
}
/// <summary>
/// Activity name
/// </summary>
public string ActivityName
{
get;
set;
}
/// <summary>
/// Activity time
/// </summary>
public TimeSpan ActivityTime
{
get;
set;
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using System;
namespace Places.Utilities
{
/// <summary>
/// Helper class to select the days from a list
/// </summary>
public class DaySelectionItem
{
/// <summary>
/// Name of the selected day
/// </summary>
public string Name { get; set; }
/// <summary>
/// Selected day in DateTime format
/// </summary>
public DateTime Day { get; set; }
/// <summary>
/// Convert to string
/// </summary>
/// <returns>Name in string format</returns>
public override string ToString()
{
return Name;
}
}
}

Просмотреть файл

@ -0,0 +1,78 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Resources;
using Windows.Devices.Geolocation;
using Windows.Services.Maps;
namespace Places.Utilities
{
/// <summary>
/// Helper class to find a geopoint location
/// </summary>
public class GeoLocationHelper
{
/// <summary>
/// Find the address of a Geopoint location
/// </summary>
/// <param name="geopoint"></param>
/// <returns><c>address</c> upon success, <c>error message</c> otherwise</returns>
public static async Task<string> GetAddress(Geopoint geopoint)
{
var loader = new ResourceLoader();
// Find the address of the tapped location
MapLocationFinderResult result = await MapLocationFinder.FindLocationsAtAsync(geopoint);
// If successful then display the address.
if (result.Status == MapLocationFinderStatus.Success)
{
string displayAddress = null;
// Get the list of locations found by MapLocationFinder
if (result.Locations.Count > 0)
{
if (string.IsNullOrEmpty(result.Locations[0].Address.Street))
{
// If the address of a geographic loaction is empty or null, get only the town and region
var region = result.Locations[0].Address.Region != "" ? ", " + result.Locations[0].Address.Region : null;
displayAddress = result.Locations[0].Address.Town + region;
}
else
{
// Get the complete address of a geographic location
displayAddress = result.Locations[0].Address.StreetNumber + " " + result.Locations[0].Address.Street;
}
return displayAddress;
}
// Show message error if location is not found
else
{
var msg = loader.GetString("AdressNotFound");
return msg;
}
}
// Show message error if the query location is not successful
var error = loader.GetString("LocationNotDefined");
return error;
}
}
}

Просмотреть файл

@ -1,4 +1,5 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy

Просмотреть файл

@ -0,0 +1,40 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
namespace Places.Utilities
{
/// <summary>
/// Class to describe a place in history page
/// </summary>
public class PlaceHistory
{
/// <summary>
/// Informations about history place
/// </summary>
public string Text { get; set; }
/// <summary>
///Path Image
/// </summary>
public string ImagePath { get; set; }
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LumiaSensorCoreSDK" version="1.0.3.263" targetFramework="wpa81" />
</packages>

Просмотреть файл

@ -64,7 +64,7 @@ file the capabilities required for it to work:
3. Version history
--------------------------------------------------------------------------------
* Version 1.2.0.5: Updated to use latest Lumia SensorCore SDK 1.1 Preview
* Version 1.2.0.1: Some bug fixes made in this release.
* Version 1.2: Updated to use version 1.0 of Lumia SensorCore SDK, added support
for frequent places and few other minor updates.
@ -76,6 +76,7 @@ file the capabilities required for it to work:
| Project | Release | Download |
| ------- | --------| -------- |
| Places | v1.2.0.5 | [places-1.2.0.5.zip](https://github.com/Microsoft/places/archive/v1.2.0.5.zip) |
| Places | v1.2.0.1 | [places-1.2.0.1.zip](https://github.com/Microsoft/places/archive/v1.2.0.1.zip) |
| Places | v1.2 | [places-1.2.zip](https://github.com/Microsoft/places/archive/v1.2.zip) |
| Places | v1.0 | [places-1.0.zip](https://github.com/Microsoft/places/archive/v1.0.zip) |