using System; using System.Collections.Generic; using System.Text; namespace OSGeo.MapGuide.Viewer { /// <summary> /// Represents a temporary change in map state. Used primarily to set the current in-memory viewer map /// into a temporary different display state for rendering and plotting. /// /// Implements IDisposable semantics allowing for temporary map state to be explicity defined within a /// C# using block with auto-reversion /// </summary> public abstract class MgTransientMapState : IDisposable { private Stack<MgdMapStateTransition> _states; /// <summary> /// The original state /// </summary> protected MgMapDisplayParameters _origState; /// <summary> /// Constructor /// </summary> protected MgTransientMapState() { _states = new Stack<MgdMapStateTransition>(); } /// <summary> /// Gets the current display state /// </summary> /// <returns></returns> protected abstract MgMapDisplayParameters GetCurrentState(); /// <summary> /// Applies the view center /// </summary> /// <param name="x"></param> /// <param name="y"></param> protected abstract void ApplyViewCenter(double x, double y); /// <summary> /// Applies the view scale /// </summary> /// <param name="scale"></param> protected abstract void ApplyViewScale(double scale); /// <summary> /// Applies the display size /// </summary> /// <param name="width"></param> /// <param name="height"></param> protected abstract void ApplyDisplaySize(int width, int height); /// <summary> /// Applies the DPI /// </summary> /// <param name="dpi"></param> protected abstract void ApplyDPI(int dpi); private void ApplyState(MgMapDisplayParameters state) { ApplyViewCenter(state.X, state.Y); ApplyViewScale(state.Scale); ApplyDisplaySize(state.Width, state.Height); if (state.DPI.HasValue) ApplyDPI(state.DPI.Value); } /// <summary> /// Gets the size of temporary state transitions on the map state stack /// </summary> public int Depth { get { return _states.Count; } } /// <summary> /// Pushes the given state onto the map state stack. The map takes on the display parameters specified /// in this given state. /// </summary> /// <param name="state"></param> public void PushState(MgMapDisplayParameters state) { if (state == null) throw new ArgumentNullException("state"); //NOXLATE var oldState = GetCurrentState(); ApplyState(state); _states.Push(new MgdMapStateTransition() { OldState = oldState, NewState = state }); } /// <summary> /// Pops the latest state from the map state stack. The map state is restored to /// the previously applied state. /// </summary> /// <returns>The state that was previously applied</returns> public MgMapDisplayParameters PopState() { if (_states.Count == 0) return null; var trans = _states.Pop(); ApplyState(trans.OldState); return trans.NewState; } /// <summary> /// Reverts the map to the original display state /// </summary> public void Dispose() { while (_states.Count > 0) { this.PopState(); } ApplyState(_origState); } } /// <summary> /// Represents a temporary map display state /// </summary> /// <typeparam name="T"></typeparam> public abstract class MgTransientMapState<T> : MgTransientMapState where T : MgMapBase { /// <summary> /// The map instance /// </summary> protected T _map; /// <summary> /// Constructor /// </summary> /// <param name="map"></param> protected MgTransientMapState(T map) { _map = map; _origState = GetCurrentState(); } /// <summary> /// Gets the current display state /// </summary> /// <returns></returns> protected override MgMapDisplayParameters GetCurrentState() { var pt = _map.ViewCenter; var coord = pt.Coordinate; return new MgMapDisplayParameters(coord.X, coord.Y, _map.ViewScale, _map.DisplayWidth, _map.DisplayHeight, _map.DisplayDpi); } } internal class MgdMapStateTransition { public MgMapDisplayParameters NewState { get; set; } public MgMapDisplayParameters OldState { get; set; } } /// <summary> /// Represents display parameters for a map /// </summary> public class MgMapDisplayParameters { /// <summary> /// The view center X coordinate /// </summary> public double X { get; private set; } /// <summary> /// The view center Y coordinate /// </summary> public double Y { get; private set; } /// <summary> /// The view scale /// </summary> public double Scale { get; private set; } /// <summary> /// The display width /// </summary> public int Width { get; private set; } /// <summary> /// The display height /// </summary> public int Height { get; private set; } /// <summary> /// The display DPI /// </summary> public int? DPI { get; private set; } /// <summary> /// Constructor /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="scale"></param> /// <param name="width"></param> /// <param name="height"></param> public MgMapDisplayParameters(double x, double y, double scale, int width, int height) { this.X = x; this.Y = y; this.Scale = scale; this.Width = width; this.Height = height; } /// <summary> /// Constructor /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="scale"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="dpi"></param> public MgMapDisplayParameters(double x, double y, double scale, int width, int height, int dpi) : this(x, y, scale, width, height) { this.DPI = dpi; } } }