FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
console.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2008 by the FIFE team *
3  * http://www.fifengine.de *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <cassert>
24 
25 // 3rd party library includes
26 #include <boost/bind.hpp>
27 #include <boost/lexical_cast.hpp>
28 #include <boost/regex.hpp>
29 #include <boost/tokenizer.hpp>
30 
31 // FIFE includes
32 // These includes are split up in two parts, separated by one empty line
33 // First block: files included from the FIFE root src directory
34 // Second block: files included from the same folder
35 #include "video/renderbackend.h"
36 #include "util/time/timemanager.h"
37 #include "util/log/logger.h"
38 #include "util/base/exception.h"
39 #include "gui/guimanager.h"
40 #include "gui/base/gui_font.h"
41 #include "gui/widgets/utf8textbox.h"
42 
43 #include "commandline.h"
44 #include "console.h"
45 
46 namespace FIFE {
47  const unsigned Console::m_maxOutputRows = 50;
48  static Logger _log(LM_CONSOLE);
49 
51  : gcn::Container(),
52  m_consoleexec(0),
53  m_input(new CommandLine()),
54  m_output(new gcn::UTF8TextBox()),
55  m_outputscrollarea(new gcn::ScrollArea(m_output)),
56  m_status(new gcn::Label()),
57  m_toolsbutton(new gcn::Button("Tools"))
58  {
59  reLayout();
60 
61  add(m_outputscrollarea);
62  add(m_input);
63  add(m_status);
64  add(m_toolsbutton);
65 
66  setOpaque(true);
67 
68  m_input->setCallback( std::bind1st( std::mem_fun(&Console::execute), this) );
69  m_prompt = "-- ";
70 
71  m_isAttached = false;
72 
73  m_fpsTimer.setInterval(500);
74  m_fpsTimer.setCallback( boost::bind(&Console::updateCaption, this) );
75 
76  m_hiding = true;
77 
78  m_animationTimer.setInterval(20);
79  m_animationTimer.setCallback( boost::bind(&Console::updateAnimation, this) );
80 
81  m_toolsbutton->addActionListener(this);
82  m_toolsbutton->setFocusable(false);
83  m_input->addFocusListener(this);
84 
85  GuiFont* font = GUIManager::instance()->createFont();
86  font->setColor(255,255,255);
87  setIOFont(font);
88  }
89 
91  Image* screen = RenderBackend::instance()->getScreenImage();
92  assert(screen);
93 
94  int w, h, b, input_h, bbar_h, button_w;
95  w = screen->getWidth() * 4/5;
96  h = screen->getHeight() * 4/5;
97  b = 0;
98  input_h = getFont()->getHeight();
99  bbar_h = input_h;
100  button_w = 80;
101 
102  gcn::Color black(0x00,0,0,0xff);
103  gcn::Color white(0xff,0xff,0xff,0xff);
104  gcn::Color dark(50,60,50,0xff);
105 
106  setSize(w, h);
107  setPosition((screen->getWidth() - w) / 2,-h);
108  setFrameSize(0);
109 
110  setForegroundColor(white);
111  setBackgroundColor(black);
112  setBaseColor(dark);
113 
114  setSize(w, h);
115 
116  m_outputscrollarea->setSize(w - 2*b, h - input_h - 3*b - bbar_h);
117  m_outputscrollarea->setPosition(b,0);
118 
119  m_input->setPosition(b, h - input_h - b - bbar_h);
120  m_input->setSize(w - 2*b, input_h);
121 
122  m_status->setPosition(b, h - b - bbar_h);
123  m_status->setSize(w - 2*b, bbar_h);
124 
125  m_toolsbutton->setPosition(w - button_w, h - b - bbar_h);
126  m_toolsbutton->setSize(button_w, bbar_h);
127 
128  m_output->setBackgroundColor(black);
129  m_output->setFocusable(false);
130 
131  m_outputscrollarea->setBackgroundColor(black);
132  m_outputscrollarea->setBaseColor(dark);
133 
134  m_input->setForegroundColor(white);
135  m_input->setBackgroundColor(black);
136 
137  m_status->setForegroundColor(white);
138  m_status->setBackgroundColor(black);
139 
140  m_toolsbutton->setForegroundColor(white);
141  m_toolsbutton->setBackgroundColor(black);
142  m_toolsbutton->setBaseColor(dark);
143 
144  m_hiddenPos = -h;
145  m_animationDelta = h/6;
146  }
147 
149  doHide();
150 
151  remove(m_input);
152  remove(m_outputscrollarea);
153  remove(m_status);
154 
155  delete m_output;
156  delete m_input;
157  delete m_outputscrollarea;
158  delete m_status;
159  delete m_toolsbutton;
160  }
161 
163  std::string caption = "FIFE Console - FPS: ";
164  float fps = 1e3/double(TimeManager::instance()->getAverageFrameTime());
165  caption += boost::lexical_cast<std::string>(fps);
166  m_status->setCaption( caption );
167  }
168 
170  if (m_hiding){
171  setPosition(getX(), getY() - m_animationDelta);
172  if (getY() <= m_hiddenPos){
173  doHide();
174  m_animationTimer.stop();
175  }
176  }else{
177  setPosition(getX(), getY() + m_animationDelta);
178  if (getY() >= 0){
179  setPosition(getX(), 0);
180  m_animationTimer.stop();
181  }
182  }
183  }
184 
185  void Console::clear() {
186  m_output->setText("");
187  }
188 
189  void Console::doShow() {
190  if (m_isAttached)
191  return;
192  m_isAttached = true;
193  GUIManager::instance()->add(this);
194  GUIManager::instance()->getTopContainer()->moveToTop(this);
195  // Assure the input field is focused when shown.
196  m_input->requestFocus();
197 
198  m_fpsTimer.start();
199  }
200 
201  void Console::doHide() {
202  if (!m_isAttached)
203  return;
204  m_isAttached = false;
205  GUIManager::instance()->remove(this);
206  m_fpsTimer.stop();
207  }
208 
209  void Console::show() {
210  if(m_hiding) {
211  m_hiding = false;
212  doShow();
213  m_animationTimer.start();
214  }
215  }
216 
217  void Console::hide() {
218  if(!m_hiding) {
219  m_hiding = true;
220  m_animationTimer.start();
221  }
222  }
223 
225  m_hiding = !m_hiding;
226  if(!m_hiding)
227  doShow();
228  m_animationTimer.start();
229  }
230 
231  void Console::execute(std::string cmd) {
232  FL_DBG(_log, LMsg("in execute with command ") << cmd);
233  if (cmd.empty())
234  return;
235 
236  // copy input to output
237  println(m_prompt + cmd);
238 
239  // run the command
240  try {
241  if (m_consoleexec) {
242  std::string resp = m_consoleexec->onConsoleCommand(cmd);
243  println(resp);
244  } else {
245  FL_WARN(_log, LMsg("ConsoleExecuter not bind, but command received: ") << cmd.c_str());
246  }
247  }
248  catch (const FIFE::Exception & e) {
249  FL_WARN(_log, LMsg("Console caught exception: ") << e.what());
250  println(e.what());
251  }
252  }
253 
254  void Console::println(const std::string & s) {
255  assert(m_output);
256 
257  // Add the text in rows
258  boost::char_separator<char> separator("\n");
259  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
260  tokenizer tokens(s,separator);
261  for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i) {
262  m_output->addRow(*i);
263  }
264 
265  // Assure the maximum number of rows
266  if( m_output->getNumberOfRows() > m_maxOutputRows ) {
267  unsigned rows = m_output->getNumberOfRows();
268  int delta_rows = rows - m_maxOutputRows;
269  std::vector<std::string> rows_text;
270  for(size_t i=delta_rows; i != rows; ++i) {
271  rows_text.push_back(m_output->getTextRow(i));
272  }
273  m_output->setText("");
274  for(size_t i=0; i != rows_text.size(); ++i) {
275  m_output->addRow(rows_text[i]);
276  }
277  }
278 
279  // Assure the new text is visible
280  gcn::Rectangle rect(0,m_output->getHeight(),0,0);
281  m_outputscrollarea->showWidgetPart(m_output,rect);
282  }
283 
284  void Console::action(const gcn::ActionEvent & event) {
285  if (m_consoleexec) {
286  m_consoleexec->onToolsClick();
287  } else {
288  FL_WARN(_log, "ConsoleExecuter not bind, but tools button clicked");
289  }
290  }
291 
292  void Console::setConsoleExecuter(ConsoleExecuter* const consoleexec) {
293  m_consoleexec = consoleexec;
294  }
295 
297  m_consoleexec = NULL;
298  }
299 
300  void Console::setIOFont(GuiFont* font) {
301  m_input->setFont(font);
302  m_output->setFont(font);
303  }
304 
305  void Console::focusLost(const gcn::Event& ) {
306  hide();
307  }
308 }
309 /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */