~s-cecilio/lenmus/v5.3

« back to all changes in this revision

Viewing changes to src/app/lenmus_document_canvas.cpp

  • Committer: cecilios
  • Date: 2012-09-11 16:59:18 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:branches/TRY-5.0:730
Paths: fixed problem with installation folders. Fixed Chinese ISO language code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//---------------------------------------------------------------------------------------
 
2
//    LenMus Phonascus: The teacher of music
 
3
//    Copyright (c) 2002-2012 LenMus project
 
4
//
 
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.
 
8
//
 
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.
 
12
//
 
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/>.
 
15
//
 
16
//    For any comment, suggestion or feature request, please contact the manager of
 
17
//    the project at cecilios@users.sourceforge.net
 
18
//
 
19
//---------------------------------------------------------------------------------------
 
20
 
 
21
//lenmus
 
22
#include "lenmus_document_canvas.h"
 
23
#include "lenmus_standard_header.h"
 
24
 
 
25
#include "lenmus_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_status_reporter.h"
 
31
#include "lenmus_dlg_debug.h"
 
32
 
 
33
//lomse
 
34
#include <lomse_shapes.h>
 
35
#include <lomse_ldp_exporter.h>
 
36
#include <lomse_lmd_exporter.h>
 
37
#include <lomse_score_player.h>
 
38
#include <lomse_midi_table.h>
 
39
#include <lomse_player_gui.h>
 
40
 
 
41
//wxWidgets
 
42
#include <wx/filename.h>
 
43
 
 
44
//other
 
45
#include <sstream>
 
46
#include <stdexcept>
 
47
using namespace std;
 
48
 
 
49
namespace lenmus
 
50
{
 
51
 
 
52
//=======================================================================================
 
53
// DocumentWindow implementation
 
54
//=======================================================================================
 
55
 
 
56
BEGIN_EVENT_TABLE(DocumentWindow, wxWindow)
 
57
    EVT_SIZE(DocumentWindow::on_size)
 
58
    EVT_MOUSE_EVENTS(DocumentWindow::on_mouse_event)
 
59
        EVT_KEY_DOWN(DocumentWindow::on_key_event)
 
60
    EVT_PAINT(DocumentWindow::on_paint)
 
61
    EVT_SCROLLWIN(DocumentWindow::on_scroll)
 
62
    LM_EVT_SCORE_HIGHLIGHT(DocumentWindow::on_visual_highlight)
 
63
    EVT_ERASE_BACKGROUND(DocumentWindow::on_erase_background)
 
64
    LM_EVT_END_OF_PLAYBACK(DocumentWindow::on_end_of_playback)
 
65
END_EVENT_TABLE()
 
66
 
 
67
DocumentWindow::DocumentWindow(wxWindow* parent, ApplicationScope& appScope,
 
68
                         LomseDoorway& lomse)
 
69
    : wxWindow(parent, wxNewId(), wxDefaultPosition, wxDefaultSize,
 
70
               wxVSCROLL | wxHSCROLL | wxALWAYS_SHOW_SB |
 
71
               wxFULL_REPAINT_ON_RESIZE, _T("DocumentWindow") )
 
72
    , m_appScope(appScope)
 
73
    , m_lomse(lomse)
 
74
    , m_pPresenter(NULL)
 
75
    , m_pInteractor(NULL)
 
76
    , m_pDoc(NULL)
 
77
    , m_buffer(NULL)
 
78
    , m_filename(_T(""))
 
79
    , m_zoomMode(k_zoom_fit_width)
 
80
    , m_fIgnoreOnSize(false)
 
81
    , m_fFirstPaint(true)
 
82
{
 
83
    Hide();     //keep hidden until necessary, to avoid useless repaints
 
84
}
 
85
 
 
86
//---------------------------------------------------------------------------------------
 
87
DocumentWindow::~DocumentWindow()
 
88
{
 
89
    ScorePlayer* pPlayer  = m_appScope.get_score_player();
 
90
    pPlayer->stop();
 
91
 
 
92
    //delete the presenter. This will also delete the Document
 
93
    delete m_pPresenter;
 
94
    //TO_FIX: delete presenter deletes all interactors and the document. But here we are
 
95
    //just atempting to delete one view, not the document and all its views.
 
96
 
 
97
    m_pInteractor = NULL;
 
98
    delete_rendering_buffer();
 
99
}
 
100
 
 
101
//---------------------------------------------------------------------------------------
 
102
void DocumentWindow::wrapper_play_score(void* pThis, SpEventInfo pEvent)
 
103
{
 
104
    //wxLogMessage(_T("callback: wrapper_play_score"));
 
105
    static_cast<DocumentWindow*>(pThis)->on_play_score(pEvent);
 
106
}
 
107
 
 
108
//---------------------------------------------------------------------------------------
 
109
void DocumentWindow::on_play_score(SpEventInfo pEvent)
 
110
{
 
111
    switch (pEvent->get_event_type())
 
112
    {
 
113
        case k_do_play_score_event:
 
114
            play_score(pEvent);
 
115
            return;
 
116
 
 
117
        case k_pause_score_event:
 
118
            play_pause();
 
119
            return;
 
120
 
 
121
        case k_stop_playback_event:
 
122
        default:
 
123
            play_stop();
 
124
            return;
 
125
    }
 
126
}
 
127
 
 
128
//---------------------------------------------------------------------------------------
 
129
void DocumentWindow::play_score(SpEventInfo pEvent)
 
130
{
 
131
    SpEventPlayScore pEv = boost::static_pointer_cast<EventPlayScore>(pEvent);
 
132
    ImoScore* pScore = pEv->get_score();
 
133
    ScorePlayer* pPlayer  = m_appScope.get_score_player();
 
134
    PlayerGui* pPlayerGui = pEv->get_player();
 
135
 
 
136
    pPlayer->load_score(pScore, pEv->get_player());
 
137
 
 
138
    //initialize with default options
 
139
    bool fVisualTracking = true;
 
140
    long nMM = pPlayerGui->get_metronome_mm();
 
141
 
 
142
    pPlayer->play(fVisualTracking, nMM, m_pInteractor);
 
143
}
 
144
 
 
145
//---------------------------------------------------------------------------------------
 
146
void DocumentWindow::play_stop()
 
147
{
 
148
    ScorePlayer* pPlayer  = m_appScope.get_score_player();
 
149
    pPlayer->stop();
 
150
}
 
151
 
 
152
//---------------------------------------------------------------------------------------
 
153
void DocumentWindow::play_pause()
 
154
{
 
155
    ScorePlayer* pPlayer  = m_appScope.get_score_player();
 
156
    pPlayer->pause();
 
157
}
 
158
 
 
159
//---------------------------------------------------------------------------------------
 
160
void DocumentWindow::wrapper_update_window(void* pThis, SpEventInfo pEvent)
 
161
{
 
162
    //wxLogMessage(_T("callback: wrapper_update_window"));
 
163
    static_cast<DocumentWindow*>(pThis)->update_window();
 
164
}
 
165
 
 
166
//---------------------------------------------------------------------------------------
 
167
void DocumentWindow::update_window()
 
168
{
 
169
    // Invoking update_window() results in just putting immediately the content
 
170
    // of the currently rendered buffer to the window without neither calling
 
171
    // any lomse methods nor generating any events (i.e. window on_paint)
 
172
 
 
173
    //wxLogMessage(_T("update_window %0x"), this);
 
174
 
 
175
    wxClientDC dc(this);
 
176
    copy_buffer_on_dc(dc);
 
177
}
 
178
 
 
179
//---------------------------------------------------------------------------------------
 
180
void DocumentWindow::copy_buffer_on_dc(wxDC& dc)
 
181
{
 
182
    //wxLogMessage(_T("copy_buffer_on_dc %0x"), this);
 
183
    if (!m_buffer || !m_buffer->IsOk())
 
184
        return;
 
185
 
 
186
    wxBitmap bitmap(*m_buffer);
 
187
    dc.DrawBitmap(bitmap, 0, 0, false /* don't use mask */);
 
188
 
 
189
    //DEBUG: info about rendering time -------------------------------------
 
190
    double renderTime = m_pInteractor->gmodel_rendering_time();
 
191
    double buildTime = m_pInteractor->gmodel_build_time();
 
192
    wxString msg = wxString::Format(_T("Build time=%.3f, render time=%.3f ms, ticks per second=%d "),
 
193
                                    buildTime, renderTime, CLOCKS_PER_SEC );
 
194
    StatusReporter* pStatus = m_appScope.get_status_reporter();
 
195
    pStatus->report_status(msg);
 
196
    //END DEBUG ------------------------------------------------------------
 
197
 
 
198
    SetFocus();
 
199
}
 
200
 
 
201
//---------------------------------------------------------------------------------------
 
202
void DocumentWindow::on_visual_highlight(lmScoreHighlightEvent& event)
 
203
{
 
204
    SpEventScoreHighlight pEv = event.get_lomse_event();
 
205
    Interactor* pInteractor = get_interactor();
 
206
    pInteractor->on_visual_highlight(pEv);
 
207
}
 
208
 
 
209
//---------------------------------------------------------------------------------------
 
210
void DocumentWindow::on_end_of_playback(lmEndOfPlaybackEvent& event)
 
211
{
 
212
    wxLogMessage(_T("[DocumentWindow::on_end_of_playback]"));
 
213
    SpEventPlayScore pEv = event.get_lomse_event();
 
214
    Interactor* pInteractor = get_interactor();
 
215
    pInteractor->send_end_of_play_event(pEv->get_score(), pEv->get_player());
 
216
}
 
217
 
 
218
//---------------------------------------------------------------------------------------
 
219
void DocumentWindow::display_document(LdpReader& reader, int viewType,
 
220
                                      const string& title)
 
221
{
 
222
    //wxLogMessage(_T("display_document %0x"), this);
 
223
 
 
224
    //get lomse reporter
 
225
    ostringstream& reporter = m_appScope.get_lomse_reporter();
 
226
    reporter.str(std::string());      //remove any previous content
 
227
 
 
228
    try
 
229
    {
 
230
        ::wxSetCursor(*wxHOURGLASS_CURSOR);
 
231
        delete m_pPresenter;
 
232
        m_pPresenter = m_lomse.open_document(viewType, reader, reporter);
 
233
        set_zoom_mode(k_zoom_fit_width);
 
234
        do_display(reporter);
 
235
    }
 
236
    catch(std::exception& e)
 
237
    {
 
238
        wxMessageBox( to_wx_string(e.what()) );
 
239
    }
 
240
}
 
241
 
 
242
//---------------------------------------------------------------------------------------
 
243
void DocumentWindow::display_document(const string& filename, int viewType)
 
244
{
 
245
    wxString sF = to_wx_string(filename);
 
246
    wxLogMessage(_T("display_document %s"), sF.c_str());
 
247
 
 
248
    //get lomse reporter
 
249
    ostringstream& reporter = m_appScope.get_lomse_reporter();
 
250
    reporter.str(std::string());      //remove any previous content
 
251
 
 
252
    try
 
253
    {
 
254
        ::wxSetCursor(*wxHOURGLASS_CURSOR);
 
255
        delete m_pPresenter;
 
256
        m_pPresenter = m_lomse.open_document(viewType, filename, reporter);
 
257
 
 
258
        //use filename (without path) as page title
 
259
        wxFileName oFN( to_wx_string(filename) );
 
260
        m_filename = oFN.GetFullName();
 
261
 
 
262
        set_zoom_mode(k_zoom_fit_width);
 
263
        do_display(reporter);
 
264
    }
 
265
    catch(std::exception& e)
 
266
    {
 
267
        wxMessageBox( to_wx_string(e.what()) );
 
268
    }
 
269
}
 
270
 
 
271
//---------------------------------------------------------------------------------------
 
272
void DocumentWindow::display_errors(ostringstream& reporter)
 
273
{
 
274
    if (!reporter.str().empty())
 
275
    {
 
276
        wxString msg = to_wx_string( reporter.str() );
 
277
        wxString title = _T("Errors in file ");
 
278
        title += m_filename;
 
279
        DlgDebug dlg(this, title, msg, true /*show 'Save' button*/);
 
280
        dlg.ShowModal();
 
281
    }
 
282
    reporter.str(std::string());      //remove any previous content
 
283
}
 
284
 
 
285
//---------------------------------------------------------------------------------------
 
286
void DocumentWindow::do_display(ostringstream& reporter)
 
287
{
 
288
    //wxLogMessage(_T("do_display %0x"), this);
 
289
 
 
290
    //get the pointers to the relevant components
 
291
    m_pDoc = m_pPresenter->get_document();
 
292
    m_pInteractor = m_pPresenter->get_interactor(0);
 
293
 
 
294
    //connect the View with the window buffer
 
295
    m_pInteractor->set_rendering_buffer(&m_rbuf_window);
 
296
 
 
297
    //register to receive desired events
 
298
    m_pInteractor->add_event_handler(k_update_window_event, this, wrapper_update_window);
 
299
    m_pInteractor->add_event_handler(k_do_play_score_event, this, wrapper_play_score);
 
300
    m_pInteractor->add_event_handler(k_pause_score_event, this, wrapper_play_score);
 
301
    m_pInteractor->add_event_handler(k_stop_playback_event, this, wrapper_play_score);
 
302
 
 
303
    //set viewport and scale
 
304
    m_fFirstPaint = true;
 
305
    //create_rendering_buffer();
 
306
    //determine_scroll_space_size();
 
307
    //m_pInteractor->new_viewport(-m_xMargin, -m_yMargin);
 
308
    //adjust_scale_and_scrollbars();
 
309
 
 
310
    //AWARE: after creating a pane and loading content on it, wxAuiNotebook / wxFrame
 
311
    //will issue an on_size() followed by an on_paint. Therefore, do not force a
 
312
    //a repaint here as it will be redundant with the coming events
 
313
    Refresh(false /* don't erase background */);
 
314
 
 
315
    ////ensure that the rendering buffer is created
 
316
    //if (m_nBufWidth == 0 || m_nBufHeight == 0)
 
317
    //    create_rendering_buffer();
 
318
 
 
319
    display_errors(reporter);
 
320
}
 
321
 
 
322
//---------------------------------------------------------------------------------------
 
323
void DocumentWindow::on_size(wxSizeEvent& WXUNUSED(event))
 
324
{
 
325
    //wxLogMessage(_T("on_size %s. Visible=%d"), GetLabel().c_str(), (IsShown() ? 1 : 0) );
 
326
 
 
327
    if (!m_pInteractor) return;
 
328
    if (m_fIgnoreOnSize) return;
 
329
 
 
330
    adjust_scale_and_scrollbars();
 
331
}
 
332
 
 
333
//---------------------------------------------------------------------------------------
 
334
void DocumentWindow::on_paint(wxPaintEvent& WXUNUSED(event))
 
335
{
 
336
    //wxLogMessage(_T("on_paint %s. Visible=%d"), GetLabel().c_str(), (IsShown() ? 1 : 0) );
 
337
 
 
338
    //AWARE: According wxWidgets documentation, any paint event handler must always
 
339
    //create a wxPaintDC object, even if not used. Otherwise, under MS Windows,
 
340
    // refreshing for this and other windows will go wrong.
 
341
    wxPaintDC dc(this);
 
342
 
 
343
    if (IsShown() && m_pInteractor)
 
344
    {
 
345
        if (m_fFirstPaint)
 
346
        {
 
347
            m_fFirstPaint = false;
 
348
            create_rendering_buffer();
 
349
            determine_scroll_space_size();
 
350
            adjust_scale_and_scrollbars();
 
351
            m_pInteractor->new_viewport(-m_xMargin, -m_yMargin);
 
352
        }
 
353
        update_rendering_buffer();
 
354
        copy_buffer_on_dc(dc);
 
355
        ::wxSetCursor(*wxSTANDARD_CURSOR);
 
356
    }
 
357
}
 
358
 
 
359
//---------------------------------------------------------------------------------------
 
360
void DocumentWindow::on_mouse_event(wxMouseEvent& event)
 
361
{
 
362
    if (!m_pInteractor) return;
 
363
 
 
364
    wxEventType nEventType = event.GetEventType();
 
365
    wxPoint pos = event.GetPosition();
 
366
    unsigned flags = get_mouse_flags(event);
 
367
 
 
368
    if (nEventType == wxEVT_LEFT_DOWN)
 
369
    {
 
370
        flags |= k_mouse_left;
 
371
        m_pInteractor->on_mouse_button_down(pos.x, pos.y, flags);
 
372
    }
 
373
    else if (nEventType == wxEVT_LEFT_UP)
 
374
    {
 
375
        flags |= k_mouse_left;
 
376
        m_pInteractor->on_mouse_button_up(pos.x, pos.y, flags);
 
377
    }
 
378
    else if (nEventType == wxEVT_RIGHT_DOWN)
 
379
    {
 
380
        flags |= k_mouse_right;
 
381
        m_pInteractor->on_mouse_button_down(pos.x, pos.y, flags);
 
382
    }
 
383
    else if (nEventType == wxEVT_RIGHT_UP)
 
384
    {
 
385
        flags |= k_mouse_right;
 
386
        m_pInteractor->on_mouse_button_up(pos.x, pos.y, flags);
 
387
    }
 
388
    else if (nEventType == wxEVT_MOUSEWHEEL)
 
389
    {
 
390
        if (flags && k_kbd_ctrl)
 
391
        {
 
392
            // Ctrl + mouse wheel --> zoom in/out
 
393
            if (event.GetWheelRotation() > 0)
 
394
                zoom_in();
 
395
            else
 
396
                zoom_out();
 
397
            Refresh(false /* don't erase background */);
 
398
        }
 
399
        else
 
400
        {
 
401
            //scroll up/down
 
402
            if (event.GetWheelRotation() > 0)
 
403
                scroll_line_up();
 
404
            else
 
405
                scroll_line_down();
 
406
            adjust_scrollbars();
 
407
        }
 
408
    }
 
409
    else if (nEventType == wxEVT_MOTION)
 
410
        m_pInteractor->on_mouse_move(pos.x, pos.y, flags);
 
411
}
 
412
 
 
413
////---------------------------------------------------------------------------------------
 
414
//void DocumentWindow::on_hyperlink_event(SpEventInfo pEvent)
 
415
//{
 
416
//    SpEventMouse pEv = boost::static_pointer_cast<EventMouse>(pEvent);
 
417
//    ImoLink* pLink = static_cast<ImoLink*>( pEv->get_imo_object() );
 
418
//    string& url = pLink->get_url();
 
419
//    wxString msg = wxString::Format(_T("[DocumentWindow::on_hyperlink_event] link='%s'"),
 
420
//                                    to_wx_string(url).c_str() );
 
421
//    wxMessageBox(msg);
 
422
//
 
423
////    //extract filename
 
424
////    //#LenMusPage/L1_MusicReading_mr1_thm12_E1.lms
 
425
////    string ebook = "/datos/USR/Desarrollo_wx/lenmus/locale/en/books/GeneralExercises.lmb#zip:";
 
426
////    string page = "GeneralExercises_ClefsReading.lms";
 
427
////    display_document(ebook + page, ViewFactory::k_view_vertical_book);
 
428
//}
 
429
 
 
430
//---------------------------------------------------------------------------------------
 
431
unsigned DocumentWindow::get_mouse_flags(wxMouseEvent& event)
 
432
{
 
433
    unsigned flags = 0;
 
434
    if (event.LeftIsDown())     flags |= k_mouse_left;
 
435
    if (event.RightIsDown())    flags |= k_mouse_right;
 
436
    if (event.MiddleDown())     flags |= k_mouse_middle;
 
437
    if (event.ShiftDown())      flags |= k_kbd_shift;
 
438
    if (event.AltDown())        flags |= k_kbd_alt;
 
439
    if (event.ControlDown())    flags |= k_kbd_ctrl;
 
440
    return flags;
 
441
}
 
442
 
 
443
//---------------------------------------------------------------------------------------
 
444
unsigned DocumentWindow::get_keyboard_flags(wxKeyEvent& event)
 
445
{
 
446
    unsigned flags = 0;
 
447
    if (event.ShiftDown())   flags |= k_kbd_shift;
 
448
    if (event.AltDown()) flags |= k_kbd_alt;
 
449
    if (event.ControlDown()) flags |= k_kbd_ctrl;
 
450
    return flags;
 
451
}
 
452
 
 
453
//---------------------------------------------------------------------------------------
 
454
void DocumentWindow::on_document_updated()
 
455
{
 
456
    if (!m_pInteractor) return;
 
457
 
 
458
    //wxLogMessage(_T("on_document_updated %0x"), this);
 
459
    m_pInteractor->on_document_reloaded();
 
460
    Refresh(false /* don't erase background */);
 
461
}
 
462
 
 
463
//---------------------------------------------------------------------------------------
 
464
void DocumentWindow::update_rendering_buffer()
 
465
{
 
466
    //wxLogMessage(_T("update_rendering_buffer %0x"), this);
 
467
 
 
468
    if (m_pInteractor && (m_pInteractor->view_needs_repaint() || !is_buffer_ok()) )
 
469
    {
 
470
        create_rendering_buffer();
 
471
        m_pInteractor->redraw_bitmap();
 
472
    }
 
473
}
 
474
 
 
475
//---------------------------------------------------------------------------------------
 
476
bool DocumentWindow::is_buffer_ok()
 
477
{
 
478
    wxSize size = this->GetClientSize();
 
479
    int width = size.GetWidth();
 
480
    int height = size.GetHeight();
 
481
 
 
482
    return  m_buffer
 
483
        &&  m_buffer->IsOk()
 
484
        && m_nBufWidth == width
 
485
        && m_nBufHeight == height;
 
486
}
 
487
 
 
488
//---------------------------------------------------------------------------------------
 
489
void DocumentWindow::delete_rendering_buffer()
 
490
{
 
491
    delete m_buffer;
 
492
}
 
493
 
 
494
//---------------------------------------------------------------------------------------
 
495
void DocumentWindow::create_rendering_buffer()
 
496
{
 
497
    //creates a bitmap of specified size and associates it to the rendering
 
498
    //buffer for the view. Any existing buffer is automatically deleted
 
499
 
 
500
    //I will use a wxImage as the rendering  buffer. wxImage is platform independent
 
501
    //and its buffer is an array of characters in RGBRGBRGB... format,  in the
 
502
    //top-to-bottom, left-to-right order. That is, the first RGB triplet corresponds
 
503
    //to the first pixel of the first row; the second RGB triplet, to the second
 
504
    //pixel of the first row, and so on until the end of the first row,
 
505
    //with second row following after it and so on.
 
506
 
 
507
    #define BYTES_PP 3      // Bytes per pixel
 
508
 
 
509
    wxSize size = this->GetClientSize();
 
510
    int width = size.GetWidth();
 
511
    int height = size.GetHeight();
 
512
    //wxLogMessage(_T("create_rendering_buffer %s, w=%d, h=%d"),
 
513
    //             GetLabel().c_str(), width, height);
 
514
 
 
515
    // allocate a LENMUS_NEW rendering buffer
 
516
    delete m_buffer;            //delete any previous buffer
 
517
    m_nBufWidth = width;
 
518
    m_nBufHeight = height;
 
519
    m_buffer = LENMUS_NEW wxImage(width, height);
 
520
 
 
521
    int stride = m_nBufWidth * BYTES_PP;        //number of bytes per row
 
522
 
 
523
    m_pdata = m_buffer->GetData();
 
524
    m_rbuf_window.attach(m_pdata, m_nBufWidth, m_nBufHeight, stride);
 
525
}
 
526
 
 
527
//---------------------------------------------------------------------------------------
 
528
void DocumentWindow::on_key_event(wxKeyEvent& event)
 
529
{
 
530
    if (!m_pInteractor) return;
 
531
 
 
532
    int nKeyCode = event.GetKeyCode();
 
533
    unsigned flags = get_keyboard_flags(event);
 
534
 
 
535
    //fix ctrol+key codes
 
536
    if (nKeyCode > 0 && nKeyCode < 27)
 
537
    {
 
538
        nKeyCode += int('A') - 1;
 
539
        flags |= k_kbd_ctrl;
 
540
    }
 
541
 
 
542
    //process key
 
543
    switch (nKeyCode)
 
544
    {
 
545
        case WXK_SHIFT:
 
546
        case WXK_ALT:
 
547
        case WXK_CONTROL:
 
548
            return;      //do nothing
 
549
 
 
550
                default:
 
551
                        on_key(event.GetX(), event.GetY(), nKeyCode, flags);;
 
552
        }
 
553
}
 
554
 
 
555
//---------------------------------------------------------------------------------------
 
556
void DocumentWindow::set_debug_draw_box(int boxType)
 
557
{
 
558
    m_pInteractor->reset_boxes_to_draw();
 
559
    m_pInteractor->set_box_to_draw(boxType);
 
560
 
 
561
    Refresh(false /* don't erase background */);
 
562
}
 
563
 
 
564
//---------------------------------------------------------------------------------------
 
565
void DocumentWindow::on_key(int x, int y, unsigned key, unsigned flags)
 
566
{
 
567
    switch (key)
 
568
    {
 
569
        case '1':
 
570
            m_pInteractor->reset_boxes_to_draw();
 
571
            m_pInteractor->set_rendering_option(k_option_draw_box_doc_page_content, true);
 
572
            break;
 
573
        case '2':
 
574
            m_pInteractor->reset_boxes_to_draw();
 
575
            m_pInteractor->set_rendering_option(k_option_draw_box_container, true);
 
576
            break;
 
577
        case '3':
 
578
            m_pInteractor->reset_boxes_to_draw();
 
579
            m_pInteractor->set_rendering_option(k_option_draw_box_system, true);
 
580
            break;
 
581
        case '4':
 
582
            m_pInteractor->reset_boxes_to_draw();
 
583
            m_pInteractor->set_rendering_option(k_option_draw_box_slice, true);
 
584
            break;
 
585
        case '5':
 
586
            m_pInteractor->reset_boxes_to_draw();
 
587
            m_pInteractor->set_rendering_option(k_option_draw_box_slice_instr, true);
 
588
            break;
 
589
        case '6':
 
590
            m_pInteractor->reset_boxes_to_draw();
 
591
            m_pInteractor->set_rendering_option(k_option_draw_box_inline_flag, true);
 
592
            break;
 
593
        case '8':
 
594
            m_pInteractor->switch_task(TaskFactory::k_task_drag_view);
 
595
            break;
 
596
        case '9':
 
597
            m_pInteractor->switch_task(TaskFactory::k_task_selection);
 
598
            break;
 
599
        case '0':
 
600
            m_pInteractor->reset_boxes_to_draw();
 
601
            break;
 
602
        case '+':
 
603
            if (flags && k_kbd_ctrl)
 
604
                zoom_in();
 
605
            break;
 
606
        case '-':
 
607
            if (flags && k_kbd_ctrl)
 
608
                zoom_out();
 
609
            break;
 
610
        default:
 
611
            return;
 
612
    }
 
613
 
 
614
    Refresh(false /* don't erase background */);
 
615
}
 
616
 
 
617
//---------------------------------------------------------------------------------------
 
618
void DocumentWindow::zoom_to(double scale)
 
619
{
 
620
    if (!m_pInteractor) return;
 
621
 
 
622
    //set zoom, centered on window center
 
623
    wxSize size = this->GetClientSize();
 
624
    m_pInteractor->set_scale(scale, size.GetWidth()/2, 0);
 
625
    m_zoomMode = k_zoom_user;
 
626
    adjust_scrollbars();
 
627
}
 
628
 
 
629
//---------------------------------------------------------------------------------------
 
630
void DocumentWindow::zoom_in()
 
631
{
 
632
    if (!m_pInteractor) return;
 
633
 
 
634
    wxSize size = this->GetClientSize();
 
635
    m_pInteractor->zoom_in(size.GetWidth()/2, 0);
 
636
    m_zoomMode = k_zoom_user;
 
637
    adjust_scrollbars();
 
638
}
 
639
 
 
640
//---------------------------------------------------------------------------------------
 
641
void DocumentWindow::zoom_out()
 
642
{
 
643
    if (!m_pInteractor) return;
 
644
 
 
645
    wxSize size = this->GetClientSize();
 
646
    m_pInteractor->zoom_out(size.GetWidth()/2, 0);
 
647
    m_zoomMode = k_zoom_user;
 
648
    adjust_scrollbars();
 
649
}
 
650
 
 
651
//---------------------------------------------------------------------------------------
 
652
void DocumentWindow::zoom_fit_width()
 
653
{
 
654
    if (!m_pInteractor) return;
 
655
 
 
656
    //wxLogMessage(_T("zoom_fit_width %0x"), this);
 
657
    wxSize size = this->GetClientSize();
 
658
    m_pInteractor->zoom_fit_width(size.GetWidth());
 
659
    m_zoomMode = k_zoom_fit_width;
 
660
    adjust_scrollbars();
 
661
}
 
662
 
 
663
//---------------------------------------------------------------------------------------
 
664
void DocumentWindow::zoom_fit_full()
 
665
{
 
666
    if (!m_pInteractor) return;
 
667
 
 
668
    //wxLogMessage(_T("zoom_fit_full %0x"), this);
 
669
    wxSize size = this->GetClientSize();
 
670
    m_pInteractor->zoom_fit_full(size.GetWidth(), size.GetHeight());
 
671
    m_zoomMode = k_zoom_fit_full;
 
672
    adjust_scrollbars();
 
673
}
 
674
 
 
675
//---------------------------------------------------------------------------------------
 
676
ImoScore* DocumentWindow::get_active_score()
 
677
{
 
678
    return m_pDoc->get_score(0);
 
679
}
 
680
 
 
681
//---------------------------------------------------------------------------------------
 
682
void DocumentWindow::open_test_document()
 
683
{
 
684
    delete m_pPresenter;
 
685
    m_pPresenter = m_lomse.new_document(ViewFactory::k_view_horizontal_book);
 
686
 
 
687
    //get the pointers to the relevant components
 
688
    m_pDoc = m_pPresenter->get_document();
 
689
    m_pInteractor = m_pPresenter->get_interactor(0);
 
690
 
 
691
    //connect the View with the window buffer
 
692
    m_pInteractor->set_rendering_buffer(&m_rbuf_window);
 
693
    m_pInteractor->add_event_handler(k_update_window_event, this, wrapper_update_window);
 
694
 
 
695
    //Now let's place content on the created document
 
696
    m_pDoc->from_string("(lenmusdoc (vers 0.0) (content (score (vers 1.6) "
 
697
        //"(instrument (musicData (clef G)(clef F3)(clef C1)(clef F4) )) )))" );
 
698
 
 
699
//        //instrument name
 
700
//        "(instrument (name \"Violin\")(musicData (clef G)(clef F4)(clef C1) )) )))" );
 
701
 
 
702
        //"(instrument (musicData )) )))" );
 
703
 
 
704
        //"(instrument (staves 2) (musicData )) )))" );
 
705
        //"(instrument (musicData )) (instrument (musicData )) )))" );
 
706
 
 
707
//    //Staves of different sizes
 
708
//    "(instrument (name \"Violin\")(abbrev \"Vln.\")(staff 1 (staffSpacing 400))(musicData (clef G)(n c4 e.))) "
 
709
//    "(instrument (name \"pilano\")(abbrev \"P\")(staves 2)(musicData (clef G p1)(clef F4 p2))) )))" );
 
710
 
 
711
//        //beamed chord. Simplest case
 
712
//        "(instrument (musicData "
 
713
//        "(clef F)(key C)(time 4 4)"
 
714
//        "(chord (n a3 e (beam 1 begin)) (n d3 e))"
 
715
//        "(chord (n g3 e (beam 1 end)) (n e3 e))"
 
716
//        "))"
 
717
//        ")))" );
 
718
 
 
719
//        //beams
 
720
//        "(instrument (name \"Violin\")(abbrev \"Vln.\")(musicData "
 
721
//        "(clef F4)(key E)(time 2 4)(n +c3 e.)(barline)"
 
722
//        "(n e2 q)(n e3 q)(barline)"
 
723
//        "(n f2 e (beam 1 +))(n g2 e (beam 1 -))"
 
724
//            "(n f3 e (beam 3 +))(n g3 e (beam 3 -))(barline)"
 
725
//        "(n f2 e. (beam 4 +))(n g2 s (beam 4 -b))"
 
726
//            "(n f3 s (beam 5 +f))(n g3 e. (beam 5 -))(barline)"
 
727
//        "(n g2 e. (beam 2 +))(n e3 s (beam 2 -b))(n g3 q)(barline)"
 
728
//        "(n a2 e (beam 6 +))(n g2 e (beam 6 -))(n a3 q)(barline)"
 
729
//        "(n -b2 q)(n =b3 q)(barline)"
 
730
//        "(n xc3 q)(n ++c4 q)(barline)"
 
731
//        "(n d3 q)(n --d4 q)(barline)"
 
732
//        "(n e3 q)(n e4 q)(barline)"
 
733
//        "(n f3 q)(n f4 q)(barline -)"
 
734
//        "))"
 
735
//        "(instrument (name \"pilano\")(abbrev \"P\")(staves 2)(musicData "
 
736
//        "(clef G p1)(clef F4 p2)(key F)(time 12 8)"
 
737
//        "(n c5 e. p1)(barline)"
 
738
//        "(n e4 e p1 (beam 10 +))(n g3 e p2 (beam 10 -))"
 
739
//        "(n e4 e p1 (stem up)(beam 11 +))(n e5 e p1 (stem down)(beam 11 -))(barline)"
 
740
//        "(n e4 s p1 (beam 12 ++))(n f4 s p1 (beam 12 ==))"
 
741
//            "(n g4 s p1 (beam 12 ==))(n a4 s p1 (beam 12 --))"
 
742
//        "(n c5 q p1)(barline)"
 
743
////        "(chord (n c4 q p1)(n e4 q p1)(n g4 q p1))"
 
744
////        "(chord (n c4 q p1)(n d4 q p1)(n g4 q p1))"
 
745
//        "))"
 
746
//        ")))" );
 
747
 
 
748
//        //beamed chord. Beam determines stem direction
 
749
//        "(instrument (musicData "
 
750
//        "(clef G)(key C)(time 2 4)"
 
751
//        "(chord (n c5 s (beam 2 begin begin))(n e5 s)(n g5 s))"
 
752
//        "(chord (n c5 s (beam 2 continue continue))(n f5 s)(n a5 s))"
 
753
//        "(chord (n d5 s (beam 2 continue continue))(n g5 s)(n b5 s))"
 
754
//        "(chord (n g4 s (beam 2 end end))(n e5 s)(n g5 s))"
 
755
//        "))"
 
756
//        ")))" );
 
757
 
 
758
//        //tuplet
 
759
//        "(instrument (musicData "
 
760
//        "(clef G)(key A)(time 2 4)"
 
761
//        "(n c4 e g+ t3/2)(n e4 e)(n d4 e g- t-)"
 
762
//        "(n e5 e g+ t3/2)(n c5 e)(n d5 e g- t-)"
 
763
//        "))"
 
764
//        ")))" );
 
765
 
 
766
//        //tuplets-engraving-rule-a-1
 
767
//        "(instrument (musicData "
 
768
//        "(time 2 4)"
 
769
//        "(n a4 e g+ t3)(n a4 e)(n a4 e g- t-)"
 
770
//        "(n a4 e g+)(n a4 e g-)"
 
771
//        "(barline)"
 
772
//        "(time 3 8)"
 
773
//        "(n a4 e g+ t4)(n a4 e)(n a4 e)(n a4 e g- t-)"
 
774
//        "(barline)"
 
775
//        "))"
 
776
//        ")))" );
 
777
 
 
778
        //tuplets-engraving-rule-d-1
 
779
//        "(instrument (musicData "
 
780
//        "(time 4 4)"
 
781
//        "(n e4 h t3)(n e4 h)(n e4 h t-)"
 
782
//        "(barline)"
 
783
//        "(n e5 h t3)(n e5 h)(n e5 h t-)"
 
784
//        "(barline)"
 
785
//        "(time 2 4)"
 
786
//        "(n e4 q t3)(n e4 e t-)"
 
787
//        "(barline)"
 
788
//        "(n e5 q t3)(n e5 e t-)"
 
789
//        "(barline)"
 
790
//        "(time 6 8)"
 
791
//        "(n e4 e g+ t4)(n e4 e g-)"
 
792
//        "(n e4 e g+)(n e4 e g-)"
 
793
//        "(n e4 e g+)(n e4 e g-)"
 
794
//        "(n e4 e g+)(n e4 e g- t-)"
 
795
//        "(barline)"
 
796
//        "(n e5 e g+ t4)(n e5 e g-)"
 
797
//        "(n e5 e g+)(n e5 e g-)"
 
798
//        "(n e5 e g+)(n e5 e g-)"
 
799
//        "(n e5 e g+)(n e5 e g- t-)"
 
800
//        "(barline)"
 
801
//        "))"
 
802
//        ")))" );
 
803
 
 
804
 
 
805
//        //tuplets-engraving-rule-b-1
 
806
//        "(instrument (musicData "
 
807
//        "(time 4 4)"
 
808
//        "(n e4 e g+ t3)(n e4 e g-)(r e t-)"
 
809
//        "(r e t3)(n e5 e)(r e t-)"
 
810
//        "(n e5 e t3)(r e)(r e t-)"
 
811
//        "(r e t3)(r e)(n e5 e t-)"
 
812
//        "))"
 
813
//        ")))" );
 
814
 
 
815
        //tie
 
816
        "(instrument (musicData "
 
817
        "(clef G)(key C)(time 4 4)"
 
818
        "(n e4 q l)(n e4 q)"
 
819
        "))"
 
820
        ")))" );
 
821
 
 
822
 
 
823
    //render the LENMUS_NEW score
 
824
    Refresh(false /* don't erase background */);
 
825
}
 
826
 
 
827
//---------------------------------------------------------------------------------------
 
828
void DocumentWindow::get_pages_info(int* pMinPage, int* pMaxPage,
 
829
                                 int* pSelPageFrom, int* pSelPageTo)
 
830
{
 
831
    //Return the default page range to be printed and the page range the user can
 
832
    //select for printing.
 
833
 
 
834
    *pMinPage = 1;
 
835
    GraphicModel* pGModel = m_pInteractor->get_graphic_model();
 
836
    *pMaxPage = pGModel->get_num_pages();
 
837
    *pSelPageFrom = 1;
 
838
    *pSelPageTo = *pMaxPage;
 
839
}
 
840
 
 
841
//---------------------------------------------------------------------------------------
 
842
void DocumentWindow::do_print(wxDC* pDC, int page, int paperWidthPixels,
 
843
                           int paperHeightPixels)
 
844
{
 
845
    pDC->SetBackground(*wxWHITE_BRUSH);
 
846
    pDC->Clear();
 
847
 
 
848
    //get page size in pixels
 
849
    VSize size = m_pInteractor->get_page_size_in_pixels(page);
 
850
    double vPageWidth( size.width );
 
851
    double vPageHeigh( size.height );
 
852
 
 
853
    //determine view scaling
 
854
    double scaleX = double(paperWidthPixels) / vPageWidth;
 
855
    double scaleY = double(paperHeightPixels) / vPageHeigh;
 
856
    double scale = max(scaleX, scaleY);
 
857
 
 
858
    //determine required buffer size (pixels)
 
859
    float wReq = float(paperWidthPixels);
 
860
    float hReq = float(paperHeightPixels);
 
861
 
 
862
    //determine tile size (pixels)
 
863
    int width = min(1024, paperWidthPixels);
 
864
    int height = min(1024, paperHeightPixels);
 
865
    int border = 8;
 
866
    if (width < 1024 && height < 1024)
 
867
        border = 0;
 
868
 
 
869
    //From paper viewpoint, for copying a tile into paper, copy origin is
 
870
    //at (B, B) and copy size is (w-2B, h-2B). Initial paper org is at (0,0).
 
871
    //From render viewpoint, initial viewport origin is at (-B, -B) and tiles
 
872
    //size (for advancing viewport origin) is also (w-2B, h-2B).
 
873
    VPoint viewport(0,0);
 
874
    VPoint paperPos(0,0);
 
875
    int tileW = width - 2 * border;
 
876
    int tileH = height - 2 * border;
 
877
 
 
878
    //determine how many tiles to print
 
879
    int rows = int(hReq / float(tileW) + 0.5f);
 
880
    int cols = int(wReq / float(tileH) + 0.5f);
 
881
 
 
882
    //determine last row and last column tile sizes
 
883
    int lastW = paperWidthPixels - tileW * (cols - 1);
 
884
    int lastH = paperHeightPixels - tileH * (rows - 1);
 
885
 
 
886
    //allocate tile buffer
 
887
    RenderingBuffer rbuf_print;
 
888
    wxImage* buffer;                        //the image to serve as buffer
 
889
    unsigned char* pdata;                   //ptr to the real bytes buffer
 
890
    #define BYTES_PP 3                      // Bytes per pixel
 
891
    buffer = LENMUS_NEW wxImage(width, height);    // allocate the rendering buffer
 
892
    int stride = width * BYTES_PP;          //number of bytes per row
 
893
    pdata = buffer->GetData();
 
894
    rbuf_print.attach(pdata, width, height, stride);
 
895
    m_pInteractor->set_printing_buffer(&rbuf_print);
 
896
 
 
897
    //loop to print tiles.
 
898
    wxMemoryDC memoryDC;
 
899
    for (int iRow=0; iRow < rows; ++iRow)
 
900
    {
 
901
        for (int iCol=0; iCol < cols; ++iCol)
 
902
        {
 
903
            m_pInteractor->on_print_page(page-1, scale, viewport);
 
904
 
 
905
            //print this tile
 
906
            int tileWidth = (iCol == cols-1 ? lastW : tileW);
 
907
            int tileHeight = (iRow == rows-1 ? lastH : tileH);
 
908
 
 
909
            #if 1
 
910
                wxBitmap bitmap = *buffer;
 
911
                if (bitmap.Ok())
 
912
                {
 
913
                    if (border > 0)
 
914
                    {
 
915
                        memoryDC.SelectObjectAsSource(bitmap);
 
916
                        pDC->Blit(paperPos.x, paperPos.y, tileWidth, tileHeight,
 
917
                                &memoryDC, border, border);
 
918
                        memoryDC.SelectObjectAsSource(wxNullBitmap);
 
919
                    }
 
920
                    else
 
921
                        pDC->DrawBitmap(bitmap, paperPos.x, paperPos.y, false /* don't use mask */);
 
922
                }
 
923
            #else
 
924
                //to try to save time, instead of blitting, get subimage
 
925
                //Results: it takes the same time and prints a black line at bottom
 
926
                if (border > 0)
 
927
                {
 
928
                    wxRect rect(border, border, tileWidth, tileHeight);
 
929
                    wxBitmap bitmap( buffer->GetSubImage(rect) );
 
930
                    if (bitmap.Ok())
 
931
                        pDC->DrawBitmap(bitmap, paperPos.x, paperPos.y, false /* don't use mask */);
 
932
                }
 
933
                else
 
934
                {
 
935
                    wxBitmap bitmap( *buffer );
 
936
                    if (bitmap.Ok())
 
937
                        pDC->DrawBitmap(bitmap, paperPos.x, paperPos.y, false /* don't use mask */);
 
938
                }
 
939
            #endif
 
940
 
 
941
            //advance origin by tile size
 
942
            viewport.x -= tileW;
 
943
            paperPos.x += tileW;
 
944
        }
 
945
        //start LENMUS_NEW row
 
946
        viewport.x = 0;
 
947
        viewport.y -= tileH;
 
948
        paperPos.x = 0;
 
949
        paperPos.y += tileH;
 
950
    }
 
951
 
 
952
    delete buffer;
 
953
}
 
954
 
 
955
//---------------------------------------------------------------------------------------
 
956
void DocumentWindow::adjust_scale_and_scrollbars()
 
957
{
 
958
    //wxLogMessage(_T("adjust_scale_and_scrollbars %0x"), this);
 
959
 
 
960
    int zoomMode = get_zoom_mode();
 
961
    if (zoomMode == k_zoom_fit_width)
 
962
        zoom_fit_width();
 
963
    else if (zoomMode == k_zoom_fit_full)
 
964
        zoom_fit_full();
 
965
    else
 
966
        adjust_scrollbars();
 
967
}
 
968
 
 
969
//---------------------------------------------------------------------------------------
 
970
void DocumentWindow::determine_scroll_space_size()
 
971
{
 
972
    //wxLogMessage(_T("determine_scroll_space_size %0x"), this);
 
973
 
 
974
    //total size of the rendered document (whole visual space, all pages)
 
975
    m_pInteractor->get_view_size(&m_xScrollSpaceWidth, &m_yScrollSpaceHeight);
 
976
    m_xMargin = m_xScrollSpaceWidth/40;              //2.5% margin, at each side
 
977
    m_yMargin = m_xMargin;
 
978
 
 
979
    //how many pixels per scroll unit?
 
980
    //AWARE: In wxWidgets scrollbars uses scroll units (arbitrary user defined units).
 
981
    //After some experimentation I concluded taht the best approach is to use pixels as
 
982
    //scroll units; otherwise truncation errors create problems. The following variables
 
983
    //are used only to define the increment/decrement when scrolling one line
 
984
    m_xPixelsPerScrollUnit = 8;
 
985
    m_yPixelsPerScrollUnit = 15;
 
986
 
 
987
    //get viewport limits (in pixels)
 
988
    m_xMinViewport = -m_xMargin;
 
989
    m_yMinViewport = -m_yMargin;
 
990
}
 
991
 
 
992
//---------------------------------------------------------------------------------------
 
993
void DocumentWindow::adjust_scrollbars()
 
994
{
 
995
    //wxLogMessage(_T("adjust_scrollbars %0x"), this);
 
996
 
 
997
    determine_scroll_space_size();
 
998
 
 
999
    //get size of scroll page (client area size)
 
1000
    m_xScrollPageWidth = m_nBufWidth;
 
1001
    m_yScrollPageHeight = m_nBufHeight;
 
1002
 
 
1003
    //get viewport limits (in pixels)
 
1004
    m_xMaxViewport = (m_xScrollSpaceWidth - m_xMargin) - m_xScrollPageWidth;
 
1005
    m_yMaxViewport = (m_yScrollSpaceHeight - m_yMargin) - m_yScrollPageHeight;
 
1006
 
 
1007
    //get current viewport position
 
1008
    int xCurPos, yCurPos;
 
1009
    m_pInteractor->get_viewport(&xCurPos, &yCurPos);
 
1010
 
 
1011
    //determine thumb size (in scroll units) and position
 
1012
    int xThumbSize = m_xScrollPageWidth;
 
1013
    int xStartThumb = max(0, (m_xMargin + xCurPos));
 
1014
    int yThumbSize = m_yScrollPageHeight;
 
1015
    int yStartThumb = max(0, (m_yMargin + yCurPos));
 
1016
 
 
1017
    //scroll space size, in scroll units
 
1018
    m_xMaxScrollUnits = m_xScrollSpaceWidth;
 
1019
    m_yMaxScrollUnits = m_yScrollSpaceHeight;
 
1020
 
 
1021
    //set scrollbars
 
1022
    m_fIgnoreOnSize = true;
 
1023
    SetScrollbar(wxVERTICAL, yStartThumb, yThumbSize, m_yMaxScrollUnits);
 
1024
    SetScrollbar(wxHORIZONTAL, xStartThumb, xThumbSize, m_xMaxScrollUnits);
 
1025
    m_fIgnoreOnSize = false;
 
1026
}
 
1027
 
 
1028
//---------------------------------------------------------------------------------------
 
1029
void DocumentWindow::on_scroll(wxScrollWinEvent& event)
 
1030
{
 
1031
    //wxLogMessage(_T("on_scroll %0x"), this);
 
1032
 
 
1033
    int xPos, yPos;
 
1034
    m_pInteractor->get_viewport(&xPos, &yPos);
 
1035
 
 
1036
    wxEventType type = event.GetEventType();
 
1037
 
 
1038
    if (event.GetOrientation() == wxVERTICAL)
 
1039
    {
 
1040
        if (type == wxEVT_SCROLLWIN_TOP)
 
1041
            yPos = m_yMinViewport;
 
1042
        else if (type == wxEVT_SCROLLWIN_BOTTOM)
 
1043
            yPos = m_yMaxViewport;
 
1044
        else if (type == wxEVT_SCROLLWIN_LINEUP)
 
1045
            yPos -= m_yPixelsPerScrollUnit;
 
1046
        else if (type == wxEVT_SCROLLWIN_LINEDOWN)
 
1047
            yPos += m_yPixelsPerScrollUnit;
 
1048
        else if (type == wxEVT_SCROLLWIN_PAGEUP)
 
1049
            yPos -= m_yScrollPageHeight;
 
1050
        else if (type == wxEVT_SCROLLWIN_PAGEDOWN)
 
1051
            yPos += m_yScrollPageHeight;
 
1052
        else if (type == wxEVT_SCROLLWIN_THUMBTRACK
 
1053
                 || type == wxEVT_SCROLLWIN_THUMBRELEASE)
 
1054
        {
 
1055
            yPos = event.GetPosition() - m_yMargin;
 
1056
        }
 
1057
 
 
1058
        #if (LENMUS_PLATFORM_WIN32 == 1)  //---------------------------------------------
 
1059
        {
 
1060
            //In Windows, up/down buttons remain enabled even when reaching top/bottom
 
1061
            if (yPos < m_yMinViewport)
 
1062
                yPos = m_yMinViewport;
 
1063
            else if (yPos > m_yMaxViewport)
 
1064
                yPos = m_yMaxViewport;
 
1065
 
 
1066
            //in Windows the scroll thumb remains at top, so we have to
 
1067
            //reposition it manually
 
1068
            if (type != wxEVT_SCROLLWIN_THUMBTRACK)
 
1069
                SetScrollPos(wxVERTICAL, m_yMargin + yPos);
 
1070
        }
 
1071
        #endif  //-----------------------------------------------------------------------
 
1072
 
 
1073
        m_pInteractor->new_viewport(xPos, yPos);
 
1074
        m_pInteractor->force_redraw();
 
1075
    }
 
1076
 
 
1077
    else
 
1078
    {
 
1079
        if (type == wxEVT_SCROLLWIN_TOP)
 
1080
            xPos = m_xMinViewport;
 
1081
        else if (type == wxEVT_SCROLLWIN_BOTTOM)
 
1082
            xPos = m_xMaxViewport;
 
1083
        else if (type == wxEVT_SCROLLWIN_LINEUP)
 
1084
            xPos -= m_xPixelsPerScrollUnit;
 
1085
        else if (type == wxEVT_SCROLLWIN_LINEDOWN)
 
1086
            xPos += m_xPixelsPerScrollUnit;
 
1087
        else if (type == wxEVT_SCROLLWIN_PAGEUP)
 
1088
            xPos -= m_xScrollPageWidth;
 
1089
        else if (type == wxEVT_SCROLLWIN_PAGEDOWN)
 
1090
            xPos += m_xScrollPageWidth;
 
1091
        else if (type == wxEVT_SCROLLWIN_THUMBTRACK
 
1092
                 || type == wxEVT_SCROLLWIN_THUMBRELEASE)
 
1093
        {
 
1094
            xPos = event.GetPosition() - m_xMargin;
 
1095
        }
 
1096
 
 
1097
        #if (LENMUS_PLATFORM_WIN32 == 1)  //---------------------------------------------
 
1098
        {
 
1099
            //In Windows, up/down buttons remain enabled even when reaching top/bottom
 
1100
            if (xPos < m_xMinViewport)
 
1101
                xPos = m_xMinViewport;
 
1102
            else if (xPos > m_xMaxViewport)
 
1103
                xPos = m_xMaxViewport;
 
1104
 
 
1105
            //in Windows the scroll thumb remains at top, so we have to
 
1106
            //reposition it manually
 
1107
            if (type != wxEVT_SCROLLWIN_THUMBTRACK)
 
1108
                SetScrollPos(wxHORIZONTAL, m_xMargin + xPos);
 
1109
        }
 
1110
        #endif  //-----------------------------------------------------------------------
 
1111
 
 
1112
        m_pInteractor->new_viewport(xPos, yPos);
 
1113
        m_pInteractor->force_redraw();
 
1114
    }
 
1115
 
 
1116
    event.Skip(false);      //do not propagate event
 
1117
}
 
1118
 
 
1119
//---------------------------------------------------------------------------------------
 
1120
void DocumentWindow::scroll_line(bool fUp)
 
1121
{
 
1122
    int xPos, yPos;
 
1123
    m_pInteractor->get_viewport(&xPos, &yPos);
 
1124
    if (fUp)
 
1125
        yPos -= m_yPixelsPerScrollUnit;
 
1126
    else
 
1127
        yPos += m_yPixelsPerScrollUnit;
 
1128
 
 
1129
    #if (LENMUS_PLATFORM_WIN32 == 1)  //---------------------------------------------
 
1130
    {
 
1131
        //In Windows, up/down buttons remain enabled even when reaching top/bottom
 
1132
        if (yPos < m_yMinViewport)
 
1133
            yPos = m_yMinViewport;
 
1134
        else if (yPos > m_yMaxViewport)
 
1135
            yPos = m_yMaxViewport;
 
1136
    }
 
1137
    #endif  //-----------------------------------------------------------------------
 
1138
 
 
1139
    m_pInteractor->new_viewport(xPos, yPos);
 
1140
    m_pInteractor->force_redraw();
 
1141
}
 
1142
 
 
1143
//---------------------------------------------------------------------------------------
 
1144
void DocumentWindow::debug_display_ldp_source()
 
1145
{
 
1146
    LdpExporter exporter;
 
1147
    string source = exporter.get_source( m_pDoc->get_imodoc() );
 
1148
    DlgDebug dlg(this, _T("Generated source code"), to_wx_string(source));
 
1149
    dlg.ShowModal();
 
1150
}
 
1151
 
 
1152
//---------------------------------------------------------------------------------------
 
1153
void DocumentWindow::debug_display_lmd_source()
 
1154
{
 
1155
    LmdExporter exporter;
 
1156
    exporter.set_score_format(LmdExporter::k_format_lmd);
 
1157
    string source = exporter.get_source( m_pDoc->get_imodoc() );
 
1158
    DlgDebug dlg(this, _T("Generated source code"), to_wx_string(source));
 
1159
    dlg.ShowModal();
 
1160
}
 
1161
 
 
1162
 
 
1163
}   //namespace lenmus