Mini Kabibi Habibi
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Media.Effects;
using DevExpress.Xpf.Map;
using System.Windows.Data;
using System;
using System.Globalization;
using System.Windows;
namespace MapDemo {
public enum RouteModelState {
Normal,
Drive
}
public class NavigatorDataModel : FrameworkElement, INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected void NotifyPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (PropertyChanged != null)
PropertyChanged(sender, e);
}
}
public class RouteModel : NavigatorDataModel {
public static readonly DependencyProperty MapCenterProperty = DependencyProperty.Register("MapCenter",
typeof(GeoPoint), typeof(RouteModel), new PropertyMetadata(new GeoPoint(34.158506,-118.255629)));
public static readonly DependencyProperty TimeScaleProperty = DependencyProperty.Register("TimeScale",
typeof(double), typeof(RouteModel), new PropertyMetadata(1.0));
Navigator navigator;
ObservableCollection<MapItem> helpers;
bool isCalculating;
RouteModelState state;
DriveModel driveModel;
List<RouteWaypoint> waypoints;
List<MapPushpin> routePushpins;
List<GeoPoint> routePath;
List<BingItineraryItem> itineraryItems;
int waypointIndex;
int searchPushpinsCount;
double drivePathDistance;
public ObservableCollection<MapItem> Helpers {
get { return this.helpers; }
}
public bool IsCalculating {
get { return this.isCalculating; }
set {
if (this.isCalculating != value) {
this.isCalculating = value;
NotifyPropertyChanged("IsCalculating");
}
}
}
public RouteModelState State {
get { return this.state; }
set {
if (this.state != value) {
this.state = value;
OnStateChanged();
NotifyPropertyChanged("State");
}
}
}
public DriveModel DriveModel {
get { return driveModel; }
set {
if (this.driveModel != value) {
this.driveModel = value;
NotifyPropertyChanged("DriveModel");
}
}
}
public Navigator Navigator {
get { return this.navigator; }
set {
if (this.navigator != value) {
this.navigator = value;
NotifyPropertyChanged("Controller");
}
}
}
public List<GeoPoint> RoutePath {
get { return routePath; }
}
public double DrivePathDistance {
get { return this.drivePathDistance; }
set { this.drivePathDistance = value; }
}
public List<BingItineraryItem> ItineraryItems {
get { return this.itineraryItems; }
set { this.itineraryItems = value; }
}
public List<MapPushpin> RoutePushpins {
get { return this.routePushpins; }
set { this.routePushpins = value; }
}
public string ActionText {
get {
if ((state == RouteModelState.Drive) && (driveModel != null)) {
return driveModel.ActionText;
}
else {
if (waypoints.Count == 0) {
if (searchPushpinsCount > 0)
return "Click the pushpin to set a start point.";
else
return "Click the map or use Search to find a location.";
}
else if (waypoints.Count == 1) {
return "Set a finish point to calculate a route.";
}
else {
return "Set another finish point or click Drive.";
}
}
}
}
public GeoPoint MapCenter {
get { return (GeoPoint)GetValue(MapCenterProperty); }
set { SetValue(MapCenterProperty, value); }
}
public double TimeScale {
get { return (double)GetValue(TimeScaleProperty); }
set { SetValue(TimeScaleProperty, value); }
}
public List<RouteWaypoint> Waypoints {
get { return this.waypoints; }
}
public RouteModel(Navigator navigator) {
this.navigator = navigator;
this.helpers = new ObservableCollection<MapItem>();
this.waypoints = new List<RouteWaypoint>();
this.routePushpins = new List<MapPushpin>();
this.itineraryItems = new List<BingItineraryItem>();
}
void SendRouteRequest() {
IsCalculating = true;
if (waypoints.Count > 1)
Navigator.RouteProvider.CalculateRoute(waypoints);
}
string NextWaypointLetter() {
string letter = "" + (char)((byte)'A' + waypointIndex % 26);
waypointIndex++;
return letter;
}
void ExtractItineraryItems(BingRouteResult result) {
itineraryItems.Clear();
foreach (BingRouteLeg leg in result.Legs)
foreach (BingItineraryItem item in leg.Itinerary)
itineraryItems.Add(item);
}
void BeginDrive() {
if ((routePath != null) && (routePath.Count > 1)) {
StopDrive();
DriveModel = new DriveModel(this);
Binding mapCenterBinding = new Binding("MapCenterBinding")
{
Path = new PropertyPath("CurrentLocation"),
Source = DriveModel
};
SetBinding(MapCenterProperty, mapCenterBinding);
}
}
void StopDrive() {
if (DriveModel != null) {
DriveModel.Cleanup();
DriveModel = null;
MapCenter = (GeoPoint)MapCenter;
}
}
void OnStateChanged() {
switch (State) {
case RouteModelState.Drive:
BeginDrive();
break;
case RouteModelState.Normal:
StopDrive();
break;
}
NotifyPropertyChanged("ActionText");
}
void CalculatePathDistance() {
drivePathDistance = 0;
if (routePath != null) {
MapUnit? lastPoint = null;
foreach (GeoPoint node in routePath) {
if (lastPoint != null) {
MapUnit currentPoint = Navigator.RouteLayer.GeoPointToMapUnit(node);
drivePathDistance += DriveModel.DistanceBetweenPoints(currentPoint, lastPoint.Value);
lastPoint = currentPoint;
}
else
lastPoint = Navigator.RouteLayer.GeoPointToMapUnit(node);
}
}
}
internal void NotifyDriveModelChanged() {
NotifyPropertyChanged("ActionText");
}
internal void NotifySearchPushpinsChanged(int count) {
searchPushpinsCount = count;
NotifyPropertyChanged("ActionText");
}
public void AddWaypoint(string description, GeoPoint location) {
RouteWaypoint waypoint = new RouteWaypoint(description, location);
if (!waypoints.Contains(waypoint)) {
MapPushpin pushpin = new MapPushpin();
pushpin.Location = location;
pushpin.Information = description;
pushpin.Text = NextWaypointLetter();
pushpin.TraceDepth = 0;
pushpin.State = MapPushpinState.Busy;
Helpers.Add(pushpin);
waypoints.Add(waypoint);
SendRouteRequest();
}
NotifyPropertyChanged("ActionText");
NotifyPropertyChanged("Waypoints");
}
public void ProcessRouteItems(MapItem[] items) {
waypointIndex = 0;
routePushpins.Clear();
foreach (MapItem item in items) {
MapPushpin pushpin = item as MapPushpin;
if (pushpin != null) {
pushpin.Text = NextWaypointLetter();
routePushpins.Add(pushpin);
}
MapPolyline polyline = item as MapPolyline;
if (polyline != null)
polyline.Effect = new DropShadowEffect() { Direction = -90, ShadowDepth = 1 };
}
Helpers.Clear();
}
public void ProcessRouteResult(BingRouteResult result) {
if (result != null) {
ExtractItineraryItems(result);
routePath = result.RoutePath;
}
else
routePath = null;
CalculatePathDistance();
}
public void Clear() {
if (RoutePath != null)
RoutePath.Clear();
Helpers.Clear();
RoutePushpins.Clear();
ItineraryItems.Clear();
DrivePathDistance = 0.0;
waypoints.Clear();
waypointIndex = 0;
NotifySearchPushpinsChanged(0);
NotifyPropertyChanged("Waypoints");
}
}
public class RouteModelStateToButtonTextConverter : IValueConverter {
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if ((value != null) && (value.GetType() == typeof(RouteModelState))) {
RouteModelState state = (RouteModelState)value;
switch (state) {
case RouteModelState.Drive:
return "Stop";
case RouteModelState.Normal:
return "Drive";
}
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
#endregion
}
public class RouteModelNormalStateToBoolConverter : IValueConverter {
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if ((value != null) && (value.GetType() == typeof(RouteModelState)))
return ((RouteModelState)value) == RouteModelState.Normal;
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
#endregion
}
public class WaypointsCountToDriveAbilityConverter : IValueConverter {
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if ((value != null) && (value.GetType() == typeof(int)))
return ((int)value) > 1;
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
#endregion
}
}