void WgPackList::_renderPatches( WgGfxDevice * pDevice, const WgRect& _canvas, const WgRect& _window, WgPatches * _pPatches )
{
	// We start by eliminating dirt outside our geometry

	WgPatches 	patches( _pPatches->Size() );								// TODO: Optimize by pre-allocating?

	for( const WgRect * pRect = _pPatches->Begin() ; pRect != _pPatches->End() ; pRect++ )
	{
		if( _canvas.IntersectsWith( *pRect ) )
			patches.Push( WgRect(*pRect,_canvas) );
	}

	// Render container itself
	
	for( const WgRect * pRect = patches.Begin() ; pRect != patches.End() ; pRect++ )
		_onRender(pDevice, _canvas, _window, *pRect );
		
	
	// Render children

	WgRect	dirtBounds = patches.Union();
	
	{
		WgRect childGeo;
		WgPackListHook * p = (WgPackListHook*)_firstHookWithGeo( childGeo );

		while(p)
		{
			WgRect canvas = childGeo + _canvas.Pos();
			if( p->_isVisible() && canvas.IntersectsWith( dirtBounds ) )
				p->_widget()->_renderPatches( pDevice, canvas, canvas, &patches );
			p = (WgPackListHook*) _nextHookWithGeo( childGeo, p );
		}
	}

	// Render header

	if( m_header.m_height != 0 )
	{
		bool bInvertedSort = (m_sortOrder == WG_SORT_DESCENDING);
		WgRect canvas = _headerGeo() + _canvas.Pos();

		for( const WgRect * pRect = patches.Begin() ; pRect != patches.End() ; pRect++ )
			_renderHeader( pDevice, canvas, *pRect, m_header.m_pSkin, &m_header.label, &m_header.icon, &m_header.arrow, m_header.m_state, true, bInvertedSort );
	}

	// Render Lasso

	if( m_pLassoSkin && m_lassoBegin != m_lassoEnd )
	{
		WgRect lasso( m_lassoBegin, m_lassoEnd );
		lasso += _canvas.Pos();


		for( const WgRect * pRect = patches.Begin() ; pRect != patches.End() ; pRect++ )
			m_pLassoSkin->Render( pDevice, lasso, m_state, WgRect( lasso, *pRect ) );
	}
}
void WgPackList::_onMaskPatches( WgPatches& patches, const WgRect& geo, const WgRect& clip, WgBlendMode blendMode )
{
	if( (m_bOpaque && blendMode == WG_BLENDMODE_BLEND) || blendMode == WG_BLENDMODE_OPAQUE)
		patches.Sub( WgRect(geo,clip) );
	else if( m_bOpaqueEntries && blendMode == WG_BLENDMODE_BLEND )
	{
		if( m_bHorizontal )
			patches.Sub( WgRect( WgRect( geo.x, geo.y, WgMin(geo.w,m_contentLength), geo.h ), clip ) );
		else
			patches.Sub( WgRect( WgRect( geo.x, geo.y, geo.w, WgMin(geo.h,m_contentLength) ), clip ) );
	}
	else
	{
		WgRect childGeo;
		WgPackListHook * p = static_cast<WgPackListHook*>(_firstHookWithGeo( childGeo ));

		while(p)
		{
			if( p->_isVisible() )
				p->_widget()->_onMaskPatches( patches, childGeo + geo.Pos(), clip, blendMode );
			p = static_cast<WgPackListHook*>(_nextHookWithGeo( childGeo, p ));
		}
	}

}
Exemple #3
0
void WgPanel::_onMaskPatches( WgPatches& patches, const WgRect& geo, const WgRect& clip, WgBlendMode blendMode )
{
	//TODO: Don't just check IsOpaque() globally, check rect by rect.
	if( (m_bOpaque && blendMode == WG_BLENDMODE_BLEND) || blendMode == WG_BLENDMODE_OPAQUE )
	{
		patches.Sub( WgRect(geo,clip) );
		return;
	}
	
	switch( m_maskOp )
	{
		case WG_MASKOP_RECURSE:
		{
			WgRect childGeo;
			WgPanelHook * p = static_cast<WgPanelHook*>(_firstHookWithGeo( childGeo ));

			while(p)
			{
				if( p->IsVisible() )
					p->_widget()->_onMaskPatches( patches, childGeo + geo.Pos(), clip, blendMode );
				p = static_cast<WgPanelHook*>(_nextHookWithGeo( childGeo, p ));
			}
			break;
		}
		case WG_MASKOP_SKIP:
			break;
		case WG_MASKOP_MASK:
			patches.Sub( WgRect(geo,clip) );
			break;
	}
}
void WgPackList::_onRender( WgGfxDevice * pDevice, const WgRect& _canvas, const WgRect& _window, const WgRect& _clip )
{
	WgRect contentRect = _listCanvas() + _canvas.Pos();

	if( m_pSkin )
	{
		m_pSkin->Render( pDevice, contentRect, m_state, _clip );
		contentRect = m_pSkin->ContentRect( contentRect, m_state );
	}

	int startOfs = m_bHorizontal ? _clip.x-contentRect.x : _clip.y-contentRect.y;
	if( startOfs < 0 )
		startOfs = 0;

	for( int i = _getEntryAt( startOfs ) ; i < m_hooks.Size() ; i++ )
	{
		WgPackListHook * pHook = m_hooks.Hook(i);
		WgWidget * pChild = pHook->_widget();

		// Get entry geometry, skin and state

		WgRect entryGeo( contentRect );
		if( m_bHorizontal )
		{
			if( pHook->m_ofs >= contentRect.w )
				break;

			entryGeo.x += pHook->m_ofs;
			entryGeo.w = pHook->m_length;
		}
		else
		{
			if( pHook->m_ofs >= contentRect.h )
				break;

			entryGeo.y += pHook->m_ofs;
			entryGeo.h = pHook->m_length;
		}
		
		WgSkin * pEntrySkin	= m_pEntrySkin[i&0x1].RawPtr();
		WgState	state		= pChild->State();
//		WgRect	childGeo( entryGeo );

		// Render entry skin, shrink child geo

		if( pEntrySkin )
		{
			pEntrySkin->Render( pDevice, entryGeo, state, _clip );
//			childGeo = pEntrySkin->ContentRect( entryGeo, state );
		}

		// Render child

//		pChild->_onRender( pDevice, childGeo, childGeo, _clip );

	}
}
WgWidget * WgPackList::_findWidget( const WgCoord& ofs, WgSearchMode mode )
{
	WgWidget * pResult = 0;
	WgRect list = _listArea();

	if( list.Contains(ofs) && _listWindow().Contains(ofs) )
	{
		int entry;
		if( m_bHorizontal )
			entry = _getEntryAt(ofs.x-list.x);
		else
			entry = _getEntryAt(ofs.y-list.y);

		if( entry != m_hooks.Size() )
		{
			WgPackListHook * pHook = m_hooks.Hook(entry);
			WgRect childGeo;
			_getChildGeo( childGeo, pHook );
			if( childGeo.Contains(ofs) )
			{
				if( pHook->_widget()->IsContainer() )
				{
					pResult = static_cast<WgContainer*>(pHook->_widget())->_findWidget( ofs - childGeo.Pos(), mode );
				}
				else if( mode == WG_SEARCH_GEOMETRY || pHook->_widget()->MarkTest( ofs - childGeo.Pos() ) )
				{
						pResult = pHook->_widget();
				}
			}

			if( !pResult && mode == WG_SEARCH_ACTION_TARGET )
				pResult = pHook->_widget();						// Entries are opaque as action targets.

		}
	}

	// Check against ourselves

	if( !pResult && ( mode == WG_SEARCH_GEOMETRY || MarkTest(ofs)) )
		pResult = this;
		
	return pResult;
}
WgWidget *  WgPopupLayer::_findWidget( const WgCoord& ofs, WgSearchMode mode )
{
	// MenuPanel has its own _findWidget() method since we need special treatment of
	// searchmode ACTION_TARGET when a menu is open.

	if( mode == WG_SEARCH_ACTION_TARGET && !m_popupHooks.IsEmpty() )
	{
		// In search mode ACTION_TARGET we limit our target to us, our menu-branches and the menu-opener if a menu is open.

		WgPopupHook * pHook = m_popupHooks.Last();
		WgWidget * pResult = 0;

		while( pHook && !pResult )
		{
			if( pHook->m_geo.Contains( ofs ) )
			{
				if( pHook->_widget()->IsContainer() )
					pResult = static_cast<WgContainer*>(pHook->_widget())->_findWidget( ofs - pHook->m_geo.Pos(), mode );
				else if( pHook->_widget()->MarkTest( ofs - pHook->m_geo.Pos() ) )
					pResult = pHook->_widget();
			}
			pHook = pHook->_prev();
		}

		if( pResult == 0 )
		{
			// Check the first opener
			
			WgPopupHook * pHook = m_popupHooks.First();
			if( pHook && pHook->m_pOpener )
			{
				WgWidget * pOpener = pHook->m_pOpener.RawPtr();

				WgCoord absPos 		= ofs + GlobalPos();
				WgRect	openerGeo 	= pOpener->GlobalGeo();

				if( openerGeo.Contains(absPos) && pOpener->MarkTest( absPos - openerGeo.Pos() ) )
					pResult = pOpener;
			}
			
			// Fall back to us.
			
			if( pResult == 0 )
				pResult = this;
		}
		return pResult;
	}
	else
	{
		// For the rest of the modes we can rely on the default method.

		return WgContainer::_findWidget( ofs, mode );
	}
}
WgCoord WgPackListHook::GlobalPos() const
{
	WgRect	geo;
	m_pParent->_getChildGeo(geo,this);
	return m_pParent->GlobalPos() + geo.Pos();
}