/// <summary>
        /// Metoda získá a vrátí seznam Child prvků daného prvku <paramref name="parentItem"/>.
        /// Seznam setřídí podle <see cref="IInteractiveItem.TabOrder"/> vzestupně (pro <paramref name="direction"/> == <see cref="Direction.Positive"/>)
        /// nebo sestupně (pro <paramref name="direction"/> == <see cref="Direction.Negative"/>).
        /// <para/>
        /// Seznam obsahuje pouze ty prvky, které jsou viditelné, které mají Enabled = true a které mají TabStop = true, vše podle požadavků v parametru <paramref name="requirements"/>.
        /// Seznam může volitelně obsahovat i explicitně zadaný Child prvek <paramref name="includeItem"/> bez ohledu na jeho Visible a TabStop (tedy pokud tento prvek je obsažen v seznamu Childs).
        /// Tato vlastnost slouží k zařazení určitého prvku pro hledání jeho Next prvků.
        /// <para/>
        /// Seznam obsahuje prvky bez ohledu na jejich vlastnost KeyboardInput, protože tuto vlastnost mohou mít až jejich vnořené Child prvky, a my chceme najít i nadřízené Containery.
        /// <para/>
        /// Pokud je na vstupu objekt <paramref name="parentItem"/>= null, nebo jeho <see cref="IInteractiveParent.Childs"/> je null, pak výstupem metody je null (nebudeme generovat new empty List).
        /// Dále pak proto, že vstupní objekt i jeho Childs připouštíme, že smí být null, ale nechceme nutit volajícího aby si to sám testoval,
        /// protože získání Childs může být výkonnostně náročnější = získáme to jen jednou a vyhodnotíme zde, volající ať si otestuje vrácený objekt, to je nenáročné.
        /// </summary>
        /// <param name="parentItem">Parent, jehož <see cref="IInteractiveParent.Childs"/> prvky budeme zpracovávat</param>
        /// <param name="direction">Směr třídění: <see cref="Direction.Positive"/> = podle TabOrder vzestupně; <see cref="Direction.Negative"/> = podle TabOrder sestupně</param>
        /// <param name="requirements">Požadavky na prohledávané prvky</param>
        /// <param name="includeItem">Prvek, který chceme do seznamu přidat bezpodmínečně (pokud v <see cref="IInteractiveParent.Childs"/> bude přítomen)</param>
        /// <returns></returns>
        private static List <IInteractiveItem> GetChildsSorted(IInteractiveParent parentItem, Direction direction, InteractiveFocusStateFlag requirements = InteractiveFocusStateFlag.Default, IInteractiveItem includeItem = null)
        {
            if (parentItem == null)
            {
                return(null);
            }
            var childs = parentItem.Childs;

            if (childs == null)
            {
                return(null);
            }

            List <IInteractiveItem> childList = childs.Where(i => IsItemValid(i, requirements, includeItem)).ToList();

            if (childList.Count > 1)
            {
                switch (direction)
                {
                case Direction.Positive:
                    childList.Sort(InteractiveObject.CompareByTabOrderAsc);
                    break;

                case Direction.Negative:
                    childList.Sort(InteractiveObject.CompareByTabOrderDesc);
                    break;
                }
            }
            return(childList);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Prověří, že daný prvek není null. Pokud je null, vyhodí chybu.
 /// </summary>
 /// <param name="item"></param>
 /// <param name="action"></param>
 protected static void CheckItem(IInteractiveParent item, string action)
 {
     if (item == null)
     {
         throw new Application.GraphLibCodeException("Nelze provést akci BoundsInfo." + action + "(), dodaný prvek je null.");
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Metoda vrací relativní souřadnici bodu v daném containeru pro danou absolutní souřadnici.
        /// Metoda určí souřadný systém <see cref="BoundsInfo"/> uvnitř daného containeru,
        /// získá jeho <see cref="BoundsInfo.AbsolutePhysicalOriginPoint"/>, a vrátí rozdíl.
        /// </summary>
        /// <param name="container"></param>
        /// <param name="absolutePoint"></param>
        /// <returns></returns>
        public static Point GetRelativePointInContainer(IInteractiveParent container, Point absolutePoint)
        {
            if (container == null)
            {
                return(absolutePoint);
            }
            BoundsInfo boundsInfo = BoundsInfo.CreateForContainer(container);

            return(absolutePoint.Sub(boundsInfo.AbsolutePhysicalOriginPoint));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Metoda vrátí absolutní souřadnice prostoru, který je zadán jako relativní souřadnice v daném containeru.
        /// Pokud tedy například daný container je umístěn na (absolutní) souřadnici Bounds = { 100,20,200,50 }, a dané relativní souřadnice jsou { 5,5,10,10 },
        /// pak výsledné absolutní souřadnice jsou { 105,25,10,10 }.
        /// </summary>
        /// <param name="container"></param>
        /// <param name="relativeBounds"></param>
        /// <param name="currentLayer">Vrstva, jejíž souřadnice řešíme. Každý prvek může mít souřadnice různé podle toho, o kterou vrstvu se jedná.
        /// To je důsledek procesu Drag and Drop, kdy ve standardní vrstvě se prvek nachází na výchozích souřadnicích Bounds,
        /// ale ve vrstvě <see cref="GInteractiveDrawLayer.Interactive"/> je na souřadnicích Drag.</param>
        /// <returns></returns>
        public static Rectangle GetAbsoluteBoundsInContainer(IInteractiveParent container, Rectangle relativeBounds, GInteractiveDrawLayer currentLayer)
        {
            if (container == null)
            {
                return(relativeBounds);
            }
            BoundsInfo boundsInfo = BoundsInfo.CreateForContainer(container, currentLayer);

            return(relativeBounds.Add(boundsInfo.AbsolutePhysicalOriginPoint));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Vrátí instanci třídy <see cref="BoundsInfo"/> pro daný IInteractiveParent parent. Ten může být i <see cref="IAutoScrollContainer"/>!
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="layer">Vrstva grafiky. Ovlivňuje výběr Bounds z dodaného prvku: pro vrstvu <see cref="GInteractiveDrawLayer.Interactive"/>
        /// akceptuje souřadnice <see cref="IInteractiveItem.BoundsInteractive"/>, jinak bere standardně <see cref="IInteractiveItem.Bounds"/>.</param>
        /// <returns></returns>
        public static BoundsInfo CreateForParent(IInteractiveParent parent, GInteractiveDrawLayer layer = GInteractiveDrawLayer.Standard)
        {
            Coordinates physicalCoordinates = Coordinates.FromSize(parent.ClientSize);
            Coordinates virtualCoordinates  = physicalCoordinates;

            if (parent is IAutoScrollContainer)
            {
                IAutoScrollContainer autoScrollContainer = parent as IAutoScrollContainer;
                if (autoScrollContainer.AutoScrollActive)
                {
                    Point     virtualOrigin = autoScrollContainer.VirtualOrigin;
                    Rectangle virtualBounds = physicalCoordinates.GetVisibleBounds(autoScrollContainer.VirtualBounds);
                    virtualCoordinates = Coordinates.FromOrigin(virtualOrigin, virtualBounds);
                }
            }
            return(new BoundsInfo(physicalCoordinates, virtualCoordinates, true, true, layer));
        }
Exemplo n.º 6
0
        /// <summary>
        /// Vrací <see cref="BoundsInfo"/> pro daného parenta a danou vrstvu souřadnic
        /// </summary>
        /// <param name="forItem"></param>
        /// <param name="asContainer"></param>
        /// <param name="layer">Vrstva, jejíž souřadnice řešíme. Každý prvek může mít souřadnice různé podle toho, o kterou vrstvu se jedná.
        /// To je důsledek procesu Drag and Drop, kdy ve standardní vrstvě se prvek nachází na výchozích souřadnicích Bounds,
        /// ale ve vrstvě <see cref="GInteractiveDrawLayer.Interactive"/> je na souřadnicích Drag = <see cref="IInteractiveItem.BoundsInteractive"/>.</param>
        /// <returns></returns>
        private static BoundsInfo _CreateForItem(IInteractiveParent forItem, bool asContainer, GInteractiveDrawLayer layer)
        {
            // Nejprve si nastřádám řadu prvků počínaje daným prvkem/nebo jeho parentem, přes jeho Parenty, až k nejspodnějšímu prvku (který nemá parenta):
            List <IInteractiveParent> parents = new List <IInteractiveParent>();
            Dictionary <uint, object> scanned = new Dictionary <uint, object>();
            IInteractiveParent        parent  = (asContainer ? forItem : forItem.Parent);

            while (parent != null)
            {
                if (scanned.ContainsKey(parent.Id))
                {
                    break;                                   // Zacyklení!
                }
                parents.Add(parent);
                parent = parent.Parent;                      // Krok na dalšího parenta
            }

            // Pak vytvořím postupně řadu BoundsInfo, počínaje od posledního v poli parents (=fyzický Control):
            int last = parents.Count - 1;

            // Pokud na vstupu byl předán container = fyzický Control, pak pole má 0 prvků a výstupní BoundsInfo je vytvořeno pro daný Control!
            if (last < 0)
            {
                return(BoundsInfo.CreateForParent(forItem));
            }
            // Poslední prvek pole = parents[last] = fyzický Control:
            BoundsInfo boundsInfo = BoundsInfo.CreateForParent(parents[last], layer);

            for (int i = last - 1; i >= 0; i--)
            {
                IInteractiveItem it = parents[i] as IInteractiveItem;
                if (it == null)
                {
                    continue;
                }
                boundsInfo = boundsInfo.GetChildsBoundsInfo(it, layer);
            }

            // Na závěr do výsledného boundsInfo vepíšu dodaný Child prvek (forItem) jako Current prvek:
            if (!asContainer && forItem is IInteractiveItem)
            {
                boundsInfo.CurrentItem = forItem as IInteractiveItem;
            }
            return(boundsInfo);
        }
        /// <summary>
        /// Metoda zkusí najít první konkrétní prvek v rámci daného interaktivního parenta, do kterého lze umístit klávesový Focus.
        /// Pokud dodaný parent sám je interaktivní prvek <see cref="IInteractiveItem"/>, a pokud vyhovuje podmínkám Visible a TabStop, a podporuje KeyboardInput, pak je vrácen přímo tento prvek.
        /// Pokud není, nebo pokud nevyhovuje, pak se prověří jeho vlastní Childs prvky, a rekurzivně i jejich vnořené Childs prvky, a vyhledá se první vyhovující prvek.
        /// Pokud takový neexistuje, je vráceno false.
        /// </summary>
        /// <param name="parent">Vstupující prvek. On sám může být tím, kdo dostane focus, anebo některý z jeho Childs prvků (rekurzivně).
        /// Vstupující prvek může být celý Control (=Host), nebo jakýkoli container nebo konkrétní prvek.</param>
        /// <param name="direction">Směr hledání: <see cref="Direction.Positive"/>: hledá první vhodný prvek (od začátku); <see cref="Direction.Negative"/>: hledá poslední vhodný prvek (od konce)</param>
        /// <param name="foundItem">Out: nalezený prvek (this nebo některý z this.Childs[.Childs[...]])</param>
        /// <param name="requirements">Požadavky na prohledávané prvky</param>
        /// <returns>true = nalezeno / false = nenalezeno</returns>
        internal static bool TryGetOuterFocusItem(IInteractiveParent parent, Direction direction, out IInteractiveItem foundItem, InteractiveFocusStateFlag requirements = InteractiveFocusStateFlag.Default)
        {
            foundItem = null;
            if (parent == null)
            {
                return(false);                                                                            // Null nebrat
            }
            // Pokud sám daný prvek je interaktivní, a pokud je vyhovující, pak jej akceptujeme:
            if (parent is IInteractiveItem)
            {
                IInteractiveItem item = parent as IInteractiveItem;
                if (IsItemValid(item, requirements) && item.Is.KeyboardInput)
                {
                    foundItem = item;
                    return(true);
                }
            }

            // Získáme seznam Childs prvky daného prvku, ve správném pořadí, a najdeme první vhodný prvek = cyklem (skrz Childs) a rekurzí (do téže metody):
            List <IInteractiveItem> childList = GetChildsSorted(parent, direction, requirements, null);

            if (childList == null)
            {
                return(false);
            }

            foreach (IInteractiveItem childItem in childList)
            {
                if (TryGetOuterFocusItem(childItem, direction, out foundItem, requirements))
                {
                    return(true);                                                                          // childItem je IInteractiveItem, a protože IInteractiveItem je potomkem IInteractiveParent, vyvoláme přímou rekurzi...
                }
            }

            return(false);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Pro daný prvek určí a vrátí jeho vlastní souřadný systém, který poskytuje svým Childs.
 /// Jde tedy o systém, do jehož <see cref="CurrentItem"/> lze vložit kterýkoli jeho Childs, a systém bude vracet jeho souřadnice.
 /// Vrácený prvek má property <see cref="BoundsInfo.CurrentItem"/> neobsazenou.
 /// </summary>
 /// <param name="currentContainer"></param>
 /// <param name="layer">Vrstva, jejíž souřadnice řešíme. Každý prvek může mít souřadnice různé podle toho, o kterou vrstvu se jedná.
 /// To je důsledek procesu Drag and Drop, kdy ve standardní vrstvě se prvek nachází na výchozích souřadnicích Bounds,
 /// ale ve vrstvě <see cref="GInteractiveDrawLayer.Interactive"/> je na souřadnicích Drag.</param>
 /// <returns></returns>
 public static BoundsInfo CreateForContainer(IInteractiveParent currentContainer, GInteractiveDrawLayer layer)
 {
     CheckItem(currentContainer, "CreateForContainer");
     return(_CreateForItem(currentContainer, true, layer));
 }
Exemplo n.º 9
0
 /// <summary>
 /// Konstruktor s parentem
 /// </summary>
 /// <param name="parent"></param>
 public GridArray(IInteractiveParent parent) : this()
 {
     this.Parent = parent;
 }
Exemplo n.º 10
0
 /// <summary>
 /// Konstruktor
 /// </summary>
 /// <param name="parent"></param>
 public TrackBar(IInteractiveParent parent) : this()
 {
     this.Parent = parent;
 }
Exemplo n.º 11
0
 /// <summary>
 /// Konstruktor s parentem
 /// </summary>
 /// <param name="parent"></param>
 public SizeAxis(IInteractiveParent parent) : this()
 {
     this.Parent = parent;
 }