1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
23 // Peter Bartok pbartok@novell.com
29 using System.Collections;
30 using System.ComponentModel;
33 namespace System.Windows.Forms {
34 [DesignTimeVisible(false)]
36 public sealed class MdiClient : Control {
37 #region Local Variables
38 private int mdi_created;
39 private HScrollBar hbar;
40 private VScrollBar vbar;
41 private SizeGrip sizegrip;
42 private int hbar_value;
43 private int vbar_value;
44 private bool lock_sizing;
45 private int prev_bottom;
46 private LayoutEventHandler initial_layout_handler;
47 internal ArrayList mdi_child_list;
49 #endregion // Local Variables
51 #region Public Classes
52 public new class ControlCollection : Control.ControlCollection {
54 private MdiClient owner;
56 public ControlCollection(MdiClient owner) : base(owner) {
58 owner.mdi_child_list = new ArrayList ();
61 public override void Add(Control value) {
62 if ((value is Form) == false || !(((Form)value).IsMdiChild)) {
63 throw new ArgumentException("Form must be MdiChild");
65 owner.mdi_child_list.Add (value);
68 // newest member is the active one
69 Form form = (Form) value;
70 owner.ActiveMdiChild = form;
73 public override void Remove(Control value)
75 Form form = value as Form;
77 MdiWindowManager wm = form.WindowManager as MdiWindowManager;
79 form.Closed -= wm.form_closed_handler;
83 owner.mdi_child_list.Remove (value);
87 #endregion // Public Classes
89 #region Public Constructors
92 BackColor = SystemColors.AppWorkspace;
93 Dock = DockStyle.Fill;
94 SetStyle (ControlStyles.Selectable, false);
96 #endregion // Public Constructors
98 internal override void OnPaintBackgroundInternal (PaintEventArgs pe)
100 if (BackgroundImage != null)
103 if (Parent == null || Parent.BackgroundImage == null)
105 Parent.PaintControlBackground (pe);
108 internal Form ParentForm {
109 get { return (Form) Parent; }
112 protected override Control.ControlCollection CreateControlsInstance ()
114 return new MdiClient.ControlCollection (this);
117 protected override void WndProc(ref Message m) {
119 switch ((Msg) m.Msg) {
121 Console.WriteLine ("ignoring paint");
126 base.WndProc (ref m);
129 protected override void OnResize (EventArgs e)
133 // Should probably make this into one loop
138 protected override void ScaleCore (float dx, float dy)
140 base.ScaleCore (dx, dy);
143 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
145 base.SetBoundsCore (x, y, width, height, specified);
148 #region Public Instance Properties
150 public override System.Drawing.Image BackgroundImage {
152 return base.BackgroundImage;
155 base.BackgroundImage = value;
159 public Form [] MdiChildren {
161 if (mdi_child_list == null)
163 return (Form []) mdi_child_list.ToArray (typeof (Form));
166 #endregion // Public Instance Properties
168 #region Protected Instance Properties
169 protected override CreateParams CreateParams {
171 return base.CreateParams;
174 #endregion // Protected Instance Properties
176 #region Public Instance Methods
177 public void LayoutMdi (MdiLayout value) {
179 int max_width = Int32.MaxValue;
180 int max_height = Int32.MaxValue;
182 if (Parent != null) {
183 max_width = Parent.Width;
184 max_height = Parent.Height;
188 case MdiLayout.Cascade:
190 for (int c = Controls.Count - 1; c >= 0; c--) {
191 Form form = (Form) Controls [c];
196 if (i != 0 && (l + form.Width > max_width || t + form.Height > max_height)) {
209 throw new NotImplementedException();
212 #endregion // Public Instance Methods
214 #region Protected Instance Methods
215 #endregion // Protected Instance Methods
217 private void SizeScrollBars ()
222 if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) {
224 hbar.Visible = false;
226 vbar.Visible = false;
230 bool hbar_required = false;
231 bool vbar_required = false;
235 foreach (Form child in Controls) {
238 if (child.Right > right)
240 if (child.Left < left) {
241 hbar_required = true;
248 foreach (Form child in Controls) {
251 if (child.Bottom > bottom)
252 bottom = child.Bottom;
254 vbar_required = true;
259 int right_edge = Right;
260 int bottom_edge = Bottom;
262 int prev_bottom_edge;
264 bool need_hbar = false;
265 bool need_vbar = false;
268 prev_right_edge = right_edge;
269 prev_bottom_edge = bottom_edge;
271 if (hbar_required || right > right_edge) {
273 bottom_edge = Bottom - SystemInformation.HorizontalScrollBarHeight;
276 bottom_edge = Bottom;
279 if (vbar_required || bottom > bottom_edge) {
281 right_edge = Right - SystemInformation.VerticalScrollBarWidth;
287 } while (right_edge != prev_right_edge || bottom_edge != prev_bottom_edge);
291 hbar = new HScrollBar ();
292 Controls.AddImplicit (hbar);
295 CalcHBar (left, right, right_edge, need_vbar);
296 } else if (hbar != null)
297 hbar.Visible = false;
301 vbar = new VScrollBar ();
302 Controls.AddImplicit (vbar);
305 CalcVBar (top, bottom, bottom_edge, need_hbar);
306 } else if (vbar != null)
307 vbar.Visible = false;
309 if (need_hbar && need_vbar) {
310 if (sizegrip == null) {
311 sizegrip = new SizeGrip ();
312 Controls.AddImplicit (sizegrip);
314 sizegrip.Location = new Point (hbar.Right, vbar.Bottom);
315 sizegrip.Width = vbar.Width;
316 sizegrip.Height = hbar.Height;
317 sizegrip.Visible = true;
318 } else if (sizegrip != null) {
319 sizegrip.Visible = false;
323 private void CalcHBar (int left, int right, int right_edge, bool vert_vis)
325 int virtual_left = Math.Min (left, 0);
326 int virtual_right = Math.Max (right, right_edge);
327 int diff = (virtual_right - virtual_left) - right_edge;
329 hbar.Top = Height - hbar.Height;
330 hbar.Width = Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
331 hbar.LargeChange = 50;
332 hbar.Maximum = diff + 51;
333 hbar.Value = -virtual_left;
335 hbar.ValueChanged += new EventHandler (HBarValueChanged);
338 private void CalcVBar (int top, int bottom, int bottom_edge, bool horz_vis)
340 int virtual_top = Math.Min (top, 0);
341 int virtual_bottom = Math.Max (bottom, bottom_edge);
342 int diff = (virtual_bottom - virtual_top) - bottom_edge;
344 vbar.Left = Width - vbar.Width;
345 vbar.Height = Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
346 vbar.LargeChange = 50;
347 vbar.Maximum = diff + 51;
348 vbar.Value = -virtual_top;
349 vbar.ValueChanged += new EventHandler (VBarValueChanged);
353 private void HBarValueChanged (object sender, EventArgs e)
355 if (hbar.Value == hbar_value)
361 foreach (Form child in Controls) {
362 child.Left += hbar_value - hbar.Value;
368 hbar_value = hbar.Value;
372 private void VBarValueChanged (object sender, EventArgs e)
374 if (vbar.Value == vbar_value)
380 foreach (Form child in Controls) {
381 child.Top += vbar_value - vbar.Value;
387 vbar_value = vbar.Value;
391 private void ArrangeWindows ()
394 if (prev_bottom != -1)
395 change = Bottom - prev_bottom;
397 foreach (Control c in Controls) {
398 Form child = c as Form;
400 if (c == null || !child.Visible)
403 MdiWindowManager wm = child.WindowManager as MdiWindowManager;
404 if (wm.GetWindowState () == FormWindowState.Maximized)
407 if (wm.GetWindowState () == FormWindowState.Minimized) {
413 prev_bottom = Bottom;
416 private void FormLocationChanged (object sender, EventArgs e)
421 private int iconic_x = -1;
422 private int iconic_y = -1;
423 internal void ArrangeIconicWindows ()
428 if (iconic_x == -1 && iconic_y == -1) {
430 iconic_y = Bottom - yspacing;
434 foreach (Form form in Controls) {
435 if (form.WindowState != FormWindowState.Minimized)
438 MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
439 // Need to get the width in the loop cause some themes might have
440 // different widths for different styles
441 int bw = ThemeEngine.Current.ManagedWindowBorderWidth (wm);
443 if (wm.IconicBounds != Rectangle.Empty) {
444 form.Bounds = wm.IconicBounds;
448 // The extra one pixel is a cheap hack for now until we
449 // handle 0 client sizes properly in the driver
450 int height = wm.TitleBarHeight + (bw * 2) + 1;
451 Rectangle rect = new Rectangle (iconic_x, iconic_y, xspacing, height);
452 form.Bounds = wm.IconicBounds = rect;
454 iconic_x += xspacing;
455 if (iconic_x >= Right) {
463 internal void CloseChildForm (Form form)
465 if (Controls.Count > 1) {
466 Form next = (Form) Controls [1];
467 if (form.WindowState == FormWindowState.Maximized)
468 next.WindowState = FormWindowState.Maximized;
469 ActivateChild (next);
472 Controls.Remove (form);
476 internal void ActivateNextChild ()
478 if (Controls.Count < 1)
481 Form front = (Form) Controls [0];
482 Form form = (Form) Controls [1];
485 ActivateChild (form);
488 internal void ActivateChild (Form form)
490 if (Controls.Count < 1)
493 Form current = (Form) Controls [0];
495 form.BringToFront ();
497 if (current != form) {
498 Message m = new Message ();
499 m.Msg = (int) Msg.WM_NCPAINT;
500 m.HWnd = current.Handle;
501 m.LParam = IntPtr.Zero;
502 m.WParam = new IntPtr (1);
503 XplatUI.SendMessage (ref m);
505 m.HWnd = form.Handle;
506 XplatUI.SendMessage (ref m);
510 internal int ChildrenCreated {
511 get { return mdi_created; }
512 set { mdi_created = value; }
515 internal Form ActiveMdiChild {
517 if (Controls.Count < 1)
519 return (Form) Controls [0];
522 ActivateChild (value);