[4311] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using System.Linq;
|
---|
| 4 | using System.Text;
|
---|
| 5 | using System.Windows;
|
---|
| 6 | using HeuristicLab.PluginInfrastructure;
|
---|
| 7 | using System.Windows.Controls;
|
---|
| 8 | using AvalonDock;
|
---|
| 9 | using System.Windows.Media.Imaging;
|
---|
| 10 | using System.Reflection;
|
---|
| 11 | using System.Windows.Media;
|
---|
| 12 | using HeuristicLab.BackgroundProcessing;
|
---|
| 13 | using System.Threading;
|
---|
| 14 | using System.Windows.Threading;
|
---|
| 15 | using System.ComponentModel;
|
---|
| 16 | using System.Windows.Input;
|
---|
| 17 | using System.Windows.Controls.Primitives;
|
---|
| 18 | using HeuristicLab.Core;
|
---|
| 19 | using System.Windows.Forms.Integration;
|
---|
| 20 | using HeuristicLab.Common;
|
---|
| 21 |
|
---|
| 22 | namespace HeuristicLab.MainForm.WPF {
|
---|
| 23 |
|
---|
| 24 | public abstract class WPFMainFormBase : Window, IMainForm, IControlManager {
|
---|
| 25 |
|
---|
| 26 | public static readonly Size ToolBarImageSize = new Size(20, 20);
|
---|
| 27 | public abstract Type UserInterfaceItemType { get; }
|
---|
| 28 |
|
---|
| 29 | public WPFMainFormBase() {
|
---|
| 30 | InitializeComponent();
|
---|
| 31 | InstallExceptionHandlers();
|
---|
| 32 | InitializeBackgroundWorkerMonitoring();
|
---|
| 33 | BuildRootMenu();
|
---|
| 34 | BuildViewsMenu();
|
---|
| 35 | BuildToolBar();
|
---|
| 36 | Messages.Items.Clear();
|
---|
| 37 | DockingManager.PropertyChanged += (sender, args) => {
|
---|
| 38 | if (args.PropertyName == "ActiveDocument")
|
---|
| 39 | OnActiveDocumentChanged();
|
---|
| 40 | };
|
---|
| 41 | MainFormManager.RegisterMainForm(this);
|
---|
| 42 | ControlManager.RegisterManager(this);
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | public void ShowControl(object control) {
|
---|
| 46 | object content = null;
|
---|
| 47 | string name = "Control";
|
---|
| 48 | if (control is HeuristicLab.MainForm.IView) {
|
---|
| 49 | content = control;
|
---|
| 50 | name = ((HeuristicLab.MainForm.IView)control).Caption;
|
---|
| 51 | }
|
---|
| 52 | ShowObjectAsView(content, name);
|
---|
| 53 | }
|
---|
| 54 |
|
---|
| 55 | public IContentView ShowContent(IContent content) {
|
---|
| 56 | throw new NotImplementedException();
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | public IContentView ShowContent(IContent content, Type viewType) {
|
---|
| 60 | throw new NotImplementedException();
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | #region GUI
|
---|
| 64 |
|
---|
| 65 | private DockPanel Panel = new DockPanel();
|
---|
| 66 | private Menu Menu = new Menu();
|
---|
| 67 | private ToolBar ToolBar = new ToolBar();
|
---|
| 68 | private StatusBar StatusBar = new StatusBar();
|
---|
| 69 | private StatusBar BackgroundWorkers = new OperationBarPanel();
|
---|
| 70 | private StatusBar Messages = new StatusBar();
|
---|
| 71 | private DocumentPane DocumentPane = new DocumentPane();
|
---|
| 72 | private DockingManager DockingManager = new DockingManager() {
|
---|
| 73 | MinHeight = 50,
|
---|
| 74 | };
|
---|
| 75 |
|
---|
| 76 | protected void InitializeComponent() {
|
---|
| 77 | StatusBar.Items.Add("OKB Cockpit");
|
---|
| 78 | StatusBar.Items.Add(new Separator());
|
---|
| 79 | StatusBar.Items.Add("Operations:");
|
---|
| 80 | StatusBar.Items.Add(BackgroundWorkers);
|
---|
| 81 | StatusBar.Items.Add(new Separator());
|
---|
| 82 | StatusBar.Items.Add(Messages);
|
---|
| 83 | StatusBar.AddHandler(Button.ClickEvent, new RoutedEventHandler(OperationAborted));
|
---|
| 84 | Menu.SetValue(DockPanel.DockProperty, Dock.Top);
|
---|
| 85 | ToolBar.SetValue(DockPanel.DockProperty, Dock.Top);
|
---|
| 86 | StatusBar.SetValue(DockPanel.DockProperty, Dock.Bottom);
|
---|
| 87 | DockingManager.Content = DocumentPane;
|
---|
| 88 | Panel.Children.Add(Menu);
|
---|
| 89 | Panel.Children.Add(ToolBar);
|
---|
| 90 | Panel.Children.Add(StatusBar);
|
---|
| 91 | Panel.Children.Add(DockingManager);
|
---|
| 92 | Content = Panel;
|
---|
| 93 | Title = "WPF Main Window";
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | #endregion
|
---|
| 97 |
|
---|
| 98 | #region fallback exception handling
|
---|
| 99 |
|
---|
| 100 | private void InstallExceptionHandlers() {
|
---|
| 101 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
---|
| 102 | Dispatcher.UnhandledException += Dispatcher_UnhandledException;
|
---|
| 103 | WorkerMonitor.Default.BackgroundWorkerException += WorkerMonitor_BackgroundWorkerException;
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
---|
| 107 | Exception x = e.ExceptionObject as Exception;
|
---|
| 108 | if (x != null)
|
---|
| 109 | ShowException("Unhandled application domain exception", x);
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | private void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) {
|
---|
| 113 | ShowException("Unhandled dispatcher exception", e.Exception);
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | private void WorkerMonitor_BackgroundWorkerException(object sender, ThreadExceptionEventArgs e) {
|
---|
| 117 | ShowException(String.Format("'{0}' raised async exception", e.Exception.Message), e.Exception.InnerException);
|
---|
| 118 | }
|
---|
| 119 |
|
---|
| 120 | protected void ShowException(string message, Exception e) {
|
---|
| 121 | Dispatcher.BeginInvoke(new Action(() => {
|
---|
| 122 | MessageBox.Show(this,
|
---|
| 123 | String.Format("{0}:\n{1}", message, e.ToString()),
|
---|
| 124 | Title, MessageBoxButton.OK, MessageBoxImage.Error);
|
---|
| 125 | }), DispatcherPriority.SystemIdle);
|
---|
| 126 | }
|
---|
| 127 |
|
---|
| 128 | #endregion
|
---|
| 129 |
|
---|
| 130 | #region view discovery
|
---|
| 131 |
|
---|
| 132 | private void BuildViewsMenu() {
|
---|
| 133 | MenuItem viewsMenu = new MenuItem() { Header = "Views" };
|
---|
| 134 | Menu.Items.Add(viewsMenu);
|
---|
| 135 | foreach (Type viewType in ApplicationManager.Manager
|
---|
| 136 | .GetTypes(UserInterfaceItemType)
|
---|
| 137 | .Where(t => t.GetInterface(typeof(IAutoView).FullName) != null)) {
|
---|
| 138 | viewsMenu.Items.Add(CreateViewsMenuEntry(viewType));
|
---|
| 139 | }
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | private MenuItem CreateViewsMenuEntry(Type viewType) {
|
---|
| 143 | MenuItem item = new MenuItem() { Header = viewType.Name };
|
---|
| 144 | item.Click += (sender, args) => {
|
---|
| 145 | ShowView((IView)Activator.CreateInstance(viewType, true));
|
---|
| 146 | };
|
---|
| 147 | return item;
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | #endregion
|
---|
| 151 |
|
---|
| 152 | #region menu discovery
|
---|
| 153 |
|
---|
| 154 | private void BuildRootMenu() {
|
---|
| 155 | foreach (Type menuItemType in
|
---|
| 156 | ApplicationManager.Manager
|
---|
| 157 | .GetTypes(UserInterfaceItemType)
|
---|
| 158 | .Where(t => t.GetInterface(typeof(IMenuItem).FullName) != null)) {
|
---|
| 159 | IMenuItem item = (IMenuItem)Activator.CreateInstance(menuItemType, true);
|
---|
| 160 | AddMenuItem(Menu.Items, item, item.Structure.GetEnumerator());
|
---|
| 161 | }
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | private void AddMenuItem(ItemCollection items, IMenuItem newItem, IEnumerator<string> structure) {
|
---|
| 165 | if (structure.MoveNext()) {
|
---|
| 166 | string name = structure.Current;
|
---|
| 167 | MenuItem parent = items.Cast<MenuItem>().SingleOrDefault(i => i.Header as string == name);
|
---|
| 168 | if (parent == null) {
|
---|
| 169 | parent = new MenuItem() { Header = name, Tag = newItem };
|
---|
| 170 | InsertSortedMenuItem(items, parent);
|
---|
| 171 | }
|
---|
| 172 | AddMenuItem(parent.Items, newItem, structure);
|
---|
| 173 | } else {
|
---|
| 174 | MenuItem item = new MenuItem() { Header = newItem.Name, Tag = newItem };
|
---|
| 175 | item.Click += (s, a) => newItem.Execute();
|
---|
| 176 | if (newItem.Image != null)
|
---|
| 177 | item.Icon = newItem.Image;
|
---|
| 178 | WPFMenuItem wpfItem = newItem as WPFMenuItem;
|
---|
| 179 | if (wpfItem != null) {
|
---|
| 180 | wpfItem.MenuItem = item;
|
---|
| 181 | item.IsEnabled = wpfItem.IsEnabled;
|
---|
| 182 | wpfItem.IsEnabledChanged += (s, a) => item.IsEnabled = wpfItem.IsEnabled;
|
---|
| 183 | }
|
---|
| 184 | InsertSortedMenuItem(items, item);
|
---|
| 185 | }
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | private static void InsertSortedMenuItem(ItemCollection items, MenuItem menuItem) {
|
---|
| 189 | IMenuItem newItem = menuItem.Tag as IMenuItem;
|
---|
| 190 | if (newItem == null) {
|
---|
| 191 | items.Add(menuItem);
|
---|
| 192 | } else {
|
---|
| 193 | int index = 0;
|
---|
| 194 | while (index < items.Count) {
|
---|
| 195 | MenuItem it = items[index] as MenuItem;
|
---|
| 196 | if (it == null) break;
|
---|
| 197 | IMenuItem item = it.Tag as IMenuItem;
|
---|
| 198 | if (item == null) break;
|
---|
| 199 | if (newItem.Position < item.Position) break;
|
---|
| 200 | index++;
|
---|
| 201 | }
|
---|
| 202 | items.Insert(index, menuItem);
|
---|
| 203 | }
|
---|
| 204 | }
|
---|
| 205 |
|
---|
| 206 | #endregion
|
---|
| 207 |
|
---|
| 208 | #region tool bar discovery
|
---|
| 209 |
|
---|
| 210 | private void BuildToolBar() {
|
---|
| 211 | foreach (Type itemType in
|
---|
| 212 | ApplicationManager.Manager
|
---|
| 213 | .GetTypes(UserInterfaceItemType)
|
---|
| 214 | .Where(t => t.GetInterface(typeof(IToolBarItem).FullName) != null)) {
|
---|
| 215 | IToolBarItem item = (IToolBarItem)Activator.CreateInstance(itemType, true);
|
---|
| 216 | StackPanel visualItem = new StackPanel() { Orientation = Orientation.Vertical };
|
---|
| 217 | Image image =
|
---|
| 218 | ImageConverter.Win32Image2WPFImage(item.Image) ??
|
---|
| 219 | new Image() {
|
---|
| 220 | Source = new BitmapImage(new Uri(
|
---|
| 221 | "pack://application:,,,/" +
|
---|
| 222 | Assembly.GetExecutingAssembly().GetName().Name +
|
---|
| 223 | ";component/Images/Lambda.png"))
|
---|
| 224 | };
|
---|
| 225 | image.Width = ToolBarImageSize.Width;
|
---|
| 226 | image.Height = ToolBarImageSize.Height;
|
---|
| 227 | image.Stretch = Stretch.UniformToFill;
|
---|
| 228 | visualItem.Children.Add(image);
|
---|
| 229 | visualItem.Children.Add(new TextBlock() { Text = item.Name });
|
---|
| 230 | Button b = new Button() { Content = visualItem };
|
---|
| 231 | b.Click += (s, a) => item.Execute();
|
---|
| 232 | WPFToolBarItem wpfItem = item as WPFToolBarItem;
|
---|
| 233 | if (wpfItem != null) {
|
---|
| 234 | b.IsEnabled = wpfItem.IsEnabled;
|
---|
| 235 | if (wpfItem.IsVisible)
|
---|
| 236 | b.Visibility = Visibility.Visible;
|
---|
| 237 | else
|
---|
| 238 | b.Visibility = Visibility.Collapsed;
|
---|
| 239 | wpfItem.IsEnabledChanged += (s, a) => b.IsEnabled = wpfItem.IsEnabled;
|
---|
| 240 | wpfItem.IsVisibleChanged += (s, a) => {
|
---|
| 241 | if (wpfItem.IsVisible)
|
---|
| 242 | b.Visibility = Visibility.Visible;
|
---|
| 243 | else
|
---|
| 244 | b.Visibility = Visibility.Collapsed;
|
---|
| 245 | };
|
---|
| 246 | }
|
---|
| 247 | ToolBar.Items.Add(b);
|
---|
| 248 | }
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | #endregion
|
---|
| 252 |
|
---|
| 253 | #region Background Worker Monitoring
|
---|
| 254 |
|
---|
| 255 | private void InitializeBackgroundWorkerMonitoring() {
|
---|
| 256 | var BackgroundWorkerView = new DispatchedView<ObservableBackgroundWorker>(
|
---|
| 257 | WorkerMonitor.Default, Dispatcher, DispatcherPriority.SystemIdle);
|
---|
| 258 | BackgroundWorkers.ItemsSource = BackgroundWorkerView;
|
---|
| 259 | BackgroundWorkerView.CollectionChanged += (sender, args) => {
|
---|
| 260 | if (args.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) {
|
---|
| 261 | if (Cursor != Cursors.AppStarting)
|
---|
| 262 | Cursor = Cursors.AppStarting;
|
---|
| 263 | } else {
|
---|
| 264 | bool active = BackgroundWorkerView.Count() > 0;
|
---|
| 265 | if (active && Cursor == Cursors.Arrow) {
|
---|
| 266 | Cursor = Cursors.AppStarting;
|
---|
| 267 | } else if (!active && Cursor == Cursors.AppStarting) {
|
---|
| 268 | Cursor = Cursors.Arrow;
|
---|
| 269 | }
|
---|
| 270 | }
|
---|
| 271 | };
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | protected void OperationAborted(object sender, RoutedEventArgs args) {
|
---|
| 275 | Button button = args.OriginalSource as Button;
|
---|
| 276 | if (button == null) return;
|
---|
| 277 | ObservableBackgroundWorker worker = button.Tag as ObservableBackgroundWorker;
|
---|
| 278 | if (worker == null) return;
|
---|
| 279 | if (worker.WorkerSupportsCancellation &&
|
---|
| 280 | MessageBox.Show(this,
|
---|
| 281 | String.Format("Do you want to cancel the background execution of '{0}'?", worker.Name), Title,
|
---|
| 282 | MessageBoxButton.YesNo, MessageBoxImage.Question) ==
|
---|
| 283 | MessageBoxResult.Yes)
|
---|
| 284 | worker.CancelAsync();
|
---|
| 285 | args.Handled = true;
|
---|
| 286 | }
|
---|
| 287 |
|
---|
| 288 | protected override void OnClosing(CancelEventArgs e) {
|
---|
| 289 | base.OnClosing(e);
|
---|
| 290 | if (WorkerMonitor.Default.Count() > 0) {
|
---|
| 291 | var result = MessageBox.Show(
|
---|
| 292 | this,
|
---|
| 293 | "You have tasks running in the background. Do you want to signal and wait for their termination?",
|
---|
| 294 | Title,
|
---|
| 295 | MessageBoxButton.YesNoCancel,
|
---|
| 296 | MessageBoxImage.Warning);
|
---|
| 297 | if (result == MessageBoxResult.Cancel || result == MessageBoxResult.None)
|
---|
| 298 | e.Cancel = true;
|
---|
| 299 | else if (result == MessageBoxResult.Yes)
|
---|
| 300 | WorkerMonitor.Default.CancelAllAsync();
|
---|
| 301 | Thread.Sleep(0);
|
---|
| 302 | }
|
---|
| 303 | }
|
---|
| 304 |
|
---|
| 305 | protected override void OnClosed(EventArgs e) {
|
---|
| 306 | AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
|
---|
| 307 | Dispatcher.UnhandledException -= Dispatcher_UnhandledException;
|
---|
| 308 | WorkerMonitor.Default.BackgroundWorkerException += WorkerMonitor_BackgroundWorkerException;
|
---|
| 309 | base.OnClosed(e);
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | #endregion
|
---|
| 313 |
|
---|
| 314 | #region Status Messages
|
---|
| 315 |
|
---|
| 316 | class Message : IStatusMessage {
|
---|
| 317 |
|
---|
| 318 | public string Text { get; set; }
|
---|
| 319 | public Action HideAction { get; set; }
|
---|
| 320 |
|
---|
| 321 | public override string ToString() {
|
---|
| 322 | return Text;
|
---|
| 323 | }
|
---|
| 324 |
|
---|
| 325 | public void Hide() {
|
---|
| 326 | HideAction();
|
---|
| 327 | }
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | public interface IStatusMessage {
|
---|
| 331 | string Text { get; }
|
---|
| 332 | void Hide();
|
---|
| 333 | }
|
---|
| 334 |
|
---|
| 335 | public IStatusMessage ShowMessage(string message, TimeSpan duration) {
|
---|
| 336 | Message m = new Message() { Text = message };
|
---|
| 337 | DispatcherTimer timer = new DispatcherTimer() { Interval = duration };
|
---|
| 338 | Action hideAction = () => {
|
---|
| 339 | Messages.Items.Remove(m);
|
---|
| 340 | timer.Stop();
|
---|
| 341 | };
|
---|
| 342 | m.HideAction = hideAction;
|
---|
| 343 | Messages.Items.Add(m);
|
---|
| 344 | if (duration != TimeSpan.Zero) {
|
---|
| 345 | timer.Tick += (sender, args) => {
|
---|
| 346 | hideAction();
|
---|
| 347 | };
|
---|
| 348 | timer.Start();
|
---|
| 349 | }
|
---|
| 350 | return m;
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | #endregion
|
---|
| 354 |
|
---|
| 355 | #region View management
|
---|
| 356 |
|
---|
| 357 | public event EventHandler<ViewEventArgs> ViewClosed;
|
---|
| 358 | public event EventHandler<ViewShownEventArgs> ViewShown;
|
---|
| 359 | public event EventHandler<ViewEventArgs> ViewHidden;
|
---|
| 360 |
|
---|
| 361 | protected void OnViewClosed(IView view) {
|
---|
| 362 | EventHandler<ViewEventArgs> handler = ViewClosed;
|
---|
| 363 | if (handler != null)
|
---|
| 364 | handler(this, new ViewEventArgs(view));
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | protected void OnViewShown(IView view, bool firstTimeShown) {
|
---|
| 368 | EventHandler<ViewShownEventArgs> handler = ViewShown;
|
---|
| 369 | if (handler != null)
|
---|
| 370 | handler(this, new ViewShownEventArgs(view, firstTimeShown));
|
---|
| 371 | }
|
---|
| 372 |
|
---|
| 373 | protected void OnViewHidden(IView view) {
|
---|
| 374 | EventHandler<ViewEventArgs> handler = ViewHidden;
|
---|
| 375 | if (handler != null)
|
---|
| 376 | handler(this, new ViewEventArgs(view));
|
---|
| 377 | }
|
---|
| 378 |
|
---|
| 379 | public IEnumerable<IView> Views {
|
---|
| 380 | get {
|
---|
| 381 | return DockingManager.DockableContents
|
---|
| 382 | .Select(c => c.Content)
|
---|
| 383 | .Where(c => c is IView)
|
---|
| 384 | .Cast<IView>().AsEnumerable();
|
---|
| 385 | }
|
---|
| 386 | }
|
---|
| 387 |
|
---|
| 388 | public IView ActiveView {
|
---|
| 389 | get {
|
---|
| 390 | return DockingManager.ActiveContent as IView;
|
---|
| 391 | }
|
---|
| 392 | }
|
---|
| 393 |
|
---|
| 394 | protected void OnActiveDocumentChanged() {
|
---|
| 395 | EventHandler handler = ActiveViewChanged;
|
---|
| 396 | if (handler != null)
|
---|
| 397 | handler(null, EventArgs.Empty);
|
---|
| 398 | }
|
---|
| 399 |
|
---|
| 400 | public event EventHandler ActiveViewChanged;
|
---|
| 401 |
|
---|
| 402 | private void ShowObjectAsView(object o, string name) {
|
---|
| 403 | if (o as System.Windows.Forms.Control != null) {
|
---|
| 404 | o = new WindowsFormsHost() { Child = (System.Windows.Forms.Control)o };
|
---|
| 405 | }
|
---|
| 406 | var content = new DockableContent() {
|
---|
| 407 | Content = o,
|
---|
| 408 | Title = name,
|
---|
| 409 | HideOnClose = false,
|
---|
| 410 | };
|
---|
| 411 | DocumentPane.Items.Add(content);
|
---|
| 412 | DocumentPane.SelectedItem = content;
|
---|
| 413 | }
|
---|
| 414 |
|
---|
| 415 | public DockableContent AddView(IView view) {
|
---|
| 416 | try {
|
---|
| 417 | DockableContent content = new DockableContent() {
|
---|
| 418 | Content = view,
|
---|
| 419 | Title = view.Caption,
|
---|
| 420 | HideOnClose = true, // to enable capturing of state change events
|
---|
| 421 | };
|
---|
| 422 | content.StateChanged += (s, a) => {
|
---|
| 423 | if (a == DockableContentState.Hidden) {
|
---|
| 424 | OnViewClosed(view);
|
---|
| 425 | content.HideOnClose = false;
|
---|
| 426 | // HideOnClose moves content to _hiddenContents private member.
|
---|
| 427 | // To remove it from there, we have to show the content again
|
---|
| 428 | // to move it back into an accessible container and remove
|
---|
| 429 | // it from there.
|
---|
| 430 | Dispatcher.BeginInvoke(new Action(() => {
|
---|
| 431 | DockingManager.Show(content);
|
---|
| 432 | content.ContainerPane.Items.Remove(content);
|
---|
| 433 | }));
|
---|
| 434 | } else {
|
---|
| 435 | OnViewShown(view, false);
|
---|
| 436 | }
|
---|
| 437 | };
|
---|
| 438 | DocumentPane.Items.Add(content);
|
---|
| 439 | DocumentPane.SelectedItem = content;
|
---|
| 440 | OnViewShown(view, true);
|
---|
| 441 | return content;
|
---|
| 442 | } catch (Exception x) {
|
---|
| 443 | MessageBox.Show(this,
|
---|
| 444 | String.Format("Could not add view '{0}':\n{1}", view.Caption, x.ToString()),
|
---|
| 445 | Title,
|
---|
| 446 | MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
---|
| 447 | return null;
|
---|
| 448 | }
|
---|
| 449 | }
|
---|
| 450 |
|
---|
| 451 | /// <summary>
|
---|
| 452 | /// Show existing view or create new one. Return true if this is the first time shown.
|
---|
| 453 | /// </summary>
|
---|
| 454 | public bool ShowView(IView view) {
|
---|
| 455 | DockableContent content = GetContent(view);
|
---|
| 456 | if (content == null) {
|
---|
| 457 | content = AddView(view);
|
---|
| 458 | return true;
|
---|
| 459 | } else {
|
---|
| 460 | DockingManager.Show(content);
|
---|
| 461 | content.ContainerPane.SelectedItem = content;
|
---|
| 462 | OnViewShown(view, false);
|
---|
| 463 | return false;
|
---|
| 464 | }
|
---|
| 465 | }
|
---|
| 466 |
|
---|
| 467 | public void HideView(IView view) {
|
---|
| 468 | DockableContent content = GetContent(view);
|
---|
| 469 | if (content != null)
|
---|
| 470 | DockingManager.Hide(content);
|
---|
| 471 | OnViewHidden(view);
|
---|
| 472 | }
|
---|
| 473 |
|
---|
| 474 | public void CloseView(IView view) {
|
---|
| 475 | DockableContent content = GetContent(view);
|
---|
| 476 | content.ContainerPane.Items.Remove(content);
|
---|
| 477 | OnViewClosed(view);
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | public void CloseAllViews() {
|
---|
| 481 | foreach (var viewContainer in DockingManager.DockableContents.Where(c => c.Content is IView)) {
|
---|
| 482 | viewContainer.ContainerPane.Items.Remove(viewContainer);
|
---|
| 483 | OnViewClosed(viewContainer.Content as IView);
|
---|
| 484 | }
|
---|
| 485 | }
|
---|
| 486 |
|
---|
| 487 | private DockableContent GetContent(IView view) {
|
---|
| 488 | DockableContent content =
|
---|
| 489 | DockingManager
|
---|
| 490 | .DockableContents
|
---|
| 491 | .SingleOrDefault(c => c.Content as IView == view);
|
---|
| 492 | return content;
|
---|
| 493 | }
|
---|
| 494 |
|
---|
| 495 | #endregion
|
---|
| 496 |
|
---|
| 497 | #region IMainForm
|
---|
| 498 |
|
---|
| 499 | public event EventHandler Changed;
|
---|
| 500 |
|
---|
| 501 | protected void OnChanged() {
|
---|
| 502 | EventHandler handler = Changed;
|
---|
| 503 | if (handler != null)
|
---|
| 504 | handler(this, EventArgs.Empty);
|
---|
| 505 | }
|
---|
| 506 |
|
---|
| 507 | #endregion
|
---|
| 508 | }
|
---|
| 509 | }
|
---|