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 * 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 ); } }
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::_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); }
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; }