/// <summary> /// Dependency property event once the focused mdi child has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void ActiveMdiChildValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var mdiContainer = (MdiContainer) sender; MdiChild newChild = (MdiChild) e.NewValue, oldChild = (MdiChild) e.OldValue; if (newChild == null || newChild == oldChild) return; if (oldChild != null && oldChild.WindowState == WindowState.Maximized) newChild.WindowState = WindowState.Maximized; int maxZindex = 0; for (int i = 0; i < mdiContainer.Children.Count; i++) { int zindex = Panel.GetZIndex(mdiContainer.Children[i]); if (zindex > maxZindex) maxZindex = zindex; if (mdiContainer.Children[i] != newChild) mdiContainer.Children[i].Focused = false; else newChild.Focused = true; } Panel.SetZIndex(newChild, maxZindex + 1); if (mdiContainer.MdiChildTitleChanged != null) mdiContainer.MdiChildTitleChanged(mdiContainer, new RoutedEventArgs()); }
public void AddChild(Behaviors.Bot bot) { var child = new MdiChild(); child.Title = "Bot"; child.Content = new BotControl(bot); child.Closed += OnChildClosed; MdiContainer.Children.Add(child); }
/// <summary> /// Handles the SizeChanged event of the MdiContainer control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.SizeChangedEventArgs"/> instance containing the event data.</param> private void MdiContainer_SizeChanged(object sender, SizeChangedEventArgs e) { if (Children.Count == 0) return; for (int i = 0; i < Children.Count; i++) { MdiChild mdiChild = Children[i]; if (mdiChild.WindowState == WindowState.Maximized) { mdiChild.Width = ActualWidth; mdiChild.Height = ActualHeight; } if (mdiChild.WindowState == WindowState.Minimized) { mdiChild.Position = new Point(mdiChild.Position.X, mdiChild.Position.Y + e.NewSize.Height - e.PreviousSize.Height); } } }
/// <summary> /// Handles the CollectionChanged event of the Children control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Collections.Specialized.NotifyCollectionChangedEventArgs"/> instance containing the event data.</param> private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: { MdiChild mdiChild = Children[e.NewStartingIndex], topChild = ActiveMdiChild; if (topChild != null && topChild.WindowState == WindowState.Maximized) mdiChild.Loaded += (s, a) => mdiChild.WindowState = WindowState.Maximized; mdiChild.Loaded += (s, a) => ActiveMdiChild = mdiChild; if (mdiChild.Position.X < 0 || mdiChild.Position.Y < 0) mdiChild.Position = new Point(m_windowOffset, m_windowOffset); m_windowCanvas.Children.Add(mdiChild); m_windowOffset += WindowOffset; if (m_windowOffset + mdiChild.Width > ActualWidth) m_windowOffset = 0; if (m_windowOffset + mdiChild.Height > ActualHeight) m_windowOffset = 0; } break; case NotifyCollectionChangedAction.Remove: { var oldChild = (MdiChild) e.OldItems[0]; m_windowCanvas.Children.Remove(oldChild); MdiChild newChild = GetTopChild(); ActiveMdiChild = newChild; if (newChild != null && oldChild.WindowState == WindowState.Maximized) newChild.WindowState = WindowState.Maximized; } break; case NotifyCollectionChangedAction.Reset: m_windowCanvas.Children.Clear(); break; } InvalidateSize(); }
/// <summary> /// Invalidates the size checking to see if the furthest /// child point exceeds the current height and width. /// </summary> internal void InvalidateSize() { var largestPoint = new Point(0, 0); for (int i = 0; i < Children.Count; i++) { MdiChild mdiChild = Children[i]; var farPosition = new Point(mdiChild.Position.X + mdiChild.Width, mdiChild.Position.Y + mdiChild.Height); if (farPosition.X > largestPoint.X) largestPoint.X = farPosition.X; if (farPosition.Y > largestPoint.Y) largestPoint.Y = farPosition.Y; } if (m_windowCanvas.Width != largestPoint.X) m_windowCanvas.Width = largestPoint.X; if (m_windowCanvas.Height != largestPoint.Y) m_windowCanvas.Height = largestPoint.Y; }
/// <summary> /// Dependency property event once the MDI layout value has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void MdiLayoutValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var mdiContainer = (MdiContainer) sender; var value = (MdiLayout) e.NewValue; if (value == MdiLayout.ArrangeIcons || mdiContainer.Children.Count < 1) return; // 1. WindowState.Maximized -> WindowState.Normal List<MdiChild> minimizedWindows = new List<MdiChild>(), normalWindows = new List<MdiChild>(); foreach (MdiChild mdiChild in mdiContainer.Children) switch (mdiChild.WindowState) { case WindowState.Minimized: minimizedWindows.Add(mdiChild); break; case WindowState.Maximized: mdiChild.WindowState = WindowState.Normal; normalWindows.Add(mdiChild); break; default: normalWindows.Add(mdiChild); break; } minimizedWindows.Sort(new MdiChildComparer()); normalWindows.Sort(new MdiChildComparer()); // 2. Arrange minimized windows double containerHeight = mdiContainer.InnerHeight; for (int i = 0; i < minimizedWindows.Count; i++) { MdiChild mdiChild = minimizedWindows[i]; int capacity = Convert.ToInt32(mdiContainer.ActualWidth)/MdiChild.MinimizedWidth, row = i/capacity + 1, col = i%capacity; containerHeight = mdiContainer.InnerHeight - MdiChild.MinimizedHeight*row; double newLeft = MdiChild.MinimizedWidth*col; mdiChild.Position = new Point(newLeft, containerHeight); } // 3. Resize & arrange normal windows switch (value) { case MdiLayout.Cascade: { double newWidth = mdiContainer.ActualWidth*0.58, // should be non-linear formula here newHeight = containerHeight*0.67, windowOffset = 0; foreach (MdiChild mdiChild in normalWindows) { if (mdiChild.Resizable) { mdiChild.Width = newWidth; mdiChild.Height = newHeight; } mdiChild.Position = new Point(windowOffset, windowOffset); windowOffset += WindowOffset; if (windowOffset + mdiChild.Width > mdiContainer.ActualWidth) windowOffset = 0; if (windowOffset + mdiChild.Height > containerHeight) windowOffset = 0; } } break; case MdiLayout.TileHorizontal: { int cols = (int) Math.Sqrt(normalWindows.Count), rows = normalWindows.Count/cols; var col_count = new List<int>(); // windows per column for (int i = 0; i < cols; i++) { if (normalWindows.Count%cols > cols - i - 1) col_count.Add(rows + 1); else col_count.Add(rows); } double newWidth = mdiContainer.ActualWidth/cols, newHeight = containerHeight/col_count[0], offsetTop = 0, offsetLeft = 0; for (int i = 0, col_index = 0, prev_count = 0; i < normalWindows.Count; i++) { if (i >= prev_count + col_count[col_index]) { prev_count += col_count[col_index++]; offsetLeft += newWidth; offsetTop = 0; newHeight = containerHeight/col_count[col_index]; } MdiChild mdiChild = normalWindows[i]; if (mdiChild.Resizable) { mdiChild.Width = newWidth; mdiChild.Height = newHeight; } mdiChild.Position = new Point(offsetLeft, offsetTop); offsetTop += newHeight; } } break; case MdiLayout.TileVertical: { int rows = (int) Math.Sqrt(normalWindows.Count), cols = normalWindows.Count/rows; var col_count = new List<int>(); // windows per column for (int i = 0; i < cols; i++) { if (normalWindows.Count%cols > cols - i - 1) col_count.Add(rows + 1); else col_count.Add(rows); } double newWidth = mdiContainer.ActualWidth/cols, newHeight = containerHeight/col_count[0], offsetTop = 0, offsetLeft = 0; for (int i = 0, col_index = 0, prev_count = 0; i < normalWindows.Count; i++) { if (i >= prev_count + col_count[col_index]) { prev_count += col_count[col_index++]; offsetLeft += newWidth; offsetTop = 0; newHeight = containerHeight/col_count[col_index]; } MdiChild mdiChild = normalWindows[i]; if (mdiChild.Resizable) { mdiChild.Width = newWidth; mdiChild.Height = newHeight; } mdiChild.Position = new Point(offsetLeft, offsetTop); offsetTop += newHeight; } } break; } mdiContainer.InvalidateSize(); mdiContainer.MdiLayout = MdiLayout.ArrangeIcons; }
/// <summary> /// Dependency property event once the windows state value has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void WindowStateValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var mdiChild = (MdiChild)sender; MdiContainer mdiContainer = mdiChild.Container; var previousWindowState = (WindowState)e.OldValue; var windowState = (WindowState)e.NewValue; if (mdiChild.Container == null || previousWindowState == windowState) { return; } if (previousWindowState == WindowState.Maximized) { if (mdiContainer.ActiveMdiChild.WindowState != WindowState.Maximized) { for (int i = 0; i < mdiContainer.Children.Count; i++) { if (mdiContainer.Children[i] != mdiChild && mdiContainer.Children[i].WindowState == WindowState.Maximized && mdiContainer.Children[i].MaximizeBox) { mdiContainer.Children[i].WindowState = WindowState.Normal; } } var sv = (ScrollViewer)((Grid)mdiContainer.Content).Children[1]; sv.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; sv.VerticalScrollBarVisibility = ScrollBarVisibility.Auto; } mdiChild.Buttons.Children.Clear(); mdiChild.Buttons = null; mdiChild.buttonsPanel.Children.Add(mdiChild.minimizeButton); mdiChild.buttonsPanel.Children.Add(mdiChild.maximizeButton); mdiChild.buttonsPanel.Children.Add(mdiChild.closeButton); } if (previousWindowState == WindowState.Minimized) { mdiChild.minimizedPosition = mdiChild.Position; } switch (windowState) { case WindowState.Normal: { mdiChild.Position = new Point(mdiChild.originalDimension.X, mdiChild.originalDimension.Y); mdiChild.Width = mdiChild.originalDimension.Width; mdiChild.Height = mdiChild.originalDimension.Height; } break; case WindowState.Minimized: { if (previousWindowState == WindowState.Normal) { mdiChild.originalDimension = new Rect(mdiChild.Position.X, mdiChild.Position.Y, mdiChild.ActualWidth, mdiChild.ActualHeight); } double newLeft, newTop; if (mdiChild.minimizedPosition.X >= 0 || mdiChild.minimizedPosition.Y >= 0) { newLeft = mdiChild.minimizedPosition.X; newTop = mdiChild.minimizedPosition.Y; } else { var minimizedWindows = new List <Rect>(); for (int i = 0; i < mdiContainer.Children.Count; i++) { MdiChild child = mdiContainer.Children[i]; if (child != mdiChild && child.WindowState == WindowState.Minimized) { minimizedWindows.Add(new Rect(child.Position.X, mdiContainer.InnerHeight - child.Position.Y, child.Width, child.Height)); } } Rect newWindowPlace; bool occupied = true; int count = 0, capacity = Convert.ToInt32(mdiContainer.ActualWidth) / MinimizedWidth; do { int row = count / capacity + 1, col = count % capacity; newTop = MinimizedHeight * row; newLeft = MinimizedWidth * col; newWindowPlace = new Rect(newLeft, newTop, MinimizedWidth, MinimizedHeight); occupied = false; foreach (Rect rect in minimizedWindows) { Rect intersection = rect; intersection.Intersect(newWindowPlace); if (intersection != Rect.Empty && intersection.Width > 0 && intersection.Height > 0) { occupied = true; break; } } count++; // TODO: handle negative Canvas coordinates somehow. if (newTop < 0) { // ugly workaround for now. newTop = 0; occupied = false; } } while (occupied); newTop = mdiContainer.InnerHeight - newTop; } mdiChild.Position = new Point(newLeft, newTop); mdiChild.Width = MinimizedWidth; mdiChild.Height = MinimizedHeight; } break; case WindowState.Maximized: { if (previousWindowState == WindowState.Normal) { mdiChild.originalDimension = new Rect(mdiChild.Position.X, mdiChild.Position.Y, mdiChild.ActualWidth, mdiChild.ActualHeight); } mdiChild.NonMaximizedState = previousWindowState; mdiChild.buttonsPanel.Children.Clear(); var sp = new StackPanel { Orientation = Orientation.Horizontal }; sp.Children.Add(mdiChild.minimizeButton); sp.Children.Add(mdiChild.maximizeButton); sp.Children.Add(mdiChild.closeButton); mdiChild.Buttons = sp; mdiChild.Position = new Point(0, 0); mdiChild.Width = mdiContainer.ActualWidth; mdiChild.Height = mdiContainer.InnerHeight - 2; // ContentBorder.BorderThickness="1" in template var sv = (ScrollViewer)((Grid)mdiContainer.Content).Children[1]; sv.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; sv.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden; } break; } if (mdiContainer.ActiveMdiChild == mdiChild) { mdiContainer.Buttons = mdiChild.Buttons; } mdiContainer.InvalidateSize(); }