/*
 * Copyright 2010 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Alex Wilson, yourpalal2@gmail.com
 *
 * Corresponds to:
 *		headers/os/interface/Layout.h	rev 38207
 *		src/kits/interface/Layout.cpp	rev 38207
 */


/*!
	\file Layout.h
	\ingroup layout
	\ingroup libbe
	\brief Defines the BLayout class.
*/


/*!
	\class BLayout
	\ingroup layout
	\ingroup libbe
	\brief The BLayout class provides an interface, and some basic
		implementation to manage the positioning and sizing of BLayoutItem s.

	BLayouts can be attached to a BView, managing the BLayoutItem's and
	BView's that reside in that view, or can be nested within another
	BLayout as a BLayoutItem.

	Before adding a BLayoutItem to a BLayout, that layout must have a target
	view. When a BLayout is attached directly to a BView via BView::SetLayout()
	then that BView becomes the target of the layout. When a BLayout is nested
	in another BLayout (via BLayout::AddItem()) the nested BLayout inherits the
	target of the layout its nested in, if it does not have a target already.
	You can retrieve the target view for a layout with the TargetView() method.
	When adding a BLayoutItem to a BLayout, the item's view (as returned by
	BLayoutItem::View()) is added to the BLayout's target view.

\code
BView* topView = new BGroupView();
BLayout* topLayout = topView->GetLayout();

BLayout* nestedLayout = new BGroupLayout(B_HORIZONTAL);
topLayout->AddItem(nestedLayout);

BLayout* veryNestedLayout = new BGroupLayout(B_VERTICAL);
nestedLayout->AddItem(veryNestedLayout);
\endcode

	After executing this code, \c veryNestedLayout, \c nestedLayout, and
	\c topLayout all have the same target view: \c topView.

	Continuing with the same objects...

\code
BLayout* nestedLayoutWithView = (new BGroupView())->GetLayout();
topLayout->AddItem(nestedLayoutWithView);
\endcode

	\c nestedLayoutWithView does have a target view of \c topView. This is
	because \c nestedLayoutWithView is attached directly to a BView.

	\warning This class is not yet finalized, if you use it in your software
	assume that it will break some time in the future.

	\since Haiku R1
*/


/*!
	\fn BLayout::BLayout()
	\brief Default constructor.

	After this constructor has finished, this BLayout holds no
	BLayoutItem's and does not have a target BView.

	\warning Because a new BLayout does not have a target BView, calls to the
		AddItem() and AddView() methods will fail.

	\since Haiku R1
*/


/*!
	\fn BLayout::BLayout(BMessage* archive)
	\brief Archive constructor.

	\param archive The archive message.

	\since Haiku R1
*/


/*!
	\fn BLayout::~BLayout()
	\brief Destructor, deletes all BLayoutItem's that this layout manages,
		and detaches from this BLayout's owner view if there is one.

	Each BLayoutItem's BView (as returned by BLayoutItem::View()) is also
	removed from their parent.

	\note Because nested BLayout's are treated as BLayoutItem's,
	any layouts nested in this BLayout will be deleted.

	\since Haiku R1
*/


/*!
	\name BView Targeting and Attachment Information
*/


//! @{


/*!
	\fn BView* BLayout::Owner() const
	\brief Returns the Owner of this layout, i.e. the view this layout manages.

	\since Haiku R1
*/


/*!
	\fn BView* BLayout::TargetView() const
	\brief Returns the target view of this layout.

	The target view of a layout becomes the parent of any BView's in this
	layout, as well as the BView's returned by BLayoutItem::View() for
	each BLayoutItem in this layout.

	\since Haiku R1
*/


/*!
	\fn BView* BLayout::View()
	\brief Returns the same BView* as BLayout::Owner(), this method is
		inherited from BLayoutItem.

	\since Haiku R1
*/


//! @}


/*!
	\name Adding, Removing, Counting and Accessing Children
*/


//! @{


/*!
	\fn BLayoutItem* BLayout::AddView(BView* child)
	\brief Creates a BLayoutItem to represent a BView, and adds that item to
		this layout.

	\a child is added to this BLayout's target view.

	\returns The BLayoutItem created to represent \a child, or \c NULL if there
		was an error.

	\param child The BView to be added to this BLayout.

	\since Haiku R1
*/


/*!
	\fn BLayoutItem* BLayout::AddView(int32 index, BView* child)
	\brief Creates a BLayoutItem to represent \a child, and adds that item at
	       \a index to this layout. \a child is added to this BLayout's target view.

	\since Haiku R1
*/


/*!
	\fn bool BLayout::AddItem(BLayoutItem* item)
	\brief Adds a BLayoutItem to this layout, and adds the BView it represents
		to this BLayout's target view.

	\param item The BLayoutItem to be added.

	\return \c true if the item was added, \c false otherwise.

	\since Haiku R1
*/


/*!
	\fn bool BLayout::AddItem(int32 index, BLayoutItem* item)
	\brief Adds \a item to this layout, and adds the BView \a item represents
		to this BLayout's target view.

	\param item The BLayoutItem to be added.
	\param index The index at which to add \c item.

	If \a index is out of bounds, \a item will be added at the end. If \a index
	is somewhere between the first and last indices, then items from \a index
	to the end will be shuffled over by one.

	\return \c true if the item was added, \c false otherwise.

	\since Haiku R1
*/


/*!
	\fn bool BLayout::RemoveView(BView* child)
	\brief Removes and deletes all BLayoutItem representing a BView from
	       this layout.

	\param child The BView to be removed.

	\return \c true if the item was removed, \c false otherwise.

	\since Haiku R1
*/


/*!
	\fn	bool BLayout::RemoveItem(BLayoutItem* item)
	\brief Removes a BLayoutItem from this layout, and also removes the view
	       it represents from this BLayout's target view.

	\param item The BLayoutItem to be removed

	\warning \a item is not deleted, you must delete it manually, or add it	to
		another BLayout.
	\warning \a item->View(), even when it is removed from the target view,
		is not deleted. If you want it deleted, you must delete it yourself!

	\return \c true if the item was removed, \c false otherwise.

	\since Haiku R1
*/


/*!
	\fn BLayoutItem* BLayout::RemoveItem(int32 index)
	\brief Remove the BLayoutItem at \a index.

	\see RemoveItem(BLayoutItem*)

	\returns The BLayoutItem that was removed.

	\since Haiku R1
*/


/*!
	\fn BLayoutItem* BLayout::ItemAt(int32 index) const
	\brief Get the BLayoutItem at \a index. Returns \c NULL if \a index is
	       out of bounds.

	\since Haiku R1
*/


/*!
	\fn int32 BLayout::CountItems() const
	\brief Get the number of BLayoutItem s in this layout.

	\since Haiku R1
*/


/*!
	\fn int32 BLayout::IndexOfItem(const BLayoutItem* item) const
	\brief Get the index of a BLayoutItem in this layout.

	\param item The BLayoutItem whose index you want.

	\retval -1 \a item was not found in this BLayout.

	\since Haiku R1
*/


/*!
	\fn int32 BLayout::IndexOfView(BView* child) const
	\brief Get the index of \a child in this layout.

	\note This finds the index of views added through BLayout::AddView(), not
		the index of an item which represents \a child that was added through
		BLayout::AddItem().

	\since Haiku R1
*/


//! @}


/*!
	\name Subclass Helpers

	These methods are meant to ease the development of BLayout
	subclasses.
*/


//! @{


/*!
	\fn bool BLayout::AncestorsVisible() const
	\brief Get the visibility of the ancestors of this layout.

	If a BLayout is connected to a BView, this will always return \c true.
	If a BLayout is nested in another layout (it was passed to AddItem()), then
	this will reflect the visibility of this BLayout's parent layout. If
	any layout is hidden (by BLayout::SetVisible()) between this layout and its
	target BView's layout, then this method will return \c false.

	\since Haiku R1
*/


/*!
	\fn BRect BLayout::LayoutArea()
	\brief Returns the on-screen area this layout has received to lay out its
		items in.

	The return value is in the coordinate space of this BLayout's target
	view. If this BLayout is attached directly to a BView, then
	<tt> LayoutArea().LeftTop() == B_ORIGIN </tt>.

	\since Haiku R1
*/


/*!
	\fn void BLayout::VisibilityChanged(bool show)
	\brief Method to be called by derived classes in their SetVisible()
		implementation. Calls AncestorVisibilityChanged() on the items in this
		BLayout.

	\param show \c true to show, \c false to hide.

	\since Haiku R1
*/


//! @}


/*!
	\name Methods Triggering or Related to Laying Out the BLayout
*/


//! @{


/*!
	\fn void BLayout::Relayout(bool immediate = false)
	\brief Request this BLayout to reposition and resize its items as required.

	If \a immediate is \c false, and there is already a request to have the
	window this layout resides in re-laid-out, then the layout will happen at
	that time. If \a immediate is \c true, and there is no such pending
	request, nor is this BLayout's parent layout in the process of laying
	out its items, then this BLayout will now layout its items.

	\param immediate Whether or not to Relayout immediately or wait for pending
	       requests first.

	\since Haiku R1
*/


/*!
	\fn void BLayout::LayoutItems(bool force = false)
	\brief If there is no layout currently ongoing, and \a force is \c false,
	       creates a new BLayoutContext and calls the DoLayout() method
	       of this BLayout and any BLayout's nested in this BLayout.

	This method also guarantees that the owner view of this layout (as returned
	by BLayout::Owner()) performs a layout as well (if it is suitable to do so).

	\param force Force the LayoutItems.

	\since Haiku R1
*/


/*!
	\fn BLayoutContext* BLayout::LayoutContext() const
	\brief Returns the BLayoutContext this BLayout is currently operating in,
		or \c NULL.

	\since Haiku R1
*/


//! @}


/*!
	\name Invalidation and State Mutators and Accessors
*/


//! @{


/*!
	\fn void BLayout::RequireLayout()
	\brief Flag this layout as stale, i.e. any cached data may still be valid,
		but the items need to be repositioned or resized.

	\since Haiku R1
*/


/*!
	\fn void BLayout::InvalidateLayout(bool children = false)
	\brief Invalidate this layout and any cached data this layout has relating
		to positioning and sizing of its items.

	Invalidating a BLayout also invalidates the view it is connected to
	(if there is one) and the BLayout this layout (or this BLayout's view)
	resides in.

	Although this method is virtual, you should not override it, override the
	BLayout::LayoutInvalidated() hook instead.

	This method should be called whenever the layout becomes invalid. This might
	happen if the size constraints of an item in this layout change, this layout
	is given more or less space than it previously had, or an object in this
	layout has had its InvalidateLayout() method called.

	\sa BView::InvalidateLayout(), BLayoutItem::InvalidateLayout(),
		BLayout::LayoutInvalidated()

	\since Haiku R1
*/


/*!
	\fn bool BLayout::IsValid()
	\brief Returns whether this layout has been invalidated (via
	       BLayout::InvalidateLayout()) and has not yet been validated
	       (by doing a layout, or by its ResetLayoutInvalidation() method.

	\since Haiku R1
*/


/*!
	\fn void BLayout::EnableLayoutInvalidation()
	\brief Re-enable layout invalidation after a call to
		DisableLayoutInvalidation().

	\since Haiku R1
*/


/*!
	\fn void BLayout::DisableLayoutInvalidation()
	\brief Disable layout invalidation notifications, i.e. calls to
	       this object's InvalidateLayout() method.

	\since Haiku R1
*/


/*!
	\fn void BLayout::ResetLayoutInvalidation()
	\brief Reset layout invalidation, causing InvalidateLayout calls to proceed
	       again. This method should be called once any cached data has been
	       validated, or updated to valid values.

	\since Haiku R1
*/


//! @}


/*!
	\name Archiving

	These methods relate to the archiving or unarchiving of this object
	and the BLayoutItem's it contains

	\since Haiku R1
*/


//! @{


/*!
	\fn status_t BLayout::Archive(BMessage* archive, bool deep = true) const
	\brief Archives this layout into \a archive. If deep is true, also archives
	       the items in this layout, calling ItemArchived() for each one.

	\since Haiku R1
*/


/*!
	\fn status_t BLayout::AllUnarchived(const BMessage* from)
	\brief Unarchives the BLayoutItem's for this layout, calling
	       ItemUnarchived() for each one.

	\since Haiku R1
*/


/*!
	\fn status_t BLayout::ItemArchived(BMessage* into, BLayoutItem* item,
		int32 index) const
	\brief Hook for derived classes to add data specific to \a item to the
	       \a into BMessage. \a item resides at \a index.

	\note The same archive is passed to BLayout::ItemArchived() for all items,
	so any data added for each item will be stored in an array.

	\since Haiku R1
*/


/*!
	\fn status_t BLayout::ItemUnarchived(const BMessage* from,
		BLayoutItem* item, int32 index)
	\brief Hook for derived classes to retrieve data specific to \a item from
		the \a from BMessage. \a item resides at \a index.

	\note The same archive is passed to BLayout::ItemArchived() for all items,
	      so any data added for each item will be stored in an array. You
	      should pass \a index to the BMessage methods you will be using in
	      this method.

	\since Haiku R1
*/


//! @}


/*!
	\name Hook Methods
*/


//! @{


/*!
	\fn bool BLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
	\brief Hook method called when \a item is added to this layout.

	\param item The BLayoutItem that is being added.
	\param atIndex The index of the BLayoutItem.

	\return \c true on succcess, false if \a item will not be added.

	\note This is a good time to allocate data for a BLayoutItem and attach it
	to \a item via BLayoutItem::SetLayoutData().

	\since Haiku R1
*/


/*!
	\fn void BLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
	\brief Hook method called when \a item is removed from this layout.

	\param item The BLayoutItem being removed.
	\param fromIndex The index where \a item used to reside.

	When this hook is called, \a item is not yet completely removed. It can
	no longer be accessed with LayoutItemAt(), nor does it contribute to the
	value of CountItems(), but the item has not yet had its ItemDetached()
	hook called.

	\note This is a good time to delete the data you've attached to \a item
	via BLayoutItem::SetLayoutData().

	\since Haiku R1
*/


/*!
	\fn void BLayout::DoLayout() = 0
	\brief Implemented by derived classes to position and resize the items in
		this layout.

	\since Haiku R1
*/


/*!
	\fn void BLayout::LayoutInvalidated(bool children)

	Hook method called when this layout becomes invalid. This is a good place
	to clear any caches your object might hold.

	\param children Whether or not child layouts have also been invalidated.

	\since Haiku R1
*/


/*!
	\fn void BLayout::OwnerChanged(BView* was)
	\brief Hook method called when this layout is attached to a BView.

	\param was The previous owner of this BLayout, for new BLayout s, this
	       will be \c NULL.

	\since Haiku R1
*/


/*!
	\fn void BLayout::AttachedToLayout()
	\brief Hook method inherited from BLayoutItem, classes derived from
	       BLayout must include the BLayout version of this method in their
	       implementation.

	\since Haiku R1
*/


/*!
	\fn void BLayout::DetachedFromLayout(BLayout* layout)
	\brief Hook method inherited from BLayoutItem, classes derived from
	       BLayout must include the BLayout version of this method in their
	       implementation.

	\param layout The BLayout that this BLayout was detached from.

	\since Haiku R1
*/


/*!
	\fn void BLayout::AncestorVisibilityChanged(bool shown)
	\brief Hook method inherited from BLayoutItem, classes derived from
	       BLayout must include the BLayout version of this method in their
	       implementation.

	\since Haiku R1
*/


//! @}
