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 // $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
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:
284  m_window->SetOrientation( event.GetId() - wxPL_Orientation_0 );
285  break;
286  case wxPL_Locate:
287  if ( m_dev->locate_mode )
288  {
290  wxPLGetApp().SetAdvanceFlag();
291  m_dev->locate_mode = 0;
292  m_dev->draw_xhair = false;
293  }
294  else
295  {
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 );
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  {
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':
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;
630  m_dev->clipmaxx = 0;
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
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
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 //--------------------------------------------------------------------------
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 );
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