Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals

xeditbox.cpp

Go to the documentation of this file.
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         //This means we've selected something, therefore, should replace it
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                 // Handle scrolling
00122                 // Patch        for "Scrolling while selecting to left in editbox" by Oldrich Dlouhy
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                 // Selection
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                         //RenderStringWithCursor
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         //If the cursor is within the control then check to see if we've already
00239         // set the cursor to the I Beam, if we have, don't do anything.  If we
00240         // havent, set it to the ibeam.
00241         //Else if it's outside the control and the I Beam cursor is set, set it
00242         // back to a normal cursor.
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)) //Shift modifier
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) //Prevent us from selecting past the beginning of the text
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++; //We WANT to select something, so we'll just increase the selection length
00353                                         }
00354                                         else if(m_SelLength == 0 && static_cast<unsigned int>(m_SelStart) < sBuffer.length())
00355                                                 ++m_SelStart; //We don't have anything selected, so we'll just incriment the start position
00356                                         else
00357                                         {
00358                                                 if (m_SelLength > 0)
00359                                                         m_SelStart = m_SelStart + m_SelLength; //Reset cursor position to the end of the selection
00360                                                 m_SelLength = 0; //Set selection length to zero
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 

Generated on Fri Dec 5 04:06:00 2003 for Borqueror by doxygen 1.3.3