Free cookie consent management tool by TermsFeed Policy Generator

source: addons/HeuristicLab.Problems.BioBoost/HeuristicLab.Problems.BioBoost.Views/3.3/BioBoostCompoundSolutionView.cs @ 16621

Last change on this file since 16621 was 13074, checked in by gkronber, 9 years ago

#2499: added license header and removed unused usings

File size: 24.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System.Globalization;
23using GeoAPI.Geometries;
24using HeuristicLab.BioBoost.Representation;
25using HeuristicLab.BioBoost.Utils;
26using HeuristicLab.BioBoost.Views.MapViews;
27using HeuristicLab.Common;
28using HeuristicLab.Core.Views;
29using HeuristicLab.MainForm;
30using HeuristicLab.MainForm.WindowsForms;
31using SharpMap.Data;
32using SharpMap.Forms;
33using SharpMap.Layers;
34using SharpMap.Rendering.Decoration;
35using SharpMap.Rendering.Decoration.ScaleBar;
36using System;
37using System.Collections.Generic;
38using System.Drawing;
39using System.Drawing.Drawing2D;
40using System.Linq;
41using System.Threading;
42using System.Windows.Forms;
43using HeuristicLab.BioBoost.Evaluators;
44using HeuristicLab.PluginInfrastructure;
45using Point = System.Drawing.Point;
46
47namespace HeuristicLab.BioBoost.Views {
48
49  [Content(typeof(BioBoostCompoundSolution), IsDefaultView = true)]
50  public partial class BioBoostCompoundSolutionView : ItemView {
51
52    private readonly Dictionary<String, ILazyLayerGenerator> layerCache;
53    private readonly GradientLegend legend;
54    private readonly Disclaimer disclaimer;
55    private Thread mapUpdateThread;
56    private Thread costsUpdateThread;
57    private ManualResetEventSlim updateMap;
58    private ManualResetEventSlim updateCosts;
59
60    private SharpMap.Rendering.Thematics.ColorBlend vectorColorBlend =
61      new SharpMap.Rendering.Thematics.ColorBlend(new[] {
62        Color.FromArgb(0, 0, 255),
63        Color.FromArgb(128, 0, 128),
64        Color.FromArgb(255, 0, 0),
65      }, new[] { 0f, .5f, 1f });
66    private string currentRegion;
67    public const string AllRegionsName = "All";
68
69    public new BioBoostCompoundSolution Content {
70      get { return (BioBoostCompoundSolution)base.Content; }
71      set { base.Content = value; }
72    }
73
74    public BioBoostCompoundSolutionView() {
75      InitializeComponent();
76      layerCache = new Dictionary<string, ILazyLayerGenerator>();
77      mapBox.Map.Decorations.Add(new ScaleBar {
78        Anchor = MapDecorationAnchor.RightBottom,
79        BarColor1 = Color.White,
80        BarColor2 = Color.Black,
81        BarStyle = ScaleBarStyle.Meridian,
82        MapUnit = (int)Unit.Degree,
83        BarUnit = (int)Unit.Kilometer,
84      });
85      disclaimer = new Disclaimer {
86        Anchor = MapDecorationAnchor.RightTop,
87        Text = "ForestryResidues Utilization",
88        Enabled = true,
89        BackgroundColor = Color.FromArgb(128, 255, 255, 255),
90        ForeColor = Color.Black,
91        BorderColor = Color.Transparent,
92        Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular)
93      };
94      legend = new GradientLegend {Size = new Size(300, 20)};
95      mapBox.Map.Decorations.Add(legend);
96      mapBox.Map.Decorations.Add(new NorthArrow());
97      mapBox.Map.Decorations.Add(disclaimer);
98       
99      updateMap = new ManualResetEventSlim(true);
100      mapUpdateThread = new Thread(UpdateMap);
101      mapUpdateThread.Start();
102      updateCosts = new ManualResetEventSlim(true);
103      costsUpdateThread = new Thread(UpdateCosts);
104      costsUpdateThread.Start();
105      currentRegion = AllRegionsName;
106    }
107
108
109    protected override void DeregisterContentEvents() {
110      Content.SolutionChanged -= SolutionChanged;
111      base.DeregisterContentEvents();
112    }
113
114    protected override void RegisterContentEvents() {
115      base.RegisterContentEvents();
116      Content.SolutionChanged += SolutionChanged;
117    }
118
119    #region Event Handlers (Content)
120
121    private void SolutionChanged(object sender, EventArgs e) {
122      if (InvokeRequired) {
123        Invoke(new EventHandler<EventArgs>(SolutionChanged), sender, e);
124      } else {
125        UpgradeSolution();
126        InitializeLayers();
127        DiscoverLayerNames();
128        summaryView.Content = new RegionDetailData {RegionName = null, Solution = Content};
129        ShowSelectedLayers(false);
130        ShowCosts();
131      }
132    }
133    #endregion
134
135    protected override void OnContentChanged() {
136      base.OnContentChanged();
137      if (Content == null) {
138        ClearAllLayerNames();
139        ClearCostsSummary();
140      } else {
141        UpgradeSolution();
142        InitializeLayers();
143        DiscoverLayerNames();
144        summaryView.Content = new RegionDetailData {RegionName = null, Solution = Content};
145        ShowSelectedLayers(true);
146        ShowCosts();
147      }
148    }
149
150    private bool upgradeInProgress = false;
151    private void UpgradeSolution() {
152      if (Content != null && !upgradeInProgress) {
153        upgradeInProgress = true;
154        Content.UpdateTo(new BioBoostCompoundSolution(
155          AggregateEvaluator.Evaluate(Content.ProblemDataReference, Content.DoubleValues, Content.IntValues),
156          Content.ProblemDataReference));
157        upgradeInProgress = false;
158      }
159    }
160
161    #region Main Logic
162    private void ResetZoom() {
163      if (mapBox.Map.Layers.Count > 0)
164        mapBox.Map.ZoomToExtents();
165      mapBox.ActiveTool = MapBox.Tools.Pan;
166      mapBox.Refresh();
167    }
168
169    private void DiscoverLayerNames() {
170      DiscoverValueLayers();
171      DiscoverVectorLayers();
172    }
173
174    private class ListBoxItem {
175      public Color Color;
176      public String Text;
177    }
178
179    private void DiscoverVectorLayers() {
180      var layerNames = vectorLayerNamesListBox.Items.Cast<ListBoxItem>().Select(l => l.Text).ToList();
181      if (layerNames.SequenceEqual(Content.IntValues.Keys)) return;
182      vectorLayerNamesListBox.BeginUpdate();
183      vectorLayerNamesListBox.Items.Clear();
184      int i = 0, n = Math.Max(1, Content.IntValues.Count - 1);
185      foreach (var values in Content.IntValues) {
186        var newItem = new ListBoxItem {
187          Color = vectorColorBlend.GetColor(1f * i++ / n),
188          Text = values.Key
189        };
190        vectorLayerNamesListBox.Items.Add(newItem);
191        if (layerNames.Any(name => name == values.Key) || layerNames.Count == 0)
192          vectorLayerNamesListBox.SelectedItems.Add(newItem);
193      }
194      vectorLayerNamesListBox.EndUpdate();
195    }
196
197    private void DiscoverValueLayers() {
198      var layerNames = AddRelativePotentials(Content.DoubleValues.Keys).ToList();
199      layerNames.Sort();
200      if (valueLayerNamesListBox.Items.Cast<string>().SequenceEqual(layerNames))
201        return;
202      valueLayerNamesListBox.BeginUpdate();
203      var selectedValueLayerName = (string)valueLayerNamesListBox.SelectedItem;
204      var firstFinalProduct = Content.ProblemDataReference.FinalProducts.FirstOrDefault();
205      if (selectedValueLayerName == null && firstFinalProduct != null)
206        selectedValueLayerName = LayerDescriptor.RelativeCostAtSource.NameWithPrefix(firstFinalProduct.Value);
207      valueLayerNamesListBox.Items.Clear();
208      foreach (var name in layerNames) {
209        var i = valueLayerNamesListBox.Items.Add(name);
210        if (name == selectedValueLayerName)
211          valueLayerNamesListBox.SelectedIndex = i;
212      }
213      if (valueLayerNamesListBox.SelectedIndex == -1)
214        valueLayerNamesListBox.SelectedIndex = 0;
215      valueLayerNamesListBox.EndUpdate();
216    }
217
218    private IEnumerable<string> AddRelativePotentials(IEnumerable<string> names) {
219      foreach (var name in names) {
220        if (LayerDescriptor.PotentialsFromProblemData.IsSuffixOf(name)) {
221          var formattedName = name.Replace(LayerDescriptor.PotentialsFromProblemData.FullName, " Potentials");
222          yield return formattedName;
223          yield return formattedName + " Relative";
224        } else {
225          yield return name;
226        }
227      }
228    }
229
230    private void ClearAllLayerNames() {
231      valueLayerNamesListBox.Items.Clear();
232      vectorLayerNamesListBox.Items.Clear();
233    }
234
235    private void ShowSelectedLayers(bool resetZoom) {
236      lock (updateMap) {
237        if (pendingUpdate != null) {
238          pendingUpdate.ResetZoom |= resetZoom;
239        } else {
240          pendingUpdate = new BackgroundArguments { ResetZoom = resetZoom };
241        }
242        updateMap.Set();
243      }
244    }
245
246    private void ShowCosts() {
247      updateCosts.Set();
248    }
249
250    private sealed class BackgroundArguments {
251      public bool ResetZoom;
252      public LazyValueLayerGenerator ValueLayerGenerator;
253      public List<LazyVectorLayerGenerator> VectorLayerGenerators;
254      public ILayer ValueLayer;
255      public List<ILayer> TransportLayers;
256    }
257
258    private BackgroundArguments pendingUpdate;
259    private bool runningUpdateMap = true;
260    private bool runningUpdateCosts = true;
261
262    private void UpdateMap() {
263      while (runningUpdateMap) {
264        BackgroundArguments currentUpdate = null;
265        // wait for a signal to update the map
266        while (!updateMap.Wait(2000)) {
267          if (!runningUpdateMap) return; // stop thread if requested
268        }
269        lock (updateMap) {
270          updateMap.Reset();
271          currentUpdate = pendingUpdate;
272          pendingUpdate = null;
273        }
274
275        // only do something if the map-tab is active
276        if (currentUpdate != null) {
277          DoShowSelectedLayers(currentUpdate);
278        }
279        Thread.Sleep(500);
280      }
281    }
282
283    private void UpdateCosts() {
284      while (runningUpdateCosts) {
285        // wait for signal to update the costs
286        while (!updateCosts.Wait(2000)) {
287          if (!runningUpdateCosts) return; // stop the thread if requested
288        }
289        updateCosts.Reset();
290
291        ClearCostsSummary();
292        PopulateRegionTree();
293        PopulateCostsSummary();
294
295        Thread.Sleep(500);
296      }
297    }
298
299    private void DoShowSelectedLayers(BackgroundArguments args) {
300      if (InvokeRequired) {
301        try {
302          var result = BeginInvoke(new Action<BackgroundArguments>(DoShowSelectedLayers), args);
303          result.AsyncWaitHandle.WaitOne();
304          EndInvoke(result);
305        } catch (ObjectDisposedException) { }
306      } else {
307        // only do something if the map-tab is active
308        if (tabControl1.SelectedTab != tabPage1) return;
309
310        GetConfigFromUI(args);
311        var generator = args.ValueLayerGenerator;
312        if (generator == null) return;
313        args.ValueLayer = generator.Layer; // this might take a while
314        args.TransportLayers = new List<ILayer>();
315        foreach (var g in args.VectorLayerGenerators) {
316          args.TransportLayers.Add(g.Layer); // TODO: cycle colors of vectors
317        }
318        UpdateUI(args);
319      }
320    }
321
322    private void GetConfigFromUI(BackgroundArguments args) {
323      var valueLayerName = (string)valueLayerNamesListBox.SelectedItem;
324      var vectorLayerNames = vectorLayerNamesListBox.SelectedItems.Cast<ListBoxItem>().Select(i => i.Text);
325      if (String.IsNullOrEmpty(valueLayerName)) return;
326      var generator = layerCache[valueLayerName] as LazyValueLayerGenerator;
327      if (generator == null) return;
328      args.ValueLayerGenerator = generator;
329      args.VectorLayerGenerators =
330        vectorLayerNames.Select(n => layerCache[n] as LazyVectorLayerGenerator).Where(g => g != null).ToList();
331
332    }
333
334    private void UpdateUI(BackgroundArguments args) {
335      if (IsDisposed || Disposing) return;
336      try {
337        var currentZoom = mapBox.Map.Zoom;
338        var currentCenter = mapBox.Map.Center;
339        mapBox.Map.Layers.Clear();
340        mapBox.Map.Layers.Add(args.ValueLayer);
341        foreach (var tl in args.TransportLayers)
342          mapBox.Map.Layers.Add(tl);
343        legend.MinValue = args.ValueLayerGenerator.ActualMinValue;
344        legend.MaxValue = args.ValueLayerGenerator.ActualMaxValue;
345        legend.Unit = args.ValueLayerGenerator.Unit;
346        legend.ColorBlend = new ColorBlend {
347          Colors = args.ValueLayerGenerator.ColorBlend.Colors,
348          Positions = args.ValueLayerGenerator.ColorBlend.Positions,
349        };
350        disclaimer.Text = args.ValueLayer.LayerName;
351        if (args.ResetZoom) {
352          ResetZoom();
353        } else {
354          mapBox.ActiveTool = MapBox.Tools.Pan;
355          mapBox.Map.Zoom = currentZoom;
356          mapBox.Map.Center = currentCenter;
357          mapBox.Refresh();
358        }
359      } catch (Exception x) {
360        MessageBox.Show(this, "Could not update UI, please try again:\n" + x);
361      }
362    }
363
364    private void InitializeLayers() {
365      lock (updateMap) {
366        layerCache.Clear();
367        var geom = Content.Geometry;
368        var locs = Content.LocationNames;
369        foreach (var kvp in Content.DoubleValues) {
370          var generator = new LazyValueLayerGenerator(geom, locs, kvp.Value, kvp.Key);
371          var name = kvp.Key;
372          if (kvp.Value.Min() > 0) generator.MinValue = 0;
373          if (kvp.Value.Max() < 0) generator.MaxValue = 0;
374          var layer = LayerDescriptor.GetLayer(name);
375          if (layer == LayerDescriptor.Utilizations || layer == LayerDescriptor.UtilizationsEffective) {
376            generator.MaxValue = 1;
377          } else if (layer == Representation.LayerDescriptor.PotentialsFromProblemData) {
378            generator.Unit = "t/a";
379            name = name.Replace(LayerDescriptor.PotentialsFromProblemData.FullName, " Potentials");
380            layerCache.Add(name + " Relative", new LazyValueLayerGenerator(geom, locs, kvp.Value, name + " Relative") {
381              MinValue = 0,
382              RealtiveToSize = true,
383              Unit = "t/ha/a"
384            });
385          } else {
386            if (layer != null)
387              generator.Unit = layer.Unit;
388          }
389          layerCache.Add(name, generator);
390        }
391        int i = 0, n = Math.Max(1, Content.IntValues.Count - 1);
392        foreach (var kvp in Content.IntValues) {
393          var name = kvp.Key;
394          var targets = kvp.Value;
395          var amounts = BioBoostCompoundSolution.FindAmountsTransportedFromSource(Content.DoubleValues, name);
396          if (amounts != null) {
397            for (int j = 0; j < amounts.Length; j++) {
398              if (amounts[j] <= 0) {
399                targets[j] = -1;
400              }
401            }
402          }
403          layerCache.Add(
404            name,
405            new LazyVectorLayerGenerator(geom, locs, targets,  amounts, vectorColorBlend.GetColor(1.0f * i / n), name) {
406              LineOffset = i * 2
407            });
408          i++;
409        }
410      }
411    }
412
413    private void ClearCostsSummary() {
414      if (InvokeRequired) {
415        try {
416          var result = BeginInvoke(new Action(ClearCostsSummary));
417          result.AsyncWaitHandle.WaitOne();
418          EndInvoke(result);
419        } catch (ObjectDisposedException) { }
420      } else {
421        if (IsDisposed || Disposing) return;
422        bioBoostSolutionCostsView1.Content = null;
423      }
424    }
425
426    private void PopulateCostsSummary() {
427      if (InvokeRequired) {
428        try {
429          var result = BeginInvoke(new Action(PopulateCostsSummary));
430          result.AsyncWaitHandle.WaitOne();
431          EndInvoke(result);
432        } catch (ObjectDisposedException) { }
433      } else {
434        if (IsDisposed || Disposing) return;
435        // only do something if the costs-tab is active
436        if (tabControl1.SelectedTab != tabPage2) return;
437
438        regionsTreeView.SelectedNode = regionsTreeView.Nodes.Find(currentRegion, true).FirstOrDefault();
439        regionsTreeView.Focus();
440        if (IsDisposed) return;
441        bioBoostSolutionCostsView1.Content = new RegionDetailData {
442          RegionName = currentRegion,
443          Solution = Content,
444        };
445      }
446    }
447
448    private void PopulateRegionTree() {
449      if (InvokeRequired) {
450        try {
451          var result = BeginInvoke(new Action(PopulateRegionTree));
452          result.AsyncWaitHandle.WaitOne();
453          EndInvoke(result);
454        } catch (ObjectDisposedException) { }
455      } else {
456        if (IsDisposed || Disposing) return;
457        regionsTreeView.Nodes.Clear();
458        if (Content == null) return;
459        regionsTreeView.Nodes.Add(AllRegionsName, AllRegionsName);
460        var allRegionsNodes = regionsTreeView.Nodes[AllRegionsName].Nodes;
461        foreach (var location in Content.LocationNames) {
462          var country = location.Substring(0, 2);
463          if (!allRegionsNodes.ContainsKey(country)) {
464            allRegionsNodes.Add(country, country);
465          }
466          allRegionsNodes[country].Nodes.Add(location, location);
467        }
468        regionsTreeView.HideSelection = false;
469        regionsTreeView.Nodes[AllRegionsName].Expand();
470      }
471    }
472
473    #endregion
474
475    public void SetFocus(string regionName) {
476      var row = Content.Geometry.Features.Rows.Cast<FeatureDataRow>().FirstOrDefault(r => (string)r["NUTS_ID"] == regionName);
477      if (row == null) return;
478      var coords = row.Geometry.Envelope.Buffer(1).Coordinates;
479      var env = new Envelope(coords.Min(c => c.X), coords.Max(c => c.X),
480                   coords.Min(c => c.Y), coords.Max(c => c.Y));
481      mapBox.Map.ZoomToBox(env);
482      mapBox.Refresh();
483    }
484
485    protected override void SetEnabledStateOfControls() {
486      base.SetEnabledStateOfControls();
487      vectorLayerNamesListBox.Enabled = Content != null;
488      valueLayerNamesListBox.Enabled = Content != null;
489      openSolutionEditorButton.Enabled = Content != null && !Locked;
490    }
491
492    #region Auxiliary Methods
493    private string GetRegionAtWorldPos(Coordinate loc) {
494      var ds = new FeatureDataSet();
495      Content.Geometry.ExecuteIntersectionQuery(new NetTopologySuite.Geometries.Point(loc), ds);
496      return (from FeatureDataRow row in ds.Tables[0]
497              select row["NUTS_ID"] as string).FirstOrDefault();
498    }
499
500    private string GetRegionDescription(string regionName) {
501      if (regionName != null && Content.Geometry.Features.Columns.Contains("name")) {
502        var row = Content.Geometry.Features.Rows.Cast<FeatureDataRow>().FirstOrDefault(r => (string)r["NUTS_ID"] == regionName);
503        if (row != null)
504          return row["name"].ToString();
505      }
506      return "";
507    }
508
509    private string GetCurrentValueLayerValue(string regionName) {
510      if (regionName == null) return "";
511      var layerName = valueLayerNamesListBox.SelectedItem as string;
512      if (layerName == null) return "";
513      var generator = layerCache[layerName] as LazyValueLayerGenerator;
514      if (generator == null) return "";
515      var mapping = generator.Mapping;
516      if (mapping == null) return "";
517      double value;
518      if (!mapping.TryGetValue(regionName, out value)) return "";
519      var v = Math.Abs(value);
520      //var format = v > 1000 ? "F0" : v > 100 ? "F1" : v > 10 ? "F2" : value < 0.01 ? "G" : "F3";
521      var format = v > 1000 ? "F0" : v > 100 ? "F1" : v > 10 ? "F2" : value < 0.01 ? "G" : "F3";
522      var info = (NumberFormatInfo)NumberFormatInfo.InvariantInfo.Clone();
523      info.NumberGroupSeparator = " ";
524      return string.Format("{0} {1}", value.ToString(format, info), generator.Unit);
525    }
526
527    #endregion
528
529    #region Event Handlers (child controls)
530    private void vectorLayerNamesListBox_SelectedIndexChanged(object sender, EventArgs e) {
531      ShowSelectedLayers(false);
532      vectorLayerNamesListBox.Invalidate();
533    }
534
535    private void valueLayerNamesListBox_SelectedIndexChanged(object sender, EventArgs e) {
536      ShowSelectedLayers(false);
537    }
538
539    private void mapBox_MouseMove(Coordinate worldPos, MouseEventArgs imagePos) {
540      var nuts_id = GetRegionAtWorldPos(worldPos);
541      var nuts_name = GetRegionDescription(nuts_id);
542      regionNameLabel.Text = nuts_id;
543      regionDescriptionLabel.Text = nuts_name;
544      valueLayerValueLabel.Text = GetCurrentValueLayerValue(nuts_id);
545      mapBox.Cursor = String.IsNullOrEmpty(nuts_id) ? Cursors.Default : Cursors.Hand;
546    }
547
548    private Point startPos = new Point(0, 0);
549    private void mapBox_MouseDown(Coordinate worldPos, MouseEventArgs imagePos) {
550      if (imagePos.Button == MouseButtons.Left) {
551        startPos = imagePos.Location;
552      }
553    }
554
555    private void mapBox_MouseUp(Coordinate worldPos, MouseEventArgs imagePos) {
556      if (imagePos.Button == MouseButtons.Left
557          && Util.Distance(imagePos.Location, startPos) < 4) {
558        currentRegion = GetRegionAtWorldPos(worldPos);
559        if (!String.IsNullOrEmpty(currentRegion)) {
560          regionDetailView.Content = new RegionDetailData {
561            RegionName = currentRegion,
562            Solution = Content,
563          };
564        }
565      }
566    }
567
568    private void solutionDetailView_RegionLabelClicked(object sender, EventArgs e) {
569      if (regionDetailView.Content != null)
570        SetFocus(regionDetailView.Content.RegionName);
571    }
572
573    private void vectorLayerNamesListBox_DrawItem(object sender, DrawItemEventArgs e) {
574      var item = vectorLayerNamesListBox.Items[e.Index];
575      var listBoxItem = item as ListBoxItem;
576      var foreColor = Color.Black;
577      if (listBoxItem != null) {
578        foreColor = listBoxItem.Color;
579      }
580      var backColor = vectorLayerNamesListBox.BackColor;
581      if (vectorLayerNamesListBox.SelectedItems.Contains(item)) {
582        backColor = foreColor;
583        foreColor = Color.White;
584      }
585      using (var backBrush = new SolidBrush(backColor)) {
586        e.Graphics.FillRectangle(backBrush, e.Bounds);
587      }
588      using (var foreBrush = new SolidBrush(foreColor)) {
589        e.Graphics.DrawString(
590          listBoxItem != null ? listBoxItem.Text : item.ToString(),
591          vectorLayerNamesListBox.Font, foreBrush, e.Bounds);
592      }
593    }
594    #endregion
595
596    private void tabControl1_Selected(object sender, TabControlEventArgs e) {
597      switch (e.TabPageIndex) {
598        case 0:
599          ShowSelectedLayers(false); // prepare for the map update
600          updateMap.Set(); // signal that the map should be updated once
601          break;
602        case 1:
603          updateCosts.Set(); // signal that the costs should be updated once
604          break;
605      }
606    }
607
608    private void regionsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
609      var labeltext = e.Node.Text.Split(' ');
610      if (labeltext.Length > 0)
611        currentRegion = labeltext[0];
612      if (e.Node.GetNodeCount(true) == 0) {
613        regionDetailView.Content = new RegionDetailData {
614          RegionName = currentRegion,
615          Solution = Content,
616        };
617      }
618
619      ClearCostsSummary();
620      PopulateCostsSummary();
621    }
622
623    private void openSolutionEditorButton_Click(object sender, EventArgs e) {
624      // clone solution and also clone problem-data separately (solution does not clone problem data itself)
625      var cloner = new Cloner();
626      var clonedSolution = cloner.Clone(Content);
627      var clonedProblemData = cloner.Clone(Content.ProblemDataReference);
628      clonedSolution.ProblemDataReference = clonedProblemData;
629
630      // create and open editor view for content
631      var vh = new ViewHost();
632      vh.Content = clonedSolution;
633      vh.ViewType = typeof (BioBoostCompoundSolutionEditor);
634      vh.Show();
635    }
636
637    public void SaveMapViewToPNG(string filename) {
638      var bitmap = new Bitmap(mapBox.Width, mapBox.Height);
639      mapBox.DrawToBitmap(bitmap, new Rectangle(0, 0, mapBox.Width, mapBox.Height));
640      bitmap.Save(filename);
641    }
642
643    private void saveMapImageButton_Click(object sender, EventArgs e) {
644      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
645        try {
646          Enabled = false;
647          SaveMapViewToPNG(saveFileDialog.FileName);
648        } catch (Exception x) {
649          ErrorHandling.ShowErrorDialog(this, x);
650        } finally {
651          Enabled = true;
652        }
653      }
654    }
655
656  }
657}
Note: See TracBrowser for help on using the repository browser.