386 lines
10 KiB
C#
386 lines
10 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Media.Imaging;
|
|
using Microsoft.Win32;
|
|
using TransportGame.MapViewer.Business;
|
|
using TransportGame.MapViewer.Storage;
|
|
using TransportGame.Model;
|
|
|
|
namespace TransportGame.MapViewer
|
|
{
|
|
/// <summary>
|
|
/// Interaction logic for MainWindow.xaml
|
|
/// </summary>
|
|
public partial class MainWindow : Window, INotifyPropertyChanged
|
|
{
|
|
private MapRenderer.Layers _layers = MapRenderer.Layers.All;
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
#region Public properties
|
|
|
|
#region Map property
|
|
|
|
private CityMap _map;
|
|
|
|
/// <summary>
|
|
/// Gets the map displayed by the map viewer.
|
|
/// </summary>
|
|
public CityMap Map
|
|
{
|
|
get
|
|
{
|
|
return _map;
|
|
}
|
|
private set
|
|
{
|
|
_map = value;
|
|
|
|
if (PropertyChanged != null)
|
|
PropertyChanged(this, new PropertyChangedEventArgs("Map"));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Loaded file property
|
|
|
|
private string _loadedFile;
|
|
|
|
/// <summary>
|
|
/// Gets the path of the currently loaded map file.
|
|
/// </summary>
|
|
public string LoadedFile
|
|
{
|
|
get
|
|
{
|
|
return _loadedFile;
|
|
}
|
|
|
|
private set
|
|
{
|
|
_loadedFile = value;
|
|
if (PropertyChanged != null)
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LoadedFile"));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Rendered map property
|
|
|
|
private BitmapSource _renderedMap;
|
|
|
|
/// <summary>
|
|
/// Gets the rendered map bitmap
|
|
/// </summary>
|
|
public BitmapSource RenderedMap
|
|
{
|
|
get
|
|
{
|
|
return _renderedMap;
|
|
}
|
|
|
|
private set
|
|
{
|
|
_renderedMap = value;
|
|
|
|
if (PropertyChanged != null)
|
|
PropertyChanged(this, new PropertyChangedEventArgs("RenderedMap"));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Gets the map renderer
|
|
/// </summary>
|
|
public MapRenderer Renderer { get; private set; }
|
|
|
|
#region Renderer layers
|
|
|
|
/// <summary>
|
|
/// Gets or sets all the layers
|
|
/// </summary>
|
|
public bool? LayersAll
|
|
{
|
|
get
|
|
{
|
|
if (LayerElevation && LayerPopulation && LayerRoadArticulations)
|
|
return true;
|
|
|
|
if (!LayerElevation && !LayerPopulation && !LayerRoadArticulations)
|
|
return false;
|
|
|
|
return null;
|
|
}
|
|
set
|
|
{
|
|
if (value.HasValue)
|
|
{
|
|
LayerElevation = value.Value;
|
|
LayerPopulation = value.Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the elevation layer flag
|
|
/// </summary>
|
|
public bool LayerElevation
|
|
{
|
|
get
|
|
{
|
|
return _layers.HasFlag(MapRenderer.Layers.Elevation);
|
|
}
|
|
set
|
|
{
|
|
if (value) _layers |= MapRenderer.Layers.Elevation;
|
|
else _layers &= ~MapRenderer.Layers.Elevation;
|
|
|
|
if (PropertyChanged != null)
|
|
{
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LayerElevation"));
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LayersAll"));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the population layer flag
|
|
/// </summary>
|
|
public bool LayerPopulation
|
|
{
|
|
get
|
|
{
|
|
return _layers.HasFlag(MapRenderer.Layers.Population);
|
|
}
|
|
set
|
|
{
|
|
if (value) _layers |= MapRenderer.Layers.Population;
|
|
else _layers &= ~MapRenderer.Layers.Population;
|
|
|
|
if (PropertyChanged != null)
|
|
{
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LayerPopulation"));
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LayersAll"));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the population layer flag
|
|
/// </summary>
|
|
public bool LayerRoadArticulations
|
|
{
|
|
get
|
|
{
|
|
return _layers.HasFlag(MapRenderer.Layers.RoadArticulations);
|
|
}
|
|
set
|
|
{
|
|
if (value) _layers |= MapRenderer.Layers.RoadArticulations;
|
|
else _layers &= ~MapRenderer.Layers.RoadArticulations;
|
|
|
|
if (PropertyChanged != null)
|
|
{
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LayerRoadArticulations"));
|
|
PropertyChanged(this, new PropertyChangedEventArgs("LayersAll"));
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Gets or sets the zoom level
|
|
/// </summary>
|
|
public float ZoomLevel
|
|
{
|
|
get
|
|
{
|
|
return Renderer.Scale * 100f;
|
|
}
|
|
set
|
|
{
|
|
Renderer.Scale = value / 100f;
|
|
if (PropertyChanged != null)
|
|
PropertyChanged(this, new PropertyChangedEventArgs("ZoomLevel"));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Initializes the main window
|
|
/// </summary>
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
|
|
Renderer = new MapRenderer();
|
|
LoadedFile = "N/A";
|
|
DataContext = this;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private async Task OpenMapFile(string filename)
|
|
{
|
|
await LoadMap(filename);
|
|
await RenderMap();
|
|
}
|
|
|
|
private async Task LoadMap(string filename)
|
|
{
|
|
progress.Visibility = System.Windows.Visibility.Visible;
|
|
progressText.Text = "Loading map...";
|
|
|
|
try
|
|
{
|
|
Map = await Task.Run(() => MapStorage.Read(filename));
|
|
LoadedFile = filename;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Error");
|
|
}
|
|
|
|
progress.Visibility = System.Windows.Visibility.Hidden;
|
|
}
|
|
|
|
private async Task RenderMap()
|
|
{
|
|
progress.Visibility = System.Windows.Visibility.Visible;
|
|
progressText.Text = "Rendering map...";
|
|
|
|
try
|
|
{
|
|
var renderResult = await Task.Run(() => Renderer.Render(Map, _layers));
|
|
RenderedMap = renderResult.ToBitmapSource();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Error");
|
|
}
|
|
|
|
progress.Visibility = System.Windows.Visibility.Hidden;
|
|
}
|
|
|
|
#region UI Event handlers
|
|
|
|
private async void buttonOpen_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Open dialog
|
|
string filename;
|
|
|
|
if (!ShowOpenMapDialog(out filename))
|
|
return;
|
|
|
|
// Load file and generate image
|
|
await OpenMapFile(filename);
|
|
}
|
|
|
|
private void buttonSave_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Show save dialog
|
|
string filename;
|
|
if (!ShowSaveMapDialog(out filename))
|
|
return;
|
|
|
|
// Save to filename
|
|
var encoder = new PngBitmapEncoder();
|
|
encoder.Frames.Add(BitmapFrame.Create(RenderedMap));
|
|
|
|
using (var writer = File.OpenWrite(filename))
|
|
{
|
|
encoder.Save(writer);
|
|
writer.Close();
|
|
}
|
|
}
|
|
|
|
private async void buttonZoomIn_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Zoom
|
|
ZoomLevel *= 2;
|
|
|
|
// Update IsEnabled
|
|
if (ZoomLevel >= 400)
|
|
buttonZoomIn.IsEnabled = false;
|
|
buttonZoomOut.IsEnabled = true;
|
|
|
|
// Render
|
|
if (Map != null)
|
|
await RenderMap();
|
|
}
|
|
|
|
private async void buttonZoomOut_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Zoom
|
|
ZoomLevel /=2;
|
|
|
|
// Update IsEnabled
|
|
if (ZoomLevel <= 10)
|
|
buttonZoomOut.IsEnabled = false;
|
|
buttonZoomIn.IsEnabled = true;
|
|
|
|
// Render
|
|
if (Map != null)
|
|
await RenderMap();
|
|
}
|
|
|
|
private async void buttonRender_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (Map != null)
|
|
await RenderMap();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helper static functions
|
|
|
|
private static bool ShowOpenMapDialog(out string filename)
|
|
{
|
|
OpenFileDialog dialog = new OpenFileDialog();
|
|
dialog.Filter = "Map files|*.map|All files|*.*";
|
|
dialog.Title = "Open map file";
|
|
|
|
bool? result = dialog.ShowDialog();
|
|
|
|
if (!result.HasValue || !result.Value)
|
|
{
|
|
filename = null;
|
|
return false;
|
|
}
|
|
|
|
filename = dialog.FileName;
|
|
return true;
|
|
}
|
|
|
|
private static bool ShowSaveMapDialog(out string filename)
|
|
{
|
|
SaveFileDialog dialog = new SaveFileDialog();
|
|
dialog.Filter = "PNG Files|*.png|All files|*.*";
|
|
dialog.Title = "Save rendered map image";
|
|
|
|
bool? result = dialog.ShowDialog();
|
|
|
|
if (!result.HasValue || !result.Value)
|
|
{
|
|
filename = null;
|
|
return false;
|
|
}
|
|
|
|
filename = dialog.FileName;
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|