00001 #include "SdlArs.h"
00002
00003 namespace Ars
00004 {
00005 XEditBox::XEditBox( void )
00006 : m_SelStart( 0 ) , m_SelLength( 0 ) , m_DragStart( 0 )
00007 , m_ScrollOffset( 0 ) , m_bMouseDown( false ) , m_bLastMouseMoveInside( false )
00008 {
00009 }
00010
00011 XEditBox::~XEditBox( void )
00012 {
00013 }
00014
00015 const bool XEditBox::SetupWindow( const Message &msg )
00016 {
00017 XBox::SetupWindow( msg );
00018
00019 SetReadOnly( (GetFlags() & F_EDITABLE) != F_EDITABLE );
00020 SetPassBox( (GetFlags() & F_PASSWORD) == F_PASSWORD );
00021
00022 MessageServer::Instance().RegisterMessageClient(this, Message::KEYBOARD_KEYDOWN);
00023 MessageServer::Instance().RegisterMessageClient(this, Message::MOUSE_BUTTONDOWN);
00024 MessageServer::Instance().RegisterMessageClient(this, Message::MOUSE_BUTTONUP);
00025 MessageServer::Instance().RegisterMessageClient(this, Message::MOUSE_MOVE);
00026 MessageServer::Instance().RegisterMessageClient(this, Message::LOST_FOCUS);
00027
00028 return true;
00029 }
00030
00031 void XEditBox::SetReadOnly( const bool bReadOnly )
00032 {
00033 if( bReadOnly )
00034 SetBgColor( GetBgColor().FadeColor( -32 ) );
00035 m_bReadOnly = bReadOnly;
00036 SetDirty();
00037 }
00038
00039 void XEditBox::SetWndText( const std::string &sText )
00040 {
00041 m_SelStart = 0;
00042 m_SelLength = 0;
00043 XBox::SetWndText( sText );
00044 }
00045
00046 std::string XEditBox::GetSelText( void )
00047 {
00048 if( !IsPassBox() )
00049 if( m_SelLength != 0 )
00050 {
00051 unsigned int SelStartNorm = 0, SelLenNorm = 0;
00052 if (m_SelLength < 0)
00053 {
00054 SelStartNorm = m_SelLength + m_SelStart;
00055 SelLenNorm = abs(m_SelLength);
00056 }
00057 else
00058 {
00059 SelStartNorm = m_SelStart;
00060 SelLenNorm = m_SelLength;
00061 }
00062 return GetWindowText().substr( SelStartNorm, SelLenNorm );
00063 }
00064
00065 return "";
00066 }
00067
00068
00069 void XEditBox::SelDelete( std::string *psString )
00070 {
00071
00072 if (m_SelLength > 0)
00073 {
00074 unsigned int SelStartNorm=0, SelLenNorm=0;
00075 if (m_SelLength < 0)
00076 {
00077 SelStartNorm = m_SelLength + m_SelStart;
00078 SelLenNorm = abs(m_SelLength);
00079 }
00080 else
00081 {
00082 SelStartNorm = m_SelStart;
00083 SelLenNorm = m_SelLength;
00084 }
00085 psString->erase(SelStartNorm, SelLenNorm);
00086 m_SelLength = 0;
00087 }
00088 }
00089
00090 void XEditBox::Draw( void )
00091 {
00092 XBox::Draw();
00093
00094 XRect SubRect( *this );
00095 XRect DrawRct( *this );
00096 DrawRct.Grow( -3 );
00097 SubRect.Grow( -3 );
00098
00099 XPoint FontCenterPoint = Center();
00100
00101 if( IsPassBox() )
00102 SetMaskChar( '*' );
00103 else
00104 SetMaskChar( ' ' );
00105
00106 if( ArsApplication::GetInstance()->GetKeyFocus() == dynamic_cast<MessageClient *>( this ) && !m_bReadOnly )
00107 {
00108
00109 XPoint Offset;
00110 std::vector<XRect> CharRects;
00111 GetMetrics( GetWindowText() , 0 , &Offset , &CharRects );
00112 int l = CharRects.size();
00113 int SelStartNorm = 0;
00114 int SelLenNorm = abs(m_SelLength);
00115 if (m_SelLength < 0)
00116 SelStartNorm = m_SelStart + m_SelLength;
00117 else
00118 SelStartNorm = m_SelStart;
00119
00120 SelStartNorm = SelStartNorm;
00121
00122
00123 if( !m_bMouseDown )
00124 {
00125 int RightBorder = CharRects[max( 0 , SelStartNorm + SelLenNorm - 1 )].Right() + Offset.x + SubRect.x + m_ScrollOffset;
00126 int LeftBorder = CharRects[SelStartNorm].x + Offset.x + m_ScrollOffset;
00127 if( GetWindowText().empty() )
00128 RightBorder = LeftBorder;
00129
00130 if (m_SelLength < 0)
00131 {
00132 if (LeftBorder <= 0)
00133 {
00134 m_ScrollOffset = -(CharRects[SelStartNorm].x + Offset.x);
00135 }
00136 else if (RightBorder > SubRect.Right())
00137 {
00138 m_ScrollOffset = SubRect.Right() - (CharRects[max( 0 , SelStartNorm + SelLenNorm - 1 )].Right() + Offset.x + SubRect.x);
00139 }
00140 }
00141 else
00142 {
00143 if (RightBorder >= SubRect.Right())
00144 {
00145 m_ScrollOffset = SubRect.Right() - (CharRects[max( 0 , SelStartNorm + SelLenNorm - 1 )].Right() + Offset.x + SubRect.x);
00146 }
00147 else if (LeftBorder < 0)
00148 {
00149 m_ScrollOffset = -(CharRects[SelStartNorm].x + Offset.x);
00150 }
00151 }
00152
00153 if (m_ScrollOffset != 0 && (CharRects[GetWindowText().length()].Right() + Offset.x + SubRect.x + m_ScrollOffset < SubRect.Right()))
00154 {
00155 m_ScrollOffset = SubRect.Right() - (CharRects[GetWindowText().length()].Right() + Offset.x + SubRect.x);
00156 if (m_ScrollOffset > 0)
00157 {
00158 m_ScrollOffset = 0;
00159 }
00160 }
00161 }
00162
00163
00164 if (m_SelLength != 0)
00165 {
00166 XRect SelRect;
00167 SelRect.y = SubRect.y;
00168 SelRect.SetBottom( SubRect.Bottom() );
00169 SelRect.x = CharRects[SelStartNorm].x + Offset.x + SubRect.x + m_ScrollOffset;
00170 SelRect.SetRight(CharRects[max( 0 , SelStartNorm + SelLenNorm - 1)].Right() + Offset.x + SubRect.x + m_ScrollOffset);
00171 SelRect.ClipTo( SubRect );
00172 DrawRect( SelRect , true , GetBgColor() , GetBgColor().FadeColor( -32 ) );
00173 }
00174 else
00175 {
00176
00177 int CursorPos;
00178 CursorPos = CharRects[m_SelStart].x + Offset.x + SubRect.x + m_ScrollOffset;
00179 if (CursorPos >= SubRect.x && CursorPos <= SubRect.Right())
00180 DrawVLine(SubRect.y, SubRect.Bottom(), CursorPos, GetBgColor().FadeColor( -64 ) );
00181 }
00182 }
00183 DrawRct.x += m_ScrollOffset;
00184 DrawRct.w -= m_ScrollOffset;
00185 int HeightDiff = GetFontSize()/4;
00186 DrawRct.y -= HeightDiff;
00187 DrawRct.SetBottom( DrawRct.Bottom() - HeightDiff );
00188 SubRect.x += m_ScrollOffset;
00189 SubRect.w -= m_ScrollOffset;
00190 TextOutStr( SubRect , GetWindowText() , GetFgColor() );
00191 }
00192
00193 const bool XEditBox::evMouseButtonDown( const MouseMessage &msg )
00194 {
00195 bool ans = XBox::evMouseButtonDown( msg );
00196
00197 if( msg.Button == MouseMessage::LEFT && FindWindow( &msg.Point ) == this && !IsReadOnly() )
00198 {
00199 XRect SubRect( *this );
00200 SubRect.Grow(-3);
00201 XRect ClientRect( GetClientRect() );
00202
00203 XPoint Offset;
00204 std::vector<XRect> CharRects;
00205 GetMetrics( GetWindowText() , 0, &Offset, &CharRects);
00206
00207 int xDelta = abs( msg.Point.x - (CharRects[0].x + Offset.x + SubRect.x));
00208 m_SelStart = 0;
00209 for (unsigned int i = 0; i < GetWindowText().length() ; ++i)
00210 {
00211 if (abs( msg.Point.x - (CharRects[i].Right() + Offset.x + SubRect.x + m_ScrollOffset)) < xDelta)
00212 {
00213 xDelta = abs( msg.Point.x - (CharRects[i].Right() + Offset.x + SubRect.x + m_ScrollOffset));
00214 m_SelStart = i + 1;
00215 }
00216 }
00217
00218 m_DragStart = m_SelStart;
00219 m_SelLength = 0;
00220 m_bMouseDown = true;
00221 SetDirty();
00222 ans = true;
00223 }
00224 return ans;
00225 }
00226
00227 const bool XEditBox::evMouseButtonUp( const MouseMessage &msg )
00228 {
00229 bool ans = XBox::evMouseButtonDown( msg );
00230 m_bMouseDown = false;
00231 return ans;
00232 }
00233
00234 const bool XEditBox::evMouseMove( const MouseMessage &msg )
00235 {
00236 bool ans = XBox::evMouseMove( msg );
00237
00238
00239
00240
00241
00242
00243 if( FindWindow( &msg.Point ) == this && !m_bLastMouseMoveInside)
00244 {
00245 m_bLastMouseMoveInside = true;
00246 Graf::SetMouse( WGRES_IBEAM_CURSOR );
00247 }
00248 else if( HitTest( msg.Point ) != RELPOS_INSIDE && m_bLastMouseMoveInside )
00249 {
00250 m_bLastMouseMoveInside= false;
00251 Graf::SetMouse( 0 );
00252 }
00253
00254 if( !IsReadOnly() && m_bMouseDown )
00255 {
00256 XRect SubRect( *this );
00257 SubRect.Grow(-3);
00258 XRect ClientRect( GetClientRect() );
00259
00260 XPoint Offset;
00261 std::vector<XRect> CharRects;
00262 GetMetrics(GetWindowText() , 0, &Offset, &CharRects);
00263
00264 int xDelta = abs( msg.Point.x - (CharRects[0].x + Offset.x + SubRect.x + m_ScrollOffset));
00265 unsigned int CursorPos = 0;
00266 for (unsigned int i = 0; i < GetWindowText().length() ; ++i)
00267 {
00268 if (abs(msg.Point.x - (CharRects[i].Right() + Offset.x + SubRect.x + m_ScrollOffset)) < xDelta)
00269 {
00270 xDelta = abs( msg.Point.x - (CharRects[i].x + Offset.x + SubRect.x + m_ScrollOffset));
00271 CursorPos = i + 1;
00272 }
00273 }
00274
00275 if (CursorPos < m_DragStart)
00276 {
00277 m_SelLength = m_DragStart - CursorPos;
00278 m_SelStart = CursorPos;
00279 }
00280 else
00281 {
00282 m_SelStart = m_DragStart;
00283 m_SelLength = CursorPos - m_SelStart;
00284 }
00285 SetDirty();
00286 }
00287 if( FindWindow( &msg.Point ) == this && !IsReadOnly() )
00288 SetState( S_HIGHLIGHT );
00289 else
00290 ResetState( S_HIGHLIGHT );
00291
00292 return ans;
00293 }
00294
00295 const bool XEditBox::evKeyDown( const KeyboardMessage &msg )
00296 {
00297 bool ans = XBox::evKeyDown( msg );
00298 if( msg.Destination() == this && !m_bReadOnly )
00299 {
00300 std::string sBuffer = GetWindowText();
00301
00302 switch( msg.Key )
00303 {
00304 case SDLK_BACKSPACE:
00305 if( m_SelStart > 0 )
00306 if (m_SelLength > 0)
00307 SelDelete( &sBuffer );
00308 else
00309 sBuffer.erase( --m_SelStart, 1 );
00310 break;
00311
00312 case SDLK_DELETE:
00313 if( static_cast<unsigned int>(m_SelStart) < sBuffer.length() )
00314 if( m_SelLength > 0 )
00315 SelDelete( &sBuffer );
00316 else
00317 sBuffer.erase( m_SelStart , 1 );
00318 break;
00319
00320 case SDLK_LEFT:
00321 if ((msg.Modifiers & KMOD_LSHIFT) || (msg.Modifiers & KMOD_RSHIFT))
00322 {
00323 if (m_SelStart > 0)
00324 {
00325 if (m_SelLength > 0)
00326 m_SelLength--;
00327 else
00328 if ((m_SelStart - abs(m_SelLength)) > 0)
00329 m_SelLength--;
00330 }
00331 }
00332 else if (m_SelLength != 0)
00333 {
00334 if (m_SelLength < 0)
00335 m_SelStart = m_SelStart + m_SelLength;
00336 m_SelLength = 0;
00337
00338 }
00339 else if (m_SelStart > 0)
00340 {
00341 --m_SelStart;
00342 m_SelLength = 0;
00343 }
00344 break;
00345
00346 case SDLK_RIGHT:
00347 if (static_cast<unsigned int>(m_SelStart) <= sBuffer.length())
00348 {
00349 if ((msg.Modifiers & KMOD_LSHIFT) || (msg.Modifiers & KMOD_RSHIFT))
00350 {
00351 if (m_SelStart + m_SelLength < sBuffer.length())
00352 m_SelLength++;
00353 }
00354 else if(m_SelLength == 0 && static_cast<unsigned int>(m_SelStart) < sBuffer.length())
00355 ++m_SelStart;
00356 else
00357 {
00358 if (m_SelLength > 0)
00359 m_SelStart = m_SelStart + m_SelLength;
00360 m_SelLength = 0;
00361 }
00362 }
00363 break;
00364
00365 case SDLK_END:
00366 if ((msg.Modifiers & KMOD_LSHIFT) || (msg.Modifiers & KMOD_RSHIFT))
00367 m_SelLength = static_cast<unsigned int>(sBuffer.length()) - m_SelStart;
00368 else
00369 {
00370 m_SelLength = 0;
00371 m_SelStart = static_cast<unsigned int>(sBuffer.length());
00372 }
00373 break;
00374
00375 case SDLK_HOME:
00376 if ((msg.Modifiers & KMOD_LSHIFT) || (msg.Modifiers & KMOD_RSHIFT))
00377 {
00378 m_SelLength = m_SelStart;
00379 m_SelStart = 0;
00380 }
00381 else
00382 {
00383 m_SelLength = 0;
00384 m_SelStart = 0;
00385 }
00386 break;
00387 default:
00388 if (msg.Unicode)
00389 {
00390 if ((msg.Unicode & 0xFF80) == 0)
00391 {
00392 SelDelete(&sBuffer);
00393 sBuffer.insert(m_SelStart++, 1, static_cast<char>(msg.Unicode & 0x7F));
00394 }
00395 else
00396 tron << "CEditBox::HandleMessage : CEditBox can't handle Unicode characters yet.\n";
00397 }
00398 break;
00399 }
00400
00401 if( GetWindowText() != sBuffer )
00402 {
00403 ArsPostMessage( CtrlMessage( Message::CTRL_VALUECHANGE, GetParent(), this, 0 ) );
00404 ArsPostMessage( CtrlMessage( Message::CTRL_VALUECHANGE, this , this, 0 ) );
00405 }
00406 XBox::SetWndText( sBuffer );
00407 GetTextSize( sBuffer );
00408 SetDirty();
00409 ans = true;
00410 }
00411
00412 return ans;
00413 }
00414
00415 }
00416