PLplot: wxwidgets_app.cpp Source File

PLplot 5.10.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
wxwidgets_app.cpp
Go to the documentation of this file.
1 // $Id: wxwidgets_app.cpp 12009 2011-10-28 13:06:27Z andrewross $
2 //
3 // Copyright (C) 2008 Werner Smekal
4 //
5 // This file is part of PLplot.
6 //
7 // PLplot is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU Library General Public License as published
9 // by the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // PLplot is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with PLplot; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21
22 // TODO:
23 // - Add dialog to get width and height from user for plot size to save.
24 //
25
26 // wxwidgets headers
27 #include "wx/wx.h"
28
29 #include "plDevs.h"
30
31 #ifdef PLD_wxwidgets
32
33 // plplot headers
34 #include "plplotP.h"
35 #include "drivers.h"
36 #include "plevent.h"
37
38 // std and driver headers
39 #include "wxwidgets.h"
40
41 // Application icon as XPM
42 // This free icon was taken from http://2pt3.com/news/twotone-icons-for-free/
43 static const char *graph[] = {
44 // columns rows colors chars-per-pixel
45 "16 16 4 2",
46 " c black",
47 ". c #BA1825",
48 "X c gray100",
49 "UX c None",
50 // pixels
51 "UX. . . . . . . . . . . . . . UX",
52 ". . . . . . . . . . . . . . . . ",
53 ". . . . . . . . . . . . . . . . ",
54 ". . . . . . . . . . . X X . . . ",
55 ". . . . . . . . . . . X X . . . ",
56 ". . . . . . . . . . . X X . . . ",
57 ". . . . . X X . . . . X X . . . ",
58 ". . . . . X X . . . . X X . . . ",
59 ". . . . . X X . X X . X X . . . ",
60 ". . . . . X X . X X . X X . . . ",
61 ". . . . . X X . X X . X X . . . ",
62 ". . . . . X X . X X . X X . . . ",
63 ". . . X X X X X X X X X X . . . ",
64 ". . . . . . . . . . . . . . . . ",
65 ". . . . . . . . . . . . . . . . ",
66 "UX. . . . . . . . . . . . . . UX"
67 };
68
69 struct dev_entry dev_entries[] =
70 {
71 { wxT( "wxbmp" ), wxT( "bmp (wx)..." ), wxT( "Save this plot as bmp!" ), wxT( "bmp files (*.bmp)|*.bmp" ), true },
72 { wxT( "wxpng" ), wxT( "png (wx)..." ), wxT( "Save this plot as png" ), wxT( "png files (*.png)|*.png" ), true },
73 { wxT( "wxpcx" ), wxT( "pcx (wx)..." ), wxT( "Save this plot as pcx!" ), wxT( "pcx files (*.pcx)|*.pcx" ), true },
74 { wxT( "wxjpeg" ), wxT( "jpeg (wx)..." ), wxT( "Save this plot as jpeg!" ), wxT( "jpg files (*.jpg;*.jpeg)|*.jpg;*.jpeg" ), true },
75 { wxT( "wxtiff" ), wxT( "tiff (wx)..." ), wxT( "Save this plot as tiff!" ), wxT( "tiff files (*.tif;*.tiff)|*.tif;*.tiff" ), true },
76 { wxT( "wxpnm" ), wxT( "pnm (wx)..." ), wxT( "Save this plot as pnm!" ), wxT( "pnm files (*.pnm)|*.pnm" ), true },
77 { wxT( "pngcairo" ), wxT( "png (cairo)..." ), wxT( "Save this plot as png using cairo!" ), wxT( "png files (*.png)|*.png" ), true },
78 { wxT( "pdfcairo" ), wxT( "pdf (cairo)..." ), wxT( "Save this plot as pdf using cairo!" ), wxT( "pdf files (*.pdf)|*.pdf" ), false },
79 { wxT( "ps" ), wxT( "postscript..." ), wxT( "Save this plot as postscript!" ), wxT( "ps files (*.ps)|*.ps" ), false },
80 { wxT( "psc" ), wxT( "color postscript..." ), wxT( "Save this plot as color postscript!" ), wxT( "ps files (*.ps;*.psc)|*.ps;*.psc" ), false },
81 { wxT( "pscairo" ), wxT( "color postscript (cairo)..." ), wxT( "Save this plot as color postscript using cairo!" ), wxT( "ps files (*.ps;*.psc)|*.ps;*.psc" ), false },
82 { wxT( "svg" ), wxT( "svg..." ), wxT( "Save this plot as svg!" ), wxT( "svg files (*.svg)|*.svg" ), false },
83 { wxT( "svgcairo" ), wxT( "svg (cairo)..." ), wxT( "Save this plot as svg using cairo!" ), wxT( "svg files (*.svg)|*.svg" ), false },
84 { wxT( "xfig" ), wxT( "xfig..." ), wxT( "Save this plot as xfig!" ), wxT( "fig files (*.fig)|*.fig" ), false }
85 };
86
87 // Application implementation
88 IMPLEMENT_PLAPP_NO_MAIN( wxPLplotApp )
89
90 // event table for the app
91 BEGIN_EVENT_TABLE( wxPLplotApp, wxApp )
92 EVT_IDLE( wxPLplotApp::OnIdle )
93 END_EVENT_TABLE()
94
95 // event table for frames
96 BEGIN_EVENT_TABLE( wxPLplotFrame, wxFrame )
97 EVT_MENU( -1, wxPLplotFrame::OnMenu ) // handle all menu events
98 EVT_CLOSE( wxPLplotFrame::OnClose )
99 END_EVENT_TABLE()
100
101 // event table for the plot widget
102 BEGIN_EVENT_TABLE( wxPLplotWindow, wxWindow )
103 EVT_PAINT( wxPLplotWindow::OnPaint ) // (re)draw the plot in window
104 EVT_CHAR( wxPLplotWindow::OnChar )
105 EVT_IDLE( wxPLplotWindow::OnIdle )
106 EVT_MOUSE_EVENTS( wxPLplotWindow::OnMouse )
107 EVT_ERASE_BACKGROUND( wxPLplotWindow::OnErase )
108 EVT_SIZE( wxPLplotWindow::OnSize )
109 EVT_MAXIMIZE( wxPLplotWindow::OnMaximize )
110 END_EVENT_TABLE()
111
112 // event table for the size dialog
113 BEGIN_EVENT_TABLE( wxGetSizeDialog, wxDialog )
114 END_EVENT_TABLE()
115
116 //--------------------------------------------------------------------------
117 // bool wxPLplotApp::OnInit()
118 //
119 // This method is called before the applications gets control.
120 //--------------------------------------------------------------------------
121 bool wxPLplotApp::OnInit()
122 {
123 // Log_Verbose( "wxPLplotApp::OnInit" );
124
125 exit = false;
126 advance = false;
127
128 #if wxUSE_LIBPNG
129 wxImage::AddHandler( new wxPNGHandler );
130 #endif
131 #if wxUSE_LIBJPEG
132 wxImage::AddHandler( new wxJPEGHandler );
133 #endif
134 #if wxUSE_PCX
135 wxImage::AddHandler( new wxPCXHandler );
136 #endif
137 #if wxUSE_LIBTIFF
138 wxImage::AddHandler( new wxTIFFHandler );
139 #endif
140 #if wxUSE_PNM
141 wxImage::AddHandler( new wxPNMHandler );
142 #endif
143
144 return true;
145 }
146
147
148 //--------------------------------------------------------------------------
149 // void wxPLplotApp::SetRefreshFlag( bool flag )
150 //
151 // XXX - missing
152 //--------------------------------------------------------------------------
153 void wxPLplotApp::SetRefreshFlag( bool flag )
154 {
155 // Log_Verbose( "wxPLplotApp::SetRefreshFlag" );
156
157 for ( size_t i = 0; i < FrameArray.GetCount(); i++ )
158 FrameArray[i]->SetRefreshFlag( flag );
159 }
160
161
162 //--------------------------------------------------------------------------
163 // void wxPLplotApp::OnIdle( wxIdleEvent& WXUNUSED(event) )
164 //
165 // XXX - missing
166 //--------------------------------------------------------------------------
167 void wxPLplotApp::OnIdle( wxIdleEvent& WXUNUSED( event ) )
168 {
169 // Log_Verbose( "wxPLplotApp::OnIdle" );
170
171 bool refresh = false;
172
173 if ( exit )
174 ExitMainLoop();
175
176 for ( size_t i = 0; i < FrameArray.GetCount(); i++ )
177 refresh |= FrameArray[i]->GetRefreshFlag();
178
179 if ( advance && !refresh )
180 ExitMainLoop();
181 }
182
183
184 //--------------------------------------------------------------------------
185 // wxPLplotFrame::wxPLplotFrame( const wxString& title, PLStream *pls )
186 //
187 // Constructor of wxPLplotFrame, where we create the menu and add the
188 // wxPLplotWindow. We need also to know the current PLStream.
189 //--------------------------------------------------------------------------
190 wxPLplotFrame::wxPLplotFrame( const wxString& title, PLStream *pls )
191 : wxFrame( NULL, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
192 wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION |
193 wxCLOSE_BOX | wxRESIZE_BORDER | wxCLIP_CHILDREN )
194 {
195 // Log_Verbose( "wxPLplotFrame::wxPLplotFrame" );
196
197 m_dev = (wxPLDevBase *) pls->dev;
198
199 m_panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN );
200 wxBoxSizer* box = new wxBoxSizer( wxVERTICAL );
201 m_window = new wxPLplotWindow( m_panel, pls );
202 box->Add( m_window, 1, wxALL | wxEXPAND, 0 );
203 m_panel->SetSizer( box );
204 m_window->SetFocus();
205
206 wxMenu* saveMenu = new wxMenu;
207 saveMenu->Append( wxPL_Save, dev_entries[0].dev_menu_short, dev_entries[0].dev_menu_long );
208 #if wxUSE_LIBPNG
209 saveMenu->Append( wxPL_Save + 1, dev_entries[1].dev_menu_short, dev_entries[1].dev_menu_long );
210 #endif
211 #if wxUSE_PCX
212 saveMenu->Append( wxPL_Save + 2, dev_entries[2].dev_menu_short, dev_entries[2].dev_menu_long );
213 #endif
214 #if wxUSE_LIBJPEG
215 saveMenu->Append( wxPL_Save + 3, dev_entries[3].dev_menu_short, dev_entries[3].dev_menu_long );
216 #endif
217 #if wxUSE_LIBTIFF
218 saveMenu->Append( wxPL_Save + 4, dev_entries[4].dev_menu_short, dev_entries[4].dev_menu_long );
219 #endif
220 #if wxUSE_PNM
221 saveMenu->Append( wxPL_Save + 5, dev_entries[5].dev_menu_short, dev_entries[5].dev_menu_long );
222 #endif
223 for ( size_t j = 6; j < sizeof ( dev_entries ) / sizeof ( dev_entry ); j++ )
224 for ( int i = 0; i < m_dev->ndev; i++ )
225 {
226 if ( !strcmp( m_dev->devName[i], dev_entries[j].dev_name.mb_str() ) )
227 saveMenu->Append( wxPL_Save + j, dev_entries[j].dev_menu_short, dev_entries[j].dev_menu_long );
228 }
229
230 wxMenu* fileMenu = new wxMenu;
231 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 6 )
232 fileMenu->Append( -1, wxT( "Save plot as..." ), saveMenu, wxT( "Save this plot as ...!" ) );
233 #else
234 fileMenu->AppendSubMenu( saveMenu, wxT( "Save plot as..." ), wxT( "Save this plot as ...!" ) );
235 #endif
236 fileMenu->Append( wxID_EXIT, wxT( "E&xit\tAlt-X" ), wxT( "Exit wxWidgets PLplot App" ) );
237
238 wxMenu* orientationMenu = new wxMenu;
239 orientationMenu->Append( wxPL_Orientation_0, wxT( "0 deg." ), wxT( "Orientation 0 deg." ) );
240 orientationMenu->Append( wxPL_Orientation_90, wxT( "90 deg." ), wxT( "Orientation 90 deg." ) );
241 orientationMenu->Append( wxPL_Orientation_180, wxT( "180 deg." ), wxT( "Orientation 180 deg." ) );
242 orientationMenu->Append( wxPL_Orientation_270, wxT( "270 deg." ), wxT( "Orientation 270 deg." ) );
243
244 wxMenu* plotMenu = new wxMenu;
245 plotMenu->Append( wxPL_Locate, wxT( "Locate\tL" ), wxT( "Enter locate mode" ) );
246 // only add the orientation menu for hershey text processing
247 if ( !pls->dev_text )
248 {
249 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 6 )
250 plotMenu->Append( -1, wxT( "Set Orientation to..." ), orientationMenu, wxT( "Set the Orientation of the plot!" ) );
251 #else
252 plotMenu->AppendSubMenu( orientationMenu, wxT( "Set Orientation to..." ), wxT( "Set the Orientation of the plot!" ) );
253 #endif
254 }
255
256 wxMenuBar* menuBar = new wxMenuBar();
257 menuBar->Append( fileMenu, wxT( "&File" ) );
258 menuBar->Append( plotMenu, wxT( "&Plot" ) );
259 SetMenuBar( menuBar );
260
261 SetIcon( wxIcon( graph ) );
262 }
263
264
265 //--------------------------------------------------------------------------
266 // void wxPLplotFrame::OnMenu( wxCommandEvent& event )
267 //
268 // Event method, which is called if user
269 //--------------------------------------------------------------------------
270 void wxPLplotFrame::OnMenu( wxCommandEvent& event )
271 {
272 // Log_Verbose( "wxPLplotFrame::OnMenu" );
273
274 switch ( event.GetId() )
275 {
276 case wxID_EXIT:
277 m_dev->exit = true;
278 wxPLGetApp().ExitMainLoop();
279 break;
280 case wxPL_Orientation_0:
281 case wxPL_Orientation_90:
282 case wxPL_Orientation_180:
283 case wxPL_Orientation_270:
284 m_window->SetOrientation( event.GetId() - wxPL_Orientation_0 );
285 break;
286 case wxPL_Locate:
287 if ( m_dev->locate_mode )
288 {
289 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_API )
290 wxPLGetApp().SetAdvanceFlag();
291 m_dev->locate_mode = 0;
292 m_dev->draw_xhair = false;
293 }
294 else
295 {
296 m_dev->locate_mode = LOCATE_INVOKED_VIA_DRIVER;
297 m_dev->draw_xhair = true;
298 }
299 break;
300 }
301
302 size_t index = event.GetId() - wxPL_Save;
303 if ( ( event.GetId() >= wxPL_Save ) && ( index < sizeof ( dev_entries ) / sizeof ( dev_entry ) ) )
304 {
305 int width = 800;
306 int height = 600;
307 bool proceed = false;
308
309 // ask for geometry in pixels only for image devices
310 if ( dev_entries[index].pixelDevice )
311 {
312 wxGetSizeDialog sizeDialog( this, -1, wxT( "Size of plot" ), wxDefaultPosition, wxDefaultSize,
313 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, width, height );
314 if ( sizeDialog.ShowModal() == wxID_OK )
315 {
316 width = sizeDialog.getWidth();
317 height = sizeDialog.getHeight();
318 proceed = true;
319 }
320 }
321 else
322 proceed = true;
323
324 if ( proceed )
325 {
326 wxFileDialog dialog( this, wxT( "Save plot as " ) + dev_entries[index].dev_name, wxT( "" ), wxT( "" ),
327 dev_entries[index].dev_file_app + wxT( "|All Files (*.*)|*.*" ),
328 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 6 )
329 wxSAVE | wxOVERWRITE_PROMPT );
330 #else
331 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
332 #endif
333 if ( dialog.ShowModal() == wxID_OK )
334 {
335 const wxCharBuffer buf1 = dialog.GetPath().mb_str();
336 const wxCharBuffer buf2 = dev_entries[index].dev_name.mb_str();
337 SavePlot( (const char *) buf1, (const char *) buf2, width, height );
338 }
339 }
340 }
341 }
342
343 //--------------------------------------------------------------------------
344 // void wxPLplotFrame::OnClose( wxCloseEvent& event )
345 //
346 // Event method, which is called if user
347 //--------------------------------------------------------------------------
348 void wxPLplotFrame::OnClose( wxCloseEvent& /* event */ )
349 {
350 // Log_Verbose( "wxPLplotFrame::OnClose" );
351
352 m_dev->exit = true;
353 wxPLGetApp().ExitMainLoop();
354 }
355
356
357 //--------------------------------------------------------------------------
358 // bool wxPLplotFrame::SavePlot( const char* filename, cost char* dev, int width,
359 // int height )
360 //
361 // This function saves the current plot to a file (filename) using a
362 // device (devname) with given width and height. There is no test if
363 // the device really exists.
364 //--------------------------------------------------------------------------
365 bool wxPLplotFrame::SavePlot( const char* filename, const char* devname, int width, int height )
366 {
367 int pls, pls_save;
368
369 if ( !strcmp( devname, "wxbmp" ) || !strcmp( devname, "wxpng" ) || !strcmp( devname, "wxpcx" ) ||
370 !strcmp( devname, "wxjpeg" ) || !strcmp( devname, "wxtiff" ) || !strcmp( devname, "wxpnm" ) )
371 {
372 wxMemoryDC memDC;
373
374 wxBitmap bitmap( width, height, -1 );
375 memDC.SelectObject( bitmap );
376
377 plgstrm( &pls );
378 plmkstrm( &pls_save );
379 plsdev( "wxwidgets" );
380 plspage( 0.0, 0.0, width, height, 0, 0 );
381
382 plsetopt( "-drvopt", "backend=0" );
383 plinit();
384 pl_cmd( PLESC_DEVINIT, (void *) &memDC );
385
386 plcpstrm( pls, 0 );
387 pladv( 0 );
388 plreplot();
389 plend1();
390 plsstrm( pls );
391
392 wxBitmapType type;
393 if ( !strcmp( devname, "wxbmp" ) )
394 type = wxBITMAP_TYPE_BMP;
395 #if wxUSE_LIBPNG
396 else if ( !strcmp( devname, "wxpng" ) )
397 type = wxBITMAP_TYPE_PNG;
398 #endif
399 #if wxUSE_PCX
400 else if ( !strcmp( devname, "wxpcx" ) )
401 type = wxBITMAP_TYPE_PCX;
402 #endif
403 #if wxUSE_LIBJPEG
404 else if ( !strcmp( devname, "wxjpeg" ) )
405 type = wxBITMAP_TYPE_JPEG;
406 #endif
407 #if wxUSE_LIBTIFF
408 else if ( !strcmp( devname, "wxtiff" ) )
409 type = wxBITMAP_TYPE_TIF;
410 #endif
411 #if wxUSE_PNM
412 else if ( !strcmp( devname, "wxpnm" ) )
413 type = wxBITMAP_TYPE_PNM;
414 #endif
415 else
416 type = wxBITMAP_TYPE_BMP;
417 bool status = bitmap.SaveFile( wxString( filename, *wxConvCurrent ), type );
418
419 if ( !status )
420 {
421 char buf[512];
422 snprintf( buf, 512, "File %s couldn't be saved", filename );
423 plabort( buf );
424 return false;
425 }
426 }
427 else
428 {
429 plgstrm( &pls );
430 plmkstrm( &pls_save );
431
432 plsdev( devname );
433 //plspage( 0., 0., width, height, 0, 0 );
434 plsfnam( filename );
435
436 plcpstrm( pls, 0 );
437 pladv( 0 );
438 plreplot();
439 plend1();
440 plsstrm( pls );
441 }
442
443 return true;
444 }
445
446
447 //--------------------------------------------------------------------------
448 // wxPLplotWindow::wxPLplotWindow( const wxString& title )
449 //
450 // Constructor of wxPLplotFrame, where we create the menu.
451 //--------------------------------------------------------------------------
452 wxPLplotWindow::wxPLplotWindow( wxWindow* parent, PLStream *pls )
453 : wxWindow( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
454 wxNO_BORDER | wxWANTS_CHARS | wxCLIP_CHILDREN )
455 {
456 // Log_Verbose( "wxPLplotWindow::wxPLplotWindow" );
457
458 m_pls = pls;
459 m_dev = (wxPLDevBase *) pls->dev;
460 refresh = false;
461 mouse_x = old_mouse_x = -1;
462 mouse_y = old_mouse_y = -1;
463 xhair_drawn = false;
464
465 SetBackgroundStyle( wxBG_STYLE_CUSTOM );
466 }
467
468
469 //--------------------------------------------------------------------------
470 // void wxPLplotWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
471 //
472 // Event method where the plots are actually drawn. Since the plots
473 // are already drawn into bitmaps, which just copy them into to client
474 // area. This method is also called, if (part) of the client area was
475 // invalidated and a refresh is necessary.
476 //--------------------------------------------------------------------------
477 void wxPLplotWindow::OnPaint( wxPaintEvent& WXUNUSED( event ) )
478 {
479 // Log_Verbose( "wxPLplotWindow::OnPaint" );
480
481 // copy bitmap into client area
482 wxPaintDC dc( this );
483
484 // only update damaged regions
485 int vX, vY, vW, vH;
486 wxRegionIterator upd( GetUpdateRegion() );
487
488 // remove the xhair before updating
489 if ( m_dev->draw_xhair && upd && xhair_drawn )
490 {
491 dc.SetLogicalFunction( wxINVERT );
492 dc.CrossHair( old_mouse_x, old_mouse_y );
493 dc.SetLogicalFunction( wxCOPY );
494 xhair_drawn = false;
495 old_mouse_x = old_mouse_y = -1;
496 }
497
498 while ( upd )
499 {
500 vX = upd.GetX();
501 vY = upd.GetY();
502 vW = upd.GetW();
503 vH = upd.GetH();
504
505 //printf( "Clipping region: x=%d, y=%d, width=%d, height=%d, counter=%d\n", vX, vY, vW, vH, counter++ );
506
507 m_dev->BlitRectangle( &dc, vX, vY, vW, vH );
508
509 upd++;
510 }
511
512 if ( m_dev->draw_xhair && !xhair_drawn )
513 {
514 dc.SetLogicalFunction( wxINVERT );
515 dc.CrossHair( mouse_x, mouse_y );
516 dc.SetLogicalFunction( wxCOPY );
517 old_mouse_x = mouse_x;
518 old_mouse_y = mouse_y;
519 xhair_drawn = true;
520 }
521 }
522
523
524 //--------------------------------------------------------------------------
525 // void wxPLplotWindow::OnChar( wxKeyEvent& event )
526 //
527 // Handle key events.
528 //--------------------------------------------------------------------------
529 void wxPLplotWindow::OnChar( wxKeyEvent& event )
530 {
531 // Log_Verbose( "wxPLplotWindow::OnChar" );
532
533 PLGraphicsIn *gin = &( m_dev->gin );
534
535 int width, height;
536 GetClientSize( &width, &height );
537
538 gin->pX = mouse_x;
539 gin->pY = mouse_y;
540 gin->dX = (PLFLT) mouse_x / ( width - 1 );
541 gin->dY = 1.0 - (PLFLT) mouse_y / ( height - 1 );
542
543 // gin->state = keyEvent->state;
544
545 int keycode = event.GetKeyCode();
546 gin->string[0] = (char) keycode;
547 gin->string[1] = '\0';
548
549 // ESCAPE, RETURN, etc. are already in ASCII equivalent
550 gin->keysym = keycode;
551
552 if ( m_dev->locate_mode )
553 {
554 // End locate mode on <Escape>
555 if ( gin->keysym == PLK_Escape )
556 {
557 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_API )
558 wxPLGetApp().SetAdvanceFlag();
559 m_dev->locate_mode = 0;
560 m_dev->draw_xhair = false;
561 DrawCrosshair();
562 plGinInit( gin );
563 }
564
565 Locate();
566 }
567 else
568 {
569 // Call user keypress event handler. Since this is called first, the user
570 // can disable all internal event handling by setting gin.keysym to 0.
571 if ( m_pls->KeyEH != NULL )
572 {
573 int advance = 0;
574 ( *m_pls->KeyEH )( gin, m_pls->KeyEH_data, &advance );
575 if ( advance )
576 wxPLGetApp().SetAdvanceFlag();
577 }
578
579 switch ( gin->keysym )
580 {
581 case 'L':
582 m_dev->locate_mode = LOCATE_INVOKED_VIA_DRIVER;
583 m_dev->draw_xhair = true;
584 DrawCrosshair();
585 break;
586 case 'Q':
587 case PLK_Escape:
588 m_dev->exit = true;
589 wxPLGetApp().SetExitFlag();
590 break;
591 case PLK_Return:
592 case WXK_SPACE:
593 case WXK_RIGHT:
594 wxPLGetApp().SetAdvanceFlag();
595 break;
596 default:
597 break;
598 }
599 }
600
601 event.Skip();
602 }
603
604
605 //--------------------------------------------------------------------------
606 // void wxPLplotWindow::OnIdle( wxIdleEvent& WXUNUSED(event) )
607 //
608 // If there is no pending event, maybe the canvas needs to be refreshed.
609 //--------------------------------------------------------------------------
610 void wxPLplotWindow::OnIdle( wxIdleEvent& WXUNUSED( event ) )
611 {
612 // Log_Verbose( "wxPLplotWindow::OnIdle" );
613
614 if ( refresh )
615 {
616 if ( !m_dev->newclipregion )
617 {
618 static wxRect rect;
619 rect.x = m_dev->clipminx;
620 rect.y = m_dev->clipminy;
621 rect.width = m_dev->clipmaxx - m_dev->clipminx + 1;
622 rect.height = m_dev->clipmaxy - m_dev->clipminy + 1;
623 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 5 )
624 RefreshRect( rect );
625 #else
626 RefreshRect( rect, false ); // don't erase background
627 #endif
628 m_dev->newclipregion = true;
629 m_dev->clipminx = m_dev->width;
630 m_dev->clipmaxx = 0;
631 m_dev->clipminy = m_dev->height;
632 m_dev->clipmaxy = 0;
633 }
634 else
635 Refresh( false );
636 refresh = false;
637 }
638 }
639
640
641 //--------------------------------------------------------------------------
642 // void wxPLplotWindow::OnErase( wxEraseEvent &WXUNUSED(event) )
643 //
644 // Do nothing here to prevent flickering.
645 //--------------------------------------------------------------------------
646 void wxPLplotWindow::OnErase( wxEraseEvent &WXUNUSED( event ) )
647 {
648 // Log_Verbose( "wxPLplotWindow::OnErase" );
649 }
650
651
652 //--------------------------------------------------------------------------
653 // void wxPLplotWindow::OnSize( wxSizeEvent & WXUNUSED(event) )
654 //
655 // Allocate a bigger bitmap if necessary and redo the plot if the
656 // window size was changed.
657 //--------------------------------------------------------------------------
658 void wxPLplotWindow::OnSize( wxSizeEvent & WXUNUSED( event ) )
659 {
660 // Log_Verbose( "wxPLplotWindow::OnSize" );
661
662 int width, height;
663 GetClientSize( &width, &height );
664
665 if ( m_dev->waiting )
666 {
667 if ( ( width != m_dev->width ) || ( height != m_dev->height ) )
668 {
669 // get a new bitmap if new size is bigger as bitmap size
670 if ( ( width > m_dev->bm_width ) || ( height > m_dev->bm_height ) )
671 {
672 m_dev->bm_width = m_dev->bm_width > width ? m_dev->bm_width : width;
673 m_dev->bm_height = m_dev->bm_height > height ? m_dev->bm_height : height;
674 }
675
676 wx_set_size( m_pls, width, height );
677 m_dev->resizing = true;
678 plRemakePlot( m_pls );
679 m_dev->resizing = false;
680 Refresh();
681 }
682 }
683 }
684
685
686 //--------------------------------------------------------------------------
687 // wxPLplotWindow::OnMaximize( wxMaximizeEvent & WXUNUSED(event) )
688 //
689 // Add a size event if the Window is maximized.
690 //--------------------------------------------------------------------------
691 void wxPLplotWindow::OnMaximize( wxMaximizeEvent & WXUNUSED( event ) )
692 {
693 // Log_Verbose( "wxPLplotWindow::OnMax" );
694
695 wxSizeEvent event( GetClientSize() );
696 AddPendingEvent( event );
697 }
698
699
700 //--------------------------------------------------------------------------
701 // void wxPLplotWindow::OnMouse( wxMouseEvent &event )
702 //
703 // Handle mouse events.
704 //--------------------------------------------------------------------------
705 void wxPLplotWindow::OnMouse( wxMouseEvent &event )
706 {
707 // Log_Verbose( "wxPLplotWindow::OnMouse" );
708
709 wxPoint pos( event.GetPosition() );
710 mouse_x = pos.x;
711 mouse_y = pos.y;
712
713 if ( event.ButtonDown() )
714 {
715 PLGraphicsIn *gin = &( m_dev->gin );
716
717 int width, height;
718 GetClientSize( &width, &height );
719
720 gin->pX = mouse_x;
721 gin->pY = mouse_y;
722 gin->dX = (PLFLT) mouse_x / ( width - 1 );
723 gin->dY = 1.0 - (PLFLT) mouse_y / ( height - 1 );
724
725 if ( event.LeftDown() )
726 {
727 gin->button = 1; // X11/X.h: #define Button1 1
728 gin->state = 1 << 8; // X11/X.h: #define Button1Mask (1<<8)
729 }
730 else if ( event.MiddleDown() )
731 {
732 gin->button = 2; // X11/X.h: #define Button2 2
733 gin->state = 1 << 9; // X11/X.h: #define Button2Mask (1<<9)
734 }
735 else if ( event.RightDown() )
736 {
737 gin->button = 3; // X11/X.h: #define Button3 3
738 gin->state = 1 << 10; // X11/X.h: #define Button3Mask (1<<10)
739 }
740 gin->keysym = 0x20; // keysym for button event from xwin.c
741
742 if ( m_dev->locate_mode )
743 Locate();
744 else
745 {
746 // Call user event handler. Since this is called first, the user can
747 // disable all PLplot internal event handling by setting gin->button to 0.
748 if ( m_pls->ButtonEH != NULL )
749 {
750 int advance = 0;
751 ( *m_pls->ButtonEH )( gin, m_pls->ButtonEH_data, &advance );
752 if ( advance )
753 wxPLGetApp().SetAdvanceFlag();
754 }
755
756 // Handle internal events
757 switch ( gin->button )
758 {
759 case 3: // on right mouse button advance
760 wxPLGetApp().SetAdvanceFlag();
761 break;
762 default:
763 break;
764 }
765 }
766 }
767
768 DrawCrosshair();
769 }
770
771
772 //--------------------------------------------------------------------------
773 // void wxPLplotWindow::Locate( void )
774 //
775 // Take care of Locate mode, called by OnChar() and OnMouse().
776 //--------------------------------------------------------------------------
777 void wxPLplotWindow::Locate( void )
778 {
779 // Log_Verbose( "wxPLplotWindow::Locate" );
780
781 PLGraphicsIn *gin = &( m_dev->gin );
782
783 // Some event (key, button) occured, and if the locate mode
784 // was initiated by the API we need to return back to the
785 // user program
786 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_API )
787 wxPLGetApp().SetAdvanceFlag();
788
789 // Call user locate mode handler if provided
790 if ( m_pls->LocateEH != NULL )
791 {
792 int locate_mode = m_dev->locate_mode;
793 ( *m_pls->LocateEH )( gin, m_pls->LocateEH_data, &locate_mode );
794 if ( !locate_mode )
795 {
796 m_dev->locate_mode = 0;
797 m_dev->draw_xhair = false;
798 }
799 }
800 else
801 {
802 if ( plTranslateCursor( gin ) )
803 {
804 // If invoked by the API, we're done
805 // Otherwise send report to stdout
806 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_DRIVER )
807 {
808 if ( gin->keysym < 0xFF && isprint( gin->keysym ) )
809 printf( "%f %f %c\n", gin->wX, gin->wY, gin->keysym );
810 else
811 printf( "%f %f 0x%02x\n", gin->wX, gin->wY, gin->keysym );
812 }
813 }
814 else
815 {
816 // Selected point is out of bounds, so end locate mode
817 m_dev->locate_mode = 0;
818 m_dev->draw_xhair = false;
819 }
820 }
821 DrawCrosshair();
822 }
823
824
825 //--------------------------------------------------------------------------
826 // void wxPLplotWindow::DrawCrosshair()
827 //
828 // Draw a cross hair (inverted lines).
829 //--------------------------------------------------------------------------
830 void wxPLplotWindow::DrawCrosshair()
831 {
832 // draw cross hair
833 wxClientDC dc( this );
834 if ( m_dev->draw_xhair )
835 {
836 if ( ( mouse_x != old_mouse_x ) || ( mouse_y != old_mouse_y ) )
837 {
838 dc.SetLogicalFunction( wxINVERT );
839 if ( xhair_drawn )
840 dc.CrossHair( old_mouse_x, old_mouse_y );
841 dc.CrossHair( mouse_x, mouse_y );
842 dc.SetLogicalFunction( wxCOPY );
843 old_mouse_x = mouse_x;
844 old_mouse_y = mouse_y;
845 xhair_drawn = true;
846 }
847 }
848 else
849 {
850 if ( xhair_drawn )
851 {
852 dc.SetLogicalFunction( wxINVERT );
853 dc.CrossHair( old_mouse_x, old_mouse_y );
854 dc.SetLogicalFunction( wxCOPY );
855 xhair_drawn = false;
856 old_mouse_x = old_mouse_y = -1;
857 }
858 }
859 }
860
861
862 //--------------------------------------------------------------------------
863 // void wxPLplotWindow::SetOrientation( int rot )
864 //
865 // Set the orientation of the plot.
866 //--------------------------------------------------------------------------
867 void wxPLplotWindow::SetOrientation( int rot )
868 {
869 PLINT bgr, bgg, bgb; // red, green, blue
870
871 //plsstrm( m_pls );
872 plsdiori( rot );
873 m_dev->resizing = true;
874 plgcolbg( &bgr, &bgg, &bgb ); // get background color information
875 m_dev->ClearBackground( bgr, bgg, bgb );
876 plRemakePlot( m_pls );
877 m_dev->resizing = false;
878 Refresh();
879 }
880
881 //--------------------------------------------------------------------------
882 // wxGetSizeDialog::wxGetSizeDialog( wxWindow *parent, ... )
883 //
884 // Constructor of GetSizeDialog.
885 //--------------------------------------------------------------------------
886 wxGetSizeDialog::wxGetSizeDialog( wxWindow *parent, wxWindowID id, const wxString &title,
887 const wxPoint &position, const wxSize& size, long style, int width, int height ) :
888 wxDialog( parent, id, title, position, size, style )
889 {
890 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
891
892 wxStaticBoxSizer *staticSizer = new wxStaticBoxSizer( new wxStaticBox( this, -1, wxT( "Size of plot" ) ), wxVERTICAL );
893
894 wxFlexGridSizer *flexSizer = new wxFlexGridSizer( 2, 0, 0 );
895 flexSizer->AddGrowableCol( 1 );
896
897 wxStaticText *textWidth = new wxStaticText( this, -1, wxT( "Width [pixels]:" ), wxDefaultPosition, wxDefaultSize, 0 );
898 flexSizer->Add( textWidth, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
899 spinControlWidth = new wxSpinCtrl( this, -1, wxString::Format( wxT( "%d" ), width ), wxDefaultPosition, wxSize( 100, -1 ), wxSP_ARROW_KEYS, 10, 4096, width );
900 flexSizer->Add( spinControlWidth, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
901 wxStaticText *textHeight = new wxStaticText( this, -1, wxT( "Height [pixels]:" ), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
902 flexSizer->Add( textHeight, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
903 spinControlHeight = new wxSpinCtrl( this, -1, wxString::Format( wxT( "%d" ), height ), wxDefaultPosition, wxSize( 100, -1 ), wxSP_ARROW_KEYS, 10, 4096, height );
904 flexSizer->Add( spinControlHeight, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
905
906 staticSizer->Add( flexSizer, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
907
908 sizer->Add( staticSizer, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
909
910 wxBoxSizer *buttonSizer = new wxBoxSizer( wxHORIZONTAL );
911 wxButton *buttonOK = new wxButton( this, wxID_OK, wxT( "OK" ), wxDefaultPosition, wxDefaultSize, 0 );
912 buttonSizer->Add( buttonOK, 0, wxALIGN_CENTER | wxALL | wxEXPAND, 5 );
913 buttonSizer->Add( 20, 20, 1, wxALIGN_CENTER | wxALL, 5 );
914 wxButton *buttonCancel = new wxButton( this, wxID_CANCEL, wxT( "Cancel" ), wxDefaultPosition, wxDefaultSize, 0 );
915 buttonSizer->Add( buttonCancel, 0, wxALIGN_CENTER | wxALL | wxEXPAND, 5 );
916
917 sizer->Add( buttonSizer, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 15 );
918
919 this->SetSizer( sizer );
920 sizer->SetSizeHints( this );
921 }
922
923 #endif // PLD_wxwidgets