Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/chat/src/orxonox/graphics/ChatBox.h @ 6596

Last change on this file since 6596 was 6596, checked in by smerkli, 14 years ago

Adding chatbox related files

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