2008-04-28 George Giolfan <georgegiolfan@yahoo.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms.Theming / VisualStyles / TabControlPainter.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2008 George Giolfan
21 //
22 // Authors:
23 //      George Giolfan (georgegiolfan@yahoo.com)
24
25 using System.Windows.Forms.VisualStyles;
26 using System.Drawing;
27 namespace System.Windows.Forms.Theming.VisualStyles
28 {
29         class TabControlPainter : Default.TabControlPainter
30         {
31                 static bool ShouldPaint (TabControl tabControl) {
32                         return tabControl.Alignment == TabAlignment.Top &&
33                                 tabControl.DrawMode == TabDrawMode.Normal;
34                 }
35                 public override void Draw (Graphics dc, Rectangle area, TabControl tab) {
36                         if (!ShouldPaint (tab)) {
37                                 base.Draw (dc, area, tab);
38                                 return;
39                         }
40
41                         VisualStyleElement element = VisualStyleElement.Tab.Pane.Normal;
42                         if (!VisualStyleRenderer.IsElementDefined (element)) {
43                                 base.Draw (dc, area, tab);
44                                 return;
45                         }
46                         Rectangle panel_rectangle = GetTabPanelRect (tab);
47                         if (panel_rectangle.IntersectsWith (area))
48                                 new VisualStyleRenderer (element).DrawBackground (dc, panel_rectangle, area);
49
50                         //TODO: The base method should be refactored to allow this class to override only what it needs to.
51                         int start = 0;
52                         int end = tab.TabPages.Count;
53                         int delta = 1;
54
55                         if (tab.Alignment == TabAlignment.Top) {
56                                 start = end;
57                                 end = 0;
58                                 delta = -1;
59                         }
60                         int counter = start;
61                         for (; counter != end; counter += delta) {
62                                 for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) {
63                                         if (i == tab.SelectedIndex)
64                                                 continue;
65                                         if (counter != tab.TabPages[i].Row)
66                                                 continue;
67                                         Rectangle rect = tab.GetTabRect (i);
68                                         if (!rect.IntersectsWith (area))
69                                                 continue;
70                                         DrawTab (dc, tab.TabPages[i], tab, rect, false);
71                                 }
72                         }
73
74                         if (tab.SelectedIndex != -1 && tab.SelectedIndex >= tab.SliderPos) {
75                                 Rectangle rect = tab.GetTabRect (tab.SelectedIndex);
76                                 if (rect.IntersectsWith (area))
77                                         DrawTab (dc, tab.TabPages[tab.SelectedIndex], tab, rect, true);
78                         }
79
80                         if (tab.ShowSlider) {
81                                 Rectangle right = GetRightScrollRect (tab);
82                                 Rectangle left = GetLeftScrollRect (tab);
83                                 ControlPaint.DrawScrollButton (dc, right, ScrollButton.Right, tab.RightSliderState);
84                                 ControlPaint.DrawScrollButton (dc, left, ScrollButton.Left, tab.LeftSliderState);
85                         }
86                 }
87                 protected override int DrawTab (Graphics dc, TabPage page, TabControl tab, Rectangle bounds, bool is_selected)
88                 {
89                         if (!ShouldPaint (tab))
90                                 return base.DrawTab (dc, page, tab, bounds, is_selected);
91                         VisualStyleElement element = GetVisualStyleElement (tab, page, is_selected);
92                         if (!VisualStyleRenderer.IsElementDefined (element))
93                                 return base.DrawTab (dc, page, tab, bounds, is_selected);
94                         new VisualStyleRenderer (element).DrawBackground (dc, bounds);
95                         bounds.Inflate (
96                                 -(FocusRectSpacing.X + BorderThickness.X),
97                                 -(FocusRectSpacing.Y + BorderThickness.Y));
98                         Rectangle text_area = bounds;
99                         if (tab.ImageList != null && page.ImageIndex >= 0 && page.ImageIndex < tab.ImageList.Images.Count) {
100                                 int image_y = bounds.Y + (bounds.Height - tab.ImageList.ImageSize.Height) / 2;
101                                 tab.ImageList.Draw (dc, new Point (bounds.X, image_y), page.ImageIndex);
102                                 int image_occupied_space = tab.ImageList.ImageSize.Width + 2;
103                                 text_area.X += image_occupied_space;
104                                 text_area.Width -= image_occupied_space;
105                         }
106                         if (page.Text != null)
107                                 dc.DrawString (page.Text, page.Font, SystemBrushes.ControlText, text_area, DefaultFormatting);
108                         if (tab.Focused && is_selected)
109                                 ControlPaint.DrawFocusRectangle (dc, bounds);
110                         return 0;
111                 }
112                 static VisualStyleElement GetVisualStyleElement (TabControl tabControl, TabPage tabPage, bool selected)
113                 {
114                         bool top_edge = tabPage.Row == tabControl.RowCount;
115                         int tab_page_index = tabControl.TabPages.IndexOf (tabPage);
116                         bool left_edge = true;
117                         int index;
118                         for (index = tabControl.SliderPos; index < tab_page_index; index++)
119                                 if (tabControl.TabPages [index].Row == tabPage.Row) {
120                                         left_edge = false;
121                                         break;
122                                 }
123                         bool right_edge = true;
124                         for (index = tab_page_index; index < tabControl.TabCount; index++)
125                                 if (tabControl.TabPages [index].Row == tabPage.Row) {
126                                         right_edge = false;
127                                         break;
128                                 }
129                         if (!tabPage.Enabled)
130                                 #region Disabled
131                                 if (top_edge)
132                                         if (left_edge)
133                                                 if (right_edge)
134                                                         return VisualStyleElement.Tab.TopTabItem.Disabled;
135                                                 else
136                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Disabled;
137                                         else
138                                                 if (right_edge)
139                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Disabled;
140                                                 else
141                                                         return VisualStyleElement.Tab.TopTabItem.Disabled;
142                                 else
143                                         if (left_edge)
144                                                 if (right_edge)
145                                                         return VisualStyleElement.Tab.TabItem.Disabled;
146                                                 else
147                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Disabled;
148                                         else
149                                                 if (right_edge)
150                                                         return VisualStyleElement.Tab.TabItemRightEdge.Disabled;
151                                                 else
152                                                         return VisualStyleElement.Tab.TabItem.Disabled;
153                                 #endregion
154                         /*TODO Repaint the tab when the mouse enters or leaves its area.
155                         else if (hot)
156                                 #region Hot
157                                 if (top_edge)
158                                         if (left_edge)
159                                                 if (right_edge)
160                                                         return VisualStyleElement.Tab.TopTabItem.Hot;
161                                                 else
162                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Hot;
163                                         else
164                                                 if (right_edge)
165                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Hot;
166                                                 else
167                                                         return VisualStyleElement.Tab.TopTabItem.Hot;
168                                 else
169                                         if (left_edge)
170                                                 if (right_edge)
171                                                         return VisualStyleElement.Tab.TabItem.Hot;
172                                                 else
173                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Hot;
174                                         else
175                                                 if (right_edge)
176                                                         return VisualStyleElement.Tab.TabItemRightEdge.Hot;
177                                                 else
178                                                         return VisualStyleElement.Tab.TabItem.Hot;
179                                 #endregion
180                         */
181                         else if (selected)
182                                 #region Pressed
183                                 if (top_edge)
184                                         if (left_edge)
185                                                 if (right_edge)
186                                                         return VisualStyleElement.Tab.TopTabItem.Pressed;
187                                                 else
188                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Pressed;
189                                         else
190                                                 if (right_edge)
191                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Pressed;
192                                                 else
193                                                         return VisualStyleElement.Tab.TopTabItem.Pressed;
194                                 else
195                                         if (left_edge)
196                                                 if (right_edge)
197                                                         return VisualStyleElement.Tab.TabItem.Pressed;
198                                                 else
199                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Pressed;
200                                         else
201                                                 if (right_edge)
202                                                         return VisualStyleElement.Tab.TabItemRightEdge.Pressed;
203                                                 else
204                                                         return VisualStyleElement.Tab.TabItem.Pressed;
205                                 #endregion
206                         else
207                                 #region Normal
208                                 if (top_edge)
209                                         if (left_edge)
210                                                 if (right_edge)
211                                                         return VisualStyleElement.Tab.TopTabItemBothEdges.Normal;
212                                                 else
213                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Normal;
214                                         else
215                                                 if (right_edge)
216                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Normal;
217                                                 else
218                                                         return VisualStyleElement.Tab.TopTabItem.Normal;
219                                 else
220                                         if (left_edge)
221                                                 if (right_edge)
222                                                         return VisualStyleElement.Tab.TabItemBothEdges.Normal;
223                                                 else
224                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Normal;
225                                         else
226                                                 if (right_edge)
227                                                         return VisualStyleElement.Tab.TabItemRightEdge.Normal;
228                                                 else
229                                                         return VisualStyleElement.Tab.TabItem.Normal;
230                                 #endregion
231                 }
232         }
233 }
234 // Permission is hereby granted, free of charge, to any person obtaining
235 // a copy of this software and associated documentation files (the
236 // "Software"), to deal in the Software without restriction, including
237 // without limitation the rights to use, copy, modify, merge, publish,
238 // distribute, sublicense, and/or sell copies of the Software, and to
239 // permit persons to whom the Software is furnished to do so, subject to
240 // the following conditions:
241 //
242 // The above copyright notice and this permission notice shall be
243 // included in all copies or substantial portions of the Software.
244 //
245 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
246 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
247 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
248 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
249 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
250 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
251 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
252 //
253 // Copyright (c) 2008 George Giolfan
254 //
255 // Authors:
256 //      George Giolfan (georgegiolfan@yahoo.com)
257
258 using System.Windows.Forms.VisualStyles;
259 using System.Drawing;
260 namespace System.Windows.Forms.Theming.VisualStyles
261 {
262         class TabControlPainter : Default.TabControlPainter
263         {
264                 static bool ShouldPaint (TabControl tabControl) {
265                         return tabControl.Alignment == TabAlignment.Top &&
266                                 tabControl.DrawMode == TabDrawMode.Normal;
267                 }
268                 public override void Draw (Graphics dc, Rectangle area, TabControl tab) {
269                         if (!ShouldPaint (tab)) {
270                                 base.Draw (dc, area, tab);
271                                 return;
272                         }
273
274                         VisualStyleElement element = VisualStyleElement.Tab.Pane.Normal;
275                         if (!VisualStyleRenderer.IsElementDefined (element)) {
276                                 base.Draw (dc, area, tab);
277                                 return;
278                         }
279                         Rectangle panel_rectangle = GetTabPanelRect (tab);
280                         if (panel_rectangle.IntersectsWith (area))
281                                 new VisualStyleRenderer (element).DrawBackground (dc, panel_rectangle, area);
282
283                         //TODO: The base method should be refactored to allow this class to override only what it needs to.
284                         int start = 0;
285                         int end = tab.TabPages.Count;
286                         int delta = 1;
287
288                         if (tab.Alignment == TabAlignment.Top) {
289                                 start = end;
290                                 end = 0;
291                                 delta = -1;
292                         }
293                         int counter = start;
294                         for (; counter != end; counter += delta) {
295                                 for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) {
296                                         if (i == tab.SelectedIndex)
297                                                 continue;
298                                         if (counter != tab.TabPages[i].Row)
299                                                 continue;
300                                         Rectangle rect = tab.GetTabRect (i);
301                                         if (!rect.IntersectsWith (area))
302                                                 continue;
303                                         DrawTab (dc, tab.TabPages[i], tab, rect, false);
304                                 }
305                         }
306
307                         if (tab.SelectedIndex != -1 && tab.SelectedIndex >= tab.SliderPos) {
308                                 Rectangle rect = tab.GetTabRect (tab.SelectedIndex);
309                                 if (rect.IntersectsWith (area))
310                                         DrawTab (dc, tab.TabPages[tab.SelectedIndex], tab, rect, true);
311                         }
312
313                         if (tab.ShowSlider) {
314                                 Rectangle right = GetRightScrollRect (tab);
315                                 Rectangle left = GetLeftScrollRect (tab);
316                                 ControlPaint.DrawScrollButton (dc, right, ScrollButton.Right, tab.RightSliderState);
317                                 ControlPaint.DrawScrollButton (dc, left, ScrollButton.Left, tab.LeftSliderState);
318                         }
319                 }
320                 protected override int DrawTab (Graphics dc, TabPage page, TabControl tab, Rectangle bounds, bool is_selected)
321                 {
322                         if (!ShouldPaint (tab))
323                                 return base.DrawTab (dc, page, tab, bounds, is_selected);
324                         VisualStyleElement element = GetVisualStyleElement (tab, page, is_selected);
325                         if (!VisualStyleRenderer.IsElementDefined (element))
326                                 return base.DrawTab (dc, page, tab, bounds, is_selected);
327                         new VisualStyleRenderer (element).DrawBackground (dc, bounds);
328                         bounds.Inflate (
329                                 -(FocusRectSpacing.X + BorderThickness.X),
330                                 -(FocusRectSpacing.Y + BorderThickness.Y));
331                         Rectangle text_area = bounds;
332                         if (tab.ImageList != null && page.ImageIndex >= 0 && page.ImageIndex < tab.ImageList.Images.Count) {
333                                 int image_y = bounds.Y + (bounds.Height - tab.ImageList.ImageSize.Height) / 2;
334                                 tab.ImageList.Draw (dc, new Point (bounds.X, image_y), page.ImageIndex);
335                                 int image_occupied_space = tab.ImageList.ImageSize.Width + 2;
336                                 text_area.X += image_occupied_space;
337                                 text_area.Width -= image_occupied_space;
338                         }
339                         if (page.Text != null)
340                                 dc.DrawString (page.Text, page.Font, SystemBrushes.ControlText, text_area, DefaultFormatting);
341                         if (tab.Focused && is_selected)
342                                 ControlPaint.DrawFocusRectangle (dc, bounds);
343                         return 0;
344                 }
345                 static VisualStyleElement GetVisualStyleElement (TabControl tabControl, TabPage tabPage, bool selected)
346                 {
347                         bool top_edge = tabPage.Row == tabControl.RowCount;
348                         int tab_page_index = tabControl.TabPages.IndexOf (tabPage);
349                         bool left_edge = true;
350                         int index;
351                         for (index = tabControl.SliderPos; index < tab_page_index; index++)
352                                 if (tabControl.TabPages [index].Row == tabPage.Row) {
353                                         left_edge = false;
354                                         break;
355                                 }
356                         bool right_edge = true;
357                         for (index = tab_page_index; index < tabControl.TabCount; index++)
358                                 if (tabControl.TabPages [index].Row == tabPage.Row) {
359                                         right_edge = false;
360                                         break;
361                                 }
362                         if (!tabPage.Enabled)
363                                 #region Disabled
364                                 if (top_edge)
365                                         if (left_edge)
366                                                 if (right_edge)
367                                                         return VisualStyleElement.Tab.TopTabItem.Disabled;
368                                                 else
369                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Disabled;
370                                         else
371                                                 if (right_edge)
372                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Disabled;
373                                                 else
374                                                         return VisualStyleElement.Tab.TopTabItem.Disabled;
375                                 else
376                                         if (left_edge)
377                                                 if (right_edge)
378                                                         return VisualStyleElement.Tab.TabItem.Disabled;
379                                                 else
380                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Disabled;
381                                         else
382                                                 if (right_edge)
383                                                         return VisualStyleElement.Tab.TabItemRightEdge.Disabled;
384                                                 else
385                                                         return VisualStyleElement.Tab.TabItem.Disabled;
386                                 #endregion
387                         /*TODO Repaint the tab when the mouse enters or leaves its area.
388                         else if (hot)
389                                 #region Hot
390                                 if (top_edge)
391                                         if (left_edge)
392                                                 if (right_edge)
393                                                         return VisualStyleElement.Tab.TopTabItem.Hot;
394                                                 else
395                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Hot;
396                                         else
397                                                 if (right_edge)
398                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Hot;
399                                                 else
400                                                         return VisualStyleElement.Tab.TopTabItem.Hot;
401                                 else
402                                         if (left_edge)
403                                                 if (right_edge)
404                                                         return VisualStyleElement.Tab.TabItem.Hot;
405                                                 else
406                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Hot;
407                                         else
408                                                 if (right_edge)
409                                                         return VisualStyleElement.Tab.TabItemRightEdge.Hot;
410                                                 else
411                                                         return VisualStyleElement.Tab.TabItem.Hot;
412                                 #endregion
413                         */
414                         else if (selected)
415                                 #region Pressed
416                                 if (top_edge)
417                                         if (left_edge)
418                                                 if (right_edge)
419                                                         return VisualStyleElement.Tab.TopTabItem.Pressed;
420                                                 else
421                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Pressed;
422                                         else
423                                                 if (right_edge)
424                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Pressed;
425                                                 else
426                                                         return VisualStyleElement.Tab.TopTabItem.Pressed;
427                                 else
428                                         if (left_edge)
429                                                 if (right_edge)
430                                                         return VisualStyleElement.Tab.TabItem.Pressed;
431                                                 else
432                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Pressed;
433                                         else
434                                                 if (right_edge)
435                                                         return VisualStyleElement.Tab.TabItemRightEdge.Pressed;
436                                                 else
437                                                         return VisualStyleElement.Tab.TabItem.Pressed;
438                                 #endregion
439                         else
440                                 #region Normal
441                                 if (top_edge)
442                                         if (left_edge)
443                                                 if (right_edge)
444                                                         return VisualStyleElement.Tab.TopTabItemBothEdges.Normal;
445                                                 else
446                                                         return VisualStyleElement.Tab.TopTabItemLeftEdge.Normal;
447                                         else
448                                                 if (right_edge)
449                                                         return VisualStyleElement.Tab.TopTabItemRightEdge.Normal;
450                                                 else
451                                                         return VisualStyleElement.Tab.TopTabItem.Normal;
452                                 else
453                                         if (left_edge)
454                                                 if (right_edge)
455                                                         return VisualStyleElement.Tab.TabItemBothEdges.Normal;
456                                                 else
457                                                         return VisualStyleElement.Tab.TabItemLeftEdge.Normal;
458                                         else
459                                                 if (right_edge)
460                                                         return VisualStyleElement.Tab.TabItemRightEdge.Normal;
461                                                 else
462                                                         return VisualStyleElement.Tab.TabItem.Normal;
463                                 #endregion
464                 }
465         }
466 }