Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell_input.cc @ 7451

Last change on this file since 7451 was 7451, checked in by bensch, 18 years ago

orxonox/trunk: Test the MultiLineText in this revision

File size: 8.5 KB
RevLine 
[4744]1/*
[1853]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
[1855]10
11   ### File Specific:
[5254]12   main-programmer: Benjamin Grauer
[1855]13   co-programmer: ...
[1853]14*/
15
[7374]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SHELL
[1853]17
[5178]18#include "shell_input.h"
[1853]19
[5181]20
21
22#include "shell_command.h"
[5639]23#include "shell_command_class.h"
[5181]24#include "shell_completion.h"
[5180]25#include "event_handler.h"
[5179]26
27#include "debug.h"
28#include "compiler.h"
29#include "stdlibincl.h"
[5180]30#include "key_names.h"
[5179]31
[5180]32
[1853]33
[5237]34
[7374]35
36namespace OrxShell
[3365]37{
[7374]38  SHELL_COMMAND(help, ShellInput, help)
39  ->describe("retrieve some help about the input mode")
40  ->setAlias("help");
[4320]41
[5180]42
[7374]43  /**
44   * @brief constructor
45   * this also generates a ShellCompletion automatically.
46  */
47  ShellInput::ShellInput ()
[7451]48      : MultiLineText ("")
[5309]49  {
[7451]50    this->setLineWidth(100);
51
[7374]52    this->pressedKey = SDLK_FIRST;
53    this->setClassID(CL_SHELL_INPUT, "ShellInput");
[7341]54
[7374]55    this->inputLine = "";
56    this->historyIT = this->history.begin();
57    this->setHistoryLength(50);
58    this->historyScrolling = false;
59    this->delayed = 0;
60    this->setRepeatDelay(.3, .05);
[1853]61
[7374]62    // subscribe all keyboard commands to ES_SEHLL
63    EventHandler* evh = EventHandler::getInstance();
64    for (int i = 1; i < SDLK_LAST; i++)
65    {
66      if (!evh->isSubscribed(ES_SHELL, i))
67        evh->subscribe(this, ES_SHELL, i);
68    }
69    // unsubscribe unused TODO improve.
70    evh->unsubscribe(ES_SHELL, SDLK_BACKQUOTE);
71    evh->unsubscribe(ES_SHELL, SDLK_F12);
72    evh->unsubscribe(ES_SHELL, SDLK_PAGEUP);
73    evh->unsubscribe(ES_SHELL, SDLK_PAGEDOWN);
[5179]74
[7374]75  }
[5179]76
[7374]77  /**
78   * @brief standard deconstructor
79   */
80  ShellInput::~ShellInput ()
81{}
[5179]82
[7374]83  /**
84   * @brief sets the Repeate-delay and rate
85   * @param repeatDelay the Delay it takes, to repeate a key
86   * @param repeatRate the rate to repeate a pressed key
87   */
88  void ShellInput::setRepeatDelay(float repeatDelay, float repeatRate)
[5244]89  {
[7374]90    this->repeatDelay = repeatDelay;
91    this->repeatRate = repeatRate;
[5244]92  }
93
[7374]94  /**
95   * @brief deletes the InputLine
96   */
97  void ShellInput::flush()
[5244]98  {
[7374]99    this->inputLine.clear();
100    this->setText(this->inputLine);
[5244]101  }
102
[7374]103  /**
104   * @brief sets the entire text of the InputLine to text
105   * @param text the new Text to set as InputLine
106   */
107  void ShellInput::setInputText(const std::string& text)
[5244]108  {
[7374]109    this->inputLine = text;
110    this->setText(this->inputLine);
[5244]111  }
112
[5179]113
[7374]114  /**
115   * @brief adds one character to the inputLine
116   * @param character the character to add to the inputLine
117   */
118  void ShellInput::addCharacter(char character)
119  {
120    if (this->historyScrolling)
121    {
122      this->history.pop_back();
123      this->historyScrolling = false;
124    }
[5179]125
[7374]126    this->inputLine += character;
127    this->setText(this->inputLine);
128  }
[5369]129
[7374]130  /**
131   * @brief adds multiple Characters to thr inputLine
132   * @param characters a \\0 terminated char-array to add to the InputLine
133   */
134  void ShellInput::addCharacters(const std::string& characters)
135  {
136    if (this->historyScrolling)
137    {
138      this->history.pop_back();
139      this->historyScrolling = false;
140    }
[5179]141
[7374]142    this->inputLine += characters;
143    this->setText(this->inputLine);
[5243]144  }
145
[7374]146  /**
147   * @brief removes characterCount characters from the InputLine
148   * @param characterCount the count of Characters to remove from the input Line
149   */
150  void ShellInput::removeCharacters(unsigned int characterCount)
[5243]151  {
[7374]152    if (this->historyScrolling)
153    {
154      this->history.pop_back();
155      this->historyScrolling = false;
156    }
157    if (this->inputLine.size() < characterCount)
158      characterCount = this->inputLine.size();
159
160    this->inputLine.erase(this->inputLine.size() - characterCount, this->inputLine.size());
161    this->setText(this->inputLine);
[5243]162  }
163
[7374]164  /**
165   * @brief executes the command stored in the inputLine
166   * @return true if the command was commited successfully, false otherwise
167   */
168  bool ShellInput::executeCommand()
169  {
170    ShellBuffer::addBufferLineStatic("Execute Command: %s\n", this->inputLine.c_str());
[5179]171
[7374]172    if (this->inputLine.empty())
173      return false;
[5179]174
[7374]175    ShellCommand::execute(this->inputLine);
[5180]176
[7374]177    // removing the eventually added Entry (from scrolling) to the List
178    if (this->historyScrolling)
179    {
180      this->history.pop_back();
181      this->historyScrolling = false;
182    }
183
184    // adding the new Command to the History
[7221]185    this->history.push_back(this->inputLine);
[7374]186    if (this->history.size() > this->historyLength)
187    {
188      this->history.pop_front();
189    }
190
191    this->flush();
192
193    return true;
[5243]194  }
195
[7374]196
197  /**
198   * @brief moves one entry up in the history.
199   */
200  void ShellInput::historyMoveUp()
[5243]201  {
[7374]202    if (!this->historyScrolling)
[5785]203    {
[7374]204      this->history.push_back(this->inputLine);
205      this->historyScrolling = true;
206      this->historyIT = --this->history.end();
[5785]207    }
[7374]208
209    if(this->historyIT != this->history.begin())
210    {
211      std::string prevElem = *(--this->historyIT);
212      /*if (prevElem == NULL) /// TODO STD
213        return;
214      else */
215      {
216        this->flush();
217        this->setInputText(prevElem);
218      }
219    }
[5243]220  }
221
[7374]222  /**
223   * @brief moves one entry down in the history
224   */
225  void ShellInput::historyMoveDown()
[5243]226  {
[7374]227    if (!this->historyScrolling)
[5785]228      return;
[7374]229    if (!this->history.empty() && this->historyIT != --this->history.end())
[5785]230    {
[7374]231      std::string nextElem = *(++this->historyIT);
232      /*    if (nextElem == NULL) /// TODO FIX STD
233        return;
234      else */
235      {
236        this->flush();
237        this->setInputText(nextElem);
238      }
[5785]239    }
[5243]240  }
241
242
[7374]243  /**
244   * @brief prints out some nice help about the Shell
245   */
246  void ShellInput::help(const std::string& className, const std::string& functionName)
247  {
248    printf("%s::%s\n", className.c_str(), functionName.c_str());
[5207]249
[7374]250    if (className.empty())
251    {
252      PRINT(0)("Help for the most important Shell-commands\n");
253      PRINT(0)("F1 - HELP; F2 - DEBUG; '`' - open/close shell\n");
254      PRINT(0)("input order:\n");
255      PRINT(0)("ClassName [objectName] function [parameter1, [parameter2 ...]]  or\n");
256      PRINT(0)("Alias [parameter]\n");
257      PRINT(0)("- Also try 'help className'");
258    }
259    else if (!className.empty() && functionName.empty())
260    {
261      ShellCommandClass::help(className);
262      //PRINTF(1)("%s::%s\n", className, functionName);
263    }
[5204]264  }
[5180]265
[7374]266  /**
267   * @brief ticks the ShellInput
268   * @param dt the time passed since the last update
269   */
270  void ShellInput::tick(float dt)
[5180]271  {
[7374]272    if (this->delayed > 0.0)
273      this->delayed -= dt;
274    else if (this->pressedKey != SDLK_FIRST )
[5786]275    {
[7374]276      this->delayed = this->repeatRate;
277      switch (this->pressedKey )
[5786]278      {
[7374]279        case SDLK_BACKSPACE:
280          this->removeCharacters(1);
281          break;
282        case SDLK_UP:
283          this->historyMoveUp();
284          break;
285        case SDLK_DOWN:
286          this->historyMoveDown();
287          break;
288        default:
289          {
290            if (likely(pressedKey < 127))
291              this->addCharacter(this->pressedKey);
292          }
[5786]293      }
294    }
[5180]295  }
296
[7374]297  /**
298   * @brief listens for some event
299   * @param event the Event happened
300   */
301  void ShellInput::process(const Event &event)
[5180]302  {
[7374]303    if (event.bPressed)
[5786]304    {
[7374]305      PRINTF(5)("Shell received command %s\n", SDLKToKeyname(event.type));
306      if (event.type == SDLK_F1)
307        this->help();
308      else if (event.type == SDLK_F2)
309      {
310        ;//this->debug();
311      }
312      else if (event.type == SDLK_UP)
313      {
314        this->historyMoveUp();
315        this->pressedKey = event.type;
316      }
317      else if (event.type == SDLK_DOWN)
318      {
319        this->historyMoveDown();
320        this->pressedKey = event.type;
321      }
322      else if (event.type == SDLK_TAB)
323      {
324        this->completion.autoComplete(this->inputLine);
325        this->setText(this->inputLine);
326      }
327      else if (event.type == SDLK_BACKSPACE)
328      {
329        this->delayed = this->repeatDelay;
330        this->pressedKey = SDLK_BACKSPACE;
331        this->removeCharacters(1);
332      }
333      else if (event.type == SDLK_RETURN)
334      {
335        this->executeCommand();
336        this->pressedKey = event.type;
337      }
338      // any other keyboard key
339      else if (likely(event.type < 127))
340      {
341        this->addCharacter(event.x);
342        this->pressedKey = event.x;
343      }
[5180]344      this->delayed = this->repeatDelay;
345    }
[7374]346    else // if(!event.bPressed)
[5786]347    {
[7374]348      if (this->pressedKey == event.x || this->pressedKey == event.type)
349      {
350        this->pressedKey = 0;
351        this->delayed = 0.0;
352      }
[5786]353    }
[5180]354  }
[7374]355
[5180]356}
Note: See TracBrowser for help on using the repository browser.