Free cookie consent management tool by TermsFeed Policy Generator

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

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

added possibility to clear the cached views in the ViewHost (ticket #972)

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