Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

WindowManager.cpp

Go to the documentation of this file.
00001 
00002 /*
00003     TEDDY - General graphics application library
00004     Copyright (C) 1999-2002  Timo Suoranta
00005     tksuoran@cc.helsinki.fi
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021     $Id: WindowManager.cpp,v 1.7 2002/03/12 10:46:07 tksuoran Exp $
00022 */
00023 
00024 
00025 #include "Teddy/TeddyConfig.h"
00026 #include "Teddy/PhysicalComponents/ActionButton.h"
00027 #include "Teddy/PhysicalComponents/WindowManager.h"
00028 #include "Teddy/PhysicalComponents/Dock.h"
00029 #include "Teddy/PhysicalComponents/Layer.h"
00030 #include "Teddy/Graphics/View.h"
00031 #include "Teddy/Graphics/ImageFileTexture.h"
00032 #include "Teddy/SysSupport/Messages.h"
00033 #include "Teddy/SysSupport/StdSDL.h"
00034 #include "Teddy/SysSupport/StdIO.h"
00035 using namespace Teddy::Graphics;
00036 
00037 
00038 namespace Teddy              {
00039 namespace PhysicalComponents {
00040 
00041 
00043 WindowManager::WindowManager( View *view ){
00044     int i;
00045 
00046     this->view        = view;
00047     this->focus       = NULL;
00048     this->show_cursor = true;
00049 
00050     SDL_EnableUNICODE  ( 1 );
00051     SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
00052 
00053 #   if 0
00054     this->cursor    = new ImageFileTexture( "Data/gui/frontier_cursor.png" );
00055     if( cursor != NULL ){
00056         if( cursor->isGood() == true ){
00057             //SDL_ShowCursor( SDL_DISABLE );
00058         }
00059     }
00060 #   else
00061     this->cursor = NULL;
00062 #   endif
00063 
00064 #if defined( HAVE_SDL_JOYSTICKOPEN )
00065     //  Quick-hack joystick test code
00066     int num_joys = SDL_NumJoysticks();
00067     dmsg( M_INIT, "%d joysticks found", num_joys );
00068     for( i=1; i<=num_joys; i++ ){
00069         const char *j_name = SDL_JoystickName( i );
00070         if( j_name != NULL ){
00071             dmsg( M_WME, "Joystick number %d: %s", i, j_name );
00072         }
00073     }
00074     
00075     if( num_joys >= 1 ){
00076         //  Open first joystick
00077         joystick = SDL_JoystickOpen( 0 );
00078         if( joystick != NULL ){
00079             int joy_axes    = SDL_JoystickNumAxes   ( joystick );
00080             int joy_balls   = SDL_JoystickNumBalls  ( joystick );
00081             int joy_hats    = SDL_JoystickNumHats   ( joystick );
00082             int joy_buttons = SDL_JoystickNumButtons( joystick );
00083             dmsg( M_WME,
00084                 "Joystick: %d axes %d balls %d hats %d buttons", 
00085                 joy_axes,
00086                 joy_balls,
00087                 joy_hats,
00088                 joy_buttons
00089             );
00090 
00091             //int joy_events_enabled = SDL_JoystickEventState( SDL_DISABLE );
00092             int joy_events_enabled = SDL_JoystickEventState( SDL_ENABLE );
00093             if( joy_events_enabled == SDL_ENABLE ){
00094                 dmsg( M_WME, "Joystick events enabled" );
00095             }else{
00096                 dmsg( M_WME, "Joystick events : %d", joy_events_enabled );
00097             }
00098         }else{
00099             emsg( M_WME, "SDL_JoystickOpen() did not work" );
00100         }
00101     }else{
00102         joystick = NULL;
00103     }
00104 #else
00105     dmsg( M_INIT, "Teddy was compiled without SDL joystick support" );
00106     joystick = NULL;
00107 #endif
00108 
00109     show_cursor = true;
00110     hold        = false;
00111 
00112     for( i=0; i<3; i ++ ){ 
00113         mouse_b[i] = 0; 
00114     } 
00115     hold_pos  = view->getSize() / 2; 
00116     mouse_pos = view->getSize() / 2; 
00117     SDL_WarpMouse( (int)hold_pos[0], (int)hold_pos[1] );
00118 }
00119 
00120 
00122 WindowManager::~WindowManager(){
00123 #if defined( HAVE_SDL_JOYSTICKOPEN )
00124     if( joystick != NULL ){
00125         SDL_JoystickClose( joystick );
00126         joystick = NULL;
00127     }
00128 #endif
00129 }
00130 
00131 
00133 void WindowManager::inputLoop(){
00134     for( ;; ){
00135         SDL_Event event;
00136 
00137 #   if !defined( USE_TINY_GL )
00138         SDL_Delay( 1 );  // FIX some kind of delay is needed if going faster than 100 fps
00139 #   endif
00140         view->display();
00141 
00142         while( SDL_PollEvent(&event) ) {
00143             switch( event.type ){
00144 
00145             case SDL_KEYDOWN:
00146                 switch( event.key.keysym.sym ){
00147                 case SDLK_ESCAPE:  
00148                     dmsg( M_WME, "SDL_KEYDOWN SDLK_ESCAPE" );
00149                     exit( 0 ); 
00150                     break;
00151                 case SDLK_EXCLAIM: // for those that dont have print key
00152                 case SDLK_PRINT:   
00153                     dmsg( M_WME, "SDL_KEYDOWN SDLK_EXCLAIM or SDLK_PRINT" );
00154                     view->pngScreenshot( "shot.png" );
00155                     break;
00156                 default: break;
00157                 }
00158                 break;
00159             case SDL_MOUSEMOTION:
00160                 dmsg( M_WME, "SDL_MOUSEMOTION" );
00161                 mouseMotion( event.motion.x, event.motion.y, 0, 0 );
00162                 break;
00163             case SDL_MOUSEBUTTONDOWN:
00164             case SDL_MOUSEBUTTONUP:
00165                 dmsg( M_WME, "SDL_MOUSEBUTTONDOWN / SDL_MOUSEBUTTONUP" );
00166                 mouseKey( event.button.button, event.button.state, event.button.x, event.button.y );
00167                 break;
00168             case SDL_QUIT:            
00169                 dmsg( M_WME, "SDL_QUIT" );
00170                 exit( 0 ); 
00171                 break;
00172             case SDL_VIDEORESIZE:
00173                 dmsg( M_WME, "SDL_VIDEORESIZE" );
00174                 //  This messes OpenGL contexts; destroys the old one and creates a new one.
00175                 //  We need to reupload textures and redo displaylists
00176                 if( SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL|SDL_RESIZABLE/*|SDL_FULLSCREEN*/) == NULL ) {
00177                     fmsg( M_WME, "Unable to resize OpenGL screen: %s", SDL_GetError() );
00178                 }
00179                 break;
00180             default:
00181                 break;
00182             }
00183 
00184             if( focus != NULL ){  //  Some focus
00185                 Named       *focus_name = dynamic_cast<Named *>( focus );
00186                 std::string  names      = "[unnamed]";
00187                 if( focus_name != NULL ){
00188                     names = focus_name->getName();
00189                 }
00190                 const char *name = names.c_str();
00191                 dmsg( M_WME, "%s focus", name );
00192                 switch( event.type ){
00193                 case SDL_KEYDOWN:       
00194                     dmsg( M_WME, "SDL_KEYDOWN" );
00195                     focus->event( KeyDownEvent  (event.key.keysym) ); 
00196                     break;
00197                 case SDL_KEYUP:         
00198                     dmsg( M_WME, "SDL_KEYUP" );
00199                     focus->event( KeyUpEvent    (event.key.keysym) ); 
00200                     break;
00201                 case SDL_JOYAXISMOTION: 
00202                     dmsg( M_WME, "SDL_JOYAXISMOTION" );
00203                     focus->event( JoyAxisEvent  (event.jaxis.axis, event.jaxis.value) ); 
00204                     break;
00205                 case SDL_JOYHATMOTION:  
00206                     dmsg( M_WME, "SDL_JOYHATMOTION" );
00207                     focus->event( JoyHatEvent   (event.jhat.hat, event.jhat.value) ); 
00208                     break;
00209                 case SDL_JOYBALLMOTION: 
00210                     dmsg( M_WME, "SDL_JOYBALLMOTION" );
00211                     focus->event( JoyBallEvent  (event.jball.ball, Vector2(event.jball.xrel,event.jball.yrel) ) ); 
00212                     break;
00213                 case SDL_JOYBUTTONDOWN: 
00214                 case SDL_JOYBUTTONUP:   
00215                     dmsg( M_WME, "SDL_JOYBUTTONDOWN / SDL_JOYBUTTONUP" );
00216                     focus->event( JoyButtonEvent(event.jbutton.button, event.jbutton.state) ); 
00217                     break;
00218                 default:
00219                     break;
00220                 }
00221             }
00222         }  //  while( SDL_PollEvent(&event) )
00223     }  //  for(;;){
00224 }
00225 
00226 
00228 /*virtual*/ void WindowManager::mouseKey( int button, int state, int x, int y ){
00229     EventListener *focus_try      = NULL;
00230     Area          *focus_try_area = NULL;
00231     Vector2        pos(x,y);
00232 
00233     mouse_b[button] = state;
00234 
00235 #   if defined( USE_TINY_GL )
00236     bool all_released = true;
00237     for( int i=1; i<4; i++ ){
00238         if( mouse_b[i] == SDL_PRESSED ){
00239             all_released = false;
00240         }
00241     }
00242 #   endif
00243 
00244 
00245     //  Every click checks if area needs to be changed
00246     //  This is click to focus policy
00247     //  Should be configurable; do later
00248     if( state==SDL_PRESSED ){
00249         dmsg( M_WME, "looking for hit" );
00250         Area *hit = NULL;
00251 
00252         list<Layer*>::iterator l_it = layers.begin();
00253         while( l_it != layers.end() ){
00254             Layer *l = (*l_it);
00255             hit = l->getHit( pos );
00256             if( hit != NULL ){
00257                 break;
00258             }
00259             l_it++;
00260         }
00261 
00262         if( hit == NULL ){
00263             dmsg( M_WME, "No area there" );
00264         }else{
00265             dmsg( M_WME, "Click over %s", hit->getName().c_str() );
00266 
00267             Named        *focus_name = dynamic_cast<Named *>( hit );
00268             std::string   name       = "[unnamed]";
00269             if( focus_name != NULL ){
00270                 name = focus_name->getName();
00271             }
00272             //  Is this Area an EventListener one?
00273             dmsg( M_WME, "Area          * = 0x%08x", (unsigned long)(hit)       );
00274             focus_try = dynamic_cast<EventListener*>( hit );
00275             dmsg( M_WME, "EventListener * = 0x%08x", (unsigned long)(focus_try) );
00276             if( focus_try == NULL ){
00277                 dmsg( M_WME, "%s is not listening to events", name.c_str() );
00278             }
00279 
00280             this->setFocus( focus_try );
00281         }
00282 
00283     }
00284 
00285     Named       *focus_name = dynamic_cast<Named *>( focus );
00286     std::string  name       = "[unnamed]";
00287     if( focus_name != NULL ){
00288         name = focus_name->getName();
00289     }
00290         
00291     //  FIX It is unclear - should use style or something - if
00292     //  Area wants to receive the event that activated it.
00293     if( focus != NULL ){
00294         if( state && focus->doesEvent(Event::MouseButtonDownEvent_ID) ){
00295             dmsg( M_WME, "MouseButtonDownEvent sent to %s", name.c_str() );
00296             focus->event( MouseButtonDownEvent(button,state,pos) );
00297         }else if( !state && focus->doesEvent(Event::MouseButtonUpEvent_ID) ){
00298             dmsg( M_WME, "MouseButtonUpEvent sent to %s", name.c_str() );
00299             focus->event( MouseButtonUpEvent(button,state,pos) );
00300         }else{
00301             dmsg( M_WME, "does not MouseButtonDownEvent / MouseButtonUpEvent" );
00302         }
00303         if( focus->doesEvent(Event::MouseHoldDragEvent_ID) ){
00304             hold_pos = pos;
00305             setHold( state==SDL_PRESSED ? true : false );
00306         }else{
00307             dmsg( M_WME, "does not MouseHoldDragEvent_ID" );
00308         }
00309     }else{
00310         dmsg( M_WME, "No Area has focus" );
00311     }
00312 
00313 }
00314 
00315 
00316 //  MouseListener interface
00317 /*virtual*/ void WindowManager::mouseMotion( int x, int y, int dx, int dy ){
00318     IntVector2 pos(x,y);
00319     //  Motion does not currently check for
00320     //  focus change; Click to focus policy is used
00321     //  Should be able to change focus with motion
00322     //  only too; Add later
00323 
00324     //  If warping, don't process mouse motion
00325     //  Actually here may be some cases which want the
00326     //  motion
00327     if( hold == true ){
00328         if( pos == hold_pos ){
00329             mouse_pos = pos;
00330             dmsg( M_WME, "Hold ignore" );
00331             return;
00332         }
00333         SDL_WarpMouse( hold_pos[0], hold_pos[1] );
00334         dmsg( M_WME, "Hold warp" );
00335     }
00336 
00337     IntVector2 delta = pos - mouse_pos;
00338     mouse_pos = pos;
00339 
00340     if( focus == NULL ){
00341         dmsg( M_WME, "No Area has focus" );
00342         return;
00343     }
00344 
00345     Named       *focus_name = dynamic_cast<Named *>( focus );
00346     std::string  names      = "[unnamed]";
00347     if( focus_name != NULL ){
00348         names = focus_name->getName();
00349     }
00350     const char *name = names.c_str();
00351 
00352     if( focus->doesEvent(Event::MouseMotionEvent_ID) ){
00353         focus->event( MouseMotionEvent(mouse_pos,delta) );
00354     }else{
00355         dmsg( M_WME, "%s does not MouseMotionEvent", name );
00356     }
00357 
00358     //  Update last button drag positions
00359     for( int b=1; b<4; b++ ){
00360         if( mouse_b[b]==SDL_PRESSED ){
00361             if( focus->doesEvent(Event::MouseHoldDragEvent_ID) ){
00362 #               if defined( USE_TINY_GL )
00363                 //SDL_ShowCursor( SDL_DISABLE );
00364 #               endif
00365                 focus->event( MouseHoldDragEvent(pos,delta,b) );
00366             }else if( focus->doesEvent(Event::MouseDragEvent_ID) ){
00367                 focus->event( MouseDragEvent(pos,delta,b) );
00368             }else{
00369                 dmsg( M_WME, "%s does not MouseHoldDragEvent nor MouseDragEvent", name );
00370             }
00371         }
00372     }
00373 
00374 }
00375 
00376 
00378 void WindowManager::insert( Layer *layer ){
00379     layers.push_back( layer );
00380 }
00381 
00382 
00384 void WindowManager::showCursor(){
00385 #   if !defined( USE_TINY_GL )
00386     show_cursor = true;
00387 #   else
00388     //SDL_ShowCursor( SDL_ENABLE );
00389 #   endif
00390 }
00391 
00392 
00394 void WindowManager::hideCursor(){
00395 #   if !defined( USE_TINY_GL )
00396     show_cursor = false;
00397 #   else
00398     //SDL_ShowCursor( SDL_DISABLE );
00399 #   endif
00400 }
00401 
00402  
00404 void WindowManager::draw(){
00405     list<Layer*>::iterator l_it = layers.begin();
00406     while( l_it != layers.end() ){
00407         Layer *l = (*l_it);
00408         l->drawLayer();
00409         l_it++;
00410     }
00411 
00412     view->begin2d();
00413     view->enable( View::TEXTURE_2D );
00414     view->enable( View::BLEND );
00415 
00416 #   if !defined( USE_TINY_GL )
00417     if( (show_cursor == true) && (cursor != NULL) && (cursor->isGood() == true) ){
00418         view->color( C_WHITE );
00419         Vector2 fpos = mouse_pos - cursor->getSize()/2;
00420         view->blit( fpos, cursor );
00421     }
00422 #   endif
00423 }
00424 
00425 
00427 void WindowManager::update(){
00428     list<Layer*>::iterator l_it = layers.begin();
00429     while( l_it != layers.end() ){
00430         (*l_it)->update( view );
00431         l_it++;
00432     }
00433 }
00434 
00435 
00436 
00437 void WindowManager::setHold( bool apply ){
00438     dmsg( M_WME, "WindowManager::setHold( %s )", apply?"true":"false" );
00439     if( hold != apply ){
00440         hold     = apply;
00441         if( hold == true ){
00442             hold_pos = mouse_pos;
00443             dmsg( M_WME, "Set hold to true" );
00444         }else{
00445             dmsg( M_WME, "Hold released" );
00446         }
00447         if( cursor == NULL || cursor->isGood() == false ){
00448             if( hold==true ){
00449                 //SDL_ShowCursor( SDL_DISABLE );
00450             }else{
00451                 //SDL_ShowCursor( SDL_ENABLE );
00452             }
00453         }
00454     }else{
00455         dmsg( M_WME, "Hold unchanged" );
00456     }
00457 }       
00458 
00459 
00460 bool WindowManager::getHold() const {
00461     return hold;
00462 }
00463 
00464 
00466 void WindowManager::setFocus( EventListener *focus_try ){
00467     if( focus != focus_try ){
00468         if( focus != NULL ){
00469             focus->event( WindowFocusActiveEvent(0) );
00470         }
00471         focus = focus_try;
00472         if( focus != NULL ){
00473             focus->event( WindowFocusActiveEvent(1) );
00474         }
00475     }
00476 }
00477 
00478 
00480 View *WindowManager::getView(){
00481     return this->view;
00482 }
00483 
00484 
00485 };  //  namespace PhysicalComponents
00486 };  //  namespace Teddy
00487 
00488