Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/shell/shell_input.cc @ 9788

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

renamed newclassid to classid and newobjectlist to objectlist

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