Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/chat2/src/orxonox/graphics/ChatBox.cc @ 6836

Last change on this file since 6836 was 6836, checked in by rgrieder, 14 years ago
  • Property svn:eol-style set to native
File size: 12.3 KB
Line 
1#include "ChatBox.h"
2
3#include "CEGuiSample.h"
4#include "CEGUI/CEGUI.h"
5#include "CEGUI/CEGUIXMLAttributes.h"
6
7bool ChatBox::initialiseSample()
8{
9  using namespace CEGUI;
10  try
11  {
12    // Retrieve the window manager
13    WindowManager& winMgr = WindowManager::getSingleton();
14
15    // Load the TaharezLook scheme and set up the default mouse cursor and font
16    SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");
17    System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
18    if(!FontManager::getSingleton().isFontPresent("Commonwealth-10"))
19      FontManager::getSingleton().createFont("Commonwealth-10.font");
20
21    // Set the GUI Sheet
22    Window* sheet = winMgr.createWindow("DefaultWindow", "root_wnd");
23    System::getSingleton().setGUISheet(sheet);
24
25    // Load a layout
26    Window* guiLayout = winMgr.loadWindowLayout("ChatBox.layout");
27    sheet->addChildWindow(guiLayout);
28
29    // Obtain the handles of some widgets
30    Window* historySize = winMgr.getWindow("/ChatBox/History");
31    Window* fontName = winMgr.getWindow("/ChatBox/FontName");
32    Spinner* fontSize = static_cast<Spinner*>(winMgr.getWindow("/ChatBox/FontSize"));
33    Window* chatText = winMgr.getWindow("/ChatBox/Text");
34
35    // Disable widgets until a valid font is registered
36    fontName->setEnabled(false);
37    fontSize->setEnabled(false);
38    chatText->setEnabled(false);
39
40    // Retrieve the design-specified values
41    mHistorySize = static_cast<size_t>(PropertyHelper::stringToUint(historySize->getText()));
42    mDefaultFontSize = fontSize->getText();
43    mChatFontName = fontName->getText();
44    setHistorySize(mHistorySize);
45    fontName->setText("");
46
47    // Configure the history size
48    // Pressing <ENTER> changes the maximal number of entries within the history Listbox
49    historySize->subscribeEvent(Editbox::EventTextAccepted,  Event::Subscriber(&ChatBox::Event_HistorySizeChange, this)); 
50
51    // Configure the text Editbox
52    // Pressing <ENTER> puts the text into the history Listbox
53    chatText->subscribeEvent(Editbox::EventTextAccepted,  Event::Subscriber(&ChatBox::Event_ChatTextAdded,  this)); 
54
55    // Configure the font name Combobox
56    // Selecting a name changes the font used in the history Listbox and the text Editbox
57    fontName->subscribeEvent(Combobox::EventTextChanged,  Event::Subscriber(&ChatBox::Event_FontChange,  this)); 
58
59    // Configure the font size Spinner
60    // Selecting a size changes the font size used in the history Listbox and the text Editbox
61    fontSize->subscribeEvent(Spinner::EventValueChanged,  Event::Subscriber(&ChatBox::Event_FontChange,  this)); 
62    fontSize->setTextInputMode(Spinner::Integer);
63    fontSize->setMinimumValue(4.0f);
64    fontSize->setMaximumValue(72.0f);
65    fontSize->setStepSize(1.0f);
66    fontSize->setCurrentValue(PropertyHelper::stringToFloat(mDefaultFontSize));
67
68    // Initialize the list of fonts
69    // The first registered font becomes the active font
70    registerFont("Commonwealth",  "Commonv2c.ttf");
71    registerFont("DejaVuSans",    "DejaVuSans.ttf");
72    registerFont("Iconified",    "Iconiv2.ttf");
73    registerFont("MissingFile",    "MissingFile.ttf");  // What happens if a font is missing?
74    registerFont("Pixmap Font",    "FairChar-30.font"); // And what about a non-Freetype font?
75  }
76  catch(Exception &e)
77  {
78    #if defined( __WIN32__ ) || defined( _WIN32 )
79      MessageBox(NULL, e.getMessage().c_str(), "Error initializing the demo", MB_OK | MB_ICONERROR | MB_TASKMODAL);
80    #else
81      //std::cout << "Error initializing the demo:" << e.getMessage().c_str() << "\n";
82    #endif
83  }
84
85  return true;
86}
87
88void ChatBox::cleanupSample(void)
89{
90}
91
92bool ChatBox::Event_HistorySizeChange(const CEGUI::EventArgs& args)
93{
94  using namespace CEGUI;
95
96  WindowManager& winMgr = WindowManager::getSingleton();
97  CEGUI::Window* historySize = winMgr.getWindow("/ChatBox/History");
98  int size = PropertyHelper::stringToInt( historySize->getText() );
99  setHistorySize(size);
100  return true;
101}
102
103bool ChatBox::Event_ChatTextAdded(const CEGUI::EventArgs& args)
104{
105  using namespace CEGUI;
106
107  WindowManager& winMgr = WindowManager::getSingleton();
108  Editbox* chatText = static_cast<Editbox*> (winMgr.getWindow("/ChatBox/Text"));
109  addChatText(chatText->getText());
110
111  // Clear the text in the Editbox
112  chatText->setText("");
113  return true;
114}
115
116bool ChatBox::Event_FontChange(const CEGUI::EventArgs& args)
117{
118  using namespace CEGUI;
119  WindowManager& winMgr = WindowManager::getSingleton();
120  Window* fontName = winMgr.getWindow("/ChatBox/FontName");
121  String name = fontName->getText();
122
123  Spinner* fontSize = static_cast<Spinner*>(winMgr.getWindow("/ChatBox/FontSize"));
124  String size = PropertyHelper::floatToString(fontSize->getCurrentValue());
125
126  Window* chatText = winMgr.getWindow("/ChatBox/Text");
127  chatText->setText(name + " - " + size);
128
129  changeFont(name, size);
130  return true;
131}
132
133void ChatBox::setHistorySize(const size_t& pSize)
134{
135  using namespace CEGUI;
136
137  if(pSize > 0)
138  {
139    // A better validation would be to enforce a minimal and a maximal size
140    mHistorySize = pSize;
141
142    WindowManager& winMgr = WindowManager::getSingleton();
143    Listbox* chatHistory = static_cast<Listbox*> (winMgr.getWindow("/ChatBox/List"));
144    ListboxItem* chatItem;
145    while(chatHistory->getItemCount() > mHistorySize)
146    {
147      // There are too many items within the history Listbox, purging them one at a time
148      chatItem = chatHistory->getListboxItemFromIndex(0);
149      chatHistory->removeItem(chatItem);
150    }
151  }
152}
153
154void ChatBox::addChatText(const CEGUI::String& pText)
155{
156  using namespace CEGUI;
157
158  WindowManager& winMgr = WindowManager::getSingleton();
159  Listbox* chatHistory = static_cast<Listbox*> (winMgr.getWindow("/ChatBox/List"));
160
161  // If there's text then add it
162  if(pText.size())
163  {
164    // Add the Editbox text to the history Listbox
165    ListboxTextItem* chatItem;
166    if(chatHistory->getItemCount() == mHistorySize)
167    {
168      /* We have reached the capacity of the Listbox so re-use the first Listbox item.
169         This code is a little crafty.  By default the ListboxTextItem is created with
170         the auto-delete flag set to true, which results in its automatic deletion when
171         removed from the Listbox.  So we change that flag to false, extract the item
172         from the Listbox, change its text, put the auto-delete flag back to true, and
173         finally put the item back into the Listbox. */
174      chatItem = static_cast<ListboxTextItem*>(chatHistory->getListboxItemFromIndex(0));
175      chatItem->setAutoDeleted(false);
176      chatHistory->removeItem(chatItem);
177      chatItem->setAutoDeleted(true);
178      chatItem->setText(pText);
179    }
180    else
181    {
182      // Create a new listbox item
183      chatItem = new ListboxTextItem(pText);
184    }
185    chatHistory->addItem(chatItem);
186    chatHistory->ensureItemIsVisible(chatHistory->getItemCount());
187  }
188}
189
190void ChatBox::registerFont(const CEGUI::String& pLogicalName, const CEGUI::String& pFileName)
191{
192  using namespace CEGUI;
193
194  // Ensure that font names are registered only once
195  if(mFontList.find(pLogicalName) == mFontList.end())
196  {
197    // Test the font so that only valid fonts are available
198    String testFont = mChatFontName;
199    if(mFontList.size() != 0)
200    {
201      // If the list is empty then attempt to create the font using the "real" font name
202      // Otherwise use a "test" font name so as not to corrupt the "real" one
203      testFont += "__test_font__";
204    }
205    Font* font = makeFont(testFont, pFileName, mDefaultFontSize);
206    if(mFontList.size() != 0 
207      && FontManager::getSingleton().isFontPresent(testFont))
208    {
209      // Since this was only a test font we destroy it
210      FontManager::getSingleton().destroyFont(testFont);
211    }
212    if(!font)
213    {
214      // This font is invalid
215      if(FontManager::getSingleton().isFontPresent(testFont))
216        return;
217      else
218      return;
219    }
220
221    WindowManager& winMgr = WindowManager::getSingleton();
222    Combobox* fontName = static_cast<Combobox*>(winMgr.getWindow("/ChatBox/FontName"));
223    mFontList[pLogicalName] = pFileName;
224    ListboxTextItem* fontNameItem = new ListboxTextItem(pLogicalName);
225    fontNameItem->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
226    fontName->addItem(fontNameItem);
227    if(fontName->getItemCount() == 1)
228    {
229      // Enable widgets now that at least one valid font has been found
230      Spinner* fontSize = static_cast<Spinner*>(winMgr.getWindow("/ChatBox/FontSize"));
231      Window* chatText = winMgr.getWindow("/ChatBox/Text");
232      fontName->setEnabled(true);
233      fontSize->setEnabled(true);
234      chatText->setEnabled(true);
235
236      // The first registered font becomes the active font
237      fontName->setText(pLogicalName); // This triggers a call to changeFont
238      fontName->setItemSelectState(fontNameItem, true);
239    }
240  }
241}
242
243CEGUI::Font* ChatBox::makeFont(const CEGUI::String& pFontName, const CEGUI::String& pFileName, const CEGUI::String& pSize)
244{
245  using namespace CEGUI;
246
247  Font* font;
248  try
249  {
250    if(FontManager::getSingleton().isFontPresent(pFontName))
251    {
252      // The chat font is reused rather than deleted and recreated
253      // every time an attribute changes.  For this reason it is
254      // important to use a unique logical name for the font.
255      font = FontManager::getSingleton().getFont(pFontName);
256      font->setProperty("FileName", pFileName);
257      font->setProperty("PointSize", pSize);
258    }
259    else
260    {
261      // This is the first time we make the chat font so we need to create it
262      XMLAttributes xmlAttributes;
263
264      // CEGUIFont.cpp
265      xmlAttributes.add("Name", pFontName);
266      xmlAttributes.add("Filename", pFileName);
267      xmlAttributes.add("ResourceGroup", "");
268      xmlAttributes.add("AutoScaled", "true");
269      xmlAttributes.add("NativeHorzRes", "800");
270      xmlAttributes.add("NativeVertRes", "600");
271
272      // CEGUIXMLAttributes.cpp
273      xmlAttributes.add("Size", pSize);
274      xmlAttributes.add("AntiAlias", "true");
275
276      font = FontManager::getSingleton().createFont("FreeType", xmlAttributes);
277    }
278    font->load();
279  }
280  catch(Exception& e)
281  {
282    // Display the error message in the chat window
283    //addChatText(e.getMessage());
284    font = 0;
285  }
286
287  return font;
288}
289
290void ChatBox::changeFont(const CEGUI::String& pFontLogicalName, const CEGUI::String& pFontSize)
291{
292  using namespace CEGUI;
293  WindowManager& winMgr = WindowManager::getSingleton();
294
295  if(!FontManager::getSingleton().isFontPresent(mChatFontName))
296  {
297    addChatText("You must call registerFont() at least once with a valid font");
298    return;
299  }
300
301  FontList::iterator itFontList = mFontList.find(pFontLogicalName);
302  if(itFontList == mFontList.end())
303  {
304    addChatText(pFontLogicalName + " has not been registered");
305    return;
306  }
307
308  // Measure the height of the selected font
309  Font* currentFont = makeFont(mChatFontName, (*itFontList).second, pFontSize);
310  float fontHeight = currentFont->getFontHeight();
311
312  /* Alter the area of the Editbox.  The original value is {{0.01,0},{1,-30},{0.99,0},{1,-5}}
313     The value we are altering is the "-30" within the second couplet, defining the position of
314     the upper y coordinate of the Editbox.  We base the new value on the position of the lower
315     y coordinate, which is "-5", and the height of the font.  To this we add some space "10" to
316     account for the Editbox's border. */
317  Editbox* editBox = static_cast<Editbox*> (winMgr.getWindow("/ChatBox/Text"));
318  URect chatTextArea = editBox->getArea();
319  chatTextArea.d_min.d_y.d_offset = chatTextArea.d_max.d_y.d_offset
320                  - fontHeight
321                  - 10;
322  editBox->setArea(chatTextArea);
323  editBox->setFont(currentFont);
324
325  /* Alther the area of the Listbox.  Here we only need the lower y coordinate.  Since this
326     value is the same as the upper y coordinate of the Editbox we do not need to calculate
327     it.  We also change the font of the Listbox and call upon handleUpdatedItemData() to
328     update the current Listbox items.  Finally we ensure that the last entry is still
329     visible. */
330  Listbox* listBox = static_cast<Listbox*> (winMgr.getWindow("/ChatBox/List"));
331  URect listTextArea = listBox->getArea();
332  listTextArea.d_max.d_y.d_offset = chatTextArea.d_min.d_y.d_offset;
333  listBox->setArea(listTextArea);
334  listBox->setFont(currentFont);
335  listBox->handleUpdatedItemData();
336  size_t itemCount = listBox->getItemCount();
337  if(itemCount)
338  {
339    ListboxItem* currentItem = listBox->getListboxItemFromIndex(itemCount - 1);
340    listBox->ensureItemIsVisible(currentItem);
341  }
342}
343
Note: See TracBrowser for help on using the repository browser.