1 /*
2  *  The ManaPlus Client
3  *  Copyright (C) 2004-2009  The Mana World Development Team
4  *  Copyright (C) 2009-2010  The Mana Developers
5  *  Copyright (C) 2011-2019  The ManaPlus Developers
6  *  Copyright (C) 2019-2021  Andrei Karas
7  *
8  *  This file is part of The ManaPlus Client.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef GUI_WINDOWS_CHATWINDOW_H
25 #define GUI_WINDOWS_CHATWINDOW_H
26 
27 #include "enums/gui/chatmsgtype.h"
28 #include "enums/gui/chattabtype.h"
29 
30 #include "enums/simpletypes/ignorerecord.h"
31 #include "enums/simpletypes/tryremovecolors.h"
32 
33 #include "gui/widgets/window.h"
34 
35 #include "listeners/actionlistener.h"
36 #include "listeners/attributelistener.h"
37 #include "listeners/debugmessagelistener.h"
38 #include "listeners/keylistener.h"
39 
40 class Button;
41 class ChannelTab;
42 class ChatTab;
43 class ChatInput;
44 class ColorListModel;
45 class DropDown;
46 class TabbedArea;
47 class ItemLinkHandler;
48 class WhisperTab;
49 
50 /**
51  * The chat window.
52  *
53  * \ingroup Interface
54  */
55 class ChatWindow final : public Window,
56                          public ActionListener,
57                          public KeyListener,
58                          public ConfigListener,
59                          public AttributeListener,
60                          public DebugMessageListener
61 {
62     public:
63         /**
64          * Constructor.
65          */
66         explicit ChatWindow(const std::string &name);
67 
68         A_DELETE_COPY(ChatWindow)
69 
70         /**
71          * Destructor: used to write back values to the config file
72          */
73         ~ChatWindow() override final;
74 
75         /**
76          * Gets the focused tab.
77          */
78         ChatTab *getFocused() const A_WARN_UNUSED;
79 
80         /**
81          * Clear the given tab.
82          */
83         static void clearTab(ChatTab *const tab);
84 
85         /**
86          * Clear the current tab.
87          */
88         void clearTab() const;
89 
90         /**
91          * Switch to the previous tab in order
92          */
93         void prevTab();
94 
95         /**
96          * Switch to the next tab in order
97          */
98         void nextTab();
99 
100         /**
101          * Close current chat tab
102          */
103         void closeTab() const;
104 
105         /**
106          * Switch to the default tab
107          */
108         void defaultTab();
109 
110         /**
111          * Performs action.
112          */
113         void action(const ActionEvent &event) override final;
114 
115         /**
116          * Request focus for typing chat message.
117          *
118          * \returns true if the input was shown
119          *          false otherwise
120          */
121         bool requestChatFocus();
122 
123         /**
124          * Checks whether ChatWindow is Focused or not.
125          */
126         bool isInputFocused() const A_WARN_UNUSED;
127 
128         /**
129          * Passes the text to the current tab as input
130          *
131          * @param msg  The message text which is to be sent.
132          */
133         void chatInput(const std::string &msg) const;
134 
135         /**
136          * Passes the text to the local chat tab as input
137          *
138          * @param msg  The message text which is to be sent.
139          */
140         void localChatInput(const std::string &msg) const;
141 
142         /** Called when key is pressed */
143         void keyPressed(KeyEvent &event) override final;
144 
145         /** Set the chat input as the given text. */
146         void setInputText(const std::string &text);
147 
148         /** Add the given text to the chat input. */
149         void addInputText(const std::string &text,
150                           const bool space);
151 
152         /** Called to add item to chat */
153         void addItemText(const std::string &item);
154 
155         /** Override to reset mTmpVisible */
156         void setVisible(Visible visible) override final;
157 
158         /**
159          * Handles mouse when dragged.
160          */
161         void mouseDragged(MouseEvent &event) override final;
162 
163         /**
164          * Handles mouse when pressed.
165          */
166         void mousePressed(MouseEvent &event) override final;
167 
168         /**
169          * Scrolls the chat window
170          *
171          * @param amount direction and amount to scroll.  Negative numbers scroll
172          * up, positive numbers scroll down.  The absolute amount indicates the
173          * amount of 1/8ths of chat window real estate that should be scrolled.
174          */
175         void scroll(const int amount) const;
176 
177         /**
178          * Sets the file being recorded to
179          *
180          * @param msg The file to write out to. If null, then stop recording.
181          */
182         void setRecordingFile(const std::string &msg);
183 
getReturnTogglesChat()184         bool getReturnTogglesChat() const noexcept2 A_WARN_UNUSED
185         { return mReturnToggles; }
186 
setReturnTogglesChat(const bool toggles)187         void setReturnTogglesChat(const bool toggles)
188         { mReturnToggles = toggles; }
189 
190         void doPresent() const;
191 
192         void addWhisper(const std::string &restrict nick,
193                         const std::string &restrict mes,
194                         const ChatMsgTypeT own);
195 
196         WhisperTab *addWhisperTab(const std::string &caption,
197                                   const std::string &nick,
198                                   const bool switchTo) A_WARN_UNUSED;
199 
200         WhisperTab *getWhisperTab(const std::string &nick) const A_WARN_UNUSED;
201 
202         ChatTab *addChannelTab(const std::string &name,
203                                const bool switchTo);
204 
205         ChatTab *addSpecialChannelTab(const std::string &name,
206                                       const bool switchTo);
207 
208         ChatTab *addChatTab(const std::string &name,
209                             const bool switchTo,
210                             const bool join) A_WARN_UNUSED;
211 
212         void joinRoom(const bool isJoin);
213 
214         void removeAllWhispers();
215 
216         void removeAllChannels();
217 
218         void ignoreAllWhispers();
219 
220         bool resortChatLog(std::string line, ChatMsgTypeT own,
221                            const std::string &channel,
222                            const IgnoreRecord ignoreRecord,
223                            const TryRemoveColors tryRemoveColors);
224 
225         static void battleChatLog(const std::string &line,
226                                   ChatMsgTypeT own,
227                                   const IgnoreRecord ignoreRecord,
228                                   const TryRemoveColors tryRemoveColors);
229 
230         void channelChatLog(const std::string &channel,
231                             const std::string &line,
232                             ChatMsgTypeT own,
233                             const IgnoreRecord ignoreRecord,
234                             const TryRemoveColors tryRemoveColors);
235 
236         void updateOnline(const std::set<std::string> &onlinePlayers) const;
237 
238         void loadState();
239 
240         void saveState() const;
241 
242         static bool saveTab(const int num,
243                             const ChatTab *const tab);
244 
245         void loadCustomList();
246 
247         void loadGMCommands();
248 
249         static std::string doReplace(const std::string &msg) A_WARN_UNUSED;
250 
251         void adjustTabSize();
252 
253         void addToAwayLog(const std::string &line);
254 
255         void displayAwayLog() const;
256 
clearAwayLog()257         void clearAwayLog()
258         { mAwayLog.clear(); }
259 
260         void parseHighlights();
261 
262         void parseGlobalsFilter();
263 
264         bool findHighlight(const std::string &str) A_WARN_UNUSED;
265 
266         void copyToClipboard(const int x, const int y) const;
267 
268         void optionChanged(const std::string &name) override final;
269 
270         void mouseEntered(MouseEvent& event) override final;
271 
272         void mouseMoved(MouseEvent &event) override final;
273 
274         void mouseExited(MouseEvent& event A_UNUSED) override final;
275 
276         void draw(Graphics *const graphics) override final A_NONNULL(2);
277 
278         void safeDraw(Graphics *const graphics) override final A_NONNULL(2);
279 
280         void updateVisibility();
281 
282         void unHideWindow();
283 
284         void widgetResized(const Event &event) override final;
285 
286         void addGlobalMessage(const std::string &line);
287 
288         void postInit() override final;
289 
290         bool isTabPresent(const ChatTab *const tab) const A_WARN_UNUSED;
291 
292         void selectTabByType(const ChatTabTypeT &type);
293 
294         void attributeChanged(const AttributesT id,
295                               const int64_t oldVal,
296                               const int64_t newVal) override final;
297 
298         void postConnection();
299 
300         void showGMTab();
301 
302         void debugMessage(const std::string &msg) override final;
303 
304         void scheduleDelete() override final;
305 
306 #ifdef USE_PROFILER
307         void logicChildren();
308 #endif  // USE_PROFILER
309 
310     protected:
311         friend class ChannelTab;
312         friend class ChatTab;
313         friend class WhisperTab;
314         friend class PopupMenu;
315 
316         typedef std::list<std::string> History;
317 
318         /** Remove the given tab from the window */
319         void removeTab(ChatTab *const tab);
320 
321         /** Add the tab to the window */
322         void addTab(ChatTab *const tab);
323 
324         void removeWhisper(const std::string &nick);
325 
326         void removeChannel(const std::string &nick);
327 
328         void autoComplete();
329 
330         std::string addColors(std::string &msg);
331 
332         std::string autoCompleteHistory(const std::string &partName) const;
333 
334         static std::string autoComplete(const std::string &partName,
335                                         const History *const words);
336 
337         static std::string autoComplete(const StringVect &names,
338                                         std::string partName);
339 
340         /** Used for showing item popup on clicking links **/
341         ItemLinkHandler *mItemLinkHandler A_NONNULLPOINTER;
342 
343         /** Tabbed area for holding each channel. */
344         TabbedArea *mChatTabs A_NONNULLPOINTER;
345 
346         /** Input box for typing chat messages. */
347         ChatInput *mChatInput A_NONNULLPOINTER;
348 
349         void initTradeFilter();
350 
351         void toggleChatFocus();
352 
353         unsigned int mRainbowColor;
354 
355     private:
356         void fillCommands();
357 
358         void loadCommandsFile(const std::string &name);
359 
360         void updateTabsMargin();
361 
362         bool addCurrentToHistory();
363 
364         typedef std::map<const std::string, WhisperTab*> TabMap;
365         typedef std::map<const std::string, ChannelTab*> ChannelMap;
366 
367         /** Manage whisper tabs */
368         TabMap mWhispers;
369         ChannelMap mChannels;
370 
371         typedef History::iterator HistoryIterator;
372         History mHistory;          /**< Command history. */
373         HistoryIterator mCurHist;  /**< History iterator. */
374 
375         typedef std::list<std::string> ChatCommands;
376         typedef ChatCommands::iterator ChatCommandsIterator;
377         History mCommands;         /**< Command list. */
378         History mCustomWords;
379 
380         StringVect mTradeFilter;
381 
382         ColorListModel *mColorListModel A_NONNULLPOINTER;
383         DropDown *mColorPicker A_NONNULLPOINTER;
384         Button *mChatButton A_NONNULLPOINTER;
385         std::list<std::string> mAwayLog;
386         StringVect mHighlights;
387         StringVect mGlobalsFilter;
388         int mChatColor;
389         int mEmoteButtonSpacing;
390         int mEmoteButtonY;
391         unsigned int mChatHistoryIndex;
392         bool mReturnToggles;  // Marks whether <Return> toggles the chat log
393                               // or not
394         bool mGMLoaded;
395         bool mHaveMouse;
396         bool mAutoHide;
397         bool mShowBattleEvents;
398         bool mShowAllLang;
399         bool mEnableTradeFilter;
400         bool mTmpVisible;
401 };
402 
403 extern ChatWindow *chatWindow;
404 
405 #endif  // GUI_WINDOWS_CHATWINDOW_H
406