| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- #pragma once
- #include "BsEditorPrerequisites.h"
- #include "BsGUIElementContainer.h"
- #include "BsVirtualInput.h"
- #include "BsEvent.h"
- namespace BansheeEngine
- {
- /**
- * @brief GUI element that displays some contents in a tree-view where elements
- * are placed vertically above/beneath each other, and different elements
- * may be nested within other elements.
- *
- * Elements may be selected, renamed, dragged and re-parented.
- *
- * This class is abstract and meant to be extended by an implementation
- * specific to some content type (e.g. scene object hierarchy).
- */
- class BS_ED_EXPORT GUITreeView : public GUIElementContainer
- {
- protected:
- /**
- * @brief Types of possible states when the tree view is auto-scrolling.
- */
- enum class ScrollState
- {
- None,
- Up,
- Down,
- TransitioningUp,
- TransitioningDown
- };
- /**
- * @brief Contains data about a single piece of content
- * and all its children. This element may be visible and represented
- * by a GUI element, but might not (e.g. its parent is collapsed).
- */
- struct TreeElement
- {
- TreeElement();
- virtual ~TreeElement();
- TreeElement* mParent;
- Vector<TreeElement*> mChildren;
- GUIToggle* mFoldoutBtn;
- GUILabel* mElement;
- String mName;
- UINT32 mSortedIdx;
- bool mIsExpanded;
- bool mIsSelected;
- bool mIsHighlighted;
- bool mIsVisible;
- bool mIsGrayedOut;
- Color mTint;
- bool isParentRec(TreeElement* element) const;
- };
- /**
- * @brief Contains data about all visible elements in the tree view.
- * This might be a TreeElement entry, or a separator (empty space)
- * between two TreeElement%s.
- */
- struct InteractableElement
- {
- InteractableElement(TreeElement* parent, UINT32 index, const Rect2I& bounds)
- :parent(parent), index(index), bounds(bounds)
- { }
- bool isTreeElement() const { return index % 2 == 1; }
- TreeElement* getTreeElement() const;
- TreeElement* parent;
- UINT32 index;
- Rect2I bounds;
- };
- /**
- * @brief Contains data about one of the currently selected tree elements.
- */
- struct SelectedElement
- {
- SelectedElement()
- :element(nullptr), background(nullptr)
- { }
- SelectedElement(TreeElement* elem, GUITexture* back)
- :element(elem), background(back)
- { }
- TreeElement* element;
- GUITexture* background;
- };
- public:
- /**
- * Returns type name of the GUI element used for finding GUI element styles.
- */
- static const String& getGUITypeName();
- /**
- * @brief Updates tree view if dirty, among other operations.
- * Must be called every frame.
- *
- * @note Internal method.
- */
- void _update();
- protected:
- GUITreeView(const String& backgroundStyle, const String& elementBtnStyle,
- const String& foldoutBtnStyle, const String& highlightBackgroundStyle, const String& selectionBackgroundStyle, const String& editBoxStyle,
- const String& dragHighlightStyle, const String& dragSepHighlightStyle, const GUIDimensions& dimensions);
- virtual ~GUITreeView();
- /**
- * @copydoc GUIElement::_getOptimalSize
- */
- Vector2I _getOptimalSize() const override;
- /**
- * @copydoc GUIElement::updateClippedBounds
- */
- void updateClippedBounds() override;
- /**
- * @copydoc GUIElement::_updateLayoutInternal
- */
- virtual void _updateLayoutInternal(const GUILayoutData& data) override;
- /**
- * @copydoc GUIElement::_mouseEvent
- */
- virtual bool _mouseEvent(const GUIMouseEvent& ev) override;
- /**
- * @copydoc GUIElement::_commandEvent
- */
- virtual bool _commandEvent(const GUICommandEvent& ev) override;
- /**
- * @copydoc GUIElement::_virtualButtonEvent
- */
- virtual bool _virtualButtonEvent(const GUIVirtualButtonEvent& ev) override;
- /**
- * @brief Attempts to find an interactable element under the specified coordinates.
- * Returns null if one cannot be found.
- *
- * @param coord Coordinates relative to parent GUI widget.
- */
- const GUITreeView::InteractableElement* findElementUnderCoord(const Vector2I& coord) const;
- /**
- * @brief Returns the top-most selected tree element if selection is active,
- * null otherwise.
- */
- TreeElement* getTopMostSelectedElement() const;
- /**
- * @brief Returns the bottom-most selected tree element if selection is active,
- * null otherwise.
- */
- TreeElement* getBottomMostSelectedElement() const;
- /**
- * @brief Starts rename operation on the specified tree element, spawning an input box.
- */
- void enableEdit(TreeElement* element);
- /**
- * @brief Ends rename operation if one is currently active.
- *
- * @param acceptChanges Should the new name be accepted or discarded.
- */
- void disableEdit(bool acceptChanges);
- /**
- * @brief Triggered when the Foldout button for a tree element was been toggled.
- * (i.e. something was expanded or collapsed).
- */
- void elementToggled(TreeElement* element, bool toggled);
- /**
- * @brief Returns the top level TreeElement.
- */
- virtual TreeElement& getRootElement() = 0;
- /**
- * @brief Returns the top level TreeElement that cannot be modified.
- */
- virtual const TreeElement& getRootElementConst() const = 0;
- /**
- * @brief Checks if the hierarchy needs any updates and performs those
- * updates if needed.
- */
- virtual void updateTreeElementHierarchy() = 0;
- /**
- * @brief Changes the name of the content associated with the provided tree element.
- */
- virtual void renameTreeElement(TreeElement* element, const WString& name) = 0;
- /**
- * @brief Deletes the content associated with the provided tree element.
- */
- virtual void deleteTreeElement(TreeElement* element) = 0;
- /**
- * @brief Checks whether the tree view can accept the currently active drag and drop
- * operation.
- */
- virtual bool acceptDragAndDrop() const = 0;
- /**
- * @brief Triggered when the user drags a tree element and starts a drag and drop operation.
- */
- virtual void dragAndDropStart() = 0;
- /**
- * @brief Triggered when the user ends a drag and drop operation over the tree view.
- *
- * @param overTreeElement TreeElement the drag operation ended over, if any.
- */
- virtual void dragAndDropEnded(TreeElement* overTreeElement) = 0;
- /**
- * @brief Triggered whenever a TreeElement gets selected or deselected.
- */
- virtual void selectionChanged() { }
- /**
- * @brief Are any tree elements currently selected.
- */
- bool isSelectionActive() const;
- /**
- * @brief Expands the selection to the provided TreeElement. Doesn't clear
- * previous selection.
- */
- void selectElement(TreeElement* element);
- /**
- * @brief Unselects the provided TreeElement.
- */
- void unselectElement(TreeElement* element);
- /**
- * @brief Unselects all selected TreeElement%s.
- *
- * @param sendEvent Determines should the external world be notified of this change.
- */
- void unselectAll(bool sendEvent = true);
- /**
- * @brief Starts rename operation on the currently selected element.
- */
- void renameSelected();
- /**
- * @brief Deletes all currently selected elements.
- */
- void deleteSelection();
- /**
- * @brief Expands all parents of the provided TreeElement making it interactable.
- */
- void expandToElement(TreeElement* element);
- /**
- * @brief Expands the provided TreeElement making its children interactable.
- */
- void expandElement(TreeElement* element);
- /**
- * @brief Collapses the provided TreeElement making its children hidden and not interactable.
- */
- void collapseElement(TreeElement* element);
- /**
- * @brief Duplicates the currently selected entries.
- */
- virtual void duplicateSelection() { }
- /**
- * @brief Marks the current selection for copying.
- */
- virtual void copySelection() { }
-
- /**
- * @brief Marks the current selection for cutting.
- */
- virtual void cutSelection() { }
- /**
- * @brief Pastes a set of entries previously marked for cut or copy.
- */
- virtual void paste() { }
- /**
- * @brief Rebuilds the needed GUI elements for the provided TreeElement.
- */
- void updateElementGUI(TreeElement* element);
- /**
- * @brief Close any elements that were temporarily expanded due to a drag operation
- * hovering over them.
- */
- void closeTemporarilyExpandedElements();
- /**
- * @brief Temporarily expand the provided element. Temporarily expanded elements can be
- * closed by calling ::closeTemporarilyExpandedElements.
- */
- void temporarilyExpandElement(const GUITreeView::InteractableElement* mouseOverElement);
- /**
- * @brief Scrolls the parent GUIScrollArea (if any) so that the specified TreeElement is visible.
- *
- * @param element Element to scroll to.
- * @param center If true the element will be centered in the scroll view,
- * otherwise it will be at the top.
- */
- void scrollToElement(TreeElement* element, bool center);
- /**
- * @brief Attempts to find the parent GUIScrollArea that the tree view is a child of.
- */
- GUIScrollArea* findParentScrollArea() const;
- /**
- * @brief Scrolls the tree view to the specified element and highlights it.
- */
- void ping(TreeElement* element);
- /**
- * @brief Clears the ping highlight on the currently highlighted element.
- */
- void clearPing();
- /**
- * @brief Triggered when the user accepts the changes during a rename operation.
- */
- void onEditAccepted();
- /**
- * @brief Triggered when the user rejects the changes during a rename operation.
- */
- void onEditCanceled();
- /**
- * @brief Triggered when the user clicks outside of the edit box during a rename operation.
- */
- void onEditFocusLost();
- String mBackgroundStyle;
- String mElementBtnStyle;
- String mFoldoutBtnStyle;
- String mSelectionBackgroundStyle;
- String mHighlightBackgroundStyle;
- String mEditBoxStyle;
- String mDragHighlightStyle;
- String mDragSepHighlightStyle;
- GUITexture* mBackgroundImage;
- Vector<InteractableElement> mVisibleElements;
- bool mIsElementSelected;
- Vector<SelectedElement> mSelectedElements;
- bool mIsElementHighlighted;
- SelectedElement mHighlightedElement;
- TreeElement* mEditElement;
- GUITreeViewEditBox* mNameEditBox;
- Vector2I mDragStartPosition;
- Vector2I mDragPosition;
- bool mDragInProgress;
- GUITexture* mDragHighlight;
- GUITexture* mDragSepHighlight;
- Rect2I mTopScrollBounds;
- Rect2I mBottomScrollBounds;
- ScrollState mScrollState;
- float mLastScrollTime;
- Stack<TreeElement*> mAutoExpandedElements;
- TreeElement* mMouseOverDragElement;
- float mMouseOverDragElementTime;
- static VirtualButton mRenameVB;
- static VirtualButton mDeleteVB;
- static VirtualButton mDuplicateVB;
- static VirtualButton mCutVB;
- static VirtualButton mCopyVB;
- static VirtualButton mPasteVB;
- static const UINT32 ELEMENT_EXTRA_SPACING;
- static const UINT32 INDENT_SIZE;
- static const UINT32 INITIAL_INDENT_OFFSET;
- static const UINT32 DRAG_MIN_DISTANCE;
- static const float AUTO_EXPAND_DELAY_SEC;
- static const float SCROLL_AREA_HEIGHT_PCT;
- static const UINT32 SCROLL_SPEED_PX_PER_SEC;
- static const Color GRAYED_OUT_COLOR;
- };
- }
|