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