1
//---------------------------------------------------------------------------------------
2
// LenMus Phonascus: The teacher of music
3
// Copyright (c) 2002-2012 LenMus project
5
// This program is free software; you can redistribute it and/or modify it under the
6
// terms of the GNU General Public License as published by the Free Software Foundation,
7
// either version 3 of the License, or (at your option) any later version.
9
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
10
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11
// PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
// You should have received a copy of the GNU General Public License along with this
14
// program. If not, see <http://www.gnu.org/licenses/>.
16
// For any comment, suggestion or feature request, please contact the manager of
17
// the project at cecilios@users.sourceforge.net
19
//---------------------------------------------------------------------------------------
22
#include "lenmus_document_frame.h"
24
#include "lenmus_canvas.h"
25
#include "lenmus_document_canvas.h"
26
#include "lenmus_string.h"
27
#include "lenmus_midi_server.h"
28
#include "lenmus_dyncontrol.h"
29
#include "lenmus_standard_header.h"
30
#include "lenmus_book_reader.h"
31
#include "lenmus_content_box.h"
32
#include "lenmus_content_box_ctrol.h"
33
#include "lenmus_zip_reader.h"
36
#include <lomse_shapes.h>
39
#include <wx/filename.h>
43
#include <wx/textctrl.h>
44
#include <wx/notebook.h>
45
#include <wx/imaglist.h>
46
#include <wx/treectrl.h>
47
#include <wx/tokenzr.h>
48
#include <wx/wfstream.h>
49
#include <wx/html/htmlwin.h>
50
#include <wx/busyinfo.h>
51
#include <wx/progdlg.h>
52
#include <wx/toolbar.h>
53
#include <wx/fontenum.h>
54
#include <wx/stream.h>
55
#include <wx/filedlg.h>
56
#include <wx/artprov.h>
57
#include <wx/spinctrl.h>
58
#include <wx/dynarray.h>
59
#include <wx/choicdlg.h>
60
#include <wx/settings.h>
66
//--------------------------------------------------------------------------
67
// TextBookHelpTreeItemData (private)
68
//--------------------------------------------------------------------------
70
class TextBookHelpTreeItemData : public wxTreeItemData
73
TextBookHelpTreeItemData(int id) : wxTreeItemData()
80
//--------------------------------------------------------------------------
81
// TextBookHelpHashData (private)
82
//--------------------------------------------------------------------------
84
class TextBookHelpHashData : public wxObject
87
TextBookHelpHashData(int index, long id) : wxObject()
88
{ m_Index = index; m_Id = id;}
89
~TextBookHelpHashData() {}
96
//---------------------------------------------------------------------------
97
// DocumentFrame::m_mergedIndex
98
//---------------------------------------------------------------------------
100
WX_DEFINE_ARRAY_PTR(const BookIndexItem*, wxHtmlHelpDataItemPtrArray);
102
struct TextBookHelpMergedIndexItem
104
TextBookHelpMergedIndexItem *parent;
106
wxHtmlHelpDataItemPtrArray items;
109
WX_DECLARE_OBJARRAY(TextBookHelpMergedIndexItem, TextBookHelpMergedIndex);
110
#include <wx/arrimpl.cpp>
111
WX_DEFINE_OBJARRAY(TextBookHelpMergedIndex)
113
//void DocumentFrame::UpdateMergedIndex()
115
// // Updates "merged index" structure that combines indexes of all books
116
// // into better searchable structure
118
// delete m_mergedIndex;
119
// m_mergedIndex = LENMUS_NEW TextBookHelpMergedIndex;
120
// TextBookHelpMergedIndex& merged = *m_mergedIndex;
122
// const BookIndexArray& items = m_pBookReader->GetIndexArray();
123
// size_t len = items.size();
125
// TextBookHelpMergedIndexItem *history[128] = {NULL};
127
// for (size_t i = 0; i < len; i++)
129
// const BookIndexItem* pItem = items[i];
130
// wxASSERT_MSG( pItem->level < 128, _T("nested index entries too deep") );
132
// if (history[pItem->level] &&
133
// history[pItem->level]->items[0]->title == pItem->title)
135
// // same index entry as previous one, update list of items
136
// history[pItem->level]->items.Add(pItem);
140
// // LENMUS_NEW index entry
141
// TextBookHelpMergedIndexItem *mi = LENMUS_NEW TextBookHelpMergedIndexItem();
142
// mi->name = pItem->GetIndentedName();
143
// mi->items.Add(pItem);
144
// mi->parent = (pItem->level == 0) ? NULL : history[pItem->level - 1];
145
// history[pItem->level] = mi;
151
//=======================================================================================
152
// DocumentLoader implementation
153
//=======================================================================================
154
DocumentLoader::DocumentLoader(ContentWindow* parent, ApplicationScope& appScope,
156
: m_pContentWindow(parent)
157
, m_appScope(appScope)
162
//---------------------------------------------------------------------------------------
163
CanvasInterface* DocumentLoader::create_canvas(const string& filename, int viewType)
165
//use filename (without path) as page title
166
wxFileName document( to_wx_string(filename) );
167
bool fIsBook = (document.GetExt().Upper() == _T("LMB"));
171
DocumentFrame* pCanvas = LENMUS_NEW DocumentFrame(m_pContentWindow, m_appScope, m_lomse);
172
m_pContentWindow->add_canvas(pCanvas, document.GetName());
173
pCanvas->display_document(filename, viewType);
178
DocumentCanvas* pCanvas = LENMUS_NEW DocumentCanvas(m_pContentWindow, m_appScope, m_lomse);
179
m_pContentWindow->add_canvas(pCanvas, document.GetName());
180
pCanvas->display_document(filename, viewType);
186
//=======================================================================================
187
// DocumentFrame implementation
188
//=======================================================================================
190
BEGIN_EVENT_TABLE(DocumentFrame, wxSplitterWindow)
191
EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY, DocumentFrame::on_splitter_moved)
192
LM_EVT_PAGE_REQUEST(DocumentFrame::on_page_change_requested)
195
DocumentFrame::DocumentFrame(ContentWindow* parent, ApplicationScope& appScope,
197
: wxSplitterWindow(parent, wxNewId(), wxDefaultPosition,
198
wxDefaultSize, 0, _T("Canvas"))
199
, CanvasInterface(parent)
200
, m_appScope(appScope)
204
, m_pBookReader(NULL)
208
//---------------------------------------------------------------------------------------
209
DocumentFrame::~DocumentFrame()
211
delete m_pBookReader;
216
////---------------------------------------------------------------------------------------
217
//void DocumentFrame::on_show_toc(wxCommandEvent& WXUNUSED(event) )
221
// m_left->Show(true);
222
// m_right->Show(true);
223
// SplitVertically(m_left, m_right, 100);
226
////---------------------------------------------------------------------------------------
227
//void DocumentFrame::on_hide_toc(wxCommandEvent& WXUNUSED(event) )
233
//---------------------------------------------------------------------------------------
234
void DocumentFrame::on_page_change_requested(PageRequestEvent& event)
236
wxString url = to_wx_string(event.get_url());
240
//---------------------------------------------------------------------------------------
241
void DocumentFrame::create_toc_pane()
243
m_left = LENMUS_NEW BookContentBox(this, this, m_appScope, wxID_ANY, wxDefaultPosition,
244
wxDefaultSize, 0, _T("The TOC"));
245
m_left->CreateContents(m_pBookReader);
248
//---------------------------------------------------------------------------------------
249
void DocumentFrame::create_content_pane(const string& filename)
251
m_right = LENMUS_NEW DocumentWindow(this, m_appScope, m_lomse);
255
//---------------------------------------------------------------------------------------
256
void DocumentFrame::create_content_pane(int iTocItem)
258
m_right = LENMUS_NEW DocumentWindow(this, m_appScope, m_lomse);
262
//---------------------------------------------------------------------------------------
263
ImoScore* DocumentFrame::get_active_score()
266
return m_right->get_active_score();
271
//---------------------------------------------------------------------------------------
272
Interactor* DocumentFrame::get_interactor()
275
return m_right->get_interactor();
280
//---------------------------------------------------------------------------------------
281
void DocumentFrame::display_document(const string& filename, int viewType)
283
wxFileName document( to_wx_string(filename) );
284
bool fIsBook = (document.GetExt().Upper() == _T("LMB"));
286
m_bookPath = document.GetFullPath();
291
m_pBookReader = LENMUS_NEW BookReader();
292
if (!m_pBookReader->AddBook(document))
294
//TODO better error handling
295
wxMessageBox(wxString::Format(_("Failed adding book %s"),
296
document.GetFullPath().c_str() ));
300
create_content_pane(0);
305
wxSize size = this->GetClientSize();
306
int leftPixels = size.GetWidth() / 4;
307
SplitVertically(m_left, m_right, leftPixels);
312
create_content_pane(filename);
317
//---------------------------------------------------------------------------------------
318
void DocumentFrame::on_hyperlink_event(SpEventInfo pEvent)
320
SpEventMouse pEv = boost::static_pointer_cast<EventMouse>(pEvent);
321
ImoLink* pLink = static_cast<ImoLink*>( pEv->get_imo_object() );
322
wxString url = to_wx_string( pLink->get_url() );
325
if (url.StartsWith(_T("#LenMusPage/"), &pagename))
326
change_to_page(pagename);
328
::wxLaunchDefaultBrowser(url);
331
//---------------------------------------------------------------------------------------
332
void DocumentFrame::change_to_page(wxString& pagename)
334
wxString fullpath = m_pBookReader->FindPageByName(pagename);
335
if (fullpath != _T(""))
337
load_page( to_std_string(fullpath) );
338
m_right->Refresh(false /* don't erase background */);
342
wxString msg = wxString::Format(_T("Invalid link='%s'\nPage='%s' not found."),
343
pagename.c_str(), fullpath.c_str() );
348
//---------------------------------------------------------------------------------------
349
void DocumentFrame::load_page(int iTocItem)
351
wxLogMessage(_T("DocumentFrame::load_page (by toc item, item %d) %s"), iTocItem, GetLabel().c_str());
352
wxString fullpath = get_path_for_toc_item(iTocItem);
353
wxLogMessage(_T("[DocumentFrame::load_page] page: <%s>"), fullpath.c_str());
354
load_page( to_std_string(fullpath) );
357
//---------------------------------------------------------------------------------------
358
void DocumentFrame::load_page(const string& filename)
360
wxLogMessage(_T("DocumentFrame::load_page (by filename) %s. Filename='%s'"), GetLabel().c_str(), to_wx_string(filename).c_str());
361
//Code commented out and replaced by following code because it causes a rare problem
362
//when returning back from exercise 1 in L1_MusicReading_accidentals.lms
364
//int viewType = ViewFactory::k_view_vertical_book;
365
// m_right->display_document(filename, viewType);
367
if (!filename.empty())
369
LdpZipReader reader(filename);
370
int viewType = ViewFactory::k_view_vertical_book;
371
string title = "test";
372
m_right->display_document(reader, viewType, title);
376
//---------------------------------------------------------------------------------------
377
wxString DocumentFrame::get_path_for_toc_item(int iItem)
379
const BookIndexArray& contents = m_pBookReader->GetContentsArray();
380
if (!contents[iItem]->page.empty())
381
return contents[iItem]->GetFullPath();
383
return wxEmptyString;
386
//---------------------------------------------------------------------------------------
387
void DocumentFrame::on_splitter_moved(wxSplitterEvent& WXUNUSED(event))
389
wxLogMessage(_T("DocumentFrame::on_splitter_moved %s"), GetLabel().c_str());
391
m_right->zoom_fit_width();