city-generation/Tools/MapViewer/MapViewer/MainWindow.xaml.cs

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
}
}