public static VisualElement CreateAbsoluteIsland(BuilderPaneWindow paneWindow, VisualElement documentRootElement, Vector2 localMousePosition)
        {
            var vta       = paneWindow.document.visualTreeAsset;
            var selection = paneWindow.primarySelection;

            // Create absolute island container.
            var absoluteIslandContainer = new VisualElement();

            absoluteIslandContainer.name = "unity-absolute-island";
            documentRootElement.Add(absoluteIslandContainer);
            BuilderAssetUtilities.AddElementToAsset(paneWindow.document, absoluteIslandContainer);

            bool isTop    = localMousePosition.y < documentRootElement.resolvedStyle.height / 2;
            bool isBottom = !isTop;
            bool isLeft   = localMousePosition.x < documentRootElement.resolvedStyle.width / 2;
            bool isRight  = !isLeft;

            // Set Absolute position.
            BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "position", Position.Absolute);

            if (isTop && isLeft)
            {
                var left = localMousePosition.x;
                var top  = localMousePosition.y;
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "left", left);
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "top", top);
            }
            else if (isTop && isRight)
            {
                var right = documentRootElement.resolvedStyle.width - localMousePosition.x;
                var top   = localMousePosition.y;
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "right", right);
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "top", top);
            }
            else if (isBottom && isLeft)
            {
                var left   = localMousePosition.x;
                var bottom = documentRootElement.resolvedStyle.height - localMousePosition.y;
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "left", left);
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "bottom", bottom);
            }
            else if (isBottom && isRight)
            {
                var right  = documentRootElement.resolvedStyle.width - localMousePosition.x;
                var bottom = documentRootElement.resolvedStyle.height - localMousePosition.y;
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "right", right);
                BuilderStyleUtilities.SetInlineStyleValue(vta, absoluteIslandContainer, "bottom", bottom);
            }

            // Need to explicitly update inline styles from asset.
            selection.NotifyOfHierarchyChange(null, absoluteIslandContainer, BuilderHierarchyChangeType.InlineStyle | BuilderHierarchyChangeType.FullRefresh);

            return(absoluteIslandContainer);
        }
        protected void SetTargetAsset(ScriptableObject targetAsset, bool hasUnsavedChanges)
        {
            if (pane == null)
            {
                return;
            }

            m_TargetAsset = targetAsset;
            pane.subTitle = BuilderAssetUtilities.GetAssetName(targetAsset, previewAssetExtension, hasUnsavedChanges);
            m_OpenTargetAssetSourceButton.style.display = isTargetAssetAvailableOnDisk ? DisplayStyle.Flex : DisplayStyle.None;
        }
Ejemplo n.º 3
0
        bool WriteUXMLToFile(string uxmlPath, string uxmlText)
        {
            // Make sure the folders exist.
            var uxmlFolder = Path.GetDirectoryName(uxmlPath);

            if (!Directory.Exists(uxmlFolder))
            {
                Directory.CreateDirectory(uxmlFolder);
            }

            return(BuilderAssetUtilities.WriteTextFileToDisk(uxmlPath, uxmlText));
        }
Ejemplo n.º 4
0
        void AddStyleClass(string className)
        {
            PreAddStyleClass(className);

            // Update VisualTreeAsset.
            BuilderAssetUtilities.AddStyleClassToElementInAsset(
                m_PaneWindow.document, currentVisualElement, className);

            // We actually want to get the notification back and refresh ourselves.
            m_Selection.NotifyOfHierarchyChange(null);
            m_Selection.NotifyOfStylingChange(null);
        }
        void PerformActionForStyleSheet(VisualElement destination, DestinationPane pane, int index = -1)
        {
            if (destination == null)
            {
                destination = BuilderSharedStyles.GetSelectorContainerElement(selection.documentRootElement);
            }

            BuilderAssetUtilities.ReorderStyleSheetsInAsset(paneWindow.document, destination);

            selection.NotifyOfHierarchyChange();
            selection.NotifyOfStylingChange(null);
            selection.ForceReselection();
        }
Ejemplo n.º 6
0
        public static void RemoveUSSFromAsset(BuilderPaneWindow paneWindow, int selectedStyleSheetIndex)
        {
            // We need to save all files before we remove the USS.
            // If we don't do this, changes in the removed USS will be lost.
            var shouldContinue = s_CheckForUnsavedChanges(paneWindow);

            if (!shouldContinue)
            {
                return;
            }

            BuilderAssetUtilities.RemoveStyleSheetFromAsset(paneWindow.document, selectedStyleSheetIndex);
            paneWindow.OnEnableAfterAllSerialization();
        }
Ejemplo n.º 7
0
        protected override void PerformAction(VisualElement destination, DestinationPane pane, int index = -1)
        {
            m_DragPreviewElement.RemoveFromClassList(s_DragPreviewElementClassName);

            destination.RemoveMinSizeSpecialElement();

            // We already have the correct index from the preview element that is
            // already inserted in the hierarchy. The index we get from the arguments
            // is actually incorrect (off by one) because it will count the
            // preview element.
            index = m_DragPreviewLastParent.IndexOf(m_DragPreviewElement);

            // We should have an item reference here if the OnDragStart() worked.
            var item    = m_LibraryItem;
            var itemVTA = item.SourceAsset;

            if (!paneWindow.document.WillCauseCircularDependency(itemVTA))
            {
                BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidWouldCauseCircularDependencyMessage,
                                                    BuilderConstants.InvalidWouldCauseCircularDependencyMessageDescription, null);
                return;
            }

            if (item.MakeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(
                    paneWindow.document, m_DragPreviewElement, index);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    paneWindow.document, m_DragPreviewElement, item.MakeElementAssetCallback, index);
            }

            selection.NotifyOfHierarchyChange(null);
            selection.NotifyOfStylingChange(null);
            selection.Select(null, m_DragPreviewElement);

            // Commit to the preview element as the final element.
            // This will stop the ResetDragPreviewElement() from calling
            // RemoveFromHierarchy() on it.
            m_DragPreviewElement = null;

            // If we dragged into the Viewport, focus the Viewport.
            if (pane == DestinationPane.Viewport)
            {
                Viewport.pane.Focus();
            }
        }
Ejemplo n.º 8
0
        public static void SetValue(this StyleSheet styleSheet, StyleValueHandle valueHandle, Object value)
        {
            // Undo/Redo
            Undo.RegisterCompleteObjectUndo(styleSheet, BuilderConstants.ChangeUIStyleValueUndoMessage);

            if (valueHandle.valueType == StyleValueType.ResourcePath)
            {
                var resourcesPath = BuilderAssetUtilities.GetResourcesPathForAsset(value);
                styleSheet.strings[valueHandle.valueIndex] = resourcesPath;
            }
            else
            {
                styleSheet.assets[valueHandle.valueIndex] = value;
            }
        }
Ejemplo n.º 9
0
        bool DeleteElementFromVisualTreeAsset(VisualElement element)
        {
            var vea = element.GetVisualElementAsset();

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

            BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element);
            element.RemoveFromHierarchy();
            m_Selection.NotifyOfHierarchyChange();

            return(true);
        }
Ejemplo n.º 10
0
        void PasteUXML(string copyBuffer)
        {
            var importer = new BuilderVisualTreeAssetImporter(); // Cannot be cached because the StyleBuilder never gets reset.

            importer.ImportXmlFromString(copyBuffer, out var pasteVta);

            /* If the current parent element is linked to a VisualTreeAsset, it could mean
             * that our parent is the TemplateContainer belonging to our parent document and the
             * current open document is a sub-document opened in-place. In such a case, we don't
             * want to use our parent's VisualElementAsset, as that belongs to our parent document.
             * So instead, we just use no parent, indicating that we are adding this new element
             * to the root of our document. */
            VisualElementAsset parent = null;

            if (!m_Selection.isEmpty)
            {
                var selectionParent = m_Selection.selection.First().parent;
                parent = selectionParent?.GetVisualElementAsset();

                if (selectionParent?.GetVisualTreeAsset() == m_PaneWindow.document.visualTreeAsset)
                {
                    parent = null;
                }

                m_Selection.ClearSelection(null);
            }

            // Select all pasted elements.
            foreach (var templateAsset in pasteVta.templateAssets)
            {
                if (pasteVta.IsRootElement(templateAsset))
                {
                    templateAsset.Select();
                }
            }
            foreach (var vea in pasteVta.visualElementAssets)
            {
                if (pasteVta.IsRootElement(vea))
                {
                    vea.Select();
                }
            }

            BuilderAssetUtilities.TransferAssetToAsset(m_PaneWindow.document, parent, pasteVta);
            m_PaneWindow.document.AddStyleSheetsToAllRootElements();

            ScriptableObject.DestroyImmediate(pasteVta);
        }
Ejemplo n.º 11
0
        public void AddToSelection(IBuilderSelectionNotifier source, VisualElement ve, bool undo = true)
        {
            if (ve == null)
            {
                return;
            }

            m_Selection.Add(ve);

            if (undo)
            {
                BuilderAssetUtilities.AddElementToSelectionInAsset(m_PaneWindow.document, ve);
            }

            NotifyOfSelectionChange(source);
        }
Ejemplo n.º 12
0
        void PasteUSS(string copyBuffer)
        {
            var pasteStyleSheet = StyleSheetUtilities.CreateInstance();
            var importer        = new BuilderStyleSheetImporter(); // Cannot be cached because the StyleBuilder never gets reset.

            importer.Import(pasteStyleSheet, copyBuffer);

            BuilderAssetUtilities.TransferAssetToAsset(m_PaneWindow.document, pasteStyleSheet);

            m_Selection.ClearSelection(null);
            var scs = m_PaneWindow.document.mainStyleSheet.complexSelectors.Last();

            BuilderAssetUtilities.AddStyleComplexSelectorToSelection(m_PaneWindow.document, scs);

            ScriptableObject.DestroyImmediate(pasteStyleSheet);
        }
Ejemplo n.º 13
0
        bool DeleteElementFromVisualTreeAsset(VisualElement element)
        {
            var vea = element.GetVisualElementAsset();

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

#if UNITY_2019_4
            // Before 2020.1, the only way to attach a StyleSheet to a UXML document was via a <Style>
            // tag as a child of an element tag. This meant that if there were no elements in the document,
            // there cannot be any StyleSheets attached to it. Therefore, we need to warn the user when
            // deleting the last element in the document that they will lose the list of attached StyleSheets
            // as well. This is something that can be undone via undo so it's not terrible if they say "Yes"
            // accidentally.
            //
            // 2020.1 adds support for the global <Style> tag so this limitation is lifted. However, the
            // UI Builder does not yet support the global <Style> tag. Plus, even when support to the
            // UI Builder is added, we still need to maintain support for 2019.3 via this logic.
            if (m_PaneWindow.document.firstStyleSheet != null &&
                m_PaneWindow.document.visualTreeAsset.WillBeEmptyIfRemovingOne(vea))
            {
                var continueDeletion = BuilderDialogsUtility.DisplayDialog(
                    BuilderConstants.DeleteLastElementDialogTitle,
                    BuilderConstants.DeleteLastElementDialogMessage,
                    "Yes", "Cancel");
                if (!continueDeletion)
                {
                    return(false);
                }

                BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element);

                m_PaneWindow.OnEnableAfterAllSerialization();
            }
            else
#endif
            {
                BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, element);

                element.RemoveFromHierarchy();
                m_Selection.NotifyOfHierarchyChange();
            }

            return(true);
        }
Ejemplo n.º 14
0
        internal static StyleValueHandle AddValue(this StyleSheet styleSheet, StyleProperty property, Object value)
        {
            // Undo/Redo
            Undo.RegisterCompleteObjectUndo(styleSheet, BuilderConstants.ChangeUIStyleValueUndoMessage);

            // Determine real asset type.
            var resourcePath   = BuilderAssetUtilities.GetResourcesPathForAsset(value);
            var styleValueType = string.IsNullOrEmpty(resourcePath) ? StyleValueType.AssetReference : StyleValueType.ResourcePath;

            // Add value data to data array.
            var index = string.IsNullOrEmpty(resourcePath) ? styleSheet.AddValueToArray(value) : styleSheet.AddValueToArray(resourcePath);

            // Add value object to property.
            var newValue = styleSheet.AddValueHandle(property, index, styleValueType);

            return(newValue);
        }
Ejemplo n.º 15
0
        protected void AddItemToTheDocument(BuilderLibraryTreeItem item)
        {
            // If this is the uxml file entry of the currently open file, don't allow
            // the user to instantiate it (infinite recursion) or re-open it.
            var  listOfOpenDocuments   = m_PaneWindow.document.openUXMLFiles;
            bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.name);

            if (isCurrentDocumentOpen)
            {
                return;
            }

            var newElement = item.makeVisualElementCallback?.Invoke();

            if (newElement == null)
            {
                return;
            }

            var activeVTARootElement = m_DocumentRootElement.Query().Where(e => e.GetVisualTreeAsset() == m_PaneWindow.document.visualTreeAsset).First();

            if (activeVTARootElement == null)
            {
                Debug.LogError("UI Builder has a bug. Could not find document root element for currently active open UXML document.");
                return;
            }
            activeVTARootElement.Add(newElement);

            if (item.makeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    m_PaneWindow.document, newElement, item.makeElementAssetCallback);
            }

            // TODO: ListView bug. Does not refresh selection pseudo states after a
            // call to Refresh().
            m_Selection.NotifyOfHierarchyChange();
            schedule.Execute(() =>
            {
                m_Selection.Select(null, newElement);
            }).ExecuteLater(200);
        }
Ejemplo n.º 16
0
        protected override void PerformAction(VisualElement destination, DestinationPane pane, Vector2 localMousePosition, int index = -1)
        {
            if (pane == DestinationPane.Viewport && !IsPickedElementValid(m_TargetElementToReparent))
            {
                return;
            }

            base.PerformAction(destination, pane, localMousePosition, index);

            m_TargetElementToReparent.RemoveFromClassList(s_DragPreviewElementClassName);

            // Remove temporary min-size element.
            destination.RemoveMinSizeSpecialElement();

            var newParent = destination;

            // We already have the correct index from the preview element that is
            // already inserted in the hierarchy. The index we get from the arguments
            // is actually incorrect (off by one) because it will count the
            // preview element.
            index = m_DragPreviewLastParent.IndexOf(m_TargetElementToReparent);

            bool undo = true;

            foreach (var elementToReparent in m_ElementsToReparent)
            {
                var element = elementToReparent.element;

                if (newParent == element || newParent.HasAncestor(element))
                {
                    continue;
                }

                BuilderAssetUtilities.ReparentElementInAsset(
                    paneWindow.document, element, newParent, index, undo);

                undo = false;
            }

            BuilderAssetUtilities.SortElementsByTheirVisualElementInAsset(newParent);

            selection.NotifyOfHierarchyChange(null);
            selection.NotifyOfStylingChange(null);
            selection.ForceReselection(null);
        }
Ejemplo n.º 17
0
        void OnStyleClassDelete(EventBase evt)
        {
            var target    = evt.target as VisualElement;
            var className = target.userData as string;

            // Actually remove the style class from the element in the canvas.
            currentVisualElement.RemoveFromClassList(className);

            // Update VisualTreeAsset.
            BuilderAssetUtilities.RemoveStyleClassFromElementInAsset(
                m_PaneWindow.document, currentVisualElement, className);

            // We actually want to get the notification back and refresh ourselves.
            m_Selection.NotifyOfHierarchyChange(null);
            m_Selection.NotifyOfStylingChange(null);

            evt.StopPropagation();
        }
        protected override void PerformAction(VisualElement destination, DestinationPane pane, int index = -1)
        {
            if (BuilderSharedStyles.IsDocumentElement(destination))
            {
                return;
            }

            var className = m_ClassNameBeingDragged.TrimStart('.');

            destination.AddToClassList(className);

            // Update VisualTreeAsset.
            BuilderAssetUtilities.AddStyleClassToElementInAsset(
                paneWindow.document, destination, className);

            selection.NotifyOfHierarchyChange(null);
            selection.NotifyOfStylingChange(null);
        }
Ejemplo n.º 19
0
        public void ClearSelection(IBuilderSelectionNotifier source, bool undo = true)
        {
            if (isEmpty)
            {
                return;
            }

            if (undo)
            {
                foreach (var sel in m_Selection)
                {
                    BuilderAssetUtilities.RemoveElementFromSelectionInAsset(m_PaneWindow.document, sel);
                }
            }

            m_Selection.Clear();

            NotifyOfSelectionChange(source);
        }
        void PasteUXML(string copyBuffer)
        {
            VisualTreeAsset pasteVta = null;
            var             importer = new BuilderVisualTreeAssetImporter(); // Cannot be cached because the StyleBuilder never gets reset.

            importer.ImportXmlFromString(copyBuffer, out pasteVta);

            VisualElementAsset parent = null;

            if (!m_Selection.isEmpty)
            {
                parent = m_Selection.selection.First().parent?.GetVisualElementAsset();
            }

            BuilderAssetUtilities.TransferAssetToAsset(m_PaneWindow.document, parent, pasteVta);

            m_PaneWindow.document.AddStyleSheetToAllRootElements();

            ScriptableObject.DestroyImmediate(pasteVta);
        }
        protected override void PerformAction(VisualElement destination, DestinationPane pane, int index = -1)
        {
            m_TargetElementToReparent.RemoveFromClassList(s_DragPreviewElementClassName);

            // Remove temporary min-size element.
            destination.RemoveMinSizeSpecialElement();

            var elementToReparent = m_TargetElementToReparent;
            var newParent         = destination;

            // We already have the correct index from the preview element that is
            // already inserted in the hierarchy. The index we get from the arguments
            // is actually incorrect (off by one) because it will count the
            // preview element.
            index = m_DragPreviewLastParent.IndexOf(m_TargetElementToReparent);

            BuilderAssetUtilities.ReparentElementInAsset(
                paneWindow.document, elementToReparent, newParent, index);

            selection.NotifyOfHierarchyChange(null);
        }
Ejemplo n.º 22
0
        public bool LoadDocument(VisualTreeAsset visualTreeAsset, bool unloadAllSubdocuments = true, bool assetModifiedExternally = false, string assetPath = null)
        {
            if (!BuilderAssetUtilities.ValidateAsset(visualTreeAsset, assetPath))
            {
                return(false);
            }

            if (!document.CheckForUnsavedChanges(assetModifiedExternally))
            {
                return(false);
            }

            if (unloadAllSubdocuments)
            {
                document.GoToRootDocument(m_Viewport.documentRootElement, m_PaneWindow);
            }

            LoadDocumentInternal(visualTreeAsset);

            return(true);
        }
Ejemplo n.º 23
0
        protected void AddItemToTheDocument(BuilderLibraryTreeItem item)
        {
            // If this is the uxml file entry of the currently open file, don't allow
            // the user to instantiate it (infinite recursion) or re-open it.
            var  listOfOpenDocuments   = m_PaneWindow.document.openUXMLFiles;
            bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.Name);

            if (isCurrentDocumentOpen)
            {
                return;
            }

            var newElement = item.MakeVisualElementCallback?.Invoke();

            if (newElement == null)
            {
                return;
            }

            m_DocumentElement.Add(newElement);

            if (item.MakeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    m_PaneWindow.document, newElement, item.MakeElementAssetCallback);
            }

            // TODO: ListView bug. Does not refresh selection pseudo states after a
            // call to Refresh().
            m_Selection.NotifyOfHierarchyChange();
            schedule.Execute(() =>
            {
                m_Selection.Select(null, newElement);
            }).ExecuteLater(200);
        }
Ejemplo n.º 24
0
        public void Select(IBuilderSelectionNotifier source, VisualElement ve)
        {
            if (ve == null)
            {
                return;
            }

            foreach (var sel in m_Selection)
            {
                if (sel == null)
                {
                    continue;
                }

                BuilderAssetUtilities.RemoveElementFromSelectionInAsset(m_PaneWindow.document, sel);
            }

            m_Selection.Clear();

            m_Selection.Add(ve);
            BuilderAssetUtilities.AddElementToSelectionInAsset(m_PaneWindow.document, ve);

            NotifyOfSelectionChange(source);
        }
Ejemplo n.º 25
0
        public void UnpackTemplateContainer(VisualElement templateContainer, bool unpackCompletely = false)
        {
            if (templateContainer == null)
            {
                Debug.LogError("Template to unpack is null");
                return;
            }

            var elementsToUnpack = new List <VisualElement>();
            var rootVEA          = templateContainer.GetVisualElementAsset();
            var isRootElement    = true;
            VisualElementAsset rootUnpackedVEA = null;

            elementsToUnpack.Add(templateContainer);

            while (elementsToUnpack.Count > 0)
            {
                var elementToUnpack         = elementsToUnpack[0];
                var unpackedVE              = new VisualElement();
                var templateContainerParent = elementToUnpack.parent;
                var templateContainerIndex  = templateContainerParent.IndexOf(elementToUnpack);

                // Create new unpacked element and add it in the hierarchy
                templateContainerParent.Add(unpackedVE);
                BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, unpackedVE, templateContainerIndex + 1);

                var linkedInstancedVTA   = elementToUnpack.GetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName) as VisualTreeAsset;
                var linkedTA             = elementToUnpack.GetVisualElementAsset() as TemplateAsset;
                var linkedVTACopy        = linkedInstancedVTA.DeepCopy();
                var unpackedVEA          = unpackedVE.GetVisualElementAsset();
                var templateContainerVEA = elementToUnpack.GetVisualElementAsset();
                var attributeOverrides   = linkedTA.attributeOverrides;

                var attributes = elementToUnpack.GetOverriddenAttributes();
                foreach (var attribute in attributes)
                {
                    unpackedVEA.SetAttributeValue(attribute.Key, attribute.Value);
                }

                if (isRootElement)
                {
                    rootUnpackedVEA = unpackedVEA;
                }

                // Apply attribute overrides to elements in the unpacked element
                BuilderAssetUtilities.ApplyAttributeOverridesToTreeAsset(attributeOverrides, linkedVTACopy);

                // Move attribute overrides to new template containers
                BuilderAssetUtilities.CopyAttributeOverridesToChildTemplateAssets(attributeOverrides, linkedVTACopy);

                // Apply stylesheets to new element + inline rules
                BuilderAssetUtilities.AddStyleSheetsFromTreeAsset(unpackedVEA, linkedInstancedVTA);
                unpackedVEA.ruleIndex = templateContainerVEA.ruleIndex;

                BuilderAssetUtilities.TransferAssetToAsset(m_PaneWindow.document, unpackedVEA, linkedVTACopy, false);

                elementsToUnpack.Remove(elementToUnpack);

                if (elementToUnpack != templateContainer)
                {
                    BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, elementToUnpack, false);
                    elementToUnpack.RemoveFromHierarchy();
                }

                if (unpackCompletely && elementsToUnpack.Count == 0)
                {
                    VisualElement tree = new VisualElement();
                    m_PaneWindow.document.activeOpenUXMLFile.visualTreeAsset.LinkedCloneTree(tree);
                    var newElement   = tree.Query <VisualElement>().Where(x => x.GetVisualElementAsset() == rootUnpackedVEA).First();
                    var newTemplates = newElement.Query <TemplateContainer>().Where(x => x.GetVisualElementAsset() != null).ToList();
                    elementsToUnpack.AddRange(newTemplates);
                    isRootElement = false;
                }
            }

            m_Selection.NotifyOfHierarchyChange();
            m_PaneWindow.OnEnableAfterAllSerialization();

            // Keep hierarchy tree state in the new unpacked element
            var hierarchy = Builder.ActiveWindow.hierarchy;

            hierarchy.elementHierarchyView.CopyTreeViewItemStates(rootVEA, rootUnpackedVEA);

            // Delete old template element
            BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, templateContainer, false);
            templateContainer.RemoveFromHierarchy();

            m_Selection.ClearSelection(null);
            rootUnpackedVEA.Select();

            m_Selection.NotifyOfHierarchyChange();
            m_PaneWindow.OnEnableAfterAllSerialization();
        }
Ejemplo n.º 26
0
        public void CreateTemplateFromHierarchy(VisualElement ve, VisualTreeAsset vta, string path = "")
        {
            var veas = new List <VisualElementAsset>();
            var vea  = ve.GetVisualElementAsset();

            veas.Add(vea);

            if (string.IsNullOrEmpty(path))
            {
                path = BuilderDialogsUtility.DisplaySaveFileDialog("Save UXML", null, ve.name, "uxml");

                if (string.IsNullOrEmpty(path))
                {
                    // Save dialog cancelled
                    return;
                }
            }

            if (path == m_PaneWindow.document.activeOpenUXMLFile.uxmlPath)
            {
                // Path is the same as the active open uxml file. Abort!
                BuilderDialogsUtility.DisplayDialog(
                    BuilderConstants.InvalidCreateTemplatePathTitle,
                    BuilderConstants.InvalidCreateTemplatePathMessage,
                    BuilderConstants.DialogOkOption);

                return;
            }

            var uxml = VisualTreeAssetToUXML.GenerateUXML(vta, null, veas);

            if (!m_PaneWindow.document.SaveNewTemplateFileFromHierarchy(path, uxml))
            {
                // New template wasn't saved
                return;
            }

            var parent    = ve.parent;
            var parentVEA = parent.GetVisualElementAsset();
            var index     = parent.IndexOf(ve);

            // Delete old element
            BuilderAssetUtilities.DeleteElementFromAsset(m_PaneWindow.document, ve);
            ve.RemoveFromHierarchy();

            // Replace with new template
            var newTemplateVTA       = EditorGUIUtility.Load(path) as VisualTreeAsset;
            var newTemplateContainer = newTemplateVTA.CloneTree();

            newTemplateContainer.SetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName, path);
            newTemplateContainer.name = newTemplateVTA.name;

            parent.Insert(index, newTemplateContainer);

            BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newTemplateContainer, (inVta, inParent, ve) =>
            {
                var vea = inVta.AddTemplateInstance(inParent, path) as VisualElementAsset;
                vea.AddProperty("name", newTemplateVTA.name);
                ve.SetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName, newTemplateVTA);
                return(vea);
            }, index);

            m_Selection.Select(null, newTemplateContainer);

            // Refresh
            m_Selection.NotifyOfHierarchyChange();
            m_PaneWindow.OnEnableAfterAllSerialization();
        }
        void ExtractLocalStylesToNewClass(string className)
        {
            // Get StyleSheet.
            var mainStyleSheet = m_PaneWindow.document.activeStyleSheet;

            if (mainStyleSheet == null)
            {
                var option = BuilderDialogsUtility.DisplayDialogComplex(
                    BuilderConstants.ExtractInlineStylesNoUSSDialogTitle,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogMessage,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogNewUSSOption,
                    BuilderConstants.ExtractInlineStylesNoUSSDialogExistingUSSOption,
                    BuilderConstants.DialogCancelOption);

                switch (option)
                {
                // New
                case 0:
                    if (!BuilderStyleSheetsUtilities.CreateNewUSSAsset(m_PaneWindow))
                    {
                        return;
                    }
                    break;

                // Existing
                case 1:
                    if (!BuilderStyleSheetsUtilities.AddExistingUSSToAsset(m_PaneWindow))
                    {
                        return;
                    }
                    break;

                // Cancel
                case 2:
                    return;
                }

                mainStyleSheet = m_PaneWindow.document.activeStyleSheet;
            }

            PreAddStyleClass(className);

            // Create new selector in main StyleSheet.
            var selectorString       = BuilderConstants.UssSelectorClassNameSymbol + className;
            var selectorsRootElement = BuilderSharedStyles.GetSelectorContainerElement(m_Selection.documentElement);
            var newSelector          = BuilderSharedStyles.CreateNewSelector(selectorsRootElement, mainStyleSheet, selectorString);

            // Transfer all properties from inline styles rule to new selector.
            mainStyleSheet.TransferRulePropertiesToSelector(
                newSelector, m_Inspector.styleSheet, m_Inspector.currentRule);

            // Update VisualTreeAsset.
            BuilderAssetUtilities.AddStyleClassToElementInAsset(
                m_PaneWindow.document, currentVisualElement, className);

            // Overwrite Undo Message.
            Undo.RegisterCompleteObjectUndo(
                new Object[] { m_PaneWindow.document.visualTreeAsset, mainStyleSheet },
                BuilderConstants.CreateStyleClassUndoMessage);

            // We actually want to get the notification back and refresh ourselves.
            m_Selection.NotifyOfStylingChange(null);
            m_Selection.NotifyOfHierarchyChange(null, currentVisualElement);
        }
        protected override void PerformAction(VisualElement destination, DestinationPane pane, Vector2 localMousePosition, int index = -1)
        {
            // We should have an item reference here if the OnDragStart() worked.
            var item    = m_LibraryItem;
            var itemVTA = item.sourceAsset;

            if (paneWindow.document.WillCauseCircularDependency(itemVTA))
            {
                BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidWouldCauseCircularDependencyMessage,
                                                    BuilderConstants.InvalidWouldCauseCircularDependencyMessageDescription, BuilderConstants.DialogOkOption);
                return;
            }

            if (item.makeElementAssetCallback != null && m_DragPreviewElement is TemplateContainer tempContainer)
            {
                if (!BuilderAssetUtilities.ValidateAsset(item.sourceAsset, item.sourceAssetPath))
                {
                    return;
                }
            }

            // Determine if it applies and use Absolute Island insertion.
            if (BuilderProjectSettings.enableAbsolutePositionPlacement && pane == DestinationPane.Viewport && m_DragPreviewLastParent == documentRootElement && index < 0)
            {
                m_DragPreviewLastParent = BuilderPlacementUtilities.CreateAbsoluteIsland(paneWindow, documentRootElement, localMousePosition);
            }

            // Add VisualElement to Canvas.
            m_DragPreviewElement.RemoveFromClassList(s_DragPreviewElementClassName);
            if (index < 0)
            {
                m_DragPreviewLastParent.Add(m_DragPreviewElement);
            }
            else
            {
                m_DragPreviewLastParent.Insert(index, m_DragPreviewElement);
            }

            // Create equivalent VisualElementAsset.
            if (item.makeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(
                    paneWindow.document, m_DragPreviewElement, index);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    paneWindow.document, m_DragPreviewElement, item.makeElementAssetCallback, index);
            }

            selection.NotifyOfHierarchyChange(null);
            selection.NotifyOfStylingChange(null);
            selection.Select(null, m_DragPreviewElement);

            // Commit to the preview element as the final element.
            // This will stop the ResetDragPreviewElement() from calling
            // RemoveFromHierarchy() on it.
            m_DragPreviewElement = null;

            // If we dragged into the Viewport, focus the Viewport.
            if (pane == DestinationPane.Viewport)
            {
                viewport.pane.Focus();
            }
        }
Ejemplo n.º 29
0
        void FillItem(VisualElement element, ITreeViewItem item)
        {
            var explorerItem = element as BuilderExplorerItem;

            explorerItem.Clear();

            // Pre-emptive cleanup.
            var row = explorerItem.parent.parent;

            row.RemoveFromClassList(BuilderConstants.ExplorerHeaderRowClassName);
            row.RemoveFromClassList(BuilderConstants.ExplorerItemHiddenClassName);

            // Get target element (in the document).
            var documentElement = (item as TreeViewItem <VisualElement>).data;

            documentElement.SetProperty(BuilderConstants.ElementLinkedExplorerItemVEPropertyName, explorerItem);
            explorerItem.SetProperty(BuilderConstants.ElementLinkedDocumentVisualElementVEPropertyName, documentElement);
            row.userData = documentElement;

            // If we have a FillItem callback (override), we call it and stop creating the rest of the item.
            var fillItemCallback =
                documentElement.GetProperty(BuilderConstants.ExplorerItemFillItemCallbackVEPropertyName) as Action <VisualElement, ITreeViewItem, BuilderSelection>;

            if (fillItemCallback != null)
            {
                fillItemCallback(explorerItem, item, m_Selection);
                return;
            }

            // Create main label container.
            var labelCont = new VisualElement();

            labelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName);
            explorerItem.Add(labelCont);

            if (BuilderSharedStyles.IsSelectorsContainerElement(documentElement))
            {
                var styleSheetAsset     = documentElement.GetStyleSheet();
                var styleSheetFileName  = AssetDatabase.GetAssetPath(styleSheetAsset);
                var styleSheetAssetName = BuilderAssetUtilities.GetStyleSheetAssetName(styleSheetAsset);
                var ssLabel             = new Label(styleSheetAssetName);
                ssLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                ssLabel.AddToClassList("unity-debugger-tree-item-type");
                row.AddToClassList(BuilderConstants.ExplorerHeaderRowClassName);
                labelCont.Add(ssLabel);
                return;
            }
            else if (BuilderSharedStyles.IsSelectorElement(documentElement))
            {
                var selectorParts = BuilderSharedStyles.GetSelectorParts(documentElement);

                foreach (var partStr in selectorParts)
                {
                    if (partStr.StartsWith(BuilderConstants.UssSelectorClassNameSymbol))
                    {
                        m_ClassPillTemplate.CloneTree(labelCont);
                        var pill      = labelCont.contentContainer.ElementAt(labelCont.childCount - 1);
                        var pillLabel = pill.Q <Label>("class-name-label");
                        pill.AddToClassList("unity-debugger-tree-item-pill");
                        pill.SetProperty(BuilderConstants.ExplorerStyleClassPillClassNameVEPropertyName, partStr);
                        pill.userData = documentElement;

                        // Add ellipsis if the class name is too long.
                        var partStrShortened = BuilderNameUtilities.CapStringLengthAndAddEllipsis(partStr, BuilderConstants.ClassNameInPillMaxLength);
                        pillLabel.text = partStrShortened;

                        m_ClassDragger.RegisterCallbacksOnTarget(pill);
                    }
                    else if (partStr.StartsWith(BuilderConstants.UssSelectorNameSymbol))
                    {
                        var selectorPartLabel = new Label(partStr);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementNameClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                    else if (partStr.StartsWith(BuilderConstants.UssSelectorPseudoStateSymbol))
                    {
                        var selectorPartLabel = new Label(partStr);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementPseudoStateClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                    else if (partStr == BuilderConstants.SingleSpace)
                    {
                        var selectorPartLabel = new Label(BuilderConstants.TripleSpace);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementTypeClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                    else
                    {
                        var selectorPartLabel = new Label(partStr);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementTypeClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                }

                // Register right-click events for context menu actions.
                m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem);

                return;
            }

            if (BuilderSharedStyles.IsDocumentElement(documentElement))
            {
                var uxmlAsset = documentElement.GetVisualTreeAsset();
                var ssLabel   = new Label(BuilderAssetUtilities.GetVisualTreeAssetAssetName(uxmlAsset));
                ssLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                ssLabel.AddToClassList("unity-debugger-tree-item-type");
                row.AddToClassList(BuilderConstants.ExplorerHeaderRowClassName);
                labelCont.Add(ssLabel);
                return;
            }

            // Check if element is inside current document.
            if (!documentElement.IsPartOfCurrentDocument())
            {
                row.AddToClassList(BuilderConstants.ExplorerItemHiddenClassName);
            }

            // Register drag-and-drop events for reparenting.
            m_HierarchyDragger.RegisterCallbacksOnTarget(explorerItem);

            // Allow reparenting.
            explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement);

            // Element type label.
            if (string.IsNullOrEmpty(documentElement.name) ||
                elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.TypeName))
            {
                var typeLabel = new Label(documentElement.typeName);
                typeLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                typeLabel.AddToClassList(BuilderConstants.ElementTypeClassName);
                labelCont.Add(typeLabel);
            }

            // Element name label.
            var nameLabel = new Label();

            nameLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
            nameLabel.AddToClassList("unity-debugger-tree-item-name-label");
            nameLabel.AddToClassList(BuilderConstants.ExplorerItemNameLabelClassName);
            nameLabel.AddToClassList(BuilderConstants.ElementNameClassName);
            if (!string.IsNullOrEmpty(documentElement.name))
            {
                nameLabel.text = "#" + documentElement.name;
            }
            labelCont.Add(nameLabel);

            // Textfield to rename element in hierarchy.
            var renameTextfield = explorerItem.CreateRenamingTextField(documentElement, nameLabel, m_Selection);

            labelCont.Add(renameTextfield);

            // Add class list.
            if (documentElement.classList.Count > 0 && elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.ClassList))
            {
                foreach (var ussClass in documentElement.GetClasses())
                {
                    var classLabelCont = new VisualElement();
                    classLabelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName);
                    explorerItem.Add(classLabelCont);

                    var classLabel = new Label("." + ussClass);
                    classLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                    classLabel.AddToClassList(BuilderConstants.ElementClassNameClassName);
                    classLabel.AddToClassList("unity-debugger-tree-item-classlist-label");

                    classLabelCont.Add(classLabel);
                }
            }

            // Show name of uxml file if this element is a TemplateContainer.
            var path = documentElement.GetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName) as string;

            if (documentElement is TemplateContainer && !string.IsNullOrEmpty(path))
            {
                var pathStr = Path.GetFileName(path);
                var label   = new Label(pathStr);
                label.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                label.AddToClassList(BuilderConstants.ElementTypeClassName);
                label.AddToClassList("unity-builder-explorer-tree-item-template-path"); // Just make it look a bit shaded.
                labelCont.Add(label);
            }

            // Register right-click events for context menu actions.
            m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem);
        }
Ejemplo n.º 30
0
        void FillItem(VisualElement element, ITreeViewItem item)
        {
            var explorerItem = element as BuilderExplorerItem;

            explorerItem.Clear();

            // Pre-emptive cleanup.
            var row = explorerItem.parent.parent;

            row.RemoveFromClassList(BuilderConstants.ExplorerHeaderRowClassName);
            row.RemoveFromClassList(BuilderConstants.ExplorerItemHiddenClassName);
            row.RemoveFromClassList(BuilderConstants.ExplorerActiveStyleSheetClassName);

            // Get target element (in the document).
            var documentElement = (item as TreeViewItem <VisualElement>).data;

            documentElement.SetProperty(BuilderConstants.ElementLinkedExplorerItemVEPropertyName, explorerItem);
            explorerItem.SetProperty(BuilderConstants.ElementLinkedDocumentVisualElementVEPropertyName, documentElement);
            row.userData = documentElement;

            // If we have a FillItem callback (override), we call it and stop creating the rest of the item.
            var fillItemCallback =
                documentElement.GetProperty(BuilderConstants.ExplorerItemFillItemCallbackVEPropertyName) as Action <VisualElement, ITreeViewItem, BuilderSelection>;

            if (fillItemCallback != null)
            {
                fillItemCallback(explorerItem, item, m_Selection);
                return;
            }

            // Create main label container.
            var labelCont = new VisualElement();

            labelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName);
            explorerItem.Add(labelCont);

            if (BuilderSharedStyles.IsStyleSheetElement(documentElement))
            {
                var owningUxmlPath         = documentElement.GetProperty(BuilderConstants.ExplorerItemLinkedUXMLFileName) as string;
                var isPartOfParentDocument = !string.IsNullOrEmpty(owningUxmlPath);

                var styleSheetAsset     = documentElement.GetStyleSheet();
                var styleSheetFileName  = AssetDatabase.GetAssetPath(styleSheetAsset);
                var styleSheetAssetName = BuilderAssetUtilities.GetStyleSheetAssetName(styleSheetAsset, hasUnsavedChanges && !isPartOfParentDocument);
                var ssLabel             = new Label(styleSheetAssetName);
                ssLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                ssLabel.AddToClassList("unity-debugger-tree-item-type");
                row.AddToClassList(BuilderConstants.ExplorerHeaderRowClassName);
                labelCont.Add(ssLabel);

                // Register right-click events for context menu actions.
                m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem);

                // Register drag-and-drop events for reparenting.
                m_ExplorerDragger.RegisterCallbacksOnTarget(explorerItem);

                // Allow reparenting.
                explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement);

                var assetIsActiveStyleSheet = styleSheetAsset == m_PaneWindow.document.activeStyleSheet;
                if (assetIsActiveStyleSheet)
                {
                    row.AddToClassList(BuilderConstants.ExplorerActiveStyleSheetClassName);
                }

                if (isPartOfParentDocument)
                {
                    row.AddToClassList(BuilderConstants.ExplorerItemHiddenClassName);
                }

                // Show name of UXML file that USS file 'belongs' to.
                if (!string.IsNullOrEmpty(owningUxmlPath))
                {
                    var pathStr = Path.GetFileName(owningUxmlPath);
                    var label   = new Label(BuilderConstants.TripleSpace + pathStr);
                    label.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                    label.AddToClassList(BuilderConstants.ElementTypeClassName);
                    label.AddToClassList("unity-builder-explorer-tree-item-template-path"); // Just make it look a bit shaded.
                    labelCont.Add(label);
                }

                return;
            }
            else if (BuilderSharedStyles.IsSelectorElement(documentElement))
            {
                var selectorParts = BuilderSharedStyles.GetSelectorParts(documentElement);

                // Register right-click events for context menu actions.
                m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem);

                // Register drag-and-drop events for reparenting.
                m_ExplorerDragger.RegisterCallbacksOnTarget(explorerItem);

                foreach (var partStr in selectorParts)
                {
                    if (partStr.StartsWith(BuilderConstants.UssSelectorClassNameSymbol))
                    {
                        m_ClassPillTemplate.CloneTree(labelCont);
                        var pill      = labelCont.contentContainer.ElementAt(labelCont.childCount - 1);
                        var pillLabel = pill.Q <Label>("class-name-label");
                        pill.name = "unity-builder-tree-class-pill";
                        pill.AddToClassList("unity-debugger-tree-item-pill");
                        pill.SetProperty(BuilderConstants.ExplorerStyleClassPillClassNameVEPropertyName, partStr);
                        pill.userData = documentElement;

                        // Add ellipsis if the class name is too long.
                        var partStrShortened = BuilderNameUtilities.CapStringLengthAndAddEllipsis(partStr, BuilderConstants.ClassNameInPillMaxLength);
                        pillLabel.text = partStrShortened;

                        m_ClassDragger.RegisterCallbacksOnTarget(pill);
                    }
                    else if (partStr.StartsWith(BuilderConstants.UssSelectorNameSymbol))
                    {
                        var selectorPartLabel = new Label(partStr);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementNameClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                    else if (partStr.StartsWith(BuilderConstants.UssSelectorPseudoStateSymbol))
                    {
                        var selectorPartLabel = new Label(partStr);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementPseudoStateClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                    else if (partStr == BuilderConstants.SingleSpace)
                    {
                        var selectorPartLabel = new Label(BuilderConstants.TripleSpace);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementTypeClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                    else
                    {
                        var selectorPartLabel = new Label(partStr);
                        selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        selectorPartLabel.AddToClassList(BuilderConstants.ElementTypeClassName);
                        labelCont.Add(selectorPartLabel);
                    }
                }

                // Allow reparenting.
                explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement);

                // Check if selector element is inside current open StyleSheets
                if (documentElement.IsParentSelector())
                {
                    row.AddToClassList(BuilderConstants.ExplorerItemHiddenClassName);
                }

                return;
            }

            if (BuilderSharedStyles.IsDocumentElement(documentElement))
            {
                var uxmlAsset = documentElement.GetVisualTreeAsset();
                var ssLabel   = new Label(BuilderAssetUtilities.GetVisualTreeAssetAssetName(uxmlAsset, hasUnsavedChanges));
                ssLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                ssLabel.AddToClassList("unity-debugger-tree-item-type");
                row.AddToClassList(BuilderConstants.ExplorerHeaderRowClassName);
                labelCont.Add(ssLabel);

                // Allow reparenting.
                explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement);

                // Register right-click events for context menu actions.
                m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem);

                return;
            }

            // Check if element is inside current document.
            if (!documentElement.IsPartOfActiveVisualTreeAsset(m_PaneWindow.document))
            {
                row.AddToClassList(BuilderConstants.ExplorerItemHiddenClassName);
            }

            // Register drag-and-drop events for reparenting.
            m_ExplorerDragger.RegisterCallbacksOnTarget(explorerItem);

            // Allow reparenting.
            explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement);

            // Element type label.
            if (string.IsNullOrEmpty(documentElement.name) ||
                elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.TypeName))
            {
                var typeLabel = new Label(documentElement.typeName);
                typeLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                typeLabel.AddToClassList(BuilderConstants.ElementTypeClassName);
                labelCont.Add(typeLabel);
            }

            // Element name label.
            var nameLabel = new Label();

            nameLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
            nameLabel.AddToClassList("unity-debugger-tree-item-name-label");
            nameLabel.AddToClassList(BuilderConstants.ExplorerItemNameLabelClassName);
            nameLabel.AddToClassList(BuilderConstants.ElementNameClassName);
            if (!string.IsNullOrEmpty(documentElement.name))
            {
                nameLabel.text = BuilderConstants.UssSelectorNameSymbol + documentElement.name;
            }
            labelCont.Add(nameLabel);

            // Textfield to rename element in hierarchy.
            var renameTextfield = explorerItem.CreateRenamingTextField(documentElement, nameLabel, m_Selection);

            labelCont.Add(renameTextfield);

            // Add class list.
            if (documentElement.classList.Count > 0 && elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.ClassList))
            {
                foreach (var ussClass in documentElement.GetClasses())
                {
                    var classLabelCont = new VisualElement();
                    classLabelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName);
                    explorerItem.Add(classLabelCont);

                    var classLabel = new Label(BuilderConstants.UssSelectorClassNameSymbol + ussClass);
                    classLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                    classLabel.AddToClassList(BuilderConstants.ElementClassNameClassName);
                    classLabel.AddToClassList("unity-debugger-tree-item-classlist-label");
                    classLabelCont.Add(classLabel);
                }
            }

            // Add stylesheets.
            if (elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.StyleSheets))
            {
                var vea = documentElement.GetVisualElementAsset();
                if (vea != null)
                {
                    foreach (var ussPath in vea.GetStyleSheetPaths())
                    {
                        if (string.IsNullOrEmpty(ussPath))
                        {
                            continue;
                        }

                        var classLabelCont = new VisualElement();
                        classLabelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName);
                        explorerItem.Add(classLabelCont);

                        var classLabel = new Label(Path.GetFileName(ussPath));
                        classLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        classLabel.AddToClassList(BuilderConstants.ElementAttachedStyleSheetClassName);
                        classLabel.AddToClassList("unity-debugger-tree-item-classlist-label");
                        classLabelCont.Add(classLabel);
                    }
                }
                else
                {
                    for (int i = 0; i < documentElement.styleSheets.count; ++i)
                    {
                        var attachedStyleSheet = documentElement.styleSheets[i];
                        if (attachedStyleSheet == null)
                        {
                            continue;
                        }

                        var classLabelCont = new VisualElement();
                        classLabelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName);
                        explorerItem.Add(classLabelCont);

                        var classLabel = new Label(attachedStyleSheet.name + BuilderConstants.UssExtension);
                        classLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                        classLabel.AddToClassList(BuilderConstants.ElementAttachedStyleSheetClassName);
                        classLabel.AddToClassList("unity-debugger-tree-item-classlist-label");
                        classLabelCont.Add(classLabel);
                    }
                }
            }

            // Show name of uxml file if this element is a TemplateContainer.
            var       path = documentElement.GetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName) as string;
            Texture2D itemIcon;

            if (documentElement is TemplateContainer && !string.IsNullOrEmpty(path))
            {
                var pathStr = Path.GetFileName(path);
                var label   = new Label(pathStr);
                label.AddToClassList(BuilderConstants.ExplorerItemLabelClassName);
                label.AddToClassList(BuilderConstants.ElementTypeClassName);
                label.AddToClassList("unity-builder-explorer-tree-item-template-path"); // Just make it look a bit shaded.
                labelCont.Add(label);
                itemIcon = BuilderLibraryContent.GetUXMLAssetIcon(path);
            }
            else
            {
                itemIcon = BuilderLibraryContent.GetTypeLibraryIcon(documentElement.GetType());
            }

            // Element icon.
            var icon = new VisualElement();

            icon.AddToClassList(BuilderConstants.ExplorerItemIconClassName);
            var styleBackgroundImage = icon.style.backgroundImage;

            styleBackgroundImage.value = new Background {
                texture = itemIcon
            };
            icon.style.backgroundImage = styleBackgroundImage;
            labelCont.Insert(0, icon);

            // Register right-click events for context menu actions.
            m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem);
        }