void LineEditor::_render( GfxDevice * pDevice, const Rect& _canvas, const Rect& _window, const Rect& _clip ) { Widget::_render(pDevice,_canvas,_window,_clip); LegacyTextItem * pText = &m_text; //TODO: Get password mode working again! /* if( m_bPasswordMode ) { int nChars = m_text.length(); uint16_t * pContent = new uint16_t[nChars+1]; for( int i = 0 ; i < nChars ; i++ ) pContent[i] = m_pwGlyph; pContent[nChars] = 0; pText = new LegacyTextItem( pContent ); delete [] pContent; pText->setWrap(false); pText->setAutoEllipsis(false); pText->setAlignment(m_text.alignment()); pText->setProperties(m_text.properties()); pText->setSelectionProperties(m_text.selectionProperties()); pText->setState(m_text.state()); pText->setEditMode(m_text.editMode()); pText->showCaret(); pText->gotoSoftPos( m_text.line(), m_text.column() ); pText->incTime( m_text.time() ); int sl, sc, el, ec; if( m_text.getSelection(sl, sc, el, ec) ) pText->selectText(sl, sc, el, ec); } */ Rect canvas; if( m_pSkin ) canvas = m_pSkin->sizeForContent(_canvas); else canvas = _canvas; Rect textClip( _clip, canvas ); canvas.x -= m_viewOfs; canvas.w += m_viewOfs; if( m_state.isFocused() && _isEditable() ) pText->showCaret(); else pText->hideCaret(); pDevice->printText( textClip, pText, canvas ); if( pText != &m_text ) delete pText; }
void WgLineEditor::_onRender( WgGfxDevice * pDevice, const WgRect& _canvas, const WgRect& _window, const WgRect& _clip ) { WgWidget::_onRender(pDevice,_canvas,_window,_clip); WgLegacyTextField * pText = &m_text; //TODO: Get password mode working again! /* if( m_bPasswordMode ) { int nChars = m_text.Length(); Uint16 * pContent = new Uint16[nChars+1]; for( int i = 0 ; i < nChars ; i++ ) pContent[i] = m_pwGlyph; pContent[nChars] = 0; pText = new WgLegacyTextField( pContent ); delete [] pContent; pText->SetWrap(false); pText->SetAutoEllipsis(false); pText->SetAlignment(m_text.Alignment()); pText->SetProperties(m_text.Properties()); pText->SetSelectionProperties(m_text.SelectionProperties()); pText->setState(m_text.State()); pText->SetEditMode(m_text.EditMode()); pText->showCursor(); pText->gotoSoftPos( m_text.line(), m_text.column() ); pText->incTime( m_text.time() ); int sl, sc, el, ec; if( m_text.getSelection(sl, sc, el, ec) ) pText->selectText(sl, sc, el, ec); } */ WgRect canvas; if( m_pSkin ) canvas = m_pSkin->SizeForContent(_canvas); else canvas = _canvas; WgRect textClip( _clip, canvas ); canvas.x -= m_viewOfs; canvas.w += m_viewOfs; if( m_state.IsFocused() && _isEditable() ) pText->showCursor(); else pText->hideCursor(); pDevice->PrintText( textClip, pText, canvas ); if( pText != &m_text ) delete pText; }
void LineEditor::_setState( State state ) { State oldState = m_state; Widget::_setState(state); m_text.setState(state); _requestRender(); //TODO: Only request render if text appearance has changed. if( state.isFocused() && !oldState.isFocused() ) { if( _isEditable() ) { m_tickRouteId = Base::msgRouter()->addRoute( MsgType::Tick, this ); if( m_bResetCaretOnFocus ) m_text.goEol(); _requestRender(); // render with cursor on } } if( !state.isFocused() && oldState.isFocused() ) { if( _isSelectable() ) { m_text.clearSelection(); m_text.setSelectionMode(false); m_bResetCaretOnFocus = false; } if( _isEditable() || m_viewOfs != 0 ) { Base::msgRouter()->deleteRoute( m_tickRouteId ); m_tickRouteId = 0; Base::msgRouter()->post( new TextEditMsg(text.ptr(),true) ); m_viewOfs = 0; _requestRender(); } } }
void WgLineEditor::_onStateChanged( WgState oldState ) { WgWidget::_onStateChanged(oldState); m_text.setState(m_state); _requestRender(); //TODO: Only request render if text appearance has changed. if( m_state.IsFocused() && !oldState.IsFocused() ) { if( _isEditable() ) { _startReceiveTicks(); if( m_bResetCursorOnFocus ) m_text.GoEOL(); _requestRender(); // render with cursor on } } if( !m_state.IsFocused() && oldState.IsFocused() ) { if( _isSelectable() ) { m_text.ClearSelection(); m_text.setSelectionMode(false); m_bResetCursorOnFocus = false; } if( _isEditable() || m_viewOfs != 0 ) { _stopReceiveTicks(); _queueEvent( new WgTextEditEvent(this, &text,true) ); m_viewOfs = 0; _requestRender(); } } }
bool LineEditor::insertCharAtCaret( uint16_t c ) { if( !_isEditable() ) return false; if( !m_state.isFocused() ) if( !grabFocus() ) return false; // Couldn't get input focus... if( !m_text.putChar( c ) ) return false; Base::msgRouter()->post( new TextEditMsg(text.ptr(),false) ); _adjustViewOfs(); return true; }
int LineEditor::insertTextAtCaret( const CharSeq& str ) { if( !_isEditable() ) return 0; if( !m_state.isFocused() ) if( !grabFocus() ) return 0; // Couldn't get input focus... int retVal = m_text.putText( str ); Base::msgRouter()->post( new TextEditMsg(text.ptr(),false) ); _adjustViewOfs(); return retVal; }
bool WgLineEditor::InsertCharAtCursor( Uint16 c ) { if( !_isEditable() ) return false; if( !m_state.IsFocused() ) if( !GrabFocus() ) return false; // Couldn't get input focus... if( !m_text.putChar( c ) ) return false; _queueEvent( new WgTextEditEvent(this,&text,false) ); _adjustViewOfs(); return true; }
int WgLineEditor::InsertTextAtCursor( const WgCharSeq& str ) { if( !_isEditable() ) return 0; if( !m_state.IsFocused() ) if( !GrabFocus() ) return 0; // Couldn't get input focus... int retVal = m_text.putText( str ); _queueEvent( new WgTextEditEvent(this,&text,false) ); _adjustViewOfs(); return retVal; }
void LineEditor::_receive( const Msg_p& pMsg ) { Widget::_receive(pMsg); MsgRouter_p pHandler = Base::msgRouter(); MsgType event = pMsg->type(); if( event == MsgType::Tick ) { if( _isSelectable() && m_state.isFocused() ) { m_text.incTime( TickMsg::cast(pMsg)->timediff() ); _requestRender(); //TODO: Should only render the cursor and selection! } return; } if( (event == MsgType::MousePress || event == MsgType::MouseDrag) && MouseButtonMsg::cast(pMsg)->button() == MouseButton::Left ) { MouseButtonMsg_p pButtonMsg = MouseButtonMsg::cast(pMsg); if( !m_state.isFocused() ) grabFocus(); if( m_state.isFocused() ) { if( _isSelectable() && (pButtonMsg->modKeys() & MODKEY_SHIFT) ) { m_text.setSelectionMode(true); } Coord ofs = pButtonMsg->pointerPos() - globalPos(); int x = ofs.x + m_viewOfs; int y = 0; if( m_bPasswordMode ) { TextAttr attr; m_text.getBaseAttr( attr ); Pen 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( Coord(x, 0), Rect(0,0,1000000,1000000) ); } if(_isSelectable() && event == MsgType::MousePress && !(pButtonMsg->modKeys() & MODKEY_SHIFT)) { m_text.clearSelection(); m_text.setSelectionMode(true); } } _adjustViewOfs(); } if( event == MsgType::MouseRelease ) { if( m_state.isFocused() && MouseButtonMsg::cast(pMsg)->button() == MouseButton::Left ) m_text.setSelectionMode(false); } if( event == MsgType::TextInput ) { String str = TextInputMsg::cast(pMsg)->text(); if( _isEditable() && m_state.isFocused() ) { if(m_text.hasSelection()) m_text.delSelection(); m_text.setSelectionMode(false); bool bModified = false; for( int i = 0 ; i < str.length() ; i++ ) { unsigned short ch = str.chars()[i].getGlyph(); if( ch >= 32 && ch != 127 ) { if( m_text.putChar( ch ) ) bModified = true; } } if( bModified ) { if( pHandler ) pHandler->post( new TextEditMsg(text.ptr(),false) ); _adjustViewOfs(); } } } if( event == MsgType::KeyRelease && m_state.isFocused() ) { Key key = KeyMsg::cast(pMsg)->translatedKeyCode(); switch( key ) { case Key::Shift: if(!Base::inputHandler()->isButtonPressed(MouseButton::Left)) m_text.setSelectionMode(false); break; } } if( (event == MsgType::KeyPress || event == MsgType::KeyRepeat) && _isEditable() && m_state.isFocused() ) { KeyMsg_p pKeyMsg = KeyMsg::cast(pMsg); Key key = pKeyMsg->translatedKeyCode(); switch( key ) { case Key::Left: if( pKeyMsg->modKeys() & MODKEY_SHIFT ) m_text.setSelectionMode(true); if( pKeyMsg->modKeys() & MODKEY_CTRL ) { if( m_bPasswordMode ) m_text.goBol(); else m_text.gotoPrevWord(); } else { m_text.goLeft(); } break; case Key::Right: if( pKeyMsg->modKeys() & MODKEY_SHIFT ) m_text.setSelectionMode(true); if( pKeyMsg->modKeys() & MODKEY_CTRL ) { if( m_bPasswordMode ) m_text.goEol(); else m_text.gotoNextWord(); } else { m_text.goRight(); } break; case Key::Backspace: { if(m_text.hasSelection()) m_text.delSelection(); else if( (pKeyMsg->modKeys() & MODKEY_CTRL) && !m_bPasswordMode) m_text.delPrevWord(); else m_text.delPrevChar(); if( pHandler ) pHandler->post( new TextEditMsg(text.ptr(),false) ); break; } case Key::Delete: { if(m_text.hasSelection()) m_text.delSelection(); else if( (pKeyMsg->modKeys() & MODKEY_CTRL) && !m_bPasswordMode) m_text.delNextWord(); else m_text.delNextChar(); if( pHandler ) pHandler->post( new TextEditMsg(text.ptr(),false) ); break; } case 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( pKeyMsg->modKeys() ) { case MODKEY_CTRL: break; default: // no modifier key was pressed if(pKeyMsg->modKeys() & MODKEY_SHIFT ) m_text.setSelectionMode(true); m_text.goBol(); break; } break; case 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( pKeyMsg->modKeys() ) { case MODKEY_CTRL: break; default: // no modifier key was pressed if( pKeyMsg->modKeys() & MODKEY_SHIFT ) m_text.setSelectionMode(true); m_text.goEol(); break; } break; default: break; } _adjustViewOfs(); } // Swallow message depending on rules. if( pMsg->isMouseButtreceive() ) { if( MouseButtonMsg::cast(pMsg)->button() == MouseButton::Left ) pMsg->swallow(); } else if( pMsg->isKeyMsg() ) { Key key = KeyMsg::cast(pMsg)->translatedKeyCode(); if( KeyMsg::cast(pMsg)->isMovementKey() == true || key == Key::Delete || key == Key::Backspace ) pMsg->swallow(); //TODO: Would be good if we didn't forward any character-creating keys either... } }
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... } }