PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/GPX.Firemap.Desktop/GPX.Firemap.Desktop.Add-ins/GraticuleCustomLayers.esriaddin/Helpers/LayoutMethods.cs

https://bitbucket.org/shope/dfu
C# | 267 lines | 179 code | 21 blank | 67 comment | 40 complexity | 98be5b206513ac1108b9417deaad8024 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections;
  4. using System.Linq;
  5. using System.Text;
  6. using ESRI.ArcGIS.Carto;
  7. using ESRI.ArcGIS.Geometry;
  8. using ESRI.ArcGIS.Display;
  9. using ESRI.ArcGIS.esriSystem;
  10. using ESRI.ArcGIS.Framework;
  11. namespace GraticuleCustomLayers.esriaddin
  12. {
  13. /// <summary>
  14. /// Provides methods to manipulate ESRI layouts and layout elements
  15. /// </summary>
  16. public class LayoutMethods
  17. {
  18. private const string TitleElementName = "OSRA_Title";
  19. private const string SubTitleElementName = "OSRA_SubTitle";
  20. private const string TimeStampElementName = "OSRA_TimeStamp";
  21. private const string LegendFrameName = "OSRA_LegendFrame";
  22. private const string LegendName = "OSRA_Legend";
  23. /// <summary>
  24. /// Updates the title text on a layout. The first text element found on the layout
  25. /// named "OSRA_Title" is updated with the input text string.
  26. /// </summary>
  27. /// <param name="text">The title text.</param>
  28. /// <param name="layout">The layout.</param>
  29. public static void UpdateTitleText(string text, IPageLayout layout)
  30. {
  31. foreach (IElement element in GetLayoutElements(layout))
  32. {
  33. if (((element as ITextElement) != null) && ((IElementProperties)element).Name == TitleElementName)
  34. {
  35. ((ITextElement)element).Text = text;
  36. return;
  37. }
  38. }
  39. }
  40. /// <summary>
  41. /// Updates the sub title text on a layout. The first text element found on the layout
  42. /// named "OSRA_SubTitle" is updated with the input text string.
  43. /// </summary>
  44. /// <param name="text">The sub title text.</param>
  45. /// <param name="layout">The layout.</param>
  46. public static void UpdateSubTitleText(string text, IPageLayout layout)
  47. {
  48. foreach (IElement element in GetLayoutElements(layout))
  49. {
  50. if (((element as ITextElement) != null) && ((IElementProperties)element).Name == SubTitleElementName)
  51. {
  52. ((ITextElement)element).Text = text;
  53. return;
  54. }
  55. }
  56. }
  57. /// <summary>
  58. /// Updates the timestamp text on a layout. The first text element found on the layout
  59. /// named "OSRA_TimeStamp" is updated with the input text string.
  60. /// </summary>
  61. /// <param name="text">The text.</param>
  62. /// <param name="layout">The layout.</param>
  63. public static void UpdateTimeStampText(string text, IPageLayout layout)
  64. {
  65. foreach (IElement element in GetLayoutElements(layout))
  66. {
  67. if (((element as ITextElement) != null) && ((IElementProperties)element).Name == TimeStampElementName)
  68. {
  69. ((ITextElement)element).Text = text;
  70. return;
  71. }
  72. }
  73. }
  74. /// <summary>
  75. /// Finds the first rectangle element on the layout named "OSRA_LegendFrame" and fits the first legend on the layout
  76. /// named "OSRA_Legend" to its extent.
  77. /// </summary>
  78. /// <param name="layout">The layout.</param>
  79. public static void FitLegendToFrame(IPageLayout layout)
  80. {
  81. // try and find the legend and the frame
  82. IRectangleElement legendFrame = null;
  83. IMapSurroundFrame legendSurroundFrame = null;
  84. ILegend legend = null;
  85. foreach (IElement element in GetLayoutElements(layout))
  86. {
  87. if (((element as IRectangleElement) != null) && ((IElementProperties)element).Name == LegendFrameName)
  88. {
  89. legendFrame = ((IRectangleElement)element);
  90. }
  91. if (((element as IMapSurroundFrame) != null) && ((IElementProperties)element).Name == LegendName)
  92. {
  93. legendSurroundFrame = ((IMapSurroundFrame)element);
  94. legend = (ILegend)legendSurroundFrame.MapSurround;
  95. }
  96. }
  97. // If everything we need is found then try and fit the legend
  98. if (legendSurroundFrame != null && legend != null && legendFrame != null)
  99. {
  100. // Shrink the legend frame envelope slightly (so the legend is not flush with the frame)
  101. IEnvelope legendFrameEnvelope = ((IElement)legendFrame).Geometry.Envelope;
  102. legendFrameEnvelope.Expand(-0.25, -0.25, false);
  103. // Work out the extent of the current legend
  104. object data = null;
  105. IEnumElement enumElement = ((IGraphicsComposite)legendSurroundFrame).get_Graphics(((IActiveView)layout).ScreenDisplay, data);
  106. IEnvelope graphicsBounds = GetGraphicsBounds(enumElement, ((IActiveView)layout).ScreenDisplay);
  107. // Adjust depedning on size relative to the frame it will be fitted to
  108. if (graphicsBounds.Width > legendFrameEnvelope.Width)
  109. {
  110. double ratio = legendFrameEnvelope.Width / graphicsBounds.Width;
  111. graphicsBounds.Expand(ratio, ratio, true);
  112. if (graphicsBounds.Height > legendFrameEnvelope.Height)
  113. {
  114. ((IElement)legendSurroundFrame).Geometry = legendFrameEnvelope;
  115. System.Diagnostics.Debug.WriteLine("Legend: To wide, adjusted for width, still to high, fully fitted");
  116. }
  117. else
  118. {
  119. graphicsBounds.Offset(legendFrameEnvelope.XMin - graphicsBounds.XMin, legendFrameEnvelope.YMax - graphicsBounds.YMax);
  120. ((IElement)legendSurroundFrame).Geometry = graphicsBounds;
  121. System.Diagnostics.Debug.WriteLine("Legend: To wide, adjusted for width, not to high after adjustment");
  122. }
  123. }
  124. else if (graphicsBounds.Height > legendFrameEnvelope.Height)
  125. {
  126. ((IElement)legendSurroundFrame).Geometry = legendFrameEnvelope;
  127. System.Diagnostics.Debug.WriteLine("Legend: To high, not to wide, fully fitted");
  128. }
  129. else
  130. {
  131. double ratio = legendFrameEnvelope.Width / graphicsBounds.Width;
  132. graphicsBounds.Expand(ratio, 1, true);
  133. graphicsBounds.Offset(legendFrameEnvelope.XMin - graphicsBounds.XMin, legendFrameEnvelope.YMax - graphicsBounds.YMax);
  134. ((IElement)legendSurroundFrame).Geometry = graphicsBounds;
  135. System.Diagnostics.Debug.WriteLine("Legend: Not to wide, not to high, fitted in X only");
  136. }
  137. }
  138. }
  139. /// <summary>
  140. /// Gets the bounds (Query Bounds) of all the graphics held in the input element enumeration.
  141. /// The sub-elements of nested graphics (in graphic groups) are included in the calculation.
  142. /// </summary>
  143. /// <param name="enumElement">The enum element.</param>
  144. /// <param name="display">The display.</param>
  145. /// <returns>
  146. /// An IEnvelope holding the extent of the graphics, or an empty IEnvelope if no
  147. /// graphics or a nil extent are found.
  148. /// </returns>
  149. public static IEnvelope GetGraphicsBounds(IEnumElement enumElement, IDisplay display)
  150. {
  151. IEnvelope graphicBounds = new EnvelopeClass();
  152. IEnvelope graphicsBounds = new EnvelopeClass();
  153. enumElement.Reset();
  154. IElement element = enumElement.Next();
  155. while (element != null)
  156. {
  157. //foreach (IElement subElement in GetSubElements(element))
  158. //{
  159. //subElement.QueryBounds(display, graphicBounds);
  160. element.QueryBounds(display, graphicBounds);
  161. graphicsBounds.Union(graphicBounds);
  162. //}
  163. element = enumElement.Next();
  164. }
  165. return graphicsBounds;
  166. }
  167. /// <summary>
  168. /// Gets the set of map frames from a given page layout.
  169. /// </summary>
  170. /// <param name="layout">The layout.</param>
  171. /// <returns>IMapFrame array</returns>
  172. public static IMapFrame[] GetMapFrames(IPageLayout layout)
  173. {
  174. ArrayList list = new ArrayList();
  175. // First try and find the map frame in the graphics container of the layout
  176. foreach (IElement element in GetLayoutElements(layout))
  177. {
  178. IMapFrame frame = element as IMapFrame;
  179. if (frame != null)
  180. {
  181. list.Add(frame);
  182. }
  183. }
  184. return (IMapFrame[])list.ToArray(typeof(IMapFrame));
  185. }
  186. /// <summary>
  187. /// Returns an array of graphic elements for a given layout.
  188. /// This has to be used, rather than just enumerating through the IGraphicsContainer as
  189. /// testing has shown that sometimes (for example, when ArcMap is automated for
  190. /// unit testing) the IGraphicsContainer reports that it is empty - when in fact it is not.
  191. /// The IGraphicsContainerSelect does not seem to suffer from this problem.
  192. /// </summary>
  193. /// <value>The layout elements.</value>
  194. public static IElement[] GetLayoutElements(IPageLayout layout)
  195. {
  196. ArrayList list = new ArrayList();
  197. IGraphicsContainerSelect graphicsSelect = layout as IGraphicsContainerSelect;
  198. IEnumElement originalSelectionEnum = graphicsSelect.SelectedElements;
  199. graphicsSelect.SelectAllElements();
  200. IEnumElement allSelectionEnum = graphicsSelect.SelectedElements;
  201. allSelectionEnum.Reset();
  202. IElement selectionElement = allSelectionEnum.Next();
  203. while (selectionElement != null)
  204. {
  205. list.Add(selectionElement);
  206. selectionElement = allSelectionEnum.Next();
  207. }
  208. graphicsSelect.UnselectAllElements();
  209. graphicsSelect.SelectElements(originalSelectionEnum); //re-set the selection
  210. return (IElement[])list.ToArray(typeof(IElement));
  211. }
  212. /// <summary>
  213. /// Gets the sub elements of a graphic element. This method extracts the individual graphics
  214. /// elements from group elements (if they exist), including nested group elements.
  215. /// </summary>
  216. /// <param name="element">The element.</param>
  217. /// <returns>An array of elements (IElement).</returns>
  218. /// <remarks>If the input element is not a group element an array is returned holding
  219. /// the input element only.</remarks>
  220. public static IElement[] GetSubElements(IElement element)
  221. {
  222. ArrayList elementList = new ArrayList();
  223. if ((element as IGroupElement) != null)
  224. {
  225. IEnumElement enumElement = ((IGroupElement)element).Elements;
  226. enumElement.Reset();
  227. IElement subElement = enumElement.Next();
  228. while (subElement != null)
  229. {
  230. IElement[] internalElements = GetSubElements(subElement);
  231. foreach (IElement internalElement in internalElements)
  232. {
  233. elementList.Add(internalElement);
  234. }
  235. subElement = enumElement.Next();
  236. }
  237. return ((IElement[])elementList.ToArray(typeof(IElement)));
  238. }
  239. else
  240. {
  241. elementList.Add(element);
  242. return ((IElement[])elementList.ToArray(typeof(IElement)));
  243. }
  244. }
  245. }
  246. }