📄 renderers.cs
字号:
{
map = new System.Collections.Hashtable();
}
/// <summary>
/// Make a new renderer that will show the given image when the given key is the aspect value
/// </summary>
/// <param name="key">The data value to be matched</param>
/// <param name="image">The image to be shown when the key is matched</param>
public MappedImageRenderer(Object key, Object image)
: this()
{
this.Add(key, image);
}
/// <summary>
/// Make a new renderer that will show the given images when it receives the given keys
/// </summary>
/// <param name="key1"></param>
/// <param name="image1"></param>
/// <param name="key2"></param>
/// <param name="image2"></param>
public MappedImageRenderer(Object key1, Object image1, Object key2, Object image2)
: this()
{
this.Add(key1, image1);
this.Add(key2, image2);
}
/// <summary>
/// Build a renderer from the given array of keys and their matching images
/// </summary>
/// <param name="keysAndImages">An array of key/image pairs</param>
public MappedImageRenderer(Object[] keysAndImages)
: this()
{
if ((keysAndImages.GetLength(0) % 2) != 0)
throw new ArgumentException("Array must have key/image pairs");
for (int i = 0; i < keysAndImages.GetLength(0); i += 2)
this.Add(keysAndImages[i], keysAndImages[i + 1]);
}
/// <summary>
/// Register the image that should be drawn when our Aspect has the data value.
/// </summary>
/// <param name="value">Value that the Aspect must match</param>
/// <param name="image">An ImageSelector -- an int, string or image</param>
public void Add(Object value, Object image)
{
if (value == null)
this.nullImage = image;
else
map[value] = image;
}
/// <summary>
/// Render our value
/// </summary>
/// <param name="g"></param>
/// <param name="r"></param>
public override void Render(Graphics g, Rectangle r)
{
this.DrawBackground(g, r);
ICollection aspectAsCollection = this.Aspect as ICollection;
if (aspectAsCollection == null)
this.RenderOne(g, r, this.Aspect);
else
this.RenderCollection(g, r, aspectAsCollection);
}
protected void RenderCollection(Graphics g, Rectangle r, ICollection imageSelectors)
{
ArrayList images = new ArrayList();
Image image = null;
foreach (Object selector in imageSelectors) {
if (selector == null)
image = this.GetImage(this.nullImage);
else if (map.ContainsKey(selector))
image = this.GetImage(map[selector]);
else
image = null;
if (image != null)
images.Add(image);
}
this.DrawImages(g, r, images);
}
protected void RenderOne(Graphics g, Rectangle r, Object selector)
{
Image image = null;
if (selector == null)
image = this.GetImage(this.nullImage);
else
if (map.ContainsKey(selector))
image = this.GetImage(map[selector]);
if (image != null)
this.DrawAlignedImage(g, r, image);
}
#region Private variables
private Hashtable map; // Track the association between values and images
private Object nullImage; // image to be drawn for null values (since null can't be a key)
#endregion
}
/// <summary>
/// This renderer draws just a checkbox to match the check state of our model object.
/// </summary>
public class CheckStateRenderer : BaseRenderer
{
public override void Render(Graphics g, Rectangle r)
{
this.DrawBackground(g, r);
r = this.CalculateCheckBoxBounds(g, r);
this.DrawImage(g, r, this.Column.GetCheckStateImage(this.RowObject));
}
protected override Rectangle HandleGetEditRectangle(Graphics g, Rectangle cellBounds, OLVListItem item, int subItemIndex)
{
return cellBounds;
}
protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y)
{
Rectangle r = this.CalculateCheckBoxBounds(g, this.Bounds);
if (r.Contains(x, y))
hti.HitTestLocation = HitTestLocation.CheckBox;
}
private Rectangle CalculateCheckBoxBounds(Graphics g, Rectangle cellBounds)
{
// We don't use this because the checkbox images were drawn into the small image list
//Size checkBoxSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.CheckedNormal);
Size checkBoxSize = this.ListView.SmallImageList.ImageSize;
return this.AlignRectangle(cellBounds, new Rectangle(new Point(0, 0), checkBoxSize));
}
}
/// <summary>
/// Render an image that comes from our data source.
/// </summary>
/// <remarks>The image can be sourced from:
/// <list>
/// <item>a byte-array (normally when the image to be shown is
/// stored as a value in a database)</item>
/// <item>an int, which is treated as an index into the image list</item>
/// <item>a string, which is treated first as a file name, and failing that as an index into the image list</item>
/// <item>an ICollection of ints or strings, which will be drawn as consecutive images</item>
/// </list>
/// <para>If an image is an animated GIF, it's state is stored in the SubItem object.</para>
/// <para>By default, the image renderer does not render animations (it begins life with animations paused).
/// To enable animations, you must call Unpause().</para>
/// </remarks>
public class ImageRenderer : BaseRenderer
{
/// <summary>
/// Make an empty image renderer
/// </summary>
public ImageRenderer()
: base()
{
this.tickler = new System.Threading.Timer(new TimerCallback(this.OnTimer), null, Timeout.Infinite, Timeout.Infinite);
this.stopwatch = new Stopwatch();
}
/// <summary>
/// Make an empty image renderer that begins life ready for animations
/// </summary>
public ImageRenderer(bool startAnimations)
: this()
{
this.Paused = !startAnimations;
}
#region Properties
/// <summary>
/// Should the animations in this renderer be paused?
/// </summary>
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool Paused
{
get { return isPaused; }
set
{
if (isPaused != value) {
isPaused = value;
if (isPaused) {
this.tickler.Change(Timeout.Infinite, Timeout.Infinite);
this.stopwatch.Stop();
} else {
this.tickler.Change(1, Timeout.Infinite);
this.stopwatch.Start();
}
}
}
}
private bool isPaused = true;
#endregion
#region Commands
/// <summary>
/// Pause any animations
/// </summary>
public void Pause()
{
this.Paused = true;
}
/// <summary>
/// Unpause any animations
/// </summary>
public void Unpause()
{
this.Paused = false;
}
#endregion
#region Drawing
/// <summary>
/// Draw our image
/// </summary>
/// <param name="g"></param>
/// <param name="r"></param>
public override void Render(Graphics g, Rectangle r)
{
this.DrawBackground(g, r);
if (this.Aspect == null || this.Aspect == System.DBNull.Value)
return;
ICollection imageSelectors = this.Aspect as ICollection;
if (imageSelectors == null)
this.DrawAlignedImage(g, r, this.GetImageFromAspect());
else
this.DrawImages(g, r, imageSelectors);
}
/// <summary>
/// Translate our Aspect into an image.
/// </summary>
/// <remarks>The strategy is:<list type="unordered">
/// <item>If its a byte array, we treat it as an in-memory image</item>
/// <item>If it's an int, we use that as an index into our image list</item>
/// <item>If it's a string, we try to load a file by that name. If we can't,
/// we use the string as an index into our image list.</item>
///</list></remarks>
/// <returns>An image</returns>
protected Image GetImageFromAspect()
{
// If we've already figured out the image, don't do it again
if (this.OLVSubItem != null && this.OLVSubItem.ImageSelector is Image) {
if (this.OLVSubItem.AnimationState == null)
return (Image)this.OLVSubItem.ImageSelector;
else
return this.OLVSubItem.AnimationState.image;
}
// Try to convert our Aspect into an Image
// If its a byte array, we treat it as an in-memory image
// If it's an int, we use that as an index into our image list
// If it's a string, we try to find a file by that name.
// If we can't, we use the string as an index into our image list.
Image image = null;
if (this.Aspect is System.Byte[]) {
using (MemoryStream stream = new MemoryStream((System.Byte[])this.Aspect)) {
try {
image = Image.FromStream(stream);
}
catch (ArgumentException) {
// ignore
}
}
} else if (this.Aspect is Int32) {
image = this.GetImage(this.Aspect);
} else {
String str = this.Aspect as String;
if (!String.IsNullOrEmpty(str)) {
try {
image = Image.FromFile(str);
}
catch (FileNotFoundException) {
image = this.GetImage(this.Aspect);
}
catch (OutOfMemoryException) {
image = this.GetImage(this.Aspect);
}
}
}
// If this image is an animation, initialize the animation process
if (this.OLVSubItem != null && AnimationState.IsAnimation(image)) {
this.OLVSubItem.AnimationState = new AnimationState(image);
}
// Cache the image so we don't repeat this dreary process
if (this.OLVSubItem != null)
this.OLVSubItem.ImageSelector = image;
return image;
}
#endregion
#region Events
/// <summary>
/// This is the method that is invoked by the timer. It basically switches control to the listview thread.
/// </summary>
/// <param name="state">not used</param>
public void OnTimer(Object state)
{
if (this.ListView == null || this.Paused)
this.tickler.Change(1000, Timeout.Infinite);
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -