Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/ViewHost.cs @ 4083

Last change on this file since 4083 was 4083, checked in by mkommend, 14 years ago

fixed bug concerning invisible views in viewhost (ticket #972)

File size: 11.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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;
23using System.Collections.Generic;
24using System.Linq;
25using System.Windows.Forms;
26using HeuristicLab.Common;
27using System.Reflection;
28
29namespace HeuristicLab.MainForm.WindowsForms {
30  [Content(typeof(IContent))]
31  public sealed partial class ViewHost : AsynchronousContentView {
32    public ViewHost() {
33      InitializeComponent();
34      cachedViews = new Dictionary<Type, IContentView>();
35      startDragAndDrop = false;
36      viewContextMenuStrip.IgnoredViewTypes = new List<Type>() { typeof(ViewHost) };
37
38      viewType = null;
39      activeView = null;
40      Content = null;
41      messageLabel.Visible = false;
42      viewsLabel.Visible = false;
43    }
44
45    private Dictionary<Type, IContentView> cachedViews;
46    public IEnumerable<IContentView> Views {
47      get { return cachedViews.Values; }
48    }
49
50    private IContentView activeView;
51    public IContentView ActiveView {
52      get { return this.activeView; }
53      private set {
54        if (activeView != value) {
55          if (activeView != null) {
56            DeregisterActiveViewEvents();
57            View view = activeView as View;
58            if (view != null)
59              view.OnHidden(EventArgs.Empty);
60            if (ActiveViewControl != null)
61              ActiveViewControl.Visible = false;
62          }
63          activeView = value;
64          if (activeView != null) {
65            viewType = activeView.GetType();
66            RegisterActiveViewEvents();
67            View view = activeView as View;
68            if (view != null)
69              view.OnShown(new ViewShownEventArgs(view, false));
70            if (ActiveViewControl != null) {
71              ActiveViewControl.Visible = true;
72              ActiveViewControl.BringToFront();
73            }
74          }
75          OnActiveViewChanged();
76        }
77      }
78    }
79
80    private Control ActiveViewControl {
81      get { return ActiveView as Control; }
82    }
83
84    private Type viewType;
85    public Type ViewType {
86      get { return this.viewType; }
87      set {
88        if (viewType != value) {
89          if (value != null && Content != null && !ViewCanShowContent(value, Content))
90            throw new ArgumentException(string.Format("View \"{0}\" cannot display content \"{1}\".",
91                                                      value, Content.GetType()));
92          viewType = value;
93          OnViewTypeChanged();
94        }
95      }
96    }
97
98    public new bool Enabled {
99      get { return base.Enabled; }
100      set {
101        this.SuspendRepaint();
102        base.Enabled = value;
103        this.viewsLabel.Enabled = value;
104        this.ResumeRepaint(true);
105      }
106    }
107
108    protected override void OnContentChanged() {
109      viewContextMenuStrip.Item = Content;
110      //remove cached views which cannot show the content
111      foreach (Type type in cachedViews.Keys.ToList()) {
112        if (!ViewCanShowContent(type, Content)) {
113          Control c = cachedViews[type] as Control;
114          if (c != null) {
115            this.Controls.Remove(c);
116            c.Dispose();
117          }
118          cachedViews.Remove(type);
119        }
120      }
121
122      //change ViewType if view of ViewType can not show content or is null
123      if (Content != null && !ViewCanShowContent(viewType, Content)) {
124        Type defaultViewType = MainFormManager.GetDefaultViewType(Content.GetType());
125        if (defaultViewType != null)
126          ViewType = defaultViewType;
127        else if (viewContextMenuStrip.Items.Count > 0)  // create first available view if no default view is available
128          ViewType = (Type)viewContextMenuStrip.Items[0].Tag;
129        else
130          ViewType = null;
131      }
132
133      foreach (IContentView view in cachedViews.Values)
134        view.Content = this.Content;
135
136      if (Content != null && viewType != null)
137        ActiveView = cachedViews[viewType];
138      else
139        ActiveView = null;
140
141      if (Content != null && viewContextMenuStrip.Items.Count > 0) {
142        messageLabel.Visible = false;
143        viewsLabel.Visible = true;
144      } else if (Content != null) {
145        messageLabel.Visible = true;
146        viewsLabel.Visible = false;
147      } else {
148        messageLabel.Visible = false;
149        viewsLabel.Visible = false;
150      }
151    }
152
153    private void OnViewTypeChanged() {
154      if (viewType != null) {
155        if (!ViewCanShowContent(viewType, Content))
156          throw new InvalidOperationException(string.Format("View \"{0}\" cannot display content \"{1}\".",
157                                                            viewType, Content.GetType()));
158        IContentView view;
159        if (!cachedViews.ContainsKey(ViewType)) {
160          view = MainFormManager.CreateView(viewType);
161          view.ReadOnly = this.ReadOnly;
162          view.Locked = this.Locked;
163          view.Content = Content;
164          cachedViews.Add(viewType, view);
165          Control c = view as Control;
166          if (c != null)
167            this.Controls.Add(c);
168        }
169        UpdateActiveMenuItem();
170        ActiveView = cachedViews[viewType];
171      }
172    }
173
174    private void OnActiveViewChanged() {
175      this.SuspendRepaint();
176      if (activeView != null) {
177        UpdateActiveMenuItem();
178        this.ActiveView.ReadOnly = this.ReadOnly;
179        this.ActiveView.Locked = this.Locked;
180        this.ActiveViewControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
181        this.ActiveViewControl.Size = new System.Drawing.Size(this.Width - this.viewsLabel.Width - this.viewsLabel.Margin.Left - this.viewsLabel.Margin.Right, this.Height);
182        this.ActiveViewChanged();
183      }
184      this.ResumeRepaint(true);
185    }
186
187    protected override void OnSizeChanged(EventArgs e) {
188      //mkommend: solution to resizing issues. taken from http://support.microsoft.com/kb/953934
189      //not implemented with a panel to reduce the number of nested controls
190      if (this.Handle != null)
191        this.BeginInvoke((Action<EventArgs>)OnSizeChangedHelper, e);
192    }
193    private void OnSizeChangedHelper(EventArgs e) {
194      base.OnSizeChanged(e);
195      this.viewsLabel.Location = new System.Drawing.Point(this.Width - this.viewsLabel.Margin.Right - this.viewsLabel.Width, this.viewsLabel.Margin.Top);
196    }
197
198    private void RegisterActiveViewEvents() {
199      activeView.Changed += new EventHandler(activeView_Changed);
200      activeView.CaptionChanged += new EventHandler(activeView_CaptionChanged);
201    }
202    private void DeregisterActiveViewEvents() {
203      activeView.Changed -= new EventHandler(activeView_Changed);
204      activeView.CaptionChanged -= new EventHandler(activeView_CaptionChanged);
205    }
206    private void activeView_CaptionChanged(object sender, EventArgs e) {
207      this.ActiveViewChanged();
208    }
209    private void activeView_Changed(object sender, EventArgs e) {
210      this.ActiveViewChanged();
211    }
212    private void ActiveViewChanged() {
213      if (ActiveView != null) {
214        this.Caption = this.ActiveView.Caption;
215        this.Locked = this.ActiveView.Locked;
216      }
217    }
218
219    #region forwarding of view events
220    protected override void PropagateStateChanges(Control control, Type type, System.Reflection.PropertyInfo propertyInfo) {
221      if (!type.GetProperties().Contains(propertyInfo))
222        throw new ArgumentException("The specified type " + type + "implement the property " + propertyInfo.Name + ".");
223      if (!type.IsAssignableFrom(this.GetType()))
224        throw new ArgumentException("The specified type " + type + "must be the same or a base class / interface of this object.");
225      if (!propertyInfo.CanWrite)
226        throw new ArgumentException("The specified property " + propertyInfo.Name + " must have a setter.");
227
228      if (activeView != null) {
229        Type controlType = activeView.GetType();
230        PropertyInfo controlPropertyInfo = controlType.GetProperty(propertyInfo.Name, propertyInfo.PropertyType);
231        if (type.IsAssignableFrom(controlType) && controlPropertyInfo != null) {
232          var thisValue = propertyInfo.GetValue(this, null);
233          controlPropertyInfo.SetValue(activeView, thisValue, null);
234        }
235      }
236    }
237
238    internal protected override void OnShown(ViewShownEventArgs e) {
239      base.OnShown(e);
240      View view = this.ActiveView as View;
241      if (view != null)
242        view.OnShown(e);
243    }
244    internal protected override void OnHidden(EventArgs e) {
245      base.OnHidden(e);
246      View view = this.ActiveView as View;
247      if (view != null)
248        view.OnHidden(e);
249    }
250    internal protected override void OnClosing(FormClosingEventArgs e) {
251      base.OnClosing(e);
252      foreach (View view in this.Views.OfType<View>())
253        view.OnClosing(e);
254    }
255    internal protected override void OnClosed(FormClosedEventArgs e) {
256      base.OnClosed(e);
257      foreach (View view in this.Views.OfType<View>())
258        view.OnClosed(e);
259    }
260    #endregion
261
262    #region GUI actions
263    private void UpdateActiveMenuItem() {
264      foreach (KeyValuePair<Type, ToolStripMenuItem> item in viewContextMenuStrip.MenuItems) {
265        if (item.Key == viewType) {
266          item.Value.Checked = true;
267          item.Value.Enabled = false;
268        } else {
269          item.Value.Checked = false;
270          item.Value.Enabled = true;
271        }
272      }
273    }
274
275    private bool ViewCanShowContent(Type viewType, object content) {
276      if (content == null) // every view can display null
277        return true;
278      if (viewType == null)
279        return false;
280      return ContentAttribute.CanViewType(viewType, Content.GetType()) && viewContextMenuStrip.MenuItems.Any(item => item.Key == viewType);
281    }
282
283    private void viewsLabel_DoubleClick(object sender, EventArgs e) {
284      IContentView view = MainFormManager.MainForm.ShowContent(this.Content, this.ViewType);
285      if (view != null) {
286        view.ReadOnly = this.ReadOnly;
287        view.Locked = this.Locked;
288      }
289    }
290    private void viewContextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {
291      Type viewType = (Type)e.ClickedItem.Tag;
292      ViewType = viewType;
293    }
294
295    private bool startDragAndDrop;
296    private void viewsLabel_MouseDown(object sender, MouseEventArgs e) {
297      if (!Locked) {
298        startDragAndDrop = true;
299        viewsLabel.Capture = false;
300        viewsLabel.Focus();
301      }
302    }
303    private void viewsLabel_MouseLeave(object sender, EventArgs e) {
304      if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left && startDragAndDrop) {
305        DataObject data = new DataObject();
306        data.SetData("Type", Content.GetType());
307        data.SetData("Value", Content);
308        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
309      } else
310        startDragAndDrop = false;
311    }
312    #endregion
313  }
314}
Note: See TracBrowser for help on using the repository browser.