Chat.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*\
  2. |*| Copyright 2015 bill-auger <https://github.com/bill-auger/av-caster/issues>
  3. |*|
  4. |*| This file is part of the AvCaster program.
  5. |*|
  6. |*| AvCaster is free software: you can redistribute it and/or modify
  7. |*| it under the terms of the GNU Lesser General Public License version 3
  8. |*| as published by the Free Software Foundation.
  9. |*|
  10. |*| AvCaster is distributed in the hope that it will be useful,
  11. |*| but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. |*| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. |*| GNU Lesser General Public License for more details.
  14. |*|
  15. |*| You should have received a copy of the GNU Lesser General Public License
  16. |*| along with AvCaster. If not, see <http://www.gnu.org/licenses/>.
  17. \*/
  18. //[Headers] You can add your own extra header files here...
  19. #include "AvCaster.h"
  20. #include "Trace/TraceChat.h"
  21. //[/Headers]
  22. #include "Chat.h"
  23. //[MiscUserDefs] You can add your own user definitions and misc code here...
  24. //[/MiscUserDefs]
  25. //==============================================================================
  26. Chat::Chat ()
  27. {
  28. addAndMakeVisible (chatGroup = new GroupComponent ("chatGroup",
  29. TRANS("Chat")));
  30. chatGroup->setColour (GroupComponent::outlineColourId, Colours::white);
  31. chatGroup->setColour (GroupComponent::textColourId, Colours::white);
  32. addAndMakeVisible (chatHistoryGroup = new GroupComponent ("chatHistoryGroup",
  33. String::empty));
  34. chatHistoryGroup->setColour (GroupComponent::outlineColourId, Colours::white);
  35. chatHistoryGroup->setColour (GroupComponent::textColourId, Colours::white);
  36. addAndMakeVisible (chatHistoryText = new TextEditor ("chatHistoryText"));
  37. chatHistoryText->setMultiLine (true);
  38. chatHistoryText->setReturnKeyStartsNewLine (false);
  39. chatHistoryText->setReadOnly (true);
  40. chatHistoryText->setScrollbarsShown (true);
  41. chatHistoryText->setCaretVisible (false);
  42. chatHistoryText->setPopupMenuEnabled (true);
  43. chatHistoryText->setColour (TextEditor::textColourId, Colours::white);
  44. chatHistoryText->setColour (TextEditor::backgroundColourId, Colours::black);
  45. chatHistoryText->setText (String::empty);
  46. addAndMakeVisible (chatEntryGroup = new GroupComponent ("chatEntryGroup",
  47. String::empty));
  48. chatEntryGroup->setExplicitFocusOrder (1);
  49. chatEntryGroup->setColour (GroupComponent::outlineColourId, Colours::white);
  50. chatEntryGroup->setColour (GroupComponent::textColourId, Colours::white);
  51. addAndMakeVisible (chatEntryText = new TextEditor ("chatEntryText"));
  52. chatEntryText->setExplicitFocusOrder (2);
  53. chatEntryText->setMultiLine (false);
  54. chatEntryText->setReturnKeyStartsNewLine (false);
  55. chatEntryText->setReadOnly (false);
  56. chatEntryText->setScrollbarsShown (false);
  57. chatEntryText->setCaretVisible (true);
  58. chatEntryText->setPopupMenuEnabled (true);
  59. chatEntryText->setColour (TextEditor::textColourId, Colours::white);
  60. chatEntryText->setColour (TextEditor::backgroundColourId, Colour (0xff202020));
  61. chatEntryText->setText (String::empty);
  62. addAndMakeVisible (dummyChatList = new ChatList (ValueTree::invalid));
  63. dummyChatList->setExplicitFocusOrder (2);
  64. dummyChatList->setName ("dummyChatList");
  65. //[UserPreSize]
  66. //[/UserPreSize]
  67. setSize (1, 1);
  68. //[Constructor] You can add your own custom stuff here..
  69. // defer visibility until connected to some chat channel
  70. updateVisiblilty() ;
  71. // text editor colors
  72. this->chatEntryText ->setColour(CaretComponent::caretColourId , GUI::TEXT_CARET_COLOR ) ;
  73. this->chatHistoryText->setColour(TextEditor::textColourId , GUI::TEXT_NORMAL_COLOR ) ;
  74. this->chatEntryText ->setColour(TextEditor::textColourId , GUI::TEXT_NORMAL_COLOR ) ;
  75. this->chatHistoryText->setColour(TextEditor::highlightColourId , GUI::TEXT_HILITEBG_COLOR) ;
  76. this->chatEntryText ->setColour(TextEditor::highlightColourId , GUI::TEXT_HILITEBG_COLOR) ;
  77. this->chatHistoryText->setColour(TextEditor::highlightedTextColourId , GUI::TEXT_HILITE_COLOR ) ;
  78. this->chatEntryText ->setColour(TextEditor::highlightedTextColourId , GUI::TEXT_HILITE_COLOR ) ;
  79. this->chatHistoryText->setColour(TextEditor::outlineColourId , GUI::TEXT_BG_COLOR ) ;
  80. this->chatEntryText ->setColour(TextEditor::outlineColourId , GUI::TEXT_BG_COLOR ) ;
  81. this->chatHistoryText->setColour(TextEditor::focusedOutlineColourId , GUI::TEXT_FOCUS_COLOR ) ;
  82. this->chatEntryText ->setColour(TextEditor::focusedOutlineColourId , GUI::TEXT_FOCUS_COLOR ) ;
  83. this->chatHistoryText->setColour(TextEditor::shadowColourId , GUI::TEXT_SHADOW_COLOR ) ;
  84. this->chatEntryText ->setColour(TextEditor::shadowColourId , GUI::TEXT_SHADOW_COLOR ) ;
  85. this->chatHistoryText->setColour(TextEditor::backgroundColourId , GUI::TEXT_BG_COLOR ) ;
  86. this->chatEntryText ->setColour(TextEditor::backgroundColourId , GUI::TEXT_BG_COLOR ) ;
  87. // text editor behaviors
  88. this->chatEntryText->setSelectAllWhenFocused(true) ;
  89. this->chatEntryText->setTextToShowWhenEmpty(GUI::CHAT_PROMPT_TEXT , GUI::TEXT_EMPTY_COLOR) ;
  90. this->chatEntryText->setInputRestrictions(1024) ;
  91. // hide GUI designer placeholder
  92. this->dummyChatList->setVisible(false) ;
  93. // register interest in outgoing chat text
  94. this->chatEntryText->addListener(this) ;
  95. //[/Constructor]
  96. }
  97. Chat::~Chat()
  98. {
  99. //[Destructor_pre]. You can add your own custom destruction code here..
  100. //[/Destructor_pre]
  101. chatGroup = nullptr;
  102. chatHistoryGroup = nullptr;
  103. chatHistoryText = nullptr;
  104. chatEntryGroup = nullptr;
  105. chatEntryText = nullptr;
  106. dummyChatList = nullptr;
  107. //[Destructor]. You can add your own custom destruction code here..
  108. //[/Destructor]
  109. }
  110. //==============================================================================
  111. void Chat::paint (Graphics& g)
  112. {
  113. //[UserPrePaint] Add your own custom painting code here..
  114. //[/UserPrePaint]
  115. g.setColour (Colour (0xff303030));
  116. g.fillRoundedRectangle (20.0f, 18.0f, static_cast<float> (getWidth() - 40), static_cast<float> (getHeight() - 36), 4.000f);
  117. //[UserPaint] Add your own custom painting code here..
  118. //[/UserPaint]
  119. }
  120. void Chat::resized()
  121. {
  122. //[UserPreResize] Add your own custom resize code here..
  123. //[/UserPreResize]
  124. chatGroup->setBounds (16, 8, getWidth() - 32, getHeight() - 24);
  125. chatHistoryGroup->setBounds (28, 22, getWidth() - 56, getHeight() - 90);
  126. chatHistoryText->setBounds (32, 32, getWidth() - 64, getHeight() - 104);
  127. chatEntryGroup->setBounds (28, getHeight() - 68, getWidth() - 56, 38);
  128. chatEntryText->setBounds (32, getHeight() - 58, getWidth() - 64, 24);
  129. dummyChatList->setBounds (getWidth() - 160, 32, 128, 48);
  130. //[UserResized] Add your own custom resize handling here..
  131. //[/UserResized]
  132. }
  133. //[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
  134. /* Chat public instance methods */
  135. void Chat::updateVisiblilty()
  136. {
  137. int n_chatters = 0 ; int n_servers = this->serversStore.getNumChildren() ;
  138. for (int server_n = 0 ; server_n < n_servers ; ++server_n)
  139. {
  140. ValueTree server = this->serversStore.getChild(server_n) ;
  141. ValueTree chatters = server.getChildWithName(CONFIG::CHATTERS_ID) ;
  142. n_chatters += chatters.getNumChildren() ;
  143. }
  144. bool is_visible = n_chatters > 0 ;
  145. String group_title = (is_visible) ? GUI::CHAT_GROUP_TITLE : AvCaster::GetVersionString() ;
  146. DEBUG_TRACE_CHAT_VISIBILITY
  147. this->chatGroup ->setText (group_title) ;
  148. this->chatHistoryGroup->setVisible(is_visible) ;
  149. this->chatHistoryText ->setVisible(is_visible) ;
  150. this->chatEntryGroup ->setVisible(is_visible) ;
  151. this->chatEntryText ->setVisible(is_visible) ;
  152. for (int server_n = 0 ; server_n < this->chatLists.size() ; ++server_n)
  153. this->chatLists[server_n]->setVisible(is_visible) ;
  154. }
  155. void Chat::refresh()
  156. {
  157. updateVisiblilty() ;
  158. // calculate total height
  159. int server_n = this->chatLists.size() ; int lists_h = GUI::CHATLIST_Y ;
  160. while (server_n--) lists_h += this->chatLists[server_n]->getHeight() + GUI::PAD ;
  161. bool is_scrollbar_visible = lists_h > getHeight() ;
  162. int list_x_offset = (is_scrollbar_visible)? GUI::OFFSET_CHATLIST_X : GUI::CHATLIST_X ;
  163. int list_x = getWidth() - list_x_offset ;
  164. int list_y = GUI::CHATLIST_Y ;
  165. // arrange lists
  166. for (int server_n = 0 ; server_n < this->chatLists.size() ; ++server_n)
  167. {
  168. ChatList* chatList = this->chatLists[server_n] ;
  169. chatList->setTopLeftPosition(list_x , list_y) ;
  170. list_y += chatList->getHeight() ;
  171. }
  172. }
  173. void Chat::addChatLine(String prefix , String nick , String message_text)
  174. {
  175. String message_header = prefix + ((nick == GUI::CLIENT_NICK) ? "" : nick + ": ") ;
  176. const MessageManagerLock mmLock ;
  177. this->chatHistoryText->moveCaretToEnd() ;
  178. this->chatHistoryText->insertTextAtCaret("\n" + message_header + message_text) ;
  179. }
  180. /* Chat private instance methods */
  181. void Chat::textEditorReturnKeyPressed(TextEditor& a_text_editor)
  182. {
  183. if (&a_text_editor != this->chatEntryText) return ;
  184. AvCaster::SendChat(this->chatEntryText->getText()) ;
  185. this->chatEntryText->clear() ;
  186. }
  187. void Chat::valueTreeChildAdded(ValueTree& a_parent_node , ValueTree& a_node)
  188. {
  189. if (isServersNode(a_parent_node , a_node)) createChatList(a_node) ;
  190. }
  191. void Chat::valueTreeChildRemoved(ValueTree& a_parent_node , ValueTree& a_node)
  192. {
  193. if (isServersNode(a_parent_node , a_node)) destroyChatList(String(a_node.getType())) ;
  194. }
  195. void Chat::initialize(ValueTree servers_store)
  196. {
  197. this->serversStore = servers_store ; this->serversStore.addListener(this) ;
  198. for (int server_n = 0 ; server_n < servers_store.getNumChildren() ; ++server_n)
  199. createChatList(this->serversStore.getChild(server_n)) ;
  200. }
  201. void Chat::createChatList(ValueTree server_store)
  202. {
  203. ValueTree chatters_store = server_store.getChildWithName(CONFIG::CHATTERS_ID) ;
  204. String server_id = String(server_store.getType()) ;
  205. ChatList* chat_list = new ChatList(chatters_store) ;
  206. chat_list->setComponentID(server_id) ; addAndMakeVisible(chat_list) ;
  207. this->chatLists.add(chat_list) ;
  208. refresh() ;
  209. }
  210. void Chat::destroyChatList(String server_id)
  211. {
  212. for (int server_n = 0 ; server_n < this->chatLists.size() ; ++server_n)
  213. {
  214. ChatList* chatlist = this->chatLists[server_n] ;
  215. if (chatlist->getComponentID() == server_id) this->chatLists.removeObject(chatlist) ;
  216. }
  217. refresh() ;
  218. }
  219. bool Chat::isServersNode(ValueTree& a_parent_node , ValueTree& a_node)
  220. {
  221. return a_parent_node.getType() == CONFIG::SERVERS_ID ;
  222. }
  223. //[/MiscUserCode]
  224. //==============================================================================
  225. #if 0
  226. /* -- Introjucer information section --
  227. This is where the Introjucer stores the metadata that describe this GUI layout, so
  228. make changes in here at your peril!
  229. BEGIN_JUCER_METADATA
  230. <JUCER_COMPONENT documentType="Component" className="Chat" componentName="" parentClasses="public Component, public TextEditor::Listener, public ValueTree::Listener"
  231. constructorParams="" variableInitialisers="" snapPixels="8" snapActive="1"
  232. snapShown="1" overlayOpacity="0.330" fixedSize="0" initialWidth="1"
  233. initialHeight="1">
  234. <BACKGROUND backgroundColour="0">
  235. <ROUNDRECT pos="20 18 40M 36M" cornerSize="4" fill="solid: ff303030" hasStroke="0"/>
  236. </BACKGROUND>
  237. <GROUPCOMPONENT name="chatGroup" id="6607ba656d5c8919" memberName="chatGroup"
  238. virtualName="" explicitFocusOrder="0" pos="16 8 32M 24M" outlinecol="ffffffff"
  239. textcol="ffffffff" title="Chat"/>
  240. <GROUPCOMPONENT name="chatHistoryGroup" id="258cc166964ef054" memberName="chatHistoryGroup"
  241. virtualName="" explicitFocusOrder="0" pos="28 22 56M 90M" outlinecol="ffffffff"
  242. textcol="ffffffff" title=""/>
  243. <TEXTEDITOR name="chatHistoryText" id="f98355c5e336ef72" memberName="chatHistoryText"
  244. virtualName="" explicitFocusOrder="0" pos="32 32 64M 104M" textcol="ffffffff"
  245. bkgcol="ff000000" initialText="" multiline="1" retKeyStartsLine="0"
  246. readonly="1" scrollbars="1" caret="0" popupmenu="1"/>
  247. <GROUPCOMPONENT name="chatEntryGroup" id="da473ae049822d5c" memberName="chatEntryGroup"
  248. virtualName="" explicitFocusOrder="1" pos="28 68R 56M 38" outlinecol="ffffffff"
  249. textcol="ffffffff" title=""/>
  250. <TEXTEDITOR name="chatEntryText" id="1dd802ce165b4013" memberName="chatEntryText"
  251. virtualName="" explicitFocusOrder="2" pos="32 58R 64M 24" textcol="ffffffff"
  252. bkgcol="ff202020" initialText="" multiline="0" retKeyStartsLine="0"
  253. readonly="0" scrollbars="0" caret="1" popupmenu="1"/>
  254. <GENERICCOMPONENT name="dummyChatList" id="90795555172fbed0" memberName="dummyChatList"
  255. virtualName="" explicitFocusOrder="2" pos="160R 32 128 48" class="ChatList"
  256. params="ValueTree::invalid"/>
  257. </JUCER_COMPONENT>
  258. END_JUCER_METADATA
  259. */
  260. #endif
  261. //[EndFile] You can add extra defines here...
  262. //[/EndFile]