1 /* Copyright (C) 2007 The SpringLobby Team. All rights reserved. */
2 //
3 // Class: MainChatTab
4 //
5 
6 #include <stdexcept>
7 #include <wx/intl.h>
8 #include <wx/imaglist.h>
9 #include <wx/sizer.h>
10 #include <wx/notebook.h>
11 #include <wx/image.h>
12 #include <wx/log.h>
13 
14 #include "aui/auimanager.h"
15 #include "mainchattab.h"
16 #include "utils/debug.h"
17 #include "utils/conversion.h"
18 #include <lslutils/misc.h>
19 #include "utils/controls.h"
20 #include "mainwindow.h"
21 #include "channel/channel.h"
22 #include "user.h"
23 #include "chatpanel.h"
24 #include "server.h"
25 #include "settings.h"
26 #include "aui/artprovider.h"
27 #include "aui/slbook.h"
28 
29 #include "images/close.xpm"
30 #include "images/server.xpm"
31 #include "images/channel.xpm"
32 #include "images/userchat.xpm"
33 
BEGIN_EVENT_TABLE(MainChatTab,wxPanel)34 BEGIN_EVENT_TABLE( MainChatTab, wxPanel )
35 
36 	EVT_AUINOTEBOOK_PAGE_CHANGED    ( CHAT_TABS, MainChatTab::OnTabsChanged     )
37 	EVT_AUINOTEBOOK_PAGE_CLOSE      ( CHAT_TABS, MainChatTab::OnTabClose        )
38 
39 END_EVENT_TABLE()
40 
41 
42 MainChatTab::MainChatTab( wxWindow* parent )
43     : wxScrolledWindow( parent, -1, wxDefaultPosition, wxDefaultSize, 0, wxPanelNameStr )
44 {
45 	GetAui().manager->AddPane( this, wxLEFT, _T( "mainchattab" ) );
46 
47 	m_newtab_sel = -1;
48 	m_server_chat = 0;
49 
50 	m_main_sizer = new wxBoxSizer( wxVERTICAL );
51 
52 	m_chat_tabs = new SLChatNotebook( this, CHAT_TABS, wxDefaultPosition, wxDefaultSize, wxAUI_NB_DEFAULT_STYLE | wxAUI_NB_TOP | wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_WINDOWLIST_BUTTON );
53 	m_chat_tabs ->SetArtProvider( new SLArtProvider );
54 
55 	wxBitmap userchat ( userchat_xpm ); //*charArr2wxBitmap(userchat_png, sizeof(userchat_png) );
56 	m_imagelist = new wxImageList( 12, 12 );
57 	m_imagelist->Add( wxBitmap( close_xpm ) );
58 	m_imagelist->Add( wxBitmap( server_xpm ) );
59 	m_imagelist->Add( wxBitmap( channel_xpm ) );
60 	m_imagelist->Add( wxBitmap( userchat_xpm ) );
61 
62 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( channel_xpm ), sett().GetChatColorJoinPart() ) ) );
63 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( userchat_xpm ), sett().GetChatColorJoinPart() ) ) );
64 
65 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( channel_xpm ), sett().GetChatColorMine() ) ) );
66 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( userchat_xpm ), sett().GetChatColorMine() ) ) );
67 
68 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( channel_xpm ), sett().GetChatColorHighlight() ) ) );
69 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( userchat_xpm ), sett().GetChatColorHighlight() ) ) );
70 
71 	m_imagelist->Add( wxBitmap ( ReplaceChannelStatusColour( wxBitmap( server_xpm ), sett().GetChatColorError() ) ) );
72 
73 	m_main_sizer->Add( m_chat_tabs, 1, wxEXPAND );
74 
75 	SetSizer( m_main_sizer );
76 	m_main_sizer->SetSizeHints( this );
77 	SetScrollRate( SCROLL_RATE, SCROLL_RATE );
78 
79 	Layout();
80 }
81 
82 
~MainChatTab()83 MainChatTab::~MainChatTab()
84 {
85 
86 }
87 
ServerChat()88 ChatPanel& MainChatTab::ServerChat()
89 {
90 	ASSERT_LOGIC( m_server_chat != 0, _T( "m_server_chat = 0" ) );
91 	return *m_server_chat;
92 }
93 
94 
GetActiveChatPanel()95 ChatPanel* MainChatTab::GetActiveChatPanel()
96 {
97     int selection = m_chat_tabs->GetSelection();
98     if ( selection < 0 )
99         return NULL;
100     else
101         return static_cast< ChatPanel* >( m_chat_tabs->GetPage( selection ) );
102 }
103 
104 
GetChannelChatPanel(const wxString & channel)105 ChatPanel* MainChatTab::GetChannelChatPanel( const wxString& channel )
106 {
107 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
108 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
109 		if ( tmp->GetPanelType() == CPT_Channel ) {
110 			wxString name = m_chat_tabs->GetPageText( i );
111 			if ( name.Lower() == channel.Lower() ) return ( ChatPanel* )m_chat_tabs->GetPage( i );
112 		}
113 	}
114 	return 0;
115 }
116 
UpdateNicklistHighlights()117 void MainChatTab::UpdateNicklistHighlights()
118 {
119 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
120 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
121 		if ( tmp->GetPanelType() == CPT_Channel ) {
122 			tmp->UpdateNicklistHighlights();
123 		}
124 	}
125 	if ( m_server_chat != 0 )
126 	{
127 		m_server_chat->UpdateNicklistHighlights();
128 	}
129 }
130 
GetUserChatPanel(const wxString & user)131 ChatPanel* MainChatTab::GetUserChatPanel( const wxString& user )
132 {
133 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
134 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
135 		if ( tmp->GetPanelType() == CPT_User ) {
136 			wxString name = m_chat_tabs->GetPageText( i );
137 			if ( name.Lower() == user.Lower() ) return ( ChatPanel* )m_chat_tabs->GetPage( i );
138 		}
139 	}
140 	return 0;
141 }
142 
143 
OnUserConnected(User & user)144 void MainChatTab::OnUserConnected( User& user )
145 {
146 	ChatPanel* panel = GetUserChatPanel( user.GetNick() );
147 	if ( panel != 0 )
148 	{
149 		panel->SetUser( &user );
150 		panel->OnUserConnected();
151 		//TODO enable send button (koshi)
152 	}
153 	if ( m_server_chat != 0 )
154 	{
155 		m_server_chat->OnChannelJoin( user );
156 	}
157 }
158 
159 
OnUserDisconnected(User & user)160 void MainChatTab::OnUserDisconnected( User& user )
161 {
162 	ChatPanel* panel = GetUserChatPanel( user.GetNick() );
163 	if ( panel != 0 )
164 	{
165 		panel->OnUserDisconnected();
166 		panel->SetUser( 0 );
167 		//TODO disable send button (koshi)
168 	}
169 	if ( m_server_chat != 0 )
170 	{
171 		m_server_chat->Parted( user, wxEmptyString );
172 	}
173 }
174 
LeaveChannels()175 void MainChatTab::LeaveChannels()
176 {
177 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
178 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
179 		if ( tmp->GetPanelType() == CPT_Channel )
180 		{
181 			tmp->StatusMessage( _( "Disconnected from server, chat closed." ) );
182 			tmp->SetChannel( 0 );
183 		} else if ( tmp->GetPanelType() == CPT_User )
184 		{
185 			tmp->StatusMessage( _( "Disconnected from server, chat closed." ) );
186 			tmp->SetUser( 0 );
187 		}
188 	}
189 }
190 
RejoinChannels()191 void MainChatTab::RejoinChannels()
192 {
193 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ )
194 	{
195 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
196 		if ( tmp->GetPanelType() == CPT_Channel )
197 		{
198 
199 			// TODO: This will not rejoin passworded channels.
200 			wxString name = m_chat_tabs->GetPageText( i );
201 			bool alreadyin = false;
202 			try
203 			{
204 				serverSelector().GetServer().GetChannel( name ).GetMe();
205 				alreadyin = true;
206 			}
207 			catch ( ... ) {}
208 			if ( !alreadyin )
209 			{
210 				serverSelector().GetServer().JoinChannel( name, wxEmptyString );
211 				tmp->SetChannel( &serverSelector().GetServer().GetChannel( name ) );
212 			}
213 
214 		} else if ( tmp->GetPanelType() == CPT_User )
215 		{
216 
217 			wxString name = m_chat_tabs->GetPageText( i );
218 			if ( serverSelector().GetServer().UserExists( name ) ) tmp->SetUser( &serverSelector().GetServer().GetUser( name ) );
219 
220 		}
221 	}
222 }
223 
224 
AddChatPanel(Channel & channel,bool doFocus)225 ChatPanel* MainChatTab::AddChatPanel( Channel& channel, bool doFocus )
226 {
227 
228 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
229 		if ( m_chat_tabs->GetPageText( i ) == channel.GetName() ) {
230 			ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
231 			if ( tmp->GetPanelType() == CPT_Channel ) {
232 				if ( doFocus )
233 					m_chat_tabs->SetSelection( i );
234 				tmp->SetChannel( &channel );
235 				return tmp;
236 			}
237 		}
238 	}
239 
240 	ChatPanel* chat = new ChatPanel( m_chat_tabs, channel, m_imagelist );
241 	m_chat_tabs->InsertPage( m_chat_tabs->GetPageCount() - 1, chat, channel.GetName(), doFocus, wxBitmap( channel_xpm ) );
242 	if ( doFocus )
243 		chat->FocusInputBox();
244 	return chat;
245 }
246 
AddChatPanel(Server & server,const wxString & name)247 ChatPanel* MainChatTab::AddChatPanel( Server& server, const wxString& name )
248 {
249 
250 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
251 		//if ( m_chat_tabs->GetPageText( i ) == name ) {
252 		if ( true ) { // wipe all old server tabs
253 			ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
254 			if ( tmp->GetPanelType() == CPT_Server ) {
255 				m_chat_tabs->DeletePage( i );
256 				i--;
257 			}
258 		}
259 	}
260 
261 	ChatPanel* chat = new ChatPanel( m_chat_tabs, server, m_imagelist );
262 	m_server_chat = chat;
263 	m_chat_tabs->InsertPage( m_chat_tabs->GetPageCount() - 1, chat, name, true, wxBitmap( server_xpm ) );
264 	return chat;
265 }
266 
AddChatPanel(const User & user)267 ChatPanel* MainChatTab::AddChatPanel( const User& user )
268 {
269 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
270 		if ( m_chat_tabs->GetPageText( i ) == user.GetNick() ) {
271 			ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
272 			if ( tmp->GetPanelType() == CPT_User ) {
273 				m_chat_tabs->SetSelection( i );
274 				tmp->SetUser( &user );
275 				return tmp;
276 			}
277 		}
278 	}
279 	int selection = m_chat_tabs->GetSelection();
280 	ChatPanel* chat = new ChatPanel( m_chat_tabs, user, m_imagelist );
281 	m_chat_tabs->InsertPage( m_chat_tabs->GetPageCount() - 1, chat, user.GetNick(), true, wxBitmap( userchat_xpm ) );
282 	if ( selection > 0 ) m_chat_tabs->SetSelection( selection );
283 	return chat;
284 }
285 
286 
BroadcastMessage(const wxString & message)287 void MainChatTab::BroadcastMessage( const wxString& message )
288 {
289 	// spam the message in all channels
290 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ )
291 	{
292 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
293 		tmp->StatusMessage( message );
294 	}
295 }
296 
297 
GetCurrentPanel()298 ChatPanel* MainChatTab::GetCurrentPanel()
299 {
300 	int sel = m_chat_tabs->GetSelection();
301 	if ( sel < 0 ) return 0;
302 	return ( ChatPanel* )m_chat_tabs->GetPage( sel );
303 }
304 
305 
OnTabClose(wxAuiNotebookEvent & event)306 void MainChatTab::OnTabClose( wxAuiNotebookEvent& event )
307 {
308 	int selection = event.GetSelection();
309 	ChatPanel* panel = ( ChatPanel* )m_chat_tabs->GetPage( selection );
310 	if ( panel )
311 	{
312 		panel->Part();
313 		if( panel->IsServerPanel() )
314             m_server_chat = 0;
315 	}
316 
317 }
318 
OnTabsChanged(wxAuiNotebookEvent & event)319 void MainChatTab::OnTabsChanged( wxAuiNotebookEvent& event )
320 {
321 	wxLogDebugFunc( wxEmptyString );
322 
323 	int oldsel = event.GetOldSelection();
324 	if ( oldsel < 0 ) return;
325 	int newsel = event.GetSelection();
326 	if ( newsel < 0 ) return;
327 
328 	// change icon to default the icon to show that no new events happened
329 	size_t ImageIndex = ( ( ChatPanel* )m_chat_tabs->GetPage( newsel ) )->GetIconIndex();
330 	if ( ImageIndex == 4 || ImageIndex == 6 || ImageIndex == 8 )
331 	{
332 		GetActiveChatPanel()->SetIconIndex( 2 );
333 		m_chat_tabs->SetPageBitmap( newsel, wxBitmap( channel_xpm ) );
334 	}
335 	else if ( ImageIndex == 5 || ImageIndex == 7 || ImageIndex == 9 )
336 	{
337 		GetActiveChatPanel()->SetIconIndex( 3 );
338 		m_chat_tabs->SetPageBitmap( newsel, wxBitmap( userchat_xpm ) );
339 	}
340 	else if ( ImageIndex == 10 )
341 	{
342 		GetActiveChatPanel()->SetIconIndex( 1 );
343 		m_chat_tabs->SetPageBitmap( newsel, wxBitmap( server_xpm ) );
344 	}
345 
346 	wxWindow* newpage = m_chat_tabs->GetPage( newsel );
347 	if ( newpage == 0 ) { // Not sure what to do here
348 		wxLogError( _T( "Newpage NULL." ) );
349 		return;
350 	}
351 
352 	GetActiveChatPanel()->FocusInputBox();
353 
354 }
355 
356 
ReplaceChannelStatusColour(wxBitmap img,const wxColour & colour) const357 wxImage MainChatTab::ReplaceChannelStatusColour( wxBitmap img, const wxColour& colour ) const
358 {
359 	wxImage ret = img.ConvertToImage();
360 	wxImage::HSVValue origcolour = wxImage::RGBtoHSV( wxImage::RGBValue( colour.Red(), colour.Green(), colour.Blue() ) );
361 
362 	double bright = origcolour.value - 0.1 * origcolour.value;
363 	bright = LSL::Util::Clamp( bright, 0.0, 1.0 );
364 	wxImage::HSVValue hsvdarker1( origcolour.hue, origcolour.saturation, bright );
365 	bright = origcolour.value - 0.5 * origcolour.value;
366 	bright = LSL::Util::Clamp( bright, 0.0, 1.0 );
367 	wxImage::HSVValue hsvdarker2( origcolour.hue, origcolour.saturation, bright );
368 
369 	wxImage::RGBValue rgbdarker1 = wxImage::HSVtoRGB( hsvdarker1 );
370 	wxImage::RGBValue rgbdarker2 = wxImage::HSVtoRGB( hsvdarker2 );
371 
372 
373 	ret.Replace( 164, 147, 0, rgbdarker2.red, rgbdarker2.green, rgbdarker2.blue );
374 
375 	ret.Replace( 255, 228, 0, rgbdarker1.red, rgbdarker1.green, rgbdarker1.blue );
376 
377 	ret.Replace( 255, 253, 234, colour.Red(), colour.Green(), colour.Blue() );
378 
379 	ret.Replace( 255, 228, 0, rgbdarker1.red, rgbdarker1.green, rgbdarker1.blue );
380 
381 	// server icon
382 
383 	ret.Replace( 211, 211, 211, rgbdarker2.red, rgbdarker2.green, rgbdarker2.blue );
384 
385 	ret.Replace( 249, 249, 249, rgbdarker1.red, rgbdarker1.green, rgbdarker1.blue );
386 
387 	ret.Replace( 0, 180, 255, colour.Red(), colour.Green(), colour.Blue() );
388 
389 
390 	return ret;
391 }
392 
RemoveChatPanel(ChatPanel * panel)393 bool MainChatTab::RemoveChatPanel( ChatPanel* panel )
394 {
395 	for ( unsigned int i = 0; i < m_chat_tabs->GetPageCount(); i++ ) {
396 		ChatPanel* tmp = ( ChatPanel* )m_chat_tabs->GetPage( i );
397 		if ( tmp == panel && panel != 0 )
398 		{
399 			m_chat_tabs->DeletePage( i );
400 			return true;
401 		}
402 	}
403 	return false;
404 }
405 
LoadPerspective(const wxString & perspective_name)406 void MainChatTab::LoadPerspective( const wxString& perspective_name  )
407 {
408     LoadNotebookPerspective( m_chat_tabs, perspective_name );
409 }
410 
SavePerspective(const wxString & perspective_name)411 void MainChatTab::SavePerspective( const wxString& perspective_name )
412 {
413     SaveNotebookPerspective( m_chat_tabs, perspective_name );
414 }
415 
AdvanceSelection(bool forward)416 void MainChatTab::AdvanceSelection( bool forward )
417 {
418 	m_chat_tabs->AdvanceSelection( forward );
419 }
420