public static void onSelectObjectsFromHighlight(Object sender, ClickEventArgs e) { NlmTreeListView listView = e.ListView; MaxNodes.ClearNodeSelection(); IEnumerable <UIntPtr> handles = listView.NodeControl.Query.SelectionAndAllChildObjectHandles; MaxNodes.SelectNodes(handles); }
private void BuildChildObjects(LayerTreeNode layerTreeNode, IILayer maxLayer) { IEnumerable <IINode> layerNodes = MaxLayers.GetChildNodes(maxLayer); foreach (IINode maxNode in layerNodes) { UIntPtr iNodeHandle = MaxAnimatable.GetHandleByAnim(maxNode); ObjectTreeNode objectTreeNode = new ObjectTreeNode(MaxNodes.GetObjectClass(maxNode), iNodeHandle, HandleMap); ListView.NodeControl.Parent.AddChild(objectTreeNode, layerTreeNode, false); } }
private void onNodeCreated(object sender, SystemNotificationAnimEventArgs e) { #if DEBUG MaxListener.PrintToListener("onNodeCreated"); #endif try { ListView.BeginUpdate(); List <BaseTreeNode> refreshNodes = new List <BaseTreeNode>(); foreach (UIntPtr handle in e.Handles) { IAnimatable anim = MaxAnimatable.GetAnimByHandle(handle); if (anim == null) { return; } IINode node = anim as IINode; IILayer layer = MaxLayers.GetLayer(node); UIntPtr layerHandle = MaxAnimatable.GetHandleByAnim(layer); ObjectTreeNode.ObjectClass objectClass = MaxNodes.GetObjectClass(node); List <BaseTreeNode> layerTreeNodes = NodeControl.HandleMap.GetTreeNodesByHandle(layerHandle); foreach (BaseTreeNode layerTreeNode in layerTreeNodes) { ObjectTreeNode objectTreeNode = new ObjectTreeNode(objectClass, handle, NodeControl.HandleMap); NodeControl.Parent.AddChild(objectTreeNode, layerTreeNode, false); if (!refreshNodes.Contains(layerTreeNode)) { refreshNodes.Add(layerTreeNode); } } } MaxListener.PrintToListener(refreshNodes.Count.ToString()); ListView.RefreshObjects(refreshNodes); ListView.Sort(ListView.NlmColumns.NameColumn, SortOrder.Ascending); } catch { throw new Exception(); } finally { ListView.EndUpdate(); } }
public override void LayerChanged(ITab <UIntPtr> nodes) { #if DEBUG MaxListener.PrintToListener("NodeEventCallback > LayerChanged"); #endif List <BaseTreeNode> deleteNodes = new List <BaseTreeNode>(); List <Tuple <BaseTreeNode, BaseTreeNode> > addNodes = new List <Tuple <BaseTreeNode, BaseTreeNode> >(); for (int i = 0; i < nodes.Count; i++) { UIntPtr maxNodeHandle = nodes[(IntPtr)i]; IINode maxNode = MaxAnimatable.GetAnimByHandle(maxNodeHandle) as IINode; IILayer maxLayer = MaxLayers.GetLayer(maxNode); UIntPtr layerHandle = MaxAnimatable.GetHandleByAnim(maxLayer); // We need to handle the following scenarios: // An object being moved to another layer. // Objects on instances layers moving to uninstanced layers. // Objects on uninstanced layers moving to instanced layers. // The easiest way to do this is to remove old object nodes and create new ones. // This should be pretty fast, and this event should fire relatively rarely, // but it may have to be rethought if it's too slow. // First we remove the old nodes. List <BaseTreeNode> objectTreeNodes = NodeControl.HandleMap.GetTreeNodesByHandle(maxNodeHandle); deleteNodes.AddRange(objectTreeNodes); // Then we add the object node to the new layer. List <BaseTreeNode> layerTreeNodes = NodeControl.HandleMap.GetTreeNodesByHandle(layerHandle); foreach (BaseTreeNode layerTreeNode in layerTreeNodes) { ObjectTreeNode newObjectTreeNode = new ObjectTreeNode(MaxNodes.GetObjectClass(maxNode), maxNodeHandle, NodeControl.HandleMap); addNodes.Add(new Tuple <BaseTreeNode, BaseTreeNode> (newObjectTreeNode, layerTreeNode)); } } // And finally we actually do the update all at once. NodeControl.Destroy.DeleteTreeNodes(deleteNodes); foreach (Tuple <BaseTreeNode, BaseTreeNode> tuple in addNodes) { NodeControl.Parent.AddChild(tuple.Item1, tuple.Item2, false); } // And sort :) ListView.Sort(ListView.NlmColumns.NameColumn, SortOrder.Ascending); }
public static void onAddSelectedObjectsToLayer(Object sender, ClickEventArgs e) { // TODO: // This is quite slow compared to the NodeEventCallback LayerChanged. Look at that for tips. // Do we really need BeginUpdate and EndUpdate? Calculate which objects to refresh. // Also fix crappy bug where adding children to an expanded layer does not redraw properly. NlmTreeListView listView = e.ListView; try { listView.BeginUpdate(); IList selection = listView.SelectedObjects; if (selection.Count == 1) { LayerTreeNode layerTreeNode = selection[0] as LayerTreeNode; if (layerTreeNode != null) { List <BaseTreeNode> moveTreeNodes = new List <BaseTreeNode>(); IAnimatable layerAnim = MaxAnimatable.GetAnimByHandle(layerTreeNode.Handle); foreach (IINode maxNode in MaxNodes.SelectedNodes) { UIntPtr maxNodeHandle = MaxAnimatable.GetHandleByAnim(maxNode as IAnimatable); List <BaseTreeNode> treeNodes = listView.NodeControl.HandleMap.GetTreeNodesByHandle(maxNodeHandle); foreach (BaseTreeNode treeNode in treeNodes) { moveTreeNodes.Add(treeNode); } MaxNodes.MoveNodeToLayer(maxNode, layerAnim as IILayer); } listView.NodeControl.Parent.MoveTreeNodes(moveTreeNodes, layerTreeNode); } } listView.Sort(listView.NlmColumns.NameColumn, SortOrder.Ascending); } catch { throw new Exception(); } finally { e.ListView.EndUpdate(); } }
public void AddMissingChildObjects(IEnumerable <LayerTreeNode> layerNodes) { foreach (LayerTreeNode layerNode in layerNodes) { IILayer layer = MaxAnimatable.GetAnimByHandle(layerNode.Handle) as IILayer; IEnumerable <IINode> maxNodes = MaxLayers.GetChildNodes(layer); foreach (IINode maxNode in maxNodes) { UIntPtr iNodeHandle = MaxAnimatable.GetHandleByAnim(maxNode); // TODO: This needs to work with instanced layers. if (!HandleMap.ContainsHandle(iNodeHandle)) { ObjectTreeNode objectTreeNode = new ObjectTreeNode(MaxNodes.GetObjectClass(maxNode), iNodeHandle, HandleMap); objectTreeNode.Parent = layerNode; layerNode.Children.Add(objectTreeNode); } } } }
/// <summary> /// Returns the message to be displayed when a node publishing limit has been reached /// </summary> /// <returns></returns> public string GetMessage() { //Custom message overrides everything if (!string.IsNullOrEmpty(CustomMessage)) { return(CustomMessage); } //Return a standard message if this rule is created on the fly based on a special document property value if (FromProperty) { return(string.Format("Node saved but not published. Max allowed child nodes for this specific node: {0}.", MaxNodes.ToString())); } //This is the message that is returned when a rule is in the config file, and no custom message has been defined. return(string.Format( "Node saved but not published. Max allowed nodes {1} directly under {2}: {0}." , MaxNodes.ToString() , ChildDocType.Equals("*") ? "of any type" : string.Format("of type \"{0}\"", ChildDocType) , ParentDocType.Equals("*") ? "any node" : string.Format("nodes of type \"{0}\"", ParentDocType) )); }
/// <summary> /// Returns the warning message to be displayed on publishing a node when a rule is in effect but the limit has not been reached. /// </summary> /// <param name="currentNodeCount"></param> /// <returns></returns> public string GetWarningMessage(int currentNodeCount) { //Custom message overrides everything if (!string.IsNullOrEmpty(CustomWarningMessage)) { return(CustomWarningMessage); } //Return a standard message if this rule is created on the fly based on a special document property value if (FromProperty) { return(string.Format("Restrictions for this node are in place. You have published {0} out {1} allowed child nodes.", (currentNodeCount + 1).ToString(), MaxNodes.ToString())); } //This is the message that is returned when a rule is in the config file, and no custom message has been defined. return(string.Format( "Restrictions in place. {3} directly under {2}: {1} of {0} allowed." , MaxNodes.ToString() , (currentNodeCount + 1).ToString() , ParentDocType.Equals("*") ? "any node" : string.Format("nodes of type \"{0}\"", ParentDocType) , ChildDocType.Equals("*") ? "Any node" : string.Format("Nodes of type \"{0}\"", ChildDocType) )); }
// Move nodes to new parent after a drag drop operation. private void DragDropMoveNodes(BaseTreeNode target, IList dragNodes) { IList selection = ListView.SelectedObjects; ListView.BeginUpdate(); MaxEvents.NodeEvents.Unregister(); IEnumerable <BaseTreeNode> dragNodesEnum = dragNodes.Cast <BaseTreeNode>(); // Are layers or folders being dropped on layers? // If so, make the target the parent of the target. if (dragNodesEnum.All(x => x is LayerTreeNode) && target is LayerTreeNode || dragNodesEnum.All(x => x is FolderTreeNode) && target is LayerTreeNode) { target = target.Parent; } // Are objects being dropped on objects? // If so, make the target the parent of the target. if (dragNodesEnum.All(x => x is ObjectTreeNode) && target is ObjectTreeNode) { target = target.Parent; } // Do we move to the root or move under a treeNode? // If the target is null, we have to move to root. if (target != null && target is LayerTreeNode) { // Move the treenodes in the listView. NodeParentEngine.MoveTreeNodes(dragNodes.Cast <BaseTreeNode>().ToList(), target); //TODO: //IEnumerable<UIntPtr> handles = dragNodes.Cast<IEnumerable<BaseTreeNode>>() // .Where(x => x is ObjectTreeNode) // .Cast<ObjectTreeNode>() // .Select(x => x.Handle); // Move nodes to new layer in max. List <UIntPtr> handles = new List <UIntPtr>(); foreach (BaseTreeNode child in dragNodes) { ObjectTreeNode objectChild = child as ObjectTreeNode; if (objectChild != null) { handles.Add(objectChild.Handle); } } IILayer layer = MaxAnimatable.GetAnimByHandle(((LayerTreeNode)target).Handle) as IILayer; if (layer != null) { MaxNodes.MoveNodesToLayer(handles, layer); } } else { NodeParentEngine.MoveTreeNodes(dragNodes.Cast <BaseTreeNode>().ToList(), target); } MaxEvents.NodeEvents.Register(); // Default after drop behaviour tries to select nodes based on itemIndex. As nodes have moved this does not work. // Instead, return saved selection to SelectedObjects property, and make sure dropped Objects are visible. if (!ListView.IsExpanded(target)) { ListView.Expand(target); } ListView.Sort(ListView.NlmColumns.NameColumn, SortOrder.Ascending); ListView.SelectedObjects = selection; ListView.EndUpdate(); }
/// <summary> /// Deletes the selected treenodes, including associated max nodes. /// All children of selection are also deleted. /// Max nodes will not be deleted if not all instanced nodes are selected. /// If every layer 0 instance is selected, nothing will happen. /// </summary> public void DeleteSelection() { #if DEBUG System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); #endif ListView.NodeControl.MaxEvents.NodeEvents.Unregister(); ListView.NodeControl.MaxEvents.LayerEvents.LayerDeleted.UnregisterNotification(); // Don't do anything if every single layer 0 is selected. IILayer layer0 = MaxLayers.GetLayer(0); UIntPtr layer0handle = MaxAnimatable.GetHandleByAnim(layer0); List <BaseTreeNode> layerTreeNodes = HandleMap.GetTreeNodesByHandle(layer0handle); if (layerTreeNodes.All(x => NodeQuery.SelectionAndAllChildNodes.Contains(x))) { return; } // Collect the selection IEnumerables to use. HashSet <BaseTreeNode> selectionAndAllChildren = new HashSet <BaseTreeNode> (NodeQuery.SelectionAndAllChildNodes); // Calculate layer and object handles. IEnumerable <UIntPtr> objectHandles = selectionAndAllChildren.Where (x => x is ObjectTreeNode).Cast <ObjectTreeNode>().Select(x => x.Handle); IEnumerable <UIntPtr> layerHandles = selectionAndAllChildren.Where (x => x is LayerTreeNode).Cast <LayerTreeNode>().Select(x => x.Handle); // Delete handles from max. foreach (UIntPtr handle in objectHandles) { List <BaseTreeNode> instances = HandleMap.GetTreeNodesByHandle(handle); if (instances.Count() > 1) { if (!instances.All(x => selectionAndAllChildren.Contains(x))) { continue; } } MaxNodes.DeleteNode(handle); } foreach (UIntPtr handle in layerHandles) { List <BaseTreeNode> instances = HandleMap.GetTreeNodesByHandle(handle); if (instances.Count() > 1) { if (!instances.All(x => selectionAndAllChildren.Contains(x))) { continue; } } MaxLayers.DeleteLayer(handle); } // And now to delete the tree nodes now there are no max nodes. DeleteTreeNodes(selectionAndAllChildren); // The default behaviour of the listview is to maintain selection based on item index. // This is not very desirable, as the selection should be nothing. ListView.SelectedObjects = new Object[] {}; ListView.NodeControl.MaxEvents.LayerEvents.LayerDeleted.RegisterNotification(); ListView.NodeControl.MaxEvents.NodeEvents.Register(); #if DEBUG stopwatch.Stop(); MaxListener.PrintToListener("DeleteSelection completed in: " + stopwatch.ElapsedMilliseconds); #endif }