Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4101 was 4097, checked in by swagner, 14 years ago

Fixed minor bugs of r4084 (#972)

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