Merge pull request #2102 from AdamBurgess/master
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / ToolStripDropDownMenu.cs
1 //
2 // ToolStripDropDownMenu.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29 using System.Drawing;
30 using System.ComponentModel;
31 using System.Runtime.InteropServices;
32 using System.Windows.Forms.Layout;
33
34 namespace System.Windows.Forms
35 {
36         [ComVisible (true)]
37         [ClassInterface (ClassInterfaceType.AutoDispatch)]
38         [Designer ("System.Windows.Forms.Design.ToolStripDropDownDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
39         public class ToolStripDropDownMenu : ToolStripDropDown
40         {
41                 private ToolStripLayoutStyle layout_style;
42                 private bool show_check_margin;
43                 private bool show_image_margin;
44
45                 #region Public Constructors
46                 public ToolStripDropDownMenu () : base ()
47                 {
48                         this.layout_style = ToolStripLayoutStyle.Flow;
49                         this.show_image_margin = true;
50                 }
51                 #endregion
52
53                 #region Public Properties
54                 public override Rectangle DisplayRectangle {
55                         get { return base.DisplayRectangle; }
56                 }
57
58                 public override LayoutEngine LayoutEngine {
59                         get { return base.LayoutEngine; }
60                 }
61                 
62                 [DefaultValue (ToolStripLayoutStyle.Flow)]
63                 public new ToolStripLayoutStyle LayoutStyle {
64                         get { return this.layout_style; }
65                         set { this.layout_style = value; }
66                 }
67                 
68                 [DefaultValue (false)]
69                 public bool ShowCheckMargin {
70                         get { return this.show_check_margin; }
71                         set { 
72                                 if (this.show_check_margin != value) {
73                                         this.show_check_margin = value;
74                                         PerformLayout (this, "ShowCheckMargin");
75                                 }
76                         }
77                 }
78
79                 [DefaultValue (true)]
80                 public bool ShowImageMargin {
81                         get { return this.show_image_margin; }
82                         set { 
83                                 if (this.show_image_margin != value) {
84                                         this.show_image_margin = value;
85                                         PerformLayout (this, "ShowImageMargin");
86                                 }
87                         }
88                 }
89                 #endregion
90
91                 #region Protected Properties
92                 protected override Padding DefaultPadding {
93                         get { return base.DefaultPadding; }
94                 }
95
96                 protected internal override Size MaxItemSize {
97                         get { return Size; }
98                 }
99                 #endregion
100
101                 #region Protected Methods
102                 protected internal override ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
103                 {
104                         return base.CreateDefaultItem (text, image, onClick);
105                 }
106
107                 protected override void OnFontChanged (EventArgs e)
108                 {
109                         base.OnFontChanged (e);
110                 }
111
112                 protected override void OnLayout (LayoutEventArgs e)
113                 {
114                         // Find the widest menu item
115                         int widest = 0;
116
117                         foreach (ToolStripItem tsi in this.Items) {
118                                 if (!tsi.Available)
119                                         continue;
120
121                                 tsi.SetPlacement (ToolStripItemPlacement.Main);
122
123                                 widest = Math.Max (widest, tsi.GetPreferredSize (Size.Empty).Width);
124                         }
125
126                         int x = this.Padding.Left;
127                         
128                         if (show_check_margin || show_image_margin)
129                                 widest += 68 - this.Padding.Horizontal;
130                         else
131                                 widest += 47 - this.Padding.Horizontal;
132                         
133                         int y = this.Padding.Top;
134
135                         foreach (ToolStripItem tsi in this.Items) {
136                                 if (!tsi.Available)
137                                         continue;
138
139                                 y += tsi.Margin.Top;
140
141                                 int height = 0;
142         
143                                 Size preferred_size = tsi.GetPreferredSize (Size.Empty);
144
145                                 if (preferred_size.Height > 22)
146                                         height = preferred_size.Height;
147                                 else if (tsi is ToolStripSeparator)
148                                         height = 7;
149                                 else
150                                         height = 22;
151
152                                 tsi.SetBounds (new Rectangle (x, y, widest, height));
153                                 y += height + tsi.Margin.Bottom;
154                         }
155
156                         this.Size = new Size (widest + this.Padding.Horizontal, y + this.Padding.Bottom);// + 2);
157                         this.SetDisplayedItems ();
158                         this.OnLayoutCompleted (EventArgs.Empty);
159                         this.Invalidate ();
160                 }
161                 
162                 protected override void OnPaintBackground (PaintEventArgs e)
163                 {
164                         Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
165
166                         ToolStripRenderEventArgs tsrea = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, SystemColors.Control);
167                         tsrea.InternalConnectedArea = CalculateConnectedArea ();
168
169                         this.Renderer.DrawToolStripBackground (tsrea);
170                         
171                         if (this.ShowCheckMargin || this.ShowImageMargin) {
172                                 tsrea = new ToolStripRenderEventArgs (e.Graphics, this, new Rectangle (tsrea.AffectedBounds.Location, new Size (25, tsrea.AffectedBounds.Height)), SystemColors.Control);
173                                 this.Renderer.DrawImageMargin (tsrea);
174                         }
175                 }
176
177                 protected override void SetDisplayedItems ()
178                 {
179                         base.SetDisplayedItems ();
180                 }
181                 #endregion
182
183                 #region Internal Methods
184                 internal override Rectangle CalculateConnectedArea ()
185                 {
186                         if (this.OwnerItem != null && !this.OwnerItem.IsOnDropDown && !(this.OwnerItem is MdiControlStrip.SystemMenuItem)) {
187                                 Point owner_screen_loc = OwnerItem.GetCurrentParent ().PointToScreen (OwnerItem.Location);
188                                 return new Rectangle (owner_screen_loc.X - Left, 0, this.OwnerItem.Width - 1, 2);
189                         }
190
191                         return base.CalculateConnectedArea ();
192                 }
193                 #endregion
194         }
195 }