1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2004-2011 Angel Vidal ( kry@amule.org )
5// Copyright (c) 2004-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24//
25
26#include <wx/menu.h>
27#include <wx/intl.h>
28
29#include "MuleNotebook.h"	// Interface declarations
30
31#include <common/MenuIDs.h>
32
33DEFINE_LOCAL_EVENT_TYPE(wxEVT_COMMAND_MULENOTEBOOK_PAGE_CLOSING)
34DEFINE_LOCAL_EVENT_TYPE(wxEVT_COMMAND_MULENOTEBOOK_ALL_PAGES_CLOSED)
35
36BEGIN_EVENT_TABLE(CMuleNotebook, wxNotebook)
37	EVT_RIGHT_DOWN(CMuleNotebook::OnRMButton)
38
39	EVT_MENU(MP_CLOSE_TAB,			CMuleNotebook::OnPopupClose)
40	EVT_MENU(MP_CLOSE_ALL_TABS,		CMuleNotebook::OnPopupCloseAll)
41	EVT_MENU(MP_CLOSE_OTHER_TABS,	CMuleNotebook::OnPopupCloseOthers)
42
43	// Madcat - tab closing engine
44	EVT_LEFT_UP(CMuleNotebook::OnMouseLeftRelease)
45	EVT_MOTION(CMuleNotebook::OnMouseMotion)
46END_EVENT_TABLE()
47
48CMuleNotebook::CMuleNotebook( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
49	: wxNotebook(parent, id, pos, size, style, name)
50{
51	m_popup_enable = true;
52	m_popup_widget = NULL;
53}
54
55
56CMuleNotebook::~CMuleNotebook()
57{
58	// Ensure that all notifications gets sent
59	DeleteAllPages();
60}
61
62
63bool CMuleNotebook::DeletePage(int nPage)
64{
65	wxCHECK_MSG((nPage >= 0) && (nPage < (int)GetPageCount()), false,
66		wxT("Trying to delete invalid page-index in CMuleNotebook::DeletePage"));
67
68	// Send out close event
69	wxNotebookEvent evt( wxEVT_COMMAND_MULENOTEBOOK_PAGE_CLOSING, GetId(), nPage );
70	evt.SetEventObject(this);
71	ProcessEvent( evt );
72
73	// and finally remove the actual page
74	bool result = wxNotebook::DeletePage( nPage );
75
76	// Ensure a valid selection
77	if ( GetPageCount() && (int)GetSelection() >= (int)GetPageCount() ) {
78		SetSelection( GetPageCount() - 1 );
79	}
80
81	// Send a page change event to work around wx problem when newly selected page
82	// is identical with deleted page (wx sends a page change event during deletion,
83	// but the control is still the one to be deleted at that moment).
84	if (GetPageCount()) {
85		// Select the tab that took the place of the one we just deleted.
86		size_t page = nPage;
87		// Except if we deleted the last one - then select the one that is last now.
88		if (page == GetPageCount()) {
89			page--;
90		}
91		wxNotebookEvent event( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, GetId(), page );
92		event.SetEventObject(this);
93		ProcessEvent( event );
94	} else {
95	// Send an event when no pages are left open
96		wxNotebookEvent event( wxEVT_COMMAND_MULENOTEBOOK_ALL_PAGES_CLOSED, GetId() );
97		event.SetEventObject(this);
98		ProcessEvent( event );
99	}
100
101	return result;
102}
103
104
105bool CMuleNotebook::DeleteAllPages()
106{
107	Freeze();
108
109	bool result = true;
110	while ( GetPageCount() ) {
111		result &= DeletePage( 0 );
112	}
113
114	Thaw();
115
116	return result;
117}
118
119
120void CMuleNotebook::EnablePopup( bool enable )
121{
122	m_popup_enable = enable;
123}
124
125
126void CMuleNotebook::SetPopupHandler( wxWindow* widget )
127{
128	m_popup_widget = widget;
129}
130
131
132//#warning wxMac does not support selection by right-clicking on tabs!
133void CMuleNotebook::OnRMButton(wxMouseEvent& event)
134{
135	// Cases where we shouldn't be showing a popup-menu.
136	if ( !GetPageCount() || !m_popup_enable ) {
137		event.Skip();
138		return;
139	}
140
141
142// For some reason, gtk1 does a rather poor job when using the HitTest
143	wxPoint eventPoint = event.GetPosition();
144
145	int tab = HitTest(eventPoint);
146	if (tab != wxNOT_FOUND) {
147		SetSelection(tab);
148	} else {
149		event.Skip();
150		return;
151	}
152
153	// Should we send the event to a specific widget?
154	if ( m_popup_widget ) {
155		wxMouseEvent evt = event;
156
157		// Map the coordinates onto the parent
158		wxPoint point = evt.GetPosition();
159		point = ClientToScreen( point );
160		point = m_popup_widget->ScreenToClient( point );
161
162		evt.m_x = point.x;
163		evt.m_y = point.y;
164
165		m_popup_widget->GetEventHandler()->AddPendingEvent( evt );
166	} else {
167		wxMenu menu(_("Close"));
168		menu.Append(MP_CLOSE_TAB, wxString(_("Close tab")));
169		menu.Append(MP_CLOSE_ALL_TABS, wxString(_("Close all tabs")));
170		menu.Append(MP_CLOSE_OTHER_TABS, wxString(_("Close other tabs")));
171
172		PopupMenu( &menu, event.GetPosition() );
173	}
174}
175
176
177void CMuleNotebook::OnPopupClose(wxCommandEvent& WXUNUSED(evt))
178{
179	DeletePage( GetSelection() );
180}
181
182
183void CMuleNotebook::OnPopupCloseAll(wxCommandEvent& WXUNUSED(evt))
184{
185	DeleteAllPages();
186}
187
188
189void CMuleNotebook::OnPopupCloseOthers(wxCommandEvent& WXUNUSED(evt))
190{
191	wxNotebookPage* current = GetPage( GetSelection() );
192
193	for ( int i = GetPageCount() - 1; i >= 0; i-- ) {
194		if ( current != GetPage( i ) )
195			DeletePage( i );
196	}
197}
198
199
200void CMuleNotebook::OnMouseLeftRelease(wxMouseEvent &event)
201{
202
203	if (GetImageList() == NULL) {
204		// This Mulenotebook has no images on tabs, so nothing to do.
205		event.Skip();
206		return;
207	}
208
209	long xpos, ypos;
210	event.GetPosition(&xpos, &ypos);
211
212	long flags = 0;
213	int tab = HitTest(wxPoint(xpos,ypos),&flags);
214
215	if ((tab != -1) &&  (flags == wxNB_HITTEST_ONICON)) {
216		// User did click on a 'x'
217		DeletePage(tab);
218	} else {
219		// Is not a 'x'. Send this event up.
220		event.Skip();
221	}
222
223}
224
225void CMuleNotebook::OnMouseMotion(wxMouseEvent &event)
226{
227
228	if (GetImageList() == NULL) {
229		// This Mulenotebook has no images on tabs, so nothing to do.
230		event.Skip();
231		return;
232	}
233
234	long flags = 0;
235	int tab = HitTest(wxPoint(event.m_x,event.m_y),&flags);
236
237	// Clear the highlight for all tabs.
238	for (int i=0;i<(int)GetPageCount();++i) {
239		SetPageImage(i, 0);
240	}
241
242	if ((tab != -1) &&  (flags == wxNB_HITTEST_ONICON)) {
243		// Mouse is over a 'x'
244		SetPageImage(tab, 1);
245	} else {
246		// Is not a 'x'. Send this event up.
247		event.Skip();
248	}
249
250}
251
252// File_checked_for_headers
253