Changeset 2273

Show
Ignore:
Timestamp:
03/04/10 15:52:24 (5 months ago)
Author:
JO94
Message:

fixed repeated FalconView refreshes when tree nodes checked / unchecked

Location:
FalconView/trunk/public/Plugins/Overlays/GeodataOverlayServer
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • FalconView/trunk/public/Plugins/Overlays/GeodataOverlayServer/DataSourceTree.cs

    r2267 r2273  
    453453      { 
    454454         Tree.AfterCheck -= m_clickHandler; 
    455          if (!e.Node.Checked) 
    456          { 
     455         if (e.Node.Checked) 
     456            SetCheckNodeAndParents((FvDataTreeNode)e.Node, true); 
     457         else 
    457458            SetCheckNodeAndChildren((FvDataTreeNode)e.Node, false); 
    458          } 
    459          if (e.Node.Checked) 
    460          { 
    461             SetCheckNodeAndParents((FvDataTreeNode)e.Node, true); 
    462          } 
     459         new fvw.LayerClass().Refresh(-1); // refresh FalconView 
    463460         Tree.AfterCheck += m_clickHandler; 
    464461      } 
  • FalconView/trunk/public/Plugins/Overlays/GeodataOverlayServer/GeodataOverlay.cs

    r2271 r2273  
    3939namespace GeodataOverlayServer 
    4040{ 
    41     [Guid("641E4D02-4A04-4315-93F3-F32FBFC85E21")] 
    42     public class GeodataOverlay : IFvOverlay,   //base overlay functionality 
    43         IFvOverlayContextMenu,                  //for context menu manipulation 
    44         IFvOverlayPersistence,                  //for file handling 
    45         IFvOverlayRenderer,                     //for drawing 
    46         IFvInformationDialogCallback,           //for smartly closing dialog 
    47         IFvPlaybackEventsObserver,              //for temporal filtering 
    48         IFvPlaybackTimeInterval                 //for temporal filtering 
    49     { 
    50         #region Variables 
    51  
    52         //static 
    53         private static IUserControlContainer s_treeControl; 
    54         private static int s_treeControlMenuItemAddCount = 0; 
    55         private static ILayer s_layer; 
    56  
    57         //members 
    58         private TreeViewEventHandler m_clickHandler; 
    59         private FvDataTreeNode m_dataSource; 
    60         private bool m_dirty = false; 
    61         private string m_fileSpec; 
    62         private GeometryFilter m_screenFilter; 
    63         private bool m_resetFilter = true; 
    64         private double prevUpperLat; 
    65         private double prevLowerLat; 
    66         private double prevLeftLon; 
    67         private double prevRightLon; 
    68         private Guid m_guid; 
    69         private bool m_isVisible = true; 
    70         private bool m_readOnly; 
    71         private IDataSourceRenderer m_renderer; 
    72         private bool m_saved = true; 
    73         private ISymbolFactory m_symbolFactory; 
    74         private IUserSimulator m_userSimulator = new UserSimulatorClass(); 
    75         private DateTime m_temporalFilterDateTime = DateTime.Now; 
    76         private IDisplayChangeNotifyEvents m_displayChangeNotifyEvents; 
    77  
    78         #endregion 
    79  
    80         #region Properties 
    81  
    82         void Singleton_SettingsApplied() 
    83         { 
    84             Layer.Refresh(-1); 
    85         } 
    86  
    87         public static ILayer Layer 
    88         { 
    89             get 
    90             { 
    91                 if (s_layer == null) 
    92                 { 
    93                     s_layer = new LayerClass(); 
    94                 } 
    95                 return s_layer; 
    96             } 
    97         } 
    98  
    99         public int OverlayCount 
    100         { 
    101             get 
    102             { 
    103                 return Tree.Tree.Nodes.Count; 
    104             } 
    105         } 
    106  
    107         public static DataSourceTree Tree 
    108         { 
    109             get 
    110             { 
    111                 return TreeContainer.Tree; 
    112             } 
    113         } 
    114  
    115         public static IUserControlContainer TreeContainer 
    116         { 
    117             get 
    118             { 
    119                 if (s_treeControl == null) 
    120                 { 
    121                     s_treeControl = new GeodataControl(); 
    122                 } 
    123                 return s_treeControl; 
    124             } 
    125         } 
    126  
    127         public ISymbolFactory SymbolFactory 
    128         { 
    129             get { return m_symbolFactory; } 
    130             set { m_symbolFactory = value; } 
    131         } 
    132  
    133         #endregion 
    134  
    135         #region Methods 
    136  
    137         public GeodataOverlay() 
    138         { 
    139             m_clickHandler = new TreeViewEventHandler(Tree_AfterCheck); 
    140  
    141             DefaultRendererSettings.Singleton.SettingsApplied += new AppliedHandler(Singleton_SettingsApplied); 
    142         } 
    143  
    144         private void AppendGetFeatureInfoMenuItem(IFvContextMenu pContextMenu, IFvMapView pMapView, int x, int y) 
    145         { 
    146             //if we hit a drawn element, then add the option to display information for that element 
    147             List<IFeature> clickedFeatures = new List<IFeature>(); 
    148  
    149             GeometryFilter locationFilter = new GeometryFilterClass(); 
    150  
    151             ISettableMapProj mapProjection = (ISettableMapProj)pMapView.CurrentMapProj; 
    152  
    153             double northLat, eastLon; 
    154             double southLat, westLon; 
    155             int result; 
    156             double offset = 4; 
    157             mapProjection.surface_to_geo_dbl((double)x + offset, (double)y + offset, out northLat, out eastLon, out result); 
    158             mapProjection.surface_to_geo_dbl((double)x - offset, (double)y - offset, out southLat, out westLon, out result); 
    159  
    160  
    161             locationFilter.CreateByRectangle( 
    162                 Math.Min(eastLon, westLon), Math.Min(northLat, southLat), 
    163                 Math.Max(eastLon, westLon), Math.Max(northLat, southLat)); 
    164             clickedFeatures.AddRange(ClickedFeatures(m_dataSource, (IFilter)locationFilter)); 
    165  
    166             if (clickedFeatures.Count > 0) 
    167             { 
    168                 pContextMenu.AppendMenuItem(new ShowInfo(clickedFeatures, this)); 
    169             } 
    170         } 
    171  
    172         private void AppendToggleTreeMenuItem(IFvContextMenu pContextMenu) 
    173         { 
    174             if (s_treeControlMenuItemAddCount == 0) 
    175             { 
    176                 pContextMenu.AppendMenuItem(new ToggleTreeMenuItem(TreeContainer)); 
    177             } 
    178  
    179             s_treeControlMenuItemAddCount++; 
    180  
    181             if (s_treeControlMenuItemAddCount == OverlayCount) 
    182             { 
    183                 s_treeControlMenuItemAddCount = 0; 
    184             } 
    185  
    186         } 
    187  
    188         protected List<IFeature> ClickedFeatures(TreeNode parentNode, IFilter locationFilter) 
    189         { 
    190             List<IFeature> result = new List<IFeature>(); 
    191             foreach (TreeNode node in parentNode.Nodes) 
    192             { 
    193                 if (node.Checked) 
    194                 { 
    195                     if (node is FvDataTreeNode) 
    196                     { 
    197                         result.AddRange(ClickedFeatures(node, locationFilter)); 
     41   [Guid("641E4D02-4A04-4315-93F3-F32FBFC85E21")] 
     42   public class GeodataOverlay : IFvOverlay,   //base overlay functionality 
     43       IFvOverlayContextMenu,                  //for context menu manipulation 
     44       IFvOverlayPersistence,                  //for file handling 
     45       IFvOverlayRenderer,                     //for drawing 
     46       IFvInformationDialogCallback,           //for smartly closing dialog 
     47       IFvPlaybackEventsObserver,              //for temporal filtering 
     48       IFvPlaybackTimeInterval                 //for temporal filtering 
     49   { 
     50      #region Variables 
     51 
     52      //static 
     53      private static IUserControlContainer s_treeControl; 
     54      private static int s_treeControlMenuItemAddCount = 0; 
     55 
     56      //members 
     57      private FvDataTreeNode m_dataSource; 
     58      private bool m_dirty = false; 
     59      private string m_fileSpec; 
     60      private GeometryFilter m_screenFilter; 
     61      private bool m_resetFilter = true; 
     62      private double prevUpperLat; 
     63      private double prevLowerLat; 
     64      private double prevLeftLon; 
     65      private double prevRightLon; 
     66      private Guid m_guid; 
     67      private bool m_isVisible = true; 
     68      private bool m_readOnly; 
     69      private IDataSourceRenderer m_renderer; 
     70      private bool m_saved = true; 
     71      private ISymbolFactory m_symbolFactory; 
     72      private IUserSimulator m_userSimulator = new UserSimulatorClass(); 
     73      private DateTime m_temporalFilterDateTime = DateTime.Now; 
     74      private IDisplayChangeNotifyEvents m_displayChangeNotifyEvents; 
     75 
     76      #endregion 
     77 
     78      #region Properties 
     79 
     80      void Singleton_SettingsApplied() 
     81      { 
     82         new fvw.LayerClass().Refresh(-1); // refresh FalconView 
     83      } 
     84 
     85      public int OverlayCount 
     86      { 
     87         get 
     88         { 
     89            return Tree.Tree.Nodes.Count; 
     90         } 
     91      } 
     92 
     93      public static DataSourceTree Tree 
     94      { 
     95         get 
     96         { 
     97            return TreeContainer.Tree; 
     98         } 
     99      } 
     100 
     101      public static IUserControlContainer TreeContainer 
     102      { 
     103         get 
     104         { 
     105            if (s_treeControl == null) 
     106            { 
     107               s_treeControl = new GeodataControl(); 
     108            } 
     109            return s_treeControl; 
     110         } 
     111      } 
     112 
     113      public ISymbolFactory SymbolFactory 
     114      { 
     115         get { return m_symbolFactory; } 
     116         set { m_symbolFactory = value; } 
     117      } 
     118 
     119      #endregion 
     120 
     121      #region Methods 
     122 
     123      public GeodataOverlay() 
     124      { 
     125         DefaultRendererSettings.Singleton.SettingsApplied += new AppliedHandler(Singleton_SettingsApplied); 
     126      } 
     127 
     128      private void AppendGetFeatureInfoMenuItem(IFvContextMenu pContextMenu, IFvMapView pMapView, int x, int y) 
     129      { 
     130         //if we hit a drawn element, then add the option to display information for that element 
     131         List<IFeature> clickedFeatures = new List<IFeature>(); 
     132 
     133         GeometryFilter locationFilter = new GeometryFilterClass(); 
     134 
     135         ISettableMapProj mapProjection = (ISettableMapProj)pMapView.CurrentMapProj; 
     136 
     137         double northLat, eastLon; 
     138         double southLat, westLon; 
     139         int result; 
     140         double offset = 4; 
     141         mapProjection.surface_to_geo_dbl((double)x + offset, (double)y + offset, out northLat, out eastLon, out result); 
     142         mapProjection.surface_to_geo_dbl((double)x - offset, (double)y - offset, out southLat, out westLon, out result); 
     143 
     144 
     145         locationFilter.CreateByRectangle( 
     146             Math.Min(eastLon, westLon), Math.Min(northLat, southLat), 
     147             Math.Max(eastLon, westLon), Math.Max(northLat, southLat)); 
     148         clickedFeatures.AddRange(ClickedFeatures(m_dataSource, (IFilter)locationFilter)); 
     149 
     150         if (clickedFeatures.Count > 0) 
     151         { 
     152            pContextMenu.AppendMenuItem(new ShowInfo(clickedFeatures, this)); 
     153         } 
     154      } 
     155 
     156      private void AppendToggleTreeMenuItem(IFvContextMenu pContextMenu) 
     157      { 
     158         if (s_treeControlMenuItemAddCount == 0) 
     159         { 
     160            pContextMenu.AppendMenuItem(new ToggleTreeMenuItem(TreeContainer)); 
     161         } 
     162 
     163         s_treeControlMenuItemAddCount++; 
     164 
     165         if (s_treeControlMenuItemAddCount == OverlayCount) 
     166         { 
     167            s_treeControlMenuItemAddCount = 0; 
     168         } 
     169 
     170      } 
     171 
     172      protected List<IFeature> ClickedFeatures(TreeNode parentNode, IFilter locationFilter) 
     173      { 
     174         List<IFeature> result = new List<IFeature>(); 
     175         foreach (TreeNode node in parentNode.Nodes) 
     176         { 
     177            if (node.Checked) 
     178            { 
     179               if (node is FvDataTreeNode) 
     180               { 
     181                  result.AddRange(ClickedFeatures(node, locationFilter)); 
     182 
     183                  IFvDataSet set = (node as FvDataTreeNode).Set; 
     184                  if (set is IFeatureDataSet) 
     185                  { 
     186                     result.AddRange(ClickedFeatures(set as IFeatureDataSet, locationFilter)); 
     187                  } 
     188               } 
     189            } 
     190         } 
     191         return result; 
     192      } 
     193 
     194      protected List<IFeature> ClickedFeatures(IFeatureDataSet featureDataSet, IFilter locationFilter) 
     195      { 
     196         List<IFeature> result = new List<IFeature>(); 
     197 
     198         IFilter originalFilter = (featureDataSet as IFvDataSet).Filter; 
     199         try 
     200         { 
     201            (featureDataSet as IFvDataSet).Filter = locationFilter; 
     202         } 
     203         catch (Exception ex) 
     204         { 
     205            LoggingUtils.ReportError(ex); 
     206            //filter didn't work, return empty set (better to return nothing than everything) 
     207            return result; 
     208         } 
     209 
     210         for (int i = 0; i < featureDataSet.FeatureCount; i++) 
     211         { 
     212            result.Add(featureDataSet.GetFeature(i)); 
     213         } 
     214 
     215         //since the first worked, we assume the second will work 
     216         (featureDataSet as IFvDataSet).Filter = originalFilter; 
     217 
     218         return result; 
     219      } 
     220 
     221      protected void OnDraw(TreeNode parentNode) 
     222      { 
     223         //using (new Profiler("GeodataOverlay.OnDraw")) // comment out except when performance testing 
     224         { 
     225            // global hold on refreshing tree during drawing 
     226            bool bOriginalHoldValue = DataSourceTree.DataSourceCallbackHandler.HoldDataSourceChangedCallbacks; 
     227            DataSourceTree.DataSourceCallbackHandler.HoldDataSourceChangedCallbacks = true; 
     228 
     229            try 
     230            { 
     231               //traverse children backwards - lowest node drawn first 
     232               for (int i = parentNode.Nodes.Count; i > 0; i--) 
     233               { 
     234                  TreeNode node = parentNode.Nodes[i - 1]; 
     235                  if (node.Checked) 
     236                  { 
     237                     if (node is FvDataTreeNode) 
     238                     { 
     239                        //render after traversing children - lowest node drawn first 
     240                        OnDraw(node); 
    198241 
    199242                        IFvDataSet set = (node as FvDataTreeNode).Set; 
    200                         if (set is IFeatureDataSet) 
     243                        if (set != null) 
    201244                        { 
    202                             result.AddRange(ClickedFeatures(set as IFeatureDataSet, locationFilter)); 
     245                           OnDraw(set); 
    203246                        } 
    204                     } 
    205                 } 
    206             } 
    207             return result; 
    208         } 
    209  
    210         protected List<IFeature> ClickedFeatures(IFeatureDataSet featureDataSet, IFilter locationFilter) 
    211         { 
    212             List<IFeature> result = new List<IFeature>(); 
    213  
    214             IFilter originalFilter = (featureDataSet as IFvDataSet).Filter; 
     247                     } 
     248                  } 
     249               } 
     250            } 
     251            finally 
     252            { 
     253               DataSourceTree.DataSourceCallbackHandler.HoldDataSourceChangedCallbacks = bOriginalHoldValue; 
     254            } 
     255         } 
     256      } 
     257 
     258      protected void OnDraw(IFvDataSet set) 
     259      { 
     260         try 
     261         { 
     262            // try first to draw with filtering (if the filter was reset) 
     263 
     264            if (m_resetFilter) 
     265            { 
     266               IFilter oldFilter = null; 
     267               bool bOldFilterValid = false; 
     268 
     269               try 
     270               { 
     271                  // a composite filter will filter both time and space 
     272 
     273                  oldFilter = set.Filter; 
     274                  bOldFilterValid = true; 
     275 
     276                  ITemporalFilter temporalFilter = new TemporalFilterClass(); 
     277                  temporalFilter.Start = m_temporalFilterDateTime; 
     278                  temporalFilter.End = m_temporalFilterDateTime; 
     279 
     280                  ICompositeFilter compositeFilter = new CompositeFilterClass(); 
     281                  compositeFilter.AddFilter((IFilter)m_screenFilter); 
     282                  compositeFilter.AddFilter((IFilter)temporalFilter); 
     283 
     284                  set.Filter = (IFilter)compositeFilter; 
     285                  m_renderer.RenderDataSet(set); 
     286                  set.Filter = oldFilter; 
     287                  return; // drawing with filtering succeeded 
     288               } 
     289               catch (Exception ex) 
     290               { 
     291                  LoggingUtils.TraceMessage("Drawing with filtering failed (this may not be a problem): " + ex.Message); 
     292                  //filter didn't work; go on and draw everything 
     293               } 
     294 
     295               try 
     296               { 
     297                  // since something went wrong before, we try to reset filtering on the data set 
     298                  if (bOldFilterValid) set.Filter = oldFilter; 
     299               } 
     300               catch (Exception ex) 
     301               { 
     302                  LoggingUtils.TraceMessage("Filter reset failed (this may not be a problem): " + ex.Message); 
     303               } 
     304            } 
     305 
     306            // If we get here, we didn't draw with filtering, so we draw without. 
     307 
     308            //render after traversing children - lowest node drawn first 
     309            m_renderer.RenderDataSet(set); 
     310         } 
     311         catch (Exception ex) 
     312         { 
     313            LoggingUtils.ReportError(ex); 
     314         } 
     315      } 
     316 
     317      public static IFvDataSource LoadDataSource(string connectString) 
     318      { 
     319         FvObjectRegistry registry = new FvObjectRegistryClass(); 
     320         IFvDataSource dataSource = registry.CreateDataSourceForConnectString(connectString, true); 
     321 
     322         IFileDataSource fileDataSource = dataSource as IFileDataSource; 
     323         if (fileDataSource != null) 
     324         { 
     325            fileDataSource.Open(connectString); 
     326         } 
     327         else 
     328         { 
     329            // HACK: shouldn't need special knowledge of WMS data source - registry should maybe open in this case??? 
     330            IWMSDataSource wmsDataSource = dataSource as IWMSDataSource; 
     331            if (wmsDataSource != null) 
     332            { 
     333               // see ConnectString on WmsInputForm for a description of the connect string for WMS 
     334               XmlDocument xDoc = new XmlDocument(); 
     335               xDoc.LoadXml(connectString); 
     336               XmlNode pwNode = xDoc.GetElementsByTagName("password")[0]; 
     337               XmlNode unNode = xDoc.GetElementsByTagName("user_name")[0]; 
     338               XmlNode urlNode = xDoc.GetElementsByTagName("URL")[0]; 
     339               string errors = ""; 
     340               if (urlNode.FirstChild != null) 
     341               { 
     342                  if (unNode.FirstChild != null && pwNode.FirstChild != null) 
     343                     errors = wmsDataSource.OpenWMS(urlNode.FirstChild.InnerText, unNode.FirstChild.InnerText, pwNode.FirstChild.InnerText); 
     344                  else 
     345                     errors = wmsDataSource.OpenWMS(urlNode.FirstChild.InnerText, null, null); 
     346               } 
     347               else 
     348               { 
     349                  string errorString = "Problem Opening WMS: no url available"; 
     350                  MessageBox.Show(errorString); 
     351                  throw new System.IO.FileNotFoundException(errorString + ":" + connectString); 
     352               } 
     353               if (errors != "") 
     354               { 
     355                  MessageBox.Show(errors, "Problem Opening WMS"); 
     356                  dataSource = null; 
     357               } 
     358            } 
     359         } 
     360 
     361         return dataSource; 
     362      } 
     363 
     364      #endregion 
     365 
     366      #region IFvOverlay Members 
     367 
     368      public object OverlayEventSink 
     369      { 
     370         set { m_displayChangeNotifyEvents = value as IDisplayChangeNotifyEvents; } 
     371      } 
     372 
     373      public void Initialize(Guid overlayDescGuid) 
     374      { 
     375         m_guid = overlayDescGuid; 
     376         IsOverlayVisible = 1; 
     377 
     378         if (!TreeContainer.Visible) 
     379         { 
     380            TreeContainer.Display(); 
     381         } 
     382      } 
     383 
     384      public int Terminate(int bCanAbortTermination) 
     385      { 
     386         // code here may be used for debugging memory leaks 
     387         //IUtilityMethods utilMethods = new UtilityMethodsClass(); 
     388         //object obj = utilMethods.GetLeakData(); 
     389 
     390         { 
     391            Tree.Unload(m_dataSource); 
     392            if (OverlayCount == 0) 
     393               TreeContainer.Hide(); 
     394 
     395            IFileDataSource fileDataSource = m_dataSource.Source as IFileDataSource; 
     396            if (fileDataSource != null) 
     397               fileDataSource.CloseFile(); 
     398 
     399            IFvInformationDialog dialog = new FvInformationDialogClass(); 
     400            if (dialog.CurrentInfoDlgCallback != null && dialog.CurrentInfoDlgCallback.Equals(this)) 
     401               dialog.CloseDialog(); 
     402 
     403            m_dataSource = null; 
     404            m_screenFilter = null; 
     405            m_symbolFactory = null; 
     406            m_renderer = null; 
     407         } 
     408 
     409         System.GC.Collect(); // for easier unmanaged memory leak debugging 
     410 
     411         //obj = utilMethods.GetLeakData(); 
     412         return 0; 
     413      } 
     414 
     415      public int IsOverlayVisible 
     416      { 
     417         get 
     418         { 
     419            return m_isVisible ? 1 : 0; 
     420         } 
     421         set 
     422         { 
     423            m_isVisible = value == 0 ? false : true; 
     424         } 
     425      } 
     426 
     427      public Guid OverlayDescGuid 
     428      { 
     429         get { return m_guid; } 
     430      } 
     431 
     432      #endregion 
     433 
     434      #region IFvOverlayContextMenu Members 
     435 
     436      public void AppendMenuItems(IFvContextMenu pContextMenu, IFvMapView pMapView, int x, int y) 
     437      { 
     438         AppendToggleTreeMenuItem(pContextMenu); 
     439 
     440         AppendGetFeatureInfoMenuItem(pContextMenu, pMapView, x, y); 
     441      } 
     442 
     443      #endregion 
     444 
     445      #region IFvOverlayRenderer Members 
     446 
     447      public void OnDraw(IFvMapView pMapView, object pActiveMap) 
     448      { 
     449         if (m_renderer == null) 
     450         { 
     451            //not yet initialized 
     452            return; 
     453         } 
     454 
     455         try 
     456         { 
     457            IActiveMapProj proj = pActiveMap as IActiveMapProj; 
    215458            try 
    216459            { 
    217                 (featureDataSet as IFvDataSet).Filter = locationFilter; 
     460               // apply a geometry filter 
     461               ISettableMapProj settableMapProj; 
     462               proj.GetSettableMapProj(out settableMapProj); 
     463 
     464               double upperLat, lowerLat; 
     465               double leftLon, rightLon; 
     466               int result; 
     467               settableMapProj.get_vmap_bounds(out lowerLat, out leftLon, out upperLat, out rightLon, out result, VirtualSurfaceEnum.EQUALARC_VSURFACE); 
     468               LoggingUtils.Assert(result == 0, "get_vmap_bounds returned " + result); 
     469 
     470               if (leftLon > rightLon) 
     471               { 
     472                  // If we span the date line, translate the right boundary to be between 180 and 360 so that 
     473                  // the xmin and xmax in CreateByRectangle reflect the date line crossing. 
     474                  rightLon += 360; 
     475               } 
     476 
     477               if (upperLat != prevUpperLat || 
     478                   lowerLat != prevLowerLat || 
     479                   leftLon != prevLeftLon || 
     480                   rightLon != prevRightLon) 
     481               { 
     482                  m_screenFilter = new GeometryFilterClass(); 
     483                  m_screenFilter.CreateByRectangle(leftLon, lowerLat, rightLon, upperLat); 
     484                  prevUpperLat = upperLat; 
     485                  prevLowerLat = lowerLat; 
     486                  prevLeftLon = leftLon; 
     487                  prevRightLon = rightLon; 
     488                  m_resetFilter = true; 
     489               } 
     490 
     491               m_renderer.PrepareForRendering(proj, SymbolFactory); 
     492 
     493               //draw children 
     494               OnDraw(m_dataSource); 
     495 
    218496            } 
    219497            catch (Exception ex) 
    220498            { 
    221                 LoggingUtils.ReportError(ex); 
    222                 //filter didn't work, return empty set (better to return nothing than everything) 
    223                 return result; 
    224             } 
    225  
    226             for (int i = 0; i < featureDataSet.FeatureCount; i++) 
    227             { 
    228                 result.Add(featureDataSet.GetFeature(i)); 
    229             } 
    230  
    231             //since the first worked, we assume the second will work 
    232             (featureDataSet as IFvDataSet).Filter = originalFilter; 
    233  
    234             return result; 
    235         } 
    236  
    237         protected void OnDraw(TreeNode parentNode) 
    238         { 
    239            //using (new Profiler("GeodataOverlay.OnDraw")) // comment out except when performance testing 
    240            { 
    241               // global hold on refreshing tree during drawing 
    242               bool bOriginalHoldValue = DataSourceTree.DataSourceCallbackHandler.HoldDataSourceChangedCallbacks; 
    243               DataSourceTree.DataSourceCallbackHandler.HoldDataSourceChangedCallbacks = true; 
    244  
    245               try 
    246               { 
    247                  //traverse children backwards - lowest node drawn first 
    248                  for (int i = parentNode.Nodes.Count; i > 0; i--) 
    249                  { 
    250                     TreeNode node = parentNode.Nodes[i - 1]; 
    251                     if (node.Checked) 
    252                     { 
    253                        if (node is FvDataTreeNode) 
    254                        { 
    255                           //render after traversing children - lowest node drawn first 
    256                           OnDraw(node); 
    257  
    258                           IFvDataSet set = (node as FvDataTreeNode).Set; 
    259                           if (set != null) 
    260                           { 
    261                              OnDraw(set); 
    262                           } 
    263                        } 
    264                     } 
    265                  } 
    266               } 
    267               finally 
    268               { 
    269                  DataSourceTree.DataSourceCallbackHandler.HoldDataSourceChangedCallbacks = bOriginalHoldValue; 
    270               } 
    271            } 
    272         } 
    273  
    274        protected void OnDraw(IFvDataSet set) 
    275        { 
    276           try 
    277           { 
    278              // try first to draw with filtering (if the filter was reset) 
    279  
    280              if (m_resetFilter) 
    281              { 
    282                 IFilter oldFilter = null; 
    283                 bool bOldFilterValid = false; 
    284  
    285                 try 
    286                 { 
    287                    // a composite filter will filter both time and space 
    288  
    289                    oldFilter = set.Filter; 
    290                    bOldFilterValid = true; 
    291  
    292                    ITemporalFilter temporalFilter = new TemporalFilterClass(); 
    293                    temporalFilter.Start = m_temporalFilterDateTime; 
    294                    temporalFilter.End = m_temporalFilterDateTime; 
    295  
    296                    ICompositeFilter compositeFilter = new CompositeFilterClass(); 
    297                    compositeFilter.AddFilter((IFilter)m_screenFilter); 
    298                    compositeFilter.AddFilter((IFilter)temporalFilter); 
    299  
    300                    set.Filter = (IFilter)compositeFilter; 
    301                    m_renderer.RenderDataSet(set); 
    302                    set.Filter = oldFilter; 
    303                    return; // drawing with filtering succeeded 
    304                 } 
    305                 catch (Exception ex) 
    306                 { 
    307                    LoggingUtils.TraceMessage("Drawing with filtering failed (this may not be a problem): " + ex.Message); 
    308                    //filter didn't work; go on and draw everything 
    309                 } 
    310  
    311                 try 
    312                 { 
    313                    // since something went wrong before, we try to reset filtering on the data set 
    314                    if (bOldFilterValid) set.Filter = oldFilter; 
    315                 } 
    316                 catch (Exception ex) 
    317                 { 
    318                    LoggingUtils.TraceMessage("Filter reset failed (this may not be a problem): " + ex.Message); 
    319                 } 
    320              } 
    321  
    322              // If we get here, we didn't draw with filtering, so we draw without. 
    323  
    324              //render after traversing children - lowest node drawn first 
    325              m_renderer.RenderDataSet(set); 
    326           } 
    327           catch (Exception ex) 
    328           { 
    329              LoggingUtils.ReportError(ex); 
    330           } 
    331        } 
    332  
    333         public static IFvDataSource LoadDataSource(string connectString) 
    334         { 
     499               LoggingUtils.ReportError(ex); 
     500            } 
     501            finally 
     502            { 
     503               m_renderer.BreakdownAfterRendering(); 
     504            } 
     505         } 
     506         catch (Exception ex) 
     507         { 
     508            LoggingUtils.ReportError(ex); 
     509         } 
     510      } 
     511 
     512      #endregion 
     513 
     514      #region IFvOverlayPersistence Members 
     515 
     516      // Fon now just check if a file ending in .SLD exists in the same directory 
     517      // in the future we might get this from overlay options. 
     518      private Boolean checkForSLD(string dataSourceSpec, out string sldFileSpec) 
     519      { 
     520         char[] dot = new char[] { '.' }; 
     521         sldFileSpec = dataSourceSpec.Substring(0, dataSourceSpec.LastIndexOfAny(dot)) + ".sld"; 
     522         return System.IO.File.Exists(sldFileSpec); 
     523      } 
     524 
     525      public void FileNew() 
     526      { 
     527         m_fileSpec = "Geodata Overlay"; 
     528      } 
     529 
     530      public void FileOpen(string fileSpecification) 
     531      { 
     532         try 
     533         { 
     534            IFvDataSource dataSource = LoadDataSource(fileSpecification); 
     535            if (dataSource == null) 
     536               throw new System.IO.FileNotFoundException("Failed to create data source:" + fileSpecification); 
     537 
     538            if (dataSource.Name != null && dataSource.Name.Length > 0) 
     539               m_fileSpec = dataSource.Name; 
     540 
     541            bool copyToMemory = false; 
     542            string SLDFileSpec = null; 
     543            m_renderer = null; 
     544 
     545            if (dataSource is IFileDataSource) 
     546            { 
     547               if (checkForSLD(fileSpecification, out SLDFileSpec)) 
     548               { 
     549                  SLDRenderer sldRenderer = new SLDRenderer(); 
     550                  sldRenderer.LoadSLD(SLDFileSpec); 
     551                  m_renderer = sldRenderer; 
     552                  copyToMemory = true; 
     553               } 
     554            } 
     555 
     556            if (m_renderer == null) 
     557            { 
     558               IFvObjectRegistry registry = new FvObjectRegistryClass(); 
     559               m_renderer = registry.CreateRendererForDataSource(dataSource); 
     560            } 
     561 
     562            // if the data set is not an OGR Dataset, copy it to an OGR Memory dataset 
     563            // kml data sources don't support attribute filter, but sld renderer needs it 
     564            // ogr memory data sources do support this filter 
     565            if (copyToMemory && !(dataSource is IFvOGRDataSource)) 
     566            { 
     567               FvOGRDataSource MemDS = new FvOGRDataSourceClass(); 
     568               IFvDataSourceEdit MemDSEdit = MemDS as IFvDataSourceEdit; 
     569               MemDSEdit.StartEditing(); 
     570               MemDS.CreateMemoryDataSource(); 
     571               MemDSEdit.CopyDataSource((IFvDataSource)dataSource); 
     572               MemDSEdit.FinishEditing(); 
     573               if (dataSource is IFileDataSource) 
     574               { 
     575                  (dataSource as IFileDataSource).CloseFile(); 
     576               } 
     577               dataSource = MemDS as IFvDataSource; 
     578            } 
     579 
     580            m_dataSource = Tree.AddDataSource(dataSource); 
     581 
     582            SymbolFactory = m_dataSource.Source as ISymbolFactory; 
     583            if (SymbolFactory == null) 
     584            { 
     585               SymbolFactory = new DefaultSymbolFactory(); 
     586            } 
     587 
     588            Tree.OnTreeNodeRefreshed += new DataSourceTree.TreeNodeRefreshed(Tree_OnTreeNodeRefreshed); 
     589         } 
     590         catch (Exception ex) 
     591         { 
     592            LoggingUtils.ReportError(ex); 
     593            MessageBox.Show( 
     594               "There was a problem opening this data source.  More information may be found in the FalconView error log.\n\nDETAILS:\n\n" + ex.Message, 
     595               "Problem Opening Data Source", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 
     596            Terminate(0); 
     597            throw (ex); 
     598         } 
     599      } 
     600 
     601      void Tree_OnTreeNodeRefreshed(object sender, FvDataTreeNode oldNode, FvDataTreeNode newNode) 
     602      { 
     603         if (m_dataSource == oldNode) m_dataSource = newNode; 
     604         new fvw.LayerClass().Refresh(-1); // refresh FalconView 
     605      } 
     606 
     607      public void FileSaveAs(string fileSpecification, int nSaveFormat) 
     608      { 
     609         try 
     610         { 
     611            if (m_dataSource.Source == null) 
     612               throw new Exception("no data source to save"); 
     613 
    335614            FvObjectRegistry registry = new FvObjectRegistryClass(); 
    336             IFvDataSource dataSource = registry.CreateDataSourceForConnectString(connectString, true); 
    337  
    338             IFileDataSource fileDataSource = dataSource as IFileDataSource; 
    339             if (fileDataSource != null) 
    340             { 
    341                 fileDataSource.Open(connectString); 
    342             } 
    343             else 
    344             { 
    345                // HACK: shouldn't need special knowledge of WMS data source - registry should maybe open in this case??? 
    346                IWMSDataSource wmsDataSource = dataSource as IWMSDataSource; 
    347                if (wmsDataSource != null) 
    348                { 
    349                   // see ConnectString on WmsInputForm for a description of the connect string for WMS 
    350                   XmlDocument xDoc = new XmlDocument(); 
    351                   xDoc.LoadXml(connectString); 
    352                   XmlNode pwNode = xDoc.GetElementsByTagName("password")[0]; 
    353                   XmlNode unNode = xDoc.GetElementsByTagName("user_name")[0]; 
    354                   XmlNode urlNode = xDoc.GetElementsByTagName("URL")[0]; 
    355                   string errors = ""; 
    356                   if (urlNode.FirstChild != null) 
    357                   { 
    358                       if (unNode.FirstChild != null && pwNode.FirstChild != null) 
    359                           errors = wmsDataSource.OpenWMS(urlNode.FirstChild.InnerText, unNode.FirstChild.InnerText, pwNode.FirstChild.InnerText); 
    360                       else 
    361                           errors = wmsDataSource.OpenWMS(urlNode.FirstChild.InnerText, null, null); 
    362                   } 
    363                   else 
    364                   { 
    365                       string errorString = "Problem Opening WMS: no url available"; 
    366                       MessageBox.Show(errorString); 
    367                       throw new System.IO.FileNotFoundException(errorString + ":" + connectString); 
    368                   } 
    369                   if (errors != "") 
    370                   { 
    371                       MessageBox.Show(errors, "Problem Opening WMS"); 
    372                       dataSource = null; 
    373                   } 
    374                } 
    375             } 
    376  
    377             return dataSource; 
    378         } 
    379  
    380         void Tree_AfterCheck(object sender, TreeViewEventArgs e) 
    381         { 
    382             Layer.Refresh(-1); 
    383         } 
    384  
    385         #endregion 
    386  
    387         #region IFvOverlay Members 
    388  
    389         public object OverlayEventSink 
    390         { 
    391             set 
    392             { 
    393                 m_displayChangeNotifyEvents = (IDisplayChangeNotifyEvents)value; 
    394             } 
    395         } 
    396  
    397         public void Initialize(Guid overlayDescGuid) 
    398         { 
    399             m_guid = overlayDescGuid; 
    400             IsOverlayVisible = 1; 
    401  
    402             if (!TreeContainer.Visible) 
    403             { 
    404                 TreeContainer.Display(); 
    405             } 
    406         } 
    407  
    408         public int Terminate(int bCanAbortTermination) 
    409         { 
    410            // code here may be used for debugging memory leaks 
    411            //IUtilityMethods utilMethods = new UtilityMethodsClass(); 
    412            //object obj = utilMethods.GetLeakData(); 
    413  
    414            { 
    415               Tree.Tree.AfterCheck -= m_clickHandler; 
    416               Tree.Unload(m_dataSource); 
    417               if (OverlayCount == 0) 
    418                  TreeContainer.Hide(); 
    419  
    420               IFileDataSource fileDataSource = m_dataSource.Source as IFileDataSource; 
    421               if (fileDataSource != null) 
    422                  fileDataSource.CloseFile(); 
    423  
    424               IFvInformationDialog dialog = new FvInformationDialogClass(); 
    425               if (dialog.CurrentInfoDlgCallback != null && dialog.CurrentInfoDlgCallback.Equals(this)) 
    426                  dialog.CloseDialog(); 
    427  
    428               m_dataSource = null; 
    429               m_screenFilter = null; 
    430               m_symbolFactory = null; 
    431               m_renderer = null; 
    432            } 
    433  
    434            System.GC.Collect(); // for easier unmanaged memory leak debugging 
    435  
    436            //obj = utilMethods.GetLeakData(); 
    437            return 0; 
    438         } 
    439  
    440         public int IsOverlayVisible 
    441         { 
    442             get 
    443             { 
    444                 return m_isVisible ? 1 : 0; 
    445             } 
    446             set 
    447             { 
    448                 m_isVisible = value == 0 ? false : true; 
    449             } 
    450         } 
    451  
    452         public Guid OverlayDescGuid 
    453         { 
    454             get { return m_guid; } 
    455         } 
    456  
    457         #endregion 
    458  
    459         #region IFvOverlayContextMenu Members 
    460  
    461         public void AppendMenuItems(IFvContextMenu pContextMenu, IFvMapView pMapView, int x, int y) 
    462         { 
    463             AppendToggleTreeMenuItem(pContextMenu); 
    464  
    465             AppendGetFeatureInfoMenuItem(pContextMenu, pMapView, x, y); 
    466         } 
    467  
    468         #endregion 
    469  
    470         #region IFvOverlayRenderer Members 
    471  
    472         public void OnDraw(IFvMapView pMapView, object pActiveMap) 
    473         { 
    474             if (m_renderer == null) 
    475             { 
    476                 //not yet initialized 
    477                 return; 
    478             } 
     615 
     616            IFileDataSource fileDataSource = (IFileDataSource)registry.CreateDataSourceForConnectString(fileSpecification, false); 
     617            IFvDataSourceEdit editDataSource = fileDataSource as IFvDataSourceEdit; 
     618            if (editDataSource == null) 
     619            { 
     620               throw new Exception("Saving to this file format is not supported"); 
     621            } 
     622 
     623            editDataSource.StartEditing(); 
     624            fileDataSource.CreateNewFile(fileSpecification); 
     625            editDataSource.CopyDataSource((IFvDataSource)m_dataSource.Source); 
     626            editDataSource.FinishEditing(); 
     627            fileDataSource.CloseFile(); 
     628         } 
     629         catch (Exception ex) 
     630         { 
     631            LoggingUtils.ReportError(ex); 
     632         } 
     633      } 
     634 
     635      public int HasBeenSaved 
     636      { 
     637         get 
     638         { 
     639            //we never edit 
     640            return m_saved ? 1 : 0; 
     641         } 
     642         set 
     643         { 
     644            m_saved = value == 0 ? false : true; 
     645         } 
     646      } 
     647 
     648      public int IsDirty 
     649      { 
     650         get 
     651         { 
     652            //we never edit 
     653            return m_dirty ? 1 : 0; 
     654         } 
     655         set 
     656         { 
     657            m_dirty = value == 0 ? false : true; 
     658         } 
     659      } 
     660 
     661      public int IsReadOnly 
     662      { 
     663         get 
     664         { 
     665            //we never edit 
     666            return m_readOnly ? 1 : 0; 
     667         } 
     668         set 
     669         { 
     670            m_readOnly = value == 0 ? false : true; 
     671         } 
     672      } 
     673 
     674      public string FileSpecification 
     675      { 
     676         get { return m_fileSpec; } 
     677      } 
     678 
     679      #endregion 
     680 
     681      #region IFvInformationDialogCallback Members 
     682 
     683      public void InfoDialogOwnerChanged() 
     684      { 
     685      } 
     686 
     687      #endregion 
     688 
     689      #region IFvPlaybackEventsObserver Members 
     690 
     691      public void OnPlaybackRateChanged(IFvMapView pMapView, int lNewPlaybackRate) 
     692      { 
     693      } 
     694 
     695      public void OnPlaybackStarted(IFvMapView pMapView) 
     696      { 
     697      } 
     698 
     699      public void OnPlaybackStopped(IFvMapView pMapView) 
     700      { 
     701      } 
     702 
     703      public void OnPlaybackTimeChanged(IFvMapView pMapView, DateTime dateCurrentTime) 
     704      { 
     705         // TODO: Don't invalidate every time, if possible.  Problem is that we don't know when data sets 
     706         // may change based on temporal filter changes. 
     707         new fvw.LayerClass().Refresh(-1); // refresh FalconView 
     708         m_temporalFilterDateTime = dateCurrentTime; 
     709      } 
     710 
     711      #endregion 
     712 
     713      private TimeInterval GetBoundingTimeIntervalForNodeData(TreeNode node) 
     714      { 
     715         // This method returns a time interval based on the max and min ends of every time interval of every checked node. 
     716         // Nodes with no time interval and unbounded ends of time intervals are ignored.  If no bounded time interval can 
     717         // be constructed, it returns an invalid time interval, though it does set the ends to any outer bounds it finds. 
     718 
     719         TimeInterval timeInterval = new TimeInterval(); 
     720         timeInterval.dtBegin = DateTime.MinValue; // no bound found (important for recursion) 
     721         timeInterval.dtEnd = DateTime.MaxValue; // no bound found (important for recursion) 
     722 
     723         // find any bounds of this node 
     724         FvDataTreeNode fvDataTreeNode = node as FvDataTreeNode; 
     725         if (fvDataTreeNode != null) 
     726         { 
     727            IFvTemporalDataSet temporalDataSet = fvDataTreeNode.Set as IFvTemporalDataSet; 
     728            if (node.Checked && temporalDataSet != null) 
     729            { 
     730               if (temporalDataSet.HasStart) 
     731                  timeInterval.dtBegin = temporalDataSet.Start; 
     732               if (temporalDataSet.HasEnd) 
     733                  timeInterval.dtEnd = temporalDataSet.End; 
     734            } 
     735         } 
     736 
     737         // if the any child has a broader (but bounded!) time interval, shift the begin and/or end of the interval to be returned 
     738         foreach (TreeNode treeNode in node.Nodes) 
     739         { 
     740            TimeInterval childTimeInterval = GetBoundingTimeIntervalForNodeData(treeNode); 
     741            if (childTimeInterval.dtBegin > DateTime.MinValue && (timeInterval.dtBegin == DateTime.MinValue || childTimeInterval.dtBegin < timeInterval.dtBegin)) 
     742               timeInterval.dtBegin = childTimeInterval.dtBegin; 
     743            if (childTimeInterval.dtEnd < DateTime.MaxValue && (timeInterval.dtEnd == DateTime.MaxValue || childTimeInterval.dtEnd > timeInterval.dtEnd)) 
     744               timeInterval.dtEnd = childTimeInterval.dtEnd; 
     745         } 
     746 
     747         // valid if we found bounds on both ends 
     748         timeInterval.bTimeIntervalValid = timeInterval.dtBegin > DateTime.MinValue && timeInterval.dtEnd < DateTime.MaxValue ? 1 : 0; 
     749 
     750         return timeInterval; 
     751      } 
     752 
     753      #region IFvPlaybackTimeInterval Members 
     754 
     755      public uint GanntChartColor 
     756      { 
     757         get { return 0x0000ffff; } 
     758      } 
     759 
     760      public TimeInterval PlaybackTimeInterval 
     761      { 
     762         get 
     763         { 
     764            TimeInterval timeInterval; 
    479765 
    480766            try 
    481767            { 
    482                 IActiveMapProj proj = pActiveMap as IActiveMapProj; 
    483                 try 
    484                 { 
    485                     // apply a geometry filter 
    486                     ISettableMapProj settableMapProj; 
    487                     proj.GetSettableMapProj(out settableMapProj); 
    488  
    489                     double upperLat, lowerLat; 
    490                     double leftLon, rightLon; 
    491                     int result; 
    492                     settableMapProj.get_vmap_bounds(out lowerLat, out leftLon, out upperLat, out rightLon, out result, VirtualSurfaceEnum.EQUALARC_VSURFACE); 
    493                     LoggingUtils.Assert(result == 0, "get_vmap_bounds returned " + result); 
    494  
    495                     if (leftLon > rightLon) 
    496                     { 
    497                        // If we span the date line, translate the right boundary to be between 180 and 360 so that 
    498                        // the xmin and xmax in CreateByRectangle reflect the date line crossing. 
    499                        rightLon += 360; 
    500                     } 
    501  
    502                     if (upperLat != prevUpperLat || 
    503                         lowerLat != prevLowerLat || 
    504                         leftLon != prevLeftLon || 
    505                         rightLon != prevRightLon) 
    506                     { 
    507                         m_screenFilter = new GeometryFilterClass(); 
    508                         m_screenFilter.CreateByRectangle(leftLon, lowerLat, rightLon, upperLat); 
    509                         prevUpperLat = upperLat; 
    510                         prevLowerLat = lowerLat; 
    511                         prevLeftLon = leftLon; 
    512                         prevRightLon = rightLon; 
    513                         m_resetFilter = true; 
    514                     } 
    515  
    516                     m_renderer.PrepareForRendering(proj, SymbolFactory); 
    517  
    518                     //draw children 
    519                     OnDraw(m_dataSource); 
    520  
    521                 } 
    522                 catch (Exception ex) 
    523                 { 
    524                    LoggingUtils.ReportError(ex); 
    525                 } 
    526                 finally 
    527                 { 
    528                     m_renderer.BreakdownAfterRendering(); 
    529                 } 
     768               if (m_dataSource != null) 
     769                  return GetBoundingTimeIntervalForNodeData(m_dataSource); 
    530770            } 
    531771            catch (Exception ex) 
    532772            { 
    533                 LoggingUtils.ReportError(ex); 
    534             } 
    535         } 
    536  
    537         #endregion 
    538  
    539         #region IFvOverlayPersistence Members 
    540  
    541         // Fon now just check if a file ending in .SLD exists in the same directory 
    542         // in the future we might get this from overlay options. 
    543         private Boolean checkForSLD(string dataSourceSpec, out string sldFileSpec) 
    544         { 
    545             char[] dot = new char[] { '.' }; 
    546             sldFileSpec = dataSourceSpec.Substring(0, dataSourceSpec.LastIndexOfAny(dot)) + ".sld"; 
    547             return System.IO.File.Exists(sldFileSpec); 
    548         } 
    549  
    550         public void FileNew() 
    551         { 
    552            m_fileSpec = "Geodata Overlay"; 
    553         } 
    554  
    555         public void FileOpen(string fileSpecification) 
    556         { 
    557             try 
    558             { 
    559                 IFvDataSource dataSource = LoadDataSource(fileSpecification); 
    560                 if (dataSource == null) 
    561                     throw new System.IO.FileNotFoundException("Failed to create data source:" + fileSpecification); 
    562  
    563                 if (dataSource.Name != null && dataSource.Name.Length > 0) 
    564                     m_fileSpec = dataSource.Name; 
    565  
    566                 bool copyToMemory = false; 
    567                 string SLDFileSpec = null; 
    568                 m_renderer = null; 
    569  
    570                 if (dataSource is IFileDataSource) 
    571                 { 
    572                    if (checkForSLD(fileSpecification, out SLDFileSpec)) 
    573                    { 
    574                       SLDRenderer sldRenderer = new SLDRenderer(); 
    575                       sldRenderer.LoadSLD(SLDFileSpec); 
    576                       m_renderer = sldRenderer; 
    577                       copyToMemory = true; 
    578                    } 
    579                 } 
    580  
    581                 if (m_renderer == null) 
    582                 { 
    583                    IFvObjectRegistry registry = new FvObjectRegistryClass(); 
    584                    m_renderer = registry.CreateRendererForDataSource(dataSource); 
    585                 } 
    586  
    587                 // if the data set is not an OGR Dataset, copy it to an OGR Memory dataset 
    588                 // kml data sources don't support attribute filter, but sld renderer needs it 
    589                 // ogr memory data sources do support this filter 
    590                 if (copyToMemory && !(dataSource is IFvOGRDataSource)) 
    591                 { 
    592                     FvOGRDataSource MemDS = new FvOGRDataSourceClass(); 
    593                     IFvDataSourceEdit MemDSEdit = MemDS as IFvDataSourceEdit; 
    594                     MemDSEdit.StartEditing(); 
    595                     MemDS.CreateMemoryDataSource(); 
    596                     MemDSEdit.CopyDataSource((IFvDataSource)dataSource); 
    597                     MemDSEdit.FinishEditing(); 
    598                     if (dataSource is IFileDataSource) 
    599                     { 
    600                         (dataSource as IFileDataSource).CloseFile(); 
    601                     } 
    602                     dataSource = MemDS as IFvDataSource; 
    603                 } 
    604  
    605                 m_dataSource = Tree.AddDataSource(dataSource); 
    606  
    607                 Tree.Tree.AfterCheck += m_clickHandler; 
    608                 SymbolFactory = m_dataSource.Source as ISymbolFactory; 
    609                 if (SymbolFactory == null) 
    610                 { 
    611                     SymbolFactory = new DefaultSymbolFactory(); 
    612                 } 
    613  
    614                 Tree.OnTreeNodeRefreshed += new DataSourceTree.TreeNodeRefreshed(Tree_OnTreeNodeRefreshed); 
    615             } 
    616             catch (Exception ex) 
    617             { 
    618                LoggingUtils.ReportError(ex); 
    619                MessageBox.Show( 
    620                   "There was a problem opening this data source.  More information may be found in the FalconView error log.\n\nDETAILS:\n\n" + ex.Message, 
    621                   "Problem Opening Data Source", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 
    622                 Terminate(0); 
    623                 throw (ex); 
    624             } 
    625         } 
    626  
    627         void Tree_OnTreeNodeRefreshed(object sender, FvDataTreeNode oldNode, FvDataTreeNode newNode) 
    628         { 
    629            if (m_dataSource == oldNode) m_dataSource = newNode; 
    630            new fvw.LayerClass().Refresh(-1); // refresh FalconView 
    631         } 
    632  
    633         public void FileSaveAs(string fileSpecification, int nSaveFormat) 
    634         { 
    635             try 
    636             { 
    637                if (m_dataSource.Source == null) 
    638                   throw new Exception("no data source to save"); 
    639  
    640                FvObjectRegistry registry = new FvObjectRegistryClass(); 
    641  
    642                IFileDataSource fileDataSource = (IFileDataSource)registry.CreateDataSourceForConnectString(fileSpecification, false); 
    643                IFvDataSourceEdit editDataSource = fileDataSource as IFvDataSourceEdit; 
    644                if (editDataSource == null) 
    645                { 
    646                   throw new Exception("Saving to this file format is not supported"); 
    647                } 
    648  
    649                editDataSource.StartEditing(); 
    650                fileDataSource.CreateNewFile(fileSpecification); 
    651                editDataSource.CopyDataSource((IFvDataSource)m_dataSource.Source); 
    652                editDataSource.FinishEditing(); 
    653                fileDataSource.CloseFile(); 
    654             } 
    655             catch (Exception ex) 
    656             { 
    657                 LoggingUtils.ReportError(ex); 
    658             } 
    659         } 
    660  
    661         public int HasBeenSaved 
    662         { 
    663             get 
    664             { 
    665                 //we never edit 
    666                 return m_saved ? 1 : 0; 
    667             } 
    668             set 
    669             { 
    670                 m_saved = value == 0 ? false : true; 
    671             } 
    672         } 
    673  
    674         public int IsDirty 
    675         { 
    676             get 
    677             { 
    678                 //we never edit 
    679                 return m_dirty ? 1 : 0; 
    680             } 
    681             set 
    682             { 
    683                 m_dirty = value == 0 ? false : true; 
    684             } 
    685         } 
    686  
    687         public int IsReadOnly 
    688         { 
    689             get 
    690             { 
    691                 //we never edit 
    692                 return m_readOnly ? 1 : 0; 
    693             } 
    694             set 
    695             { 
    696                 m_readOnly = value == 0 ? false : true; 
    697             } 
    698         } 
    699  
    700         public string FileSpecification 
    701         { 
    702             get { return m_fileSpec; } 
    703         } 
    704  
    705         #endregion 
    706  
    707         #region IFvInformationDialogCallback Members 
    708  
    709         public void InfoDialogOwnerChanged() 
    710         { 
    711         } 
    712  
    713         #endregion 
    714  
    715         #region IFvPlaybackEventsObserver Members 
    716  
    717         public void OnPlaybackRateChanged(IFvMapView pMapView, int lNewPlaybackRate) 
    718         { 
    719         } 
    720  
    721         public void OnPlaybackStarted(IFvMapView pMapView) 
    722         { 
    723         } 
    724  
    725         public void OnPlaybackStopped(IFvMapView pMapView) 
    726         { 
    727         } 
    728  
    729         public void OnPlaybackTimeChanged(IFvMapView pMapView, DateTime dateCurrentTime) 
    730         { 
    731            // TODO: Don't invalidate every time, if possible.  Problem is that we don't know when data sets 
    732            // may change based on temporal filter changes. 
    733            m_displayChangeNotifyEvents.InvalidateOverlay(); 
    734            m_temporalFilterDateTime = dateCurrentTime; 
    735         } 
    736  
    737         #endregion 
    738  
    739         private TimeInterval GetBoundingTimeIntervalForNodeData(TreeNode node) 
    740         { 
    741            // This method returns a time interval based on the max and min ends of every time interval of every checked node. 
    742            // Nodes with no time interval and unbounded ends of time intervals are ignored.  If no bounded time interval can 
    743            // be constructed, it returns an invalid time interval, though it does set the ends to any outer bounds it finds. 
    744  
    745            TimeInterval timeInterval = new TimeInterval(); 
    746            timeInterval.dtBegin = DateTime.MinValue; // no bound found (important for recursion) 
    747            timeInterval.dtEnd = DateTime.MaxValue; // no bound found (important for recursion) 
    748  
    749            // find any bounds of this node 
    750            FvDataTreeNode fvDataTreeNode = node as FvDataTreeNode; 
    751            if (fvDataTreeNode != null) 
    752            { 
    753               IFvTemporalDataSet temporalDataSet = fvDataTreeNode.Set as IFvTemporalDataSet; 
    754               if (node.Checked && temporalDataSet != null) 
    755               { 
    756                  if (temporalDataSet.HasStart) 
    757                     timeInterval.dtBegin = temporalDataSet.Start; 
    758                  if (temporalDataSet.HasEnd) 
    759                     timeInterval.dtEnd = temporalDataSet.End; 
    760               } 
    761            } 
    762  
    763            // if the any child has a broader (but bounded!) time interval, shift the begin and/or end of the interval to be returned 
    764            foreach (TreeNode treeNode in node.Nodes) 
    765            { 
    766               TimeInterval childTimeInterval = GetBoundingTimeIntervalForNodeData(treeNode); 
    767               if (childTimeInterval.dtBegin > DateTime.MinValue && (timeInterval.dtBegin == DateTime.MinValue || childTimeInterval.dtBegin < timeInterval.dtBegin)) 
    768                  timeInterval.dtBegin = childTimeInterval.dtBegin; 
    769               if (childTimeInterval.dtEnd < DateTime.MaxValue && (timeInterval.dtEnd == DateTime.MaxValue || childTimeInterval.dtEnd > timeInterval.dtEnd)) 
    770                  timeInterval.dtEnd = childTimeInterval.dtEnd; 
    771            } 
    772  
    773            // valid if we found bounds on both ends 
    774            timeInterval.bTimeIntervalValid = timeInterval.dtBegin > DateTime.MinValue && timeInterval.dtEnd < DateTime.MaxValue ? 1 : 0; 
    775  
    776            return timeInterval; 
    777         } 
    778  
    779         #region IFvPlaybackTimeInterval Members 
    780  
    781         public uint GanntChartColor 
    782         { 
    783            get { return 0x0000ffff; } 
    784         } 
    785  
    786         public TimeInterval PlaybackTimeInterval 
    787         { 
    788            get 
    789            { 
    790               TimeInterval timeInterval; 
    791  
    792               try 
    793               { 
    794                  if (m_dataSource != null) 
    795                     return GetBoundingTimeIntervalForNodeData(m_dataSource); 
    796               } 
    797               catch (Exception ex) 
    798               { 
    799                  if (!(ex is NotImplementedException)) 
    800                     LoggingUtils.ReportError(ex); 
    801               } 
    802  
    803               timeInterval = new TimeInterval(); 
    804               timeInterval.bTimeIntervalValid = 0; 
    805               return timeInterval; 
    806            } 
    807         } 
    808  
    809         #endregion 
    810      } 
    811  
    812     public class ToggleTreeMenuItem : IFvContextMenuItem 
    813     { 
    814         private IUserControlContainer m_control; 
    815  
    816         public ToggleTreeMenuItem(IUserControlContainer control) 
    817         { 
    818             m_control = control; 
    819         } 
    820  
    821         #region IFvContextMenuItem Members 
    822  
    823         public int MenuItemChecked 
    824         { 
    825             get 
    826             { 
    827                 return 0; 
    828             } 
    829         } 
    830  
    831         public int MenuItemEnabled 
    832         { 
    833             get 
    834             { 
    835                 return 1; 
    836             } 
    837         } 
    838  
    839         public string MenuItemName 
    840         { 
    841             get 
    842             { 
    843                 if (m_control.Visible) 
    844                 { 
    845                     return "Hide Tree Control"; 
    846                 } 
    847                 return "Display Tree Control"; 
    848             } 
    849         } 
    850  
    851         public void MenuItemSelected() 
    852         { 
     773               if (!(ex is NotImplementedException)) 
     774                  LoggingUtils.ReportError(ex); 
     775            } 
     776 
     777            timeInterval = new TimeInterval(); 
     778            timeInterval.bTimeIntervalValid = 0; 
     779            return timeInterval; 
     780         } 
     781      } 
     782 
     783      #endregion 
     784   } 
     785 
     786   public class ToggleTreeMenuItem : IFvContextMenuItem 
     787   { 
     788      private IUserControlContainer m_control; 
     789 
     790      public ToggleTreeMenuItem(IUserControlContainer control) 
     791      { 
     792         m_control = control; 
     793      } 
     794 
     795      #region IFvContextMenuItem Members 
     796 
     797      public int MenuItemChecked 
     798      { 
     799         get 
     800         { 
     801            return 0; 
     802         } 
     803      } 
     804 
     805      public int MenuItemEnabled 
     806      { 
     807         get 
     808         { 
     809            return 1; 
     810         } 
     811      } 
     812 
     813      public string MenuItemName 
     814      { 
     815         get 
     816         { 
    853817            if (m_control.Visible) 
    854818            { 
    855                 m_control.Hide(); 
    856             } 
    857             else 
    858             { 
    859                 m_control.Display(); 
    860             } 
    861         } 
    862  
    863         #endregion 
    864     } 
    865  
    866     public class ShowInfo : IFvContextMenuItem 
    867     { 
    868         private List<IFeature> m_list; 
    869         private IFvInformationDialogCallback m_callback; 
    870  
    871         public ShowInfo(List<IFeature> list, IFvInformationDialogCallback callback) 
    872         { 
    873             m_list = list; 
    874             m_callback = callback; 
    875         } 
    876  
    877         #region IFvContextMenuItem Members 
    878  
    879         public int MenuItemChecked 
    880         { 
    881             get 
    882             { 
    883                 return 0; 
    884             } 
    885         } 
    886  
    887         public int MenuItemEnabled 
    888         { 
    889             get 
    890             { 
    891                 return 1; 
    892             } 
    893         } 
    894  
    895         public string MenuItemName 
    896         { 
    897             get 
    898             { 
    899                 return "Get Feature Info..."; 
    900             } 
    901         } 
    902  
    903         public void MenuItemSelected() 
    904         { 
    905             FvInformationDialog dialog = new FvInformationDialogClass(); 
    906  
    907             //build a string from the features 
    908             string informationString = ""; 
    909             foreach (IFeature feature in m_list) 
    910             { 
    911                 string name = ""; 
    912                 string description = ""; 
    913                 string attributes = ""; 
    914                 for (int i = 0; i < feature.FieldCount; i++) 
    915                 { 
    916                     if (feature.GetFieldName(i).Equals("balloon_style_text")) 
    917                     { 
    918                         description = feature.GetFieldValue(i).ToString(); 
    919                     } 
    920                     else if (feature.GetFieldName(i).Equals("name")) 
    921                     { 
    922                         name = feature.GetFieldValue(i).ToString(); 
    923                     } 
    924                     else 
    925                     { 
    926                         attributes += "<TR><TD>"; 
    927                         attributes += feature.GetFieldName(i); 
    928                         attributes += "</TD><TD>"; 
    929                         attributes += feature.GetFieldValue(i).ToString(); 
    930                         attributes += "</TD></TR>"; 
    931                     } 
    932                 } 
    933  
    934                 if (name.Length > 0) 
    935                 { 
    936                     informationString += name; 
    937                     informationString += "<BR/><BR/>"; 
    938                 } 
    939                 if (description.Length > 0) 
    940                 { 
    941                     informationString += description; 
    942                     informationString += "<BR/><BR/>"; 
    943                 } 
    944  
    945                 if (attributes.Length > 0) 
    946                 { 
    947                     informationString += "<Table>"; 
    948                     informationString += attributes; 
    949                     informationString += "</Table>"; 
    950                 } 
    951             } 
    952  
    953             dialog.ShowDialog(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle.ToInt32(), 
    954                 "", "Feature Information", informationString, TextFormatEnum.TEXT_FORMAT_HTML, m_callback); 
    955         } 
    956  
    957         #endregion 
    958     } 
    959  
     819               return "Hide Tree Control"; 
     820            } 
     821            return "Display Tree Control"; 
     822         } 
     823      } 
     824 
     825      public void MenuItemSelected() 
     826      { 
     827         if (m_control.Visible) 
     828         { 
     829            m_control.Hide(); 
     830         } 
     831         else 
     832         { 
     833            m_control.Display(); 
     834         } 
     835      } 
     836 
     837      #endregion 
     838   } 
     839 
     840   public class ShowInfo : IFvContextMenuItem 
     841   { 
     842      private List<IFeature> m_list; 
     843      private IFvInformationDialogCallback m_callback; 
     844 
     845      public ShowInfo(List<IFeature> list, IFvInformationDialogCallback callback) 
     846      { 
     847         m_list = list; 
     848         m_callback = callback; 
     849      } 
     850 
     851      #region IFvContextMenuItem Members 
     852 
     853      public int MenuItemChecked 
     854      { 
     855         get 
     856         { 
     857            return 0; 
     858         } 
     859      } 
     860 
     861      public int MenuItemEnabled 
     862      { 
     863         get 
     864         { 
     865            return 1; 
     866         } 
     867      } 
     868 
     869      public string MenuItemName 
     870      { 
     871         get 
     872         { 
     873            return "Get Feature Info..."; 
     874         } 
     875      } 
     876 
     877      public void MenuItemSelected() 
     878      { 
     879         FvInformationDialog dialog = new FvInformationDialogClass(); 
     880 
     881         //build a string from the features 
     882         string informationString = ""; 
     883         foreach (IFeature feature in m_list) 
     884         { 
     885            string name = ""; 
     886            string description = ""; 
     887            string attributes = ""; 
     888            for (int i = 0; i < feature.FieldCount; i++) 
     889            { 
     890               if (feature.GetFieldName(i).Equals("balloon_style_text")) 
     891               { 
     892                  description = feature.GetFieldValue(i).ToString(); 
     893               } 
     894               else if (feature.GetFieldName(i).Equals("name")) 
     895               { 
     896                  name = feature.GetFieldValue(i).ToString(); 
     897               } 
     898               else 
     899               { 
     900                  attributes += "<TR><TD>"; 
     901                  attributes += feature.GetFieldName(i); 
     902                  attributes += "</TD><TD>"; 
     903                  attributes += feature.GetFieldValue(i).ToString(); 
     904                  attributes += "</TD></TR>"; 
     905               } 
     906            } 
     907 
     908            if (name.Length > 0) 
     909            { 
     910               informationString += name; 
     911               informationString += "<BR/><BR/>"; 
     912            } 
     913            if (description.Length > 0) 
     914            { 
     915               informationString += description; 
     916               informationString += "<BR/><BR/>"; 
     917            } 
     918 
     919            if (attributes.Length > 0) 
     920            { 
     921               informationString += "<Table>"; 
     922               informationString += attributes; 
     923               informationString += "</Table>"; 
     924            } 
     925         } 
     926 
     927         dialog.ShowDialog(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle.ToInt32(), 
     928             "", "Feature Information", informationString, TextFormatEnum.TEXT_FORMAT_HTML, m_callback); 
     929      } 
     930 
     931      #endregion 
     932   } 
    960933}