comparison engine/core/gui/console/console.cpp @ 697:ecaa4d98f05f tip

Abstracted the GUI code and refactored the GUIChan-specific code into its own module. * Most of the GUIChan code has been refactored into its own gui/guichan module. However, references to the GuiFont class still persist in the Engine and GuiManager code and these will need further refactoring. * GuiManager is now an abstract base class which specific implementations (e.g. GUIChan) should subclass. * The GUIChan GUI code is now a concrete implementation of GuiManager, most of which is in the new GuiChanGuiManager class. * The GUI code in the Console class has been refactored out of the Console and into the GUIChan module as its own GuiChanConsoleWidget class. The rest of the Console class related to executing commands was left largely unchanged. * Existing client code may need to downcast the GuiManager pointer received from FIFE::Engine::getGuiManager() to GuiChanGuiManager, since not all functionality is represented in the GuiManager abstract base class. Python client code can use the new GuiChanGuiManager.castTo static method for this purpose.
author M. George Hansen <technopolitica@gmail.com>
date Sat, 18 Jun 2011 00:28:40 -1000
parents e201abd8c807
children
comparison
equal deleted inserted replaced
696:e201abd8c807 697:ecaa4d98f05f
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
50 Console::Console()
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
90 void Console::reLayout() {
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
148 Console::~Console() {
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
162 void Console::updateCaption() {
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
169 void Console::updateAnimation() {
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
224 void Console::toggleShowHide() {
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
296 void Console::removeConsoleExecuter() {
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: */