Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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...
    }
}