void WgMenu::_onEvent( const WgEventPtr& pEvent, WgEventHandler * pHandler ) { // TODO: Not handle or swallow key-events if some modifier keys are pressed. WgCoord mousePos = pEvent->PointerPos(); switch( pEvent->Type() ) { case WG_EVENT_TICK: { if( m_selectorCountdown > 0 ) { WgTickEventPtr pTick = WgTickEvent::Cast(pEvent); m_selectorCountdown -= pTick->Millisec(); if( m_selectorCountdown < 0 ) { m_selectorCountdown = 0; m_nSelectorKeys = 0; } } return; } case WG_EVENT_MOUSE_LEAVE: { // Unmark any selected item unless it is a submenu... WgMenuItem * pOldItem = m_items.Get(m_markedItem-1); if( pOldItem && pOldItem->GetType() != SUBMENU ) { m_markedItem = 0; _requestRender(); } } break; case WG_EVENT_MOUSE_ENTER: case WG_EVENT_MOUSE_MOVE: { WgMenuItem * pItem = _getItemAtPos( mousePos.x, mousePos.y ); Uint32 markedItem = 0; if( pItem ) { if( pItem->GetType() != SEPARATOR ) { if( ((WgMenuEntry*)pItem)->IsEnabled() ) markedItem = pItem->Index()+1; } } if( m_markedItem != markedItem ) { // Mark and request render m_markedItem = markedItem; _requestRender(); // Open/close submenus depending on what item we have marked. if( pItem && pItem->GetType() == SUBMENU ) { WgMenuSubMenu * pSubMenu = (WgMenuSubMenu*) pItem; if( pSubMenu != m_pOpenSubMenu ) { if( m_pOpenSubMenu ) _closeSubMenu( m_pOpenSubMenu ); _openSubMenu( pSubMenu ); } } else if( m_pOpenSubMenu ) { _closeSubMenu( m_pOpenSubMenu ); } } } break; case WG_EVENT_MOUSE_RELEASE: { WgMenuItem * pItem = _getItemAtPos( mousePos.x, mousePos.y ); if( pItem ) SelectItem(pItem); } break; case WG_EVENT_WHEEL_ROLL: { WgWheelRollEventPtr pEv = WgWheelRollEvent::Cast(pEvent); if( pEv->Wheel() == 1 ) { int distance = pEv->Distance(); _setViewOfs( m_contentOfs - m_entryHeight*distance ); _updateScrollbar( _getHandlePosition(), _getHandleSize() ); } } case WG_EVENT_CHARACTER: { Uint16 chr = WgCharacterEvent::Cast(pEvent)->Char(); if( chr != 0 ) { m_selectorCountdown = c_selectorCountdownStart; if( m_nSelectorKeys < c_maxSelectorKeys ) { m_selectorKeys[m_nSelectorKeys++] = towlower( chr ); _markFirstFilteredEntry(); } } } break; case WG_EVENT_KEY_PRESS: case WG_EVENT_KEY_REPEAT: { WgMenuItem * pItem = 0; if( m_markedItem != 0 ) pItem = m_items.Get( m_markedItem-1 ); int key = WgKeyEvent::Cast(pEvent)->TranslatedKeyCode(); switch( key ) { case WG_KEY_ESCAPE: if( m_pOpenSubMenu ) { _closeSubMenu( m_pOpenSubMenu ); } break; case WG_KEY_LEFT: if( m_pOpenSubMenu ) { _closeSubMenu( m_pOpenSubMenu ); } break; case WG_KEY_RIGHT: if( pItem ) { if( pItem->GetType() == SUBMENU ) { _openSubMenu( (WgMenuSubMenu*) pItem ); } } break; case WG_KEY_RETURN: if( pItem ) { if( pItem->GetType() == SUBMENU ) _openSubMenu( (WgMenuSubMenu*) pItem ); else { SelectItem(pItem); pItem = 0; // So we won't mark an item in the closed menu. } } break; case WG_KEY_UP: if( pItem ) { pItem = pItem->Prev(); while( pItem != 0 && (pItem->GetType() == SEPARATOR || !pItem->IsVisible() ) ) pItem = pItem->Prev(); } break; case WG_KEY_DOWN: if( pItem ) pItem = pItem->Next(); else pItem = m_items.First(); while( pItem != 0 && (pItem->GetType() == SEPARATOR || !pItem->IsVisible() ) ) pItem = pItem->Next(); break; case WG_KEY_HOME: pItem = m_items.First(); while( pItem != 0 && (pItem->GetType() == SEPARATOR || !pItem->IsVisible() ) ) pItem = pItem->Next(); break; case WG_KEY_END: pItem = m_items.Last(); while( pItem != 0 && (pItem->GetType() == SEPARATOR || !pItem->IsVisible() )) pItem = pItem->Prev(); break; case WG_KEY_PAGE_UP: { int viewHeight = _getViewSize(); int distance = m_entryHeight; while( pItem != 0 && distance < viewHeight ) { if( pItem->IsVisible() ) { if( pItem->GetType() == SEPARATOR ) distance += m_sepHeight; else distance += m_entryHeight; } pItem = pItem->Prev(); } if( !pItem ) { pItem = m_items.First(); while( pItem != 0 && (pItem->GetType() == SEPARATOR || !pItem->IsVisible() )) pItem = pItem->Next(); } break; } case WG_KEY_PAGE_DOWN: { int viewHeight = _getViewSize(); int distance = m_entryHeight; while( pItem != 0 && distance < viewHeight ) { if( pItem->IsVisible() ) { if( pItem->GetType() == SEPARATOR ) distance += m_sepHeight; else distance += m_entryHeight; } pItem = pItem->Next(); } if( !pItem ) { pItem = m_items.Last(); while( pItem != 0 && (pItem->GetType() == SEPARATOR || !pItem->IsVisible() )) pItem = pItem->Next(); } break; } } if( pItem ) { Uint32 markedItem = pItem->Index()+1; if( markedItem != m_markedItem ) { m_markedItem = markedItem; _scrollItemIntoView(pItem); _requestRender(); } } } break; default: break; } // Forward event depending on rules. if( pEvent->IsMouseButtonEvent() && WgMouseButtonEvent::Cast(pEvent)->Button() == WG_BUTTON_LEFT ) pHandler->SwallowEvent(pEvent); else if( pEvent->IsKeyEvent() ) { int key = WgKeyEvent::Cast(pEvent)->TranslatedKeyCode(); if( key == WG_KEY_RIGHT || key == WG_KEY_RETURN || key == WG_KEY_UP || key == WG_KEY_DOWN && key == WG_KEY_HOME || key == WG_KEY_END || key == WG_KEY_PAGE_UP || key == WG_KEY_PAGE_DOWN && key == WG_KEY_ESCAPE || key == WG_KEY_LEFT ) pHandler->SwallowEvent(pEvent); } else if( pEvent->Type() == WG_EVENT_CHARACTER || pEvent->Type() == WG_EVENT_WHEEL_ROLL ) pHandler->SwallowEvent(pEvent); }
void WgTablist::_onEvent( const WgEventPtr& _pEvent, WgEventHandler * pHandler ) { WgWidget::_onEvent(_pEvent,pHandler); switch( _pEvent->Type() ) { case WG_EVENT_TICK: { WgTickEventPtr pEvent = WgTickEvent::Cast(_pEvent); m_alertModeCnt -= pEvent->Millisec(); if( m_alertModeCnt <= 0 ) { m_bAlertOn = !m_bAlertOn; m_alertModeCnt = m_alertRate; // This is right, we want it to stay in the new mode at least one frame. // Check if we have to render something... WgTab * pTab = m_tabs.First(); while( pTab ) { if( pTab->m_bAlert && pTab->m_bVisible ) { _requestRender(); // Somewhat stupid to render all tabs though... break; } pTab = pTab->Next(); } } break; } case WG_EVENT_MOUSE_PRESS: { WgMouseButtonEventPtr pEvent = WgMouseButtonEvent::Cast(_pEvent); WgCoord pos = pEvent->PointerPos(); WgTab * pTab = _pos2Tab( pos.x, pos.y ); if( pTab && pTab != m_pTabSelected ) { if( pEvent->Button() == WG_BUTTON_LEFT ) SelectTab(pTab->m_id); pHandler->QueueEvent( new WgItemMousePressEvent(this, pTab->m_id, WgObjectPtr(), pEvent->Button()) ); } } break; case WG_EVENT_MOUSE_ENTER: case WG_EVENT_MOUSE_MOVE: { WgCoord pos = _pEvent->PointerPos(); WgTab * pTab = _pos2Tab( pos.x, pos.y ); if( pTab != m_pTabMarked ) { m_pTabMarked = pTab; _requestRender(); } } break; case WG_EVENT_MOUSE_LEAVE: if( m_pTabMarked ) { m_pTabMarked = 0; _requestRender(); } break; default: break; } // Swallow event depending on rules. if( _pEvent->IsMouseButtonEvent() && WgMouseButtonEvent::Cast(_pEvent)->Button() == WG_BUTTON_LEFT ) pHandler->SwallowEvent(_pEvent); }
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... } }