Files
2018-12-21 10:31:41 +03:00

195 lines
9.0 KiB
C#

namespace DevExpress.DevAV.Presenters {
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using DevExpress.DevAV;
using DevExpress.DevAV.ViewModels;
using DevExpress.XtraMap;
using DevExpress.XtraMap.Services;
public abstract class RouteMapPresenter<TEntity, TViewModel> : BasePresenter<TViewModel>
where TEntity : class
where TViewModel : class, IRouteMapViewModel {
MapControl mapControlCore;
Action<TEntity> updateUIActionCore;
Action<List<RoutePoint>> updateRouteListActionCore;
public RouteMapPresenter(MapControl mapControl, TViewModel viewModel, Action<TEntity> updateUIAction, Action<List<RoutePoint>> updateRouteList)
: base(viewModel) {
this.mapControlCore = mapControl;
this.updateUIActionCore = updateUIAction;
this.updateRouteListActionCore = updateRouteList;
if(MapControl != null) {
BindMap();
SubscribeRouteProviderEvents();
}
SubscribeViewModelEvents();
}
protected override void OnDisposing() {
if(MapControl != null)
UnsubscribeRouteProviderEvents();
UnsubscribeViewModelEvents();
this.updateUIActionCore = null;
this.updateRouteListActionCore = null;
this.mapControlCore = null;
base.OnDisposing();
}
public MapControl MapControl {
get { return mapControlCore; }
}
protected ImageLayer TilesLayer {
get { return (ImageLayer)(MapControl.Layers[0]); }
}
protected InformationLayer GeoCodeLayer {
get { return (InformationLayer)(MapControl.Layers[1]); }
}
protected InformationLayer RouteLayer {
get { return (InformationLayer)(MapControl.Layers[3]); }
}
protected BingMapDataProvider TilesProvider {
get { return (BingMapDataProvider)TilesLayer.DataProvider; }
}
protected BingGeocodeDataProvider GeoCodeProvider {
get { return (BingGeocodeDataProvider)GeoCodeLayer.DataProvider; }
}
protected BingRouteDataProvider RouteProvider {
get { return (BingRouteDataProvider)RouteLayer.DataProvider; }
}
IZoomToRegionService zoomService;
void BindMap() {
TilesProvider.BingKey = MapViewModelBase.WinBingKey;
RouteProvider.BingKey = MapViewModelBase.WinBingKey;
GeoCodeProvider.BingKey = MapViewModelBase.WinBingKey;
//
this.zoomService = ((IServiceProvider)MapControl).GetService(typeof(IZoomToRegionService)) as IZoomToRegionService;
}
protected virtual void SubscribeRouteProviderEvents() {
GeoCodeProvider.LocationInformationReceived += GeoCodeProvider_LocationInformationReceived;
RouteProvider.RouteCalculated += RouteProvider_RouteCalculated;
RouteProvider.LayerItemsGenerating += RouteProvider_LayerItemsGenerating;
}
protected virtual void SubscribeViewModelEvents() {
ViewModel.UpdateRoute += ViewModel_UpdateRoute;
ViewModel.PointAChanged += ViewModel_PointAChanged;
ViewModel.PointBChanged += ViewModel_PointBChanged;
ViewModel.TravelModeChanged += ViewModel_TravelModeChanged;
}
protected virtual void UnsubscribeRouteProviderEvents() {
GeoCodeProvider.LocationInformationReceived -= GeoCodeProvider_LocationInformationReceived;
RouteProvider.RouteCalculated -= RouteProvider_RouteCalculated;
RouteProvider.LayerItemsGenerating -= RouteProvider_LayerItemsGenerating;
}
protected virtual void UnsubscribeViewModelEvents() {
ViewModel.UpdateRoute -= ViewModel_UpdateRoute;
ViewModel.PointAChanged -= ViewModel_PointAChanged;
ViewModel.PointBChanged -= ViewModel_PointBChanged;
ViewModel.TravelModeChanged -= ViewModel_TravelModeChanged;
}
void ViewModel_UpdateRoute(object sender, EventArgs e) {
UpdateUI(GetViewModelEntity());
}
protected void ViewModel_EntityChanged(object sender, System.EventArgs e) {
UpdateUI(GetViewModelEntity());
}
protected abstract TEntity GetViewModelEntity();
void ViewModel_TravelModeChanged(object sender, System.EventArgs e) {
RouteProvider.RouteOptions.Mode = ViewModel.TravelMode;
UpdateRoute();
}
MapPushpin PointAPin { get; set; }
void ViewModel_PointAChanged(object sender, System.EventArgs e) {
if(PointAPin == null)
PointAPin = new MapPushpin() { Text = "A" };
PointAPin.Location = ViewModel.PointA.ToGeoPoint();
}
MapPushpin PointBPin { get; set; }
void ViewModel_PointBChanged(object sender, System.EventArgs e) {
if(PointBPin == null)
PointBPin = new MapPushpin() { Text = "B" };
PointBPin.Location = ViewModel.PointB.ToGeoPoint();
}
void RouteProvider_RouteCalculated(object sender, BingRouteCalculatedEventArgs e) {
if(e.Error != null || e.Cancelled || e.CalculationResult == null || e.CalculationResult.ResultCode != RequestResultCode.Success)
return;
ProcessRouteResult(e.CalculationResult.RouteResults[0]);
}
void GeoCodeProvider_LocationInformationReceived(object sender, LocationInformationReceivedEventArgs e) {
if(e.Error != null || e.Cancelled || e.Result == null || e.Result.ResultCode != RequestResultCode.Success)
return;
LocationInformation[] locations = e.Result.Locations;
if(locations.Length > 0) {
LocationInformation loc = locations[0];
ViewModel.PointB = new Address()
{
Line = loc.Address.FormattedAddress,
Latitude = loc.Location.Latitude,
Longitude = loc.Location.Longitude,
};
}
}
void RouteProvider_LayerItemsGenerating(object sender, LayerItemsGeneratingEventArgs args) {
var items = args.Items;
for(int i = 0; i < items.Length; i++) {
MapPushpin pushpin = items[i] as MapPushpin;
if(pushpin != null)
pushpin.Visible = false;
}
AddRoutePoints();
}
void AddRoutePoints() {
RouteLayer.Data.Items.Clear();
RouteLayer.Data.Items.Add(PointAPin);
RouteLayer.Data.Items.Add(PointBPin);
}
void ProcessRouteResult(BingRouteResult routeResult) {
ViewModel.RouteDistance = routeResult.Distance;
ViewModel.RouteTime = routeResult.Time;
List<RoutePoint> routePoints = new List<RoutePoint>();
foreach(BingRouteLeg leg in routeResult.Legs)
foreach(BingItineraryItem item in leg.Itinerary)
routePoints.Add(new RoutePoint(item));
UpdateRouteList(routePoints);
zoomService.ZoomTo(ViewModel.PointA, ViewModel.PointB);
}
void UpdateRouteList(List<RoutePoint> routePoints) {
if(updateRouteListActionCore != null)
updateRouteListActionCore(routePoints);
}
void UpdateRoute() {
List<RouteWaypoint> points = new List<RouteWaypoint>();
points.Add(new RouteWaypoint("Point A", ViewModel.PointA.ToGeoPoint()));
points.Add(new RouteWaypoint("Point B", ViewModel.PointB.ToGeoPoint()));
RouteProvider.CalculateRoute(points);
}
void UpdateUI(TEntity entity) {
if(entity == null) return;
if(updateUIActionCore != null)
updateUIActionCore(entity);
MapControl.CenterPoint = ViewModel.PointA.ToGeoPoint();
AddRoutePoints();
UpdateRoute();
}
}
public sealed class RoutePoint {
static Regex removeTagRegex = new Regex(@"<[^>]*>", RegexOptions.Compiled);
BingItineraryItem item;
public RoutePoint(BingItineraryItem item) {
this.item = item;
ManeuverInstruction = removeTagRegex.Replace(item.ManeuverInstruction, string.Empty);
double itemDistance = item.Distance;
Distance = (itemDistance > 0.9) ?
String.Format("{0:0} mi", Math.Ceiling(itemDistance)) :
String.Format("{0:0} ft", Math.Ceiling(itemDistance * 52.8) * 100);
}
public BingManeuverType Maneuver {
get { return item.Maneuver; }
}
public string ManeuverInstruction {
get;
private set;
}
public string Distance {
get;
private set;
}
}
}