[mapguide-commits] r6945 - in branches/2.4/MgDev/Desktop: MapViewer MapViewerTest
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Tue Aug 21 06:16:50 PDT 2012
Author: jng
Date: 2012-08-21 06:16:50 -0700 (Tue, 21 Aug 2012)
New Revision: 6945
Added:
branches/2.4/MgDev/Desktop/MapViewer/MgLegendControlPresenter.cs
Modified:
branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj
branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs
branches/2.4/MgDev/Desktop/MapViewer/MgLegend.cs
branches/2.4/MgDev/Desktop/MapViewer/MgLegend.resx
branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs
branches/2.4/MgDev/Desktop/MapViewerTest/MapViewerTest.csproj.user
Log:
#2096: Move out most of the presentation logic into a separate class, thus paving the way to do the refactoring with minimal disruption
Modified: branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj 2012-08-21 11:07:49 UTC (rev 6944)
+++ branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj 2012-08-21 13:16:50 UTC (rev 6945)
@@ -29,8 +29,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
- <DefineConstants>
- </DefineConstants>
+ <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\OSGeo.MapGuide.Viewer.XML</DocumentationFile>
@@ -83,6 +82,7 @@
<Compile Include="IMapViewerComponent.cs" />
<Compile Include="IMapStatusBar.cs" />
<Compile Include="IPropertyPane.cs" />
+ <Compile Include="MgLegendControlPresenter.cs" />
<Compile Include="MgComponent.cs">
<SubType>Component</SubType>
</Compile>
Modified: branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs 2012-08-21 11:07:49 UTC (rev 6944)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs 2012-08-21 13:16:50 UTC (rev 6945)
@@ -138,7 +138,7 @@
if (e.PropertyName == "IsBusy")
{
var busy = this.Viewer.IsBusy;
- Trace.TraceInformation("Dispatching busy state event to " + _listeners.Count + " listeners");
+ //Trace.TraceInformation("Dispatching busy state event to " + _listeners.Count + " listeners");
if (this.DisableWhenMapIsLoading)
{
foreach (var l in _listeners)
Modified: branches/2.4/MgDev/Desktop/MapViewer/MgLegend.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLegend.cs 2012-08-21 11:07:49 UTC (rev 6944)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLegend.cs 2012-08-21 13:16:50 UTC (rev 6945)
@@ -13,10 +13,12 @@
namespace OSGeo.MapGuide.Viewer
{
+ using Legend.Model;
+
/// <summary>
/// A control that displays and controls visibility of layers in a runtime map
/// </summary>
- public partial class MgLegend : UserControl, IMapLegend
+ public partial class MgLegend : UserControl, IMapLegend, ILegendView
{
// TODO:
//
@@ -36,13 +38,9 @@
const string IMG_UNSELECT = "lc_unselect";
const string IMG_OTHER = "icon_etc";
- private MgResourceService _resSvc;
- private MgMapViewerProvider _provider;
- private MgMapBase _map;
+ // The thing that does all the heavy lifting and dirty work
+ private MgLegendControlPresenter _presenter;
- private Image _selectableIcon;
- private Image _unselectableIcon;
-
/// <summary>
/// Initializes a new instance of the <see cref="MgLegend"/> class.
/// </summary>
@@ -51,37 +49,12 @@
InitializeComponent();
}
- private Dictionary<string, bool> _initialLayerSelectabilityState = new Dictionary<string, bool>();
-
internal void Init(MgMapViewerProvider provider)
{
- _provider = provider;
- _map = _provider.GetMap();
- InitInitialSelectabilityStates();
- _resSvc = (MgResourceService)_provider.CreateService(MgServiceType.ResourceService);
- _selectableIcon = Properties.Resources.lc_select;
- _unselectableIcon = Properties.Resources.lc_unselect;
+ _presenter = new MgLegendControlPresenter(this, provider);
RefreshLegend();
}
- private void InitInitialSelectabilityStates()
- {
- if (_map != null)
- {
- _initialLayerSelectabilityState.Clear();
- var layers = _map.GetLayers();
- for (int i = 0; i < layers.GetCount(); i++)
- {
- var layer = layers.GetItem(i);
- _initialLayerSelectabilityState[layer.GetObjectId()] = layer.Selectable;
- }
- }
- }
-
- private Dictionary<string, MgLayerBase> _layers = new Dictionary<string, MgLayerBase>();
- private Dictionary<string, MgLayerGroup> _groups = new Dictionary<string, MgLayerGroup>();
- private Dictionary<string, string> _layerDefinitionContents = new Dictionary<string, string>();
-
/// <summary>
/// Refreshes this component
/// </summary>
@@ -90,167 +63,18 @@
if (_noUpdate)
return;
- if (_map == null)
+ if (_presenter == null)
return;
- //System.Diagnostics.Trace.TraceInformation("MgLegend.RefreshLegend()");
- var scale = _map.ViewScale;
- var groups = _map.GetLayerGroups();
- var layers = _map.GetLayers();
-
ResetTreeView();
-
- _layerDefinitionContents.Clear();
- _layers.Clear();
- _groups.Clear();
-
trvLegend.BeginUpdate();
try
{
- //Process groups first
- List<MgLayerGroup> remainingNodes = new List<MgLayerGroup>();
- for (int i = 0; i < groups.GetCount(); i++)
- {
- var group = groups.GetItem(i);
- _groups.Add(group.GetObjectId(), group);
- if (!group.GetDisplayInLegend())
- continue;
-
- //Add ones without parents first.
- if (group.Group != null)
- {
- remainingNodes.Add(group);
- }
- else
- {
- var node = CreateGroupNode(group);
- trvLegend.Nodes.Add(node);
- }
-
- while (remainingNodes.Count > 0)
- {
- List<MgLayerGroup> toRemove = new List<MgLayerGroup>();
- for (int j = 0; j < remainingNodes.Count; j++)
- {
- var parentId = remainingNodes[j].Group.GetObjectId();
- var nodes = trvLegend.Nodes.Find(parentId, false);
- if (nodes.Length == 1)
- {
- var node = CreateGroupNode(remainingNodes[j]);
- nodes[0].Nodes.Add(node);
- toRemove.Add(remainingNodes[j]);
- }
- }
- //Whittle down this list
- if (toRemove.Count > 0)
- {
- foreach (var g in toRemove)
- {
- remainingNodes.Remove(g);
- }
- }
- }
- }
-
- //Now process layers
- for (int i = 0; i < layers.GetCount(); i++)
- {
- var lyr = layers.GetItem(i);
- var ldfId = lyr.LayerDefinition;
-
- if (!_layerDefinitionContents.ContainsKey(ldfId.ToString()))
- {
- _layerDefinitionContents[ldfId.ToString()] = string.Empty;
- }
- }
-
- //Collect all resource contents in a batch
- MgStringCollection layerIds = new MgStringCollection();
- foreach (var lid in _layerDefinitionContents.Keys)
- {
- layerIds.Add(lid);
- }
-
- MgStringCollection layerContents = _resSvc.GetResourceContents(layerIds, null);
- for (int i = 0; i < layerIds.GetCount(); i++)
- {
- string lid = layerIds.GetItem(i);
- _layerDefinitionContents[lid] = layerContents.GetItem(i);
- }
-
- List<MgLayerBase> remainingLayers = new List<MgLayerBase>();
- for (int i = 0; i < layers.GetCount(); i++)
- {
- var layer = layers.GetItem(i);
- _layers.Add(layer.GetObjectId(), layer);
-
- bool display = layer.DisplayInLegend;
- bool visible = _provider.IsLayerPotentiallyVisibleAtScale(layer, false);
- if (!display)
- continue;
-
- if (!visible)
- continue;
-
- //Add ones without parents first.
- if (layer.Group != null)
- {
- remainingLayers.Add(layer);
- }
- else
- {
- var node = CreateLayerNode(layer);
- if (node != null)
- {
- trvLegend.Nodes.Add(node);
- if (layer.ExpandInLegend)
- node.Expand();
- }
- }
-
- while (remainingLayers.Count > 0)
- {
- List<MgLayerBase> toRemove = new List<MgLayerBase>();
- for (int j = 0; j < remainingLayers.Count; j++)
- {
- var parentId = remainingLayers[j].Group.GetObjectId();
- var nodes = trvLegend.Nodes.Find(parentId, false);
- if (nodes.Length == 1)
- {
- var node = CreateLayerNode(remainingLayers[j]);
- if (node != null)
- {
- nodes[0].Nodes.Add(node);
- if (remainingLayers[j].ExpandInLegend)
- node.Expand();
- }
- toRemove.Add(remainingLayers[j]);
- }
- }
- //Whittle down this list
- if (toRemove.Count > 0)
- {
- foreach (var g in toRemove)
- {
- remainingLayers.Remove(g);
- }
- }
- }
- }
-
- //Now expand any relevant groups
- for (int i = 0; i < groups.GetCount(); i++)
- {
- var group = groups.GetItem(i);
- if (group.ExpandInLegend)
- {
- var nodes = trvLegend.Nodes.Find(group.GetObjectId(), false);
- if (nodes.Length == 1)
- {
- nodes[0].Expand();
- }
- }
- }
+ var sw = new Stopwatch();
+ sw.Start();
+ trvLegend.Nodes.AddRange(_presenter.CreateNodes());
+ sw.Stop();
+ Trace.TraceInformation("RefreshLegend: Completed in {0}ms", sw.ElapsedMilliseconds);
}
finally
{
@@ -276,6 +100,11 @@
nodes.Clear();
}
+ void ILegendView.AddLegendIcon(string id, Image img)
+ {
+ imgLegend.Images.Add(id, img);
+ }
+
private void ResetTreeView()
{
ClearNodes(trvLegend.Nodes);
@@ -291,241 +120,6 @@
imgLegend.Images.Add(IMG_OTHER, Properties.Resources.icon_etc);
}
- private TreeNode CreateLayerNode(MgLayerBase layer)
- {
- var node = new TreeNode();
- node.Name = layer.GetObjectId();
- node.Text = layer.GetLegendLabel();
- node.Checked = layer.GetVisible();
- node.ContextMenuStrip = this.LayerContextMenu;
- var lt = layer.GetLayerType();
- var fsId = layer.GetFeatureSourceId();
-
- if (fsId.EndsWith("DrawingSource"))
- {
- node.SelectedImageKey = node.ImageKey = IMG_DWF;
- //If not in the dictionary, assume it is a dynamically added layer
- bool bInitiallySelectable = _initialLayerSelectabilityState.ContainsKey(layer.GetObjectId()) ? _initialLayerSelectabilityState[layer.GetObjectId()] : layer.Selectable;
- node.Tag = new LayerNodeMetadata(layer, bInitiallySelectable);
- node.ToolTipText = string.Format(Properties.Resources.DrawingLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId);
- }
- else
- {
- string layerData = null;
- var ldfId = layer.LayerDefinition;
- if (_layerDefinitionContents.ContainsKey(ldfId.ToString()))
- layerData = _layerDefinitionContents[ldfId.ToString()];
-
- if (layerData == null)
- return null;
-
- XmlDocument doc = new XmlDocument();
- doc.LoadXml(layerData);
- int type = 0;
- XmlNodeList scaleRanges = doc.GetElementsByTagName("VectorScaleRange");
- if (scaleRanges.Count == 0)
- {
- scaleRanges = doc.GetElementsByTagName("GridScaleRange");
- if (scaleRanges.Count == 0)
- {
- scaleRanges = doc.GetElementsByTagName("DrawingLayerDefinition");
- if (scaleRanges.Count == 0)
- return null;
- type = 2;
- }
- else
- type = 1;
- }
-
- String[] typeStyles = new String[] { "PointTypeStyle", "LineTypeStyle", "AreaTypeStyle", "CompositeTypeStyle" };
- String[] ruleNames = new String[] { "PointRule", "LineRule", "AreaRule", "CompositeRule" };
-
- try
- {
- MgByteReader layerIcon = _provider.GenerateLegendImage(layer.LayerDefinition,
- _map.ViewScale,
- 16,
- 16,
- "PNG",
- -1,
- -1);
- if (layerIcon != null)
- {
- try
- {
- byte[] b = new byte[layerIcon.GetLength()];
- layerIcon.Read(b, b.Length);
- using (var ms = new MemoryStream(b))
- {
- string id = Guid.NewGuid().ToString();
- Image img = Image.FromStream(ms);
-
- imgLegend.Images.Add(id, img);
- node.SelectedImageKey = node.ImageKey = id;
- //If not in the dictionary, assume it is a dynamically added layer
- bool bInitiallySelectable = _initialLayerSelectabilityState.ContainsKey(layer.GetObjectId()) ? _initialLayerSelectabilityState[layer.GetObjectId()] : layer.Selectable;
- node.Tag = new LayerNodeMetadata(layer, bInitiallySelectable)
- {
- ThemeIcon = img
- };
- node.ToolTipText = string.Format(Properties.Resources.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName);
- }
- }
- finally
- {
- layerIcon.Dispose();
- }
- }
- else
- {
- node.SelectedImageKey = node.ImageKey = IMG_BROKEN;
- }
- }
- catch
- {
- node.SelectedImageKey = node.ImageKey = IMG_BROKEN;
- }
-
- for (int sc = 0; sc < scaleRanges.Count; sc++)
- {
- XmlElement scaleRange = (XmlElement)scaleRanges[sc];
- XmlNodeList minElt = scaleRange.GetElementsByTagName("MinScale");
- XmlNodeList maxElt = scaleRange.GetElementsByTagName("MaxScale");
- String minScale, maxScale;
- minScale = "0";
- maxScale = "1000000000000.0"; // as MDF's VectorScaleRange::MAX_MAP_SCALE
- if (minElt.Count > 0)
- minScale = minElt[0].ChildNodes[0].Value;
- if (maxElt.Count > 0)
- maxScale = maxElt[0].ChildNodes[0].Value;
-
- if (type != 0)
- break;
-
- for (int geomType = 0; geomType < typeStyles.Length; geomType++)
- {
- int catIndex = 0;
- XmlNodeList typeStyle = scaleRange.GetElementsByTagName(typeStyles[geomType]);
- for (int st = 0; st < typeStyle.Count; st++)
- {
- // We will check if this typestyle is going to be shown in the legend
- XmlNodeList showInLegend = ((XmlElement)typeStyle[st]).GetElementsByTagName("ShowInLegend");
- if (showInLegend.Count > 0)
- if (!bool.Parse(showInLegend[0].ChildNodes[0].Value))
- continue; // This typestyle does not need to be shown in the legend
-
- XmlNodeList rules = ((XmlElement)typeStyle[st]).GetElementsByTagName(ruleNames[geomType]);
- if (rules.Count > 1)
- {
- node.SelectedImageKey = node.ImageKey = IMG_THEME;
- var layerMeta = node.Tag as LayerNodeMetadata;
- if (layerMeta != null)
- {
- layerMeta.ThemeIcon = Properties.Resources.lc_theme;
- node.ToolTipText = string.Format(Properties.Resources.ThemedLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName, rules.Count);
- }
- if (this.ThemeCompressionLimit > 0 && rules.Count > this.ThemeCompressionLimit)
- {
- AddThemeRuleNode(layer, node, geomType, 0, rules, 0);
- node.Nodes.Add(CreateCompressedThemeNode(rules.Count - 2));
- AddThemeRuleNode(layer, node, geomType, rules.Count - 1, rules, rules.Count - 1);
- }
- else
- {
- for (int r = 0; r < rules.Count; r++)
- {
- AddThemeRuleNode(layer, node, geomType, catIndex++, rules, r);
- }
- }
- }
- }
- }
- }
- }
-
- return node;
- }
-
- private void AddThemeRuleNode(MgLayerBase layer, TreeNode node, int geomType, int catIndex, XmlNodeList rules, int r)
- {
- XmlElement rule = (XmlElement)rules[r];
- XmlNodeList label = rule.GetElementsByTagName("LegendLabel");
- XmlNodeList filter = rule.GetElementsByTagName("Filter");
-
- String labelText = "";
- if (label != null && label.Count > 0 && label[0].ChildNodes.Count > 0)
- labelText = label[0].ChildNodes[0].Value;
- //String filterText = "";
- //if (filter != null && filter.Count > 0 && filter[0].ChildNodes.Count > 0)
- // filterText = filter[0].ChildNodes[0].Value;
-
- var child = CreateThemeRuleNode(layer.LayerDefinition, _map.ViewScale, labelText, (geomType + 1), catIndex);
- node.Nodes.Add(child);
- }
-
- private TreeNode CreateCompressedThemeNode(int count)
- {
- TreeNode node = new TreeNode();
- node.Text = (count + " other styles");
- node.ImageKey = node.SelectedImageKey = IMG_OTHER;
- node.Tag = new LayerNodeMetadata(null, false) {
- IsBaseLayer = false,
- ThemeIcon = Properties.Resources.icon_etc,
- IsThemeRule = true
- };
- return node;
- }
-
- private TreeNode CreateThemeRuleNode(MgResourceIdentifier layerDefId, double viewScale, string labelText, int geomType, int categoryIndex)
- {
- MgByteReader icon = _provider.GenerateLegendImage(layerDefId,
- viewScale,
- 16,
- 16,
- "PNG",
- geomType,
- categoryIndex);
- TreeNode node = new TreeNode();
- node.Text = labelText;
- if (icon != null)
- {
- try
- {
-
- byte[] b = new byte[icon.GetLength()];
- icon.Read(b, b.Length);
- var tag = new LayerNodeMetadata(null, false)
- {
- IsBaseLayer = false,
- IsThemeRule = true
- };
- using (var ms = new MemoryStream(b))
- {
- string id = Guid.NewGuid().ToString();
- tag.ThemeIcon = Image.FromStream(ms);
- }
- node.Tag = tag;
- }
- finally
- {
- icon.Dispose();
- }
- }
- return node;
- }
-
- private TreeNode CreateGroupNode(MgLayerGroup group)
- {
- var node = new TreeNode();
- node.Name = group.GetObjectId();
- node.Text = group.GetLegendLabel();
- node.Checked = group.IsVisible();
- node.SelectedImageKey = node.ImageKey = IMG_GROUP;
- node.Tag = new GroupNodeMetadata(group);
- node.ContextMenuStrip = this.GroupContextMenu;
- return node;
- }
-
private double _scale;
/// <summary>
@@ -538,63 +132,8 @@
RefreshLegend();
}
- class LegendNodeMetadata
- {
- public bool IsGroup { get; protected set; }
- }
+
- class GroupNodeMetadata : LegendNodeMetadata
- {
- internal MgLayerGroup Group { get; set; }
-
- public GroupNodeMetadata(MgLayerGroup group)
- {
- base.IsGroup = true;
- this.Group = group;
- }
- }
-
- class LayerNodeMetadata : LegendNodeMetadata
- {
- public LayerNodeMetadata(MgLayerBase layer, bool bInitiallySelectable)
- {
- base.IsGroup = false;
- this.Layer = layer;
- this.IsSelectable = (layer != null) ? layer.Selectable : false;
- this.DrawSelectabilityIcon = (layer != null && bInitiallySelectable);
- this.IsThemeRule = false;
- }
-
- internal MgLayerBase Layer { get; set; }
-
- public bool DrawSelectabilityIcon { get; set; }
-
- public bool IsSelectable { get; set; }
-
- public bool IsThemeRule { get; set; }
-
- public bool IsBaseLayer { get; set; }
-
- public Image ThemeIcon { get; set; }
- }
-
- private bool HasVisibleParent(MgLayerGroup grp)
- {
- var current = grp.Group;
- if (current != null)
- return current.IsVisible();
- return true;
- }
-
- private bool HasVisibleParent(MgLayerBase layer)
- {
- var current = layer.Group;
- if (current != null)
- return current.IsVisible();
-
- return true;
- }
-
private void trvLegend_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Node.Tag == null)
@@ -602,28 +141,12 @@
if (((LegendNodeMetadata)e.Node.Tag).IsGroup) //Group
{
- if (_groups.ContainsKey(e.Node.Name))
- {
- var grp = _groups[e.Node.Name];
- grp.SetVisible(e.Node.Checked);
- var bVis = HasVisibleParent(grp);
- if (bVis)
- OnRequestRefresh();
- }
+ _presenter.SetGroupVisible(e.Node.Name, e.Node.Checked);
}
else //Layer
{
- if (_layers.ContainsKey(e.Node.Name))
- {
- var layer = _layers[e.Node.Name];
- layer.SetVisible(e.Node.Checked);
- var bVis = HasVisibleParent(layer);
- if (bVis)
- {
- layer.ForceRefresh();
- OnRequestRefresh();
- }
- }
+
+ _presenter.SetLayerVisible(e.Node.Name, e.Node.Checked);
}
}
@@ -634,18 +157,11 @@
if (((LegendNodeMetadata)e.Node.Tag).IsGroup) //Group
{
- if (_groups.ContainsKey(e.Node.Name))
- {
- _provider.SetGroupExpandInLegend(_groups[e.Node.Name], true);
- }
+ _presenter.SetGroupExpandInLegend(e.Node.Name, true);
}
else //Layer
{
- if (_layers.ContainsKey(e.Node.Name))
- {
- var layer = _layers[e.Node.Name];
- _provider.SetLayerExpandInLegend(layer, true);
- }
+ _presenter.SetLayerExpandInLegend(e.Node.Name, true);
}
}
@@ -656,24 +172,17 @@
if (((LegendNodeMetadata)e.Node.Tag).IsGroup) //Group
{
- if (_groups.ContainsKey(e.Node.Name))
- {
- _provider.SetGroupExpandInLegend(_groups[e.Node.Name], false);
- }
+ _presenter.SetGroupExpandInLegend(e.Node.Name, false);
}
else //Layer
{
- if (_layers.ContainsKey(e.Node.Name))
- {
- var layer = _layers[e.Node.Name];
- _provider.SetLayerExpandInLegend(layer, false);
- }
+ _presenter.SetLayerExpandInLegend(e.Node.Name, false);
}
}
private bool _noUpdate = false;
- private void OnRequestRefresh()
+ void ILegendView.OnRequestRefresh()
{
var handler = this.VisibilityChanged;
if (handler != null)
@@ -687,152 +196,11 @@
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public event EventHandler VisibilityChanged;
- private static bool IsThemeLayerNode(TreeNode node)
- {
- var meta = node.Tag as LayerNodeMetadata;
- if (meta != null)
- return meta.ThemeIcon != null || meta.IsBaseLayer;
+
- return false;
- }
-
- private static bool IsLayerNode(TreeNode node)
- {
- var meta = node.Tag as LayerNodeMetadata;
- return meta != null;
- }
-
private void trvLegend_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
- if (IsLayerNode(e.Node) && !e.Bounds.IsEmpty)
- {
- Color backColor, foreColor;
-
- //For some reason, the default bounds are way off from what you would
- //expect it to be. So we apply this offset for any text/image draw operations
- int xoffset = -36;
- if (trvLegend.ShowPlusMinus && e.Node.Nodes.Count > 0)
- {
- // Use the VisualStyles renderer to use the proper OS-defined glyphs
- Rectangle glyphRect = new Rectangle(e.Node.Bounds.X - 52, e.Node.Bounds.Y, 16, 16);
- if (Application.RenderWithVisualStyles)
- {
- VisualStyleElement element = (e.Node.IsExpanded) ?
- VisualStyleElement.TreeView.Glyph.Opened : VisualStyleElement.TreeView.Glyph.Closed;
-
- VisualStyleRenderer renderer = new VisualStyleRenderer(element);
- renderer.DrawBackground(e.Graphics, glyphRect);
- }
- else //Visual Styles disabled, fallback to drawing the +/- using geometric primitives
- {
- int h = 8;
- int w = 8;
- int x = glyphRect.X;
- int y = glyphRect.Y + (glyphRect.Height / 2) - 4;
-
- //Draw the -
- e.Graphics.DrawRectangle(new Pen(SystemBrushes.ControlDark), x, y, w, h);
- e.Graphics.FillRectangle(new SolidBrush(Color.White), x + 1, y + 1, w - 1, h - 1);
- e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Black)), x + 2, y + 4, x + w - 2, y + 4);
-
- //Draw the |
- if (!e.Node.IsExpanded)
- e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Black)), x + 4, y + 2, x + 4, y + h - 2);
- }
- }
-
- if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
- {
- backColor = SystemColors.Highlight;
- foreColor = SystemColors.HighlightText;
- }
- else if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
- {
- backColor = SystemColors.HotTrack;
- foreColor = SystemColors.HighlightText;
- }
- else
- {
- backColor = e.Node.BackColor;
- foreColor = e.Node.ForeColor;
- }
-
- var tag = e.Node.Tag as LayerNodeMetadata;
- var checkBoxOffset = xoffset;
- var selectabilityOffset = xoffset + 16;
- var iconOffsetNoSelect = xoffset + 16;
- if (tag != null && tag.IsThemeRule) //No checkbox for theme rule nodes
- {
- selectabilityOffset = xoffset;
- iconOffsetNoSelect = xoffset;
- }
- var iconOffset = selectabilityOffset + 20;
- var textOffset = iconOffset + 20;
- var textOffsetNoSelect = iconOffsetNoSelect + 20;
-
- //Uncomment if you need to "see" the bounds of the node
- //e.Graphics.DrawRectangle(Pens.Black, e.Node.Bounds);
-
- if (tag != null && !tag.IsThemeRule) //No checkbox for theme rule nodes
- {
- if (Application.RenderWithVisualStyles)
- {
- CheckBoxRenderer.DrawCheckBox(
- e.Graphics,
- new Point(e.Node.Bounds.X + checkBoxOffset, e.Node.Bounds.Y),
- e.Node.Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal);
- }
- else
- {
- //We don't have to do this, but with Visual Styles disabled, there is a noticeable jarring visual difference from DrawDefault'd checkboxes
- //So we might as well emulate that style for the sake of consistency
- var rect = new Rectangle(e.Node.Bounds.X + checkBoxOffset, e.Node.Bounds.Y, 16, 16);
- ControlPaint.DrawCheckBox(e.Graphics, rect, e.Node.Checked ? ButtonState.Checked | ButtonState.Flat : ButtonState.Flat);
- rect.Inflate(-2, -2);
- e.Graphics.DrawRectangle(new Pen(Brushes.Black, 2.0f), rect);
- }
- }
- if (tag != null)
- {
- if (tag.DrawSelectabilityIcon)
- {
- var icon = tag.IsSelectable ? _selectableIcon : _unselectableIcon;
- e.Graphics.DrawImage(icon, e.Node.Bounds.X + selectabilityOffset, e.Node.Bounds.Y);
- Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
- }
- if (tag.ThemeIcon != null)
- {
- if (tag.DrawSelectabilityIcon)
- {
- e.Graphics.DrawImage(tag.ThemeIcon, e.Node.Bounds.X + iconOffset, e.Node.Bounds.Y);
- Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
- }
- else
- {
- e.Graphics.DrawImage(tag.ThemeIcon, e.Node.Bounds.X + iconOffsetNoSelect, e.Node.Bounds.Y);
- Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
- }
- }
-
- using (SolidBrush brush = new SolidBrush(Color.Black))
- {
- e.Graphics.DrawString(e.Node.Text, trvLegend.Font, brush, e.Node.Bounds.X + (tag.DrawSelectabilityIcon ? textOffset : textOffsetNoSelect), e.Node.Bounds.Y);
- }
- }
- else
- {
- using (SolidBrush brush = new SolidBrush(Color.Black))
- {
- e.Graphics.DrawString(e.Node.Text, trvLegend.Font, brush, e.Node.Bounds.X + 17.0f + xoffset, e.Node.Bounds.Y);
- }
- }
-
- e.DrawDefault = false;
- }
- else
- {
- e.DrawDefault = true;
- }
+ _presenter.DrawNode(e, trvLegend.ShowPlusMinus, trvLegend.Font);
}
private ContextMenuStrip _grpContextMenu;
@@ -938,7 +306,7 @@
/// <returns></returns>
public MgLayerBase GetSelectedLayer()
{
- if (_map == null)
+ if (_presenter == null)
return null;
if (trvLegend.SelectedNode == null)
@@ -957,7 +325,7 @@
/// <returns></returns>
public MgLayerGroup GetSelectedGroup()
{
- if (_map == null)
+ if (_presenter == null)
return null;
if (trvLegend.SelectedNode == null)
Modified: branches/2.4/MgDev/Desktop/MapViewer/MgLegend.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLegend.resx 2012-08-21 11:07:49 UTC (rev 6944)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLegend.resx 2012-08-21 13:16:50 UTC (rev 6945)
@@ -120,4 +120,7 @@
<metadata name="imgLegend.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
+ <metadata name="legendUpdateWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>130, 17</value>
+ </metadata>
</root>
\ No newline at end of file
Added: branches/2.4/MgDev/Desktop/MapViewer/MgLegendControlPresenter.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLegendControlPresenter.cs (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLegendControlPresenter.cs 2012-08-21 13:16:50 UTC (rev 6945)
@@ -0,0 +1,718 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Windows.Forms.VisualStyles;
+
+namespace OSGeo.MapGuide.Viewer
+{
+ using Legend.Model;
+ using System.Xml;
+ using System.IO;
+
+ interface ILegendView
+ {
+ ContextMenuStrip LayerContextMenu { get; }
+ ContextMenuStrip GroupContextMenu { get; }
+ void AddLegendIcon(string id, Image icon);
+ int ThemeCompressionLimit { get; }
+ void OnRequestRefresh();
+ }
+
+ class MgLegendControlPresenter
+ {
+ const string IMG_BROKEN = "lc_broken";
+ const string IMG_DWF = "lc_dwf";
+ const string IMG_GROUP = "lc_group";
+ const string IMG_RASTER = "lc_raster";
+ const string IMG_SELECT = "lc_select";
+ const string IMG_THEME = "lc_theme";
+ const string IMG_UNSELECT = "lc_unselect";
+ const string IMG_OTHER = "icon_etc";
+
+ private MgResourceService _resSvc;
+ private MgMapViewerProvider _provider;
+ private MgMapBase _map;
+
+ private Image _selectableIcon;
+ private Image _unselectableIcon;
+
+ private ILegendView _legend;
+
+ //TODO: Coalesce this all into a single object. ie. Merge into the respective metadata classes.
+ private Dictionary<string, bool> _initialLayerSelectabilityState = new Dictionary<string, bool>();
+ private Dictionary<string, MgLayerBase> _layers = new Dictionary<string, MgLayerBase>();
+ private Dictionary<string, MgLayerGroup> _groups = new Dictionary<string, MgLayerGroup>();
+ private Dictionary<string, string> _layerDefinitionContents = new Dictionary<string, string>();
+
+ public MgLegendControlPresenter(ILegendView legend, MgMapViewerProvider provider)
+ {
+ _legend = legend;
+ _provider = provider;
+ _map = _provider.GetMap();
+ InitInitialSelectabilityStates();
+ _resSvc = (MgResourceService)_provider.CreateService(MgServiceType.ResourceService);
+ _selectableIcon = Properties.Resources.lc_select;
+ _unselectableIcon = Properties.Resources.lc_unselect;
+ }
+
+ private void InitInitialSelectabilityStates()
+ {
+ if (_map != null)
+ {
+ _initialLayerSelectabilityState.Clear();
+ var layers = _map.GetLayers();
+ for (int i = 0; i < layers.GetCount(); i++)
+ {
+ var layer = layers.GetItem(i);
+ _initialLayerSelectabilityState[layer.GetObjectId()] = layer.Selectable;
+ }
+ }
+ }
+
+ private bool HasVisibleParent(MgLayerGroup grp)
+ {
+ var current = grp.Group;
+ if (current != null)
+ return current.IsVisible();
+ return true;
+ }
+
+ private bool HasVisibleParent(MgLayerBase layer)
+ {
+ var current = layer.Group;
+ if (current != null)
+ return current.IsVisible();
+
+ return true;
+ }
+
+ private TreeNode CreateLayerNode(MgLayerBase layer)
+ {
+ var node = new TreeNode();
+ node.Name = layer.GetObjectId();
+ node.Text = layer.GetLegendLabel();
+ node.Checked = layer.GetVisible();
+ node.ContextMenuStrip = _legend.LayerContextMenu;
+ var lt = layer.GetLayerType();
+ var fsId = layer.GetFeatureSourceId();
+
+ if (fsId.EndsWith("DrawingSource"))
+ {
+ node.SelectedImageKey = node.ImageKey = IMG_DWF;
+ //If not in the dictionary, assume it is a dynamically added layer
+ bool bInitiallySelectable = _initialLayerSelectabilityState.ContainsKey(layer.GetObjectId()) ? _initialLayerSelectabilityState[layer.GetObjectId()] : layer.Selectable;
+ node.Tag = new LayerNodeMetadata(layer, bInitiallySelectable);
+ node.ToolTipText = string.Format(Properties.Resources.DrawingLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId);
+ }
+ else
+ {
+ string layerData = null;
+ var ldfId = layer.LayerDefinition;
+ if (_layerDefinitionContents.ContainsKey(ldfId.ToString()))
+ layerData = _layerDefinitionContents[ldfId.ToString()];
+
+ if (layerData == null)
+ return null;
+
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(layerData);
+ int type = 0;
+ XmlNodeList scaleRanges = doc.GetElementsByTagName("VectorScaleRange");
+ if (scaleRanges.Count == 0)
+ {
+ scaleRanges = doc.GetElementsByTagName("GridScaleRange");
+ if (scaleRanges.Count == 0)
+ {
+ scaleRanges = doc.GetElementsByTagName("DrawingLayerDefinition");
+ if (scaleRanges.Count == 0)
+ return null;
+ type = 2;
+ }
+ else
+ type = 1;
+ }
+
+ String[] typeStyles = new String[] { "PointTypeStyle", "LineTypeStyle", "AreaTypeStyle", "CompositeTypeStyle" };
+ String[] ruleNames = new String[] { "PointRule", "LineRule", "AreaRule", "CompositeRule" };
+
+ try
+ {
+ MgByteReader layerIcon = _provider.GenerateLegendImage(layer.LayerDefinition,
+ _map.ViewScale,
+ 16,
+ 16,
+ "PNG",
+ -1,
+ -1);
+ if (layerIcon != null)
+ {
+ try
+ {
+ byte[] b = new byte[layerIcon.GetLength()];
+ layerIcon.Read(b, b.Length);
+ using (var ms = new MemoryStream(b))
+ {
+ string id = Guid.NewGuid().ToString();
+ Image img = Image.FromStream(ms);
+
+ _legend.AddLegendIcon(id, img);
+ node.SelectedImageKey = node.ImageKey = id;
+ //If not in the dictionary, assume it is a dynamically added layer
+ bool bInitiallySelectable = _initialLayerSelectabilityState.ContainsKey(layer.GetObjectId()) ? _initialLayerSelectabilityState[layer.GetObjectId()] : layer.Selectable;
+ node.Tag = new LayerNodeMetadata(layer, bInitiallySelectable)
+ {
+ ThemeIcon = img
+ };
+ node.ToolTipText = string.Format(Properties.Resources.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName);
+ }
+ }
+ finally
+ {
+ layerIcon.Dispose();
+ }
+ }
+ else
+ {
+ node.SelectedImageKey = node.ImageKey = IMG_BROKEN;
+ }
+ }
+ catch
+ {
+ node.SelectedImageKey = node.ImageKey = IMG_BROKEN;
+ }
+
+ for (int sc = 0; sc < scaleRanges.Count; sc++)
+ {
+ XmlElement scaleRange = (XmlElement)scaleRanges[sc];
+ XmlNodeList minElt = scaleRange.GetElementsByTagName("MinScale");
+ XmlNodeList maxElt = scaleRange.GetElementsByTagName("MaxScale");
+ String minScale, maxScale;
+ minScale = "0";
+ maxScale = "1000000000000.0"; // as MDF's VectorScaleRange::MAX_MAP_SCALE
+ if (minElt.Count > 0)
+ minScale = minElt[0].ChildNodes[0].Value;
+ if (maxElt.Count > 0)
+ maxScale = maxElt[0].ChildNodes[0].Value;
+
+ if (type != 0)
+ break;
+
+ for (int geomType = 0; geomType < typeStyles.Length; geomType++)
+ {
+ int catIndex = 0;
+ XmlNodeList typeStyle = scaleRange.GetElementsByTagName(typeStyles[geomType]);
+ for (int st = 0; st < typeStyle.Count; st++)
+ {
+ // We will check if this typestyle is going to be shown in the legend
+ XmlNodeList showInLegend = ((XmlElement)typeStyle[st]).GetElementsByTagName("ShowInLegend");
+ if (showInLegend.Count > 0)
+ if (!bool.Parse(showInLegend[0].ChildNodes[0].Value))
+ continue; // This typestyle does not need to be shown in the legend
+
+ XmlNodeList rules = ((XmlElement)typeStyle[st]).GetElementsByTagName(ruleNames[geomType]);
+ if (rules.Count > 1)
+ {
+ node.SelectedImageKey = node.ImageKey = IMG_THEME;
+ var layerMeta = node.Tag as LayerNodeMetadata;
+ if (layerMeta != null)
+ {
+ layerMeta.ThemeIcon = Properties.Resources.lc_theme;
+ node.ToolTipText = string.Format(Properties.Resources.ThemedLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName, rules.Count);
+ }
+ if (_legend.ThemeCompressionLimit > 0 && rules.Count > _legend.ThemeCompressionLimit)
+ {
+ AddThemeRuleNode(layer, node, geomType, 0, rules, 0);
+ node.Nodes.Add(CreateCompressedThemeNode(rules.Count - 2));
+ AddThemeRuleNode(layer, node, geomType, rules.Count - 1, rules, rules.Count - 1);
+ }
+ else
+ {
+ for (int r = 0; r < rules.Count; r++)
+ {
+ AddThemeRuleNode(layer, node, geomType, catIndex++, rules, r);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return node;
+ }
+
+ private void AddThemeRuleNode(MgLayerBase layer, TreeNode node, int geomType, int catIndex, XmlNodeList rules, int r)
+ {
+ XmlElement rule = (XmlElement)rules[r];
+ XmlNodeList label = rule.GetElementsByTagName("LegendLabel");
+ XmlNodeList filter = rule.GetElementsByTagName("Filter");
+
+ String labelText = "";
+ if (label != null && label.Count > 0 && label[0].ChildNodes.Count > 0)
+ labelText = label[0].ChildNodes[0].Value;
+ //String filterText = "";
+ //if (filter != null && filter.Count > 0 && filter[0].ChildNodes.Count > 0)
+ // filterText = filter[0].ChildNodes[0].Value;
+
+ var child = CreateThemeRuleNode(layer.LayerDefinition, _map.ViewScale, labelText, (geomType + 1), catIndex);
+ node.Nodes.Add(child);
+ }
+
+ private TreeNode CreateCompressedThemeNode(int count)
+ {
+ TreeNode node = new TreeNode();
+ node.Text = (count + " other styles");
+ node.ImageKey = node.SelectedImageKey = IMG_OTHER;
+ node.Tag = new LayerNodeMetadata(null, false)
+ {
+ IsBaseLayer = false,
+ ThemeIcon = Properties.Resources.icon_etc,
+ IsThemeRule = true
+ };
+ return node;
+ }
+
+ private TreeNode CreateThemeRuleNode(MgResourceIdentifier layerDefId, double viewScale, string labelText, int geomType, int categoryIndex)
+ {
+ MgByteReader icon = _provider.GenerateLegendImage(layerDefId,
+ viewScale,
+ 16,
+ 16,
+ "PNG",
+ geomType,
+ categoryIndex);
+ TreeNode node = new TreeNode();
+ node.Text = labelText;
+ if (icon != null)
+ {
+ try
+ {
+
+ byte[] b = new byte[icon.GetLength()];
+ icon.Read(b, b.Length);
+ var tag = new LayerNodeMetadata(null, false)
+ {
+ IsBaseLayer = false,
+ IsThemeRule = true
+ };
+ using (var ms = new MemoryStream(b))
+ {
+ string id = Guid.NewGuid().ToString();
+ tag.ThemeIcon = Image.FromStream(ms);
+ }
+ node.Tag = tag;
+ }
+ finally
+ {
+ icon.Dispose();
+ }
+ }
+ return node;
+ }
+
+ private TreeNode CreateGroupNode(MgLayerGroup group)
+ {
+ var node = new TreeNode();
+ node.Name = group.GetObjectId();
+ node.Text = group.GetLegendLabel();
+ node.Checked = group.IsVisible();
+ node.SelectedImageKey = node.ImageKey = IMG_GROUP;
+ node.Tag = new GroupNodeMetadata(group);
+ node.ContextMenuStrip = _legend.GroupContextMenu;
+ return node;
+ }
+
+ public TreeNode[] CreateNodes()
+ {
+ List<TreeNode> output = new List<TreeNode>();
+ var nodesById = new Dictionary<string, TreeNode>();
+
+ var scale = _map.ViewScale;
+ var groups = _map.GetLayerGroups();
+ var layers = _map.GetLayers();
+
+ _layerDefinitionContents.Clear();
+ _layers.Clear();
+ _groups.Clear();
+
+ //Process groups first
+ List<MgLayerGroup> remainingNodes = new List<MgLayerGroup>();
+ for (int i = 0; i < groups.GetCount(); i++)
+ {
+ var group = groups.GetItem(i);
+ _groups.Add(group.GetObjectId(), group);
+ if (!group.GetDisplayInLegend())
+ continue;
+
+ //Add ones without parents first.
+ if (group.Group != null)
+ {
+ remainingNodes.Add(group);
+ }
+ else
+ {
+ var node = CreateGroupNode(group);
+ output.Add(node);
+ nodesById.Add(group.GetObjectId(), node);
+ }
+
+ while (remainingNodes.Count > 0)
+ {
+ List<MgLayerGroup> toRemove = new List<MgLayerGroup>();
+ for (int j = 0; j < remainingNodes.Count; j++)
+ {
+ var parentId = remainingNodes[j].Group.GetObjectId();
+ if (nodesById.ContainsKey(parentId))
+ {
+ var node = CreateGroupNode(remainingNodes[j]);
+ nodesById[parentId].Nodes.Add(node);
+ toRemove.Add(remainingNodes[j]);
+ }
+ }
+ //Whittle down this list
+ if (toRemove.Count > 0)
+ {
+ foreach (var g in toRemove)
+ {
+ remainingNodes.Remove(g);
+ }
+ }
+ }
+ }
+
+ //Now process layers
+ for (int i = 0; i < layers.GetCount(); i++)
+ {
+ var lyr = layers.GetItem(i);
+ var ldfId = lyr.LayerDefinition;
+
+ if (!_layerDefinitionContents.ContainsKey(ldfId.ToString()))
+ {
+ _layerDefinitionContents[ldfId.ToString()] = string.Empty;
+ }
+ }
+
+ //Collect all resource contents in a batch
+ MgStringCollection layerIds = new MgStringCollection();
+ foreach (var lid in _layerDefinitionContents.Keys)
+ {
+ layerIds.Add(lid);
+ }
+
+ MgStringCollection layerContents = _resSvc.GetResourceContents(layerIds, null);
+ for (int i = 0; i < layerIds.GetCount(); i++)
+ {
+ string lid = layerIds.GetItem(i);
+ _layerDefinitionContents[lid] = layerContents.GetItem(i);
+ }
+
+ List<MgLayerBase> remainingLayers = new List<MgLayerBase>();
+ for (int i = 0; i < layers.GetCount(); i++)
+ {
+ var layer = layers.GetItem(i);
+ _layers.Add(layer.GetObjectId(), layer);
+
+ bool display = layer.DisplayInLegend;
+ bool visible = _provider.IsLayerPotentiallyVisibleAtScale(layer, false);
+ if (!display)
+ continue;
+
+ if (!visible)
+ continue;
+
+ //Add ones without parents first.
+ if (layer.Group != null)
+ {
+ remainingLayers.Add(layer);
+ }
+ else
+ {
+ var node = CreateLayerNode(layer);
+ if (node != null)
+ {
+ output.Add(node);
+ nodesById.Add(layer.GetObjectId(), node);
+ if (layer.ExpandInLegend)
+ node.Expand();
+ }
+ }
+
+ while (remainingLayers.Count > 0)
+ {
+ List<MgLayerBase> toRemove = new List<MgLayerBase>();
+ for (int j = 0; j < remainingLayers.Count; j++)
+ {
+ var parentId = remainingLayers[j].Group.GetObjectId();
+ if (nodesById.ContainsKey(parentId))
+ {
+ var node = CreateLayerNode(remainingLayers[j]);
+ if (node != null)
+ {
+ nodesById[parentId].Nodes.Add(node);
+ if (remainingLayers[j].ExpandInLegend)
+ node.Expand();
+ }
+ toRemove.Add(remainingLayers[j]);
+ }
+ }
+ //Whittle down this list
+ if (toRemove.Count > 0)
+ {
+ foreach (var g in toRemove)
+ {
+ remainingLayers.Remove(g);
+ }
+ }
+ }
+ }
+
+ //Now expand any relevant groups
+ for (int i = 0; i < groups.GetCount(); i++)
+ {
+ var group = groups.GetItem(i);
+ if (group.ExpandInLegend)
+ {
+ var groupId = group.GetObjectId();
+ if (nodesById.ContainsKey(groupId))
+ {
+ nodesById[groupId].Expand();
+ }
+ }
+ }
+
+ return output.ToArray();
+ }
+
+ private static bool IsThemeLayerNode(TreeNode node)
+ {
+ var meta = node.Tag as LayerNodeMetadata;
+ if (meta != null)
+ return meta.ThemeIcon != null || meta.IsBaseLayer;
+
+ return false;
+ }
+
+ private static bool IsLayerNode(TreeNode node)
+ {
+ var meta = node.Tag as LayerNodeMetadata;
+ return meta != null;
+ }
+
+ internal void DrawNode(DrawTreeNodeEventArgs e, bool showPlusMinus, Font font)
+ {
+ if (IsLayerNode(e.Node) && !e.Bounds.IsEmpty)
+ {
+ Color backColor, foreColor;
+
+ //For some reason, the default bounds are way off from what you would
+ //expect it to be. So we apply this offset for any text/image draw operations
+ int xoffset = -36;
+ if (showPlusMinus && e.Node.Nodes.Count > 0)
+ {
+ // Use the VisualStyles renderer to use the proper OS-defined glyphs
+ Rectangle glyphRect = new Rectangle(e.Node.Bounds.X - 52, e.Node.Bounds.Y, 16, 16);
+ if (Application.RenderWithVisualStyles)
+ {
+ VisualStyleElement element = (e.Node.IsExpanded) ?
+ VisualStyleElement.TreeView.Glyph.Opened : VisualStyleElement.TreeView.Glyph.Closed;
+
+ VisualStyleRenderer renderer = new VisualStyleRenderer(element);
+ renderer.DrawBackground(e.Graphics, glyphRect);
+ }
+ else //Visual Styles disabled, fallback to drawing the +/- using geometric primitives
+ {
+ int h = 8;
+ int w = 8;
+ int x = glyphRect.X;
+ int y = glyphRect.Y + (glyphRect.Height / 2) - 4;
+
+ //Draw the -
+ e.Graphics.DrawRectangle(new Pen(SystemBrushes.ControlDark), x, y, w, h);
+ e.Graphics.FillRectangle(new SolidBrush(Color.White), x + 1, y + 1, w - 1, h - 1);
+ e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Black)), x + 2, y + 4, x + w - 2, y + 4);
+
+ //Draw the |
+ if (!e.Node.IsExpanded)
+ e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Black)), x + 4, y + 2, x + 4, y + h - 2);
+ }
+ }
+
+ if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
+ {
+ backColor = SystemColors.Highlight;
+ foreColor = SystemColors.HighlightText;
+ }
+ else if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
+ {
+ backColor = SystemColors.HotTrack;
+ foreColor = SystemColors.HighlightText;
+ }
+ else
+ {
+ backColor = e.Node.BackColor;
+ foreColor = e.Node.ForeColor;
+ }
+
+ var tag = e.Node.Tag as LayerNodeMetadata;
+ var checkBoxOffset = xoffset;
+ var selectabilityOffset = xoffset + 16;
+ var iconOffsetNoSelect = xoffset + 16;
+ if (tag != null && tag.IsThemeRule) //No checkbox for theme rule nodes
+ {
+ selectabilityOffset = xoffset;
+ iconOffsetNoSelect = xoffset;
+ }
+ var iconOffset = selectabilityOffset + 20;
+ var textOffset = iconOffset + 20;
+ var textOffsetNoSelect = iconOffsetNoSelect + 20;
+
+ //Uncomment if you need to "see" the bounds of the node
+ //e.Graphics.DrawRectangle(Pens.Black, e.Node.Bounds);
+
+ if (tag != null && !tag.IsThemeRule) //No checkbox for theme rule nodes
+ {
+ if (Application.RenderWithVisualStyles)
+ {
+ CheckBoxRenderer.DrawCheckBox(
+ e.Graphics,
+ new Point(e.Node.Bounds.X + checkBoxOffset, e.Node.Bounds.Y),
+ e.Node.Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal);
+ }
+ else
+ {
+ //We don't have to do this, but with Visual Styles disabled, there is a noticeable jarring visual difference from DrawDefault'd checkboxes
+ //So we might as well emulate that style for the sake of consistency
+ var rect = new Rectangle(e.Node.Bounds.X + checkBoxOffset, e.Node.Bounds.Y, 16, 16);
+ ControlPaint.DrawCheckBox(e.Graphics, rect, e.Node.Checked ? ButtonState.Checked | ButtonState.Flat : ButtonState.Flat);
+ rect.Inflate(-2, -2);
+ e.Graphics.DrawRectangle(new Pen(Brushes.Black, 2.0f), rect);
+ }
+ }
+ if (tag != null)
+ {
+ if (tag.DrawSelectabilityIcon)
+ {
+ var icon = tag.IsSelectable ? _selectableIcon : _unselectableIcon;
+ e.Graphics.DrawImage(icon, e.Node.Bounds.X + selectabilityOffset, e.Node.Bounds.Y);
+ //Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
+ }
+ if (tag.ThemeIcon != null)
+ {
+ if (tag.DrawSelectabilityIcon)
+ {
+ e.Graphics.DrawImage(tag.ThemeIcon, e.Node.Bounds.X + iconOffset, e.Node.Bounds.Y);
+ //Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
+ }
+ else
+ {
+ e.Graphics.DrawImage(tag.ThemeIcon, e.Node.Bounds.X + iconOffsetNoSelect, e.Node.Bounds.Y);
+ //Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
+ }
+ }
+
+ using (SolidBrush brush = new SolidBrush(Color.Black))
+ {
+ e.Graphics.DrawString(e.Node.Text, font, brush, e.Node.Bounds.X + (tag.DrawSelectabilityIcon ? textOffset : textOffsetNoSelect), e.Node.Bounds.Y);
+ }
+ }
+ else
+ {
+ using (SolidBrush brush = new SolidBrush(Color.Black))
+ {
+ e.Graphics.DrawString(e.Node.Text, font, brush, e.Node.Bounds.X + 17.0f + xoffset, e.Node.Bounds.Y);
+ }
+ }
+
+ e.DrawDefault = false;
+ }
+ else
+ {
+ e.DrawDefault = true;
+ }
+ }
+
+ internal void SetGroupExpandInLegend(string groupName, bool expand)
+ {
+ if (_groups.ContainsKey(groupName))
+ _provider.SetGroupExpandInLegend(_groups[groupName], expand);
+ }
+
+ internal void SetLayerExpandInLegend(string layerName, bool expand)
+ {
+ if (_layers.ContainsKey(layerName))
+ _provider.SetLayerExpandInLegend(_layers[layerName], expand);
+ }
+
+ internal void SetGroupVisible(string name, bool bChecked)
+ {
+ if (_groups.ContainsKey(name))
+ {
+ var grp = _groups[name];
+ grp.SetVisible(bChecked);
+ var bVis = HasVisibleParent(grp);
+ if (bVis)
+ _legend.OnRequestRefresh();
+ }
+ }
+
+ internal void SetLayerVisible(string name, bool bChecked)
+ {
+ if (_layers.ContainsKey(name))
+ {
+ var layer = _layers[name];
+ layer.SetVisible(bChecked);
+ var bVis = HasVisibleParent(layer);
+ if (bVis)
+ {
+ layer.ForceRefresh();
+ _legend.OnRequestRefresh();
+ }
+ }
+ }
+ }
+
+ namespace Legend.Model
+ {
+ class LegendNodeMetadata
+ {
+ public bool IsGroup { get; protected set; }
+ }
+
+ class GroupNodeMetadata : LegendNodeMetadata
+ {
+ internal MgLayerGroup Group { get; set; }
+
+ public GroupNodeMetadata(MgLayerGroup group)
+ {
+ base.IsGroup = true;
+ this.Group = group;
+ }
+ }
+
+ class LayerNodeMetadata : LegendNodeMetadata
+ {
+ public LayerNodeMetadata(MgLayerBase layer, bool bInitiallySelectable)
+ {
+ base.IsGroup = false;
+ this.Layer = layer;
+ this.IsSelectable = (layer != null) ? layer.Selectable : false;
+ this.DrawSelectabilityIcon = (layer != null && bInitiallySelectable);
+ this.IsThemeRule = false;
+ }
+
+ internal MgLayerBase Layer { get; set; }
+
+ public bool DrawSelectabilityIcon { get; set; }
+
+ public bool IsSelectable { get; set; }
+
+ public bool IsThemeRule { get; set; }
+
+ public bool IsBaseLayer { get; set; }
+
+ public Image ThemeIcon { get; set; }
+ }
+ }
+}
Modified: branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs 2012-08-21 11:07:49 UTC (rev 6944)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgMapViewer.cs 2012-08-21 13:16:50 UTC (rev 6945)
@@ -268,7 +268,7 @@
dPtStart.X = 0;
dPtStart.Y = 0;
this.DigitizingType = MapDigitizationType.None;
- Trace.TraceInformation("Digitization cancelled");
+ //Trace.TraceInformation("Digitization cancelled");
this.Invalidate();
}
}
@@ -453,7 +453,7 @@
_selectionRenderOpts = null;
_selectionRenderOpts = CreateSelectionRenderingOptions(value.R, value.G, value.B);
- Trace.TraceInformation("Selection color updated to ({0}, {1}, {2})", value.R, value.G, value.B);
+ //Trace.TraceInformation("Selection color updated to ({0}, {1}, {2})", value.R, value.G, value.B);
}
}
@@ -515,7 +515,7 @@
{
base.OnPaint(e);
- Trace.TraceInformation("OnPaint(e)");
+ //Trace.TraceInformation("OnPaint(e)");
ApplyPaintTranslateTransform(e);
if (mouseWheelSx.HasValue && mouseWheelSy.HasValue && mouseWheelSx.Value != 0.0 && mouseWheelSy.Value != 0.0)
@@ -529,14 +529,14 @@
if (_mapImage != null)
{
- Trace.TraceInformation("Render buffered map image");
+ //Trace.TraceInformation("Render buffered map image");
e.Graphics.DrawImage(_mapImage, new PointF(0, 0));
}
//Thread.Sleep(100);
if (_selectionImage != null)
{
- Trace.TraceInformation("Render buffered map selection");
+ //Trace.TraceInformation("Render buffered map selection");
e.Graphics.DrawImage(_selectionImage, new PointF(0, 0));
}
@@ -801,9 +801,9 @@
if (rect.HasValue)
{
var r = rect.Value;
- Trace.TraceInformation("Draw rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+ //Trace.TraceInformation("Draw rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
e.Graphics.DrawRectangle(CreateOutlinePen(), r);
- Trace.TraceInformation("Fill rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+ //Trace.TraceInformation("Fill rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
e.Graphics.FillRectangle(CreateFillBrush(), r);
DrawVertexCoordinates(e, r.Left, r.Top, true);
@@ -821,9 +821,9 @@
if (rect.HasValue)
{
var r = rect.Value;
- Trace.TraceInformation("Draw rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+ //Trace.TraceInformation("Draw rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
e.Graphics.DrawRectangle(CreateOutlinePen(), r);
- Trace.TraceInformation("Fill rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+ //Trace.TraceInformation("Fill rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
e.Graphics.FillRectangle(CreateFillBrush(), r);
}
}
@@ -1306,13 +1306,13 @@
ResetMouseWheelPaintTransforms();
if (_map != null)
{
- Trace.TraceInformation("Performing delayed resize to (" + this.Width + ", " + this.Height + ")");
+ //Trace.TraceInformation("Performing delayed resize to (" + this.Width + ", " + this.Height + ")");
_provider.SetDisplaySize(this.Width, this.Height);
UpdateExtents();
RefreshMap(false);
}
_delayedResizeTimer.Stop();
- Trace.TraceInformation("Delayed resize timer stopped");
+ //Trace.TraceInformation("Delayed resize timer stopped");
});
if (this.InvokeRequired)
this.Invoke(action);
@@ -1326,17 +1326,17 @@
{
_delayedResizeTimer = new System.Timers.Timer();
_delayedResizeTimer.Elapsed += OnDelayResizeTimerElapsed;
- Trace.TraceInformation("Delay resize timer initialized");
+ //Trace.TraceInformation("Delay resize timer initialized");
}
if (_delayedResizeTimer.Enabled)
{
- Trace.TraceInformation("Stopped delayed resize");
+ //Trace.TraceInformation("Stopped delayed resize");
_delayedResizeTimer.Stop();
}
_delayedResizeTimer.Interval = 500;
_delayedResizeTimer.Start();
- Trace.TraceInformation("Delayed resize re-scheduled");
+ //Trace.TraceInformation("Delayed resize re-scheduled");
}
/// <summary>
@@ -1609,7 +1609,7 @@
_busy = value;
#if TRACE
- Trace.TraceInformation("IsBusy = " + _busy);
+ //Trace.TraceInformation("IsBusy = " + _busy);
if (value)
{
_renderSw.Reset();
@@ -1618,7 +1618,7 @@
else
{
_renderSw.Stop();
- Trace.TraceInformation("Rendering operation took {0}ms", _renderSw.ElapsedMilliseconds);
+ //Trace.TraceInformation("Rendering operation took {0}ms", _renderSw.ElapsedMilliseconds);
}
#endif
OnPropertyChanged("IsBusy");
@@ -1907,7 +1907,7 @@
this.Image.Dispose();
this.Image = null;
}
- Trace.TraceInformation("Set map image");
+ //Trace.TraceInformation("Set map image");
this.Image = res.Image;
bInvalidate = true;
}
@@ -1918,7 +1918,7 @@
_selectionImage.Dispose();
_selectionImage = null;
}
- Trace.TraceInformation("Set selection image");
+ //Trace.TraceInformation("Set selection image");
_selectionImage = res.SelectionImage;
bInvalidate = true;
}
@@ -1926,7 +1926,7 @@
//If there is a queued refresh action, execute it now
if (_queuedRefresh != null)
{
- Trace.TraceInformation("Executing queued rendering operation");
+ //Trace.TraceInformation("Executing queued rendering operation");
_queuedRefresh();
_queuedRefresh = null;
}
@@ -2198,7 +2198,7 @@
}
#if TRACE
sw.Stop();
- Trace.TraceInformation("Selection processing completed in {0}ms", sw.ElapsedMilliseconds);
+ //Trace.TraceInformation("Selection processing completed in {0}ms", sw.ElapsedMilliseconds);
#endif
//This selection may result in nothing, so we invalidate the selection image beforehand
if (_selectionImage != null)
@@ -2299,8 +2299,8 @@
delayRenderTimer.Stop();
delayRenderTimer.Start();
- Trace.TraceInformation("Postponed delay render");
- Trace.TraceInformation("Mouse delta: " + e.Delta + " (" + (e.Delta > 0 ? "Zoom in" : "Zoom out") + ")");
+ //Trace.TraceInformation("Postponed delay render");
+ //Trace.TraceInformation("Mouse delta: " + e.Delta + " (" + (e.Delta > 0 ? "Zoom in" : "Zoom out") + ")");
//Negative delta = zoom out, Positive delta = zoom in
//deltas are in units of 120, so treat each multiple of 120 as a "zoom unit"
@@ -2328,7 +2328,7 @@
Invalidate();
}
- Trace.TraceInformation("Delta units is: " + mouseWheelDelta);
+ //Trace.TraceInformation("Delta units is: " + mouseWheelDelta);
//Completely ripped the number crunching here from the AJAX viewer with no sense of shame whatsoever :)
delayRenderScale = GetNewScale(_map.ViewScale, mouseWheelDelta.Value);
@@ -2356,7 +2356,7 @@
mouseWheelSx = (float)(w / (double)this.Width);
mouseWheelSy = (float)(h / (double)this.Height);
- Trace.TraceInformation("Paint transform (tx: " + mouseWheelTx + ", ty: " + mouseWheelTy + ", sx: " + mouseWheelSx + ", sy: " + mouseWheelSy + ")");
+ //Trace.TraceInformation("Paint transform (tx: " + mouseWheelTx + ", ty: " + mouseWheelTy + ", sx: " + mouseWheelSx + ", sy: " + mouseWheelSy + ")");
}
static double GetMetersPerPixel(int dpi)
@@ -2403,8 +2403,8 @@
void OnDelayRender(object sender, System.Timers.ElapsedEventArgs e)
{
- Trace.TraceInformation("Delay rendering");
- Trace.TraceInformation("Set new map coordinates to (" + delayRenderViewCenter.Value.X + ", " + delayRenderViewCenter.Value.Y + " at " + delayRenderScale.Value + ")");
+ //Trace.TraceInformation("Delay rendering");
+ //Trace.TraceInformation("Set new map coordinates to (" + delayRenderViewCenter.Value.X + ", " + delayRenderViewCenter.Value.Y + " at " + delayRenderScale.Value + ")");
ResetMouseWheelPaintTransforms();
MethodInvoker action = () => { ZoomToView(delayRenderViewCenter.Value.X, delayRenderViewCenter.Value.Y, delayRenderScale.Value, true); };
if (this.InvokeRequired)
@@ -2422,7 +2422,7 @@
mouseWheelTx = null;
mouseWheelTy = null;
mouseWheelDelta = 0;
- Trace.TraceInformation("Mouse wheel paint transform reset");
+ //Trace.TraceInformation("Mouse wheel paint transform reset");
}
private void HandleMouseClick(MouseEventArgs e)
@@ -2542,18 +2542,18 @@
if (e.Button == MouseButtons.Left)
{
dragStart = e.Location;
- Trace.TraceInformation("Drag started at (" + dragStart.X + ", " + dragStart.Y + ")");
+ //Trace.TraceInformation("Drag started at (" + dragStart.X + ", " + dragStart.Y + ")");
switch (this.ActiveTool)
{
case MapActiveTool.Pan:
- Trace.TraceInformation("START PANNING");
+ //Trace.TraceInformation("START PANNING");
break;
case MapActiveTool.Select:
- Trace.TraceInformation("START SELECT");
+ //Trace.TraceInformation("START SELECT");
break;
case MapActiveTool.ZoomIn:
- Trace.TraceInformation("START ZOOM");
+ //Trace.TraceInformation("START ZOOM");
break;
}
}
@@ -2677,7 +2677,7 @@
_activeTooltipText = QueryFirstVisibleTooltip(e.X, e.Y);
#if TRACE
sw.Stop();
- Trace.TraceInformation("QueryFirstVisibleTooltip() executed in {0}ms", sw.ElapsedMilliseconds);
+ //Trace.TraceInformation("QueryFirstVisibleTooltip() executed in {0}ms", sw.ElapsedMilliseconds);
#endif
}
else
@@ -2695,7 +2695,7 @@
//Fix the last one, can't edit last one because points are value types
dPath.RemoveAt(dPath.Count - 1);
dPath.Add(new Point(e.X, e.Y));
- Trace.TraceInformation("Updating last point of a {0} point path", dPath.Count);
+ //Trace.TraceInformation("Updating last point of a {0} point path", dPath.Count);
}
Invalidate();
}
@@ -2728,7 +2728,7 @@
double mdy = coord.Y - pt.Y;
ZoomToView(coord.X, coord.Y, _map.ViewScale, true);
- Trace.TraceInformation("END PANNING");
+ //Trace.TraceInformation("END PANNING");
}
else if (this.ActiveTool == MapActiveTool.Select)
{
Modified: branches/2.4/MgDev/Desktop/MapViewerTest/MapViewerTest.csproj.user
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewerTest/MapViewerTest.csproj.user 2012-08-21 11:07:49 UTC (rev 6944)
+++ branches/2.4/MgDev/Desktop/MapViewerTest/MapViewerTest.csproj.user 2012-08-21 13:16:50 UTC (rev 6945)
@@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<StartArguments>Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition</StartArguments>
- <EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
+ <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<StartArguments>Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition</StartArguments>
More information about the mapguide-commits
mailing list