///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
/*
using System.Windows.Forms.Themes;
*/
using JetBrains.Interop.WinApi;
using JetBrains.UI.Interop;
using JetBrains.UI.RichText;
// TODO(H): reenable theming, it's been disabled to see if we can work without the UxTheme cpp component
namespace JetBrains.JetListViewLibrary
{
///
/// An implenentation of IControlPainter which uses GDI and XPTheme functions for drawing.
///
public class GdiControlPainter : IControlPainter, IDisposable
{
private readonly FontCache _fontCache = new FontCache();
public void Dispose()
{
_fontCache.Dispose();
}
public void DrawFocusRect(Graphics g, Rectangle rc)
{
RECT rect = new RECT(rc.Left, rc.Top, rc.Right, rc.Bottom);
IntPtr hdc = g.GetHdc();
try
{
Win32Declarations.DrawFocusRect(hdc, ref rect);
}
finally
{
g.ReleaseHdc(hdc);
}
}
public int DrawText(Graphics g, string text, Font font, Color color, Rectangle rc, StringFormat format)
{
int height;
RectangleF rcClip = g.ClipBounds;
RECT rect = new RECT(rc.Left, rc.Top, rc.Right, rc.Bottom);
IntPtr hdc = g.GetHdc();
try
{
IntPtr clipRgn = Win32Declarations.CreateRectRgn(0, 0, 0, 0);
if(Win32Declarations.GetClipRgn(hdc, clipRgn) != 1)
{
Win32Declarations.DeleteObject(clipRgn);
clipRgn = IntPtr.Zero;
}
Win32Declarations.IntersectClipRect(hdc, (int)rcClip.Left, (int)rcClip.Top, (int)rcClip.Right, (int)rcClip.Bottom);
IntPtr hFont = _fontCache.GetHFont(font);
IntPtr oldFont = Win32Declarations.SelectObject(hdc, hFont);
int textColor = Win32Declarations.ColorToRGB(color);
int oldColor = Win32Declarations.SetTextColor(hdc, textColor);
BackgroundMode oldMode = Win32Declarations.SetBkMode(hdc, BackgroundMode.TRANSPARENT);
DrawTextFormatFlags flags = 0;
if((format.FormatFlags & StringFormatFlags.NoWrap) != 0)
flags |= DrawTextFormatFlags.DT_SINGLELINE;
else
flags |= DrawTextFormatFlags.DT_WORDBREAK;
if(format.Alignment == StringAlignment.Center)
flags |= DrawTextFormatFlags.DT_CENTER;
else if(format.Alignment == StringAlignment.Far)
flags |= DrawTextFormatFlags.DT_RIGHT;
if(format.LineAlignment == StringAlignment.Center)
flags |= DrawTextFormatFlags.DT_VCENTER;
if(format.Trimming == StringTrimming.EllipsisCharacter)
flags |= DrawTextFormatFlags.DT_END_ELLIPSIS;
if(format.HotkeyPrefix == HotkeyPrefix.None)
flags |= DrawTextFormatFlags.DT_NOPREFIX;
height = Win32Declarations.DrawText(hdc, text, text.Length, ref rect, flags);
Win32Declarations.SelectClipRgn(hdc, clipRgn);
Win32Declarations.DeleteObject(clipRgn);
Win32Declarations.SetBkMode(hdc, oldMode);
Win32Declarations.SetTextColor(hdc, oldColor);
Win32Declarations.SelectObject(hdc, oldFont);
}
finally
{
g.ReleaseHdc(hdc);
}
return height;
}
public Size MeasureText(string text, Font font)
{
IntPtr hdc = Win32Declarations.GetDC(IntPtr.Zero);
try
{
return MeasureText(hdc, font, text);
}
finally
{
Win32Declarations.ReleaseDC(IntPtr.Zero, hdc);
}
}
public Size MeasureText(Graphics g, string text, Font font)
{
IntPtr hdc = g.GetHdc();
try
{
return MeasureText(hdc, font, text);
}
finally
{
g.ReleaseHdc(hdc);
}
}
private Size MeasureText(IntPtr hdc, Font font, string text)
{
SIZE sz = new SIZE();
IntPtr hFont = _fontCache.GetHFont(font);
IntPtr oldFont = Win32Declarations.SelectObject(hdc, hFont);
Win32Declarations.GetTextExtentPoint32(hdc, text, text.Length, ref sz);
Win32Declarations.SelectObject(hdc, oldFont);
return new Size(sz.cx, sz.cy);
}
public Size MeasureText(Graphics g, string text, Font font, int maxWidth)
{
Size result;
IntPtr hdc = g.GetHdc();
try
{
IntPtr hFont = _fontCache.GetHFont(font);
IntPtr oldFont = Win32Declarations.SelectObject(hdc, hFont);
SIZE sz = new SIZE();
Win32Declarations.GetTextExtentPoint32(hdc, text, text.Length, ref sz);
if(sz.cx < maxWidth)
result = new Size(sz.cx, sz.cy);
else
{
RECT rc = new RECT(0, 0, maxWidth, Screen.PrimaryScreen.Bounds.Height);
int height = Win32Declarations.DrawText(hdc, text, text.Length, ref rc, DrawTextFormatFlags.DT_CALCRECT | DrawTextFormatFlags.DT_WORDBREAK);
result = new Size(maxWidth, height);
}
Win32Declarations.SelectObject(hdc, oldFont);
}
finally
{
g.ReleaseHdc(hdc);
}
return result;
}
public static bool IsAppThemed
{
get
{
//return UxTheme.IsAppThemed;
return false;
}
}
public void DrawCheckBox(Graphics g, Rectangle rc, ButtonState state)
{
if(IsAppThemed)
{
/*
ThemePartState partState = GetCheckBoxPart(state);
if(partState != null)
{
Rectangle rcClip = new Rectangle((int)g.ClipBounds.Left, (int)g.ClipBounds.Top, (int)g.ClipBounds.Width, (int)g.ClipBounds.Height);
try
{
partState.DrawBackground(g, rc, rcClip);
}
catch(Exception ex)
{
Trace.WriteLine("Failed to DrawCheckBox: " + ex.Message);
}
}
else
ControlPaint.DrawCheckBox(g, rc, state);
*/
}
else
ControlPaint.DrawCheckBox(g, rc, state);
}
public void DrawListViewBorder(Graphics g, Rectangle rc, BorderStyle borderStyle)
{
if(borderStyle == BorderStyle.FixedSingle)
ControlPaint.DrawBorder3D(g, rc, Border3DStyle.Flat);
else if(borderStyle == BorderStyle.Fixed3D)
{
/*
object partState = null;
if(IsAppThemed)
partState = (object)GetListViewBorderPart();
if(partState != null)
{
Rectangle rcClip = new Rectangle((int)g.ClipBounds.Left, (int)g.ClipBounds.Top, (int)g.ClipBounds.Width, (int)g.ClipBounds.Height);
try
{
partState.DrawBackground(g, rc, rcClip);
}
catch(Exception ex)
{
Trace.WriteLine("Failed to DrawListViewBorder: " + ex.Message);
}
}
else
*/
ControlPaint.DrawBorder3D(g, rc);
}
}
public int GetListViewBorderSize(BorderStyle borderStyle)
{
if(borderStyle == BorderStyle.None)
return 0;
return 1;
}
public void DrawTreeIcon(Graphics g, Rectangle rc, bool expanded)
{
if(IsAppThemed)
{
/*
ThemePart part = GetGlyphPart();
if(part != null)
{
ThemePartState partState = part.States[expanded ? "OPENED" : "CLOSED"];
Rectangle rcClip = new Rectangle((int)g.ClipBounds.Left, (int)g.ClipBounds.Top, (int)g.ClipBounds.Width, (int)g.ClipBounds.Height);
try
{
partState.DrawBackground(g, rc, rcClip);
}
catch(Exception ex)
{
Trace.WriteLine("Failed to DrawTreeIcon: " + ex.Message);
}
return;
}
*/
}
DefaultControlPainter.DoDrawTreeIcon(g, rc, expanded);
}
public Size GetTreeIconSize(Graphics g, Rectangle rc)
{
return DefaultControlPainter.DoGetTreeIconSize(rc);
}
/*
private static ThemePart GetGlyphPart()
{
ThemeInfo info = new ThemeInfo();
try
{
WindowTheme theme = info["TREEVIEW"];
return theme.Parts["GLYPH"];
}
catch(IndexOutOfRangeException)
{
// possibly the theme on the user's machine does not contain that part
return null;
}
}
*/
/*
private static ThemePartState GetListViewBorderPart()
{
ThemeInfo info = new ThemeInfo();
try
{
WindowTheme theme = info["LISTVIEW"];
ThemePart part = theme.Parts["LISTITEM"];
return part.States["NORMAL"];
}
catch(IndexOutOfRangeException)
{
return null;
}
}
*/
/*
private static ThemePartState GetCheckBoxPart(ButtonState state)
{
ThemeInfo info = new ThemeInfo();
try
{
WindowTheme theme = info["BUTTON"];
ThemePart part = theme.Parts["CHECKBOX"];
string firstPart = ((state & ButtonState.Checked) != 0) ? "CHECKED" : "UNCHECKED";
string secondPart = ((state & ButtonState.Inactive) != 0) ? "DISABLED" : "NORMAL";
return part.States[firstPart + secondPart];
}
catch(IndexOutOfRangeException)
{
return null;
}
}
*/
}
}