/// <summary> /// Vykreslí tuto jednu linku /// </summary> /// <param name="e">Data pro kreslení</param> /// <param name="mode">Důvody zobrazení</param> /// <param name="ratio">Poměr průhlednosti: hodnota v rozsahu 0.0 (neviditelná) - 1.0 (plná barva)</param> internal void Draw(GInteractiveDrawArgs e, TimeGraphLinkMode mode, float ratio) { if (this.IsLinkTypeVisible) { if (this.LinkCenter) { this.DrawCenter(e, mode, ratio); } else { this.DrawPrevNext(e, mode, ratio); } } }
/// <summary> /// Vykreslí přímou linku nebo křivku Prev.Center to Next.Center /// </summary> /// <param name="e">Data pro kreslení</param> /// <param name="mode">Důvody zobrazení</param> /// <param name="ratio">Poměr průhlednosti: hodnota v rozsahu 0.0 (neviditelná) - 1.0 (plná barva)</param> protected void DrawCenter(GInteractiveDrawArgs e, TimeGraphLinkMode mode, float ratio) { TimeGraph graph = (this.ItemNext != null ? this.ItemNext.Graph : (this.ItemPrev != null ? this.ItemPrev.Graph : null)); RelationState relationState = GetRelationState(this.ItemPrev, this.ItemNext); Color color1 = this.GetColorForState(relationState, graph); Point?prevPoint = GetPoint(this.ItemPrev, RectangleSide.CenterX | RectangleSide.CenterY, true, false); Point?nextPoint = GetPoint(this.ItemNext, RectangleSide.CenterX | RectangleSide.CenterY, true, false); if (!(prevPoint.HasValue && nextPoint.HasValue)) { return; } Painter.DrawLinkLine(e.Graphics, prevPoint.Value, nextPoint.Value, color1, this.LinkWidth, System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.LineCap.ArrowAnchor, ratio); }
/// <summary> /// Za pomoci datového zdroje <see cref="LinkDataSource"/> získá vztahy (linky) pro daný režim, a zajistí jejich zobrazení. /// Je voláno po změně režimu <see cref="CurrentLinksMode"/>, a explicitně z metody <see cref="ReloadLinks()"/>. /// </summary> /// <param name="clear">Nulovat aktuální soupis linků?</param> /// <param name="linksMode">Režim pro zobrazení nových linků</param> protected void ReadLinksForMode(bool clear, TimeGraphLinkMode linksMode) { if (clear) { this.Clear(); } ITimeGraphLinkDataSource linkDataSource = this.LinkDataSource; if (linkDataSource == null) { return; } TimeGraphLinkMode itemMode = linksMode; if (linksMode.HasFlag(TimeGraphLinkMode.Allways)) { itemMode = TimeGraphLinkMode.Allways; } CreateAllLinksArgs args = null; if (linkDataSource != null) { // Tato varianta nemusí řešit režim Linků GTimeGraphLinkMode.MouseOver, protože linky MouseOver naskočí samy při pohybu myši :-). // Primárně jde o rozlišení Allways / Selected / None: if (linksMode.HasFlag(TimeGraphLinkMode.Allways)) { args = new CreateAllLinksArgs(TimeGraphLinkMode.Allways); linkDataSource.CreateLinks(args); } else if (linksMode.HasFlag(TimeGraphLinkMode.Selected)) { if (this.Host != null && this.Host.Selector != null) { args = new CreateAllLinksArgs(TimeGraphLinkMode.Selected, this.Host.Selector.SelectedItems); linkDataSource.CreateLinks(args); } } } if (args != null && args.Links.Count > 0) { this.AddLinks(args.Links, itemMode); } }
/// <summary> /// Metoda vrací poměr průhlednosti pro daný režim linku. /// Průhlednost Linku = hodnota v rozsahu 0.0 (neviditelná) - 1.0 (plná barva). /// Na hodnoty průhlednosti má vliv i aktuální režim <see cref="CurrentLinksMode"/>. /// </summary> /// <param name="itemLinkMode"></param> /// <returns></returns> internal float GetVisibleRatioForMode(TimeGraphLinkMode itemLinkMode) { bool isMouseOver = itemLinkMode.HasFlag(TimeGraphLinkMode.MouseOver); TimeGraphLinkMode currentMode = this.CurrentLinksMode; if (currentMode.HasFlag(TimeGraphLinkMode.Allways)) { // Pokud aktuálně vidím všechny Linky, tak budu ignorovat bit Selected, a použiju dvě úrovně průhlednosti - podle přítomnosti myši nad prvkem: return(isMouseOver ? LinkVisibleRatioAllwaysWithMouse : LinkVisibleRatioAllwaysStandard); } // Nejsou zapnuty všechny linky dle režimu, tedy zobrazuji jen Linky pro prvky Selected + MouseOver: bool isSelected = itemLinkMode.HasFlag(TimeGraphLinkMode.Selected); return(isSelected ? (isMouseOver ? LinkVisibleRatioSelectedWithMouse : LinkVisibleRatioSelectedStandard) : (isMouseOver ? LinkVisibleRatioOnlyWithMouse : LinkVisibleRatioNone)); }
/// <summary> /// Vykreslí přímou linku nebo S křivku { Prev.End to Next.Begin } /// </summary> /// <param name="e">Data pro kreslení</param> /// <param name="mode">Důvody zobrazení</param> /// <param name="ratio">Poměr průhlednosti: hodnota v rozsahu 0.0 (neviditelná) - 1.0 (plná barva)</param> protected void DrawPrevNext(GInteractiveDrawArgs e, TimeGraphLinkMode mode, float ratio) { TimeGraph graph = (this.ItemNext != null ? this.ItemNext.Graph : (this.ItemPrev != null ? this.ItemPrev.Graph : null)); RelationState relationState = GetRelationState(this.ItemPrev, this.ItemNext); Color color1 = this.GetColorForState(relationState, graph); Point?prevPoint = GetPoint(this.ItemPrev, RectangleSide.MiddleRight, true, true); Point?nextPoint = GetPoint(this.ItemNext, RectangleSide.MiddleLeft, true, true); LinkLineType lineType = this.CurrentLineShape; float? treshold = 4f * (float)(this.LinkWidth.HasValue ? this.LinkWidth.Value : 3); using (System.Drawing.Drawing2D.GraphicsPath graphicsPath = Painter.CreatePathLink(lineType, prevPoint, nextPoint, treshold)) { bool useRoundAnchor = (lineType == LinkLineType.ZigZagHorizontal || lineType == LinkLineType.ZigZagVertical || lineType == LinkLineType.ZigZagOptimal); System.Drawing.Drawing2D.LineCap startCap = (useRoundAnchor ? System.Drawing.Drawing2D.LineCap.RoundAnchor : System.Drawing.Drawing2D.LineCap.Round); System.Drawing.Drawing2D.LineCap endCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; Painter.DrawLinkPath(e.Graphics, graphicsPath, color1, null, this.LinkWidth, startCap, endCap, ratio); } }
/// <summary> /// Odebere dané linky z paměti, pokud v ní jsou a pokud již neexistuje důvod pro jejich zobrazování. /// Důvod zobrazení: každý link v sobě eviduje souhrn důvodů, pro které byl zobrazen (metoda <see cref="AddLinks(IEnumerable{TimeGraphLinkItem}, TimeGraphLinkMode)"/>), /// důvody z opakovaných volání této metody se průběžně sčítají, a při odebírání se odečítají. /// A až tam nezbyde žádný, bude link ze seznamu odebrán. /// </summary> /// <param name="links">Souhrn linků k odebrání</param> /// <param name="mode">Důvod, pro který byl link zobrazen</param> public void RemoveLinks(IEnumerable <TimeGraphLinkItem> links, TimeGraphLinkMode mode) { if (links == null) { return; } if (mode == TimeGraphLinkMode.None) { return; } bool repaint = false; TimeGraphLinkMode reMode = TimeGraphLinkMode.All ^ mode; // reMode nyní obsahuje XOR požadovanou hodnotu, použije se pro AND nulování Dictionary <UInt64, LinkInfo> linkDict = this._LinkDict; foreach (TimeGraphLinkItem link in links) { if (link == null) { continue; } UInt64 key = link.Key; LinkInfo linkInfo; bool exists = linkDict.TryGetValue(key, out linkInfo); if (!exists) { continue; } // Z Důvodu zobrazení odebereme zadaný režim, a pokud zůstane None pak odebereme celý prvek Linku: linkInfo.Mode &= reMode; // Vstupní hodnota (mode) bude z hodnoty linkInfo.Mode vynulována if (linkInfo.Mode == TimeGraphLinkMode.None) // A pokud v Mode nezbyla žádná hodnota, link odebereme. { linkDict.Remove(key); repaint = true; } } if (repaint) { this.Repaint(); } }
/// <summary> /// Přidá dané linky do paměti /// </summary> /// <param name="links">Souhrn linků k přidání</param> /// <param name="mode">Důvod zobrazení</param> public void AddLinks(IEnumerable <TimeGraphLinkItem> links, TimeGraphLinkMode mode) { if (links == null) { return; } if (mode == TimeGraphLinkMode.None) { return; } Dictionary <UInt64, LinkInfo> linkDict = this._LinkDict; foreach (TimeGraphLinkItem link in links) { if (link == null) { continue; } UInt64 key = link.Key; LinkInfo linkInfo; bool exists = linkDict.TryGetValue(key, out linkInfo); if (!exists) { // Pro daný klíč (Prev-Next) dosud nemám link => založím si nový, a přidám do něj dodaná data: linkInfo = new LinkInfo(this, link) { Mode = mode }; linkDict.Add(key, linkInfo); } else { // Link máme => přidáme do něj případně nové bity do jeho režimu: linkInfo.Mode |= mode; } } // Zajistíme překreslení všech vztahů: this.Repaint(); }
/// <summary> /// Konstruktor /// </summary> /// <param name="linksMode"></param> /// <param name="selectedItems"></param> public CreateAllLinksArgs(TimeGraphLinkMode linksMode, IInteractiveItem[] selectedItems = null) { this.LinksMode = linksMode; this.SelectedItems = selectedItems; this.Links = new List <TimeGraphLinkItem>(); }