Initial commit of existing code.

* All renderdoc code up to this point was written by me, history is available by request
This commit is contained in:
baldurk
2014-05-02 08:33:01 +01:00
parent 04b1549c0f
commit c38affcded
695 changed files with 230316 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
namespace renderdocui.Controls
{
partial class ConstantBufferPreviewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
TreelistView.TreeListColumn treeListColumn1 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("VarName", "Name")));
TreelistView.TreeListColumn treeListColumn2 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("VarValue", "Value")));
TreelistView.TreeListColumn treeListColumn3 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("VarType", "Type")));
this.slotLabel = new System.Windows.Forms.Label();
this.nameLabel = new System.Windows.Forms.Label();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.variables = new TreelistView.TreeListView();
this.tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.variables)).BeginInit();
this.SuspendLayout();
//
// slotLabel
//
this.slotLabel.AutoSize = true;
this.slotLabel.Location = new System.Drawing.Point(3, 0);
this.slotLabel.Name = "slotLabel";
this.slotLabel.Padding = new System.Windows.Forms.Padding(5);
this.slotLabel.Size = new System.Drawing.Size(10, 23);
this.slotLabel.TabIndex = 0;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(19, 0);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Padding = new System.Windows.Forms.Padding(5);
this.nameLabel.Size = new System.Drawing.Size(10, 23);
this.nameLabel.TabIndex = 1;
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.slotLabel, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.nameLabel, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.variables, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(499, 357);
this.tableLayoutPanel1.TabIndex = 0;
//
// variables
//
treeListColumn1.AutoSizeMinSize = 0;
treeListColumn1.Width = 175;
treeListColumn2.AutoSize = true;
treeListColumn2.AutoSizeMinSize = 0;
treeListColumn2.Width = 50;
treeListColumn3.AutoSizeMinSize = 0;
treeListColumn3.Width = 50;
this.variables.Columns.AddRange(new TreelistView.TreeListColumn[] {
treeListColumn1,
treeListColumn2,
treeListColumn3});
this.variables.ColumnsOptions.LeftMargin = 0;
this.tableLayoutPanel1.SetColumnSpan(this.variables, 2);
this.variables.Cursor = System.Windows.Forms.Cursors.Arrow;
this.variables.Dock = System.Windows.Forms.DockStyle.Fill;
this.variables.Location = new System.Drawing.Point(3, 26);
this.variables.Name = "variables";
this.variables.RowOptions.ShowHeader = false;
this.variables.Size = new System.Drawing.Size(493, 328);
this.variables.TabIndex = 2;
this.variables.Text = "treeListView1";
this.variables.KeyDown += new System.Windows.Forms.KeyEventHandler(this.variables_KeyDown);
//
// ConstantBufferPreviewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "ConstantBufferPreviewer";
this.Size = new System.Drawing.Size(499, 357);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.variables)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private TreelistView.TreeListView variables;
private System.Windows.Forms.Label slotLabel;
private System.Windows.Forms.Label nameLabel;
}
}
@@ -0,0 +1,268 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using renderdocui.Code;
using renderdoc;
using WeifenLuo.WinFormsUI.Docking;
namespace renderdocui.Controls
{
public partial class ConstantBufferPreviewer : UserControl, ILogViewerForm
{
private Core m_Core;
public ConstantBufferPreviewer(Core c, ShaderStageType stage, UInt32 slot)
{
InitializeComponent();
m_Core = c;
Stage = stage;
Slot = slot;
shader = m_Core.CurPipelineState.GetShader(stage);
UpdateLabels();
uint offs = 0;
m_Core.CurPipelineState.GetConstantBuffer(Stage, Slot, out cbuffer, out offs);
m_Core.Renderer.BeginInvoke((ReplayRenderer r) =>
{
SetVariables(r.GetCBufferVariableContents(shader, Slot, cbuffer, offs));
});
m_Core.AddLogViewer(this);
}
private static List<DockContent> m_Docks = new List<DockContent>();
public static DockContent Has(ShaderStageType stage, UInt32 slot)
{
foreach (var d in m_Docks)
{
ConstantBufferPreviewer cb = d.Controls[0] as ConstantBufferPreviewer;
if(cb.Stage == stage && cb.Slot == slot)
return cb.Parent as DockContent;
}
return null;
}
public static void ShowDock(DockContent dock, DockPane pane, DockAlignment align, double proportion)
{
dock.FormClosed += new FormClosedEventHandler(dock_FormClosed);
if (m_Docks.Count > 0)
dock.Show(m_Docks[0].Pane, m_Docks[0]);
else
dock.Show(pane, align, proportion);
m_Docks.Add(dock);
}
static void dock_FormClosed(object sender, FormClosedEventArgs e)
{
DockContent p = sender as DockContent;
m_Docks.Remove(p);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
m_Core.RemoveLogViewer(this);
}
base.Dispose(disposing);
}
public void OnLogfileClosed()
{
variables.BeginUpdate();
variables.Nodes.Clear();
variables.EndUpdate();
variables.Invalidate();
}
public void OnLogfileLoaded()
{
variables.BeginUpdate();
variables.Nodes.Clear();
variables.EndUpdate();
variables.Invalidate();
}
private void AddVariables(TreelistView.NodeCollection root, ShaderVariable[] vars)
{
foreach (var v in vars)
{
TreelistView.Node n = root.Add(new TreelistView.Node(new object[] { v.name, v, v.TypeString() }));
if (v.rows > 1)
{
for (int i = 0; i < v.rows; i++)
{
n.Nodes.Add(new TreelistView.Node(new object[] { String.Format("{0}.row{1}", v.name, i), v.Row(i), v.RowTypeString() }));
}
}
if (v.members.Length > 0)
{
AddVariables(n.Nodes, v.members);
}
}
}
private void SetVariables(ShaderVariable[] vars)
{
if (variables.InvokeRequired)
{
this.BeginInvoke(new Action(() => { SetVariables(vars); }));
return;
}
variables.BeginUpdate();
variables.Nodes.Clear();
if(vars != null && vars.Length > 0)
AddVariables(variables.Nodes, vars);
variables.EndUpdate();
variables.Invalidate();
}
public void OnEventSelected(UInt32 frameID, UInt32 eventID)
{
uint offs = 0;
m_Core.CurPipelineState.GetConstantBuffer(Stage, Slot, out cbuffer, out offs);
shader = m_Core.CurPipelineState.GetShader(Stage);
var reflection = m_Core.CurPipelineState.GetShaderReflection(Stage);
UpdateLabels();
if (reflection == null || reflection.ConstantBlocks.Length <= Slot)
{
SetVariables(null);
return;
}
m_Core.Renderer.BeginInvoke((ReplayRenderer r) =>
{
SetVariables(r.GetCBufferVariableContents(shader, Slot, cbuffer, offs));
});
}
private string BufferName = "";
private ResourceId cbuffer;
private ResourceId shader;
private ShaderStageType Stage;
private UInt32 Slot = 0;
public override string Text
{
get
{
return String.Format("{0} CB {1}", Stage.ToString(), Slot);
}
}
private void UpdateLabels()
{
BufferName = "";
bool needName = true;
foreach (var b in m_Core.CurBuffers)
{
if (b.ID == cbuffer)
{
BufferName = b.name;
if(b.customName)
needName = false;
}
}
var reflection = m_Core.CurPipelineState.GetShaderReflection(Stage);
if (reflection != null)
{
if (needName &&
Slot < reflection.ConstantBlocks.Length &&
reflection.ConstantBlocks[Slot].name != "")
BufferName = "<" + reflection.ConstantBlocks[Slot].name + ">";
}
nameLabel.Text = BufferName;
slotLabel.Text = Stage.ToString();
slotLabel.Text += " Shader Slot " + Slot;
}
private void variables_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.C && e.Control)
{
int[] width = new int[] { 0, 0, 0 };
foreach (var n in variables.NodesSelection)
{
width[0] = Math.Max(width[0], n[0].ToString().Length);
width[1] = Math.Max(width[1], n[1].ToString().Length);
width[2] = Math.Max(width[2], n[2].ToString().Length);
}
width[0] = Math.Min(50, width[0]);
width[1] = Math.Min(50, width[1]);
width[2] = Math.Min(50, width[2]);
string fmt = "{0,-" + width[0] + "} {1,-" + width[1] + "} {2,-" + width[2] + "}" + Environment.NewLine;
string text = "";
foreach (var n in variables.NodesSelection)
{
text += string.Format(fmt, n[0], n[1], n[2]);
}
Clipboard.SetText(text);
}
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+37
View File
@@ -0,0 +1,37 @@
namespace renderdocui.Controls
{
partial class DoubleClickSplitter
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
}
#endregion
}
}
+234
View File
@@ -0,0 +1,234 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace renderdocui.Controls
{
public partial class DoubleClickSplitter : SplitContainer
{
public DoubleClickSplitter()
{
InitializeComponent();
SplitterMoving += new SplitterCancelEventHandler(OnSplitterMoving);
}
private int m_PanelMinsize = 0;
private int m_SplitterDistance = 0;
private bool m_Panel1Collapse = true;
[Description("If the first panel should be the one to collapse"), Category("Behavior")]
[DefaultValue(typeof(bool), "true")]
public bool Panel1Collapse { get { return m_Panel1Collapse; } set { m_Panel1Collapse = value; } }
private bool m_Collapsed = false;
[Browsable(false)]
public bool Collapsed
{
get
{
return m_Collapsed;
}
set
{
if (m_Collapsed != value)
{
if (value)
{
m_PanelMinsize = Panel1Collapse ? Panel1MinSize : Panel2MinSize;
m_SplitterDistance = SplitterDistance;
if (Panel1Collapse)
{
Panel1MinSize = 0;
SplitterDistance = 0;
}
else
{
Panel2MinSize = 0;
SplitterDistance = 10000;
}
}
else
{
if (Panel1Collapse)
Panel1MinSize = m_PanelMinsize;
else
Panel2MinSize = m_PanelMinsize;
SplitterDistance = m_SplitterDistance;
}
}
m_Collapsed = value;
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
try
{
if (m_Collapsed && Panel1Collapse)
SplitterDistance = Panel1MinSize;
else if (m_Collapsed && !Panel1Collapse)
{
if(Orientation == Orientation.Vertical)
SplitterDistance = Height - Panel2MinSize;
else if(Orientation == Orientation.Horizontal)
SplitterDistance = Width - Panel2MinSize;
}
}
catch (System.Exception)
{
// non fatal
}
// arrow
{
var arrow_centre = new Point(SplitterRectangle.X + SplitterRectangle.Width / 2, SplitterRectangle.Y + SplitterRectangle.Height / 2);
var oldmode = e.Graphics.SmoothingMode;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Point[] dots = null;
using(var brush = new SolidBrush(ForeColor))
{
int dot_diameter = 0;
if (Orientation == Orientation.Horizontal)
{
dot_diameter = SplitterRectangle.Height - Math.Max(0, SplitterRectangle.Height / 4);
var arrow_size = new Size(SplitterRectangle.Height * 2, dot_diameter);
var arrow_pos = new Point(arrow_centre.X - arrow_size.Width / 2, arrow_centre.Y - arrow_size.Height / 2);
if ((Panel1Collapse && !Collapsed) || (!Panel1Collapse && Collapsed))
{
e.Graphics.FillPolygon(brush, new Point[] {
new Point(arrow_pos.X, arrow_pos.Y + arrow_size.Height),
new Point(arrow_pos.X +arrow_size.Width, arrow_pos.Y + arrow_size.Height),
new Point(arrow_pos.X + arrow_size.Width/2, arrow_pos.Y),
});
}
else
{
e.Graphics.FillPolygon(brush, new Point[] {
new Point(arrow_pos.X, arrow_pos.Y),
new Point(arrow_pos.X +arrow_size.Width, arrow_pos.Y),
new Point(arrow_pos.X + arrow_size.Width/2, arrow_pos.Y + arrow_size.Height),
});
}
dots = new Point[] {
new Point(arrow_centre.X - SplitterRectangle.Width/4 - (int)(dot_diameter*1.5), arrow_centre.Y),
new Point(arrow_centre.X - SplitterRectangle.Width/4, arrow_centre.Y),
new Point(arrow_centre.X - SplitterRectangle.Width/4 + (int)(dot_diameter*1.5), arrow_centre.Y),
new Point(arrow_centre.X + SplitterRectangle.Width/4 - (int)(dot_diameter*1.5), arrow_centre.Y),
new Point(arrow_centre.X + SplitterRectangle.Width/4, arrow_centre.Y),
new Point(arrow_centre.X + SplitterRectangle.Width/4 + (int)(dot_diameter*1.5), arrow_centre.Y),
};
}
else
{
dot_diameter = SplitterRectangle.Width - Math.Max(0, SplitterRectangle.Width / 4);
var arrow_size = new Size(dot_diameter, SplitterRectangle.Width * 2);
var arrow_pos = new Point(arrow_centre.X - arrow_size.Width / 2, arrow_centre.Y - arrow_size.Height / 2);
if ((Panel1Collapse && !Collapsed) || (!Panel1Collapse && Collapsed))
{
e.Graphics.FillPolygon(brush, new Point[] {
new Point(arrow_pos.X + arrow_size.Width, arrow_pos.Y),
new Point(arrow_pos.X +arrow_size.Width, arrow_pos.Y + arrow_size.Height),
new Point(arrow_pos.X, arrow_pos.Y + arrow_size.Height/2),
});
}
else
{
e.Graphics.FillPolygon(brush, new Point[] {
new Point(arrow_pos.X, arrow_pos.Y),
new Point(arrow_pos.X, arrow_pos.Y +arrow_size.Height),
new Point(arrow_pos.X + arrow_size.Width, arrow_pos.Y + arrow_size.Height/2),
});
}
dots = new Point[] {
new Point(arrow_centre.X, arrow_centre.Y - SplitterRectangle.Height/4 - (int)(dot_diameter*1.5)),
new Point(arrow_centre.X, arrow_centre.Y - SplitterRectangle.Height/4),
new Point(arrow_centre.X, arrow_centre.Y - SplitterRectangle.Height/4 + (int)(dot_diameter*1.5)),
new Point(arrow_centre.X, arrow_centre.Y + SplitterRectangle.Height/4 - (int)(dot_diameter*1.5)),
new Point(arrow_centre.X, arrow_centre.Y + SplitterRectangle.Height/4),
new Point(arrow_centre.X, arrow_centre.Y + SplitterRectangle.Height/4 + (int)(dot_diameter*1.5)),
};
}
if (dots != null)
{
foreach (var d in dots)
{
var rect = new Rectangle(new Point(d.X - dot_diameter / 2, d.Y - dot_diameter / 2), new Size(dot_diameter, dot_diameter));
e.Graphics.FillPie(brush, rect, 0, 360.0f);
}
}
}
e.Graphics.SmoothingMode = oldmode;
}
}
protected override void OnDoubleClick(EventArgs e)
{
if (SplitterRectangle.Contains(PointToClient(Control.MousePosition)))
{
Collapsed = !Collapsed;
return;
}
base.OnDoubleClick(e);
}
void OnSplitterMoving(object sender, SplitterCancelEventArgs e)
{
if (Collapsed)
e.Cancel = true;
}
}
}
+95
View File
@@ -0,0 +1,95 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace renderdocui.Controls
{
public class NoScrollPanel : Panel
{
public MouseEventHandler MouseWheelHandler = null;
public KeyEventHandler KeyHandler = null;
public NoScrollPanel() { }
protected override void OnMouseWheel(MouseEventArgs e)
{
if (MouseWheelHandler != null)
MouseWheelHandler(this, e);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (Focused && KeyHandler != null)
{
var args = new KeyEventArgs(keyData);
KeyHandler(this, args);
if(args.Handled)
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
public bool Painting = false;
protected override void OnPaintBackground(PaintEventArgs pevent)
{
if (Controls.Count == 0 && !Painting)
{
pevent.Graphics.Clear(BackColor);
}
else if (Controls.Count == 1)
{
var pos = Controls[0].Location;
var size = Controls[0].Size;
using (var brush = new SolidBrush(BackColor))
{
var rightRect = new Rectangle(pos.X + size.Width, 0, ClientRectangle.Width - (pos.X + size.Width), ClientRectangle.Height);
var leftRect = new Rectangle(0, 0, pos.X, ClientRectangle.Height);
var topRect = new Rectangle(pos.X, 0, size.Width, pos.Y);
var bottomRect = new Rectangle(pos.X, pos.Y + size.Height, size.Width, ClientRectangle.Height - (pos.Y + size.Height));
pevent.Graphics.FillRectangle(brush, topRect);
pevent.Graphics.FillRectangle(brush, bottomRect);
pevent.Graphics.FillRectangle(brush, leftRect);
pevent.Graphics.FillRectangle(brush, rightRect);
}
}
}
protected override Point ScrollToControl(Control activeControl)
{
// Returning the current location prevents the panel from
// scrolling to the active control when the panel loses and regains focus
return this.DisplayRectangle.Location;
}
}
}
+47
View File
@@ -0,0 +1,47 @@
namespace renderdocui.Controls
{
partial class PipelineFlowchart
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// PipelineFlowchart
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Transparent;
this.Name = "PipelineFlowchart";
this.Size = new System.Drawing.Size(988, 229);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.PipelineFlowchart_Paint);
this.ResumeLayout(false);
}
#endregion
}
}
+372
View File
@@ -0,0 +1,372 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace renderdocui.Controls
{
public partial class PipelineFlowchart : UserControl
{
public PipelineFlowchart()
{
InitializeComponent();
this.DoubleBuffered = true;
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
public void SetStages(KeyValuePair<string, string>[] stages)
{
m_StageNames = stages;
m_StagesEnabled = new bool[stages.Length];
m_StageFlows = new bool[stages.Length];
for(int i=0; i < stages.Length; i++)
m_StageFlows[i] = true;
Invalidate();
}
#region Events
private static readonly object SelectedStageChangedEvent = new object();
[Description("Event raised when the selected pipeline stage is changed."), Category("Behavior")]
public event EventHandler<EventArgs> SelectedStageChanged
{
add { Events.AddHandler(SelectedStageChangedEvent, value); }
remove { Events.RemoveHandler(SelectedStageChangedEvent, value); }
}
protected virtual void OnSelectedStageChanged(EventArgs e)
{
EventHandler<EventArgs> handler = (EventHandler<EventArgs>)Events[SelectedStageChangedEvent];
if (handler != null)
handler(this, e);
}
#endregion
#region Data Properties
private bool[] m_StagesEnabled = null;
private bool[] m_StageFlows = null;
private KeyValuePair<string, string>[] m_StageNames = null;
public void SetStagesEnabled(bool[] enabled)
{
if (m_StagesEnabled != null && enabled.Length == m_StagesEnabled.Length)
m_StagesEnabled = enabled;
Invalidate();
}
public void IsolateStage(int index)
{
if (m_StageNames != null && index >= 0 && index < m_StageNames.Length)
m_StageFlows[index] = false;
}
private bool IsStageEnabled(int index)
{
return m_StagesEnabled != null && m_StagesEnabled[index];
}
private int m_HoverStage = -1;
private int m_SelectedStage = 0;
[Browsable(false)]
public int SelectedStage
{
get
{
return m_SelectedStage;
}
set
{
if (value >= 0 && m_StageNames != null && value < m_StageNames.Length)
{
m_SelectedStage = value;
Invalidate();
OnSelectedStageChanged(new EventArgs());
}
}
}
#endregion
#region Constants and positions/dimensions
const int BoxBorderWidth = 3;
const int MinBoxDimension = 25;
const int MaxBoxCornerRadius = 20;
const float BoxCornerRadiusFraction = 1.0f / 6.0f;
const float ArrowHeadSize = 6.0f;
const int MinBoxMargin = 4;
const int BoxLabelMargin = 8;
const float BoxMarginFraction = 0.02f;
private Rectangle TotalAreaRect
{
get
{
Rectangle rect = ClientRectangle;
rect.Inflate(-1, -1);
rect.X += Padding.Left;
rect.Width -= Padding.Left + Padding.Right;
rect.Y += Padding.Top;
rect.Height -= Padding.Top + Padding.Bottom;
rect.Inflate(-BoxBorderWidth, -BoxBorderWidth);
return rect;
}
}
private float BoxMargin
{
get
{
float margin = Math.Max(TotalAreaRect.Width, TotalAreaRect.Height) * BoxMarginFraction;
margin = Math.Max(MinBoxMargin, margin);
return margin;
}
}
private int NumGaps { get { return m_StageNames == null ? 1 : m_StageNames.Length - 1; } }
private int NumItems { get { return m_StageNames == null ? 2 : m_StageNames.Length; } }
private SizeF BoxSize
{
get
{
float boxeswidth = TotalAreaRect.Width - NumGaps * BoxMargin;
float boxdim = Math.Min(TotalAreaRect.Height, boxeswidth / NumItems);
boxdim = Math.Max(MinBoxDimension, boxdim);
float oblongwidth = Math.Max(0, (boxeswidth - boxdim * NumItems) / NumItems);
return new SizeF(boxdim + oblongwidth, boxdim);
}
}
private RectangleF GetBoxRect(int i)
{
return new RectangleF(TotalAreaRect.X + i * (BoxSize.Width + BoxMargin),
TotalAreaRect.Y + TotalAreaRect.Height / 2 - BoxSize.Height / 2,
BoxSize.Width, BoxSize.Height);
}
#endregion
#region Painting
GraphicsPath RoundedRect(RectangleF rect, int radius)
{
GraphicsPath ret = new GraphicsPath();
ret.StartFigure();
ret.AddArc(rect.X, rect.Y, 2 * radius, 2 * radius, 180, 90);
ret.AddLine(rect.X + radius, rect.Y, rect.X + rect.Width - radius, rect.Y);
ret.AddArc(rect.X + rect.Width - radius * 2, rect.Y, 2 * radius, 2 * radius, 270, 90);
ret.AddLine(rect.X + rect.Width, rect.Y + radius, rect.X + rect.Width, rect.Y + rect.Height - radius);
ret.AddArc(rect.X + rect.Width - 2*radius, rect.Y + rect.Height - 2 * radius, 2 * radius, 2 * radius, 0, 90);
ret.AddLine(rect.X + rect.Width - radius, rect.Y + rect.Height, rect.X + radius, rect.Y + rect.Height);
ret.AddArc(rect.X, rect.Y + rect.Height - 2*radius, 2 * radius, 2 * radius, 90, 90);
ret.CloseFigure();
return ret;
}
void DrawArrow(Graphics dc, Brush b, Pen p, float headsize, float y, float left, float right)
{
dc.DrawLine(p, new PointF(left, y), new PointF(right, y));
using (GraphicsPath head = new GraphicsPath())
{
head.StartFigure();
head.AddLine(new PointF(right, y), new PointF(right - headsize, y - headsize));
head.AddLine(new PointF(right - headsize, y - headsize), new PointF(right - headsize, y + headsize));
head.CloseFigure();
dc.FillPath(b, head);
}
}
private void PipelineFlowchart_Paint(object sender, PaintEventArgs e)
{
if (m_StageNames == null)
return;
var dc = e.Graphics;
dc.CompositingQuality = CompositingQuality.HighQuality;
dc.SmoothingMode = SmoothingMode.AntiAlias;
int radius = (int)Math.Min(MaxBoxCornerRadius, BoxSize.Height * BoxCornerRadiusFraction);
float arrowY = TotalAreaRect.Y + TotalAreaRect.Height / 2;
using (var pen = new Pen(Brushes.Black, BoxBorderWidth))
using (var selectedpen = new Pen(Brushes.Red, BoxBorderWidth))
{
for (int i = 0; i < NumGaps; i++)
{
if (!m_StageFlows[i] || !m_StageFlows[i + 1])
continue;
float right = TotalAreaRect.X + (i + 1) * (BoxSize.Width + BoxMargin);
float left = right - BoxMargin;
DrawArrow(dc, Brushes.Black, pen, ArrowHeadSize, arrowY, left, right);
}
for (int i = 0; i < NumItems; i++)
{
RectangleF boxrect = GetBoxRect(i);
var backBrush = Brushes.Gainsboro;
var textBrush = Brushes.Black;
var outlinePen = pen;
if (!IsStageEnabled(i))
{
backBrush = Brushes.DarkGray;
//textBrush = Brushes.Gainsboro;
}
if (i == m_HoverStage)
{
backBrush = Brushes.LightYellow;
}
if (i == SelectedStage)
{
//backBrush = Brushes.Coral;
outlinePen = selectedpen;
}
using (var boxpath = RoundedRect(boxrect, radius))
{
dc.FillPath(backBrush, boxpath);
dc.DrawPath(outlinePen, boxpath);
}
StringFormat format = new StringFormat();
format.LineAlignment = StringAlignment.Center;
format.Alignment = StringAlignment.Center;
var s = m_StageNames[i].Value;
var size = dc.MeasureString(s, Font);
// Decide whether we can draw the whole stage name or just the abbreviation.
// This can look a little awkward sometimes if it's sometimes abbreviated sometimes
// not. Maybe it should always abbreviate or not at all?
if (size.Width + BoxLabelMargin > (float)boxrect.Width)
{
s = s.Replace(" ", "\n");
size = dc.MeasureString(s, Font);
if (size.Width + BoxLabelMargin > (float)boxrect.Width ||
size.Height + BoxLabelMargin > (float)boxrect.Height)
{
s = m_StageNames[i].Key;
size = dc.MeasureString(s, Font);
}
}
dc.DrawString(s, Font, textBrush, new PointF(boxrect.X + boxrect.Width / 2, arrowY), format);
}
}
}
#endregion
#region Mouse Handling
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
int old = m_HoverStage;
m_HoverStage = -1;
for(int i=0; i < NumItems; i++)
{
if (GetBoxRect(i).Contains(e.Location))
{
m_HoverStage = i;
break;
}
}
if(m_HoverStage != old)
Invalidate();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
m_HoverStage = -1;
Invalidate();
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
for (int i = 0; i < NumItems; i++)
{
if (GetBoxRect(i).Contains(e.Location))
{
SelectedStage = i;
break;
}
}
}
#endregion
}
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+72
View File
@@ -0,0 +1,72 @@
namespace renderdocui.Controls
{
partial class RangeHistogram
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.whiteToolTip = new System.Windows.Forms.ToolTip(this.components);
this.blackToolTip = new System.Windows.Forms.ToolTip(this.components);
this.SuspendLayout();
//
// whiteToolTip
//
this.whiteToolTip.AutomaticDelay = 0;
this.whiteToolTip.UseAnimation = false;
this.whiteToolTip.UseFading = false;
//
// blackToolTip
//
this.blackToolTip.AutomaticDelay = 0;
this.blackToolTip.UseAnimation = false;
this.blackToolTip.UseFading = false;
//
// RangeHistogram
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.GradientActiveCaption;
this.DoubleBuffered = true;
this.Name = "RangeHistogram";
this.Size = new System.Drawing.Size(150, 40);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.RangeHistogram_Paint);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.RangeHistogram_MouseDown);
this.MouseEnter += new System.EventHandler(this.RangeHistogram_MouseEnter);
this.MouseLeave += new System.EventHandler(this.RangeHistogram_MouseLeave);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.RangeHistogram_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.RangeHistogram_MouseUp);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ToolTip whiteToolTip;
private System.Windows.Forms.ToolTip blackToolTip;
}
}
+515
View File
@@ -0,0 +1,515 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace renderdocui.Controls
{
[Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
public partial class RangeHistogram : UserControl
{
public RangeHistogram()
{
InitializeComponent();
}
#region Events
private static readonly object RangeUpdatedEvent = new object();
public event EventHandler<RangeHistogramEventArgs> RangeUpdated
{
add { Events.AddHandler(RangeUpdatedEvent, value); }
remove { Events.RemoveHandler(RangeUpdatedEvent, value); }
}
protected virtual void OnRangeUpdated(RangeHistogramEventArgs e)
{
EventHandler<RangeHistogramEventArgs> handler = (EventHandler<RangeHistogramEventArgs>)Events[RangeUpdatedEvent];
if (handler != null)
handler(this, e);
}
#endregion
#region Privates
private float m_RangeMax = 1.0f;
private float m_RangeMin = 0.0f;
private float m_WhitePoint = 1.0f;
private float m_BlackPoint = 0.0f;
private float m_MinRangeSize = 0.001f;
private int m_Margin = 4;
private int m_Border = 1;
private int m_MarkerSize = 6;
#endregion
#region Code Properties
private uint[] m_HistogramData = null;
private float m_HistogramMin = 0.0f;
private float m_HistogramMax = 1.0f;
// sets the range of data where the histogram data was calculated.
public void SetHistogramRange(float min, float max)
{
m_HistogramMin = min;
m_HistogramMax = max;
}
// sets the minimum and maximum as well as the black and white points
public void SetRange(float min, float max)
{
m_RangeMin = min;
m_RangeMax = Math.Max((min+float.Epsilon)*(1.0f+m_MinRangeSize), max);
m_BlackPoint = m_RangeMin;
m_WhitePoint = m_RangeMax;
Invalidate();
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
}
[Browsable(false)]
public uint[] HistogramData
{
get
{
return m_HistogramData;
}
set
{
m_HistogramData = value;
Invalidate();
}
}
// black point and white point are the currently selected black/white points, within the
// minimum and maximum points. (ie. not 0 or 1)
[Browsable(false)]
public float BlackPoint
{
get
{
return m_BlackPoint;
}
set
{
if (value <= m_RangeMin)
m_BlackPoint = m_RangeMin = value;
else
m_BlackPoint = value;
Invalidate();
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
}
}
[Browsable(false)]
public float WhitePoint
{
get
{
return m_WhitePoint;
}
set
{
if (value >= m_RangeMax)
m_WhitePoint = m_RangeMax = value;
else
m_WhitePoint = value;
Invalidate();
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
}
}
// range min/max are the current minimum and maximum values that can be set
// for the black and white points
[Browsable(false)]
public float RangeMin
{
get
{
return m_RangeMin;
}
set
{
m_RangeMin = Math.Min(value, m_RangeMax - MinRangeSize);
Invalidate();
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
}
}
[Browsable(false)]
public float RangeMax
{
get
{
return m_RangeMax;
}
set
{
m_RangeMax = Math.Max(value, m_RangeMin + MinRangeSize);
Invalidate();
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
}
}
#endregion
#region Designer Properties
[Description("The smallest possible range that can be selected"), Category("Behavior")]
[DefaultValue(typeof(float), "0.001")]
public float MinRangeSize
{
get { return m_MinRangeSize; }
set { m_MinRangeSize = Math.Max(0.000001f, value); }
}
[Description("The margin around the range display"), Category("Layout")]
[DefaultValue(typeof(int), "4")]
public int RangeMargin
{
get { return m_Margin; }
set { m_Margin = value; }
}
[Description("The pixel border around the range bar itself"), Category("Appearance")]
[DefaultValue(typeof(int), "1")]
public int Border
{
get { return m_Border; }
set { m_Border = value; }
}
[Description("The size in pixels of each marker"), Category("Appearance")]
[DefaultValue(typeof(int), "6")]
public int MarkerSize
{
get { return m_MarkerSize; }
set { m_MarkerSize = value; }
}
#endregion
#region Internal Properties
private int m_TotalSpace { get { return m_Margin + m_Border; } }
private int m_RegionWidth { get { return this.Width - m_TotalSpace * 2; } }
// these are internal only, they give [0, 1] from minimum to maximum of where the black and white points are
private float m_BlackDelta
{
get
{
return GetDelta(BlackPoint);
}
set
{
BlackPoint = Math.Min(WhitePoint - MinRangeSize, value * (RangeMax - RangeMin) + RangeMin);
}
}
private float m_WhiteDelta
{
get
{
return GetDelta(WhitePoint);
}
set
{
WhitePoint = Math.Max(BlackPoint + MinRangeSize, value * (RangeMax - RangeMin) + RangeMin);
}
}
private float GetDelta(float val)
{
return (val - RangeMin) / (RangeMax - RangeMin);
}
#endregion
#region Tooltips
private void ShowTooltips()
{
blackToolTip.Show(BlackPoint.ToString("F4"), this,
this.ClientRectangle.Left + (int)(this.ClientRectangle.Width * m_BlackDelta), this.ClientRectangle.Bottom);
whiteToolTip.Show(WhitePoint.ToString("F4"), this,
this.ClientRectangle.Left + (int)(this.ClientRectangle.Width * m_WhiteDelta), this.ClientRectangle.Top - 15);
}
#endregion
#region Mouse Handlers
private Point m_mousePrev = new Point(-1, -1);
private enum DraggingMode
{
NONE,
WHITE,
BLACK,
}
private DraggingMode m_DragMode;
// This handler tries to figure out which handle (white or black) you were trying to
// grab when you clicked.
private void RangeHistogram_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button != MouseButtons.Left)
return;
Rectangle rect = this.ClientRectangle;
rect.Inflate(-m_TotalSpace, -m_TotalSpace);
int whiteX = (int)(m_WhiteDelta * rect.Width);
int blackX = (int)(m_BlackDelta * rect.Width);
var whiteVec = new PointF(whiteX - e.Location.X, ClientRectangle.Height - e.Location.Y);
var blackVec = new PointF(blackX-e.Location.X, e.Location.Y);
float whitedist = (float)Math.Sqrt(whiteVec.X * whiteVec.X + whiteVec.Y * whiteVec.Y);
float blackdist = (float)Math.Sqrt(blackVec.X * blackVec.X + blackVec.Y * blackVec.Y);
System.Diagnostics.Trace.WriteLine(string.Format("white {0} black {1}", whitedist, blackdist));
if (whitedist < blackdist && whitedist < 18.0f)
m_DragMode = DraggingMode.WHITE;
else if (blackdist < whitedist && blackdist < 18.0f)
m_DragMode = DraggingMode.BLACK;
else if (e.Location.X > whiteX)
m_DragMode = DraggingMode.WHITE;
else if (e.Location.X < blackX)
m_DragMode = DraggingMode.BLACK;
if (m_DragMode == DraggingMode.WHITE)
{
float newWhite = (float)(e.Location.X - m_TotalSpace) / (float)m_RegionWidth;
m_WhiteDelta = Math.Max(m_BlackDelta + m_MinRangeSize, Math.Min(1.0f, newWhite));
}
else if (m_DragMode == DraggingMode.BLACK)
{
float newBlack = (float)(e.Location.X - m_TotalSpace) / (float)m_RegionWidth;
m_BlackDelta = Math.Min(m_WhiteDelta - m_MinRangeSize, Math.Max(0.0f, newBlack));
}
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
if (m_DragMode != DraggingMode.NONE)
{
this.Invalidate();
this.Update();
}
m_mousePrev.X = e.X;
m_mousePrev.Y = e.Y;
}
private void RangeHistogram_MouseUp(object sender, MouseEventArgs e)
{
whiteToolTip.Hide(this);
blackToolTip.Hide(this);
m_DragMode = DraggingMode.NONE;
m_mousePrev.X = m_mousePrev.Y = -1;
}
private void RangeHistogram_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && (e.X != m_mousePrev.X || e.Y != m_mousePrev.Y))
{
if (m_DragMode == DraggingMode.WHITE)
{
float newWhite = (float)(e.Location.X - m_TotalSpace) / (float)m_RegionWidth;
m_WhiteDelta = Math.Max(m_BlackDelta + m_MinRangeSize, Math.Min(1.0f, newWhite));
}
else if (m_DragMode == DraggingMode.BLACK)
{
float newBlack = (float)(e.Location.X - m_TotalSpace) / (float)m_RegionWidth;
m_BlackDelta = Math.Min(m_WhiteDelta - m_MinRangeSize, Math.Max(0.0f, newBlack));
}
OnRangeUpdated(new RangeHistogramEventArgs(BlackPoint, WhitePoint));
if (m_DragMode != DraggingMode.NONE)
{
this.Invalidate();
this.Update();
}
m_mousePrev.X = e.X;
m_mousePrev.Y = e.Y;
ShowTooltips();
}
}
private void RangeHistogram_MouseLeave(object sender, EventArgs e)
{
whiteToolTip.Hide(this);
blackToolTip.Hide(this);
}
private void RangeHistogram_MouseEnter(object sender, EventArgs e)
{
ShowTooltips();
}
#endregion
#region Other Handlers
private void RangeHistogram_Paint(object sender, PaintEventArgs e)
{
Rectangle rect = this.ClientRectangle;
e.Graphics.FillRectangle(SystemBrushes.Control, rect);
rect.Inflate(-m_Margin, -m_Margin);
e.Graphics.FillRectangle(Brushes.Black, rect);
rect.Inflate(-m_Border, -m_Border);
e.Graphics.FillRectangle(Brushes.DarkGray, rect);
int whiteX = (int)(m_WhiteDelta * rect.Width);
int blackX = (int)(m_BlackDelta * rect.Width);
Rectangle blackPoint = new Rectangle(rect.Left, rect.Top, blackX, rect.Height);
Rectangle whitePoint = new Rectangle(rect.Left + whiteX, rect.Top, rect.Width - whiteX, rect.Height);
e.Graphics.FillRectangle(Brushes.White, whitePoint);
e.Graphics.FillRectangle(Brushes.Black, blackPoint);
if (HistogramData != null)
{
float minx = GetDelta(m_HistogramMin);
float maxx = GetDelta(m_HistogramMax);
UInt32 maxval = UInt32.MinValue;
for (int i = 0; i < HistogramData.Length; i++)
{
float x = (float)i / (float)HistogramData.Length;
float xdelta = minx + x * (maxx - minx);
if (xdelta >= 0.0f && xdelta <= 1.0f)
{
maxval = Math.Max(maxval, HistogramData[i]);
}
}
for (int i = 0; i < HistogramData.Length; i++)
{
float x = (float)i / (float)HistogramData.Length;
float y = (float)HistogramData[i] / (float)maxval;
float xdelta = minx + x * (maxx - minx);
if (xdelta >= 0.0f && xdelta <= 1.0f)
{
float segwidth = Math.Max(rect.Width * (maxx - minx) / (float)HistogramData.Length, 1);
RectangleF barRect = new RectangleF(new PointF(rect.Left + rect.Width * (minx + x * (maxx - minx)), rect.Bottom - rect.Height * y),
new SizeF(segwidth, rect.Height * y));
e.Graphics.FillRectangle(Brushes.Green, barRect);
}
}
}
Point[] blackTriangle = { new Point(blackPoint.Right, m_MarkerSize*2),
new Point(blackPoint.Right+m_MarkerSize, 0),
new Point(blackPoint.Right-m_MarkerSize, 0) };
e.Graphics.FillPolygon(Brushes.DarkGray, blackTriangle);
Point[] whiteTriangle = { new Point(whitePoint.Left, whitePoint.Bottom-m_MarkerSize*2+m_Margin),
new Point(whitePoint.Left+m_MarkerSize, whitePoint.Bottom+m_Margin),
new Point(whitePoint.Left-m_MarkerSize, whitePoint.Bottom+m_Margin) };
e.Graphics.FillPolygon(Brushes.DarkGray, whiteTriangle);
blackTriangle[0].Y -= 2;
blackTriangle[1].Y += 1;
blackTriangle[2].Y += 1;
blackTriangle[1].X -= 2;
blackTriangle[2].X += 2;
whiteTriangle[0].Y += 2;
whiteTriangle[1].Y -= 1;
whiteTriangle[2].Y -= 1;
whiteTriangle[1].X -= 2;
whiteTriangle[2].X += 2;
e.Graphics.FillPolygon(Brushes.Black, blackTriangle);
e.Graphics.FillPolygon(Brushes.White, whiteTriangle);
}
#endregion
}
public class RangeHistogramEventArgs : EventArgs
{
private float m_black, m_white;
public RangeHistogramEventArgs(float black, float white)
{
m_black = black;
m_white = white;
}
public float BlackPoint
{
get { return m_black; }
}
public float WhitePoint
{
get { return m_white; }
}
}
}
+126
View File
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="whiteToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="blackToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>132, 17</value>
</metadata>
</root>
+131
View File
@@ -0,0 +1,131 @@
namespace renderdocui.Controls
{
partial class ResourcePreview
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.slotLabel = new System.Windows.Forms.Label();
this.descriptionLabel = new System.Windows.Forms.Label();
this.thumbnail = new renderdocui.Controls.NoScrollPanel();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.BackColor = System.Drawing.Color.Transparent;
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.slotLabel, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.descriptionLabel, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.thumbnail, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(110, 86);
this.tableLayoutPanel1.TabIndex = 0;
//
// slotLabel
//
this.slotLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.slotLabel.AutoSize = true;
this.slotLabel.BackColor = System.Drawing.SystemColors.InactiveCaption;
this.slotLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.slotLabel.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
this.slotLabel.Location = new System.Drawing.Point(0, 60);
this.slotLabel.Margin = new System.Windows.Forms.Padding(0);
this.slotLabel.Name = "slotLabel";
this.slotLabel.Size = new System.Drawing.Size(19, 26);
this.slotLabel.TabIndex = 1;
this.slotLabel.Text = "1";
this.slotLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.slotLabel.MouseClick += new System.Windows.Forms.MouseEventHandler(this.child_MouseClick);
this.slotLabel.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.child_MouseDoubleClick);
//
// descriptionLabel
//
this.descriptionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.descriptionLabel.AutoEllipsis = true;
this.descriptionLabel.BackColor = System.Drawing.SystemColors.InactiveCaption;
this.descriptionLabel.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
this.descriptionLabel.Location = new System.Drawing.Point(19, 60);
this.descriptionLabel.Margin = new System.Windows.Forms.Padding(0);
this.descriptionLabel.Name = "descriptionLabel";
this.descriptionLabel.Size = new System.Drawing.Size(91, 26);
this.descriptionLabel.TabIndex = 2;
this.descriptionLabel.Text = "Texture2D 117";
this.descriptionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.descriptionLabel.MouseClick += new System.Windows.Forms.MouseEventHandler(this.child_MouseClick);
this.descriptionLabel.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.child_MouseDoubleClick);
//
// thumbnail
//
this.thumbnail.BackColor = System.Drawing.Color.Chartreuse;
this.tableLayoutPanel1.SetColumnSpan(this.thumbnail, 2);
this.thumbnail.Dock = System.Windows.Forms.DockStyle.Fill;
this.thumbnail.Location = new System.Drawing.Point(0, 0);
this.thumbnail.Margin = new System.Windows.Forms.Padding(0);
this.thumbnail.Name = "thumbnail";
this.thumbnail.Size = new System.Drawing.Size(110, 60);
this.thumbnail.TabIndex = 0;
this.thumbnail.Paint += new System.Windows.Forms.PaintEventHandler(this.thumbnail_Paint);
this.thumbnail.MouseClick += new System.Windows.Forms.MouseEventHandler(this.child_MouseClick);
this.thumbnail.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.child_MouseDoubleClick);
//
// ResourcePreview
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Black;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.tableLayoutPanel1);
this.Margin = new System.Windows.Forms.Padding(5, 0, 0, 0);
this.Name = "ResourcePreview";
this.Padding = new System.Windows.Forms.Padding(3);
this.Size = new System.Drawing.Size(116, 92);
this.Load += new System.EventHandler(this.ResourcePreview_Load);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private Controls.NoScrollPanel thumbnail;
private System.Windows.Forms.Label slotLabel;
private System.Windows.Forms.Label descriptionLabel;
}
}
+173
View File
@@ -0,0 +1,173 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using renderdocui.Code;
using renderdoc;
namespace renderdocui.Controls
{
[Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
public partial class ResourcePreview : UserControl
{
private string m_Name;
private UInt32 m_Width, m_Height, m_Depth, m_NumMips;
private Core m_Core;
private ReplayOutput m_Output;
private IntPtr m_Handle;
public ResourcePreview(Core core, ReplayOutput output)
{
InitializeComponent();
m_Name = "Unbound";
m_Width = 1;
m_Height = 1;
m_Depth = 1;
m_NumMips = 0;
m_Unbound = true;
thumbnail.Painting = false;
m_Unbound = true;
slotLabel.Text = "0";
this.DoubleBuffered = true;
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
m_Handle = thumbnail.Handle;
m_Core = core;
m_Output = output;
Selected = false;
}
public void Init()
{
descriptionLabel.Text = "Unbound";
m_Unbound = true;
thumbnail.Painting = true;
}
public void Init(string Name, UInt32 Width, UInt32 Height, UInt32 Depth, UInt32 NumMips)
{
m_Name = Name;
m_Width = Width;
m_Height = Height;
m_Depth = Depth;
m_NumMips = NumMips;
m_Unbound = false;
thumbnail.Painting = true;
//descriptionLabel.Text = m_Width + "x" + m_Height + "x" + m_Depth + (m_NumMips > 0 ? "[" + m_NumMips + "]\n" : "\n") + m_Name;
descriptionLabel.Text = m_Name;
}
public string SlotName
{
get { return slotLabel.Text; }
set { slotLabel.Text = value; }
}
private bool m_Unbound = true;
public bool Unbound
{
get
{
return m_Unbound;
}
}
private bool m_Selected;
public bool Selected
{
get { return m_Selected; }
set
{
m_Selected = value;
if (value)
{
BackColor = Color.Red;
}
else
{
BackColor = Color.Black;
}
}
}
public IntPtr ThumbnailHandle
{
get { return m_Handle; }
}
private void ResourcePreview_Load(object sender, EventArgs e)
{
Init(m_Name, m_Width, m_Height, m_Depth, m_NumMips);
}
public void Clear()
{
thumbnail.Invalidate();
}
private void thumbnail_Paint(object sender, PaintEventArgs e)
{
if (m_Output == null || m_Core.Renderer == null)
{
e.Graphics.Clear(Color.Black);
return;
}
if (m_Output != null)
m_Core.Renderer.Invoke((ReplayRenderer r) => { m_Output.Display(); });
}
public void SetSize(Size s)
{
MinimumSize = MaximumSize = s;
Size = s;
}
private void child_MouseClick(object sender, MouseEventArgs e)
{
OnMouseClick(e);
}
private void child_MouseDoubleClick(object sender, MouseEventArgs e)
{
OnMouseDoubleClick(e);
}
}
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+50
View File
@@ -0,0 +1,50 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using renderdocui.Code;
namespace renderdocui.Controls
{
// thanks to Hans Passant - http://stackoverflow.com/a/6954785
public class TablessControl : TabControl
{
protected override void WndProc(ref Message m)
{
// Hide tabs by trapping the TCM_ADJUSTRECT message
if (m.Msg == (int)Win32PInvoke.Win32Message.TCM_ADJUSTRECT && !DesignMode)
m.Result = (IntPtr)1;
else
base.WndProc(ref m);
}
}
}
+233
View File
@@ -0,0 +1,233 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using renderdoc;
using renderdocui.Code;
namespace renderdocui.Controls
{
public partial class TextureListBox : ListBox
{
private List<FetchTexture> m_FilteredTextures = new List<FetchTexture>();
private static readonly object GoIconClickEvent = new object();
public event EventHandler<GoIconClickEventArgs> GoIconClick
{
add { Events.AddHandler(GoIconClickEvent, value); }
remove { Events.RemoveHandler(GoIconClickEvent, value); }
}
protected virtual void OnGoIconClick(GoIconClickEventArgs e)
{
EventHandler<GoIconClickEventArgs> handler = (EventHandler<GoIconClickEventArgs>)Events[GoIconClickEvent];
if (handler != null)
handler(this, e);
}
public Core m_Core = null;
public TextureListBox()
{
DrawMode = DrawMode.OwnerDrawFixed;
DrawItem += new DrawItemEventHandler(TextureListBox_DrawItem);
this.DoubleBuffered = true;
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
Items.Clear();
Items.Add("foobar");
}
void TextureListBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (Items.Count > 0 && e.Index >= 0)
{
Rectangle stringBounds = e.Bounds;
var image = global::renderdocui.Properties.Resources.action;
if (m_HoverHighlight == e.Index)
{
image = global::renderdocui.Properties.Resources.action_hover;
e.Graphics.DrawRectangle(Pens.LightGray, e.Bounds);
}
e.Graphics.DrawImage(image, e.Bounds.Width - 16, e.Bounds.Y, 16, 16);
stringBounds.Width -= 18;
var sf = new StringFormat(StringFormat.GenericDefault);
sf.Trimming = StringTrimming.EllipsisCharacter;
sf.FormatFlags |= StringFormatFlags.NoWrap;
using (Brush b = new SolidBrush(ForeColor))
{
e.Graphics.DrawString(Items[e.Index].ToString(),
Font, b, stringBounds, sf);
}
}
}
private int m_HoverHighlight = -1;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (Items.Count > 0 && m_HoverHighlight >= 0)
{
var rect = GetItemRectangle(m_HoverHighlight);
if (rect.Contains(e.Location))
{
OnGoIconClick(new GoIconClickEventArgs(m_FilteredTextures[m_HoverHighlight].ID));
}
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
bool curhover = m_HoverHighlight != -1;
bool hover = false;
for(int i=0; i < Items.Count; i++)
{
var rect = GetItemRectangle(i);
bool highlight = rect.Contains(e.Location);
hover |= highlight;
if (m_HoverHighlight != i && highlight)
{
m_HoverHighlight = i;
Invalidate();
}
}
if (hover)
{
Cursor = Cursors.Hand;
}
else
{
Cursor = Cursors.Arrow;
m_HoverHighlight = -1;
}
if (hover != curhover)
Invalidate();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
Cursor = Cursors.Arrow;
if (Items.Count > 0 && m_HoverHighlight >= 0)
Invalidate(GetItemRectangle(m_HoverHighlight));
m_HoverHighlight = -1;
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
FillTextureList("", true, true);
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
for (int i = 0; i < Items.Count; i++)
{
TextureListBox_DrawItem(this, new DrawItemEventArgs(e.Graphics, Font, GetItemRectangle(i), i, DrawItemState.Default));
}
}
public void FillTextureList(string filter, bool RTs, bool Texs)
{
m_FilteredTextures.Clear();
Items.Clear();
if (m_Core == null ||!m_Core.LogLoaded)
{
return;
}
for (int i = 0; i < m_Core.CurTextures.Length; i++)
{
bool include = false;
include |= (RTs && ((m_Core.CurTextures[i].creationFlags & TextureCreationFlags.RTV) > 0 ||
(m_Core.CurTextures[i].creationFlags & TextureCreationFlags.DSV) > 0));
include |= (Texs && (m_Core.CurTextures[i].creationFlags & TextureCreationFlags.RTV) == 0 &&
(m_Core.CurTextures[i].creationFlags & TextureCreationFlags.DSV) == 0);
include |= (filter != "" && (m_Core.CurTextures[i].name.ToLowerInvariant().Contains(filter.ToLowerInvariant())));
include |= (!RTs && !Texs && filter == "");
if (include)
{
m_FilteredTextures.Add(m_Core.CurTextures[i]);
Items.Add(m_Core.CurTextures[i].name);
}
}
}
}
public class GoIconClickEventArgs : EventArgs
{
private ResourceId id;
public GoIconClickEventArgs(ResourceId i)
{
id = i;
}
public ResourceId ID
{
get { return id; }
}
}
}
+106
View File
@@ -0,0 +1,106 @@
namespace renderdocui.Controls
{
partial class ThumbnailStrip
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
this.panel = new System.Windows.Forms.Panel();
this.hscroll = new System.Windows.Forms.HScrollBar();
this.vscroll = new System.Windows.Forms.VScrollBar();
tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
tableLayoutPanel1.ColumnCount = 2;
tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
tableLayoutPanel1.Controls.Add(this.panel, 0, 0);
tableLayoutPanel1.Controls.Add(this.hscroll, 0, 1);
tableLayoutPanel1.Controls.Add(this.vscroll, 1, 0);
tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
tableLayoutPanel1.Name = "tableLayoutPanel1";
tableLayoutPanel1.RowCount = 2;
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel1.Size = new System.Drawing.Size(791, 246);
tableLayoutPanel1.TabIndex = 1;
//
// panel
//
this.panel.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel.Location = new System.Drawing.Point(0, 0);
this.panel.Margin = new System.Windows.Forms.Padding(0);
this.panel.Name = "panel";
this.panel.Size = new System.Drawing.Size(775, 230);
this.panel.TabIndex = 0;
this.panel.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.panel_ControlAddRemove);
this.panel.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.panel_ControlAddRemove);
this.panel.MouseClick += new System.Windows.Forms.MouseEventHandler(this.panel_MouseClick);
//
// hscroll
//
this.hscroll.Dock = System.Windows.Forms.DockStyle.Bottom;
this.hscroll.Location = new System.Drawing.Point(0, 230);
this.hscroll.Name = "hscroll";
this.hscroll.Size = new System.Drawing.Size(775, 16);
this.hscroll.TabIndex = 1;
this.hscroll.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscroll_Scroll);
//
// vscroll
//
this.vscroll.Dock = System.Windows.Forms.DockStyle.Right;
this.vscroll.Location = new System.Drawing.Point(775, 0);
this.vscroll.Name = "vscroll";
this.vscroll.Size = new System.Drawing.Size(16, 230);
this.vscroll.TabIndex = 2;
this.vscroll.Scroll += new System.Windows.Forms.ScrollEventHandler(this.vscroll_Scroll);
//
// ThumbnailStrip
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(tableLayoutPanel1);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "ThumbnailStrip";
this.Size = new System.Drawing.Size(791, 246);
this.Layout += new System.Windows.Forms.LayoutEventHandler(this.ThumbnailStrip_Layout);
tableLayoutPanel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel;
private System.Windows.Forms.HScrollBar hscroll;
private System.Windows.Forms.VScrollBar vscroll;
}
}
+228
View File
@@ -0,0 +1,228 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace renderdocui.Controls
{
public partial class ThumbnailStrip : UserControl
{
public ThumbnailStrip()
{
InitializeComponent();
MouseWheel += new MouseEventHandler(ThumbnailStrip_MouseWheel);
}
void ThumbnailStrip_MouseWheel(object sender, MouseEventArgs e)
{
const int WHEEL_DELTA = 120;
int movement = e.Delta / WHEEL_DELTA;
if (vscroll.Visible)
vscroll.Value = Code.Helpers.Clamp(vscroll.Value - movement * vscroll.SmallChange, vscroll.Minimum, vscroll.Maximum - vscroll.LargeChange);
if (hscroll.Visible)
hscroll.Value = Code.Helpers.Clamp(hscroll.Value - movement * hscroll.SmallChange, hscroll.Minimum, hscroll.Maximum - hscroll.LargeChange);
RefreshLayout();
}
private List<ResourcePreview> m_Thumbnails = new List<ResourcePreview>();
public ResourcePreview[] Thumbnails { get { return m_Thumbnails.ToArray(); } }
public void AddThumbnail(ResourcePreview r)
{
panel.Controls.Add(r);
m_Thumbnails.Add(r);
}
public void ClearThumbnails()
{
m_Thumbnails.Clear();
panel.Controls.Clear();
}
public void RefreshLayout()
{
Rectangle avail = ClientRectangle;
avail.Inflate(new Size(-6, -6));
int numVisible = 0;
foreach (ResourcePreview c in Thumbnails)
if (c.Visible) numVisible++;
// depending on overall aspect ratio, we either lay out the strip horizontally or
// vertically. This tries to account for whether the strip is docked along one side
// or another of the texture viewer
if (avail.Width > avail.Height)
{
avail.Width += 6; // controls implicitly have a 6 margin on the right
int aspectWidth = (int)(avail.Height * 1.3f);
vscroll.Visible = false;
int noscrollWidth = numVisible * (aspectWidth + 6);
if (noscrollWidth <= avail.Width)
{
hscroll.Visible = false;
int x = avail.X;
foreach (ResourcePreview c in Thumbnails)
{
if (c.Visible)
{
c.Location = new Point(x, avail.Y);
c.SetSize(new Size(aspectWidth, avail.Height));
x += aspectWidth + 6;
}
}
}
else
{
hscroll.Visible = true;
avail.Height = avail.Height - SystemInformation.HorizontalScrollBarHeight;
aspectWidth = (int)(avail.Height * 1.3f);
int totalWidth = numVisible * (aspectWidth + 6);
hscroll.Enabled = totalWidth > avail.Width;
if (hscroll.Enabled)
{
hscroll.Maximum = totalWidth - avail.Width;
hscroll.LargeChange = Code.Helpers.Clamp(avail.Height, 1, hscroll.Maximum/2);
hscroll.SmallChange = Math.Max(1, hscroll.LargeChange / 2);
}
int x = avail.X - (int)(hscroll.Maximum*(float)hscroll.Value/(float)(hscroll.Maximum-hscroll.LargeChange));
foreach (ResourcePreview c in Thumbnails)
{
if (c.Visible)
{
c.Location = new Point(x, avail.Y);
c.SetSize(new Size(aspectWidth, avail.Height));
x += aspectWidth + 6;
}
}
}
}
else
{
avail.Height += 6; // controls implicitly have a 6 margin on the bottom
int aspectHeight = (int)(avail.Width / 1.3f);
hscroll.Visible = false;
int noscrollHeight = numVisible * (aspectHeight + 6);
if (noscrollHeight <= avail.Height)
{
vscroll.Visible = false;
int y = avail.Y;
foreach (ResourcePreview c in Thumbnails)
{
if (c.Visible)
{
c.Location = new Point(avail.X, y);
c.SetSize(new Size(avail.Width, aspectHeight));
y += aspectHeight + 6;
}
}
}
else
{
vscroll.Visible = true;
avail.Width = avail.Width - SystemInformation.VerticalScrollBarWidth;
aspectHeight = (int)(avail.Width / 1.3f);
int totalHeight = numVisible * (aspectHeight + 6);
vscroll.Enabled = totalHeight > avail.Height;
if (vscroll.Enabled)
{
vscroll.Maximum = totalHeight - avail.Height;
vscroll.LargeChange = Code.Helpers.Clamp(avail.Width, 1, vscroll.Maximum / 2);
vscroll.SmallChange = Math.Max(1, vscroll.LargeChange / 2);
}
int y = avail.Y - (int)(vscroll.Maximum * (float)vscroll.Value / (float)(vscroll.Maximum - vscroll.LargeChange));
foreach (ResourcePreview c in Thumbnails)
{
if (c.Visible)
{
c.Location = new Point(avail.X, y);
c.SetSize(new Size(avail.Width, aspectHeight));
y += aspectHeight + 6;
}
}
}
}
}
private void ThumbnailStrip_Layout(object sender, LayoutEventArgs e)
{
RefreshLayout();
}
private void panel_ControlAddRemove(object sender, ControlEventArgs e)
{
RefreshLayout();
}
private void panel_MouseClick(object sender, MouseEventArgs e)
{
OnMouseClick(e);
}
private void hscroll_Scroll(object sender, ScrollEventArgs e)
{
RefreshLayout();
}
private void vscroll_Scroll(object sender, ScrollEventArgs e)
{
RefreshLayout();
}
}
}
+123
View File
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="tableLayoutPanel1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>
@@ -0,0 +1,109 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
using System;
using System.Drawing;
using System.Windows.Forms;
namespace renderdocui.Controls
{
// toolstrip textbox that resizes to fit
// http://msdn.microsoft.com/en-us/library/ms404304(v=vs.90).aspx
public class ToolStripSpringTextBox : ToolStripTextBox
{
public override Size GetPreferredSize(Size constrainingSize)
{
// Use the default size if the text box is on the overflow menu
// or is on a vertical ToolStrip.
if (IsOnOverflow || Owner.Orientation == Orientation.Vertical)
{
return DefaultSize;
}
// Declare a variable to store the total available width as
// it is calculated, starting with the display width of the
// owning ToolStrip.
Int32 width = Owner.DisplayRectangle.Width;
// Subtract the width of the overflow button if it is displayed.
if (Owner.OverflowButton.Visible)
{
width = width - Owner.OverflowButton.Width -
Owner.OverflowButton.Margin.Horizontal;
}
// Declare a variable to maintain a count of ToolStripSpringTextBox
// items currently displayed in the owning ToolStrip.
Int32 springBoxCount = 0;
foreach (ToolStripItem item in Owner.Items)
{
// Ignore items on the overflow menu.
if (item.IsOnOverflow) continue;
if (item is ToolStripSpringTextBox)
{
// For ToolStripSpringTextBox items, increment the count and
// subtract the margin width from the total available width.
springBoxCount++;
width -= item.Margin.Horizontal;
}
else
{
// For all other items, subtract the full width from the total
// available width.
width = width - item.Width - item.Margin.Horizontal;
}
}
// If there are multiple ToolStripSpringTextBox items in the owning
// ToolStrip, divide the total available width between them.
if (springBoxCount > 1) width /= springBoxCount;
// If the available width is less than the default width, use the
// default width, forcing one or more items onto the overflow menu.
if (width < DefaultSize.Width) width = DefaultSize.Width;
// Retrieve the preferred size from the base class, but change the
// width to the calculated width.
Size size = base.GetPreferredSize(constrainingSize);
size.Width = width;
return size;
}
protected override bool ProcessCmdKey(ref Message m, Keys keyData)
{
if (keyData == Keys.Escape)
{
OnKeyPress(new KeyPressEventArgs('\0'));
return true;
}
else
{
return false;
}
}
}
}
@@ -0,0 +1,251 @@
<html>
<head>
<title>The Code Project Open License (CPOL)</title>
<Style>
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H1,H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H1 { font-size: 14pt;color:black }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
.SpacedList li { padding: 5px 0px 5px 0px;}
</style>
</head>
<body bgcolor="#FFFFFF" color=#000000>
<h1>The Code Project Open License (CPOL) 1.02</h1>
<br />
<center>
<div style="text-align: left; border: 2px solid #000000; width: 660; background-color: #FFFFD9; padding: 20px;">
<h2>Preamble</h2>
<p>
This License governs Your use of the Work. This License is intended to allow developers
to use the Source Code and Executable Files provided as part of the Work in any
application in any form.
</p>
<p>
The main points subject to the terms of the License are:</p>
<ul>
<li>Source Code and Executable Files can be used in commercial applications;</li>
<li>Source Code and Executable Files can be redistributed; and</li>
<li>Source Code can be modified to create derivative works.</li>
<li>No claim of suitability, guarantee, or any warranty whatsoever is provided. The software is
provided "as-is".</li>
<li>The Article accompanying the Work may not be distributed or republished without the
Author's consent</li>
</ul>
<p>
This License is entered between You, the individual or other entity reading or otherwise
making use of the Work licensed pursuant to this License and the individual or other
entity which offers the Work under the terms of this License ("Author").</p>
<h2>License</h2>
<p>
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CODE PROJECT OPEN
LICENSE ("LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE
LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT
LAW IS PROHIBITED.</p>
<p>
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HEREIN, YOU ACCEPT AND AGREE TO BE
BOUND BY THE TERMS OF THIS LICENSE. THE AUTHOR GRANTS YOU THE RIGHTS CONTAINED HEREIN
IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. IF YOU DO NOT
AGREE TO ACCEPT AND BE BOUND BY THE TERMS OF THIS LICENSE, YOU CANNOT MAKE ANY
USE OF THE WORK.</p>
<ol class="SpacedList">
<li><strong>Definitions.</strong>
<ol class="SpacedList" style="list-style-type: lower-alpha;">
<li><strong>"Articles"</strong> means, collectively, all articles written by Author
which describes how the Source Code and Executable Files for the Work may be used
by a user.</li>
<li><b>"Author"</b> means the individual or entity that offers the Work under the terms
of this License.<strong></strong></li>
<li><strong>"Derivative Work"</strong> means a work based upon the Work or upon the
Work and other pre-existing works.</li>
<li><b>"Executable Files"</b> refer to the executables, binary files, configuration
and any required data files included in the Work.</li>
<li>"<b>Publisher</b>" means the provider of the website, magazine, CD-ROM, DVD or other
medium from or by which the Work is obtained by You.</li>
<li><b>"Source Code"</b> refers to the collection of source code and configuration files
used to create the Executable Files.</li>
<li><b>"Standard Version"</b> refers to such a Work if it has not been modified, or
has been modified in accordance with the consent of the Author, such consent being
in the full discretion of the Author. </li>
<li><b>"Work"</b> refers to the collection of files distributed by the Publisher, including
the Source Code, Executable Files, binaries, data files, documentation, whitepapers
and the Articles. </li>
<li><b>"You"</b> is you, an individual or entity wishing to use the Work and exercise
your rights under this License.
</li>
</ol>
</li>
<li><strong>Fair Use/Fair Use Rights.</strong> Nothing in this License is intended to
reduce, limit, or restrict any rights arising from fair use, fair dealing, first
sale or other limitations on the exclusive rights of the copyright owner under copyright
law or other applicable laws.
</li>
<li><strong>License Grant.</strong> Subject to the terms and conditions of this License,
the Author hereby grants You a worldwide, royalty-free, non-exclusive, perpetual
(for the duration of the applicable copyright) license to exercise the rights in
the Work as stated below:
<ol class="SpacedList" style="list-style-type: lower-alpha;">
<li>You may use the standard version of the Source Code or Executable Files in Your
own applications. </li>
<li>You may apply bug fixes, portability fixes and other modifications obtained from
the Public Domain or from the Author. A Work modified in such a way shall still
be considered the standard version and will be subject to this License.</li>
<li>You may otherwise modify Your copy of this Work (excluding the Articles) in any
way to create a Derivative Work, provided that You insert a prominent notice in
each changed file stating how, when and where You changed that file.</li>
<li>You may distribute the standard version of the Executable Files and Source Code
or Derivative Work in aggregate with other (possibly commercial) programs as part
of a larger (possibly commercial) software distribution. </li>
<li>The Articles discussing the Work published in any form by the author may not be
distributed or republished without the Author&#39;s consent. The author retains
copyright to any such Articles. You may use the Executable Files and Source Code
pursuant to this License but you may not repost or republish or otherwise distribute
or make available the Articles, without the prior written consent of the Author.</li>
</ol>
Any subroutines or modules supplied by You and linked into the Source Code or Executable
Files of this Work shall not be considered part of this Work and will not be subject
to the terms of this License.
</li>
<li><strong>Patent License.</strong> Subject to the terms and conditions of this License,
each Author hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have made, use, import,
and otherwise transfer the Work.</li>
<li><strong>Restrictions.</strong> The license granted in Section 3 above is expressly
made subject to and limited by the following restrictions:
<ol class="SpacedList" style="list-style-type: lower-alpha;">
<li>You agree not to remove any of the original copyright, patent, trademark, and
attribution notices and associated disclaimers that may appear in the Source Code
or Executable Files. </li>
<li>You agree not to advertise or in any way imply that this Work is a product of Your
own. </li>
<li>The name of the Author may not be used to endorse or promote products derived from
the Work without the prior written consent of the Author.</li>
<li>You agree not to sell, lease, or rent any part of the Work. This does not restrict
you from including the Work or any part of the Work inside a larger software
distribution that itself is being sold. The Work by itself, though, cannot be sold,
leased or rented.</li>
<li>You may distribute the Executable Files and Source Code only under the terms of
this License, and You must include a copy of, or the Uniform Resource Identifier
for, this License with every copy of the Executable Files or Source Code You distribute
and ensure that anyone receiving such Executable Files and Source Code agrees that
the terms of this License apply to such Executable Files and/or Source Code. You
may not offer or impose any terms on the Work that alter or restrict the terms of
this License or the recipients&#39; exercise of the rights granted hereunder. You
may not sublicense the Work. You must keep intact all notices that refer to this
License and to the disclaimer of warranties. You may not distribute the Executable
Files or Source Code with any technological measures that control access or use
of the Work in a manner inconsistent with the terms of this License. </li>
<li>You agree not to use the Work for illegal, immoral or improper purposes, or on pages
containing illegal, immoral or improper material. The Work is subject to applicable
export laws. You agree to comply with all such laws and regulations that may apply
to the Work after Your receipt of the Work.
</li>
</ol>
</li>
<li><strong>Representations, Warranties and Disclaimer.</strong> THIS WORK IS PROVIDED
"AS IS", "WHERE IS" AND "AS AVAILABLE", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES
OR CONDITIONS OR GUARANTEES. YOU, THE USER, ASSUME ALL RISK IN ITS USE, INCLUDING
COPYRIGHT INFRINGEMENT, PATENT INFRINGEMENT, SUITABILITY, ETC. AUTHOR EXPRESSLY
DISCLAIMS ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES OR CONDITIONS, INCLUDING
WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY
OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT,
OR THAT THE WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, BUG-FREE OR FREE OF
VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE WORK OR DERIVATIVE
WORKS.
</li>
<li><b>Indemnity. </b>You agree to defend, indemnify and hold harmless the Author and
the Publisher from and against any claims, suits, losses, damages, liabilities,
costs, and expenses (including reasonable legal or attorneys fees) resulting from
or relating to any use of the Work by You.
</li>
<li><strong>Limitation on Liability.</strong> EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL THE AUTHOR OR THE PUBLISHER BE LIABLE TO YOU ON ANY LEGAL
THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK OR OTHERWISE, EVEN IF THE AUTHOR
OR THE PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
</li>
<li><strong>Termination.</strong>
<ol style="list-style-type: lower-alpha;">
<li>This License and the rights granted hereunder will terminate automatically upon
any breach by You of any term of this License. Individuals or entities who have
received Derivative Works from You under this License, however, will not have their
licenses terminated provided such individuals or entities remain in full compliance
with those licenses. Sections 1, 2, 6, 7, 8, 9, 10 and 11 will survive any termination
of this License. </li>
<li>If You bring a copyright, trademark, patent or any other infringement claim against
any contributor over infringements You claim are made by the Work, your License
from such contributor to the Work ends automatically.</li>
<li>Subject to the above terms and conditions, this License is perpetual (for the duration
of the applicable copyright in the Work). Notwithstanding the above, the Author
reserves the right to release the Work under different license terms or to stop
distributing the Work at any time; provided, however that any such election will
not serve to withdraw this License (or any other license that has been, or is required
to be, granted under the terms of this License), and this License will continue
in full force and effect unless terminated as stated above.
</li>
</ol>
</li>
<li><strong>Publisher</strong>. The parties hereby confirm that the Publisher shall
not, under any circumstances, be responsible for and shall not have any liability
in respect of the subject matter of this License. The Publisher makes no warranty
whatsoever in connection with the Work and shall not be liable to You or any party
on any legal theory for any damages whatsoever, including without limitation any
general, special, incidental or consequential damages arising in connection to this
license. The Publisher reserves the right to cease making the Work available to
You at any time without notice</li>
<li><strong>Miscellaneous</strong>
<ol class="SpacedList" style="list-style-type: lower-alpha;">
<li>This License shall be governed by the laws of the location of the head office of
the Author or if the Author is an individual, the laws of location of the principal
place of residence of the Author.</li>
<li>If any provision of this License is invalid or unenforceable under applicable law,
it shall not affect the validity or enforceability of the remainder of the terms
of this License, and without further action by the parties to this License, such
provision shall be reformed to the minimum extent necessary to make such provision
valid and enforceable. </li>
<li>No term or provision of this License shall be deemed waived and no breach consented
to unless such waiver or consent shall be in writing and signed by the party to
be charged with such waiver or consent. </li>
<li>This License constitutes the entire agreement between the parties with respect to
the Work licensed herein. There are no understandings, agreements or representations
with respect to the Work not specified herein. The Author shall not be bound by
any additional provisions that may appear in any communication from You. This License
may not be modified without the mutual written agreement of the Author and You.
</li>
</ol>
</li>
</ol>
</div>
</center>
</body>
</html>
@@ -0,0 +1,7 @@
This control is almost entirely taken from http://www.codeproject.com/Articles/23746/TreeView-with-Columns by jkristia.
Minor changes have been made to clean up, rename or reorganise - as well as a few fixes to the non-visual styles rendering path
and some additional changes for my use of the control (like having the tree controls in a column other than the first, which mostly
'Just Worked' (tm) ).
So all credit goes to the above author!
@@ -0,0 +1,184 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.Design;
// Taken from http://www.codeproject.com/Articles/23746/TreeView-with-Columns with minor tweaks
// and fixes for my purposes.
namespace TreelistView
{
// http://msdn2.microsoft.com/en-us/library/9zky1t4k.aspx
// Extending Design-Time Support
// ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxdeveloping/html/d6ac8a6a-42fd-4bc8-bf33-b212811297e2.htm
// http://msdn2.microsoft.com/en-us/library/37899azc.aspx
// description of the property grid
// http://msdn2.microsoft.com/en-us/library/aa302326.aspx
// http://msdn2.microsoft.com/en-us/library/aa302334.aspx
// another good one explaining
// http://www.codeproject.com/KB/cs/dzcollectioneditor.aspx?print=true
public class ColumnCollectionEditor : CollectionEditor
{
public ColumnCollectionEditor(Type type) : base(type)
{
}
protected override bool CanSelectMultipleInstances()
{
return false;
}
protected override Type CreateCollectionItemType()
{
return base.CreateCollectionItemType();
}
protected override object CreateInstance(Type itemType)
{
TreeListView owner = this.Context.Instance as TreeListView;
// create new default fieldname
string fieldname;
string caption;
int cnt = owner.Columns.Count;
do
{
fieldname = "fieldname" + cnt.ToString();
caption = "Column_" + cnt.ToString();
cnt++;
}
while (owner.Columns[fieldname] != null);
return new TreeListColumn(fieldname, caption);
}
protected override string GetDisplayText(object value)
{
string Caption = (string)value.GetType().GetProperty("Caption").GetGetMethod().Invoke(value, null);
string Fieldname = (string)value.GetType().GetProperty("Fieldname").GetGetMethod().Invoke(value, null);
if (Caption.Length > 0)
return string.Format("{0} ({1})", Caption, Fieldname);
return base.GetDisplayText(value);
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
object result = base.EditValue(context, provider, value);
TreeListView owner = this.Context.Instance as TreeListView;
owner.Invalidate();
return result;
}
}
internal class ColumnConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destType)
{
if (destType == typeof(InstanceDescriptor) || destType == typeof(string))
return true;
else
return base.CanConvertTo(context, destType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo info, object value, Type destType)
{
if (destType == typeof(string))
{
string Caption = (string)value.GetType().GetProperty("Caption").GetGetMethod().Invoke(value, null);
string Fieldname = (string)value.GetType().GetProperty("Fieldname").GetGetMethod().Invoke(value, null);
return String.Format("{0}, {1}", Caption, Fieldname);
}
if (destType == typeof(InstanceDescriptor))
{
ConstructorInfo cinfo = typeof(TreeListColumn).GetConstructor(new Type[] { typeof(string), typeof(string) });
string Caption = (string)value.GetType().GetProperty("Caption").GetGetMethod().Invoke(value, null);
string Fieldname = (string)value.GetType().GetProperty("Fieldname").GetGetMethod().Invoke(value, null);
return new InstanceDescriptor(cinfo, new object[] {Fieldname, Caption}, false);
}
return base.ConvertTo(context, info, value, destType);
}
}
class ColumnsTypeConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(TreeListColumnCollection))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
return "(Columns Collection)";
return base.ConvertTo(context, culture, value, destinationType);
}
}
/// <summary>
/// Designer for the tree view control.
/// </summary>
class TreeListViewDesigner : ControlDesigner
{
IComponentChangeService onChangeService;
public override void Initialize(IComponent component)
{
base.Initialize(component);
onChangeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
if (onChangeService != null)
onChangeService.ComponentChanged += new ComponentChangedEventHandler(OnComponentChanged);
// we need to be notified when columsn have been resized.
TreeListView tree = Control as TreeListView;
tree.AfterResizingColumn += new MouseEventHandler(OnAfterResizingColumn);
}
void OnAfterResizingColumn(object sender, MouseEventArgs e)
{
// This is to notify that component has changed.
// This is causing the code InitializeComponent code to be updated
RaiseComponentChanged(null, null, null);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
void OnComponentChanged(object sender, ComponentChangedEventArgs e)
{
// repaint the control when any properties have changed
if(Control != null)
Control.Invalidate();
}
protected override bool GetHitTest(Point point)
{
// if mouse is over node, columns or scrollbar then return true
// which will cause the mouse event to be forwarded to the control
TreeListView tree = Control as TreeListView;
point = tree.PointToClient(point);
Node node = tree.CalcHitNode(point);
if (node != null)
return true;
TreelistView.HitInfo colinfo = tree.CalcColumnHit(point);
if ((int)(colinfo.HitType & HitInfo.eHitType.kColumnHeader) > 0)
return true;
if (tree.HitTestScrollbar(point))
return true;
return base.GetHitTest(point);
}
protected override void PostFilterProperties(IDictionary properties)
{
//properties.Remove("Cursor");
base.PostFilterProperties(properties);
}
}
}
@@ -0,0 +1,624 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Windows.Forms;
// Taken from http://www.codeproject.com/Articles/23746/TreeView-with-Columns with minor tweaks
// and fixes for my purposes.
namespace TreelistView
{
public class HitInfo
{
public enum eHitType
{
kColumnHeader = 0x0001,
kColumnHeaderResize = 0x0002,
}
public eHitType HitType = 0;
public TreeListColumn Column = null;
}
/// <summary>
/// DesignTimeVisible(false) prevents the columns from showing in the component tray (bottom of screen)
/// If the class implement IComponent it must also implement default (void) constructor and when overriding
/// the collection editors CreateInstance the return object must be used (if implementing IComponent), the reason
/// is that ISite is needed, and ISite is set when base.CreateInstance is called.
/// If no default constructor then the object will not be added to the collection in the initialize.
/// In addition if implementing IComponent then name and generatemember is shown in the property grid
/// Columns should just be added to the collection, no need for member, so no need to implement IComponent
/// </summary>
[DesignTimeVisible(false)]
[TypeConverter(typeof(ColumnConverter))]
public class TreeListColumn
{
TreeList.TextFormatting m_headerFormat = new TreeList.TextFormatting();
TreeList.TextFormatting m_cellFormat = new TreeList.TextFormatting();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TreeList.TextFormatting HeaderFormat
{
get { return m_headerFormat; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TreeList.TextFormatting CellFormat
{
get { return m_cellFormat; }
}
TreeListColumnCollection m_owner = null;
Rectangle m_calculatedRect;
int m_visibleIndex = -1;
int m_colIndex = -1;
int m_width = 50;
string m_fieldName = string.Empty;
string m_caption = string.Empty;
bool m_Moving = false;
internal TreeListColumnCollection Owner
{
get { return m_owner; }
set { m_owner = value; }
}
internal Rectangle internalCalculatedRect
{
get { return m_calculatedRect; }
set { m_calculatedRect = value; }
}
internal int internalVisibleIndex
{
get { return m_visibleIndex; }
set { m_visibleIndex = value; }
}
internal int internalIndex
{
get { return m_colIndex; }
set { m_colIndex = value; }
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool Moving
{
get { return m_Moving; }
set
{
m_Moving = value;
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Rectangle CalculatedRect
{
get { return internalCalculatedRect; }
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public TreeListView TreeList
{
get
{
if (Owner == null)
return null;
return Owner.Owner;
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Font Font
{
get { return m_owner.Font; }
}
public int Width
{
get { return m_width; }
set
{
if (m_width == value)
return;
m_width = value;
if (m_owner != null && m_owner.DesignMode)
m_owner.RecalcVisibleColumsRect();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Caption
{
get { return m_caption; }
set
{
m_caption = value;
if (m_owner != null)
m_owner.Invalidate();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Fieldname
{
get { return m_fieldName; }
set
{
if (m_owner == null || m_owner.DesignMode == false)
throw new Exception("Fieldname can only be set at design time, Use Constructor to set programatically");
if (value.Length == 0)
throw new Exception("empty Fieldname not value");
if (m_owner[value] != null)
throw new Exception("fieldname already exist in collection");
m_fieldName = value;
}
}
public TreeListColumn(string fieldName)
{
m_fieldName = fieldName;
}
public TreeListColumn(string fieldName, string caption)
{
m_fieldName = fieldName;
m_caption = caption;
}
public TreeListColumn(string fieldName, string caption, int width)
{
m_fieldName = fieldName;
m_caption = caption;
m_width = width;
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int VisibleIndex
{
get { return internalVisibleIndex; }
set
{
if (m_owner != null)
m_owner.SetVisibleIndex(this, value);
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int Index
{
get { return internalIndex; }
}
public bool ishot = false;
public virtual void Draw(Graphics dc, ColumnHeaderPainter painter, Rectangle r)
{
painter.DrawHeader(dc, r, this, this.HeaderFormat, ishot, m_Moving);
}
bool m_autoSize = false;
float m_autoSizeRatio = 100;
int m_autoSizeMinSize;
[DefaultValue(false)]
public bool AutoSize
{
get { return m_autoSize; }
set { m_autoSize = value; }
}
[DefaultValue(100f)]
public float AutoSizeRatio
{
get { return m_autoSizeRatio; }
set { m_autoSizeRatio = value; }
}
public int AutoSizeMinSize
{
get { return m_autoSizeMinSize; }
set { m_autoSizeMinSize = value; }
}
int m_calculatedAutoSize;
internal int CalculatedAutoSize
{
get { return m_calculatedAutoSize; }
set { m_calculatedAutoSize = value; }
}
}
[Description("This is the columns collection")]
//[TypeConverterAttribute(typeof(ColumnsTypeConverter))]
[Editor(typeof(ColumnCollectionEditor),typeof(System.Drawing.Design.UITypeEditor))]
public class TreeListColumnCollection : IList<TreeListColumn>, IList
{
ColumnHeaderPainter m_painter;
TreeList.CollumnSetting m_options;
TreeListView m_owner;
List<TreeListColumn> m_columns = new List<TreeListColumn>();
List<TreeListColumn> m_visibleCols = new List<TreeListColumn>();
Dictionary<string, TreeListColumn> m_columnMap = new Dictionary<string,TreeListColumn>();
[Browsable(false)]
public TreeList.CollumnSetting Options
{
get { return m_options; }
}
[Browsable(false)]
public ColumnHeaderPainter Painter
{
get { return m_painter; }
set { m_painter = value; }
}
[Browsable(false)]
public TreeListView Owner
{
get { return m_owner; }
}
[Browsable(false)]
public Font Font
{
get { return m_owner.Font; }
}
[Browsable(false)]
public TreeListColumn[] VisibleColumns
{
get { return m_visibleCols.ToArray(); }
}
[Browsable(false)]
public int ColumnsWidth
{
get
{
int width = 0;
foreach (TreeListColumn col in m_visibleCols)
{
if (col.AutoSize)
width += col.CalculatedAutoSize;
else
width += col.Width;
}
return width;
}
}
public TreeListColumnCollection(TreeListView owner)
{
m_owner = owner;
m_options = new TreeList.CollumnSetting(owner);
m_painter = new ColumnHeaderPainter(owner);
}
public TreeListColumn this[int index]
{
get
{
return m_columns[index];
}
set
{
m_columns[index] = value;
}
}
public TreeListColumn this[string fieldname]
{
get
{
TreeListColumn col;
m_columnMap.TryGetValue(fieldname, out col);
return col;
}
}
public void SetVisibleIndex(TreeListColumn col, int index)
{
m_visibleCols.Remove(col);
if (index >= 0)
{
if (index < m_visibleCols.Count)
m_visibleCols.Insert(index, col);
else
m_visibleCols.Add(col);
}
RecalcVisibleColumsRect();
}
public HitInfo CalcHitInfo(Point point, int horzOffset)
{
HitInfo info = new HitInfo();
info.Column = CalcHitColumn(point, horzOffset);
if ((info.Column != null) && (point.Y < Options.HeaderHeight))
{
info.HitType |= HitInfo.eHitType.kColumnHeader;
int right = info.Column.CalculatedRect.Right - horzOffset;
if (info.Column.AutoSize == false || info.Column.internalIndex+1 < m_columns.Count)
{
if (point.X >= right - 4 && point.X <= right)
info.HitType |= HitInfo.eHitType.kColumnHeaderResize;
}
}
return info;
}
public TreeListColumn CalcHitColumn(Point point, int horzOffset)
{
if (point.X < Options.LeftMargin)
return null;
foreach (TreeListColumn col in m_visibleCols)
{
int left = col.CalculatedRect.Left - horzOffset;
int right = col.CalculatedRect.Right - horzOffset;
if (point.X >= left && point.X <= right)
return col;
}
return null;
}
public void RecalcVisibleColumsRect()
{
RecalcVisibleColumsRect(false);
}
public void RecalcVisibleColumsRect(bool isColumnResizing)
{
if (IsInitializing)
return;
int x = 0;//m_leftMargin;
if (m_owner.RowOptions.ShowHeader)
x = m_owner.RowOptions.HeaderWidth;
int y = 0;
int h = Options.HeaderHeight;
int index = 0;
foreach(TreeListColumn col in m_columns)
{
col.internalVisibleIndex = -1;
col.internalIndex = index++;
}
// calculate size requierd by fix columns and auto adjusted columns
// at the same time calculate total ratio value
int widthFixedColumns = 0;
int widthAutoSizeColumns = 0;
float totalRatio = 0;
foreach (TreeListColumn col in m_visibleCols)
{
if (col.AutoSize)
{
widthAutoSizeColumns += col.AutoSizeMinSize;
totalRatio += col.AutoSizeRatio;
}
else
widthFixedColumns += col.Width;
}
int clientWidth = m_owner.ClientRectangle.Width - m_owner.RowHeaderWidth();
// find ratio 'unit' value
float remainingWidth = clientWidth - (widthFixedColumns + widthAutoSizeColumns);
float ratioUnit = 0;
if (totalRatio > 0 && remainingWidth > 0)
ratioUnit = remainingWidth / totalRatio;
for (index = 0; index < m_visibleCols.Count; index++)
{
TreeListColumn col = m_visibleCols[index];
int width = col.Width;
if (col.AutoSize)
{
// if doing column resizing then keep adjustable columns fixed at last width
if (m_options.FreezeWhileResizing && isColumnResizing)
width = col.CalculatedAutoSize;
else
width = Math.Max(10, col.AutoSizeMinSize + (int)Math.Round(ratioUnit * col.AutoSizeRatio - 1.0f));
col.CalculatedAutoSize = width;
}
col.internalCalculatedRect = new Rectangle(x, y, width, h);
col.internalVisibleIndex = index;
x += width;
}
Invalidate();
}
public void Draw(Graphics dc, Rectangle rect, int horzOffset)
{
foreach (TreeListColumn col in m_visibleCols)
{
Rectangle r = col.CalculatedRect;
r.X -= horzOffset;
if (r.Left > rect.Right)
break;
col.Draw(dc, m_painter, r);
}
// drwa row header filler
if (m_owner.RowOptions.ShowHeader)
{
Rectangle r = new Rectangle(0, 0, m_owner.RowOptions.HeaderWidth, Options.HeaderHeight);
m_painter.DrawHeaderFiller(dc, r);
}
}
public void AddRange(IEnumerable<TreeListColumn> columns)
{
foreach (TreeListColumn col in columns)
Add(col);
}
/// <summary>
/// AddRange(Item[]) is required for the designer.
/// </summary>
/// <param name="columns"></param>
public void AddRange(TreeListColumn[] columns)
{
foreach (TreeListColumn col in columns)
Add(col);
}
public void Add(TreeListColumn item)
{
bool designmode = Owner.DesignMode;
if (!designmode)
{
Debug.Assert(m_columnMap.ContainsKey(item.Fieldname) == false);
Debug.Assert(item.Owner == null, "column.Owner == null");
}
else
{
m_columns.Remove(item);
m_visibleCols.Remove(item);
}
item.Owner = this;
m_columns.Add(item);
m_visibleCols.Add(item);
m_columnMap[item.Fieldname] = item;
RecalcVisibleColumsRect();
//return item;
}
public void Clear()
{
m_columnMap.Clear();
m_columns.Clear();
m_visibleCols.Clear();
}
public bool Contains(TreeListColumn item)
{
return m_columns.Contains(item);
}
[Browsable(false)]
public int Count
{
get { return m_columns.Count; }
}
[Browsable(false)]
public bool IsReadOnly
{
get { return false; }
}
#region IList<TreeListColumn> Members
public int IndexOf(TreeListColumn item)
{
return m_columns.IndexOf(item);
}
public void Insert(int index, TreeListColumn item)
{
m_columns.Insert(index, item);
}
public void RemoveAt(int index)
{
if (index >= 0 && index < m_columns.Count)
{
TreeListColumn col = m_columns[index];
SetVisibleIndex(col, -1);
m_columnMap.Remove(col.Fieldname);
}
m_columns.RemoveAt(index);
}
#endregion
#region ICollection<TreeListColumn> Members
public void CopyTo(TreeListColumn[] array, int arrayIndex)
{
m_columns.CopyTo(array, arrayIndex);
}
public bool Remove(TreeListColumn item)
{
SetVisibleIndex(item, -1);
m_columnMap.Remove(item.Fieldname);
return m_columns.Remove(item);
}
#endregion
#region IEnumerable<TreeListColumn> Members
public IEnumerator<TreeListColumn> GetEnumerator()
{
return m_columns.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region IList Members
int IList.Add(object value)
{
Add((TreeListColumn)value);
return Count - 1;
}
bool IList.Contains(object value)
{
return Contains((TreeListColumn)value);
}
int IList.IndexOf(object value)
{
return IndexOf((TreeListColumn)value);
}
void IList.Insert(int index, object value)
{
Insert(index, (TreeListColumn)value);
}
bool IList.IsFixedSize
{
get { return false; }
}
void IList.Remove(object value)
{
Remove((TreeListColumn)value);
}
object IList.this[int index]
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
#region ICollection Members
public void CopyTo(Array array, int index)
{
throw new Exception("The method or operation is not implemented.");
}
public bool IsSynchronized
{
get { throw new Exception("The method or operation is not implemented."); }
}
public object SyncRoot
{
get { throw new Exception("The method or operation is not implemented."); }
}
#endregion
internal bool DesignMode
{
get
{
if (m_owner != null)
return m_owner.DesignMode;
return false;
}
}
internal void Invalidate()
{
if (m_owner != null)
m_owner.Invalidate();
}
bool IsInitializing = false;
internal void BeginInit()
{
IsInitializing = true;
}
internal void EndInit()
{
IsInitializing = false;
RecalcVisibleColumsRect();
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,334 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.Windows.Forms;
// Taken from http://www.codeproject.com/Articles/23746/TreeView-with-Columns with minor tweaks
// and fixes for my purposes.
namespace TreelistView.TreeList
{
[TypeConverterAttribute(typeof(OptionsSettingTypeConverter))]
public class TextFormatting
{
ContentAlignment m_alignment = ContentAlignment.MiddleLeft;
Color m_foreColor = SystemColors.ControlText;
Color m_backColor = Color.Transparent;
Padding m_padding = new Padding(0,0,0,0);
public TextFormatFlags GetFormattingFlags()
{
TextFormatFlags flags = 0;
switch (TextAlignment)
{
case ContentAlignment.TopLeft:
flags = TextFormatFlags.Top | TextFormatFlags.Left;
break;
case ContentAlignment.TopCenter:
flags = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter;
break;
case ContentAlignment.TopRight:
flags = TextFormatFlags.Top | TextFormatFlags.Right;
break;
case ContentAlignment.MiddleLeft:
flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
break;
case ContentAlignment.MiddleCenter:
flags = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter;
break;
case ContentAlignment.MiddleRight:
flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
break;
case ContentAlignment.BottomLeft:
flags = TextFormatFlags.Bottom | TextFormatFlags.Left;
break;
case ContentAlignment.BottomCenter:
flags = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter;
break;
case ContentAlignment.BottomRight:
flags = TextFormatFlags.Bottom | TextFormatFlags.Right;
break;
}
return flags;
}
[DefaultValue(typeof(Padding), "0,0,0,0")]
public Padding Padding
{
get { return m_padding; }
set { m_padding = value; }
}
[DefaultValue(typeof(ContentAlignment), "MiddleLeft")]
public ContentAlignment TextAlignment
{
get { return m_alignment; }
set { m_alignment = value; }
}
[DefaultValue(typeof(Color), "ControlText")]
public Color ForeColor
{
get { return m_foreColor; }
set { m_foreColor = value; }
}
[DefaultValue(typeof(Color), "Transparent")]
public Color BackColor
{
get { return m_backColor; }
set { m_backColor = value; }
}
public TextFormatting()
{
}
public TextFormatting(TextFormatting aCopy)
{
m_alignment = aCopy.m_alignment;
m_foreColor = aCopy.m_foreColor;
m_backColor = aCopy.m_backColor;
m_padding = aCopy.m_padding;
}
}
[TypeConverterAttribute(typeof(OptionsSettingTypeConverter))]
public class ViewSetting
{
TreeListView m_owner;
BorderStyle m_borderStyle = BorderStyle.None;
int m_indent = 16;
bool m_showLine = true;
bool m_showPlusMinus = true;
bool m_showGridLines = true;
bool m_rearrangeableColumns = false;
bool m_hoverHand = true;
[Category("Behavior")]
[DefaultValue(typeof(int), "16")]
public int Indent
{
get { return m_indent; }
set
{
m_indent = value;
m_owner.Invalidate();
}
}
[Category("Behavior")]
[DefaultValue(typeof(bool), "True")]
public bool ShowLine
{
get { return m_showLine; }
set
{
m_showLine = value;
m_owner.Invalidate();
}
}
[Category("Behavior")]
[DefaultValue(typeof(bool), "True")]
public bool ShowPlusMinus
{
get { return m_showPlusMinus; }
set
{
m_showPlusMinus = value;
m_owner.Invalidate();
}
}
[Category("Behavior")]
[DefaultValue(typeof(bool), "True")]
public bool ShowGridLines
{
get { return m_showGridLines; }
set
{
m_showGridLines = value;
m_owner.Invalidate();
}
}
[Category("Behavior")]
[DefaultValue(typeof(bool), "False")]
public bool UserRearrangeableColumns
{
get { return m_rearrangeableColumns; }
set
{
m_rearrangeableColumns = value;
}
}
[Category("Behavior")]
[DefaultValue(typeof(bool), "True")]
public bool HoverHandTreeColumn
{
get { return m_hoverHand; }
set
{
m_hoverHand = value;
}
}
[Category("Appearance")]
[DefaultValue(typeof(BorderStyle), "None")]
public BorderStyle BorderStyle
{
get { return m_borderStyle; }
set
{
if (m_borderStyle != value)
{
m_borderStyle = value;
m_owner.internalUpdateStyles();
m_owner.Invalidate();
}
}
}
public ViewSetting(TreeListView owner)
{
m_owner = owner;
}
}
[TypeConverterAttribute(typeof(OptionsSettingTypeConverter))]
public class CollumnSetting
{
bool m_FreezeWhileResizing = false;
int m_leftMargin = 5;
int m_headerHeight = 20;
TreeListView m_owner;
[DefaultValue(false)]
public bool FreezeWhileResizing
{
get { return m_FreezeWhileResizing; }
set
{
m_FreezeWhileResizing = value;
}
}
[DefaultValue(5)]
public int LeftMargin
{
get { return m_leftMargin; }
set
{
m_leftMargin = value;
m_owner.Columns.RecalcVisibleColumsRect();
m_owner.Invalidate();
}
}
[DefaultValue(20)]
public int HeaderHeight
{
get { return m_headerHeight; }
set
{
m_headerHeight = value;
m_owner.Columns.RecalcVisibleColumsRect();
m_owner.Invalidate();
}
}
public CollumnSetting(TreeListView owner)
{
m_owner = owner;
}
}
[TypeConverterAttribute(typeof(OptionsSettingTypeConverter))]
public class RowSetting
{
TreeListView m_owner;
bool m_showHeader = true;
bool m_hoverHighlight = false;
int m_headerWidth = 15;
int m_itemHeight = 16;
[DefaultValue(true)]
public bool ShowHeader
{
get { return m_showHeader; }
set
{
if (m_showHeader == value)
return;
m_showHeader = value;
m_owner.Columns.RecalcVisibleColumsRect();
m_owner.Invalidate();
}
}
[DefaultValue(false)]
public bool HoverHighlight
{
get { return m_hoverHighlight; }
set
{
if (m_hoverHighlight == value)
return;
m_hoverHighlight = value;
m_owner.Invalidate();
}
}
[DefaultValue(15)]
public int HeaderWidth
{
get { return m_headerWidth; }
set
{
if (m_headerWidth == value)
return;
m_headerWidth = value;
m_owner.Columns.RecalcVisibleColumsRect();
m_owner.Invalidate();
}
}
[Category("Behavior")]
[DefaultValue(typeof(int), "16")]
public int ItemHeight
{
get { return m_itemHeight; }
set
{
m_itemHeight = value;
m_owner.Invalidate();
}
}
public RowSetting(TreeListView owner)
{
m_owner = owner;
}
}
class OptionsSettingTypeConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(ViewSetting))
return true;
if (destinationType == typeof(RowSetting))
return true;
if (destinationType == typeof(CollumnSetting))
return true;
if (destinationType == typeof(TextFormatting))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value.GetType() == typeof(ViewSetting))
return "(View Options)";
if (destinationType == typeof(string) && value.GetType() == typeof(RowSetting))
return "(Row Header Options)";
if (destinationType == typeof(string) && value.GetType() == typeof(CollumnSetting))
return "(Columns Options)";
if (destinationType == typeof(string) && value.GetType() == typeof(TextFormatting))
return "(Formatting)";
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
@@ -0,0 +1,427 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Runtime.InteropServices;
// Taken from http://www.codeproject.com/Articles/23746/TreeView-with-Columns with minor tweaks
// and fixes for my purposes.
namespace TreelistView
{
public class VisualStyleItemBackground // can't find system provided visual style for this.
{
[StructLayout(LayoutKind.Sequential)]
public class RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT()
{
}
public RECT(Rectangle r)
{
this.left = r.X;
this.top = r.Y;
this.right = r.Right;
this.bottom = r.Bottom;
}
}
[DllImport("uxtheme.dll", CharSet=CharSet.Auto)]
public static extern int DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int partId, int stateId, [In] RECT pRect, [In] RECT pClipRect);
[DllImport("uxtheme.dll", CharSet=CharSet.Auto)]
public static extern IntPtr OpenThemeData(IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)] string pszClassList);
[DllImport("uxtheme.dll", CharSet=CharSet.Auto)]
public static extern int CloseThemeData(IntPtr hTheme);
//http://www.ookii.org/misc/vsstyle.h
//http://msdn2.microsoft.com/en-us/library/bb773210(VS.85).aspx
enum ITEMSTATES
{
LBPSI_HOT = 1,
LBPSI_HOTSELECTED = 2,
LBPSI_SELECTED = 3,
LBPSI_SELECTEDNOTFOCUS = 4,
};
enum LISTBOXPARTS
{
LBCP_BORDER_HSCROLL = 1,
LBCP_BORDER_HVSCROLL = 2,
LBCP_BORDER_NOSCROLL = 3,
LBCP_BORDER_VSCROLL = 4,
LBCP_ITEM = 5,
};
public enum Style
{
Normal,
Inactive, // when not focused
}
Style m_style;
public VisualStyleItemBackground(Style style)
{
m_style = style;
}
public void DrawBackground(Control owner, Graphics dc, Rectangle r, Color col)
{
/*
IntPtr themeHandle = OpenThemeData(owner.Handle, "Explorer");
if (themeHandle != IntPtr.Zero)
{
DrawThemeBackground(themeHandle, dc.GetHdc(), (int)LISTBOXPARTS.LBCP_ITEM, (int)ITEMSTATES.LBPSI_SELECTED, new RECT(r), new RECT(r));
dc.ReleaseHdc();
CloseThemeData(themeHandle);
return;
}
*/
Pen pen = new Pen(col);
GraphicsPath path = new GraphicsPath();
path.AddLine(r.Left + 2, r.Top, r.Right - 2, r.Top);
path.AddLine(r.Right, r.Top + 2, r.Right, r.Bottom - 2);
path.AddLine(r.Right - 2, r.Bottom, r.Left + 2, r.Bottom);
path.AddLine(r.Left, r.Bottom - 2, r.Left, r.Top + 2);
path.CloseFigure();
dc.DrawPath(pen, path);
//r.Inflate(-1, -1);
LinearGradientBrush brush = new LinearGradientBrush(r, Color.FromArgb(120, col), col, 90);
dc.FillRectangle(brush, r);
// for some reason in some cases the 'white' end of the gradient brush is drawn with the starting color
// therefore this redraw of the 'top' line of the rectangle
//dc.DrawLine(Pens.White, r.Left + 1, r.Top, r.Right - 1, r.Top);
pen.Dispose();
brush.Dispose();
path.Dispose();
}
}
public delegate string CellDataToString(TreeListColumn column, object data);
public class CellPainter
{
public static Rectangle AdjustRectangle(Rectangle r, Padding padding)
{
r.X += padding.Left;
r.Width -= padding.Left + padding.Right;
r.Y += padding.Top;
r.Height -= padding.Top + padding.Bottom;
return r;
}
protected TreeListView m_owner;
protected CellDataToString m_converter = null;
public CellDataToString CellDataConverter
{
get { return m_converter; }
set { m_converter = value; }
}
public CellPainter(TreeListView owner)
{
m_owner = owner;
}
public virtual void DrawSelectionBackground(Graphics dc, Rectangle nodeRect, Node node)
{
Point mousePoint = m_owner.PointToClient(Cursor.Position);
Node hoverNode = m_owner.CalcHitNode(mousePoint);
if (m_owner.NodesSelection.Contains(node) || m_owner.FocusedNode == node)
{
Color col = m_owner.Focused ? SystemColors.Highlight : SystemColors.ControlLight;
if (!Application.RenderWithVisualStyles)
{
// have to fill the solid background only before the node is painted
dc.FillRectangle(SystemBrushes.FromSystemColor(col), nodeRect);
}
else
{
col = m_owner.Focused ? SystemColors.Highlight : Color.FromArgb(180, SystemColors.ControlDark);
// have to draw the transparent background after the node is painted
VisualStyleItemBackground.Style style = VisualStyleItemBackground.Style.Normal;
if (m_owner.Focused == false)
style = VisualStyleItemBackground.Style.Inactive;
VisualStyleItemBackground rendere = new VisualStyleItemBackground(style);
rendere.DrawBackground(m_owner, dc, nodeRect, col);
}
}
else if (hoverNode == node && m_owner.RowOptions.HoverHighlight)
{
Color col = SystemColors.ControlLight;
if (!Application.RenderWithVisualStyles)
{
// have to fill the solid background only before the node is painted
dc.FillRectangle(SystemBrushes.FromSystemColor(col), nodeRect);
}
else
{
// have to draw the transparent background after the node is painted
VisualStyleItemBackground.Style style = VisualStyleItemBackground.Style.Normal;
if (m_owner.Focused == false)
style = VisualStyleItemBackground.Style.Inactive;
VisualStyleItemBackground rendere = new VisualStyleItemBackground(style);
rendere.DrawBackground(m_owner, dc, nodeRect, col);
}
}
if (m_owner.Focused && (m_owner.FocusedNode == node))
{
nodeRect.Height += 1;
nodeRect.Inflate(-1,-1);
ControlPaint.DrawFocusRectangle(dc, nodeRect);
}
}
public virtual void PaintCellBackground(Graphics dc,
Rectangle cellRect,
Node node,
TreeListColumn column,
TreeList.TextFormatting format,
object data)
{
Color c = Color.Transparent;
Point mousePoint = m_owner.PointToClient(Cursor.Position);
Node hoverNode = m_owner.CalcHitNode(mousePoint);
if (format.BackColor != Color.Transparent)
c = format.BackColor;
if (node.BackColor != Color.Transparent)
c = node.BackColor;
if (!m_owner.NodesSelection.Contains(node) && m_owner.FocusedNode != node &&
!(hoverNode == node && m_owner.RowOptions.HoverHighlight) &&
node.DefaultBackColor != Color.Transparent)
c = node.DefaultBackColor;
if (c != Color.Transparent)
{
Rectangle r = cellRect;
r.X -= Math.Max(0, column.CalculatedRect.Width - cellRect.Width);
r.Width += Math.Max(0, column.CalculatedRect.Width - cellRect.Width);
SolidBrush brush = new SolidBrush(c);
dc.FillRectangle(brush, r);
brush.Dispose();
}
}
public virtual void PaintCellText(Graphics dc,
Rectangle cellRect,
Node node,
TreeListColumn column,
TreeList.TextFormatting format,
object data)
{
if (data != null)
{
cellRect = AdjustRectangle(cellRect, format.Padding);
//dc.DrawRectangle(Pens.Black, cellRect);
Color color = format.ForeColor;
if (m_owner.FocusedNode == node && Application.RenderWithVisualStyles == false && m_owner.Focused)
color = SystemColors.HighlightText;
TextFormatFlags flags= TextFormatFlags.EndEllipsis | format.GetFormattingFlags();
Font f = m_owner.Font;
Font disposefont = null;
if(node.Bold && node.Italic)
disposefont = f = new Font(f, FontStyle.Bold|FontStyle.Italic);
else if (node.Bold)
disposefont = f = new Font(f, FontStyle.Bold);
else if (node.Italic)
disposefont = f = new Font(f, FontStyle.Italic);
string datastring = "";
if(m_converter != null)
datastring = m_converter(column, data);
else
datastring = data.ToString();
TextRenderer.DrawText(dc, datastring, f, cellRect, color, flags);
if (disposefont != null) disposefont.Dispose();
}
}
public virtual void PaintCellPlusMinus(Graphics dc, Rectangle glyphRect, Node node, TreeListColumn column, TreeList.TextFormatting format)
{
if (!Application.RenderWithVisualStyles)
{
// find square rect first
int diff = glyphRect.Height-glyphRect.Width;
glyphRect.Y += diff/2;
glyphRect.Height -= diff;
// draw 8x8 box centred
while (glyphRect.Height > 8)
{
glyphRect.Height -= 2;
glyphRect.Y += 1;
glyphRect.X += 1;
}
// make a box
glyphRect.Width = glyphRect.Height;
// clear first
SolidBrush brush = new SolidBrush(format.BackColor);
if (format.BackColor == Color.Transparent)
brush = new SolidBrush(m_owner.BackColor);
dc.FillRectangle(brush, glyphRect);
brush.Dispose();
// draw outline
Pen p = new Pen(SystemColors.ControlDark);
dc.DrawRectangle(p, glyphRect);
p.Dispose();
p = new Pen(SystemColors.ControlText);
// reduce box for internal lines
glyphRect.X += 2; glyphRect.Y += 2;
glyphRect.Width -= 4; glyphRect.Height -= 4;
// draw horizontal line always
dc.DrawLine(p, glyphRect.X, glyphRect.Y + glyphRect.Height / 2, glyphRect.X + glyphRect.Width, glyphRect.Y + glyphRect.Height / 2);
// draw vertical line if this should be a +
if(!node.Expanded)
dc.DrawLine(p, glyphRect.X + glyphRect.Width / 2, glyphRect.Y, glyphRect.X + glyphRect.Width / 2, glyphRect.Y + glyphRect.Height);
p.Dispose();
return;
}
VisualStyleElement element = VisualStyleElement.TreeView.Glyph.Closed;
if (node.Expanded)
element = VisualStyleElement.TreeView.Glyph.Opened;
if (VisualStyleRenderer.IsElementDefined(element))
{
VisualStyleRenderer renderer = new VisualStyleRenderer(element);
renderer.DrawBackground(dc, glyphRect);
}
}
}
public class ColumnHeaderPainter
{
TreeListView m_owner;
public ColumnHeaderPainter(TreeListView owner)
{
m_owner = owner;
}
public static Rectangle AdjustRectangle(Rectangle r, Padding padding)
{
r.X += padding.Left;
r.Width -= padding.Left + padding.Right;
r.Y += padding.Top;
r.Height -= padding.Top + padding.Bottom;
return r;
}
public virtual void DrawHeaderFiller(Graphics dc, Rectangle r)
{
if (!Application.RenderWithVisualStyles)
{
ControlPaint.DrawButton(dc, r, ButtonState.Flat);
return;
}
VisualStyleElement element = VisualStyleElement.Header.Item.Normal;
if (VisualStyleRenderer.IsElementDefined(element))
{
VisualStyleRenderer renderer = new VisualStyleRenderer(element);
renderer.DrawBackground(dc, r);
}
}
public void DrawHeaderText(Graphics dc, Rectangle cellRect, TreeListColumn column, TreeList.TextFormatting format)
{
Color color = format.ForeColor;
TextFormatFlags flags = TextFormatFlags.EndEllipsis | format.GetFormattingFlags();
TextRenderer.DrawText(dc, column.Caption, column.Font, cellRect, color, flags);
}
public virtual void DrawHeader(Graphics dc, Rectangle cellRect, TreeListColumn column, TreeList.TextFormatting format, bool isHot, bool highlight)
{
Rectangle textRect = AdjustRectangle(cellRect, format.Padding);
if (!Application.RenderWithVisualStyles)
{
ControlPaint.DrawButton(dc, cellRect,
m_owner.ViewOptions.UserRearrangeableColumns && highlight ? ButtonState.Pushed : ButtonState.Flat);
DrawHeaderText(dc, textRect, column, format);
return;
}
VisualStyleElement element = VisualStyleElement.Header.Item.Normal;
if (isHot || highlight)
element = VisualStyleElement.Header.Item.Hot;
if (VisualStyleRenderer.IsElementDefined(element))
{
VisualStyleRenderer renderer = new VisualStyleRenderer(element);
renderer.DrawBackground(dc, cellRect);
if (format.BackColor != Color.Transparent)
{
SolidBrush brush = new SolidBrush(format.BackColor);
dc.FillRectangle(brush, cellRect);
brush.Dispose();
}
//dc.DrawRectangle(Pens.Black, cellRect);
DrawHeaderText(dc, textRect, column, format);
}
}
public virtual void DrawVerticalGridLines(TreeListColumnCollection columns, Graphics dc, Rectangle r, int hScrollOffset)
{
foreach (TreeListColumn col in columns.VisibleColumns)
{
int rightPos = col.CalculatedRect.Right - hScrollOffset;
if (rightPos < 0)
continue;
Pen p = new Pen(columns.Owner.GridLineColour);
dc.DrawLine(p, rightPos, r.Top, rightPos, r.Bottom);
p.Dispose();
}
}
}
public class RowPainter
{
public void DrawHeader(Graphics dc, Rectangle r, bool isHot)
{
if (!Application.RenderWithVisualStyles)
{
if (r.Width > 0 && r.Height > 0)
{
ControlPaint.DrawButton(dc, r, ButtonState.Flat);
}
return;
}
VisualStyleElement element = VisualStyleElement.Header.Item.Normal;
if (isHot)
element = VisualStyleElement.Header.Item.Hot;
if (VisualStyleRenderer.IsElementDefined(element))
{
VisualStyleRenderer renderer = new VisualStyleRenderer(element);
renderer.DrawBackground(dc, r);
}
}
public void DrawHorizontalGridLine(Graphics dc, Rectangle r, Color col)
{
Pen p = new Pen(col);
dc.DrawLine(p, r.Left, r.Bottom, r.Right, r.Bottom);
p.Dispose();
}
}
}
File diff suppressed because it is too large Load Diff