1 | using System;
|
---|
2 | using System.Drawing;
|
---|
3 | using System.Drawing.Drawing2D;
|
---|
4 | using System.Windows.Forms;
|
---|
5 |
|
---|
6 | namespace WeifenLuo.WinFormsUI.Docking {
|
---|
7 | internal class VS2005AutoHideStrip : AutoHideStripBase {
|
---|
8 | private class TabVS2005 : Tab {
|
---|
9 | internal TabVS2005(IDockContent content)
|
---|
10 | : base(content) {
|
---|
11 | }
|
---|
12 |
|
---|
13 | private int m_tabX = 0;
|
---|
14 | public int TabX {
|
---|
15 | get { return m_tabX; }
|
---|
16 | set { m_tabX = value; }
|
---|
17 | }
|
---|
18 |
|
---|
19 | private int m_tabWidth = 0;
|
---|
20 | public int TabWidth {
|
---|
21 | get { return m_tabWidth; }
|
---|
22 | set { m_tabWidth = value; }
|
---|
23 | }
|
---|
24 |
|
---|
25 | }
|
---|
26 |
|
---|
27 | private const int _ImageHeight = 16;
|
---|
28 | private const int _ImageWidth = 16;
|
---|
29 | private const int _ImageGapTop = 2;
|
---|
30 | private const int _ImageGapLeft = 4;
|
---|
31 | private const int _ImageGapRight = 2;
|
---|
32 | private const int _ImageGapBottom = 2;
|
---|
33 | private const int _TextGapLeft = 0;
|
---|
34 | private const int _TextGapRight = 0;
|
---|
35 | private const int _TabGapTop = 3;
|
---|
36 | private const int _TabGapLeft = 4;
|
---|
37 | private const int _TabGapBetween = 10;
|
---|
38 |
|
---|
39 | #region Customizable Properties
|
---|
40 | private static Font TextFont {
|
---|
41 | get { return SystemInformation.MenuFont; }
|
---|
42 | }
|
---|
43 |
|
---|
44 | private static StringFormat _stringFormatTabHorizontal;
|
---|
45 | private StringFormat StringFormatTabHorizontal {
|
---|
46 | get {
|
---|
47 | if (_stringFormatTabHorizontal == null) {
|
---|
48 | _stringFormatTabHorizontal = new StringFormat();
|
---|
49 | _stringFormatTabHorizontal.Alignment = StringAlignment.Near;
|
---|
50 | _stringFormatTabHorizontal.LineAlignment = StringAlignment.Center;
|
---|
51 | _stringFormatTabHorizontal.FormatFlags = StringFormatFlags.NoWrap;
|
---|
52 | _stringFormatTabHorizontal.Trimming = StringTrimming.None;
|
---|
53 | }
|
---|
54 |
|
---|
55 | if (RightToLeft == RightToLeft.Yes)
|
---|
56 | _stringFormatTabHorizontal.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
|
---|
57 | else
|
---|
58 | _stringFormatTabHorizontal.FormatFlags &= ~StringFormatFlags.DirectionRightToLeft;
|
---|
59 |
|
---|
60 | return _stringFormatTabHorizontal;
|
---|
61 | }
|
---|
62 | }
|
---|
63 |
|
---|
64 | private static StringFormat _stringFormatTabVertical;
|
---|
65 | private StringFormat StringFormatTabVertical {
|
---|
66 | get {
|
---|
67 | if (_stringFormatTabVertical == null) {
|
---|
68 | _stringFormatTabVertical = new StringFormat();
|
---|
69 | _stringFormatTabVertical.Alignment = StringAlignment.Near;
|
---|
70 | _stringFormatTabVertical.LineAlignment = StringAlignment.Center;
|
---|
71 | _stringFormatTabVertical.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.DirectionVertical;
|
---|
72 | _stringFormatTabVertical.Trimming = StringTrimming.None;
|
---|
73 | }
|
---|
74 | if (RightToLeft == RightToLeft.Yes)
|
---|
75 | _stringFormatTabVertical.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
|
---|
76 | else
|
---|
77 | _stringFormatTabVertical.FormatFlags &= ~StringFormatFlags.DirectionRightToLeft;
|
---|
78 |
|
---|
79 | return _stringFormatTabVertical;
|
---|
80 | }
|
---|
81 | }
|
---|
82 |
|
---|
83 | private static int ImageHeight {
|
---|
84 | get { return _ImageHeight; }
|
---|
85 | }
|
---|
86 |
|
---|
87 | private static int ImageWidth {
|
---|
88 | get { return _ImageWidth; }
|
---|
89 | }
|
---|
90 |
|
---|
91 | private static int ImageGapTop {
|
---|
92 | get { return _ImageGapTop; }
|
---|
93 | }
|
---|
94 |
|
---|
95 | private static int ImageGapLeft {
|
---|
96 | get { return _ImageGapLeft; }
|
---|
97 | }
|
---|
98 |
|
---|
99 | private static int ImageGapRight {
|
---|
100 | get { return _ImageGapRight; }
|
---|
101 | }
|
---|
102 |
|
---|
103 | private static int ImageGapBottom {
|
---|
104 | get { return _ImageGapBottom; }
|
---|
105 | }
|
---|
106 |
|
---|
107 | private static int TextGapLeft {
|
---|
108 | get { return _TextGapLeft; }
|
---|
109 | }
|
---|
110 |
|
---|
111 | private static int TextGapRight {
|
---|
112 | get { return _TextGapRight; }
|
---|
113 | }
|
---|
114 |
|
---|
115 | private static int TabGapTop {
|
---|
116 | get { return _TabGapTop; }
|
---|
117 | }
|
---|
118 |
|
---|
119 | private static int TabGapLeft {
|
---|
120 | get { return _TabGapLeft; }
|
---|
121 | }
|
---|
122 |
|
---|
123 | private static int TabGapBetween {
|
---|
124 | get { return _TabGapBetween; }
|
---|
125 | }
|
---|
126 |
|
---|
127 | private static Pen PenTabBorder {
|
---|
128 | get { return SystemPens.GrayText; }
|
---|
129 | }
|
---|
130 | #endregion
|
---|
131 |
|
---|
132 | private static Matrix _matrixIdentity = new Matrix();
|
---|
133 | private static Matrix MatrixIdentity {
|
---|
134 | get { return _matrixIdentity; }
|
---|
135 | }
|
---|
136 |
|
---|
137 | private static DockState[] _dockStates;
|
---|
138 | private static DockState[] DockStates {
|
---|
139 | get {
|
---|
140 | if (_dockStates == null) {
|
---|
141 | _dockStates = new DockState[4];
|
---|
142 | _dockStates[0] = DockState.DockLeftAutoHide;
|
---|
143 | _dockStates[1] = DockState.DockRightAutoHide;
|
---|
144 | _dockStates[2] = DockState.DockTopAutoHide;
|
---|
145 | _dockStates[3] = DockState.DockBottomAutoHide;
|
---|
146 | }
|
---|
147 | return _dockStates;
|
---|
148 | }
|
---|
149 | }
|
---|
150 |
|
---|
151 | private static GraphicsPath _graphicsPath;
|
---|
152 | internal static GraphicsPath GraphicsPath {
|
---|
153 | get {
|
---|
154 | if (_graphicsPath == null)
|
---|
155 | _graphicsPath = new GraphicsPath();
|
---|
156 |
|
---|
157 | return _graphicsPath;
|
---|
158 | }
|
---|
159 | }
|
---|
160 |
|
---|
161 | public VS2005AutoHideStrip(DockPanel panel)
|
---|
162 | : base(panel) {
|
---|
163 | SetStyle(ControlStyles.ResizeRedraw |
|
---|
164 | ControlStyles.UserPaint |
|
---|
165 | ControlStyles.AllPaintingInWmPaint |
|
---|
166 | ControlStyles.OptimizedDoubleBuffer, true);
|
---|
167 | BackColor = SystemColors.ControlLight;
|
---|
168 | }
|
---|
169 |
|
---|
170 | protected override void OnPaint(PaintEventArgs e) {
|
---|
171 | Graphics g = e.Graphics;
|
---|
172 |
|
---|
173 | Color startColor = DockPanel.Skin.AutoHideStripSkin.DockStripGradient.StartColor;
|
---|
174 | Color endColor = DockPanel.Skin.AutoHideStripSkin.DockStripGradient.EndColor;
|
---|
175 | LinearGradientMode gradientMode = DockPanel.Skin.AutoHideStripSkin.DockStripGradient.LinearGradientMode;
|
---|
176 | using (LinearGradientBrush brush = new LinearGradientBrush(ClientRectangle, startColor, endColor, gradientMode)) {
|
---|
177 | g.FillRectangle(brush, ClientRectangle);
|
---|
178 | }
|
---|
179 |
|
---|
180 | DrawTabStrip(g);
|
---|
181 | }
|
---|
182 |
|
---|
183 | protected override void OnLayout(LayoutEventArgs levent) {
|
---|
184 | CalculateTabs();
|
---|
185 | base.OnLayout(levent);
|
---|
186 | }
|
---|
187 |
|
---|
188 | private void DrawTabStrip(Graphics g) {
|
---|
189 | DrawTabStrip(g, DockState.DockTopAutoHide);
|
---|
190 | DrawTabStrip(g, DockState.DockBottomAutoHide);
|
---|
191 | DrawTabStrip(g, DockState.DockLeftAutoHide);
|
---|
192 | DrawTabStrip(g, DockState.DockRightAutoHide);
|
---|
193 | }
|
---|
194 |
|
---|
195 | private void DrawTabStrip(Graphics g, DockState dockState) {
|
---|
196 | Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
|
---|
197 |
|
---|
198 | if (rectTabStrip.IsEmpty)
|
---|
199 | return;
|
---|
200 |
|
---|
201 | Matrix matrixIdentity = g.Transform;
|
---|
202 | if (dockState == DockState.DockLeftAutoHide || dockState == DockState.DockRightAutoHide) {
|
---|
203 | Matrix matrixRotated = new Matrix();
|
---|
204 | matrixRotated.RotateAt(90, new PointF((float)rectTabStrip.X + (float)rectTabStrip.Height / 2,
|
---|
205 | (float)rectTabStrip.Y + (float)rectTabStrip.Height / 2));
|
---|
206 | g.Transform = matrixRotated;
|
---|
207 | }
|
---|
208 |
|
---|
209 | foreach (Pane pane in GetPanes(dockState)) {
|
---|
210 | foreach (TabVS2005 tab in pane.AutoHideTabs)
|
---|
211 | DrawTab(g, tab);
|
---|
212 | }
|
---|
213 | g.Transform = matrixIdentity;
|
---|
214 | }
|
---|
215 |
|
---|
216 | private void CalculateTabs() {
|
---|
217 | CalculateTabs(DockState.DockTopAutoHide);
|
---|
218 | CalculateTabs(DockState.DockBottomAutoHide);
|
---|
219 | CalculateTabs(DockState.DockLeftAutoHide);
|
---|
220 | CalculateTabs(DockState.DockRightAutoHide);
|
---|
221 | }
|
---|
222 |
|
---|
223 | private void CalculateTabs(DockState dockState) {
|
---|
224 | Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
|
---|
225 |
|
---|
226 | int imageHeight = rectTabStrip.Height - ImageGapTop - ImageGapBottom;
|
---|
227 | int imageWidth = ImageWidth;
|
---|
228 | if (imageHeight > ImageHeight)
|
---|
229 | imageWidth = ImageWidth * (imageHeight / ImageHeight);
|
---|
230 |
|
---|
231 | int x = TabGapLeft + rectTabStrip.X;
|
---|
232 | foreach (Pane pane in GetPanes(dockState)) {
|
---|
233 | foreach (TabVS2005 tab in pane.AutoHideTabs) {
|
---|
234 | int width = imageWidth + ImageGapLeft + ImageGapRight +
|
---|
235 | TextRenderer.MeasureText(tab.Content.DockHandler.TabText, TextFont).Width +
|
---|
236 | TextGapLeft + TextGapRight;
|
---|
237 | tab.TabX = x;
|
---|
238 | tab.TabWidth = width;
|
---|
239 | x += width;
|
---|
240 | }
|
---|
241 |
|
---|
242 | x += TabGapBetween;
|
---|
243 | }
|
---|
244 | }
|
---|
245 |
|
---|
246 | private Rectangle RtlTransform(Rectangle rect, DockState dockState) {
|
---|
247 | Rectangle rectTransformed;
|
---|
248 | if (dockState == DockState.DockLeftAutoHide || dockState == DockState.DockRightAutoHide)
|
---|
249 | rectTransformed = rect;
|
---|
250 | else
|
---|
251 | rectTransformed = DrawHelper.RtlTransform(this, rect);
|
---|
252 |
|
---|
253 | return rectTransformed;
|
---|
254 | }
|
---|
255 |
|
---|
256 | private GraphicsPath GetTabOutline(TabVS2005 tab, bool transformed, bool rtlTransform) {
|
---|
257 | DockState dockState = tab.Content.DockHandler.DockState;
|
---|
258 | Rectangle rectTab = GetTabRectangle(tab, transformed);
|
---|
259 | if (rtlTransform)
|
---|
260 | rectTab = RtlTransform(rectTab, dockState);
|
---|
261 | bool upTab = (dockState == DockState.DockLeftAutoHide || dockState == DockState.DockBottomAutoHide);
|
---|
262 | DrawHelper.GetRoundedCornerTab(GraphicsPath, rectTab, upTab);
|
---|
263 |
|
---|
264 | return GraphicsPath;
|
---|
265 | }
|
---|
266 |
|
---|
267 | private void DrawTab(Graphics g, TabVS2005 tab) {
|
---|
268 | Rectangle rectTabOrigin = GetTabRectangle(tab);
|
---|
269 | if (rectTabOrigin.IsEmpty)
|
---|
270 | return;
|
---|
271 |
|
---|
272 | DockState dockState = tab.Content.DockHandler.DockState;
|
---|
273 | IDockContent content = tab.Content;
|
---|
274 |
|
---|
275 | GraphicsPath path = GetTabOutline(tab, false, true);
|
---|
276 |
|
---|
277 | Color startColor = DockPanel.Skin.AutoHideStripSkin.TabGradient.StartColor;
|
---|
278 | Color endColor = DockPanel.Skin.AutoHideStripSkin.TabGradient.EndColor;
|
---|
279 | LinearGradientMode gradientMode = DockPanel.Skin.AutoHideStripSkin.TabGradient.LinearGradientMode;
|
---|
280 | g.FillPath(new LinearGradientBrush(rectTabOrigin, startColor, endColor, gradientMode), path);
|
---|
281 | g.DrawPath(PenTabBorder, path);
|
---|
282 |
|
---|
283 | // Set no rotate for drawing icon and text
|
---|
284 | Matrix matrixRotate = g.Transform;
|
---|
285 | g.Transform = MatrixIdentity;
|
---|
286 |
|
---|
287 | // Draw the icon
|
---|
288 | Rectangle rectImage = rectTabOrigin;
|
---|
289 | rectImage.X += ImageGapLeft;
|
---|
290 | rectImage.Y += ImageGapTop;
|
---|
291 | int imageHeight = rectTabOrigin.Height - ImageGapTop - ImageGapBottom;
|
---|
292 | int imageWidth = ImageWidth;
|
---|
293 | if (imageHeight > ImageHeight)
|
---|
294 | imageWidth = ImageWidth * (imageHeight / ImageHeight);
|
---|
295 | rectImage.Height = imageHeight;
|
---|
296 | rectImage.Width = imageWidth;
|
---|
297 | rectImage = GetTransformedRectangle(dockState, rectImage);
|
---|
298 | g.DrawIcon(((Form)content).Icon, RtlTransform(rectImage, dockState));
|
---|
299 |
|
---|
300 | // Draw the text
|
---|
301 | Rectangle rectText = rectTabOrigin;
|
---|
302 | rectText.X += ImageGapLeft + imageWidth + ImageGapRight + TextGapLeft;
|
---|
303 | rectText.Width -= ImageGapLeft + imageWidth + ImageGapRight + TextGapLeft;
|
---|
304 | rectText = RtlTransform(GetTransformedRectangle(dockState, rectText), dockState);
|
---|
305 |
|
---|
306 | Color textColor = DockPanel.Skin.AutoHideStripSkin.TabGradient.TextColor;
|
---|
307 |
|
---|
308 | if (dockState == DockState.DockLeftAutoHide || dockState == DockState.DockRightAutoHide)
|
---|
309 | g.DrawString(content.DockHandler.TabText, TextFont, new SolidBrush(textColor), rectText, StringFormatTabVertical);
|
---|
310 | else
|
---|
311 | g.DrawString(content.DockHandler.TabText, TextFont, new SolidBrush(textColor), rectText, StringFormatTabHorizontal);
|
---|
312 |
|
---|
313 | // Set rotate back
|
---|
314 | g.Transform = matrixRotate;
|
---|
315 | }
|
---|
316 |
|
---|
317 | private Rectangle GetLogicalTabStripRectangle(DockState dockState) {
|
---|
318 | return GetLogicalTabStripRectangle(dockState, false);
|
---|
319 | }
|
---|
320 |
|
---|
321 | private Rectangle GetLogicalTabStripRectangle(DockState dockState, bool transformed) {
|
---|
322 | if (!DockHelper.IsDockStateAutoHide(dockState))
|
---|
323 | return Rectangle.Empty;
|
---|
324 |
|
---|
325 | int leftPanes = GetPanes(DockState.DockLeftAutoHide).Count;
|
---|
326 | int rightPanes = GetPanes(DockState.DockRightAutoHide).Count;
|
---|
327 | int topPanes = GetPanes(DockState.DockTopAutoHide).Count;
|
---|
328 | int bottomPanes = GetPanes(DockState.DockBottomAutoHide).Count;
|
---|
329 |
|
---|
330 | int x, y, width, height;
|
---|
331 |
|
---|
332 | height = MeasureHeight();
|
---|
333 | if (dockState == DockState.DockLeftAutoHide && leftPanes > 0) {
|
---|
334 | x = 0;
|
---|
335 | y = (topPanes == 0) ? 0 : height;
|
---|
336 | width = Height - (topPanes == 0 ? 0 : height) - (bottomPanes == 0 ? 0 : height);
|
---|
337 | } else if (dockState == DockState.DockRightAutoHide && rightPanes > 0) {
|
---|
338 | x = Width - height;
|
---|
339 | if (leftPanes != 0 && x < height)
|
---|
340 | x = height;
|
---|
341 | y = (topPanes == 0) ? 0 : height;
|
---|
342 | width = Height - (topPanes == 0 ? 0 : height) - (bottomPanes == 0 ? 0 : height);
|
---|
343 | } else if (dockState == DockState.DockTopAutoHide && topPanes > 0) {
|
---|
344 | x = leftPanes == 0 ? 0 : height;
|
---|
345 | y = 0;
|
---|
346 | width = Width - (leftPanes == 0 ? 0 : height) - (rightPanes == 0 ? 0 : height);
|
---|
347 | } else if (dockState == DockState.DockBottomAutoHide && bottomPanes > 0) {
|
---|
348 | x = leftPanes == 0 ? 0 : height;
|
---|
349 | y = Height - height;
|
---|
350 | if (topPanes != 0 && y < height)
|
---|
351 | y = height;
|
---|
352 | width = Width - (leftPanes == 0 ? 0 : height) - (rightPanes == 0 ? 0 : height);
|
---|
353 | } else
|
---|
354 | return Rectangle.Empty;
|
---|
355 |
|
---|
356 | if (!transformed)
|
---|
357 | return new Rectangle(x, y, width, height);
|
---|
358 | else
|
---|
359 | return GetTransformedRectangle(dockState, new Rectangle(x, y, width, height));
|
---|
360 | }
|
---|
361 |
|
---|
362 | private Rectangle GetTabRectangle(TabVS2005 tab) {
|
---|
363 | return GetTabRectangle(tab, false);
|
---|
364 | }
|
---|
365 |
|
---|
366 | private Rectangle GetTabRectangle(TabVS2005 tab, bool transformed) {
|
---|
367 | DockState dockState = tab.Content.DockHandler.DockState;
|
---|
368 | Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
|
---|
369 |
|
---|
370 | if (rectTabStrip.IsEmpty)
|
---|
371 | return Rectangle.Empty;
|
---|
372 |
|
---|
373 | int x = tab.TabX;
|
---|
374 | int y = rectTabStrip.Y +
|
---|
375 | (dockState == DockState.DockTopAutoHide || dockState == DockState.DockRightAutoHide ?
|
---|
376 | 0 : TabGapTop);
|
---|
377 | int width = tab.TabWidth;
|
---|
378 | int height = rectTabStrip.Height - TabGapTop;
|
---|
379 |
|
---|
380 | if (!transformed)
|
---|
381 | return new Rectangle(x, y, width, height);
|
---|
382 | else
|
---|
383 | return GetTransformedRectangle(dockState, new Rectangle(x, y, width, height));
|
---|
384 | }
|
---|
385 |
|
---|
386 | private Rectangle GetTransformedRectangle(DockState dockState, Rectangle rect) {
|
---|
387 | if (dockState != DockState.DockLeftAutoHide && dockState != DockState.DockRightAutoHide)
|
---|
388 | return rect;
|
---|
389 |
|
---|
390 | PointF[] pts = new PointF[1];
|
---|
391 | // the center of the rectangle
|
---|
392 | pts[0].X = (float)rect.X + (float)rect.Width / 2;
|
---|
393 | pts[0].Y = (float)rect.Y + (float)rect.Height / 2;
|
---|
394 | Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
|
---|
395 | Matrix matrix = new Matrix();
|
---|
396 | matrix.RotateAt(90, new PointF((float)rectTabStrip.X + (float)rectTabStrip.Height / 2,
|
---|
397 | (float)rectTabStrip.Y + (float)rectTabStrip.Height / 2));
|
---|
398 | matrix.TransformPoints(pts);
|
---|
399 |
|
---|
400 | return new Rectangle((int)(pts[0].X - (float)rect.Height / 2 + .5F),
|
---|
401 | (int)(pts[0].Y - (float)rect.Width / 2 + .5F),
|
---|
402 | rect.Height, rect.Width);
|
---|
403 | }
|
---|
404 |
|
---|
405 | protected override IDockContent HitTest(Point ptMouse) {
|
---|
406 | foreach (DockState state in DockStates) {
|
---|
407 | Rectangle rectTabStrip = GetLogicalTabStripRectangle(state, true);
|
---|
408 | if (!rectTabStrip.Contains(ptMouse))
|
---|
409 | continue;
|
---|
410 |
|
---|
411 | foreach (Pane pane in GetPanes(state)) {
|
---|
412 | DockState dockState = pane.DockPane.DockState;
|
---|
413 | foreach (TabVS2005 tab in pane.AutoHideTabs) {
|
---|
414 | GraphicsPath path = GetTabOutline(tab, true, true);
|
---|
415 | if (path.IsVisible(ptMouse))
|
---|
416 | return tab.Content;
|
---|
417 | }
|
---|
418 | }
|
---|
419 | }
|
---|
420 |
|
---|
421 | return null;
|
---|
422 | }
|
---|
423 |
|
---|
424 | protected internal override int MeasureHeight() {
|
---|
425 | return Math.Max(ImageGapBottom +
|
---|
426 | ImageGapTop + ImageHeight,
|
---|
427 | TextFont.Height) + TabGapTop;
|
---|
428 | }
|
---|
429 |
|
---|
430 | protected override void OnRefreshChanges() {
|
---|
431 | CalculateTabs();
|
---|
432 | Invalidate();
|
---|
433 | }
|
---|
434 |
|
---|
435 | protected override AutoHideStripBase.Tab CreateTab(IDockContent content) {
|
---|
436 | return new TabVS2005(content);
|
---|
437 | }
|
---|
438 | }
|
---|
439 | }
|
---|