void WgStackPanel::_onRenderRequested( WgVectorHook * _pHook, const WgRect& _rect ) { WgStackHook * pHook = static_cast<WgStackHook*>(_pHook); if( !pHook->IsVisible() ) return; // Put our rectangle into patches WgRect rect = _rect + pHook->_getGeo(WgRect(0,0,m_size)).Pos(); WgPatches patches; patches.Add( rect ); // Remove portions of patches that are covered by opaque upper siblings WgStackHook * pCover = ((WgStackHook*)pHook)->_next(); while( pCover ) { WgRect geo = pCover->_getGeo(m_size); if( pCover->IsVisible() && geo.IntersectsWith( rect ) ) pCover->_widget()->_onMaskPatches( patches, geo, WgRect(0,0,65536,65536 ), _getBlendMode() ); pCover = pCover->_next(); } // Make request render calls for( const WgRect * pRect = patches.Begin() ; pRect < patches.End() ; pRect++ ) _requestRender( * pRect ); }
WgTab * WgTablist::_pos2Tab( int x, int y ) const { if( x < 0 || y < 0 ) return 0; bool bMovingUp = true; WgTab * pHit = NULL; WgTab * pTab = m_tabs.First(); WgSize sz = Size(); while( pTab ) { if(pTab->m_bVisible) { // if(pTab == m_pTabSelected) // bMovingUp = false; WgSkinPtr pSrc = _tabSkin(pTab); bool bHit = false; // Tab is hit if position is on a non-transparent (alpha != 0) pixel of the block // or inside tabs text-area. WgRect tabCanvas = WgRect(0,0,pTab->m_width,sz.h); WgRect tabContent; if( pSrc ) tabContent = pSrc->ContentRect( tabCanvas, _tabState(*pTab) ); else tabContent = tabCanvas; if( m_bTabOpaqueForMouse && tabCanvas.Contains(x,y) ) bHit = true; else if( tabContent.Contains( WgCoord(x,y) ) ) bHit = true; else if( pSrc ) bHit = pSrc->MarkTest( WgCoord(x,y), tabCanvas, _tabState(*pTab), m_markOpacity ); if( bHit ) { /* // Handle overlap if(bMovingUp) pHit = pTab; else return pTab; */ if( pTab == m_pTabSelected ) return pTab; else pHit = pTab; } x -= pTab->m_advance; } pTab = pTab->Next(); } return pHit; }
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 ); } }
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::_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 )); } } }
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 ); } }
WgListHook * WgPackList::_findEntry( const WgCoord& ofs ) { 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() ) return m_hooks.Hook(entry); } return 0; }
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 ) ); } }
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; }
void WgGfxDevice::ClipTileBlit( const WgRect& _clip, const WgSurfacePtr& _pSrc, const WgRect& _src, const WgRect& _dest ) { if( !_pSrc ) return; WgRect myRect; WgRect clip; if( !clip.Intersection( _dest, _clip ) ) return; // Take care of start-offset change caused by clipping. int xStart = (clip.x - _dest.x) % _src.w; if( xStart < 0 ) xStart += _src.w; xStart += _src.x; int yStart = (clip.y - _dest.y) % _src.h; if( yStart < 0 ) yStart += _src.h; yStart += _src.y; int destY = clip.y, destX; myRect.y = yStart; myRect.h =_src.y + _src.h - yStart; while( destY < clip.y + clip.h ) { if( myRect.h > clip.y + clip.h - destY ) myRect.h = clip.y + clip.h - destY; myRect.x = xStart; myRect.w = _src.x + _src.w - xStart; if( myRect.w > clip.w ) myRect.w = clip.w; // Blit a row. destX = clip.x; Blit( _pSrc, myRect, destX, destY ); destX += myRect.w; myRect.x = _src.x; myRect.w = _src.w; while( destX <= clip.x + clip.w - _src.w ) { Blit( _pSrc, myRect, destX, destY ); destX += myRect.w; } myRect.w = clip.x + clip.w - destX; if( myRect.w > 0 ) Blit( _pSrc, myRect, destX, destY ); destY += myRect.h; myRect.y = _src.y; myRect.h = _src.h; } return; }
void WgMenubar::_onRender( WgGfxDevice * pDevice, const WgRect& _canvas, const WgRect& _window, const WgRect& _clip ) { WgWidget::_onRender(pDevice,_canvas,_window,_clip); // Take backgrounds content borders into account WgRect window; WgRect clip; if( m_pSkin ) { window = m_pSkin->ContentRect( _canvas, m_state ); clip.Intersection( window, _clip ); } else { window = _canvas; clip = _clip; } // Go throught the MenuBarItems and print their text and render their rectangles. WgMenuBarItem * pI = m_items.First(); Uint32 posX = window.x; WgPen pen; WgTextAttr attr; WgTextTool::AddPropAttributes( attr, WgBase::GetDefaultTextprop(), WG_STATE_NORMAL); WgTextTool::AddPropAttributes( attr, m_pTextProp, WG_STATE_NORMAL); pen.SetAttributes( attr ); pen.SetClipRect( clip ); pen.SetDevice( pDevice ); Uint32 printPosY = window.y + ( window.h - pen.GetLineHeight() )/2 + pen.GetBaseline(); Uint32 itemNb = 1; while( pI ) { if( pI->IsVisible() ) { WgState state = WG_STATE_DISABLED; if( m_state.IsEnabled() && pI->m_bEnabled ) { state = WG_STATE_NORMAL; if( itemNb == m_selectedItem ) state = WG_STATE_PRESSED; else if( itemNb == m_markedItem ) state = WG_STATE_HOVERED; } WgBorder b = _getEntryBorder(); // WgColorsetPtr pTextColors; // if( m_pSkin ) // pTextColors = m_pSkin->TextColors(); if( m_pEntrySkin ) { WgRect dest( posX, window.y, pI->m_width + b.Width(), window.h ); m_pEntrySkin->Render( pDevice, dest, state, clip ); // pTextColors = m_pEntrySkin->TextColors(); } pen.SetPos( WgCoord(posX + b.left, printPosY) ); WgTextAttr attr; WgTextTool::AddPropAttributes( attr, WgBase::GetDefaultTextprop(), state ); // WgTextTool::SetAttrColor( attr, pTextColors, mode ); WgTextTool::AddPropAttributes( attr, m_pTextProp, state ); pen.SetAttributes( attr ); pDevice->PrintLine( pen, attr, pI->m_pText ); posX += pI->m_width + b.Width(); } itemNb++; pI = pI->Next(); } }
//____ _onRender() _____________________________________________________________ void WgTablePanel::_onRender( WgGfxDevice * pDevice, const WgRect& _canvas, const WgRect& _window, const WgRect& _clip ) { WgRect r = _canvas; WgRect clipView = _clip; if( r.w < _window.w ) r.w = _window.w; // Draw header (if any) if( m_bShowHeader && m_pHeaderGfx ) { WgRect headerArea( _canvas.x, _window.y, _canvas.w, m_pHeaderGfx->Height() ); WgRect r2 = headerArea; for( int i = 0 ; i < m_nColumns ; i++ ) { if( !m_pColumns[i].m_bVisible ) continue; // don't draw columns that are outside of the window if( r2.x >= _window.x + _window.w ) break; r2.w = m_pColumns[i].m_realWidth; //if( i == m_nColumns-1 && r2.x + r2.w < _window.x + _window.w ) if( i == m_nColumns-1 ) r2.w = _window.x + _window.w - r2.x; // Last column header stretches to end of tableview... WgMode mode = WG_MODE_NORMAL; if(&m_pColumns[i] == m_pMarkedHeader) mode = WG_MODE_MARKED; else if( i == m_lastSortColumn ) mode = WG_MODE_SPECIAL; pDevice->ClipBlitBlock( _clip, m_pHeaderGfx->GetBlock(mode,r2), r2 ); if( i == m_lastSortColumn && m_pAscendGfx && m_pDescendGfx ) { WgBlock block; if( m_lastSortColumnAscendStatus ) block = m_pAscendGfx->GetBlock(mode); else block = m_pDescendGfx->GetBlock(mode); WgRect dest = WgUtil::OrigoToRect( m_sortMarkerAlignment, r2.Size(), block.Size() ); dest += m_sortMarkerOfs; pDevice->ClipBlitBlock( _clip, block, dest ); } WgRect rText = r2; if( m_pHeaderGfx ) rText.Shrink( m_pHeaderGfx->Padding() ); m_pColumns[i]._getTextObj()->setProperties( m_pHeaderProps ); pDevice->PrintText( _clip, m_pColumns[i]._getTextObj(), rText ); r2.x += r2.w - 1; // HACK: Overlap last pixel to avoid double separator graphics between two headers } r.y += m_pHeaderGfx->Height(); // Modify clipping rectangle for view content (we don't want to draw over header) if( _clip.y < _window.y + m_pHeaderGfx->Height()) { int diff = _window.y + m_pHeaderGfx->Height() - _clip.y; clipView.y += diff; clipView.h -= diff; if( clipView.h < 1 ) return; } } // Start drawing cell contents. WgTableRow * pRow = m_rows.First(); int iRowColor = 0; // Skip rows that are above clipping area. r.y += m_cellPadding.top; while( pRow ) { if( pRow->IsVisible() ) { if( r.y + (int) pRow->Height() >= clipView.y ) break; r.y += pRow->Height() + m_cellPadding.Height(); iRowColor++; } pRow = pRow->Next(); } r.y -= m_cellPadding.top; // Draw cell contents for (at least partly) visible rows. while( pRow ) { if( !pRow->IsVisible() ) { pRow = pRow->Next(); continue; } if( r.y >= clipView.y + clipView.h ) break; r.h = pRow->Height() + m_cellPadding.Height(); WgRect u; if( u.Intersection( r, clipView ) ) { if( pRow->IsSelected() ) { if(HasSelectedRowBg() == true) pDevice->ClipBlitBlock(u, m_pSelectedRowGfx->GetBlock(WG_MODE_NORMAL,r), r ); else pDevice->Fill( u, m_selectedRowColor ); } else { if( m_nRowColors > 0 ) { WgColor color = m_pRowColors[ iRowColor % m_nRowColors ]; if( 0 != color.a ) pDevice->Fill( u, color ); } if( m_nRowBlocks > 0 ) { WgBlocksetPtr p = m_pRowBlocks[ iRowColor % m_nRowBlocks ]; if( p ) pDevice->ClipBlitBlock(u, p->GetBlock(WG_MODE_NORMAL,r), r ); } } } WgRect rc = r; rc.y += m_cellPadding.top; rc.h = pRow->Height(); for( int i = 0 ; i < m_nColumns ; i++ ) { WgTableHook * pHook = 0; if( pRow->m_nCells > i && pRow->m_pCells[i].Widget() != 0 ) pHook = &pRow->m_pCells[i]; // if( pHook == 0 ) //TODO: Make it right! // pHook = m_pColumns[i].m_pDefaultWidgetHook; if( m_pColumns[i].m_bVisible && pHook->IsVisible() && pHook->Widget() != 0 ) { // don't draw columns that are outside of the window if( rc.x >= _window.x + _window.w ) break; rc.w = m_pColumns[i].m_realWidth; if( i == m_nColumns-1 && rc.x + rc.w < _window.x + _window.w ) rc.w = _window.x + _window.w - rc.x; // Last column stretches to end of tableview... rc.x += m_cellPadding.left; rc.w -= m_cellPadding.Width(); WgRect clip2( rc, clipView ); // pHook->Widget()->_onRender( pDevice, rc, rc, clip2 ); rc.x += m_pColumns[i].m_realWidth - m_cellPadding.left; // Left cellpadding already added... } } r.y += pRow->Height() + m_cellPadding.Height(); pRow = (WgTableRow *) pRow->Next(); iRowColor++; } // Possibly fill with empty rows if( m_emptyRowHeight != 0 && pRow == 0 ) { while( r.y <= clipView.y + clipView.h ) { r.h = m_emptyRowHeight; WgRect u; if( u.Intersection( r, clipView ) ) { if( m_nRowColors > 0 ) { WgColor color = m_pRowColors[ iRowColor % m_nRowColors ]; if( 0 != color.a ) pDevice->Fill( u, color ); } if( m_nRowBlocks > 0 ) { WgBlocksetPtr p = m_pRowBlocks[ iRowColor % m_nRowBlocks ]; if( p ) pDevice->ClipBlitBlock(u, p->GetBlock(WG_MODE_NORMAL), r ); } } r.y += r.h; iRowColor++; } } }
void WgPackList::_onLassoUpdated( const WgRect& oldLasso, const WgRect& newLasso ) { // Get out content area WgRect listArea = _listArea(); // Check if our lassos are inside content area or not. bool bOldLassoInside = false; bool bNewLassoInside = false; if( oldLasso.IntersectsWith(listArea ) ) bOldLassoInside = true; if( newLasso.IntersectsWith(listArea ) ) bNewLassoInside = true; if( !bOldLassoInside && !bNewLassoInside ) return; // None of the lassos inside content. // Get first/last entries marked by old/new lasso int oldOfs1, oldOfs2; int newOfs1, newOfs2; if( m_bHorizontal ) { oldOfs1 = oldLasso.x - listArea.x; oldOfs2 = oldLasso.x + oldLasso.w - listArea.x; newOfs1 = newLasso.x - listArea.x; newOfs2 = newLasso.x + newLasso.w - listArea.x; } else { oldOfs1 = oldLasso.y - listArea.y; oldOfs2 = oldLasso.y + oldLasso.h - listArea.y; newOfs1 = newLasso.y - listArea.y; newOfs2 = newLasso.y + newLasso.h - listArea.y; } int oldFirst = _getEntryAt( oldOfs1 ); int oldLast = _getEntryAt( oldOfs2 ); int newFirst = _getEntryAt( newOfs1 ); int newLast = _getEntryAt( newOfs2 ); // if( bOldLassoInside != bNewLassoInside ) { int beg, end; if( bNewLassoInside ) { beg = newFirst; end = newLast; } else { beg = oldFirst; end = oldLast; } _flipRange( m_hooks.Hook(beg), m_hooks.Hook(end), true ); } else { if( oldFirst != newFirst ) { int beg = WgMin(oldFirst,newFirst); int end = WgMax(oldFirst,newFirst)-1; _flipRange( m_hooks.Hook(beg), m_hooks.Hook(end), true ); } if( oldLast != newLast ) { int beg = WgMin(oldLast,newLast)+1; int end = WgMax(oldLast,newLast); _flipRange( m_hooks.Hook(beg), m_hooks.Hook(end), true ); } } }
WgCoord WgPackListHook::GlobalPos() const { WgRect geo; m_pParent->_getChildGeo(geo,this); return m_pParent->GlobalPos() + geo.Pos(); }
void WgPackList::_onEvent( const WgEventPtr& _pEvent, WgEventHandler * pHandler ) { WgState oldState = m_state; switch( _pEvent->Type() ) { case WG_EVENT_MOUSE_MOVE: { WgMouseMoveEventPtr pEvent = WgMouseMoveEvent::Cast(_pEvent); WgCoord ofs = ToLocal(pEvent->PointerGlobalPos()); WgRect headerGeo = _headerGeo(); bool bHeaderHovered = headerGeo.Contains(ofs) && (!pHandler->IsAnyMouseButtonPressed() || (pHandler->IsMouseButtonPressed(WG_BUTTON_LEFT) && m_header.m_bPressed)); if( bHeaderHovered != m_header.m_state.IsHovered() ) { m_header.m_state.SetHovered(bHeaderHovered); _requestRender( headerGeo ); } WgList::_onEvent( _pEvent, pHandler ); break; } case WG_EVENT_MOUSE_LEAVE: { WgMouseLeaveEventPtr pEvent = WgMouseLeaveEvent::Cast(_pEvent); if( pEvent->Widget() == this && m_header.m_state.IsHovered() ) { m_header.m_state.SetPressed(false); m_header.m_state.SetHovered(false); _requestRender( _headerGeo() ); } WgList::_onEvent( _pEvent, pHandler ); break; } case WG_EVENT_MOUSE_PRESS: { WgMousePressEventPtr pEvent = WgMousePressEvent::Cast(_pEvent); WgCoord ofs = ToLocal(pEvent->PointerGlobalPos()); WgRect headerGeo = _headerGeo(); if(pEvent->Button() == WG_BUTTON_LEFT && headerGeo.Contains(ofs)) { m_header.m_bPressed = true; m_header.m_state.SetPressed(true); _requestRender( headerGeo ); pHandler->SwallowEvent( pEvent ); } else WgList::_onEvent( _pEvent, pHandler ); break; } case WG_EVENT_MOUSE_DRAG: { WgMouseDragEventPtr pEvent = WgMouseDragEvent::Cast(_pEvent); if( m_header.m_bPressed ) { WgCoord ofs = ToLocal(pEvent->PointerGlobalPos()); WgRect headerGeo = _headerGeo(); bool bHeaderHovered = headerGeo.Contains(ofs); if( bHeaderHovered != m_header.m_state.IsHovered() ) { m_header.m_state.SetHovered(bHeaderHovered); m_header.m_state.SetPressed(bHeaderHovered); _requestRender( headerGeo ); } pHandler->SwallowEvent(pEvent); } else WgList::_onEvent( _pEvent, pHandler ); break; } case WG_EVENT_MOUSE_RELEASE: { WgMouseReleaseEventPtr pEvent = WgMouseReleaseEvent::Cast(_pEvent); if(pEvent->Button() == WG_BUTTON_LEFT && m_header.m_bPressed ) { m_header.m_bPressed = false; m_header.m_state.SetPressed(false); WgRect headerGeo = _headerGeo(); _requestRender( headerGeo ); WgCoord ofs = ToLocal(pEvent->PointerGlobalPos()); if( headerGeo.Contains(ofs) ) { if( m_sortOrder == WG_SORT_ASCENDING ) m_sortOrder = WG_SORT_DESCENDING; else m_sortOrder = WG_SORT_ASCENDING; _sortEntries(); } pHandler->SwallowEvent(pEvent); } else WgList::_onEvent( _pEvent, pHandler ); break; } case WG_EVENT_KEY_PRESS: { if( m_selectMode == WG_SELECT_NONE ) break; int keyCode = WgKeyPressEvent::Cast(_pEvent)->TranslatedKeyCode(); WgModifierKeys modKeys = WgKeyPressEvent::Cast(_pEvent)->ModKeys(); if( (m_bHorizontal && (keyCode == WG_KEY_LEFT || keyCode == WG_KEY_RIGHT)) || (!m_bHorizontal && (keyCode == WG_KEY_UP || keyCode == WG_KEY_DOWN || keyCode == WG_KEY_PAGE_UP || keyCode == WG_KEY_PAGE_DOWN)) || keyCode == WG_KEY_HOME || keyCode == WG_KEY_END || (m_selectMode == WG_SELECT_FLIP && keyCode == WG_KEY_SPACE ) ) pHandler->SwallowEvent(_pEvent); WgList::_onEvent( _pEvent, pHandler ); break; } case WG_EVENT_KEY_REPEAT: case WG_EVENT_KEY_RELEASE: { if( m_selectMode == WG_SELECT_NONE ) break; int keyCode = WgKeyEvent::Cast(_pEvent)->TranslatedKeyCode(); WgModifierKeys modKeys = WgKeyEvent::Cast(_pEvent)->ModKeys(); if( (m_bHorizontal && (keyCode == WG_KEY_LEFT || keyCode == WG_KEY_RIGHT)) || (!m_bHorizontal && (keyCode == WG_KEY_UP || keyCode == WG_KEY_DOWN || keyCode == WG_KEY_PAGE_UP || keyCode == WG_KEY_PAGE_DOWN)) || keyCode == WG_KEY_HOME || keyCode == WG_KEY_END || (m_selectMode == WG_SELECT_FLIP && keyCode == WG_KEY_SPACE ) ) pHandler->SwallowEvent(_pEvent); WgList::_onEvent( _pEvent, pHandler ); break; } default: WgList::_onEvent(_pEvent, pHandler); return; } if( m_state != oldState ) _onStateChanged(oldState); }
WgSize WgPackListHook::Size() const { WgRect geo; m_pParent->_getChildGeo(geo,this); return geo.Size(); }
bool WgGfxDevice::PrintText( const WgRect& clip, const WgLegacyTextField * pText, const WgRect& dest ) { if( !pText || dest.w <= 0 ) return false; _drawTextBg(clip, pText, dest); WgPen pen; pen.SetDevice( this ); WgTextAttr attr; pText->GetBaseAttr(attr); if( !attr.pFont ) return false; pen.SetAttributes(attr); WgSize textSize( pText->Width(), pText->Height() ); if( dest.h < (int) textSize.h || dest.w < (int) textSize.w || !clip.Contains( dest ) || pText->isCursorShowing() ) pen.SetClipRect( clip ); const WgCaretInstance* pCursor = 0; int cursLine = -1, cursCol = -1; if( pText->isCursorShowing() ) { pCursor = pText->GetCursor(); pCursor->getSoftPos( cursLine, cursCol ); } bool bEllipsisActive = false; if( pText->AutoEllipsis() && !pText->isCursorShowing() && (textSize.w > dest.w || textSize.h > dest.h) ) bEllipsisActive = true; WgCoord pos; pos.y = pText->LineStartY( 0, dest ) + pText->getSoftLine(0)->baseline; int nLines = pText->nbSoftLines(); const WgLegacyTextLine * pLines = pText->getSoftLines(); for( int i = 0 ; i < nLines ; i++ ) { pos.x = pText->LineStartX( i, dest ); pen.SetOrigo( pos ); // So tab positions will start counting from start of line. pen.SetPos( pos ); pen.FlushChar(); // Remove kerning info for previous char. bool bLastFullyVisibleLine = false; if( (i < nLines-1) && (pos.y + pLines[i].lineSpacing + pLines[i+1].height - pLines[i+1].baseline > dest.y + dest.h) ) bLastFullyVisibleLine = true; if( cursLine == i ) { // Draw line parts, make space for cursor. _printTextSpan( pen, pText, pLines[i].ofs, cursCol, false ); WgCoord cursorPos = pen.GetPos(); pen.AdvancePosCursor( *pCursor ); _printTextSpan( pen, pText, pLines[i].ofs + cursCol, pLines[i].nChars - cursCol, true ); // Blit the cursor WgCoord restorePos = pen.GetPos(); pen.SetPos( cursorPos ); pen.BlitCursor( *pCursor ); pen.SetPos( restorePos ); } else { if( bEllipsisActive && (bLastFullyVisibleLine || pLines[i].width > dest.w) ) { _printEllipsisTextSpan( pen, pText, pLines[i].ofs, pLines[i].nChars, dest.x + dest.w ); break; } else _printTextSpan( pen, pText, pLines[i].ofs, pLines[i].nChars, true ); } pos.y += pLines[i].lineSpacing; } if( dest.w >= textSize.w && (dest.h >= textSize.h || nLines == 1) ) return true; else return false; }