1 #include <wx/wx.h>
2 #include <wx/power.h>
3 #include <wx/mstream.h>
4 #include <wx/stdpaths.h>
5 #include <crengine.h>
6 #include "cr3.h"
7 #include "rescont.h"
8 #include "view.h"
9 #include "optdlg.h"
10 
11 #define RENDER_TIMER_ID   123
12 #define CLOCK_TIMER_ID    124
13 #define CURSOR_TIMER_ID		125
14 
BEGIN_EVENT_TABLE(cr3view,wxPanel)15 BEGIN_EVENT_TABLE( cr3view, wxPanel )
16     EVT_PAINT( cr3view::OnPaint )
17     EVT_SIZE    ( cr3view::OnSize )
18     EVT_MOUSEWHEEL( cr3view::OnMouseWheel )
19     EVT_LEFT_DOWN( cr3view::OnMouseLDown )
20     EVT_RIGHT_DOWN( cr3view::OnMouseRDown )
21     EVT_MOTION( cr3view::OnMouseMotion )
22     EVT_MENU_RANGE( 0, 0xFFFF, cr3view::OnCommand )
23     EVT_SET_FOCUS( cr3view::OnSetFocus )
24     EVT_TIMER(RENDER_TIMER_ID, cr3view::OnTimer)
25     EVT_TIMER(CLOCK_TIMER_ID, cr3view::OnTimer)
26     EVT_TIMER(CURSOR_TIMER_ID, cr3view::OnTimer)
27     EVT_INIT_DIALOG(cr3view::OnInitDialog)
28 END_EVENT_TABLE()
29 
30 wxColour cr3view::getBackgroundColour()
31 {
32 #if (COLOR_BACKBUFFER==1)
33     lUInt32 cl = getDocView()->getBackgroundColor();
34 #else
35     lUInt32 cl = 0xFFFFFF;
36 #endif
37     wxColour wxcl( (cl>>16)&255, (cl>>8)&255, (cl>>0)&255 );
38     return wxcl;
39 }
40 
propsToPageHeaderFlags(CRPropRef props)41 int propsToPageHeaderFlags( CRPropRef props )
42 {
43     int flags = 0;
44     if ( props->getBoolDef( PROP_PAGE_HEADER_ENABLED, true ) ) {
45         if ( props->getBoolDef( PROP_PAGE_HEADER_PAGE_NUMBER, true ) )
46             flags |= PGHDR_PAGE_NUMBER;
47         if ( props->getBoolDef( PROP_PAGE_HEADER_PAGE_COUNT, true ) )
48             flags |= PGHDR_PAGE_COUNT;
49         if ( props->getBoolDef( PROP_PAGE_HEADER_CLOCK, true ) )
50             flags |= PGHDR_CLOCK;
51         if ( props->getBoolDef( PROP_PAGE_HEADER_BATTERY, true ) )
52             flags |= PGHDR_BATTERY;
53         if ( props->getBoolDef( PROP_PAGE_HEADER_AUTHOR, true ) )
54             flags |= PGHDR_AUTHOR;
55         if ( props->getBoolDef( PROP_PAGE_HEADER_TITLE, true ) )
56             flags |= PGHDR_TITLE;
57     }
58     return flags;
59 }
60 
61 
OnInitDialog(wxInitDialogEvent & event)62 void cr3view::OnInitDialog(wxInitDialogEvent& event)
63 {
64     //SetBackgroundColour( getBackgroundColour() );
65 	_isFullscreen = _props->getBoolDef(PROP_WINDOW_FULLSCREEN);
66 }
67 
GetLastRecentFileName()68 lString32 cr3view::GetLastRecentFileName()
69 {
70     if ( getDocView() && getDocView()->getHistory()->getRecords().length()>0 )
71         return getDocView()->getHistory()->getRecords()[0]->getFilePathName();
72     return lString32::empty_str;
73 }
74 
cr3view(CRPropRef props,lString32 exeDirPath)75 cr3view::cr3view(CRPropRef props, lString32 exeDirPath )
76 : _normalCursor(wxCURSOR_ARROW)
77 , _linkCursor(wxCURSOR_HAND)
78 , _scrollbar(NULL)
79 , _firstRender(false)
80 , _allowRender(true)
81 , _props(props)
82 , _screen(300,400)
83 , _wm(&_screen)
84 {
85     _wm.activateWindow( (_docwin = new CRDocViewWindow(&_wm)) );
86     getDocView()->setCallback( this );
87     IMAGE_SOURCE_FROM_BYTES(defCover, cr3_def_cover_gif);
88     LVImageSourceRef cover = LVCreateFileCopyImageSource( exeDirPath + "cr3_def_cover.png" );
89     if ( !cover.isNull() )
90         getDocView()->setDefaultCover( cover );
91     else
92         getDocView()->setDefaultCover( defCover );
93     getDocView()->setPageMargins( lvRect(14, 5, 14, 5) );
94 
95     static int fontSizes[] = {14, 16, 18, 20, 24, 28, 32, 36};
96     LVArray<int> sizes( fontSizes, sizeof(fontSizes)/sizeof(int) );
97     getDocView()->setFontSizes( sizes, false );
98     //_docview->setBackgroundColor(0x000000);
99     //_docview->setTextColor(0xFFFFFF);
100 
101     cr_rotate_angle_t angle = (cr_rotate_angle_t)(_props->getIntDef( PROP_WINDOW_ROTATE_ANGLE, 0 ) & 3);
102     getDocView()->SetRotateAngle( angle );
103 
104     {
105         LVStreamRef stream = LVOpenFileStream( GetHistoryFileName().c_str(), LVOM_READ );
106         if ( !stream.isNull() ) {
107             getDocView()->getHistory()->loadFromStream( stream );
108             stream = NULL;
109         }
110     }
111 
112 
113 
114     _renderTimer = new wxTimer( this, RENDER_TIMER_ID );
115     _clockTimer = new wxTimer( this, CLOCK_TIMER_ID );
116     _cursorTimer = new wxTimer( this, CURSOR_TIMER_ID );
117 
118     //SetBackgroundColour( getBackgroundColour() );
119     InitDialog();
120     //int width, height;
121     //GetClientSize( &width, &height );
122 	//Resize( 300, 300 );
123 
124 #if 0
125     //TEST ICONS
126     LVRefVec<LVImageSource> icons;
127     static const char * icon1[] = {
128         "8 8 3 1",
129         "* c #000000",
130         ". c #FFFFFF",
131         "  c None",
132         " ****** ",
133         "*......*",
134         "*.*..*.*",
135         "*......*",
136         "*. ** .*",
137         "*......*",
138         " **..** ",
139         "   **   ",
140     };
141     static const char * icon2[] = {
142         "8 8 3 1",
143         "* c #00C000",
144         ". c #FF80FF",
145         "  c None",
146         " ****** ",
147         "*..**..*",
148         "*.*..*.*",
149         "*.*..*.*",
150         "*. ** .*",
151         "**.  .**",
152         " **..** ",
153         "   **   ",
154     };
155     static const char * battery4[] = {
156         "24 13 4 1",
157         "0 c #000000",
158         "o c #AAAAAA",
159         ". c #FFFFFF",
160         "  c None",
161         "   .....................",
162         "   .0000000000000000000.",
163         "....0.................0.",
164         ".0000.000.000.000.000.0.",
165         ".0..0.000.000.000.000.0.",
166         ".0..0.000.000.000.000.0.",
167         ".0..0.000.000.000.000.0.",
168         ".0..0.000.000.000.000.0.",
169         ".0..0.000.000.000.000.0.",
170         ".0000.000.000.000.000.0.",
171         "....0.................0.",
172         "   .0000000000000000000.",
173         "   .....................",
174     };
175     static const char * battery3[] = {
176         "24 13 4 1",
177         "0 c #000000",
178         "o c #AAAAAA",
179         ". c #FFFFFF",
180         "  c None",
181         "   .....................",
182         "   .0000000000000000000.",
183         "....0.................0.",
184         ".0000.ooo.000.000.000.0.",
185         ".0..0.ooo.000.000.000.0.",
186         ".0..0.ooo.000.000.000.0.",
187         ".0..0.ooo.000.000.000.0.",
188         ".0..0.ooo.000.000.000.0.",
189         ".0..0.ooo.000.000.000.0.",
190         ".0000.ooo.000.000.000.0.",
191         "....0.................0.",
192         "   .0000000000000000000.",
193         "   .....................",
194     };
195     static const char * battery2[] = {
196         "24 13 4 1",
197         "0 c #000000",
198         "o c #AAAAAA",
199         ". c #FFFFFF",
200         "  c None",
201         "   .....................",
202         "   .0000000000000000000.",
203         "....0.................0.",
204         ".0000.ooo.ooo.000.000.0.",
205         ".0..0.ooo.ooo.000.000.0.",
206         ".0..0.ooo.ooo.000.000.0.",
207         ".0..0.ooo.ooo.000.000.0.",
208         ".0..0.ooo.ooo.000.000.0.",
209         ".0..0.ooo.ooo.000.000.0.",
210         ".0000.ooo.ooo.000.000.0.",
211         "....0.................0.",
212         "   .0000000000000000000.",
213         "   .....................",
214     };
215     static const char * battery1[] = {
216         "24 13 4 1",
217         "0 c #000000",
218         "o c #AAAAAA",
219         ". c #FFFFFF",
220         "  c None",
221         "   .....................",
222         "   .0000000000000000000.",
223         "....0.................0.",
224         ".0000.ooo.ooo.ooo.000.0.",
225         ".0..0.ooo.ooo.ooo.000.0.",
226         ".0..0.ooo.ooo.ooo.000.0.",
227         ".0..0.ooo.ooo.ooo.000.0.",
228         ".0..0.ooo.ooo.ooo.000.0.",
229         ".0..0.ooo.ooo.ooo.000.0.",
230         ".0000.ooo.ooo.ooo.000.0.",
231         "....0.................0.",
232         "   .0000000000000000000.",
233         "   .....................",
234     };
235     static const char * battery0[] = {
236         "24 13 4 1",
237         "0 c #000000",
238         "o c #AAAAAA",
239         ". c #FFFFFF",
240         "  c None",
241         "   .....................",
242         "   .0000000000000000000.",
243         "....0.................0.",
244         ".0000.ooo.ooo.ooo.ooo.0.",
245         ".0..0.ooo.ooo.ooo.ooo.0.",
246         ".0..0.ooo.ooo.ooo.ooo.0.",
247         ".0..0.ooo.ooo.ooo.ooo.0.",
248         ".0..0.ooo.ooo.ooo.ooo.0.",
249         ".0..0.ooo.ooo.ooo.ooo.0.",
250         ".0000.ooo.ooo.ooo.ooo.0.",
251         "....0.................0.",
252         "   .0000000000000000000.",
253         "   .....................",
254     };
255     icons.add( LVCreateXPMImageSource( icon1 ) );
256     icons.add( LVCreateXPMImageSource( icon2 ) );
257     _docview->setHeaderIcons( icons );
258     icons.clear();
259     icons.add( LVCreateXPMImageSource( battery0 ) );
260     icons.add( LVCreateXPMImageSource( battery1 ) );
261     icons.add( LVCreateXPMImageSource( battery2 ) );
262     icons.add( LVCreateXPMImageSource( battery3 ) );
263     icons.add( LVCreateXPMImageSource( battery4 ) );
264     _docview->setBatteryIcons( icons );
265 #endif
266 }
267 
~cr3view()268 cr3view::~cr3view()
269 {
270     delete _renderTimer;
271     delete _clockTimer;
272     delete _cursorTimer;
273 }
274 
OnTimer(wxTimerEvent & event)275 void cr3view::OnTimer(wxTimerEvent& event)
276 {
277     //printf("cr3view::OnTimer() \n");
278     if ( event.GetId() == RENDER_TIMER_ID ) {
279         int dx;
280         int dy;
281         GetClientSize( &dx, &dy );
282         //if ( _docview->IsRendered() && dx == _docview->GetWidth()
283         //        && dy == _docview->GetHeight() )
284         //    return; // no resize
285         if (dx<50 || dy<50 || dx>3000 || dy>3000)
286         {
287             return;
288         }
289 
290         if ( _firstRender ) {
291             getDocView()->restorePosition();
292             _firstRender = false;
293             _allowRender = true;
294         }
295 
296         _wm.reconfigure( dx, dy, CR_ROTATE_ANGLE_0 );
297 
298         Paint();
299         UpdateScrollBar();
300     } else if ( event.GetId() == CURSOR_TIMER_ID ) {
301         SetCursor( wxCursor( wxCURSOR_BLANK ) );
302     } else if ( event.GetId() == CLOCK_TIMER_ID ) {
303         if ( IsShownOnScreen() ) {
304             if ( getDocView()->IsRendered() && getDocView()->isTimeChanged() )
305                 Paint();
306         }
307     }
308 }
309 
Paint()310 void cr3view::Paint()
311 {
312     //printf("cr3view::Paint() \n");
313     int battery_state = -1;
314 #ifdef _WIN32
315     SYSTEM_POWER_STATUS bstatus;
316     BOOL pow = GetSystemPowerStatus(&bstatus);
317     if (bstatus.BatteryFlag & 128)
318         pow = FALSE;
319     if (bstatus.ACLineStatus!=0 || bstatus.BatteryLifePercent==255)
320         pow = FALSE;
321     if ( pow )
322         battery_state = bstatus.BatteryLifePercent;
323 #else
324     if ( ::wxGetPowerType() == wxPOWER_BATTERY ) {
325         int n = ::wxGetBatteryState();
326         if ( n == wxBATTERY_NORMAL_STATE )
327             battery_state = 100;
328         else if ( n == wxBATTERY_LOW_STATE )
329             battery_state = 50;
330         else if ( n == wxBATTERY_CRITICAL_STATE )
331             battery_state = 0;
332         else if ( n == wxBATTERY_SHUTDOWN_STATE )
333             battery_state = 0;
334     };
335 #endif
336     getDocView()->setBatteryState( battery_state );
337     //_docview->Draw();
338     UpdateScrollBar();
339     Refresh( FALSE );
340 }
341 
detectSlash(lString32 path)342 static lChar32 detectSlash( lString32 path )
343 {
344     for ( unsigned i=0; i<path.length(); i++ )
345         if ( path[i]=='\\' || path[i]=='/' )
346             return path[i];
347 #ifdef _WIN32
348     return '\\';
349 #else
350     return '/';
351 #endif
352 }
353 
GetHistoryFileName()354 lString32 cr3view::GetHistoryFileName()
355 {
356     wxString wxcfgdir = wxStandardPaths::Get().GetUserDataDir();
357     if ( !wxDirExists( wxcfgdir ) )
358         ::wxMkdir( wxcfgdir );
359     lString32 cfgdir = wx2cr(wxcfgdir);
360     lChar32 slash = detectSlash( cfgdir );
361     cfgdir << slash;
362     return cfgdir + "cr3hist.bmk";
363 }
364 
CloseDocument()365 void cr3view::CloseDocument()
366 {
367     //printf("cr3view::CloseDocument()  \n");
368     getDocView()->savePosition();
369     getDocView()->Clear();
370     LVStreamRef stream = LVOpenFileStream( GetHistoryFileName().c_str(), LVOM_WRITE );
371     if ( !stream.isNull() )
372         getDocView()->getHistory()->saveToStream( stream.get() );
373 }
374 
UpdateScrollBar()375 void cr3view::UpdateScrollBar()
376 {
377 	if ( !_scrollbar )
378 		return;
379     if ( !getDocView()->IsRendered() )
380         return;
381     const LVScrollInfo * lvsi = getDocView()->getScrollInfo();
382     _scrollbar->SetScrollbar(
383         lvsi->pos,      //int position,
384         lvsi->pagesize, //int thumbSize,
385         lvsi->maxpos + lvsi->pagesize,   //int range,
386         lvsi->pagesize, //int pageSize,
387         true//const bool refresh = true
388     );
389     wxStatusBar * sb = ((wxFrame*)GetParent())->GetStatusBar();
390     if ( sb )
391         sb->SetStatusText( cr2wx(lvsi->posText), 1 );
392 
393 }
394 
OnMouseMotion(wxMouseEvent & event)395 void cr3view::OnMouseMotion(wxMouseEvent& event)
396 {
397     int x = event.GetX();
398     int y = event.GetY();
399     ldomXPointer ptr = getDocView()->getNodeByPoint( lvPoint( x, y ) );
400     if ( ptr.isNull() ) {
401         return;
402     }
403     lString32 href = ptr.getHRef();
404     if ( href.empty() ) {
405         SetCursor(_normalCursor);
406     } else {
407         SetCursor(_linkCursor);
408     }
409 
410     if ( _isFullscreen ) {
411         _cursorTimer->Stop();
412         _cursorTimer->Start( 3 * 1000, wxTIMER_ONE_SHOT );
413     }
414 
415     SetCursor( wxNullCursor );
416 }
417 
OnMouseLDown(wxMouseEvent & event)418 void cr3view::OnMouseLDown( wxMouseEvent & event )
419 {
420     int x = event.GetX();
421     int y = event.GetY();
422     //lString32 txt = _docview->getPageText( true );
423     //CRLog::debug( "getPageText : %s", UnicodeToUtf8(txt).c_str() );
424     ldomXPointer ptr = getDocView()->getNodeByPoint( lvPoint( x, y ) );
425     if ( ptr.isNull() ) {
426         CRLog::debug( "cr3view::OnMouseLDown() : node not found!\n");
427         return;
428     }
429     lString32 href = ptr.getHRef();
430     if ( ptr.getNode()->isText() ) {
431         lString8 s = UnicodeToUtf8( ptr.toString() );
432         CRLog::debug("Text node clicked (%d, %d): %s", x, y, s.c_str() );
433         ldomXRange * wordRange = new ldomXRange();
434         if ( ldomXRange::getWordRange( *wordRange, ptr ) ) {
435             wordRange->setFlags( 0x10000 );
436             getDocView()->getDocument()->getSelections().clear();
437             getDocView()->getDocument()->getSelections().add( wordRange );
438             getDocView()->updateSelections();
439         } else {
440             delete wordRange;
441         }
442         if ( !href.empty() ) {
443             getDocView()->goLink( href );
444         }
445         Paint();
446         printf("text : %s     \t", s.c_str() );
447     } else {
448         printf("element : %s  \t", UnicodeToUtf8( ptr.toString() ).c_str() );
449     }
450     lvPoint pt2 = ptr.toPoint();
451     printf("  (%d, %d)  ->  (%d, %d)\n", x, y+getDocView()->GetPos(), pt2.x, pt2.y);
452 }
453 
OnMouseRDown(wxMouseEvent & event)454 void cr3view::OnMouseRDown( wxMouseEvent & event )
455 {
456     wxMenu pm;
457     pm.Append( wxID_OPEN, wxT( "&Open...\tCtrl+O" ) );
458     pm.Append( Menu_View_History, wxT( "Recent books list\tF4" ) );
459     pm.Append( wxID_SAVE, wxT( "&Save...\tCtrl+S" ) );
460     pm.AppendSeparator();
461     pm.Append( Menu_File_Options, wxT( "Options...\tF9" ) );
462     pm.AppendSeparator();
463     pm.Append( Menu_View_TOC, wxT( "Table of Contents\tF5" ) );
464     pm.Append( Menu_File_About, wxT( "&About...\tF1" ) );
465     pm.AppendSeparator();
466     pm.Append( Menu_View_ZoomIn, wxT( "Zoom In" ) );
467     pm.Append( Menu_View_ZoomOut, wxT( "Zoom Out" ) );
468     pm.AppendSeparator();
469     pm.Append( Menu_View_ToggleFullScreen, wxT( "Toggle Fullscreen\tAlt+Enter" ) );
470     pm.Append( Menu_View_TogglePages, wxT( "Toggle Pages/Scroll\tCtrl+P" ) );
471     pm.Append( Menu_View_TogglePageHeader, wxT( "Toggle page heading\tCtrl+H" ) );
472     pm.AppendSeparator();
473     pm.Append( Menu_File_Quit, wxT( "E&xit\tAlt+X" ) );
474 
475     ((wxFrame*)GetParent())->PopupMenu(&pm);
476 }
477 
SetPageHeaderFlags()478 void cr3view::SetPageHeaderFlags()
479 {
480     int newflags = propsToPageHeaderFlags( _props );
481     int oldflags = getDocView()->getPageHeaderInfo();
482     if ( oldflags==newflags )
483         return;
484     getDocView()->setPageHeaderInfo( newflags );
485     UpdateScrollBar();
486     Paint();
487 }
488 
ToggleViewMode()489 void cr3view::ToggleViewMode()
490 {
491     int mode = _props->getIntDef( PROP_PAGE_VIEW_MODE, 2 ) ? 0 : 2;
492     _props->setInt( PROP_PAGE_VIEW_MODE, mode );
493     getDocView()->setViewMode( mode>0 ? DVM_PAGES : DVM_SCROLL, mode>0 ? mode : -1 );
494     UpdateScrollBar();
495     Paint();
496 }
497 
OnCommand(wxCommandEvent & event)498 void cr3view::OnCommand(wxCommandEvent& event)
499 {
500 	switch ( event.GetId() ) {
501 	case Menu_View_ZoomIn:
502         {
503 	        wxCursor hg( wxCURSOR_WAIT );
504 	        this->SetCursor( hg );
505 	        wxSetCursor( hg );
506             //===========================================
507             doCommand( DCMD_ZOOM_IN, 0 );
508             //===========================================
509 	        this->SetCursor( wxNullCursor );
510 	        wxSetCursor( wxNullCursor );
511         }
512 		break;
513 	case Menu_View_ZoomOut:
514         {
515 	        wxCursor hg( wxCURSOR_WAIT );
516 	        this->SetCursor( hg );
517 	        wxSetCursor( hg );
518             //===========================================
519     	    doCommand( DCMD_ZOOM_OUT, 0 );
520             //===========================================
521 	        this->SetCursor( wxNullCursor );
522 	        wxSetCursor( wxNullCursor );
523         }
524 		break;
525 	case Menu_View_NextPage:
526 	    doCommand( DCMD_PAGEDOWN, 1 );
527         getDocView()->cachePageImage( 0 );
528         getDocView()->cachePageImage( 1 );
529 		break;
530     case Menu_Link_Forward:
531 		doCommand( DCMD_LINK_FORWARD, 1 );
532         break;
533     case Menu_Link_Back:
534 		doCommand( DCMD_LINK_BACK, 1 );
535         break;
536     case Menu_Link_Next:
537 		doCommand( DCMD_LINK_NEXT, 1 );
538         break;
539     case Menu_Link_Prev:
540 		doCommand( DCMD_LINK_PREV, 1 );
541         break;
542     case Menu_Link_Go:
543 		doCommand( DCMD_LINK_GO, 1 );
544         break;
545 	case Menu_View_PrevPage:
546 		doCommand( DCMD_PAGEUP, 1 );
547         getDocView()->cachePageImage( 0 );
548         getDocView()->cachePageImage( -1 );
549         break;
550 	case Menu_View_NextLine:
551 	    doCommand( DCMD_LINEDOWN, 1 );
552 		break;
553 	case Menu_View_PrevLine:
554 		doCommand( DCMD_LINEUP, 1 );
555 		break;
556 	case Menu_View_Begin:
557 	    doCommand( DCMD_BEGIN, 0 );
558 		break;
559 	case Menu_View_End:
560 		doCommand( DCMD_END, 0 );
561 		break;
562     case Menu_View_TogglePages:
563         ToggleViewMode();
564         break;
565     case Menu_View_TogglePageHeader:
566         _props->setBool( PROP_PAGE_HEADER_ENABLED, !_props->getBoolDef(PROP_PAGE_HEADER_ENABLED, true) );
567         SetPageHeaderFlags();
568         break;
569     case Menu_View_Text_Format:
570 		doCommand( DCMD_TOGGLE_TEXT_FORMAT, 0 );
571         break;
572 	}
573 }
574 
OnScroll(wxScrollEvent & event)575 void cr3view::OnScroll(wxScrollEvent& event)
576 {
577     int id = event.GetEventType();
578     //printf("Scroll event: %d\n", id);
579     if (id == wxEVT_SCROLL_TOP)
580         doCommand( DCMD_BEGIN, 0 );
581     else if (id == wxEVT_SCROLL_BOTTOM )
582         doCommand( DCMD_BEGIN, 0 );
583     else if (id == wxEVT_SCROLL_LINEUP )
584         doCommand( DCMD_LINEUP, 0 );
585     else if (id == wxEVT_SCROLL_LINEDOWN )
586         doCommand( DCMD_LINEDOWN, 0 );
587     else if (id == wxEVT_SCROLL_PAGEUP )
588         doCommand( DCMD_PAGEUP, 0 );
589     else if (id == wxEVT_SCROLL_PAGEDOWN )
590         doCommand( DCMD_PAGEDOWN, 0 );
591     else if (id == wxEVT_SCROLL_THUMBRELEASE || id == wxEVT_SCROLL_THUMBTRACK)
592     {
593         doCommand( DCMD_GO_POS,
594                    getDocView()->scrollPosToDocPos( event.GetPosition() ) );
595     }
596 }
597 
OnMouseWheel(wxMouseEvent & event)598 void cr3view::OnMouseWheel(wxMouseEvent& event)
599 {
600     int rotation = event.GetWheelRotation();
601     if ( rotation>0 )
602         doCommand( DCMD_LINEUP, 3 );
603     else if ( rotation<0 )
604         doCommand( DCMD_LINEDOWN, 3 );
605 }
606 
OnKeyDown(wxKeyEvent & event)607 void cr3view::OnKeyDown(wxKeyEvent& event)
608 {
609     int code = event.GetKeyCode() ;
610 
611         switch( code )
612         {
613         case WXK_NUMPAD_ADD:
614             {
615         doCommand( DCMD_ZOOM_IN, 0 );
616             }
617             break;
618         case WXK_NUMPAD_SUBTRACT:
619             {
620         doCommand( DCMD_ZOOM_OUT, 0 );
621             }
622             break;
623 /*        case WXK_UP:
624             {
625 		doCommand( DCMD_LINEUP, 1 );
626             }
627             break;
628         case WXK_DOWN:
629             {
630 		doCommand( DCMD_LINEDOWN, 1 );
631             }
632             break;
633         case WXK_PAGEUP:
634             {
635 		doCommand( DCMD_PAGEUP, 1 );
636             }
637             break;
638         case WXK_PAGEDOWN:
639             {
640 		doCommand( DCMD_PAGEDOWN, 1 );
641             }
642             break;
643         case WXK_HOME:
644             {
645 		doCommand( DCMD_BEGIN, 0 );
646             }
647             break;
648         case WXK_END:
649             {
650 		doCommand( DCMD_END, 0 );
651             }
652             break;
653 */
654 
655         }
656 }
657 
LoadDocument(const wxString & fname)658 bool cr3view::LoadDocument( const wxString & fname )
659 {
660     //printf("cr3view::LoadDocument()\n");
661     _renderTimer->Stop();
662     _clockTimer->Stop();
663     CloseDocument();
664 
665 	wxCursor hg( wxCURSOR_WAIT );
666 	this->SetCursor( hg );
667 	wxSetCursor( hg );
668     //===========================================
669     GetParent()->Update();
670     //printf("   loading...  ");
671     lString32 fname32 = wx2cr(fname);
672     bool res = getDocView()->LoadDocument( fname32.c_str() );
673     //printf("   done. \n");
674 	//DEBUG
675 	//_docview->exportWolFile( "test.wol", true );
676 	//_docview->SetPos(0);
677     if ( !res )
678         getDocView()->createDefaultDocument(lString32("File open error"), lString32("Cannot open file ") + fname32 );
679     lString32 title = getDocView()->getAuthors();
680     if ( !title.empty() && !getDocView()->getTitle().empty() )
681         title << U". ";
682     title << getDocView()->getTitle();
683     GetParent()->SetLabel( cr2wx(title) );
684 
685     //UpdateScrollBar();
686     _firstRender = true;
687     _allowRender = false;
688     ScheduleRender();
689     //_docview->restorePosition();
690 	//_docview->Render();
691 	//UpdateScrollBar();
692 	//Paint();
693     GetParent()->SetFocus();
694     //===========================================
695 	wxSetCursor( wxNullCursor );
696 	this->SetCursor( wxNullCursor );
697     return res;
698 }
699 
goToBookmark(ldomXPointer bm)700 void cr3view::goToBookmark(ldomXPointer bm)
701 {
702     getDocView()->goToBookmark(bm);
703     UpdateScrollBar();
704     Paint();
705 }
706 
SetRotate(cr_rotate_angle_t angle)707 void cr3view::SetRotate( cr_rotate_angle_t angle )
708 {
709     getDocView()->SetRotateAngle( angle );
710     _props->setInt( PROP_WINDOW_ROTATE_ANGLE, angle );
711     UpdateScrollBar();
712     Paint();
713 }
714 
Rotate(bool ccw)715 void cr3view::Rotate( bool ccw )
716 {
717     int angle = (getDocView()->GetRotateAngle() + 4 + (ccw?-1:1)) & 3;
718     SetRotate( (cr_rotate_angle_t) angle );
719 }
720 
doCommand(LVDocCmd cmd,int param)721 void cr3view::doCommand( LVDocCmd cmd, int param )
722 {
723     _docwin->onCommand( cmd, param );
724     UpdateScrollBar();
725     Paint();
726 }
727 
Resize(int dx,int dy)728 void cr3view::Resize(int dx, int dy)
729 {
730     //printf("   Resize(%d,%d) \n", dx, dy );
731     if ( dx==0 && dy==0 ) {
732         GetClientSize( &dx, &dy );
733     }
734     if ( getDocView()->IsRendered() && getDocView()->GetWidth() == dx && getDocView()->GetHeight() == dy )
735         return; // no resize
736     if (dx<5 || dy<5 || dx>3000 || dy>3000)
737     {
738         return;
739     }
740 
741 	_renderTimer->Stop();
742     _renderTimer->Start( 100, wxTIMER_ONE_SHOT );
743     _clockTimer->Stop();
744     _clockTimer->Start( 10 * 1000, wxTIMER_CONTINUOUS );
745 
746     if ( _isFullscreen ) {
747         _cursorTimer->Stop();
748         _cursorTimer->Start( 3 * 1000, wxTIMER_ONE_SHOT );
749     }
750 
751     SetCursor( wxNullCursor );
752 }
753 
OnPaint(wxPaintEvent & event)754 void cr3view::OnPaint(wxPaintEvent& event)
755 {
756     //printf("   OnPaint()  \n" );
757     wxPaintDC dc(this);
758     if ( !_allowRender ) {
759         dc.Clear();
760         return;
761     }
762 
763     int dx, dy;
764     GetClientSize( &dx, &dy );
765     if ( !getDocView()->IsRendered() && (getDocView()->GetWidth() != dx || getDocView()->GetHeight() != dy) ) {
766         if ( _firstRender ) {
767             getDocView()->restorePosition();
768             _firstRender = false;
769         }
770 
771         getDocView()->Resize( dx, dy );
772         return;
773     }
774 
775     // draw
776     _wm.update( true );
777     wxBitmap bmp = _screen.getWxBitmap();
778     dc.DrawBitmap( bmp, 0, 0, false );
779 }
780 
OnSize(wxSizeEvent & event)781 void cr3view::OnSize(wxSizeEvent& event)
782 {
783     int width, height;
784     GetClientSize( &width, &height );
785     //printf("   OnSize(%d, %d)  \n", width, height );
786     Resize( width, height );
787 }
788 
789 
790 // LVDocViewCallback override
OnExternalLink(lString32 url,ldomNode * node)791 void cr3view::OnExternalLink( lString32 url, ldomNode * node )
792 {
793     ::wxLaunchDefaultBrowser( cr2wx(url) );
794 }
795