// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#ifndef CL_CHAT_WINDOW_H
#define CL_CHAT_WINDOW_H
#include "nel/misc/ucstring.h"
#include "nel/misc/smart_ptr.h"
#include "game_share/chat_group.h"
class CChatWindow;
class CGroupContainer;
class CGroupEditBox;
class CCtrlBase;
class CViewText;
/** Interface to react to a chat box entry
* Derivers should define the msgEntered member function to handle entry event.
*/
struct IChatWindowListener
{
// the user entered a msg in the given chat box
virtual void msgEntered(const ucstring &msg, CChatWindow *chatWindow) = 0;
};
/** description of a chat window
*/
struct CChatWindowDesc
{
typedef std::vector > TTemplateParams;
ucstring Title; // unique title for the window
std::string FatherContainer; // name of the father container. If empty, the chat box must be added manually in the hierarchy
std::string ChatTemplate; // Template for the chat interface, or "" to use the default one
TTemplateParams ChatTemplateParams; // optional tempalte parameters
sint InsertPosition; // [optional] -1 if the chat box should be inserted at the end of the container list, or the index otherwise
bool ParentBlink; // [optional] when true, make the parent group blink
bool Savable; // should the position of the chat box be saved between session ? Default is false
bool Localize; // should we have to localize the window?
IChatWindowListener *Listener;
std::string Id;
std::string AHOnActive;
std::string AHOnActiveParams;
std::string AHOnDeactive;
std::string AHOnDeactiveParams;
std::string AHOnCloseButton;
std::string AHOnCloseButtonParams;
std::string HeaderColor;
// default ctor : build optionnal parameters with their default values
CChatWindowDesc();
};
/** This class can be used to easily manipulate a chat box without having to deal directly with the ui.
* Each chat box must have a unique identifier.
* For that reason, they should be created from a CChatWindowManager instance
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2003
*/
class CChatWindow : public NLMISC::CRefCount
{
public:
// a listener to know when a chat window is removed, or when a msg is displayed to it
struct IObserver
{
// called by a CChatWindow when it is deleted
virtual void chatWindowRemoved(CChatWindow * /* cw */) {}
// called by a CChatWindow when a msg has been displayed in it ('displayMessage' has been called)
//virtual void displayMessage(CChatWindow *cw, const ucstring &msg, NLMISC::CRGBA col, uint numBlinks = 0) {}
};
public:
// display a message in this chat box with the given color
virtual void displayMessage(const ucstring &msg, NLMISC::CRGBA col, CChatGroup::TGroupType gt, uint32 dynamicChatDbIndex, uint numBlinks = 0, bool *windowVisible = NULL);
virtual void displayTellMessage(const ucstring &/* msg */, NLMISC::CRGBA /* col */, const ucstring &/* sender */) {}
virtual void clearMessages(CChatGroup::TGroupType gt, uint32 dynamicChatDbIndex);
// Test if the window is visible
bool isVisible() const;
// set the keyboard focus to this chat window (if it has a edit box)
void setKeyboardFocus();
// Make the window blink
void enableBlink(uint numBlinks);
// set a command to be displayed and eventually executed in this chat window. std::string version for backward compatibility
void setCommand(const std::string &command, bool execute);
// set a command to be displayed and eventually executed in this chat window
void setCommand(const ucstring &command, bool execute);
// set a string to be displayed in the edit box of this window (if it has one)
void setEntry(const ucstring &entry);
// Set listener to react to a chat entry
void setListener(IChatWindowListener *listener) { _Listener = listener; }
IChatWindowListener *getListener() const { return _Listener; }
// Set the menu for the chat
void setMenu(const std::string &menuName);
// Set a new prompt for the chat window
void setPrompt(const ucstring &prompt);
// Set the color for the chat window
void setPromptColor(NLMISC::CRGBA col);
/** Get the container associated with this chat window
* NB : you should not change the name of the window ! Use rename instead
*/
CGroupContainer *getContainer() const { return _Chat; }
//
CGroupEditBox *getEditBox() const;
/** try to rename the chat window
* \return true if success
*/
bool rename(const ucstring &newName, bool newNameLocalize);
/** delete the container
* Don't do it in the dtor, because done automatically at the end of the app by the interface manager.
* Useful only if querried by the user
*/
void deleteContainer();
// get the last chat window from which a command has been called
static CChatWindow *getChatWindowLaunchingCommand() { return _ChatWindowLaunchingCommand; }
// get the title of this chat window
ucstring getTitle() const;
// observers
void addObserver(IObserver *obs);
void removeObserver(IObserver *obs);
bool isObserver(const IObserver *obs) const;
// AH adder
void setAHOnActive(const std::string &n);
void setAHOnActiveParams(const std::string &n);
void setAHOnDeactive(const std::string &n);
void setAHOnDeactiveParams(const std::string &n);
void setAHOnCloseButton(const std::string &n);
void setAHOnCloseButtonParams(const std::string &n);
void setHeaderColor(const std::string &n);
//
void displayLocalPlayerTell(const ucstring &msg, uint numBlinks = 0);
/// Encode a color tag '@{RGBA}' in the text. If append is true, append at end of text, otherwise, replace the text
static void encodeColorTag(const NLMISC::CRGBA &color, ucstring &text, bool append=true);
///////////////////////////////////////////////////////////////////////////////////////
protected:
// ctor
CChatWindow();
// dtor
~CChatWindow();
protected:
IChatWindowListener *_Listener;
NLMISC::CRefPtr _Chat;
CGroupEditBox *_EB;
bool _ParentBlink;
static CChatWindow *_ChatWindowLaunchingCommand;
std::vector _Observers;
protected:
friend class CChatWindowManager;
friend class CHandlerChatBoxEntry;
friend class CHandlerContactEntry; // TODO : remove this if CChatBox are used in people lists
/** Create a chat window
* The name and the id should be unique
* The id shouldn't contains ui:interface
*/
bool create(const CChatWindowDesc &desc, const std::string &id);
};
// -----------------------------------------------------------------------------------
class CChatGroupWindow : public CChatWindow
{
public:
CChatGroupWindow() {}
// display a message in this chat box with the given color (callback from chat input filter)
virtual void displayMessage(const ucstring &msg, NLMISC::CRGBA col, CChatGroup::TGroupType gt, uint32 dynamicChatDbIndex, uint numBlinks = 0, bool *windowVisible = NULL);
virtual void displayTellMessage(const ucstring &msg, NLMISC::CRGBA col, const ucstring &sender);
virtual void clearMessages(CChatGroup::TGroupType gt, uint32 dynamicChatDbIndex);
sint32 getTabIndex();
void setTabIndex(sint32 n);
// Free Teller
CGroupContainer *createFreeTeller(const ucstring &winName, const std::string &winColor="");
void setActiveFreeTeller(const ucstring &winName, bool bActive=true);
ucstring getFreeTellerName(const std::string &containerID);
bool removeFreeTeller(const std::string &containerID); // Return true if free teller found
void removeAllFreeTellers();
void saveFreeTeller(NLMISC::IStream &f);
void loadFreeTeller(NLMISC::IStream &f);
// update headers of all free tellers
void updateAllFreeTellerHeaders();
protected:
friend class CChatWindowManager;
std::vector _FreeTellers;
void getAssociatedSubWindow(CChatGroup::TGroupType gt, uint32 dynamicChatDbIndex, class CGroupList *&gl, class CCtrlTabButton *&tab);
void updateFreeTellerHeader(CGroupContainer &ft);
private:
/** Get a valid string to use like ui id
* \param stringId initial unchecked string
* \return valid string
**/
const std::string getValidUiStringId(const std::string &stringId);
};
/** Class that manage several chat windows with unique names
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2003
*/
class CChatWindowManager
{
public:
// dtor
~CChatWindowManager();
/** Create a new chat window. Each chat window should have a unique name
* The window should be inserted in an other container by the caller.
* \param name A unique title to affect to that window
* \param listener A listener to react to the event of the window
* \return A pointer on the window, or NULL, if creation failed or if name already exists.
*/
CChatWindow *createChatWindow(const CChatWindowDesc &desc);
CChatWindow *createChatGroupWindow(const CChatWindowDesc &desc);
// Get a chat window by its title
CChatWindow *getChatWindow(const ucstring &title);
/// Remove a chat window by its title
void removeChatWindow(const ucstring &title);
// Remove a chat window by its pointer
void removeChatWindow(CChatWindow *cw);
/// from a ctrl of a chat box that triggered a menu, or an event, retrieve the associated chat box
CChatWindow *getChatWindowFromCaller(CCtrlBase *caller);
// Singleton pattern applied to the chat window manager
static CChatWindowManager &getInstance();
// try to rename a window
bool rename(const ucstring &oldName, const ucstring &newName, bool newNameLocalize);
// warning : this is slow
uint getNumChatWindow() const { return _ChatWindowMap.size(); }
// warning : this is slow : for debug only
CChatWindow *getChatWindowByIndex(uint index);
///////////////////////////////////////////////////////////////////////////////////////
private:
typedef std::map > TChatWindowMap;
private:
//
TChatWindowMap _ChatWindowMap;
uint _WindowID;
private:
// ctor
CChatWindowManager();
};
// shortcut to get instance of the chat window manager
inline CChatWindowManager &getChatWndMgr() { return CChatWindowManager::getInstance(); }
#endif