Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 1, 2009, 3:57:56 PM (15 years ago)
Author:
rgrieder
Message:

IOConsole: Resolved flickering problem and moved status line below input line

Location:
code/branches/console/src/libraries/core
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/console/src/libraries/core/IOConsole.cc

    r6012 r6013  
    6868        , originalTerminalSettings_(new termios())
    6969        , bStatusPrinted_(false)
    70         , promptString_("orxonox> ")
     70        , promptString_("orxonox # ")
    7171    {
    7272        this->setTerminalMode();
     
    7474
    7575        // Manually set the widths of the individual status lines
    76         this->statusLineWidths_.push_back(6);
    77         this->statusLineMaxWidth_ = 6;
     76        this->statusLineWidths_.push_back(20);
     77        this->statusLineMaxWidth_ = 20;
    7878    }
    7979
    8080    IOConsole::~IOConsole()
    8181    {
    82         std::cout << "\033[0G\033[K";
     82        // Goto last line and erase it
     83        if (this->bStatusPrinted_)
     84            std::cout << "\033[" << this->statusLineWidths_.size() << 'E';
     85        std::cout << "\033[1G\033[K";
    8386        std::cout.flush();
    8487        resetTerminalMode();
     
    188191            this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, '\033', 0));
    189192
    190         // Clear screen below the last output line by first moving the cursor to the beginning of the first status line
    191         std::cout << "\033[" << (this->bStatusPrinted_ ? this->statusLineWidths_.size() : 0) << "F\033[J";
     193        // Determine terminal width and height
     194        this->getTerminalSize();
     195
     196        if (!this->bStatusPrinted_ && this->willPrintStatusLines())
     197        {
     198            // Print new lines to make way for status lines
     199            std::cout << std::string(this->statusLineWidths_.size(), '\n');
     200            // Move cursor up again
     201            std::cout << "\033[" << this->statusLineWidths_.size() << 'A';
     202            this->bStatusPrinted_ = true;
     203        }
     204        // Move cursor horizontally and erase status and input lines
     205        std::cout << "\033[1G\033[J";
     206        this->printInputLine();
    192207        this->printStatusLines();
    193         this->printInputLine();
    194208        std::cout.flush();
    195209    }
     
    235249        std::cout << "\033[1G\033[K";
    236250        // Indicate a command prompt
    237         std::cout << promptString_;
     251        std::cout << this->promptString_;
    238252        // Save cursor position
    239253        std::cout << "\033[s";
     
    248262    void IOConsole::printStatusLines()
    249263    {
    250         if (!this->statusLineWidths_.empty())
    251         {
    252             // Check terminal size
    253             int x, y;
    254             if (this->getTerminalSize(&x, &y) && (x < (int)this->statusLineMaxWidth_ || y < (int)(this->minOutputLines_ + this->statusLineWidths_.size())))
    255             {
    256                 this->bStatusPrinted_ = false;
    257                 return;
    258             }
    259             std::cout << "Status" << std::endl;
     264        if (this->willPrintStatusLines())
     265        {
     266            // Save cursor position
     267            std::cout << "\033[s";
     268            // Move cursor down (don't create a new line here because the buffer might flush then!)
     269            std::cout << "\033[1E";
     270            std::cout << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
     271            std::cout <<               std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
     272            // Restore cursor position
     273            std::cout << "\033[u";
    260274            this->bStatusPrinted_ = true;
    261275        }
    262     }
    263 
    264     int IOConsole::getTerminalSize(int* x, int* y)
     276        else
     277            this->bStatusPrinted_ = false;
     278    }
     279
     280    inline bool IOConsole::willPrintStatusLines()
     281    {
     282        return !this->statusLineWidths_.empty()
     283             && this->terminalWidth_  >= this->statusLineMaxWidth_
     284             && this->terminalHeight_ >= (this->minOutputLines_ + this->statusLineWidths_.size());
     285    }
     286
     287    void IOConsole::getTerminalSize()
    265288    {
    266289#ifdef TIOCGSIZE
    267290        struct ttysize win;
    268 #elif defined(TIOCGWINSZ)
     291        if (!ioctl(STDIN_FILENO, TIOCGSIZE, &win))
     292        {
     293            this->terminalWidth_  = win.ts_cols;
     294            this->terminalHeight_ = win.ts_lines;
     295            return;
     296        }
     297#elif defined TIOCGWINSZ
    269298        struct winsize win;
     299        if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &win))
     300        {
     301            this->terminalWidth_  = win.ws_col;
     302            this->terminalHeight_ = win.ws_row;
     303            return;
     304        }
     305#else
     306        const char* s = getenv("COLUMNS");
     307        this->terminalWidth_  = s ? strtol(s, NULL, 10) : 80;
     308        s = getenv("LINES");
     309        this->terminalHeight_ = s ? strtol(s, NULL, 10) : 24;
     310        return;
    270311#endif
    271 
    272 #ifdef TIOCGSIZE
    273         if (ioctl(STDIN_FILENO, TIOCGSIZE, &win))
    274             return 0;
    275         *y = win.ts_lines;
    276         *x = win.ts_cols;
    277 #elif defined TIOCGWINSZ
    278         if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win))
    279             return 0;
    280         *y = win.ws_row;
    281         *x = win.ws_col;
    282 #else
    283         {
    284             const char* s = getenv("LINES");
    285             if (s)
    286                 *y = strtol(s, NULL, 10);
    287             else
    288                 *y = 25;
    289             s = getenv("COLUMNS");
    290             if (s)
    291                 *x = strtol(s, NULL, 10);
    292             else
    293                 *x = 80;
    294         }
    295 #endif
    296         return 1;
     312        this->terminalWidth_  = 80;
     313        this->terminalHeight_ = 24;
    297314    }
    298315
     
    357374    {
    358375        // Save cursor position and move it to the beginning of the first output line
    359         std::cout << "\033[s\033[" << (1 + this->statusLineWidths_.size()) << "F";
     376        std::cout << "\033[s\033[1F";
    360377        // Erase the line
    361378        std::cout << "\033[K";
     
    373390    void IOConsole::lineAdded()
    374391    {
    375         // Move cursor to the beginning of the first status line and erase screen from there
    376         std::cout << "\033[" << this->statusLineWidths_.size() << "F\033[J";
     392        // Move cursor to the bottom line
     393        if (this->bStatusPrinted_)
     394            std::cout << "\033[" << this->statusLineWidths_.size() << 'E';
     395        // Create the new line on the screen
     396        std::cout << '\n';
     397        // Move cursor to the beginning of the new (last) output line
     398        std::cout << "\033[" << (1 + this->statusLineWidths_.size()) << 'F';
     399        // Erase screen from here
     400        std::cout << "\033[J";
    377401        // Print the new output line
    378402        this->printLogText(*(this->shell_->getNewestLineIterator()));
    379         std::cout << std::endl;
     403        // Move cursor down
     404        std::cout << "\033[1E";
     405        // Print status and input lines
     406        this->printInputLine();
    380407        this->printStatusLines();
     408        std::cout.flush();
     409    }
     410
     411    /**
     412    @brief
     413        Called if the text in the input-line has changed.
     414    */
     415    void IOConsole::inputChanged()
     416    {
    381417        this->printInputLine();
    382418        std::cout.flush();
     
    385421    /**
    386422    @brief
    387         Called if the text in the input-line has changed.
    388     */
    389     void IOConsole::inputChanged()
     423        Called if the position of the cursor in the input-line has changed.
     424    */
     425    void IOConsole::cursorChanged()
    390426    {
    391427        this->printInputLine();
     
    395431    /**
    396432    @brief
    397         Called if the position of the cursor in the input-line has changed.
    398     */
    399     void IOConsole::cursorChanged()
    400     {
    401         this->printInputLine();
    402         std::cout.flush();
    403     }
    404 
    405     /**
    406     @brief
    407433        Called if a command is about to be executed
    408434    */
  • code/branches/console/src/libraries/core/IOConsole.h

    r6010 r6013  
    5656        void setTerminalMode();
    5757        void resetTerminalMode();
    58         int getTerminalSize(int* x, int* y);
     58        void getTerminalSize();
     59        bool willPrintStatusLines();
    5960
    6061        void printLogText(const std::string& line);
     
    7071        void executed();
    7172        void exit();
     73
    7274        Shell*                  shell_;
    7375        InputBuffer*            buffer_;
    7476        termios*                originalTerminalSettings_;
     77        unsigned int            terminalWidth_;
     78        unsigned int            terminalHeight_;
    7579        bool                    bPrintStatusLine_;
    7680        bool                    bStatusPrinted_;
Note: See TracChangeset for help on using the changeset viewer.