/GPX.Firemap.Desktop/GPX.Firemap.Desktop.Add-ins/GraticuleCustomLayers.esriaddin/Helpers/LayoutMethods.cs
C# | 267 lines | 179 code | 21 blank | 67 comment | 40 complexity | 98be5b206513ac1108b9417deaad8024 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Collections;
- using System.Linq;
- using System.Text;
- using ESRI.ArcGIS.Carto;
- using ESRI.ArcGIS.Geometry;
- using ESRI.ArcGIS.Display;
- using ESRI.ArcGIS.esriSystem;
- using ESRI.ArcGIS.Framework;
-
- namespace GraticuleCustomLayers.esriaddin
- {
- /// <summary>
- /// Provides methods to manipulate ESRI layouts and layout elements
- /// </summary>
- public class LayoutMethods
- {
- private const string TitleElementName = "OSRA_Title";
-
- private const string SubTitleElementName = "OSRA_SubTitle";
-
- private const string TimeStampElementName = "OSRA_TimeStamp";
-
- private const string LegendFrameName = "OSRA_LegendFrame";
-
- private const string LegendName = "OSRA_Legend";
-
- /// <summary>
- /// Updates the title text on a layout. The first text element found on the layout
- /// named "OSRA_Title" is updated with the input text string.
- /// </summary>
- /// <param name="text">The title text.</param>
- /// <param name="layout">The layout.</param>
- public static void UpdateTitleText(string text, IPageLayout layout)
- {
- foreach (IElement element in GetLayoutElements(layout))
- {
- if (((element as ITextElement) != null) && ((IElementProperties)element).Name == TitleElementName)
- {
- ((ITextElement)element).Text = text;
- return;
- }
- }
- }
-
- /// <summary>
- /// Updates the sub title text on a layout. The first text element found on the layout
- /// named "OSRA_SubTitle" is updated with the input text string.
- /// </summary>
- /// <param name="text">The sub title text.</param>
- /// <param name="layout">The layout.</param>
- public static void UpdateSubTitleText(string text, IPageLayout layout)
- {
- foreach (IElement element in GetLayoutElements(layout))
- {
- if (((element as ITextElement) != null) && ((IElementProperties)element).Name == SubTitleElementName)
- {
- ((ITextElement)element).Text = text;
- return;
- }
- }
- }
-
- /// <summary>
- /// Updates the timestamp text on a layout. The first text element found on the layout
- /// named "OSRA_TimeStamp" is updated with the input text string.
- /// </summary>
- /// <param name="text">The text.</param>
- /// <param name="layout">The layout.</param>
- public static void UpdateTimeStampText(string text, IPageLayout layout)
- {
- foreach (IElement element in GetLayoutElements(layout))
- {
- if (((element as ITextElement) != null) && ((IElementProperties)element).Name == TimeStampElementName)
- {
- ((ITextElement)element).Text = text;
- return;
- }
- }
- }
-
- /// <summary>
- /// Finds the first rectangle element on the layout named "OSRA_LegendFrame" and fits the first legend on the layout
- /// named "OSRA_Legend" to its extent.
- /// </summary>
- /// <param name="layout">The layout.</param>
- public static void FitLegendToFrame(IPageLayout layout)
- {
- // try and find the legend and the frame
- IRectangleElement legendFrame = null;
- IMapSurroundFrame legendSurroundFrame = null;
- ILegend legend = null;
- foreach (IElement element in GetLayoutElements(layout))
- {
- if (((element as IRectangleElement) != null) && ((IElementProperties)element).Name == LegendFrameName)
- {
- legendFrame = ((IRectangleElement)element);
- }
- if (((element as IMapSurroundFrame) != null) && ((IElementProperties)element).Name == LegendName)
- {
- legendSurroundFrame = ((IMapSurroundFrame)element);
- legend = (ILegend)legendSurroundFrame.MapSurround;
- }
- }
-
- // If everything we need is found then try and fit the legend
- if (legendSurroundFrame != null && legend != null && legendFrame != null)
- {
- // Shrink the legend frame envelope slightly (so the legend is not flush with the frame)
- IEnvelope legendFrameEnvelope = ((IElement)legendFrame).Geometry.Envelope;
- legendFrameEnvelope.Expand(-0.25, -0.25, false);
-
- // Work out the extent of the current legend
- object data = null;
- IEnumElement enumElement = ((IGraphicsComposite)legendSurroundFrame).get_Graphics(((IActiveView)layout).ScreenDisplay, data);
- IEnvelope graphicsBounds = GetGraphicsBounds(enumElement, ((IActiveView)layout).ScreenDisplay);
-
- // Adjust depedning on size relative to the frame it will be fitted to
- if (graphicsBounds.Width > legendFrameEnvelope.Width)
- {
- double ratio = legendFrameEnvelope.Width / graphicsBounds.Width;
- graphicsBounds.Expand(ratio, ratio, true);
- if (graphicsBounds.Height > legendFrameEnvelope.Height)
- {
- ((IElement)legendSurroundFrame).Geometry = legendFrameEnvelope;
- System.Diagnostics.Debug.WriteLine("Legend: To wide, adjusted for width, still to high, fully fitted");
- }
- else
- {
- graphicsBounds.Offset(legendFrameEnvelope.XMin - graphicsBounds.XMin, legendFrameEnvelope.YMax - graphicsBounds.YMax);
- ((IElement)legendSurroundFrame).Geometry = graphicsBounds;
- System.Diagnostics.Debug.WriteLine("Legend: To wide, adjusted for width, not to high after adjustment");
- }
- }
- else if (graphicsBounds.Height > legendFrameEnvelope.Height)
- {
- ((IElement)legendSurroundFrame).Geometry = legendFrameEnvelope;
- System.Diagnostics.Debug.WriteLine("Legend: To high, not to wide, fully fitted");
- }
- else
- {
- double ratio = legendFrameEnvelope.Width / graphicsBounds.Width;
- graphicsBounds.Expand(ratio, 1, true);
- graphicsBounds.Offset(legendFrameEnvelope.XMin - graphicsBounds.XMin, legendFrameEnvelope.YMax - graphicsBounds.YMax);
- ((IElement)legendSurroundFrame).Geometry = graphicsBounds;
- System.Diagnostics.Debug.WriteLine("Legend: Not to wide, not to high, fitted in X only");
- }
- }
- }
-
- /// <summary>
- /// Gets the bounds (Query Bounds) of all the graphics held in the input element enumeration.
- /// The sub-elements of nested graphics (in graphic groups) are included in the calculation.
- /// </summary>
- /// <param name="enumElement">The enum element.</param>
- /// <param name="display">The display.</param>
- /// <returns>
- /// An IEnvelope holding the extent of the graphics, or an empty IEnvelope if no
- /// graphics or a nil extent are found.
- /// </returns>
- public static IEnvelope GetGraphicsBounds(IEnumElement enumElement, IDisplay display)
- {
- IEnvelope graphicBounds = new EnvelopeClass();
- IEnvelope graphicsBounds = new EnvelopeClass();
- enumElement.Reset();
- IElement element = enumElement.Next();
- while (element != null)
- {
- //foreach (IElement subElement in GetSubElements(element))
- //{
- //subElement.QueryBounds(display, graphicBounds);
- element.QueryBounds(display, graphicBounds);
- graphicsBounds.Union(graphicBounds);
-
- //}
- element = enumElement.Next();
- }
- return graphicsBounds;
- }
-
- /// <summary>
- /// Gets the set of map frames from a given page layout.
- /// </summary>
- /// <param name="layout">The layout.</param>
- /// <returns>IMapFrame array</returns>
- public static IMapFrame[] GetMapFrames(IPageLayout layout)
- {
- ArrayList list = new ArrayList();
-
- // First try and find the map frame in the graphics container of the layout
- foreach (IElement element in GetLayoutElements(layout))
- {
- IMapFrame frame = element as IMapFrame;
- if (frame != null)
- {
- list.Add(frame);
- }
- }
-
- return (IMapFrame[])list.ToArray(typeof(IMapFrame));
- }
-
- /// <summary>
- /// Returns an array of graphic elements for a given layout.
- /// This has to be used, rather than just enumerating through the IGraphicsContainer as
- /// testing has shown that sometimes (for example, when ArcMap is automated for
- /// unit testing) the IGraphicsContainer reports that it is empty - when in fact it is not.
- /// The IGraphicsContainerSelect does not seem to suffer from this problem.
- /// </summary>
- /// <value>The layout elements.</value>
- public static IElement[] GetLayoutElements(IPageLayout layout)
- {
- ArrayList list = new ArrayList();
-
- IGraphicsContainerSelect graphicsSelect = layout as IGraphicsContainerSelect;
- IEnumElement originalSelectionEnum = graphicsSelect.SelectedElements;
- graphicsSelect.SelectAllElements();
- IEnumElement allSelectionEnum = graphicsSelect.SelectedElements;
- allSelectionEnum.Reset();
- IElement selectionElement = allSelectionEnum.Next();
- while (selectionElement != null)
- {
- list.Add(selectionElement);
- selectionElement = allSelectionEnum.Next();
- }
- graphicsSelect.UnselectAllElements();
- graphicsSelect.SelectElements(originalSelectionEnum); //re-set the selection
-
- return (IElement[])list.ToArray(typeof(IElement));
- }
-
- /// <summary>
- /// Gets the sub elements of a graphic element. This method extracts the individual graphics
- /// elements from group elements (if they exist), including nested group elements.
- /// </summary>
- /// <param name="element">The element.</param>
- /// <returns>An array of elements (IElement).</returns>
- /// <remarks>If the input element is not a group element an array is returned holding
- /// the input element only.</remarks>
- public static IElement[] GetSubElements(IElement element)
- {
- ArrayList elementList = new ArrayList();
- if ((element as IGroupElement) != null)
- {
- IEnumElement enumElement = ((IGroupElement)element).Elements;
- enumElement.Reset();
- IElement subElement = enumElement.Next();
- while (subElement != null)
- {
- IElement[] internalElements = GetSubElements(subElement);
- foreach (IElement internalElement in internalElements)
- {
- elementList.Add(internalElement);
- }
- subElement = enumElement.Next();
- }
- return ((IElement[])elementList.ToArray(typeof(IElement)));
- }
- else
- {
- elementList.Add(element);
- return ((IElement[])elementList.ToArray(typeof(IElement)));
- }
- }
- }
- }