/// <summary> /// Takes an XYItem (like (2,2) or a node) and tries to make it into a referenceable node /// (i.e, one with a name) /// /// Concretely, the routine does the following: /// - if item is a named node, return item. /// - if item is an unnamed node, give it a unique name and return item. /// - if item is a coordinate, see if there is a node at this coordinate /// (algorithm: see if next non-tikz_something item is a node) /// - if yes, start anew with item=this node /// - if no, add a named node at the specified coordinate /// </summary> /// <param name="item"></param> /// <returns></returns> protected Tikz_Node MakeReferenceableNode(Tikz_XYItem item) { Tikz_Picture tpict = overlay.ParseTree.GetTikzPicture(); if (item is Tikz_Node) { Tikz_Node n = item as Tikz_Node; if (n.name == "") { n.SetName(tpict.GetUniqueName()); n.UpdateText(); } return(n); } else if (item is Tikz_Coord) { // find the next node for (int i = item.parent.Children.IndexOf(item) + 1; i < item.parent.Children.Count; i++) { if (item.parent.Children[i] is Tikz_Node) { // check if the node is really at the same position as the coordinate item if ((item.parent.Children[i] as Tikz_Node).coord == null) { return(MakeReferenceableNode(item.parent.Children[i] as Tikz_Node)); } else { break; } } if (!(item.parent.Children[i] is Tikz_Something)) { break; } } // if we get here, nothing was found => add a new node Tikz_Something ws = new Tikz_Something(" "); Tikz_Node n = new Tikz_Node(); n.coord = null; item.parent.InsertChildAt(ws, item.parent.Children.IndexOf(item) + 1); item.parent.InsertChildAt(n, item.parent.Children.IndexOf(item) + 2); n.SetName(tpict.GetUniqueName()); n.UpdateText(); return(n); } else { throw new NotImplementedException("MakeReferenceableNode not implemented for this type"); } }
/// <summary> /// Recursive function to scan the parsetree in a depth first manner. /// nodelist contains the current map from _old_ nodenames to nodes. it is used to update node references /// </summary> private static void ScanTree(TikzContainerParseItem tc, Dictionary <string, Tikz_Node> nodelist, Tikz_Picture tp) { foreach (var tpi in tc.Children) { if (tpi is Tikz_Node) { Tikz_Node tn = tpi as Tikz_Node; if (tn.name != null && tn.name.Trim() != "") { string name = CleanName(tn.name.Trim()); // remember the node with its old name (all coordinates referring to this name henceforth will be changed to the new name nodelist[name] = tn; if (tp.nodelist.ContainsKey(name)) { // we have to change the name tn.name = UniquefyName(name, tp); tn.UpdateText(); } tn.RegisterNodeAndStyleRefs(); } } else if (tpi is Tikz_Coord) { Tikz_Coord tco = tpi as Tikz_Coord; if (tco.type == Tikz_CoordType.Named) { string nameref = CleanName(tco.nameref); if (nodelist.ContainsKey(nameref)) { if (CleanName(nodelist[nameref].name) != nameref) { tco.nameref = CleanName(nodelist[nameref].name); tco.UpdateText(); } } } } else if (tpi is TikzContainerParseItem) { ScanTree(tpi as TikzContainerParseItem, nodelist, tp); } } }
public void AssignStyle(AssignStyleType type) { string cStyle = NodeStyle; Tikz_Picture tp = ParseTree.GetTikzPicture(); if (tp == null) { return; } if (View.Tool != OverlayToolType.move) { return; // context menu should actually only open with move tool,... but to be safe against later changes... } if (type == AssignStyleType.AssignNewStyle || type == AssignStyleType.ChangeToNewStyle) { if (Overlay.InputMessageBox.ShowInputDialog("New style...", "Please enter a unique style name", out cStyle) != MessageBoxResult.OK) { return; } cStyle = cStyle.Trim(); // check if style name is valid and unique if (ParseTree == null || cStyle == "") { return; } if (ParseTree.styles.ContainsKey(cStyle)) { GlobalUI.ShowMessageBox("Error: Style name '" + cStyle + "' already exists.", "Style exists", MessageBoxButton.OK, MessageBoxImage.Warning); return; } // add new style, immediately before \begin{tikzpicture}[...] BeginUpdate(); Tikz_Option to = new Tikz_Option(); to.type = Tikz_OptionType.style; to.key = cStyle; to.val = ""; to.text = "\\tikzstyle{" + cStyle + "}=[];"; int index = ParseTree.Children.IndexOf(tp); if (index >= 0) { ParseTree.InsertChildAt(to, index); to.RegisterNodeAndStyleRefs(); ParseTree.InsertChildAt(new Tikz_Something(Environment.NewLine), index + 1); } } else { if (cStyle.Trim() == "") { return; } BeginUpdate(); } // loop through selected items and set styles foreach (OverlayShape ols in selectionTool.SelItems) { // currently only node styles can be set if (ols.item is Tikz_Node) { Tikz_Node tn = ols.item as Tikz_Node; if (tn.options == "" || type == AssignStyleType.ChangeToCurrentNodeStyle || type == AssignStyleType.ChangeToNewStyle) { tn.options = "[" + cStyle + "]"; } else // just add option { string o = tn.options.Trim(); if (o.EndsWith("]")) { o = o.Substring(0, o.Length - 1); o = o + ", " + cStyle + "]"; } // otherwise, do nothing (error) tn.options = o; } tn.UpdateText(); } } EndUpdate(); // Make sure EndUpdate() is always called (..if Beginupdate() was)! }