using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using FastReport.Utils;
using FastReport.Controls;
namespace FastReport.Design.ToolWindows
{
///
/// Represents the "Report Tree" window.
///
public class ReportTreeWindow : FilterableToolWindow
{
#region Fields
//private TreeView tree;
private Button collapseExpButton = new Button();
private List components;
private List nodes;
private List nodesSelected;
private TreeNode nodeTree;
private int lastFromitem;
private int lastToitem;
private bool lastNeedReverse;
private bool updating;
private bool LastData;
private bool passSelection = false;
private bool cancelNextSelection = false;
private bool ShiftNonSelect = false;
private bool RewriteSelect = false;
private bool mouseButtonRight = false;
#endregion
#region Private Methods
protected override void UpdateTree()
{
// if there was no changes in the report structure, do nothing
if (Designer.ActiveReport != null && tree.Nodes.Count > 0)
{
if (CheckChanges(Designer.ActiveReport, tree.Nodes[0]))
return;
}
updating = true;
tree.BeginUpdate();
tree.Nodes.Clear();
components.Clear();
nodes.Clear();
if (Designer.ActiveReport != null)
EnumComponents(Designer.ActiveReport, tree.Nodes);
tree.ExpandAll();
tree.EndUpdate();
updating = false;
}
private void UpdateSelection()
{
if (updating)
return;
if (Designer.SelectedObjects == null || Designer.SelectedObjects.Count == 0)
return;
Base c = Designer.SelectedObjects[Designer.SelectedObjects.Count - 1];
int i = components.IndexOf(c);
if (i != -1)
{
unpaintSelectedNodes();
updating = true;
tree.SelectedNode = nodes[i];
nodesSelected.Clear();
foreach (Base b in Designer.SelectedObjects)
{
nodesSelected.Add(nodes[components.IndexOf(b)]);
}
updating = false;
paintSelectedNodes();
}
}
void paintSelectedNodes()
{
Color backColor = SystemColors.Highlight;
Color foreColor = SystemColors.HighlightText;
foreach (TreeNode node in nodesSelected)
{
node.BackColor = backColor;
node.ForeColor = foreColor;
}
}
void unpaintSelectedNodes()
{
foreach (TreeNode node in nodesSelected)
{
node.BackColor = tree.BackColor;
node.ForeColor = tree.ForeColor;
}
}
private void EnumComponents(Base rootComponent, TreeNodeCollection rootNode)
{
string name = rootComponent is Report ?
"Report - " + Designer.ActiveReportTab.ReportName : rootComponent.Name;
TreeNode node = rootNode.Add(name);
node.Tag = rootComponent;
components.Add(rootComponent);
nodes.Add(node);
ObjectInfo objItem = RegisteredObjects.FindObject(rootComponent);
if (objItem != null)
{
int imageIndex = objItem.ImageIndex;
node.ImageIndex = imageIndex;
node.SelectedImageIndex = imageIndex;
}
if (rootComponent.HasFlag(Flags.CanShowChildrenInReportTree))
{
foreach (Base component in rootComponent.ChildObjects)
EnumComponents(component, node.Nodes);
}
}
private bool CheckChanges(Base rootComponent, TreeNode rootNode)
{
if (rootNode.Tag != rootComponent)
return false;
if (!(rootComponent is Report))
{
if (rootNode.Text != rootComponent.Name)
return false;
}
if (!rootComponent.HasFlag(Flags.CanShowChildrenInReportTree))
return true;
ObjectCollection childObjects = rootComponent.ChildObjects;
if (childObjects.Count != rootNode.Nodes.Count)
return false;
for (int i = 0; i < childObjects.Count; i++)
{
if (!CheckChanges(childObjects[i], rootNode.Nodes[i]))
return false;
}
return true;
}
private void tree_AfterSelect(object sender, TreeViewEventArgs e)
{
if (passSelection)
return;
if (updating)
return;
if (Designer.SelectedObjects != null)
{
if (Control.ModifierKeys == Keys.Control && !mouseButtonRight)
{
if (Designer.SelectedObjects[0] is BandBase || Designer.SelectedObjects[0] is ReportPage)
{
Designer.SelectedObjects.Clear();
}
if (Designer.SelectedObjects.Contains(e.Node.Tag as Base))
{
Designer.SelectedObjects.Remove(e.Node.Tag as Base);
LastData = false;
Designer.SelectionChanged(this);
UpdateSelection();
return;
}
else
{
if (e.Node.Tag is BandBase)
{
return;
}
Designer.SelectedObjects.Add(e.Node.Tag as Base);
nodeTree = e.Node;
LastData = false;
Designer.SelectionChanged(this);
UpdateSelection();
return;
}
}
Base c = e.Node.Tag as Base;
if (Control.ModifierKeys == Keys.Shift)
{
if (nodeTree != null && isSameLevel(nodeTree, e.Node))
{
List nodeBas = nodes;
int nodeTreeIndex = getNodeIndexInNodes(nodeTree);
int eNodeTreeIndex = getNodeIndexInNodes(e.Node);
int from = Math.Min(nodeTreeIndex, eNodeTreeIndex);
int to = Math.Max(nodeTreeIndex, eNodeTreeIndex);
bool needReverse = nodeTreeIndex > eNodeTreeIndex;
if (!(c is Report))
Designer.ActiveReportTab.ActivePage = c.Page;
if (RewriteSelect)
{
Designer.SelectedObjects.Clear();
RewriteSelect = false;
}
if (from == lastFromitem && LastData)
{
if (to < lastToitem)
{
Designer.SelectedObjects.Clear();
for (int i = from; i <= to; i++)
{
if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
{
continue;
}
Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
}
}
else
{
for (int i = lastToitem + 1; i <= to; i++)
{
if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
{
continue;
}
Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
}
}
}
if (to == lastToitem && LastData)
{
if (needReverse)
{
if (from > lastFromitem)
{
Designer.SelectedObjects.Clear();
for (int i = to; i >= from; i--)
{
if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
{
continue;
}
Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
}
}
else
{
for (int i = lastFromitem - 1; i >= from; i--)
{
if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
continue;
Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
}
}
}
}
if (LastData == false || lastNeedReverse != needReverse)
{
Designer.SelectedObjects.Clear();
if (needReverse)
{
for (int i = to; i >= from; i--)
{
if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
continue;
Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
}
}
else
{
for (int i = from; i <= to; i++)
{
if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
continue;
Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
}
}
}
if (Designer.SelectedObjects.Count == 0)
{
Designer.SelectedObjects.Add(nodeTree.Tag as Base);
tree.SelectedNode = nodeTree;
RewriteSelect = true;
}
LastData = true;
lastFromitem = from;
lastToitem = to;
lastNeedReverse = needReverse;
tree.SelectedNode = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 1]))];
Designer.SelectionChanged(this);
UpdateSelection();
}
}
else
{
LastData = false;
updating = true;
if (!(c is Report))
Designer.ActiveReportTab.ActivePage = c.Page;
updating = false;
nodeTree = e.Node;
Designer.SelectedObjects.Clear();
Designer.SelectedObjects.Add(c);
Designer.SelectionChanged(null);
}
}
}
private int getNodeIndexInNodes(TreeNode node1)
{
int i = 0;
foreach (TreeNode itemNode in nodes)
{
if (itemNode == node1)
{
return i;
}
i++;
}
return 0;
}
private bool isSameLevel(TreeNode node1, TreeNode node2)
{
foreach (TreeNode element in nodes)
{
if (element == node2)
{
return true;
}
}
return false;
}
private void tree_ItemDrag(object sender, ItemDragEventArgs e)
{
SelectedObjectCollection draggedComponent = Designer.SelectedObjects;
foreach (Base itemDragComp in draggedComponent)
{
if (itemDragComp is ComponentBase &&
(itemDragComp.IsAncestor || itemDragComp.HasFlag(Flags.CanChangeParent)))
{
tree.DoDragDrop(draggedComponent, DragDropEffects.Move);
}
else
{
tree.DoDragDrop(draggedComponent, DragDropEffects.None);
}
}
}
private void tree_DragDrop(object sender, DragEventArgs e)
{
TreeNode targetNode = tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y)));
Base targetComponent = targetNode.Tag as Base;
// cases:
// - target can contain dragged. Just change parent.
// - target cannot contain dragged. Change creation order (Z-order).
foreach (Base item in Designer.SelectedObjects)
{
if (targetComponent is IParent && (targetComponent as IParent).CanContain(item))
{
item.Parent = targetComponent;
}
else
{
Base parent = targetComponent.Parent;
item.Parent = parent;
item.ZOrder = targetComponent.ZOrder;
}
}
// update all designer plugins (this one too)
Designer.SetModified(null, "ChangeParent");
Base b = Designer.SelectedObjects[Designer.SelectedObjects.Count - 1];
int i = components.IndexOf(b);
nodeTree = nodes[i];
UpdateSelection();
}
private void tree_DragOver(object sender, DragEventArgs e)
{
List draggedNode = (List)e.Data.GetData(typeof(List));
TreeNode targetNode = (tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y))));
if (targetNode == null)
{
return;
}
SelectedObjectCollection draggedComponent = Designer.SelectedObjects;
Base targetComponent = targetNode.Tag as Base;
// allowed moves are:
// - target is not dragged
// - target is not child of dragged
// - target can contain dragged, or
// parent of target can contain dragged
foreach (Base itemDragComp in draggedComponent)
{
if (itemDragComp != targetComponent &&
!targetComponent.HasParent(itemDragComp) &&
(((targetComponent is IParent) && (targetComponent as IParent).CanContain(itemDragComp) ||
(targetComponent.Parent != null && (targetComponent.Parent as IParent).CanContain(itemDragComp)))))
{
e.Effect = e.AllowedEffect;
}
else
{
e.Effect = DragDropEffects.None;
}
}
// disable the Designer.OnSelectionChanged
updating = true;
tree.SelectedNode = targetNode;
updating = false;
}
private void tree_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
Designer.cmdDelete.Invoke();
}
private void tree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
{
if (Designer.SelectedObjects.Count == 1 && Control.ModifierKeys == Keys.None)
{
Base c = e.Node.Tag as Base;
if (c is Report)
e.CancelEdit = false;
}
else
{
e.CancelEdit = true;
}
}
private void tree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
if (Designer.SelectedObjects.Count == 1 && Control.ModifierKeys == Keys.None)
{
if (e.Label != null)
{
Base c = e.Node.Tag as Base;
string saveName = c.Name;
try
{
c.Name = e.Label;
Designer.SetModified(this, "Change");
}
catch (Exception ex)
{
FRMessageBox.Error(ex.Message);
e.CancelEdit = true;
}
}
}
else
{
e.CancelEdit = true;
}
}
private void FTree_MouseUp(object sender, TreeNodeMouseClickEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
mouseButtonRight = true;
}
else
{
mouseButtonRight = false;
}
if (Control.ModifierKeys == Keys.Control && e.Button != MouseButtons.Right)
{
if (e.Node.Tag is BandBase || e.Node.Tag is ReportPage || e.Node.Tag is Report)
{
ShiftNonSelect = true;
Designer.SelectionChanged(this);
UpdateSelection();
cancelNextSelection = true;
return;
}
if (tree.SelectedNode == e.Node && Designer.SelectedObjects.Count > 1 && Designer.SelectedObjects.Contains(e.Node.Tag as Base))
{
passSelection = true;
tree.SelectedNode = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 2]))];
nodeTree = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 2]))];
LastData = false;
passSelection = false;
Designer.SelectedObjects.Remove(e.Node.Tag as Base);
Designer.SelectionChanged(this);
UpdateSelection();
cancelNextSelection = true;
}
return;
}
else
{
if (Designer.SelectedObjects.Count > 1 && e.Node == tree.SelectedNode && e.Button != MouseButtons.Right)
{
Designer.SelectedObjects.Clear();
Designer.SelectedObjects.Add(e.Node.Tag as Base);
nodeTree = e.Node;
LastData = false;
Designer.SelectionChanged(null);
UpdateSelection();
}
}
if (e.Button == MouseButtons.Right)
{
tree.SelectedNode = tree.GetNodeAt(e.Location);
if (tree.SelectedNode != null)
{
ContextMenuBase menu = (tree.SelectedNode.Tag as Base).GetContextMenu();
if (menu != null)
{
menu.Show(tree, e.Location);
}
}
}
}
private void tree_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if (updating || passSelection)
return;
if (cancelNextSelection)
{
e.Cancel = true;
cancelNextSelection = false;
return;
}
if (Control.ModifierKeys == Keys.Control && Designer.SelectedObjects.Contains(e.Node.Tag as Base) && !ShiftNonSelect)
{
e.Cancel = true;
Designer.SelectedObjects.Remove(e.Node.Tag as Base);
Designer.SelectionChanged(null);
UpdateSelection();
return;
}
}
#endregion
#region Public Methods
///
public override void SelectionChanged()
{
UpdateSelection();
}
///
public override void UpdateContent()
{
UpdateTree();
UpdateSelection();
}
///
public override void Localize()
{
base.Localize();
Text = Res.Get("Designer,ToolWindow,ReportTree");
}
///
public override void UpdateDpiDependencies()
{
base.UpdateDpiDependencies();
Image = Designer.GetImage(189);
tree.ImageList = Designer.GetImages();
#if !MONO
ImageIndex = 189;
#endif
}
#endregion
///
/// Initializes a new instance of the class with default settings.
///
/// The report designer.
public ReportTreeWindow(Designer designer) : base(designer)
{
Name = "ReportTreeWindow";
components = new List();
nodes = new List();
nodesSelected = new List();
tree.ShowRootLines = false;
tree.HideSelection = true;
tree.LabelEdit = true;
tree.AllowDrop = true;
tree.AfterSelect += tree_AfterSelect;
tree.BeforeSelect += tree_BeforeSelect;
tree.ItemDrag += tree_ItemDrag;
tree.DragOver += tree_DragOver;
tree.DragDrop += tree_DragDrop;
tree.KeyDown += tree_KeyDown;
tree.BeforeLabelEdit += tree_BeforeLabelEdit;
tree.AfterLabelEdit += tree_AfterLabelEdit;
tree.NodeMouseClick += FTree_MouseUp;
Localize();
UpdateDpiDependencies();
}
}
}