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

Console.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: Console.cpp,v 1.5 2002/03/12 10:46:07 tksuoran Exp $
00022 */
00023 
00024 
00025 #include "Teddy/TeddyConfig.h"
00026 #include "Teddy/PhysicalComponents/Console.h"
00027 #include "Teddy/PhysicalComponents/Style.h"
00028 #include "Teddy/PhysicalComponents/GradientFill.h"
00029 #include "Teddy/PhysicalComponents/WindowManager.h"
00030 #include "Teddy/PhysicalComponents/Label.h"
00031 #include "Teddy/Graphics/Color.h"
00032 #include "Teddy/Graphics/Font.h"
00033 #include "Teddy/Graphics/View.h"
00034 #include "Teddy/SysSupport/Messages.h"
00035 #include "Teddy/SysSupport/StdIO.h"
00036 #ifndef SWIG
00037 #include <cstdlib>
00038 using namespace std;
00039 #endif
00040 using namespace Teddy::Graphics;
00041 using namespace Teddy::Signals;
00042 
00043 
00044 namespace Teddy              {
00045 namespace PhysicalComponents {
00046 
00047 
00049 Console::Console( const std::string &name, const int w, const int h )
00050 :Area( name )
00051 {
00052     this->font_width       = style->monospace_font->getWidth();
00053     this->font_height      = style->monospace_font->getHeight();
00054     this->width_chars      = w;
00055     this->height_chars     = h;
00056     this->max_height_chars = h;
00057 
00058     //  This might need to be changed somehow
00059     buffer_lines.reserve( 200 );
00060     for( int i=0; i<h; i++ ){
00061         buffer_lines.push_back( new string("") );
00062     }
00063 
00064     topleft_x      = 0;
00065     topleft_y      = 0;
00066     cx             = 0;
00067     cy             = 0;
00068     cursor_visible = true;  //  FIX should be in Style
00069     text_color     = Color::GRAY_75;
00070 //  logical_ui     = NULL;
00071 
00072     fill_base_pixels[0] = w * font_width;
00073     fill_base_pixels[1] = h * font_height;
00074 
00075     //  FIX  Don't do this in final Console
00076     //       Only while debugging when there is no decent
00077     //       source for LayoutConstraint
00078     GradientFill *fill = new GradientFill(
00079         Color( 0.2f, 0.3f, 0.4f, 0.99f ),
00080         Color( 0.2f, 0.3f, 0.4f, 0.99f ),
00081         Color( 0.1f, 0.2f, 0.3f, 0.66f ),
00082         Color( 0.1f, 0.2f, 0.3f, 0.66f )
00083     );
00084 //  WindowFrame *frame = new WindowFrame( name );
00085     this->insert( fill );
00086 //  this->insert( frame );
00087 
00088     drawing_ordering = post_self;
00089 
00090     bind( Event::WindowFocusActiveEvent_ID, functor( this, &Console::focusActive ) );
00091     bind( Event::KeyDownEvent_ID          , functor( this, &Console::keyDown     ) );
00092 }
00093 
00094 /*
00095 
00096 C:\Work\Teddy-1.78\Teddy\PhysicalComponents\Console.cpp(89)
00097 : error: more than one instance of overloaded function "functor" matches the argument list:
00098 
00099             function template "Teddy::Signals::functor(T *, void (T::*)(A1))"
00100             function template "Teddy::Signals::functor(T *, R (T::*)(A1))"
00101 
00102             argument types are: (Teddy::PhysicalComponents::Console *, void (Teddy::PhysicalComponents::Console::*)(const Teddy::PhysicalComponents::Event &))
00103    bind( WindowFocusActiveEvent_ID, functor( this, &Console::focusActive ) );
00104                                     ^
00105 
00106   */
00107 
00108 /*
00109 const int Event_ID                  =  0;
00110 const int WindowEvent_ID            =  1;
00111 const int WindowFocusActiveEvent_ID =  2;
00112 const int WindowPopupOpenEvent_ID   =  3;
00113 const int WindowPopupCloseEvent_ID  =  4;
00114 const int WindowMoveEvent_ID        =  5;
00115 const int WindowSizeEventEvent_ID   =  6;
00116 const int WindowToFrontEvent_ID     =  7;
00117 const int WindowToBackEvent_ID      =  8;
00118 const int WindowSplitUpdateEvent_ID =  9;
00119 const int MouseEvent_ID             = 10;
00120 const int MouseButtonEvent_ID       = 11;
00121 const int MouseMotionEvent_ID       = 12;
00122 const int MouseDragEvent_ID         = 13;
00123 const int MouseHoldDragEvent_ID     = 14;
00124 const int KeyEvent_ID               = 15;
00125 const int KeyDownEvent_ID           = 16;
00126 const int KeyUpEvent_ID             = 17;
00127 const int JoyEvent_ID               = 18;
00128 const int JoyButtonEvent_ID         = 19;
00129 const int JoyAxisEvent_ID           = 20;
00130 const int JoyHatEvent_ID            = 21;
00131 const int JoyBallEvent_ID           = 22;
00132 */
00133 
00134 
00135 
00137 
00142 #if 0
00143 void Console::setSize( const int width, const int height ){
00144     Area::setSize( width, height );
00145 
00146     //  Calculate new size
00147     width_chars  = width  / style->monospace_font->getWidth ();
00148     height_chars = height / style->monospace_font->getHeight();
00149 
00150     //  Reposition view to last visible lines
00151     //  FIX could be configurable: first visible lines, last visible lines
00152     //  FIX actually should maintain topleft_y (adjust though - which direction?)
00153 //  topleft_y = max_height_chars - height_chars;
00154     if( topleft_y < 0 ){
00155 //      cout << "ERROR topleft_y < 0" << endl;
00156         topleft_y = 0;
00157     }
00158 }
00159 #endif
00160 
00161 
00163 /*virtual*/ void Console::drawSelf(){
00164     color( text_color );
00165     view->enable( View::BLEND );
00166     view->enable( View::TEXTURE_2D );
00167     view->setBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00168 
00169     //  Draw visible parts of lines
00170 
00171     for( int y=0; y<height_chars && (long)(y+topleft_y)<(long)(buffer_lines.size()); y++ ){
00172         string  line = buffer_lines[y+topleft_y]->substr( topleft_x, width_chars );
00173         Vector2 pos( 0.0f, (float)(font_height * y) );
00174 
00175         drawString( pos, line.c_str(), style->monospace_font );
00176     }
00177 
00178     //  FIX  Draw cursor if wanted
00179     if(
00180         cursor_visible &&
00181         (cx-topleft_x)< width_chars  &&
00182         (cy-topleft_y)< height_chars &&
00183         cx>=topleft_x &&
00184         cy>=topleft_y
00185     ){
00186         Vector2 cpos( (cx-topleft_x)*font_width, (cy-topleft_y)*font_height );
00187         drawString( cpos, "_", style->monospace_font );
00188     }
00189 
00190 /*  char tmp[100];
00191     sprintf( tmp, "Cursor: %d, %d topleft_y: %d height_chars: %d", cx, cy, topleft_y, height_chars );
00192     drawString(  style->monospace_font, tmp, 0, -35 );
00193 */
00194 }
00195 
00196 
00198 /*virtual*/ bool Console::focusActive( const Event &e ){
00199     if( e.state ){
00200         text_color = Color(0.95f,0.95f,1.00f);
00201     }else{                
00202         text_color = Color(0.85f,0.85f,0.95f);
00203     }
00204     return true;
00205 }
00206 
00207 
00209 Console &Console::operator<<( const string &s ){
00210     buffer_lines[cy]->append( s );  //  FIX  Should insert instead
00211     cx = buffer_lines[cy]->size();
00212     return *this;
00213 }
00214 
00215 
00217 void Console::append( int c ){
00218     switch( c ){
00219     case '\n':
00220         this->newLine();
00221         break;
00222     default:
00223 //      buffer_lines[cy]
00224         *buffer_lines[cy] += c;
00225         break;
00226     }
00227 }
00228 
00230 void Console::append( const char *str, int count ){
00231     for( int i=0; i<count; i ++ ){
00232         char c = str[i];
00233         switch( c ){
00234         case '\n':
00235             this->newLine();
00236             break;
00237         default:
00238             *buffer_lines[cy] += c;
00239             break;
00240         }
00241     }
00242 }
00243 
00244 
00246 Console &Console::setLine( const int l, const string &s ){
00247     buffer_lines[l]->assign( s );
00248     return *this;
00249 }
00250 
00251 
00252 
00253 void Console::scroll( int x1, int y1, int x2, int y2, int dx, int dy ){
00254     //  FIX
00255 }
00256 
00257 
00258 void Console::cursorDown(){
00259     if( (long)(cy)<(long)(buffer_lines.size())-1 ){
00260         cy++;
00261     }
00262     //printf( "Cursor: %d, %d topleft_y: %d height_chars: %d\n", cx, cy, topleft_y, height_chars );
00263     if( cy>topleft_y+height_chars-1 ){
00264         topleft_y++;
00265         //printf( "Scrolling down\n" );
00266         //printf( "Cursor: %d, %d topleft_y: %d height_chars: %d\n", cx, cy, topleft_y, height_chars );
00267     }
00268 }
00269 
00270 
00271 void Console::insertLine( const int y ){
00272     buffer_lines.insert( buffer_lines.begin() + y, new string("") );
00273 }
00274 
00275 
00276 void Console::killLine( const int y ){
00277     string *line = buffer_lines[y];
00278     delete line;
00279     buffer_lines.erase( buffer_lines.begin() + y );
00280 }
00281 
00282 
00283 void Console::killChar( const int x, const int y ){
00284     //  assert( x > 0 );
00285     int    right_part = buffer_lines[y]->size() - x;
00286     string new_line   = buffer_lines[y]->substr( 0, x-1 );
00287     if( right_part > 0 ){
00288         new_line.append( buffer_lines[y]->substr( x, right_part ) );
00289     }
00290     buffer_lines[y]->assign( new_line );
00291 }
00292 
00293 
00294 /*void Console::setLogicalUI( LogicalUI *lui ){
00295     this->logical_ui = lui;
00296 }
00297 
00298 void Console::parse( const char *commandline ){
00299     if( logical_ui!=NULL ){
00300         logical_ui->invoke( commandline );
00301     }
00302 }*/
00303 
00304 
00311 /*virtual*/ bool Console::keyDown( const Event &e ){
00312     string old_line;
00313     string new_line;
00314     int    right_part;
00315 
00316     switch( e.key.sym ){
00317 
00318     //  Editing
00319     case SDLK_BACKSPACE:
00320         //  Kill prev char
00321 
00322         if( cx>0 ){
00323             killChar( cx, cy );
00324             cx--;
00325         }else{  //  Also join with previous line
00326             if( cy>0 ){
00327                     
00328                 cx = buffer_lines[cy-1]->size();
00329                 buffer_lines[cy-1]->append( *buffer_lines[cy] );
00330                 killLine( cy );
00331                 cy--;
00332             }
00333         }
00334         break;
00335 
00336     case SDLK_DELETE:
00337         //  Kill next char
00338         if( (long)(cx)<(long)(buffer_lines[cy]->size()) ){
00339             killChar( cx+1, cy );
00340 
00341         }else{  //  Kill newline
00342             if( (long)(cy)<(long)(buffer_lines.size()-1) ){
00343                 buffer_lines[cy]->append( *buffer_lines[cy+1] );
00344                 killLine( cy+1 );
00345                 /*                  if( cy<topleft_y ){
00346                         topleft_y
00347                         }*/
00348             }
00349         }
00350         break;
00351                                 
00352     //  Newline                                 
00353     case SDLK_RETURN:           
00354         insertLine( cy+1 );
00355         cursorDown();
00356         right_part = buffer_lines[cy-1]->size()-cx;
00357 
00358         if( right_part>0 ){
00359             buffer_lines[cy]->append( buffer_lines[cy-1]->substr( cx, right_part ) );
00360         }
00361 
00362         if( cx>0 ){
00363             buffer_lines[cy-1]->assign( buffer_lines[cy-1]->substr( 0, cx ) );
00364 //          parse( buffer_lines[cy-1]->c_str() );
00365         }else{
00366             buffer_lines[cy-1]->assign( string("") );
00367         }
00368 
00369         cx = 0;
00370         break;
00371 
00372     //  Move cursor up / down
00373     case SDLK_UP:
00374         if( cy>0 ){
00375             cy--;
00376             if( topleft_y>cy ){
00377                 topleft_y--;
00378             }
00379             right_part = buffer_lines[cy]->size()-cx;
00380             if( right_part<0 ){
00381                 cx += right_part;
00382             }
00383         }
00384         break;
00385     case SDLK_DOWN:
00386         cursorDown();
00387         right_part = buffer_lines[cy]->size()-cx;
00388         if( right_part<0 ){
00389             cx += right_part;
00390         }
00391         break;
00392 
00393         //  Move cursor right / left
00394     case SDLK_RIGHT:
00395         if( (long)(cx) < (long)(buffer_lines[cy]->size()) ){
00396             cx++;
00397         }
00398         break;
00399 
00400     case SDLK_LEFT:
00401         if( cx>0 ){
00402             cx--;
00403             }
00404         break;
00405 
00406         //  Move cursor to start of / end of line
00407     case SDLK_HOME:
00408         cx = 0;
00409         break;
00410 
00411     case SDLK_END:
00412         cx = buffer_lines[cy]->size();
00413         break;
00414 
00415     case SDLK_INSERT:
00416     case SDLK_PAGEUP:
00417     case SDLK_PAGEDOWN:
00418     case SDLK_PAUSE:   //  ? Passthrough?
00419     case SDLK_ESCAPE:  //  ?
00420     case SDLK_TAB:     //  To next tab pos
00421     case SDLK_CLEAR:   //  ? clear line ?
00422     case SDLK_PRINT:
00423     case SDLK_SYSREQ:
00424     case SDLK_BREAK:
00425     case SDLK_MENU:
00426     case SDLK_POWER:
00427     case SDLK_HELP:
00428         break;
00429 
00430         //  Modifiers
00431     case SDLK_NUMLOCK:
00432     case SDLK_CAPSLOCK:
00433     case SDLK_SCROLLOCK:
00434     case SDLK_RSHIFT:
00435     case SDLK_LSHIFT:
00436     case SDLK_RCTRL:
00437     case SDLK_LCTRL:
00438     case SDLK_RALT:
00439     case SDLK_LALT:
00440     case SDLK_RMETA:
00441     case SDLK_LMETA:
00442     case SDLK_LSUPER:
00443     case SDLK_RSUPER:
00444     case SDLK_MODE:
00445         break;
00446 
00447         //  Function keys
00448     case SDLK_F1:
00449     case SDLK_F2:
00450     case SDLK_F3:
00451     case SDLK_F4:
00452     case SDLK_F5:
00453     case SDLK_F6:
00454     case SDLK_F7:
00455     case SDLK_F8:
00456     case SDLK_F9:
00457     case SDLK_F10:
00458     case SDLK_F11:
00459     case SDLK_F12:
00460     case SDLK_F13:
00461     case SDLK_F14:
00462     case SDLK_F15:
00463         break;
00464 
00465         //  Number keypad
00466     case SDLK_KP0:
00467     case SDLK_KP1:
00468     case SDLK_KP2:
00469     case SDLK_KP3:
00470     case SDLK_KP4:
00471     case SDLK_KP5:
00472     case SDLK_KP6:
00473     case SDLK_KP7:
00474     case SDLK_KP8:
00475     case SDLK_KP9:
00476         break;
00477 
00478         //  Insert character
00479     default:
00480         char buf[25];
00481         unsigned int sym = e.key.unicode;
00482 
00483         buf[1] = 0;
00484         if( (sym & 0xff80) == 0 ) {
00485             buf[0] = sym & 0x7f;
00486         }else{
00487             switch( sym ){
00488             case 167: buf[0] = '§'; break;
00489             case 196: buf[0] = 'Ä'; break;
00490             case 197: buf[0] = 'Å'; break;
00491             case 214: buf[0] = 'Ö'; break;
00492             case 228: buf[0] = 'ä'; break;
00493             case 229: buf[0] = 'å'; break;
00494             case 246: buf[0] = 'ö'; break;
00495             default:
00496                 sprintf( buf, " %d", sym );
00497                 break;
00498             }
00499         }
00500 
00501         //  Insertion
00502         old_line = *buffer_lines[cy];
00503         right_part = old_line.size()-cx;
00504         if( right_part > 0 ){
00505             new_line = old_line.substr( 0, cx );
00506             new_line.append( string(buf) );
00507             new_line.append( old_line.substr( cx, right_part ) );
00508             buffer_lines[cy]->erase();
00509             buffer_lines[cy]->append( new_line );
00510         }else{
00511             buffer_lines[cy]->append( string(buf) );
00512         }
00513         cx += strlen( buf );
00514         break;
00515     }
00516     return true;
00517 };
00518 
00519 
00520 };  //  namespace PhysicalComponents
00521 };  //  namespace Teddy
00522