Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/chat/src/orxonox/graphics/ChatBox.cc @ 6597

Last change on this file since 6597 was 6597, checked in by smerkli, 15 years ago

Split ChatBox.h into ChatBox.h and ChatBox.cc, comments to follow.

File size: 11.8 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(&DemoSample::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(&DemoSample::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(&DemoSample::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(&DemoSample::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* 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 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.