357 lines
12 KiB
C++
357 lines
12 KiB
C++
// This file is part of VSTGUI. It is subject to the license terms
|
|
// in the LICENSE file found in the top-level directory of this
|
|
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
|
|
|
#pragma once
|
|
|
|
#include "vstguifwd.h"
|
|
#include "cview.h"
|
|
#include "cdrawdefs.h"
|
|
#if VSTGUI_TOUCH_EVENT_HANDLING
|
|
#include "itouchevent.h"
|
|
#endif
|
|
#include <list>
|
|
#include <memory>
|
|
#include <optional>
|
|
|
|
namespace VSTGUI {
|
|
|
|
/** Message of a view loosing focus (only CTextEdit and COptionMenu send this) */
|
|
extern IdStringPtr kMsgLooseFocus;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
struct GetViewOptions
|
|
{
|
|
enum {
|
|
kNone = 0,
|
|
kDeep = 1 << 0,
|
|
kMouseEnabled = 1 << 1,
|
|
kIncludeViewContainer = 1 << 2,
|
|
kIncludeInvisible = 1 << 3
|
|
};
|
|
|
|
explicit GetViewOptions (uint32_t options = kNone) : flags (options) {}
|
|
|
|
GetViewOptions& deep (bool state = true) { setBit (flags, kDeep, state); return *this; }
|
|
GetViewOptions& mouseEnabled (bool state = true) { setBit (flags, kMouseEnabled, state); return *this; }
|
|
GetViewOptions& includeViewContainer (bool state = true) { setBit (flags, kIncludeViewContainer, state); return *this; }
|
|
GetViewOptions& includeInvisible (bool state = true) { setBit (flags, kIncludeInvisible, state); return *this; }
|
|
|
|
bool getDeep () const { return hasBit (flags, kDeep); }
|
|
bool getMouseEnabled () const { return hasBit (flags, kMouseEnabled); }
|
|
bool getIncludeViewContainer () const { return hasBit (flags, kIncludeViewContainer); }
|
|
bool getIncludeInvisible () const { return hasBit (flags, kIncludeInvisible); }
|
|
private:
|
|
uint32_t flags;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// CViewContainer Declaration
|
|
//! @brief Container Class of CView objects
|
|
/// @ingroup containerviews
|
|
//-----------------------------------------------------------------------------
|
|
class CViewContainer : public CView
|
|
{
|
|
public:
|
|
using ViewList = std::list<SharedPointer<CView>>;
|
|
|
|
explicit CViewContainer (const CRect& size);
|
|
CViewContainer (const CViewContainer& viewContainer);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// @name Sub View Methods
|
|
//-----------------------------------------------------------------------------
|
|
//@{
|
|
/** add a child view */
|
|
bool addView (CView* pView, const CRect& mouseableArea, bool mouseEnabled = true);
|
|
/** add a child view before another view */
|
|
virtual bool addView (CView* pView, CView* pBefore = nullptr);
|
|
/** remove a child view */
|
|
virtual bool removeView (CView* pView, bool withForget = true);
|
|
/** remove all child views */
|
|
virtual bool removeAll (bool withForget = true);
|
|
/** check if pView is a child view of this container */
|
|
bool isChild (CView* pView) const;
|
|
/** check if pView is a child view of this container */
|
|
virtual bool isChild (CView* pView, bool deep) const;
|
|
/** check if container has child views */
|
|
virtual bool hasChildren () const;
|
|
/** get the number of child views */
|
|
virtual uint32_t getNbViews () const;
|
|
/** get the child view at index */
|
|
virtual CView* getView (uint32_t index) const;
|
|
/** get the view at point where */
|
|
virtual CView* getViewAt (const CPoint& where, const GetViewOptions& options = GetViewOptions ()) const;
|
|
/** get the container at point where */
|
|
virtual CViewContainer* getContainerAt (const CPoint& where, const GetViewOptions& options = GetViewOptions ().deep ()) const;
|
|
/** get all views at point where, top->down */
|
|
virtual bool getViewsAt (const CPoint& where, ViewList& views, const GetViewOptions& options = GetViewOptions ().deep ()) const;
|
|
/** change view z order position */
|
|
virtual bool changeViewZOrder (CView* view, uint32_t newIndex);
|
|
|
|
virtual bool hitTestSubViews (const CPoint& where, const Event& event);
|
|
|
|
/** enable or disable autosizing subviews. Per default this is enabled. */
|
|
virtual void setAutosizingEnabled (bool state);
|
|
bool getAutosizingEnabled () const { return hasViewFlag (kAutosizeSubviews); }
|
|
|
|
/** get child views of type ViewClass. ContainerClass must be a stdc++ container */
|
|
template<class ViewClass, class ContainerClass>
|
|
uint32_t getChildViewsOfType (ContainerClass& result, bool deep = false) const;
|
|
|
|
/** execute proc for each child view */
|
|
template<typename Proc>
|
|
void forEachChild (Proc proc) const;
|
|
|
|
template<typename Proc>
|
|
CView* findFirstViewIf (Proc filter) const;
|
|
|
|
//@}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// @name View Layouter Methods
|
|
//-----------------------------------------------------------------------------
|
|
//@{
|
|
/** set a view layouter
|
|
*
|
|
* Per default the view container has an AutoSizeLayouter set.
|
|
* Use this method to set a custom layouter.
|
|
* To reset the layouter to the default AutoSizeLayouter use setViewLayouter (nullptr).
|
|
*/
|
|
void setViewLayouter (const SharedPointer<IViewLayouter>& layouter);
|
|
/** get the current view layouter */
|
|
SharedPointer<IViewLayouter> getViewLayouter () const;
|
|
/** calculate the view layout for the new size */
|
|
std::optional<ViewLayout> calculateViewLayout (const CRect& newSize) const;
|
|
/** apply a previously calculated view layout */
|
|
bool applyViewLayout (const ViewLayout& layout);
|
|
/** check if a view layout is currently applied */
|
|
bool inApplyViewLayout () const;
|
|
//@}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// @name Background Methods
|
|
//-----------------------------------------------------------------------------
|
|
//@{
|
|
/** set the background color (will only be drawn if this container is not set to transparent and does not have a background bitmap) */
|
|
virtual void setBackgroundColor (const CColor& color);
|
|
/** get the background color */
|
|
virtual CColor getBackgroundColor () const;
|
|
/** set the offset of the background bitmap */
|
|
virtual void setBackgroundOffset (const CPoint& p);
|
|
/** get the offset of the background bitmap */
|
|
virtual CPoint getBackgroundOffset () const;
|
|
/** draw the background */
|
|
virtual void drawBackgroundRect (CDrawContext* pContext, const CRect& _updateRect);
|
|
|
|
virtual void setBackgroundColorDrawStyle (CDrawStyle style);
|
|
CDrawStyle getBackgroundColorDrawStyle () const;
|
|
//@}
|
|
|
|
/** set custom initial focus view
|
|
* which is first focused when advanceNextFocusView is called without oldFocus view
|
|
*/
|
|
void setInitialFocusView (CView* view);
|
|
/** get custom initial focus view */
|
|
CView* getInitialFocusView () const;
|
|
|
|
virtual bool advanceNextFocusView (CView* oldFocus, bool reverse = false);
|
|
virtual bool invalidateDirtyViews ();
|
|
virtual CRect getVisibleSize (const CRect& rect) const;
|
|
|
|
void setTransform (const CGraphicsTransform& t);
|
|
const CGraphicsTransform& getTransform () const;
|
|
|
|
void registerViewContainerListener (IViewContainerListener* listener);
|
|
void unregisterViewContainerListener (IViewContainerListener* listener);
|
|
|
|
// CView
|
|
void draw (CDrawContext* pContext) override;
|
|
void drawRect (CDrawContext* pContext, const CRect& updateRect) override;
|
|
void onMouseDownEvent (MouseDownEvent& event) override;
|
|
void onMouseMoveEvent (MouseMoveEvent& event) override;
|
|
void onMouseUpEvent (MouseUpEvent& event) override;
|
|
void onMouseCancelEvent (MouseCancelEvent& event) override;
|
|
void onMouseWheelEvent (MouseWheelEvent& event) override;
|
|
void onZoomGestureEvent (ZoomGestureEvent& event) override;
|
|
CMessageResult notify (CBaseObject* sender, IdStringPtr message) override;
|
|
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
bool onWheel (const CPoint& where, const CMouseWheelAxis& axis, const float& distance,
|
|
const CButtonState& buttons) final;
|
|
#endif
|
|
#if VSTGUI_TOUCH_EVENT_HANDLING
|
|
virtual void onTouchEvent (ITouchEvent& event) override;
|
|
virtual bool wantsMultiTouchEvents () const override { return true; }
|
|
virtual bool findSingleTouchEventTarget (ITouchEvent::Touch& event);
|
|
#endif
|
|
|
|
SharedPointer<IDropTarget> getDropTarget () override;
|
|
|
|
void looseFocus () override;
|
|
void takeFocus () override;
|
|
|
|
bool isDirty () const override;
|
|
|
|
void invalid () override;
|
|
void invalidRect (const CRect& rect) override;
|
|
|
|
void setViewSize (const CRect& rect, bool invalid = true) override;
|
|
void parentSizeChanged () override;
|
|
bool sizeToFit () override;
|
|
|
|
bool removed (CView* parent) override;
|
|
bool attached (CView* parent) override;
|
|
|
|
CPoint& frameToLocal (CPoint& point) const override;
|
|
CPoint& localToFrame (CPoint& point) const override;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
using ChildViewConstIterator = ViewList::const_iterator;
|
|
using ChildViewConstReverseIterator = ViewList::const_reverse_iterator;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<bool reverse>
|
|
class Iterator
|
|
{
|
|
public:
|
|
using IteratorType = typename std::conditional<reverse, ChildViewConstReverseIterator,
|
|
ChildViewConstIterator>::type;
|
|
|
|
explicit Iterator (const CViewContainer* container) : children (container->getChildren ())
|
|
{
|
|
if constexpr (reverse)
|
|
iterator = children.rbegin ();
|
|
else
|
|
iterator = children.begin ();
|
|
}
|
|
|
|
explicit Iterator (const Iterator<reverse>& vi)
|
|
: children (vi.children), iterator (vi.iterator)
|
|
{
|
|
}
|
|
|
|
Iterator (Iterator<reverse>&& o) : children (o.children), iterator (std::move (o.iterator))
|
|
{
|
|
}
|
|
|
|
Iterator<reverse>& operator++ ()
|
|
{
|
|
++iterator;
|
|
return *this;
|
|
}
|
|
|
|
Iterator<reverse> operator++ (int)
|
|
{
|
|
Iterator<reverse> old (*this);
|
|
++iterator;
|
|
return old;
|
|
}
|
|
|
|
Iterator<reverse>& operator-- ()
|
|
{
|
|
--iterator;
|
|
return *this;
|
|
}
|
|
|
|
CView* operator* () const
|
|
{
|
|
if constexpr (reverse)
|
|
return (iterator == children.rend ()) ? nullptr : *iterator;
|
|
else
|
|
return (iterator == children.end ()) ? nullptr : *iterator;
|
|
}
|
|
|
|
protected:
|
|
const ViewList& children;
|
|
IteratorType iterator;
|
|
};
|
|
|
|
//-------------------------------------------
|
|
CLASS_METHODS(CViewContainer, CView)
|
|
|
|
#if DEBUG
|
|
void dumpInfo () override;
|
|
virtual void dumpHierarchy ();
|
|
#endif
|
|
|
|
CViewContainer* asViewContainer () final { return this; }
|
|
const CViewContainer* asViewContainer () const final { return this; }
|
|
|
|
protected:
|
|
enum
|
|
{
|
|
kAutosizeSubviews = 1 << (CView::kLastCViewFlag + 1),
|
|
kInApplyLayout = 1 << (CView::kLastCViewFlag + 2),
|
|
};
|
|
|
|
~CViewContainer () noexcept override;
|
|
void beforeDelete () override;
|
|
|
|
virtual bool checkUpdateRect (CView* view, const CRect& rect);
|
|
|
|
void setMouseDownView (CView* view);
|
|
CView* getMouseDownView () const;
|
|
|
|
const ViewList& getChildren () const;
|
|
private:
|
|
static constexpr CViewAttributeID kInitialFocusViewAttribute = 'cifv';
|
|
|
|
void dispatchEventToSubViews (Event& event);
|
|
|
|
void clearMouseDownView ();
|
|
CRect getLastDrawnFocus () const;
|
|
void setLastDrawnFocus (CRect r);
|
|
|
|
struct Impl;
|
|
std::unique_ptr<Impl> pImpl;
|
|
};
|
|
|
|
using ViewIterator = CViewContainer::Iterator<false>;
|
|
using ReverseViewIterator = CViewContainer::Iterator<true>;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class ViewClass, class ContainerClass>
|
|
inline uint32_t CViewContainer::getChildViewsOfType (ContainerClass& result, bool deep) const
|
|
{
|
|
for (auto& child : getChildren ())
|
|
{
|
|
auto vObj = child.cast<ViewClass> ();
|
|
if (vObj)
|
|
{
|
|
result.push_back (vObj);
|
|
}
|
|
if (deep)
|
|
{
|
|
if (auto container = child->asViewContainer ())
|
|
{
|
|
container->getChildViewsOfType<ViewClass, ContainerClass> (result, deep);
|
|
}
|
|
}
|
|
}
|
|
return static_cast<uint32_t> (result.size ());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename Proc>
|
|
inline void CViewContainer::forEachChild (Proc proc) const
|
|
{
|
|
for (auto& child : getChildren ())
|
|
{
|
|
proc (child);
|
|
}
|
|
}
|
|
|
|
template<typename Proc>
|
|
inline CView* CViewContainer::findFirstViewIf (Proc filter) const
|
|
{
|
|
for (const auto& child : getChildren ())
|
|
{
|
|
if (filter (child))
|
|
return child;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
} // VSTGUI
|