a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
1003 lines
26 KiB
C#
1003 lines
26 KiB
C#
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
|
//
|
|
// Authors:
|
|
// Peter Bartok pbartok@novell.com
|
|
//
|
|
//
|
|
|
|
// NOT COMPLETE
|
|
|
|
using System.Collections;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace System.Windows.Forms {
|
|
[ComVisible (true)]
|
|
[ClassInterface(ClassInterfaceType.AutoDispatch)]
|
|
[DesignTimeVisible(false)]
|
|
[ToolboxItem(false)]
|
|
public sealed class MdiClient : Control {
|
|
#region Local Variables
|
|
private int mdi_created;
|
|
private ImplicitHScrollBar hbar;
|
|
private ImplicitVScrollBar vbar;
|
|
private SizeGrip sizegrip;
|
|
private int hbar_value;
|
|
private int vbar_value;
|
|
private bool lock_sizing;
|
|
private bool initializing_scrollbars;
|
|
private int prev_bottom;
|
|
private bool setting_windowstates = false;
|
|
internal ArrayList mdi_child_list;
|
|
private string form_text;
|
|
private bool setting_form_text;
|
|
private Form active_child;
|
|
|
|
#endregion // Local Variables
|
|
|
|
#region Public Classes
|
|
[ComVisible (false)]
|
|
public new class ControlCollection : Control.ControlCollection {
|
|
|
|
private MdiClient owner;
|
|
|
|
public ControlCollection(MdiClient owner) : base(owner) {
|
|
this.owner = owner;
|
|
}
|
|
|
|
public override void Add(Control value) {
|
|
if ((value is Form) == false || !(((Form)value).IsMdiChild)) {
|
|
throw new ArgumentException("Form must be MdiChild");
|
|
}
|
|
owner.mdi_child_list.Add (value);
|
|
base.Add (value);
|
|
|
|
// newest member is the active one
|
|
Form form = (Form) value;
|
|
owner.ActiveMdiChild = form;
|
|
}
|
|
|
|
public override void Remove(Control value)
|
|
{
|
|
Form form = value as Form;
|
|
if (form != null) {
|
|
MdiWindowManager wm = form.WindowManager as MdiWindowManager;
|
|
if (wm != null) {
|
|
form.Closed -= wm.form_closed_handler;
|
|
}
|
|
}
|
|
|
|
owner.mdi_child_list.Remove (value);
|
|
base.Remove (value);
|
|
}
|
|
}
|
|
#endregion // Public Classes
|
|
|
|
#region Public Constructors
|
|
public MdiClient()
|
|
{
|
|
mdi_child_list = new ArrayList ();
|
|
BackColor = SystemColors.AppWorkspace;
|
|
Dock = DockStyle.Fill;
|
|
SetStyle (ControlStyles.Selectable, false);
|
|
}
|
|
#endregion // Public Constructors
|
|
|
|
internal void SendFocusToActiveChild ()
|
|
{
|
|
Form active = this.ActiveMdiChild;
|
|
if (active == null) {
|
|
ParentForm.SendControlFocus (this);
|
|
} else {
|
|
active.SendControlFocus (active);
|
|
ParentForm.ActiveControl = active;
|
|
}
|
|
}
|
|
|
|
internal bool HorizontalScrollbarVisible {
|
|
get { return hbar != null && hbar.Visible; }
|
|
}
|
|
internal bool VerticalScrollbarVisible {
|
|
get { return vbar != null && vbar.Visible; }
|
|
}
|
|
|
|
internal void SetParentText(bool text_changed)
|
|
{
|
|
if (setting_form_text)
|
|
return;
|
|
|
|
setting_form_text = true;
|
|
|
|
if (text_changed)
|
|
form_text = ParentForm.Text;
|
|
|
|
if (ParentForm.ActiveMaximizedMdiChild == null) {
|
|
ParentForm.Text = form_text;
|
|
} else {
|
|
string childText = ParentForm.ActiveMaximizedMdiChild.form.Text;
|
|
if (childText.Length > 0) {
|
|
ParentForm.Text = form_text + " - [" + ParentForm.ActiveMaximizedMdiChild.form.Text + "]";
|
|
} else {
|
|
ParentForm.Text = form_text;
|
|
}
|
|
}
|
|
|
|
setting_form_text = false;
|
|
}
|
|
|
|
internal override void OnPaintBackgroundInternal (PaintEventArgs pe)
|
|
{
|
|
if (BackgroundImage != null)
|
|
return;
|
|
|
|
if (Parent == null || Parent.BackgroundImage == null)
|
|
return;
|
|
Parent.PaintControlBackground (pe);
|
|
}
|
|
|
|
internal Form ParentForm {
|
|
get { return (Form) Parent; }
|
|
}
|
|
|
|
protected override Control.ControlCollection CreateControlsInstance ()
|
|
{
|
|
return new MdiClient.ControlCollection (this);
|
|
}
|
|
|
|
protected override void WndProc(ref Message m) {
|
|
switch ((Msg)m.Msg) {
|
|
case Msg.WM_NCPAINT:
|
|
PaintEventArgs pe = XplatUI.PaintEventStart (ref m, Handle, false);
|
|
|
|
Rectangle clip;
|
|
clip = new Rectangle (0, 0, Width, Height);
|
|
|
|
ControlPaint.DrawBorder3D (pe.Graphics, clip, Border3DStyle.Sunken);
|
|
XplatUI.PaintEventEnd (ref m, Handle, false);
|
|
m.Result = IntPtr.Zero;
|
|
return ;
|
|
}
|
|
|
|
base.WndProc (ref m);
|
|
}
|
|
|
|
protected override void OnResize (EventArgs e)
|
|
{
|
|
base.OnResize (e);
|
|
|
|
if (Parent != null && Parent.IsHandleCreated)
|
|
XplatUI.InvalidateNC (Parent.Handle);
|
|
// Should probably make this into one loop
|
|
SizeScrollBars ();
|
|
ArrangeWindows ();
|
|
}
|
|
|
|
protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
|
|
{
|
|
// Never change the MdiClient's location
|
|
specified &= ~BoundsSpecified.Location;
|
|
|
|
base.ScaleControl (factor, specified);
|
|
}
|
|
|
|
[System.ComponentModel.EditorBrowsable (EditorBrowsableState.Never)]
|
|
protected override void ScaleCore (float dx, float dy)
|
|
{
|
|
base.ScaleCore (dx, dy);
|
|
}
|
|
|
|
protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
|
|
{
|
|
base.SetBoundsCore (x, y, width, height, specified);
|
|
}
|
|
|
|
#region Public Instance Properties
|
|
[Localizable(true)]
|
|
public override System.Drawing.Image BackgroundImage {
|
|
get {
|
|
return base.BackgroundImage;
|
|
}
|
|
set {
|
|
base.BackgroundImage = value;
|
|
}
|
|
}
|
|
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
[Browsable (false)]
|
|
public override ImageLayout BackgroundImageLayout {
|
|
get {
|
|
return base.BackgroundImageLayout;
|
|
}
|
|
set {
|
|
base.BackgroundImageLayout = value;
|
|
}
|
|
}
|
|
|
|
public Form [] MdiChildren {
|
|
get {
|
|
if (mdi_child_list == null)
|
|
return new Form [0];
|
|
return (Form []) mdi_child_list.ToArray (typeof (Form));
|
|
}
|
|
}
|
|
#endregion // Public Instance Properties
|
|
|
|
#region Protected Instance Properties
|
|
protected override CreateParams CreateParams {
|
|
get {
|
|
CreateParams result = base.CreateParams;
|
|
result.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE;
|
|
return result;
|
|
}
|
|
}
|
|
#endregion // Protected Instance Properties
|
|
|
|
#region Public Instance Methods
|
|
public void LayoutMdi (MdiLayout value) {
|
|
|
|
// Don't forget to always call ArrangeIconicWindows
|
|
ArrangeIconicWindows (true);
|
|
|
|
switch (value) {
|
|
case MdiLayout.Cascade: {
|
|
int i = 0;
|
|
for (int c = Controls.Count - 1; c >= 0; c--) {
|
|
Form form = (Form) Controls [c];
|
|
|
|
if (form.WindowState == FormWindowState.Minimized)
|
|
continue;
|
|
|
|
if (form.WindowState == FormWindowState.Maximized)
|
|
form.WindowState = FormWindowState.Normal;
|
|
|
|
form.Width = System.Convert.ToInt32 (ClientSize.Width * 0.8);
|
|
form.Height = Math.Max (
|
|
System.Convert.ToInt32 (ClientSize.Height * 0.8),
|
|
SystemInformation.MinimumWindowSize.Height + 2);
|
|
|
|
int l = 22 * i;
|
|
int t = 22 * i;
|
|
|
|
if (i != 0 && (l + form.Width > ClientSize.Width || t + form.Height > ClientSize.Height)) {
|
|
i = 0;
|
|
l = 22 * i;
|
|
t = 22 * i;
|
|
}
|
|
|
|
form.Left = l;
|
|
form.Top = t;
|
|
|
|
i++;
|
|
}
|
|
break;
|
|
}
|
|
case MdiLayout.TileHorizontal:
|
|
case MdiLayout.TileVertical: {
|
|
// First count number of windows to tile
|
|
int total = 0;
|
|
|
|
// And space used by iconic windows
|
|
int clientHeight = ClientSize.Height;
|
|
|
|
for (int i = 0; i < Controls.Count; i++) {
|
|
Form form = Controls [i] as Form;
|
|
|
|
if (form == null)
|
|
continue;
|
|
|
|
if (!form.Visible)
|
|
continue;
|
|
|
|
if (form.WindowState == FormWindowState.Maximized)
|
|
form.WindowState = FormWindowState.Normal;
|
|
else if (form.WindowState == FormWindowState.Minimized) {
|
|
if (form.Bounds.Top < clientHeight)
|
|
clientHeight = form.Bounds.Top;
|
|
continue;
|
|
}
|
|
|
|
total++;
|
|
}
|
|
if (total <= 0)
|
|
return;
|
|
|
|
// Calculate desired height and width
|
|
Size newSize;
|
|
Size offset;
|
|
|
|
if (value == MdiLayout.TileHorizontal) {
|
|
newSize = new Size(ClientSize.Width, clientHeight / total);
|
|
offset = new Size (0, newSize.Height);
|
|
} else {
|
|
newSize = new Size(ClientSize.Width / total, clientHeight);
|
|
offset = new Size (newSize.Width, 0);
|
|
}
|
|
|
|
// Loop again and set the size and location.
|
|
Point nextLocation = Point.Empty;
|
|
|
|
for (int i = 0; i < Controls.Count; i++) {
|
|
Form form = Controls [i] as Form;
|
|
|
|
if (form == null)
|
|
continue;
|
|
|
|
if (!form.Visible)
|
|
continue;
|
|
|
|
if (form.WindowState == FormWindowState.Minimized)
|
|
continue;
|
|
|
|
form.Size = newSize;
|
|
form.Location = nextLocation;
|
|
nextLocation += offset;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endregion // Public Instance Methods
|
|
|
|
#region Protected Instance Methods
|
|
#endregion // Protected Instance Methods
|
|
|
|
internal void SizeScrollBars ()
|
|
{
|
|
if (lock_sizing)
|
|
return;
|
|
|
|
if (!IsHandleCreated)
|
|
return;
|
|
|
|
if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) {
|
|
if (hbar != null)
|
|
hbar.Visible = false;
|
|
if (vbar != null)
|
|
vbar.Visible = false;
|
|
if (sizegrip != null)
|
|
sizegrip.Visible = false;
|
|
return;
|
|
}
|
|
|
|
int right = 0;
|
|
int left = 0;
|
|
int top = 0;
|
|
int bottom = 0;
|
|
|
|
foreach (Form child in Controls) {
|
|
if (!child.Visible)
|
|
continue;
|
|
if (child.Right > right)
|
|
right = child.Right;
|
|
if (child.Left < left) {
|
|
left = child.Left;
|
|
}
|
|
|
|
if (child.Bottom > bottom)
|
|
bottom = child.Bottom;
|
|
if (child.Top < 0) {
|
|
top = child.Top;
|
|
}
|
|
}
|
|
|
|
int available_width = ClientSize.Width;
|
|
int available_height = ClientSize.Height;
|
|
|
|
bool need_hbar = false;
|
|
bool need_vbar = false;
|
|
|
|
if (right - left > available_width || left < 0) {
|
|
need_hbar = true;
|
|
available_height -= SystemInformation.HorizontalScrollBarHeight;
|
|
}
|
|
if (bottom - top > available_height || top < 0) {
|
|
need_vbar = true;
|
|
available_width -= SystemInformation.VerticalScrollBarWidth;
|
|
|
|
if (!need_hbar && (right - left > available_width || left < 0)) {
|
|
need_hbar = true;
|
|
available_height -= SystemInformation.HorizontalScrollBarHeight;
|
|
}
|
|
}
|
|
|
|
if (need_hbar) {
|
|
if (hbar == null) {
|
|
hbar = new ImplicitHScrollBar ();
|
|
Controls.AddImplicit (hbar);
|
|
}
|
|
hbar.Visible = true;
|
|
CalcHBar (left, right, need_vbar);
|
|
} else if (hbar != null)
|
|
hbar.Visible = false;
|
|
|
|
if (need_vbar) {
|
|
if (vbar == null) {
|
|
vbar = new ImplicitVScrollBar ();
|
|
Controls.AddImplicit (vbar);
|
|
}
|
|
vbar.Visible = true;
|
|
CalcVBar (top, bottom, need_hbar);
|
|
} else if (vbar != null)
|
|
vbar.Visible = false;
|
|
|
|
if (need_hbar && need_vbar) {
|
|
if (sizegrip == null) {
|
|
sizegrip = new SizeGrip (this.ParentForm);
|
|
Controls.AddImplicit (sizegrip);
|
|
}
|
|
sizegrip.Location = new Point (hbar.Right, vbar.Bottom);
|
|
sizegrip.Visible = true;
|
|
XplatUI.SetZOrder (sizegrip.Handle, vbar.Handle, false, false);
|
|
} else if (sizegrip != null) {
|
|
sizegrip.Visible = false;
|
|
}
|
|
|
|
XplatUI.InvalidateNC (Handle);
|
|
}
|
|
|
|
private void CalcHBar (int left, int right, bool vert_vis)
|
|
{
|
|
initializing_scrollbars = true;
|
|
|
|
hbar.Left = 0;
|
|
hbar.Top = ClientRectangle.Bottom - hbar.Height;
|
|
hbar.Width = ClientRectangle.Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
|
|
hbar.LargeChange = 50;
|
|
hbar.Minimum = Math.Min (left, 0);
|
|
hbar.Maximum = Math.Max (right - ClientSize.Width + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0), 0);
|
|
hbar.Value = 0;
|
|
hbar_value = 0;
|
|
hbar.ValueChanged += new EventHandler (HBarValueChanged);
|
|
XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
|
|
|
|
initializing_scrollbars = false;
|
|
}
|
|
|
|
private void CalcVBar (int top, int bottom, bool horz_vis)
|
|
{
|
|
initializing_scrollbars = true;
|
|
|
|
vbar.Top = 0;
|
|
vbar.Left = ClientRectangle.Right - vbar.Width;
|
|
vbar.Height = ClientRectangle.Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
|
|
vbar.LargeChange = 50;
|
|
vbar.Minimum = Math.Min (top, 0);
|
|
vbar.Maximum = Math.Max (bottom - ClientSize.Height + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0), 0);
|
|
vbar.Value = 0;
|
|
vbar_value = 0;
|
|
vbar.ValueChanged += new EventHandler (VBarValueChanged);
|
|
XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
|
|
|
|
initializing_scrollbars = false;
|
|
}
|
|
|
|
private void HBarValueChanged (object sender, EventArgs e)
|
|
{
|
|
if (initializing_scrollbars)
|
|
return;
|
|
|
|
if (hbar.Value == hbar_value)
|
|
return;
|
|
|
|
lock_sizing = true;
|
|
|
|
try {
|
|
int diff = hbar_value - hbar.Value;
|
|
foreach (Form child in Controls) {
|
|
child.Left += diff;
|
|
}
|
|
} finally {
|
|
lock_sizing = false;
|
|
}
|
|
|
|
hbar_value = hbar.Value;
|
|
}
|
|
|
|
private void VBarValueChanged (object sender, EventArgs e)
|
|
{
|
|
if (initializing_scrollbars)
|
|
return;
|
|
|
|
if (vbar.Value == vbar_value)
|
|
return;
|
|
|
|
lock_sizing = true;
|
|
|
|
try {
|
|
int diff = vbar_value - vbar.Value;
|
|
foreach (Form child in Controls) {
|
|
child.Top += diff;
|
|
}
|
|
} finally {
|
|
lock_sizing = false;
|
|
}
|
|
|
|
vbar_value = vbar.Value;
|
|
}
|
|
|
|
private void ArrangeWindows ()
|
|
{
|
|
if (!IsHandleCreated)
|
|
return;
|
|
|
|
int change = 0;
|
|
if (prev_bottom != -1)
|
|
change = Bottom - prev_bottom;
|
|
|
|
foreach (Control c in Controls) {
|
|
Form child = c as Form;
|
|
|
|
if (c == null || !child.Visible)
|
|
continue;
|
|
|
|
MdiWindowManager wm = child.WindowManager as MdiWindowManager;
|
|
if (wm.GetWindowState () == FormWindowState.Maximized)
|
|
child.Bounds = wm.MaximizedBounds;
|
|
|
|
if (wm.GetWindowState () == FormWindowState.Minimized) {
|
|
child.Top += change;
|
|
}
|
|
|
|
}
|
|
|
|
prev_bottom = Bottom;
|
|
}
|
|
|
|
internal void ArrangeIconicWindows (bool rearrange_all)
|
|
{
|
|
Rectangle rect = Rectangle.Empty;
|
|
|
|
lock_sizing = true;
|
|
foreach (Form form in Controls) {
|
|
if (form.WindowState != FormWindowState.Minimized)
|
|
continue;
|
|
|
|
MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
|
|
|
|
if (wm.IconicBounds != Rectangle.Empty && !rearrange_all) {
|
|
if (form.Bounds != wm.IconicBounds)
|
|
form.Bounds = wm.IconicBounds;
|
|
continue;
|
|
}
|
|
|
|
bool success = true;
|
|
int startx, starty, currentx, currenty;
|
|
|
|
rect.Size = wm.IconicSize;
|
|
|
|
startx = 0;
|
|
starty = ClientSize.Height - rect.Height;
|
|
currentx = startx;
|
|
currenty = starty;
|
|
|
|
do {
|
|
rect.X = currentx;
|
|
rect.Y = currenty;
|
|
success = true;
|
|
foreach (Form form2 in Controls) {
|
|
if (form2 == form || form2.window_state != FormWindowState.Minimized)
|
|
continue;
|
|
|
|
if (form2.Bounds.IntersectsWith(rect)) {
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!success) {
|
|
currentx += rect.Width;
|
|
if (currentx + rect.Width > Right) {
|
|
currentx = startx;
|
|
currenty -= rect.Height;
|
|
}
|
|
}
|
|
} while (!success);
|
|
wm.IconicBounds = rect;
|
|
form.Bounds = wm.IconicBounds;
|
|
}
|
|
lock_sizing = false;
|
|
}
|
|
|
|
internal void ChildFormClosed (Form form)
|
|
{
|
|
FormWindowState closed_form_windowstate = form.WindowState;
|
|
|
|
form.Visible = false;
|
|
Controls.Remove (form);
|
|
|
|
if (Controls.Count == 0) {
|
|
((MdiWindowManager) form.window_manager).RaiseDeactivate ();
|
|
} else if (closed_form_windowstate == FormWindowState.Maximized) {
|
|
Form current = (Form) Controls [0];
|
|
current.WindowState = FormWindowState.Maximized;
|
|
ActivateChild(current);
|
|
}
|
|
|
|
if (Controls.Count == 0) {
|
|
XplatUI.RequestNCRecalc (Parent.Handle);
|
|
ParentForm.PerformLayout ();
|
|
|
|
// If we closed the last child, unmerge the menus.
|
|
// If it's not the last child, the menu will be unmerged
|
|
// when another child takes focus.
|
|
MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
|
|
|
|
if (parent_menu != null)
|
|
if (parent_menu.IsCurrentlyMerged)
|
|
ToolStripManager.RevertMerge (parent_menu);
|
|
}
|
|
SizeScrollBars ();
|
|
SetParentText (false);
|
|
form.Dispose();
|
|
}
|
|
|
|
internal void ActivateNextChild ()
|
|
{
|
|
if (Controls.Count < 1)
|
|
return;
|
|
if (Controls.Count == 1 && Controls[0] == ActiveMdiChild)
|
|
return;
|
|
|
|
Form front = (Form) Controls [0];
|
|
Form form = (Form) Controls [1];
|
|
|
|
ActivateChild (form);
|
|
front.SendToBack ();
|
|
}
|
|
|
|
internal void ActivatePreviousChild ()
|
|
{
|
|
if (Controls.Count <= 1)
|
|
return;
|
|
|
|
Form back = (Form) Controls [Controls.Count - 1];
|
|
|
|
ActivateChild (back);
|
|
}
|
|
|
|
internal void ActivateChild (Form form)
|
|
{
|
|
if (Controls.Count < 1)
|
|
return;
|
|
|
|
if (ParentForm.is_changing_visible_state > 0)
|
|
return;
|
|
|
|
Form current = (Form) Controls [0];
|
|
bool raise_deactivate = ParentForm.ActiveControl == current;
|
|
|
|
// We want to resize the new active form before it is
|
|
// made active to avoid flickering. Can't do it in the
|
|
// normal way (form.WindowState = Maximized) since it's not
|
|
// active yet and everything would just return to before.
|
|
// We also won't suspend layout, this way the layout will
|
|
// happen before the form is made active (and in many cases
|
|
// before it is visible, which avoids flickering as well).
|
|
MdiWindowManager wm = (MdiWindowManager)form.WindowManager;
|
|
|
|
if (current.WindowState == FormWindowState.Maximized && form.WindowState != FormWindowState.Maximized && form.Visible) {
|
|
FormWindowState old_state = form.window_state;
|
|
SetWindowState (form, old_state, FormWindowState.Maximized, true);
|
|
wm.was_minimized = form.window_state == FormWindowState.Minimized;
|
|
form.window_state = FormWindowState.Maximized;
|
|
SetParentText (false);
|
|
}
|
|
|
|
form.BringToFront ();
|
|
form.SendControlFocus (form);
|
|
SetWindowStates (wm);
|
|
if (current != form) {
|
|
form.has_focus = false;
|
|
if (current.IsHandleCreated)
|
|
XplatUI.InvalidateNC (current.Handle);
|
|
if (form.IsHandleCreated)
|
|
XplatUI.InvalidateNC (form.Handle);
|
|
if (raise_deactivate) {
|
|
MdiWindowManager current_wm = (MdiWindowManager) current.window_manager;
|
|
current_wm.RaiseDeactivate ();
|
|
|
|
}
|
|
}
|
|
active_child = (Form) Controls [0];
|
|
|
|
if (active_child.Visible) {
|
|
bool raise_activated = ParentForm.ActiveControl != active_child;
|
|
ParentForm.ActiveControl = active_child;
|
|
if (raise_activated) {
|
|
MdiWindowManager active_wm = (MdiWindowManager) active_child.window_manager;
|
|
active_wm.RaiseActivated ();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal override IntPtr AfterTopMostControl ()
|
|
{
|
|
// order of scrollbars:
|
|
// top = vertical
|
|
// sizegrid
|
|
// bottom = horizontal
|
|
if (hbar != null && hbar.Visible)
|
|
return hbar.Handle;
|
|
// no need to check for sizegrip since it will only
|
|
// be visible if hbar is visible.
|
|
if (vbar != null && vbar.Visible)
|
|
return vbar.Handle;
|
|
|
|
return base.AfterTopMostControl ();
|
|
}
|
|
|
|
internal bool SetWindowStates (MdiWindowManager wm)
|
|
{
|
|
/*
|
|
MDI WindowState behaviour:
|
|
- If the active window is maximized, all other maximized windows are normalized.
|
|
- If a normal window gets focus and the original active window was maximized,
|
|
the normal window gets maximized and the original window gets normalized.
|
|
- If a minimized window gets focus and the original window was maximized,
|
|
the minimzed window gets maximized and the original window gets normalized.
|
|
If the ex-minimized window gets deactivated, it will be normalized.
|
|
*/
|
|
Form form = wm.form;
|
|
|
|
if (setting_windowstates) {
|
|
return false;
|
|
}
|
|
|
|
if (!form.Visible)
|
|
return false;
|
|
|
|
bool is_active = wm.IsActive;
|
|
bool maximize_this = false;
|
|
|
|
if (!is_active){
|
|
return false;
|
|
}
|
|
|
|
ArrayList minimize_these = new ArrayList ();
|
|
ArrayList normalize_these = new ArrayList ();
|
|
|
|
setting_windowstates = true;
|
|
foreach (Form frm in mdi_child_list) {
|
|
if (frm == form) {
|
|
continue;
|
|
} else if (!frm.Visible){
|
|
continue;
|
|
}
|
|
if (frm.WindowState == FormWindowState.Maximized && is_active) {
|
|
maximize_this = true;
|
|
if (((MdiWindowManager) frm.window_manager).was_minimized) {
|
|
minimize_these.Add (frm);
|
|
} else {
|
|
normalize_these.Add (frm);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (maximize_this && form.WindowState != FormWindowState.Maximized) {
|
|
wm.was_minimized = form.window_state == FormWindowState.Minimized;
|
|
form.WindowState = FormWindowState.Maximized;
|
|
}
|
|
|
|
foreach (Form frm in minimize_these)
|
|
frm.WindowState = FormWindowState.Minimized;
|
|
|
|
foreach (Form frm in normalize_these)
|
|
frm.WindowState = FormWindowState.Normal;
|
|
|
|
|
|
SetParentText (false);
|
|
|
|
XplatUI.RequestNCRecalc (ParentForm.Handle);
|
|
XplatUI.RequestNCRecalc (Handle);
|
|
|
|
SizeScrollBars ();
|
|
|
|
setting_windowstates = false;
|
|
|
|
if (form.MdiParent.MainMenuStrip != null)
|
|
form.MdiParent.MainMenuStrip.RefreshMdiItems ();
|
|
|
|
// Implicit menu strip merging
|
|
// - When child is activated
|
|
// - Parent form must have a MainMenuStrip
|
|
// - Find the first menustrip on the child
|
|
// - Merge
|
|
MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
|
|
|
|
if (parent_menu != null) {
|
|
if (parent_menu.IsCurrentlyMerged)
|
|
ToolStripManager.RevertMerge (parent_menu);
|
|
|
|
MenuStrip child_menu = LookForChildMenu (form);
|
|
|
|
if (form.WindowState != FormWindowState.Maximized)
|
|
RemoveControlMenuItems (wm);
|
|
|
|
if (form.WindowState == FormWindowState.Maximized) {
|
|
bool found = false;
|
|
|
|
foreach (ToolStripItem tsi in parent_menu.Items) {
|
|
if (tsi is MdiControlStrip.SystemMenuItem) {
|
|
(tsi as MdiControlStrip.SystemMenuItem).MdiForm = form;
|
|
found = true;
|
|
} else if (tsi is MdiControlStrip.ControlBoxMenuItem) {
|
|
(tsi as MdiControlStrip.ControlBoxMenuItem).MdiForm = form;
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
parent_menu.SuspendLayout ();
|
|
parent_menu.Items.Insert (0, new MdiControlStrip.SystemMenuItem (form));
|
|
parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Close));
|
|
parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Max));
|
|
parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Min));
|
|
parent_menu.ResumeLayout ();
|
|
}
|
|
}
|
|
|
|
if (child_menu != null)
|
|
ToolStripManager.Merge (child_menu, parent_menu);
|
|
}
|
|
|
|
return maximize_this;
|
|
}
|
|
|
|
private MenuStrip LookForChildMenu (Control parent)
|
|
{
|
|
foreach (Control c in parent.Controls) {
|
|
if (c is MenuStrip)
|
|
return (MenuStrip)c;
|
|
|
|
if (c is ToolStripContainer || c is ToolStripPanel) {
|
|
MenuStrip ms = LookForChildMenu (c);
|
|
|
|
if (ms != null)
|
|
return ms;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
internal void RemoveControlMenuItems (MdiWindowManager wm)
|
|
{
|
|
Form form = wm.form;
|
|
MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
|
|
|
|
// Only remove the items if the form requesting still owns the menu items
|
|
if (parent_menu != null) {
|
|
parent_menu.SuspendLayout ();
|
|
|
|
for (int i = parent_menu.Items.Count - 1; i >= 0; i--) {
|
|
if (parent_menu.Items[i] is MdiControlStrip.SystemMenuItem) {
|
|
if ((parent_menu.Items[i] as MdiControlStrip.SystemMenuItem).MdiForm == form)
|
|
parent_menu.Items.RemoveAt (i);
|
|
} else if (parent_menu.Items[i] is MdiControlStrip.ControlBoxMenuItem) {
|
|
if ((parent_menu.Items[i] as MdiControlStrip.ControlBoxMenuItem).MdiForm == form)
|
|
parent_menu.Items.RemoveAt (i);
|
|
}
|
|
}
|
|
|
|
parent_menu.ResumeLayout ();
|
|
}
|
|
}
|
|
|
|
internal void SetWindowState (Form form, FormWindowState old_window_state, FormWindowState new_window_state, bool is_activating_child)
|
|
{
|
|
bool mdiclient_layout;
|
|
|
|
MdiWindowManager wm = (MdiWindowManager) form.window_manager;
|
|
|
|
if (!is_activating_child && new_window_state == FormWindowState.Maximized && !wm.IsActive) {
|
|
ActivateChild (form);
|
|
return;
|
|
}
|
|
|
|
if (old_window_state == FormWindowState.Normal)
|
|
wm.NormalBounds = form.Bounds;
|
|
|
|
if (SetWindowStates (wm))
|
|
return;
|
|
|
|
if (old_window_state == new_window_state)
|
|
return;
|
|
|
|
mdiclient_layout = old_window_state == FormWindowState.Maximized || new_window_state == FormWindowState.Maximized;
|
|
|
|
switch (new_window_state) {
|
|
case FormWindowState.Minimized:
|
|
ArrangeIconicWindows (false);
|
|
break;
|
|
case FormWindowState.Maximized:
|
|
form.Bounds = wm.MaximizedBounds;
|
|
break;
|
|
case FormWindowState.Normal:
|
|
form.Bounds = wm.NormalBounds;
|
|
break;
|
|
}
|
|
|
|
wm.UpdateWindowDecorations (new_window_state);
|
|
|
|
form.ResetCursor ();
|
|
|
|
if (mdiclient_layout)
|
|
Parent.PerformLayout ();
|
|
|
|
XplatUI.RequestNCRecalc (Parent.Handle);
|
|
XplatUI.RequestNCRecalc (form.Handle);
|
|
if (!setting_windowstates)
|
|
SizeScrollBars ();
|
|
}
|
|
internal int ChildrenCreated {
|
|
get { return mdi_created; }
|
|
set { mdi_created = value; }
|
|
}
|
|
|
|
internal Form ActiveMdiChild {
|
|
get {
|
|
if (ParentForm != null && !ParentForm.Visible)
|
|
return null;
|
|
|
|
if (Controls.Count < 1)
|
|
return null;
|
|
|
|
if (!ParentForm.IsHandleCreated)
|
|
return null;
|
|
|
|
if (!ParentForm.has_been_visible)
|
|
return null;
|
|
|
|
if (!ParentForm.Visible)
|
|
return active_child;
|
|
|
|
active_child = null;
|
|
for (int i = 0; i < Controls.Count; i++) {
|
|
if (Controls [i].Visible) {
|
|
active_child = (Form) Controls [i];
|
|
break;
|
|
}
|
|
}
|
|
return active_child;
|
|
}
|
|
set {
|
|
ActivateChild (value);
|
|
}
|
|
}
|
|
|
|
internal void ActivateActiveMdiChild ()
|
|
{
|
|
if (ParentForm.is_changing_visible_state > 0)
|
|
return;
|
|
|
|
for (int i = 0; i < Controls.Count; i++) {
|
|
if (Controls [i].Visible) {
|
|
ActivateChild ((Form) Controls [i]);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|