public static void AddOption(TikzContainerParseItem tcpi, Tikz_Option o) { if (tcpi.options == null) { Tikz_Options topts = new Tikz_Options(); tcpi.AddChild(topts, true); tcpi.options = topts; } tcpi.options.AddOption(o); }
public Tikz_Option AddOption(string key, string value) { Tikz_Option to = new Tikz_Option(); to.type = Tikz_OptionType.keyval; to.key = key; to.val = value; AddOption(to); return to; }
public void AddOption(Tikz_Option o) { if (OptionsCount() > 0) { Tikz_Something komma = new Tikz_Something(", "); AddChild(komma); } o.UpdateText(); AddChild(o); }
/// <summary> /// Same as above, but additionally the editable shift is returned. /// (or null if a new one needs to be created) /// </summary> /// <param name="ret"></param> /// <param name="EditableShift"></param> /// <returns></returns> bool GetTransformAtEditableShift(out TikzMatrix ret, out Tikz_Option EditableShift) { ret = new TikzMatrix(); // stores the coord trsf. at current position EditableShift = null; if (!parent.GetCurrentTransformAt(this, out ret)) return false; //bool foundone = false; foreach (TikzParseItem tpi in Children) { if (tpi is Tikz_Option) { Tikz_Option to = tpi as Tikz_Option; if (to.type == Tikz_OptionType.keyval && to.key.Trim() == "shift") { if (to.coordval == null) return false; if (to.coordval.type == Tikz_CoordType.Cartesian) { // we found one (yoohoo) EditableShift = to; return true; } } if (!TransformFromOption(to, ret, out ret)) return false; // invalid coord trafo encountered -> report failure } } EditableShift = null; // nothing found -> return null return true; }
public Tikz_Option AddOption(string key) { Tikz_Option to = new Tikz_Option(); to.type = Tikz_OptionType.key; to.key = key; AddOption(to); return to; }
/// <summary> /// Returns the coordinate transfor corresponding to an option, if possible. /// If the option is not relevant for coordinate tranformation (or not supported), true is returned /// and newTrafo = oldTrafo. If the option is recognized, but the value cannot be determined, /// false is returned and newTrafo shouldn't be used. /// </summary> /// <param name="to"></param> /// <param name="oldTrafo"></param> /// <param name="newTrafo"></param> /// <returns></returns> bool TransformFromOption(Tikz_Option to, TikzMatrix oldTrafo, out TikzMatrix newTrafo) { TikzMatrix ret = new TikzMatrix(); newTrafo = ret; if (to.type == Tikz_OptionType.keyval) { switch (to.key.Trim()) { case "xscale": if (to.numval == null) return false; ret.m[0, 0] = to.numval.GetInCM(); break; case "yscale": if (to.numval == null) return false; ret.m[1, 1] = to.numval.GetInCM(); break; case "scale": if (to.numval == null) return false; ret.m[0, 0] = to.numval.GetInCM(); ret.m[1, 1] = ret.m[0, 0]; break; case "xshift": if (to.numval == null) return false; ret.m[0, 2] = to.numval.GetInCM("pt"); break; case "yshift": if (to.numval == null) return false; ret.m[1, 2] = to.numval.GetInCM("pt"); break; case "shift": // shift is complicated..... if (to.coordval == null) return false; if (to.coordval.type == Tikz_CoordType.Named) { // for named coord, shift sets the _absolute_ origin of the coord system // hence we need the absolute coord trafo at the current point! Point neworig; if (!to.coordval.GetAbsPos(out neworig, this)) return false; TikzMatrix Mabs; if (!parent.GetCurrentTransformAt(this, out Mabs)) return false; Mabs = Mabs * oldTrafo; Point theshift = Mabs.Inverse().Transform(neworig); ret.m[0, 2] = theshift.X; ret.m[1, 2] = theshift.Y; } else if (to.coordval.type == Tikz_CoordType.Cartesian || to.coordval.type == Tikz_CoordType.Polar) { Point p = to.coordval.GetCartesian(); ret.m[0, 2] = p.X; ret.m[1, 2] = p.Y; } else { // invalid coordinate value return false; } break; case "rotate": if (to.numval == null) return false; double angle = to.numval.GetInCM() * 2* Math.PI / 360; ret.m[0, 0] = Math.Cos(angle); ret.m[1, 0] = Math.Sin(angle); ret.m[0, 1] = -Math.Sin(angle); ret.m[1, 1] = Math.Cos(angle); break; case "xslant": if (to.numval == null) return false; double amount = to.numval.GetInCM(); ret.m[0, 0] = 1; ret.m[1, 0] = 0; ret.m[0, 1] = amount; ret.m[1, 1] = 1; break; case "yslant": if (to.numval == null) return false; amount = to.numval.GetInCM(); ret.m[0, 0] = 1; ret.m[1, 0] = amount; ret.m[0, 1] = 0; ret.m[1, 1] = 1; break; default: // option not relevant for coordinate computation (or not supported) -> ignore newTrafo = oldTrafo; return true; } } // if we get here, the option was recognized as relevant for coordinate transf., and the value could be read newTrafo = oldTrafo * ret; return true; }
/// <summary> /// Adds the specified amounts to the current xshift and yshift. /// Note that this might be complicated since the coord transf. can be encoded as, e.g. /// [xshift=1cm, scale=2, xshift=-3cm, scale=-1, shift={(45:1)}] /// Which shift should we change? Where should we insert a yshift? /// /// The policy is as follows: /// (i) change the first occuring _cartesian_ "shift=..." item if present. /// (ii) if not present, add a shift=... to the end. /// /// Keep in mind that we also want to support rotations.... /// Todo: check whether ambient coord transform is taken into account... /// </summary> /// <param name="xshift"></param> /// <param name="yshift"></param> public void SetShiftRel(double xshift, double yshift) { TikzMatrix curTrafo; Tikz_Option EditableShift; if (!GetTransformAtEditableShift(out curTrafo, out EditableShift)) return; if (EditableShift == null) { // We need to add a new shift=... option Point theshift = curTrafo.Inverse().Transform(new Point(xshift, yshift), true); Tikz_Option topt = new Tikz_Option(); topt.type = Tikz_OptionType.keyval; topt.key = "shift"; topt.coordval = new Tikz_Coord(); topt.coordval.type = Tikz_CoordType.Cartesian; topt.coordval.SetCartesian(theshift.X, theshift.Y); AddOption(topt); } else { // We already have a suitable shift=... -option, add shift Point oldshift = EditableShift.coordval.GetCartesian(); Point shifttoadd = curTrafo.Inverse().Transform(new Point(xshift, yshift), true); EditableShift.coordval.SetCartesian(oldshift.X + shifttoadd.X, oldshift.Y + shifttoadd.Y); EditableShift.UpdateText(); return; } /*= new TikzMatrix(); // stores the coord trsf. at current position if (!parent.GetCurrentTransformAt(this, out curTrafo)) return; //bool foundone = false; foreach (TikzParseItem tpi in Children) { if (tpi is Tikz_Option) { Tikz_Option to = tpi as Tikz_Option; if (to.type == Tikz_OptionType.keyval && to.key.Trim() == "shift") { if (to.coordval == null) return; if (to.coordval.type == Tikz_CoordType.Cartesian) { // we found one (yoohoo), set the shift accordingly and exit Point oldshift = to.coordval.GetCartesian(); Point shifttoadd = curTrafo.Inverse().Transform(new Point(xshift, yshift), true); to.coordval.SetCartesian(oldshift.X + shifttoadd.X, oldshift.Y + shifttoadd.Y); to.UpdateText(); return; } } if (!TransformFromOption(to, curTrafo, out curTrafo)) return; // invalid coord trafo encountered -> do nothing } } */ // When we get here, nothing was found -> add new shift=... at the end //if (!foundone) //{ //} /*if (xshift != 0) { Tikz_Option o = GetOption("xshift", Tikz_OptionType.keyval); if (o == null) { o = new Tikz_Option(); o.type = Tikz_OptionType.keyval; o.key = "xshift"; o.numval = new Tikz_NumberUnit(); o.numval.unit = "cm"; o.numval.SetInCM(xshift); AddOption(o); } else { o.numval.SetInCM(o.numval.GetInCM() + xshift, "pt"); o.UpdateText(); } } if (yshift != 0) { Tikz_Option o = GetOption("yshift", Tikz_OptionType.keyval); if (o == null) { o = new Tikz_Option(); o.type = Tikz_OptionType.keyval; o.key = "yshift"; o.numval = new Tikz_NumberUnit(); o.numval.unit = "cm"; o.numval.SetInCM(yshift); AddOption(o); } else { o.numval.SetInCM(o.numval.GetInCM() + yshift, "pt"); o.UpdateText(); } } */ }
public Tikz_NumberUnit numval; // only one of val, numval, coordval should be not null /* public static string GetID(ITree t) { if (t.ChildCount <= 0) return ""; string s = ""; for (int i=0;i<t.ChildCount;i++) s = s + " " + t.GetChild(i).Text; return s.Remove(0,1); // remove leading space } */ public static Tikz_Option FromCommonTree(ITree t, CommonTokenStream tokens) { Tikz_Option to = new Tikz_Option(); switch (t.Type) { case simpletikzParser.IM_OPTION_KV: if (t.ChildCount == 1) { to.type = Tikz_OptionType.key; to.key = TikzParser.getTokensString(tokens, t.GetChild(0)); return to; } else if (t.ChildCount == 2) { to.type = Tikz_OptionType.keyval; to.key = TikzParser.getTokensString(tokens, t.GetChild(0)); if (t.GetChild(1).Type == simpletikzParser.IM_NUMBERUNIT) to.numval = new Tikz_NumberUnit(t.GetChild(1)); else if (t.GetChild(1).Type == simpletikzParser.IM_COORD) to.coordval = Tikz_Coord.FromCommonTree(t.GetChild(1), tokens); else to.val = TikzParser.getTokensString(tokens, t.GetChild(1)); return to; } else { throw new Exception("The parser seems to have returned an invalid parsetree: invalid number of children of IM_OPTION_KV node"); //return null; } case simpletikzParser.IM_OPTION_STYLE: if (t.ChildCount < 1) return null; else { to.type = Tikz_OptionType.style; to.key = TikzParser.getTokensString(tokens, t.GetChild(0)); to.val = "";// GetID(t.GetChild(1)); // hack return to; } case simpletikzParser.IM_STYLE: to.type = Tikz_OptionType.style; to.key = TikzParser.getTokensString(tokens, t.GetChild(0)); to.val = t.GetChild(1).Text; // hack,... but irrelevant return to; default: return null; // error } }
/// <summary> /// This is called by child-nodes in the parse-tree, in response to a call of RegisterNodeAndStyleRefs(). /// </summary> /// <param name="to">The Tikz_Option representing a style that wants to register itself in the list.</param> public override void AddStyleRef(Tikz_Option to) { string CleanKey = TikzParseTreeHelper.CleanName(to.key); if (!styles.ContainsKey(CleanKey)) styles[CleanKey] = to; }
/// <summary> /// Called in repsonse to Registernoderefs by its children /// </summary> /// <param name="tn"></param> public virtual void AddStyleRef(Tikz_Option to) { if (parent != null) parent.AddStyleRef(to); }
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)! }
//create a new CurAddTo (even though their already might be one) //(needed for edge tool) protected virtual bool AddNewCurAddTo() { // find tikzpicture Tikz_Picture tpict = overlay.ParseTree.GetTikzPicture(); if (tpict == null) return false; Parser.Tikz_Path tp = new Parser.Tikz_Path(); tp.starttag = @"\draw "; tp.endtag = ";"; if (overlay.EdgeStyle != "") { Parser.Tikz_Options topt = new Parser.Tikz_Options(); topt.starttag = "["; topt.endtag = "]"; Parser.Tikz_Option to = new Parser.Tikz_Option(); to.type = Parser.Tikz_OptionType.key; to.key = overlay.EdgeStyle; topt.AddOption(to); tp.AddChild(topt); tp.options = topt; } if (overlay.CurEditing != null) { overlay.CurEditing.tikzitem.AddChild(tp); overlay.CurEditing.tikzitem.AddChild(new Parser.Tikz_Something("\r\n")); } else { tpict.AddChild(tp); tpict.AddChild(new Parser.Tikz_Something("\r\n")); } curAddTo = tp; return true; }