00001 #include "SdlArs.h"
00002
00003 namespace Ars
00004 {
00005 Window::Window( void )
00006 : clientRect( 0 , 0 , 0 , 0 ) , m_MouseButton( 0 )
00007 , paintAlreadySent( false ) , parentWindow( 0 ) , bkgnd( 0 ) , toolTip( 0 )
00008 {
00009 MessageServer::Instance().RegisterMessageClient( this , Message::SETUP_WINDOW );
00010 }
00011
00012 Window::~Window( void )
00013 {
00014 MessageServer::Instance().DeregisterMessageClient( this );
00015
00016 if( bkgnd )
00017 {
00018 if( GetGDI() )
00019 {
00020 XRect r( 0 , 0 , bkgnd->w , bkgnd->h );
00021 SDL_BlitSurface( bkgnd , &r , GetGDI() , static_cast<SDL_Rect *>( this ) );
00022 }
00023 SDL_FreeSurface( bkgnd );
00024 }
00025 bkgnd = 0;
00026
00027
00028 unsigned int iSanityCheck = static_cast<unsigned int>( size() );
00029 while( size() > 0 && iSanityCheck > 0 )
00030 {
00031 Window *w = *(begin());
00032 delete w;
00033 --iSanityCheck;
00034 }
00035 TraceIf( iSanityCheck != 0, "Sanity check failed in CWindow destructor!" );
00036 TraceIf( !empty(), "CWindow children not empty at end of destructor!" );
00037 clear();
00038 SetParent( 0 );
00039
00040 if( toolTip )
00041 delete toolTip;
00042 toolTip = 0;
00043 }
00044
00045 const bool Window::SetupWindow( const Message &msg )
00046 {
00047 Painter::SetupWindow( msg );
00048 MessageServer::Instance().DeregisterMessageClient( this , Message::SETUP_WINDOW );
00049 MessageServer::Instance().RegisterMessageClient(this, Message::APP_PAINT);
00050
00051 if( toolTip )
00052 toolTip->SetupWindow( msg );
00053
00054 return true;
00055 }
00056
00057 void Window::Init( icstring &aStr )
00058 {
00059 Painter::Init( aStr );
00060 icstring tmp = Rsrc::FindCrdOf( aStr , "str" );
00061 SetWndText( Rsrc::GetStr( tmp , GetWindowText() ) );
00062
00063 tmp = Rsrc::FindCrdOf( aStr , "sound" );
00064 soundName = Rsrc::GetId(tmp );
00065
00066 tmp = Rsrc::FindCrdOf( aStr , "tooltip" );
00067 if( !tmp.empty() )
00068 {
00069
00070 toolTip = new XToolTip( this );
00071
00072 toolTip->Init( tmp );
00073 }
00074 }
00075
00076 const bool Window::ShowWindow( void )
00077 {
00078 ResetFlags( F_HIDETREE );
00079 for_each( begin() , end() , mem_fun( &Window::ShowWindow ) );
00080
00081 return true;
00082 }
00083
00084 const bool Window::HideWindow( void )
00085 {
00086 SetFlags( F_HIDETREE );
00087 for_each( begin() , end() , mem_fun( &Window::HideWindow ) );
00088
00089 return true;
00090 }
00091
00092 XRect Window::GetClientRect( void )
00093 {
00094 XRect ClientRect( GetWindowRect().TopLeft() + clientRect.TopLeft(), GetWindowRect().TopLeft() + clientRect.BottomRight());
00095 ClientRect.ClipTo( GetWindowRect() );
00096 return ClientRect;
00097 }
00098
00099 Window *Window::GetRoot( void ) const
00100 {
00101 if( parentWindow )
00102 {
00103 Window *pWindow = GetParent();
00104
00105 while( pWindow->GetParent() )
00106 pWindow = pWindow->GetParent();
00107
00108 return pWindow;
00109 }
00110 else
00111 return const_cast< Window *>( this );
00112 }
00113
00114 const bool Window::SetParent( Window *pNewParent)
00115 {
00116
00117
00118
00119
00120 if( pNewParent )
00121 {
00122 if( parentWindow )
00123 parentWindow->DeregisterChildWindow( this );
00124 pNewParent->RegisterChildWindow( this );
00125 SetGDI( pNewParent->GetRoot()->GetGDI() );
00126 }
00127 else
00128 {
00129 MessageServer::Instance().DeregisterMessageClient( this );
00130 MessageServer::Instance().RegisterMessageClient( this , Message::SETUP_WINDOW );
00131 for_each( begin() , end() , mem_fun( &Window::ResetChildren ) );
00132
00133 clear();
00134
00135 if( parentWindow )
00136 parentWindow->DeregisterChildWindow( this );
00137 }
00138
00139 parentWindow = pNewParent;
00140
00141 return true;
00142 }
00143
00144 const bool Window::ResetChildren( void )
00145 {
00146 parentWindow = 0;
00147
00148 MessageServer::Instance().DeregisterMessageClient( this );
00149 MessageServer::Instance().RegisterMessageClient( this , Message::SETUP_WINDOW );
00150
00151 for_each( begin() , end() , mem_fun( &Window::ResetChildren ) );
00152
00153 clear();
00154
00155 return true;
00156 }
00157
00158 void Window::RegisterChildWindow( Window *window)
00159 {
00160 push_back( window );
00161 }
00162
00163
00164 void Window::DeregisterChildWindow( Window *window )
00165 {
00166 remove( window );
00167 }
00168
00169 const bool Window::DeregChild( const CtrlMessage &msg )
00170 {
00171 DeregisterChildWindow( (Window *)msg.source );
00172 return true;
00173 }
00174
00175 void Window::UpdateWindow( const bool aNow )
00176 {
00177 if( aNow )
00178 ArsSendMessage( Message( Message::APP_PAINT , this ) );
00179 else if( !paintAlreadySent )
00180 {
00181 ArsPostMessage( Message( Message::APP_PAINT , this ) );
00182 paintAlreadySent = true;
00183 }
00184 }
00185
00186 void Window::DrawBG( void )
00187 {
00188 if( bkgnd == 0 && GetGDI() )
00189 {
00190 bkgnd = Graf::NewSurface( Width() + 1 , Height() + 1 , GetGDI() );
00191 XRect r( 0 , 0 , bkgnd->w , bkgnd->h );
00192 XRect t( *this );
00193 t.w += 1;
00194 t.h += 1;
00195 SDL_BlitSurface( GetGDI() , &t , bkgnd , &r );
00196 }
00197
00198 if( (GetStates() & S_TRANSPARENT) == 0 )
00199 DrawRect( GetWindowRect() , true , GetBgColor() , GetBgColor() );
00200 }
00201
00202 void Window::Draw( void )
00203 {
00204 }
00205
00206 void Window::DrawChildren( void )
00207 {
00208 if( !empty() )
00209 {
00210 int n = size();
00211 for_each( begin() , end() , mem_fun( &Window::DrawProc ) );
00212 }
00213 }
00214
00215 const bool Window::DrawProc( void )
00216 {
00217 if( IsVisible() )
00218 {
00219 AdjustColors();
00220
00221 DrawBG();
00222 Draw();
00223
00224 RestoreColors();
00225
00226 DrawChildren();
00227 }
00228
00229 SetDirty( false );
00230
00231 return IsVisible();
00232 }
00233
00234 const bool Window::wmPaint( const Message &m )
00235 {
00236 if( IsVisible() )
00237 {
00238 DrawProc();
00239 SDL_UpdateRect( GetGDI() , x , y , w , h );
00240 paintAlreadySent = false;
00241 }
00242 else if( GetGDI() && bkgnd )
00243 {
00244 XRect r( 0 , 0 , bkgnd->w , bkgnd->h );
00245 XRect t( *this );
00246 t.w += 1;
00247 t.h += 1;
00248 SDL_BlitSurface( bkgnd , &r , GetGDI() , &t );
00249 SDL_UpdateRect( GetGDI() , x , y , w , h );
00250 paintAlreadySent = false;
00251 SDL_FreeSurface( bkgnd );
00252 bkgnd = 0;
00253 }
00254
00255 SetDirty( false );
00256
00257 return (m.Destination() == this);
00258 }
00259
00260 const bool Window::HandleMessage( const Message &msg )
00261 {
00262 const bool ans = Thing::HandleMessage( msg );
00263
00264 if( msg.MessageType() != Message::SETUP_WINDOW )
00265 if( IsDirty() )
00266 UpdateWindow( true );
00267
00268 return ans;
00269 }
00270
00271 const bool Window::evMouseButtonDown( const MouseMessage &msg )
00272 {
00273 bool ans = Painter::evMouseButtonDown( msg );
00274
00275 if( (GetStates() & S_DISABLED) != S_DISABLED )
00276 {
00277 if( FindWindow( &msg.Point ) == this )
00278 {
00279 m_MouseButton = msg.Button;
00280
00281 if( ArsApplication::GetInstance()->GetKeyFocus() != this && (GetFlags() & MAY_GAINFOCUS) != 0 )
00282 ArsApplication::GetInstance()->SetKeyFocus( this );
00283
00284 ans = true;
00285 }
00286 }
00287 return ans;
00288 }
00289
00290 const bool Window::evMouseButtonUp( const MouseMessage &msg )
00291 {
00292 bool ans = Painter::evMouseButtonUp( msg );
00293
00294 if( (GetStates() & S_DISABLED) != S_DISABLED )
00295 {
00296 if( FindWindow( &msg.Point ) == this && m_MouseButton == msg.Button )
00297 {
00298 Message::EMessageType MessageType = Message::UNKNOWN;
00299 switch( m_MouseButton )
00300 {
00301 case MouseMessage::LEFT:
00302
00303 MessageType = Message::CTRL_LCLICK;
00304 break;
00305 case MouseMessage::RIGHT:
00306 MessageType = Message::CTRL_RCLICK;
00307 break;
00308 case MouseMessage::MIDDLE:
00309 MessageType = Message::CTRL_MCLICK;
00310 break;
00311 }
00312 if( !soundName.empty() )
00313 GetSound( soundName ).Play();
00314
00315 ArsSendMessage( CtrlMessage( MessageType , this , this, 0 ) );
00316
00317 ans = true;
00318 }
00319 }
00320 return ans;
00321 }
00322
00323 const bool Window::RelposInside( const XPoint *pt )
00324 {
00325 return HitTest( *pt ) == RELPOS_INSIDE;
00326 }
00327
00328 Window *Window::FindWindow( const XPoint *pt )
00329 {
00330 if( HitTest( *pt ) == RELPOS_INSIDE )
00331 {
00332 std::list<Window *>::iterator at = find_if( begin() , end() , bind2nd( mem_fun( &Window::RelposInside ) , pt ) );
00333 if( at != end() && (*at)->IsVisible() )
00334 return(*at)->FindWindow( pt );
00335 return this;
00336 }
00337 return 0;
00338 }
00339
00340 const bool Window::IsChild( Window *wnd )
00341 {
00342 if( !empty() )
00343 for( std::list<Window *>::iterator it = begin() ; it != end() ; ++it )
00344 if( (*it) == wnd )
00345 return true;
00346 else if( (*it)->IsChild( wnd ) )
00347 return true;
00348 return false;
00349 }
00350
00351 }