453 lines
15 KiB
C#
453 lines
15 KiB
C#
/******************************************************
|
|
* ROMVault2 is written by Gordon J. *
|
|
* Contact gordon@romvault.com *
|
|
* Copyright 2014 *
|
|
******************************************************/
|
|
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Windows.Forms;
|
|
using ROMVault2.RvDB;
|
|
|
|
namespace ROMVault2
|
|
{
|
|
|
|
public partial class RvTree : UserControl
|
|
{
|
|
|
|
|
|
public event MouseEventHandler RvSelected;
|
|
|
|
private RvDir _lTree;
|
|
|
|
private RvDir _lSelected;
|
|
|
|
public RvTree()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
#region "Setup"
|
|
private int _yPos;
|
|
|
|
public void Setup(ref RvDir dirTree)
|
|
{
|
|
_lSelected = null;
|
|
_lTree = dirTree;
|
|
SetupInt();
|
|
}
|
|
|
|
private void SetupInt()
|
|
{
|
|
_yPos = 0;
|
|
|
|
int treeCount = _lTree.ChildCount;
|
|
|
|
if (treeCount >= 1)
|
|
{
|
|
for (int i = 0; i < treeCount - 1; i++)
|
|
SetupTree((RvDir)_lTree.Child(i), "├");
|
|
|
|
SetupTree((RvDir)_lTree.Child(treeCount - 1), "└");
|
|
}
|
|
AutoScrollMinSize = new Size(500, _yPos);
|
|
Refresh();
|
|
}
|
|
|
|
private void SetupTree(RvDir pTree, string pTreeBranches)
|
|
{
|
|
int nodeDepth = pTreeBranches.Length - 1;
|
|
|
|
pTree.Tree.TreeBranches = pTreeBranches;
|
|
|
|
pTree.Tree.RTree = new Rectangle(0, _yPos - 8, nodeDepth * 18, 16);
|
|
pTree.Tree.RExpand = new Rectangle(5 + nodeDepth * 18, _yPos + 4, 9, 9);
|
|
pTree.Tree.RChecked = new Rectangle(20 + nodeDepth * 18, _yPos + 2, 13, 13);
|
|
pTree.Tree.RIcon = new Rectangle(35 + nodeDepth * 18, _yPos, 16, 16);
|
|
pTree.Tree.RText = new Rectangle(51 + nodeDepth * 18, _yPos, 500, 16);
|
|
|
|
pTreeBranches = pTreeBranches.Replace("├", "│");
|
|
pTreeBranches = pTreeBranches.Replace("└", " ");
|
|
|
|
_yPos = _yPos + 16;
|
|
|
|
bool found = false;
|
|
int last = 0;
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase t = pTree.Child(i);
|
|
if (t is RvDir)
|
|
if (((RvDir)t).Tree != null)
|
|
{
|
|
found = true;
|
|
if (pTree.Tree.TreeExpanded)
|
|
last = i;
|
|
}
|
|
}
|
|
if (!found)
|
|
pTree.Tree.RExpand = new Rectangle(0, 0, 0, 0);
|
|
|
|
|
|
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase t = pTree.Child(i);
|
|
if (t is RvDir)
|
|
if (((RvDir)t).Tree != null)
|
|
{
|
|
if (pTree.Tree.TreeExpanded)
|
|
{
|
|
if (i != last)
|
|
SetupTree((RvDir)pTree.Child(i), pTreeBranches + "├");
|
|
else
|
|
SetupTree((RvDir)pTree.Child(i), pTreeBranches + "└");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region "Paint"
|
|
private int _hScroll;
|
|
private int _vScroll;
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
{
|
|
|
|
Graphics g = e.Graphics;
|
|
|
|
_hScroll = HorizontalScroll.Value;
|
|
_vScroll = VerticalScroll.Value;
|
|
|
|
Rectangle t = new Rectangle(e.ClipRectangle.Left + _hScroll, e.ClipRectangle.Top + _vScroll, e.ClipRectangle.Width, e.ClipRectangle.Height);
|
|
|
|
g.FillRectangle(Brushes.White, e.ClipRectangle);
|
|
|
|
if (_lTree != null)
|
|
for (int i = 0; i < _lTree.ChildCount; i++)
|
|
{
|
|
RvBase tBase = _lTree.Child(i);
|
|
if (tBase is RvDir)
|
|
{
|
|
RvDir tDir = (RvDir)tBase;
|
|
if (tDir.Tree != null)
|
|
PaintTree(tDir, g, t);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private void PaintTree(RvDir pTree, Graphics g, Rectangle t)
|
|
{
|
|
int y = pTree.Tree.RTree.Top - _vScroll;
|
|
|
|
if (pTree.Tree.RTree.IntersectsWith(t))
|
|
{
|
|
Pen p = new Pen(Brushes.Gray, 1) { DashStyle = DashStyle.Dot };
|
|
|
|
string lTree = pTree.Tree.TreeBranches;
|
|
for (int j = 0; j < lTree.Length; j++)
|
|
{
|
|
int x = j * 18 - _hScroll;
|
|
string cTree = lTree.Substring(j, 1);
|
|
switch (cTree)
|
|
{
|
|
case "│":
|
|
g.DrawLine(p, x + 9, y, x + 9, y + 16);
|
|
break;
|
|
|
|
case "├":
|
|
case "└":
|
|
g.DrawLine(p, x + 9, y, x + 9, y + 16);
|
|
g.DrawLine(p, x + 9, y + 16, x + 27, y + 16);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pTree.Tree.RExpand.IsEmpty)
|
|
if (pTree.Tree.RExpand.IntersectsWith(t))
|
|
{
|
|
g.DrawImage(pTree.Tree.TreeExpanded ? rvImages.ExpandBoxMinus : rvImages.ExpandBoxPlus, RSub(pTree.Tree.RExpand, _hScroll, _vScroll));
|
|
}
|
|
|
|
|
|
if (pTree.Tree.RChecked.IntersectsWith(t))
|
|
{
|
|
switch (pTree.Tree.Checked)
|
|
{
|
|
case RvTreeRow.TreeSelect.Disabled:
|
|
g.DrawImage(rvImages.TickBoxDisabled, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
|
|
break;
|
|
case RvTreeRow.TreeSelect.UnSelected:
|
|
g.DrawImage(rvImages.TickBoxUnTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
|
|
break;
|
|
case RvTreeRow.TreeSelect.Selected:
|
|
g.DrawImage(rvImages.TickBoxTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pTree.Tree.RIcon.IntersectsWith(t))
|
|
{
|
|
int icon = 2;
|
|
if (pTree.DirStatus.HasInToSort())
|
|
{
|
|
icon = 4;
|
|
}
|
|
else if (!pTree.DirStatus.HasCorrect())
|
|
{
|
|
icon = 1;
|
|
}
|
|
else if (!pTree.DirStatus.HasMissing())
|
|
{
|
|
icon = 3;
|
|
}
|
|
|
|
|
|
|
|
Bitmap bm;
|
|
if (pTree.Dat == null && pTree.DirDatCount != 1) // Directory above DAT's in Tree
|
|
bm = rvImages.GetBitmap("DirectoryTree" + icon);
|
|
else if (pTree.Dat == null && pTree.DirDatCount == 1) // Directory that contains DAT's
|
|
bm = rvImages.GetBitmap("Tree" + icon);
|
|
else if (pTree.Dat != null && pTree.DirDatCount == 0) // Directories made by a DAT
|
|
bm = rvImages.GetBitmap("Tree" + icon);
|
|
else
|
|
{
|
|
ReportError.SendAndShow("Unknown Tree settings in DisplayTree.");
|
|
bm = null;
|
|
}
|
|
|
|
if (bm != null)
|
|
{
|
|
g.DrawImage(bm, RSub(pTree.Tree.RIcon, _hScroll, _vScroll));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Rectangle recBackGround = new Rectangle(pTree.Tree.RText.X, pTree.Tree.RText.Y, Width - pTree.Tree.RText.X + _hScroll, pTree.Tree.RText.Height);
|
|
|
|
if (recBackGround.IntersectsWith(t))
|
|
{
|
|
string thistxt;
|
|
|
|
if (pTree.Dat == null && pTree.DirDatCount != 1) // Directory above DAT's in Tree
|
|
thistxt = pTree.Name;
|
|
else if (pTree.Dat == null && pTree.DirDatCount == 1) // Directory that contains DAT's
|
|
thistxt = pTree.Name + ": " + pTree.DirDat(0).GetData(RvDat.DatData.Description) + " ( Have:" + pTree.DirStatus.CountCorrect() + " \\ Missing: " + pTree.DirStatus.CountMissing() + " )";
|
|
|
|
// pTree.Parent.DirDatCount>1: This should probably be a test like parent contains Dat
|
|
else if (pTree.Dat != null && pTree.Dat.AutoAddDirectory && pTree.Parent.DirDatCount > 1)
|
|
thistxt = pTree.Name + ": " + pTree.Dat.GetData(RvDat.DatData.Description) + " ( Have:" + pTree.DirStatus.CountCorrect() + " \\ Missing: " + pTree.DirStatus.CountMissing() + " )";
|
|
else if (pTree.Dat != null && pTree.DirDatCount == 0) // Directories made by a DAT
|
|
thistxt = pTree.Name + " ( Have:" + pTree.DirStatus.CountCorrect() + " \\ Missing: " + pTree.DirStatus.CountMissing() + " )";
|
|
else
|
|
{
|
|
ReportError.SendAndShow("Unknown Tree settings in DisplayTree.");
|
|
thistxt = "";
|
|
}
|
|
|
|
|
|
if (_lSelected != null && pTree.TreeFullName == _lSelected.TreeFullName)
|
|
{
|
|
g.FillRectangle(new SolidBrush(Color.FromArgb(51, 153, 255)), RSub(recBackGround, _hScroll, _vScroll));
|
|
g.DrawString(thistxt, new Font("Microsoft Sans Serif", 8), Brushes.White, pTree.Tree.RText.Left - _hScroll, pTree.Tree.RText.Top + 1 - _vScroll);
|
|
}
|
|
else
|
|
{
|
|
g.DrawString(thistxt, new Font("Microsoft Sans Serif", 8), Brushes.Black, pTree.Tree.RText.Left - _hScroll, pTree.Tree.RText.Top + 1 - _vScroll);
|
|
}
|
|
}
|
|
|
|
if (pTree.Tree.TreeExpanded)
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase tBase = pTree.Child(i);
|
|
if (tBase is RvDir)
|
|
{
|
|
RvDir tDir = (RvDir)tBase;
|
|
if (tDir.Tree != null)
|
|
PaintTree(tDir, g, t);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private static Rectangle RSub(Rectangle r, int h, int v)
|
|
{
|
|
Rectangle ret = new Rectangle(r.Left - h, r.Top - v, r.Width, r.Height);
|
|
return ret;
|
|
}
|
|
#endregion
|
|
|
|
#region"Mouse Events"
|
|
private bool _mousehit;
|
|
protected override void OnMouseDown(MouseEventArgs mevent)
|
|
{
|
|
int x = mevent.X + HorizontalScroll.Value;
|
|
int y = mevent.Y + VerticalScroll.Value;
|
|
|
|
if (_lTree != null)
|
|
for (int i = 0; i < _lTree.ChildCount; i++)
|
|
{
|
|
RvDir tDir = (RvDir)_lTree.Child(i);
|
|
if (tDir.Tree != null)
|
|
if (CheckMouseDown(tDir, x, y, mevent))
|
|
break;
|
|
}
|
|
|
|
if (!_mousehit) return;
|
|
|
|
SetupInt();
|
|
base.OnMouseDown(mevent);
|
|
}
|
|
|
|
public void SetSelected(RvDir selected)
|
|
{
|
|
bool found = false;
|
|
|
|
RvDir t = selected;
|
|
while (t != null)
|
|
{
|
|
if (t.Tree != null)
|
|
{
|
|
if (!found)
|
|
{
|
|
_lSelected = t;
|
|
found = true;
|
|
}
|
|
else
|
|
t.Tree.TreeExpanded = true;
|
|
}
|
|
t = t.Parent;
|
|
}
|
|
SetupInt();
|
|
}
|
|
|
|
public RvDir GetSelected()
|
|
{
|
|
return _lSelected;
|
|
}
|
|
|
|
private bool CheckMouseDown(RvDir pTree, int x, int y, MouseEventArgs mevent)
|
|
{
|
|
if (pTree.Tree.RChecked.Contains(x, y))
|
|
{
|
|
if (pTree.Tree.Checked == RvTreeRow.TreeSelect.Disabled)
|
|
return true;
|
|
|
|
_mousehit = true;
|
|
SetChecked(pTree, pTree.Tree.Checked == RvTreeRow.TreeSelect.Selected ? RvTreeRow.TreeSelect.UnSelected : RvTreeRow.TreeSelect.Selected);
|
|
return true;
|
|
}
|
|
|
|
if (pTree.Tree.RExpand.Contains(x, y))
|
|
{
|
|
_mousehit = true;
|
|
SetExpanded(pTree, mevent.Button == MouseButtons.Right);
|
|
return true;
|
|
}
|
|
|
|
if (pTree.Tree.RText.Contains(x, y))
|
|
{
|
|
_mousehit = true;
|
|
|
|
if (RvSelected != null)
|
|
RvSelected(pTree, mevent);
|
|
|
|
_lSelected = pTree;
|
|
return true;
|
|
}
|
|
|
|
if (pTree.Tree.TreeExpanded)
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase rBase = pTree.Child(i);
|
|
if (rBase is RvDir)
|
|
{
|
|
RvDir rDir = (RvDir)rBase;
|
|
if (rDir.Tree != null)
|
|
if (CheckMouseDown(rDir, x, y, mevent))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void SetChecked(RvDir pTree, RvTreeRow.TreeSelect nSelection)
|
|
{
|
|
pTree.Tree.Checked = nSelection;
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase b = pTree.Child(i);
|
|
if (b is RvDir)
|
|
{
|
|
RvDir d = (RvDir)b;
|
|
if (d.Tree != null)
|
|
{
|
|
SetChecked(d, nSelection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void SetExpanded(RvDir pTree, bool rightClick)
|
|
{
|
|
if (!rightClick)
|
|
{
|
|
pTree.Tree.TreeExpanded = !pTree.Tree.TreeExpanded;
|
|
return;
|
|
}
|
|
|
|
// Find the value of the first child node.
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase b = pTree.Child(i);
|
|
if (b is RvDir)
|
|
{
|
|
RvDir d = (RvDir)b;
|
|
if (d.Tree != null)
|
|
{
|
|
//Recusivly Set All Child Nodes to this value
|
|
SetExpandedRecurse(pTree, !d.Tree.TreeExpanded);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void SetExpandedRecurse(RvDir pTree, bool expanded)
|
|
{
|
|
for (int i = 0; i < pTree.ChildCount; i++)
|
|
{
|
|
RvBase b = pTree.Child(i);
|
|
if (b is RvDir)
|
|
{
|
|
RvDir d = (RvDir)b;
|
|
if (d.Tree != null)
|
|
{
|
|
d.Tree.TreeExpanded = expanded;
|
|
SetExpandedRecurse(d, expanded);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public RvBase Selected
|
|
{
|
|
get
|
|
{
|
|
return _lSelected;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|