Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.BioBoost/HeuristicLab.Problems.BioBoost.Views/3.3/BioBoostCompoundSolutionView.cs @ 13072

Last change on this file since 13072 was 13072, checked in by gkronber, 7 years ago

#2499: added code from HeuristicLab.BioBoost.Views (from private repository) nothing much has been changed

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