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; }
WgRoot * setupGUI( WgGfxDevice * pDevice ) { WgResDB * pDB = sdl_wglib::LoadStdGizmos( "../resources/blocks.png", WgSurfaceFactorySoft() ); if( !pDB ) return 0; WgRoot * pRoot = new WgRoot( pDevice ); WgGizmoFlexgeo * pMainContainer = new WgGizmoFlexgeo(); int hAnchorLeft = pMainContainer->AddAnchor( 0.f, 0.f, WgCoord(0,100) ); int hAnchorRight = pMainContainer->AddAnchor( 1.f, 0.f, WgCoord(0,100) ); pRoot->SetChild(pMainContainer); WgGizmoStack * pPanelStack = new WgGizmoStack(); pMainContainer->AddChild( pPanelStack, WG_NORTHWEST, hAnchorRight ); // WgGizmo * pCheckeredBack = pDB->CloneGizmo( "bg_blue_gradient" ); WgGizmo * pCheckeredBack = pDB->CloneGizmo( "bg_checkered_grey" ); pMainContainer->AddChild( pCheckeredBack, hAnchorLeft, WG_SOUTHEAST ); WgGizmo * pPanelBack = pDB->CloneGizmo( "plate" ); pPanelStack->AddChild( pPanelBack ); WgGizmoFill * pFill = new WgGizmoFill(); pFill->SetColor( WgColor(255,0,0) ); pMainContainer->AddChild( pFill, WgRect(100,100,100,100) ); WgGizmoFill * pFill2 = new WgGizmoFill(); pFill2->SetColor( WgColor(0,255,0) ); pMainContainer->AddChild( pFill2, WgRect(200,100,100,100) ); WgGizmoFill * pFill3 = new WgGizmoFill(); pFill3->SetColor( WgColor(0,0,255) ); pMainContainer->AddChild( pFill3, WgRect(300,100,100,100) ); WgGizmoText * pText = new WgGizmoText(); pText->SetTextProperties( WgBase::GetDefaultTextprop() ); pText->SetText( "TESTING" ); pPanelStack->AddChild( pText ); WgGizmo * pSlider = pDB->CloneGizmo( "hslider" ); WgStackHook * pSliderHook = pPanelStack->AddChild( pSlider ); // pSliderHook->SetOrientation( WG_SOUTH ); pSliderHook->SetBorder( WgBorder(0,0,81,0) ); // return pRoot; }
WgWidget * WgTablePanel::FindWidget( const WgCoord& ofs, WgSearchMode mode ) { // Check cell content int xOfs; int yOfs; WgTableRow* pRow; int col = _getMarkedColumn( ofs.x, xOfs ); int row = _getMarkedRow( ofs.y, pRow, yOfs ); WgWidget * pWidget = 0; if( col != -1 && row != -1 && pRow->GetHook(col)->IsVisible() ) { if( xOfs < m_cellPadding.left || xOfs >= m_pColumns[col].m_realWidth - m_cellPadding.right || yOfs < m_cellPadding.top || yOfs >= pRow->Height() - m_cellPadding.bottom ) { pWidget = pRow->GetWidget(col); if( mode == WG_SEARCH_GEOMETRY || pWidget->MarkTest( WgCoord( xOfs-m_cellPadding.left, yOfs-m_cellPadding.top) ) ) return pWidget; } } // Check ourselves if( mode == WG_SEARCH_GEOMETRY || MarkTest( ofs ) ) return this; else return 0; }
Uint32 WgMenubar::_getItemAtAbsPos( int x, int y ) { WgCoord pos = ToLocal( WgCoord(x, y) ); if( m_pSkin ) pos = m_pSkin->ContentRect( pos, WG_STATE_NORMAL ).Pos(); if( y > 0 && x > 0 && y < (int) Size().h ) { int bordersWidth = _getEntryBorder().Width(); WgMenuBarItem * pItem = m_items.First(); int item = 1; while( pItem ) { if(pItem->IsVisible()) { x -= pItem->m_width+bordersWidth; if( x < 0 ) return item; } pItem = pItem->Next(); item++; } } return 0; }
bool WgMenubar::_openMenu( int nb ) { WgMenuBarItem * pItem = m_items.Get(nb-1); if( pItem == 0 || !pItem->m_pMenu ) return false; WgCoord pos = ToLocal( WgCoord(0, 0) ); if( m_pSkin ) pos = m_pSkin->ContentRect( pos, WG_STATE_NORMAL ).Pos(); int bordersWidth = _getEntryBorder().Width(); WgMenuBarItem * pI = m_items.First(); while( pI != pItem ) { if( pI->IsVisible() ) pos.x += pI->m_width + bordersWidth; pI = pI->Next(); } WgRect r(pos, pI->m_width+bordersWidth, Size().h ); WgPopupLayer * pLayer = 0; if( Parent() ) pLayer = Parent()->_getPopupLayer(); if( !pLayer ) return false; pLayer->OpenPopup( pItem->m_pMenu, this, r - pLayer->GlobalPos(), WG_SOUTHWEST ); return true; }
void WgMenu::_onRender( WgGfxDevice * pDevice, const WgRect& canvas, const WgRect& window, const WgRect& clip ) { WgWidget::_onRender(pDevice,canvas,window,clip); // Render the menu-items WgRect contentRect = m_pSkin?m_pSkin->ContentRect(canvas, m_state):canvas; WgRect contentClip( contentRect, clip ); // A clip rectangle for content. WgMenuItem * pItem = m_items.First(); int yPos = contentRect.y - m_contentOfs; int xPosText = contentRect.x + m_iconFieldWidth; int xPosIcon = contentRect.x; int textFieldLen = contentRect.w - m_iconFieldWidth - m_arrowFieldWidth; WgPen entryPen( pDevice, WgCoord( xPosText, yPos ), contentClip ); WgPen accelPen( pDevice, WgCoord( xPosText, yPos ), contentClip ); unsigned int item = 1; while( pItem ) { if( pItem->IsVisible() ) { if( pItem->GetType() == SEPARATOR ) { if( m_pSeparatorSkin ) { WgRect dest( contentRect.x, yPos + m_sepBorder.top, contentRect.w, m_pSeparatorSkin->PreferredSize().h ); m_pSeparatorSkin->Render( pDevice, dest, m_state, contentClip ); yPos += m_sepHeight; } } else { WgState state = WG_STATE_DISABLED; if( ((WgMenuEntry*)pItem)->IsEnabled() ) state = WG_STATE_NORMAL; if( item == m_markedItem ) state = WG_STATE_HOVERED; // Render the tile for this entry WgRect tileDest( contentRect.x, yPos, contentRect.w, m_entryHeight ); // WgRect tileClip( contentClip, tileDest); if( m_pEntrySkin ) m_pEntrySkin->Render( pDevice, tileDest, state, contentClip ); // Print the text (if any) const WgChar * pText = ((WgMenuEntry*)pItem)->GetText().Chars(); if( pText->Glyph() != 0 ) { WgTextAttr attr; WgTextTool::AddPropAttributes( attr, WgBase::GetDefaultTextprop(), state ); // if( m_pSkin ) // WgTextTool::SetAttrColor( attr, m_pSkin->TextColors(), mode ); WgTextTool::AddPropAttributes( attr, m_pEntryProp, state ); entryPen.SetAttributes( attr ); int y = yPos + (m_entryHeight - entryPen.GetLineHeight())/2 + entryPen.GetBaseline(); entryPen.SetPos( WgCoord( xPosText, y ) ); pDevice->PrintLine( entryPen, attr, pText ); } // Print the accel text (if any) const WgChar * pAccelText = ((WgMenuEntry*)pItem)->GetAccelText().Chars(); if( pAccelText->Glyph() != 0 ) { WgTextAttr attr; WgTextTool::AddPropAttributes( attr, WgBase::GetDefaultTextprop(), state ); // if( m_pSkin ) // WgTextTool::SetAttrColor( attr, m_pSkin->TextColors(), mode ); WgTextTool::AddPropAttributes( attr, m_pKeyAccelProp, state ); accelPen.SetAttributes( attr ); int y = yPos + (m_entryHeight - accelPen.GetLineHeight())/2 + accelPen.GetBaseline(); int width = WgTextTool::lineWidth( attr, state, pAccelText ); int x = xPosText + textFieldLen - width; accelPen.SetPos( WgCoord(x, y) ); pDevice->PrintLine( accelPen, attr, pAccelText ); } // Show the icon/checkbox/radiobutton (if any) switch( pItem->GetType() ) { case ENTRY: { WgSkinPtr pIcon = ((WgMenuEntry*)pItem)->GetIcon(); if( pIcon ) { WgSize sz = pIcon->PreferredSize(); if( sz.w > m_iconFieldWidth ) sz.w = m_iconFieldWidth; if( sz.h > m_entryHeight ) sz.h = m_entryHeight; int y = yPos + (m_entryHeight - sz.h)/2; int x = xPosIcon + (m_iconFieldWidth - sz.w)/2; pIcon->Render( pDevice, WgRect(x,y,sz), state, contentClip ); } } break; case CHECKBOX: { WgState checkboxState = state; if( ((WgMenuCheckBox*)pItem)->IsChecked() ) checkboxState.SetSelected(true); if( m_pCheckBoxSkin ) { WgSize sz = m_pCheckBoxSkin->PreferredSize(); int y = yPos + (m_entryHeight - sz.h)/2; int x = xPosIcon + (m_iconFieldWidth - sz.w)/2; m_pCheckBoxSkin->Render( pDevice, WgRect(x,y,sz), checkboxState, contentClip ); } } break; case RADIOBUTTON: { WgState radiobuttonState = state; if( ((WgMenuRadioButton*)pItem)->IsSelected() ) radiobuttonState.SetSelected(true); if( m_pRadioButtonSkin ) { WgSize sz = m_pRadioButtonSkin->PreferredSize(); int y = yPos + (m_entryHeight - sz.h)/2; int x = xPosIcon + (m_iconFieldWidth - sz.w)/2; m_pRadioButtonSkin->Render( pDevice, WgRect(x,y,sz), radiobuttonState, contentClip ); } } break; case SUBMENU: { //TODO: Show submenu arrow. } break; default: break; } yPos += m_entryHeight; } } pItem = pItem->Next(); item++; } }
WgCoord WgMenu::ScrollbarHook::GlobalPos() const { WgRect content = m_pParent->GlobalGeo() - m_pParent->_getPadding(); return WgCoord( content.x + content.w - m_size.w, content.y); }
WgCoord WgMenu::ScrollbarHook::Pos() const { WgSize parentSize = m_pParent->Size(); WgBorder borders = m_pParent->_getPadding(); return WgCoord(parentSize.w-m_size.w-borders.right,borders.top); }
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(); } }
void WgLineEditor::_onEvent( const WgEventPtr& pEvent, WgEventHandler * pHandler ) { WgWidget::_onEvent(pEvent,pHandler); WgEventType event = pEvent->Type(); if( event == WG_EVENT_TICK ) { if( _isSelectable() && m_state.IsFocused() ) { m_text.incTime( WgTickEvent::Cast(pEvent)->Millisec() ); _requestRender(); //TODO: Should only render the cursor and selection! } return; } if( (event == WG_EVENT_MOUSE_PRESS || event == WG_EVENT_MOUSE_DRAG) && WgMouseButtonEvent::Cast(pEvent)->Button() == WG_BUTTON_LEFT ) { if( !m_state.IsFocused() ) GrabFocus(); if( m_state.IsFocused() ) { if( _isSelectable() && (pEvent->ModKeys() & WG_MODKEY_SHIFT) ) { m_text.setSelectionMode(true); } WgCoord ofs = pEvent->PointerPos(); int x = ofs.x + m_viewOfs; int y = 0; if( m_bPasswordMode ) { WgTextAttr attr; m_text.GetBaseAttr( attr ); WgPen pen; pen.SetAttributes( attr ); pen.SetChar(m_pwGlyph); pen.AdvancePos(); int spacing = pen.GetPosX(); int height = pen.GetLineSpacing(); int line = y/height; int col = (x+spacing/2)/spacing; if(col < 0) { col = 0; line = 0; } m_text.gotoSoftPos(line,col); } else { m_text.CursorGotoCoord( WgCoord(x, 0), WgRect(0,0,1000000,1000000) ); } if(_isSelectable() && event == WG_EVENT_MOUSE_PRESS && !(pEvent->ModKeys() & WG_MODKEY_SHIFT)) { m_text.ClearSelection(); m_text.setSelectionMode(true); } } _adjustViewOfs(); } if( event == WG_EVENT_MOUSE_RELEASE ) { if( m_state.IsFocused() && WgMouseButtonEvent::Cast(pEvent)->Button() == WG_BUTTON_LEFT ) m_text.setSelectionMode(false); } if( event == WG_EVENT_CHARACTER ) { int ch = WgCharacterEvent::Cast(pEvent)->Char(); if( _isEditable() && m_state.IsFocused() && ch >= 32 && ch != 127) { if(m_text.hasSelection()) m_text.delSelection(); m_text.setSelectionMode(false); if( m_text.putChar( ch ) ) { if( pHandler ) pHandler->QueueEvent( new WgTextEditEvent(this,&text,false) ); _adjustViewOfs(); } } } if( event == WG_EVENT_KEY_RELEASE && m_state.IsFocused() ) { int key = WgKeyEvent::Cast(pEvent)->TranslatedKeyCode(); switch( key ) { case WG_KEY_SHIFT: if(!pHandler->IsMouseButtonPressed(1)) m_text.setSelectionMode(false); break; } } if( (event == WG_EVENT_KEY_PRESS || event == WG_EVENT_KEY_REPEAT) && _isEditable() && m_state.IsFocused() ) { int key = WgKeyEvent::Cast(pEvent)->TranslatedKeyCode(); switch( key ) { case WG_KEY_LEFT: if( pEvent->ModKeys() & WG_MODKEY_SHIFT ) m_text.setSelectionMode(true); if( pEvent->ModKeys() & WG_MODKEY_CTRL ) { if( m_bPasswordMode ) m_text.GoBOL(); else m_text.gotoPrevWord(); } else { m_text.goLeft(); } break; case WG_KEY_RIGHT: if( pEvent->ModKeys() & WG_MODKEY_SHIFT ) m_text.setSelectionMode(true); if( pEvent->ModKeys() & WG_MODKEY_CTRL ) { if( m_bPasswordMode ) m_text.GoEOL(); else m_text.gotoNextWord(); } else { m_text.goRight(); } break; case WG_KEY_BACKSPACE: { if(m_text.hasSelection()) m_text.delSelection(); else if( (pEvent->ModKeys() & WG_MODKEY_CTRL) && !m_bPasswordMode) m_text.delPrevWord(); else m_text.delPrevChar(); if( pHandler ) pHandler->QueueEvent( new WgTextEditEvent(this,&text,false) ); break; } case WG_KEY_DELETE: { if(m_text.hasSelection()) m_text.delSelection(); else if( (pEvent->ModKeys() & WG_MODKEY_CTRL) && !m_bPasswordMode) m_text.delNextWord(); else m_text.delNextChar(); if( pHandler ) pHandler->QueueEvent( new WgTextEditEvent(this,&text,false) ); break; } case WG_KEY_HOME: /* * I am not sure if this is the proper way to this, but in my opinion, the default * "actions" has to be separated from any modifier key action combination */ switch( pEvent->ModKeys() ) { case WG_MODKEY_CTRL: break; default: // no modifier key was pressed if(pEvent->ModKeys() & WG_MODKEY_SHIFT ) m_text.setSelectionMode(true); m_text.GoBOL(); break; } break; case WG_KEY_END: /* * I am not sure if this is the proper way to this, but in my opinion, the default * "actions" has to be separated from any modifier key action combination */ switch( pEvent->ModKeys() ) { case WG_MODKEY_CTRL: break; default: // no modifier key was pressed if( pEvent->ModKeys() & WG_MODKEY_SHIFT ) m_text.setSelectionMode(true); m_text.GoEOL(); break; } break; default: break; } _adjustViewOfs(); } // Forward event depending on rules. if( pEvent->IsMouseButtonEvent() ) { if( WgMouseButtonEvent::Cast(pEvent)->Button() == WG_BUTTON_LEFT ) pHandler->SwallowEvent(pEvent); } else if( pEvent->IsKeyEvent() ) { int key = WgKeyEvent::Cast(pEvent)->TranslatedKeyCode(); if( WgKeyEvent::Cast(pEvent)->IsMovementKey() == true || key == WG_KEY_DELETE || key == WG_KEY_BACKSPACE ) pHandler->SwallowEvent(pEvent); //TODO: Would be good if we didn't forward any character-creating keys either... } }