PLplot
5.10.0
|
00001 // Copyright (C) 2008 Werner Smekal 00002 // 00003 // This file is part of PLplot. 00004 // 00005 // PLplot is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU Library General Public License as published 00007 // by the Free Software Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // PLplot is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU Library General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Library General Public License 00016 // along with PLplot; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00018 // 00019 00020 // TODO: 00021 // - Add dialog to get width and height from user for plot size to save. 00022 // 00023 00024 // wxwidgets headers 00025 #include "wx/wx.h" 00026 00027 #include "plDevs.h" 00028 00029 #ifdef PLD_wxwidgets 00030 00031 // plplot headers 00032 #include "plplotP.h" 00033 #include "drivers.h" 00034 #include "plevent.h" 00035 00036 // std and driver headers 00037 #include "wxwidgets.h" 00038 00039 // Application icon as XPM 00040 // This free icon was taken from http://2pt3.com/news/twotone-icons-for-free/ 00041 static const char *graph[] = { 00042 // columns rows colors chars-per-pixel 00043 "16 16 4 2", 00044 " c black", 00045 ". c #BA1825", 00046 "X c gray100", 00047 "UX c None", 00048 // pixels 00049 "UX. . . . . . . . . . . . . . UX", 00050 ". . . . . . . . . . . . . . . . ", 00051 ". . . . . . . . . . . . . . . . ", 00052 ". . . . . . . . . . . X X . . . ", 00053 ". . . . . . . . . . . X X . . . ", 00054 ". . . . . . . . . . . X X . . . ", 00055 ". . . . . X X . . . . X X . . . ", 00056 ". . . . . X X . . . . X X . . . ", 00057 ". . . . . X X . X X . X X . . . ", 00058 ". . . . . X X . X X . X X . . . ", 00059 ". . . . . X X . X X . X X . . . ", 00060 ". . . . . X X . X X . X X . . . ", 00061 ". . . X X X X X X X X X X . . . ", 00062 ". . . . . . . . . . . . . . . . ", 00063 ". . . . . . . . . . . . . . . . ", 00064 "UX. . . . . . . . . . . . . . UX" 00065 }; 00066 00067 struct dev_entry dev_entries[] = 00068 { 00069 { wxT( "wxbmp" ), wxT( "bmp (wx)..." ), wxT( "Save this plot as bmp!" ), wxT( "bmp files (*.bmp)|*.bmp" ), true }, 00070 { wxT( "wxpng" ), wxT( "png (wx)..." ), wxT( "Save this plot as png" ), wxT( "png files (*.png)|*.png" ), true }, 00071 { wxT( "wxpcx" ), wxT( "pcx (wx)..." ), wxT( "Save this plot as pcx!" ), wxT( "pcx files (*.pcx)|*.pcx" ), true }, 00072 { wxT( "wxjpeg" ), wxT( "jpeg (wx)..." ), wxT( "Save this plot as jpeg!" ), wxT( "jpg files (*.jpg;*.jpeg)|*.jpg;*.jpeg" ), true }, 00073 { wxT( "wxtiff" ), wxT( "tiff (wx)..." ), wxT( "Save this plot as tiff!" ), wxT( "tiff files (*.tif;*.tiff)|*.tif;*.tiff" ), true }, 00074 { wxT( "wxpnm" ), wxT( "pnm (wx)..." ), wxT( "Save this plot as pnm!" ), wxT( "pnm files (*.pnm)|*.pnm" ), true }, 00075 { wxT( "pngcairo" ), wxT( "png (cairo)..." ), wxT( "Save this plot as png using cairo!" ), wxT( "png files (*.png)|*.png" ), true }, 00076 { wxT( "pdfcairo" ), wxT( "pdf (cairo)..." ), wxT( "Save this plot as pdf using cairo!" ), wxT( "pdf files (*.pdf)|*.pdf" ), false }, 00077 { wxT( "ps" ), wxT( "postscript..." ), wxT( "Save this plot as postscript!" ), wxT( "ps files (*.ps)|*.ps" ), false }, 00078 { wxT( "psc" ), wxT( "color postscript..." ), wxT( "Save this plot as color postscript!" ), wxT( "ps files (*.ps;*.psc)|*.ps;*.psc" ), false }, 00079 { wxT( "pscairo" ), wxT( "color postscript (cairo)..." ), wxT( "Save this plot as color postscript using cairo!" ), wxT( "ps files (*.ps;*.psc)|*.ps;*.psc" ), false }, 00080 { wxT( "svg" ), wxT( "svg..." ), wxT( "Save this plot as svg!" ), wxT( "svg files (*.svg)|*.svg" ), false }, 00081 { wxT( "svgcairo" ), wxT( "svg (cairo)..." ), wxT( "Save this plot as svg using cairo!" ), wxT( "svg files (*.svg)|*.svg" ), false }, 00082 { wxT( "xfig" ), wxT( "xfig..." ), wxT( "Save this plot as xfig!" ), wxT( "fig files (*.fig)|*.fig" ), false } 00083 }; 00084 00085 // Application implementation 00086 IMPLEMENT_PLAPP_NO_MAIN( wxPLplotApp ) 00087 00088 // event table for the app 00089 BEGIN_EVENT_TABLE( wxPLplotApp, wxApp ) 00090 EVT_IDLE( wxPLplotApp::OnIdle ) 00091 END_EVENT_TABLE() 00092 00093 // event table for frames 00094 BEGIN_EVENT_TABLE( wxPLplotFrame, wxFrame ) 00095 EVT_MENU( -1, wxPLplotFrame::OnMenu ) // handle all menu events 00096 EVT_CLOSE( wxPLplotFrame::OnClose ) 00097 END_EVENT_TABLE() 00098 00099 // event table for the plot widget 00100 BEGIN_EVENT_TABLE( wxPLplotWindow, wxWindow ) 00101 EVT_PAINT( wxPLplotWindow::OnPaint ) // (re)draw the plot in window 00102 EVT_CHAR( wxPLplotWindow::OnChar ) 00103 EVT_IDLE( wxPLplotWindow::OnIdle ) 00104 EVT_MOUSE_EVENTS( wxPLplotWindow::OnMouse ) 00105 EVT_ERASE_BACKGROUND( wxPLplotWindow::OnErase ) 00106 EVT_SIZE( wxPLplotWindow::OnSize ) 00107 EVT_MAXIMIZE( wxPLplotWindow::OnMaximize ) 00108 END_EVENT_TABLE() 00109 00110 // event table for the size dialog 00111 BEGIN_EVENT_TABLE( wxGetSizeDialog, wxDialog ) 00112 END_EVENT_TABLE() 00113 00114 //-------------------------------------------------------------------------- 00115 // bool wxPLplotApp::OnInit() 00116 // 00117 // This method is called before the applications gets control. 00118 //-------------------------------------------------------------------------- 00119 bool wxPLplotApp::OnInit() 00120 { 00121 // Log_Verbose( "wxPLplotApp::OnInit" ); 00122 00123 exit = false; 00124 advance = false; 00125 00126 #if wxUSE_LIBPNG 00127 wxImage::AddHandler( new wxPNGHandler ); 00128 #endif 00129 #if wxUSE_LIBJPEG 00130 wxImage::AddHandler( new wxJPEGHandler ); 00131 #endif 00132 #if wxUSE_PCX 00133 wxImage::AddHandler( new wxPCXHandler ); 00134 #endif 00135 #if wxUSE_LIBTIFF 00136 wxImage::AddHandler( new wxTIFFHandler ); 00137 #endif 00138 #if wxUSE_PNM 00139 wxImage::AddHandler( new wxPNMHandler ); 00140 #endif 00141 00142 return true; 00143 } 00144 00145 00146 //-------------------------------------------------------------------------- 00147 // void wxPLplotApp::SetRefreshFlag( bool flag ) 00148 // 00149 // XXX - missing 00150 //-------------------------------------------------------------------------- 00151 void wxPLplotApp::SetRefreshFlag( bool flag ) 00152 { 00153 // Log_Verbose( "wxPLplotApp::SetRefreshFlag" ); 00154 00155 for ( size_t i = 0; i < FrameArray.GetCount(); i++ ) 00156 FrameArray[i]->SetRefreshFlag( flag ); 00157 } 00158 00159 00160 //-------------------------------------------------------------------------- 00161 // void wxPLplotApp::OnIdle( wxIdleEvent& WXUNUSED(event) ) 00162 // 00163 // XXX - missing 00164 //-------------------------------------------------------------------------- 00165 void wxPLplotApp::OnIdle( wxIdleEvent& WXUNUSED( event ) ) 00166 { 00167 // Log_Verbose( "wxPLplotApp::OnIdle" ); 00168 00169 bool refresh = false; 00170 00171 if ( exit ) 00172 ExitMainLoop(); 00173 00174 for ( size_t i = 0; i < FrameArray.GetCount(); i++ ) 00175 refresh |= FrameArray[i]->GetRefreshFlag(); 00176 00177 if ( advance && !refresh ) 00178 ExitMainLoop(); 00179 } 00180 00181 00182 //-------------------------------------------------------------------------- 00183 // wxPLplotFrame::wxPLplotFrame( const wxString& title, PLStream *pls ) 00184 // 00185 // Constructor of wxPLplotFrame, where we create the menu and add the 00186 // wxPLplotWindow. We need also to know the current PLStream. 00187 //-------------------------------------------------------------------------- 00188 wxPLplotFrame::wxPLplotFrame( const wxString& title, PLStream *pls ) 00189 : wxFrame( NULL, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 00190 wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | 00191 wxCLOSE_BOX | wxRESIZE_BORDER | wxCLIP_CHILDREN ) 00192 { 00193 // Log_Verbose( "wxPLplotFrame::wxPLplotFrame" ); 00194 00195 m_dev = (wxPLDevBase *) pls->dev; 00196 00197 m_panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN ); 00198 wxBoxSizer* box = new wxBoxSizer( wxVERTICAL ); 00199 m_window = new wxPLplotWindow( m_panel, pls ); 00200 box->Add( m_window, 1, wxALL | wxEXPAND, 0 ); 00201 m_panel->SetSizer( box ); 00202 m_window->SetFocus(); 00203 00204 wxMenu* saveMenu = new wxMenu; 00205 saveMenu->Append( wxPL_Save, dev_entries[0].dev_menu_short, dev_entries[0].dev_menu_long ); 00206 #if wxUSE_LIBPNG 00207 saveMenu->Append( wxPL_Save + 1, dev_entries[1].dev_menu_short, dev_entries[1].dev_menu_long ); 00208 #endif 00209 #if wxUSE_PCX 00210 saveMenu->Append( wxPL_Save + 2, dev_entries[2].dev_menu_short, dev_entries[2].dev_menu_long ); 00211 #endif 00212 #if wxUSE_LIBJPEG 00213 saveMenu->Append( wxPL_Save + 3, dev_entries[3].dev_menu_short, dev_entries[3].dev_menu_long ); 00214 #endif 00215 #if wxUSE_LIBTIFF 00216 saveMenu->Append( wxPL_Save + 4, dev_entries[4].dev_menu_short, dev_entries[4].dev_menu_long ); 00217 #endif 00218 #if wxUSE_PNM 00219 saveMenu->Append( wxPL_Save + 5, dev_entries[5].dev_menu_short, dev_entries[5].dev_menu_long ); 00220 #endif 00221 for ( size_t j = 6; j < sizeof ( dev_entries ) / sizeof ( dev_entry ); j++ ) 00222 for ( int i = 0; i < m_dev->ndev; i++ ) 00223 { 00224 if ( !strcmp( m_dev->devName[i], dev_entries[j].dev_name.mb_str() ) ) 00225 saveMenu->Append( wxPL_Save + j, dev_entries[j].dev_menu_short, dev_entries[j].dev_menu_long ); 00226 } 00227 00228 wxMenu* fileMenu = new wxMenu; 00229 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 6 ) 00230 fileMenu->Append( -1, wxT( "Save plot as..." ), saveMenu, wxT( "Save this plot as ...!" ) ); 00231 #else 00232 fileMenu->AppendSubMenu( saveMenu, wxT( "Save plot as..." ), wxT( "Save this plot as ...!" ) ); 00233 #endif 00234 fileMenu->Append( wxID_EXIT, wxT( "E&xit\tAlt-X" ), wxT( "Exit wxWidgets PLplot App" ) ); 00235 00236 wxMenu* orientationMenu = new wxMenu; 00237 orientationMenu->Append( wxPL_Orientation_0, wxT( "0 deg." ), wxT( "Orientation 0 deg." ) ); 00238 orientationMenu->Append( wxPL_Orientation_90, wxT( "90 deg." ), wxT( "Orientation 90 deg." ) ); 00239 orientationMenu->Append( wxPL_Orientation_180, wxT( "180 deg." ), wxT( "Orientation 180 deg." ) ); 00240 orientationMenu->Append( wxPL_Orientation_270, wxT( "270 deg." ), wxT( "Orientation 270 deg." ) ); 00241 00242 wxMenu* plotMenu = new wxMenu; 00243 plotMenu->Append( wxPL_Locate, wxT( "Locate\tL" ), wxT( "Enter locate mode" ) ); 00244 // only add the orientation menu for hershey text processing 00245 if ( !pls->dev_text ) 00246 { 00247 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 6 ) 00248 plotMenu->Append( -1, wxT( "Set Orientation to..." ), orientationMenu, wxT( "Set the Orientation of the plot!" ) ); 00249 #else 00250 plotMenu->AppendSubMenu( orientationMenu, wxT( "Set Orientation to..." ), wxT( "Set the Orientation of the plot!" ) ); 00251 #endif 00252 } 00253 00254 wxMenuBar* menuBar = new wxMenuBar(); 00255 menuBar->Append( fileMenu, wxT( "&File" ) ); 00256 menuBar->Append( plotMenu, wxT( "&Plot" ) ); 00257 SetMenuBar( menuBar ); 00258 00259 SetIcon( wxIcon( graph ) ); 00260 } 00261 00262 00263 //-------------------------------------------------------------------------- 00264 // void wxPLplotFrame::OnMenu( wxCommandEvent& event ) 00265 // 00266 // Event method, which is called if user 00267 //-------------------------------------------------------------------------- 00268 void wxPLplotFrame::OnMenu( wxCommandEvent& event ) 00269 { 00270 // Log_Verbose( "wxPLplotFrame::OnMenu" ); 00271 00272 switch ( event.GetId() ) 00273 { 00274 case wxID_EXIT: 00275 m_dev->exit = true; 00276 wxPLGetApp().ExitMainLoop(); 00277 break; 00278 case wxPL_Orientation_0: 00279 case wxPL_Orientation_90: 00280 case wxPL_Orientation_180: 00281 case wxPL_Orientation_270: 00282 m_window->SetOrientation( event.GetId() - wxPL_Orientation_0 ); 00283 break; 00284 case wxPL_Locate: 00285 if ( m_dev->locate_mode ) 00286 { 00287 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_API ) 00288 wxPLGetApp().SetAdvanceFlag(); 00289 m_dev->locate_mode = 0; 00290 m_dev->draw_xhair = false; 00291 } 00292 else 00293 { 00294 m_dev->locate_mode = LOCATE_INVOKED_VIA_DRIVER; 00295 m_dev->draw_xhair = true; 00296 } 00297 break; 00298 } 00299 00300 size_t index = event.GetId() - wxPL_Save; 00301 if ( ( event.GetId() >= wxPL_Save ) && ( index < sizeof ( dev_entries ) / sizeof ( dev_entry ) ) ) 00302 { 00303 int width = 800; 00304 int height = 600; 00305 bool proceed = false; 00306 00307 // ask for geometry in pixels only for image devices 00308 if ( dev_entries[index].pixelDevice ) 00309 { 00310 wxGetSizeDialog sizeDialog( this, -1, wxT( "Size of plot" ), wxDefaultPosition, wxDefaultSize, 00311 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, width, height ); 00312 if ( sizeDialog.ShowModal() == wxID_OK ) 00313 { 00314 width = sizeDialog.getWidth(); 00315 height = sizeDialog.getHeight(); 00316 proceed = true; 00317 } 00318 } 00319 else 00320 proceed = true; 00321 00322 if ( proceed ) 00323 { 00324 wxFileDialog dialog( this, wxT( "Save plot as " ) + dev_entries[index].dev_name, wxT( "" ), wxT( "" ), 00325 dev_entries[index].dev_file_app + wxT( "|All Files (*.*)|*.*" ), 00326 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 6 ) 00327 wxSAVE | wxOVERWRITE_PROMPT ); 00328 #else 00329 wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); 00330 #endif 00331 if ( dialog.ShowModal() == wxID_OK ) 00332 { 00333 const wxCharBuffer buf1 = dialog.GetPath().mb_str(); 00334 const wxCharBuffer buf2 = dev_entries[index].dev_name.mb_str(); 00335 SavePlot( (const char *) buf1, (const char *) buf2, width, height ); 00336 } 00337 } 00338 } 00339 } 00340 00341 //-------------------------------------------------------------------------- 00342 // void wxPLplotFrame::OnClose( wxCloseEvent& event ) 00343 // 00344 // Event method, which is called if user 00345 //-------------------------------------------------------------------------- 00346 void wxPLplotFrame::OnClose( wxCloseEvent& /* event */ ) 00347 { 00348 // Log_Verbose( "wxPLplotFrame::OnClose" ); 00349 00350 m_dev->exit = true; 00351 wxPLGetApp().ExitMainLoop(); 00352 } 00353 00354 00355 //-------------------------------------------------------------------------- 00356 // bool wxPLplotFrame::SavePlot( const char* filename, cost char* dev, int width, 00357 // int height ) 00358 // 00359 // This function saves the current plot to a file (filename) using a 00360 // device (devname) with given width and height. There is no test if 00361 // the device really exists. 00362 //-------------------------------------------------------------------------- 00363 bool wxPLplotFrame::SavePlot( const char* filename, const char* devname, int width, int height ) 00364 { 00365 int pls, pls_save; 00366 00367 if ( !strcmp( devname, "wxbmp" ) || !strcmp( devname, "wxpng" ) || !strcmp( devname, "wxpcx" ) || 00368 !strcmp( devname, "wxjpeg" ) || !strcmp( devname, "wxtiff" ) || !strcmp( devname, "wxpnm" ) ) 00369 { 00370 wxMemoryDC memDC; 00371 00372 wxBitmap bitmap( width, height, -1 ); 00373 memDC.SelectObject( bitmap ); 00374 00375 plgstrm( &pls ); 00376 plmkstrm( &pls_save ); 00377 plsdev( "wxwidgets" ); 00378 plspage( 0.0, 0.0, width, height, 0, 0 ); 00379 00380 plsetopt( "-drvopt", "backend=0" ); 00381 plinit(); 00382 pl_cmd( PLESC_DEVINIT, (void *) &memDC ); 00383 00384 plcpstrm( pls, 0 ); 00385 pladv( 0 ); 00386 plreplot(); 00387 plend1(); 00388 plsstrm( pls ); 00389 00390 wxBitmapType type; 00391 if ( !strcmp( devname, "wxbmp" ) ) 00392 type = wxBITMAP_TYPE_BMP; 00393 #if wxUSE_LIBPNG 00394 else if ( !strcmp( devname, "wxpng" ) ) 00395 type = wxBITMAP_TYPE_PNG; 00396 #endif 00397 #if wxUSE_PCX 00398 else if ( !strcmp( devname, "wxpcx" ) ) 00399 type = wxBITMAP_TYPE_PCX; 00400 #endif 00401 #if wxUSE_LIBJPEG 00402 else if ( !strcmp( devname, "wxjpeg" ) ) 00403 type = wxBITMAP_TYPE_JPEG; 00404 #endif 00405 #if wxUSE_LIBTIFF 00406 else if ( !strcmp( devname, "wxtiff" ) ) 00407 type = wxBITMAP_TYPE_TIF; 00408 #endif 00409 #if wxUSE_PNM 00410 else if ( !strcmp( devname, "wxpnm" ) ) 00411 type = wxBITMAP_TYPE_PNM; 00412 #endif 00413 else 00414 type = wxBITMAP_TYPE_BMP; 00415 bool status = bitmap.SaveFile( wxString( filename, *wxConvCurrent ), type ); 00416 00417 if ( !status ) 00418 { 00419 char buf[512]; 00420 snprintf( buf, 512, "File %s couldn't be saved", filename ); 00421 plabort( buf ); 00422 return false; 00423 } 00424 } 00425 else 00426 { 00427 plgstrm( &pls ); 00428 plmkstrm( &pls_save ); 00429 00430 plsdev( devname ); 00431 //plspage( 0., 0., width, height, 0, 0 ); 00432 plsfnam( filename ); 00433 00434 plcpstrm( pls, 0 ); 00435 pladv( 0 ); 00436 plreplot(); 00437 plend1(); 00438 plsstrm( pls ); 00439 } 00440 00441 return true; 00442 } 00443 00444 00445 //-------------------------------------------------------------------------- 00446 // wxPLplotWindow::wxPLplotWindow( const wxString& title ) 00447 // 00448 // Constructor of wxPLplotFrame, where we create the menu. 00449 //-------------------------------------------------------------------------- 00450 wxPLplotWindow::wxPLplotWindow( wxWindow* parent, PLStream *pls ) 00451 : wxWindow( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 00452 wxNO_BORDER | wxWANTS_CHARS | wxCLIP_CHILDREN ) 00453 { 00454 // Log_Verbose( "wxPLplotWindow::wxPLplotWindow" ); 00455 00456 m_pls = pls; 00457 m_dev = (wxPLDevBase *) pls->dev; 00458 refresh = false; 00459 mouse_x = old_mouse_x = -1; 00460 mouse_y = old_mouse_y = -1; 00461 xhair_drawn = false; 00462 00463 SetBackgroundStyle( wxBG_STYLE_CUSTOM ); 00464 } 00465 00466 00467 //-------------------------------------------------------------------------- 00468 // void wxPLplotWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) 00469 // 00470 // Event method where the plots are actually drawn. Since the plots 00471 // are already drawn into bitmaps, which just copy them into to client 00472 // area. This method is also called, if (part) of the client area was 00473 // invalidated and a refresh is necessary. 00474 //-------------------------------------------------------------------------- 00475 void wxPLplotWindow::OnPaint( wxPaintEvent& WXUNUSED( event ) ) 00476 { 00477 // Log_Verbose( "wxPLplotWindow::OnPaint" ); 00478 00479 // copy bitmap into client area 00480 wxPaintDC dc( this ); 00481 00482 // only update damaged regions 00483 int vX, vY, vW, vH; 00484 wxRegionIterator upd( GetUpdateRegion() ); 00485 00486 // remove the xhair before updating 00487 if ( m_dev->draw_xhair && upd && xhair_drawn ) 00488 { 00489 dc.SetLogicalFunction( wxINVERT ); 00490 dc.CrossHair( old_mouse_x, old_mouse_y ); 00491 dc.SetLogicalFunction( wxCOPY ); 00492 xhair_drawn = false; 00493 old_mouse_x = old_mouse_y = -1; 00494 } 00495 00496 while ( upd ) 00497 { 00498 vX = upd.GetX(); 00499 vY = upd.GetY(); 00500 vW = upd.GetW(); 00501 vH = upd.GetH(); 00502 00503 //printf( "Clipping region: x=%d, y=%d, width=%d, height=%d, counter=%d\n", vX, vY, vW, vH, counter++ ); 00504 00505 m_dev->BlitRectangle( &dc, vX, vY, vW, vH ); 00506 00507 upd++; 00508 } 00509 00510 if ( m_dev->draw_xhair && !xhair_drawn ) 00511 { 00512 dc.SetLogicalFunction( wxINVERT ); 00513 dc.CrossHair( mouse_x, mouse_y ); 00514 dc.SetLogicalFunction( wxCOPY ); 00515 old_mouse_x = mouse_x; 00516 old_mouse_y = mouse_y; 00517 xhair_drawn = true; 00518 } 00519 } 00520 00521 00522 //-------------------------------------------------------------------------- 00523 // void wxPLplotWindow::OnChar( wxKeyEvent& event ) 00524 // 00525 // Handle key events. 00526 //-------------------------------------------------------------------------- 00527 void wxPLplotWindow::OnChar( wxKeyEvent& event ) 00528 { 00529 // Log_Verbose( "wxPLplotWindow::OnChar" ); 00530 00531 PLGraphicsIn *gin = &( m_dev->gin ); 00532 00533 int width, height; 00534 GetClientSize( &width, &height ); 00535 00536 gin->pX = mouse_x; 00537 gin->pY = mouse_y; 00538 gin->dX = (PLFLT) mouse_x / ( width - 1 ); 00539 gin->dY = 1.0 - (PLFLT) mouse_y / ( height - 1 ); 00540 00541 // gin->state = keyEvent->state; 00542 00543 int keycode = event.GetKeyCode(); 00544 gin->string[0] = (char) keycode; 00545 gin->string[1] = '\0'; 00546 00547 // ESCAPE, RETURN, etc. are already in ASCII equivalent 00548 gin->keysym = keycode; 00549 00550 if ( m_dev->locate_mode ) 00551 { 00552 // End locate mode on <Escape> 00553 if ( gin->keysym == PLK_Escape ) 00554 { 00555 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_API ) 00556 wxPLGetApp().SetAdvanceFlag(); 00557 m_dev->locate_mode = 0; 00558 m_dev->draw_xhair = false; 00559 DrawCrosshair(); 00560 plGinInit( gin ); 00561 } 00562 00563 Locate(); 00564 } 00565 else 00566 { 00567 // Call user keypress event handler. Since this is called first, the user 00568 // can disable all internal event handling by setting gin.keysym to 0. 00569 if ( m_pls->KeyEH != NULL ) 00570 { 00571 int advance = 0; 00572 ( *m_pls->KeyEH )( gin, m_pls->KeyEH_data, &advance ); 00573 if ( advance ) 00574 wxPLGetApp().SetAdvanceFlag(); 00575 } 00576 00577 switch ( gin->keysym ) 00578 { 00579 case 'L': 00580 m_dev->locate_mode = LOCATE_INVOKED_VIA_DRIVER; 00581 m_dev->draw_xhair = true; 00582 DrawCrosshair(); 00583 break; 00584 case 'Q': 00585 case PLK_Escape: 00586 m_dev->exit = true; 00587 wxPLGetApp().SetExitFlag(); 00588 break; 00589 case PLK_Return: 00590 case WXK_SPACE: 00591 case WXK_RIGHT: 00592 wxPLGetApp().SetAdvanceFlag(); 00593 break; 00594 default: 00595 break; 00596 } 00597 } 00598 00599 event.Skip(); 00600 } 00601 00602 00603 //-------------------------------------------------------------------------- 00604 // void wxPLplotWindow::OnIdle( wxIdleEvent& WXUNUSED(event) ) 00605 // 00606 // If there is no pending event, maybe the canvas needs to be refreshed. 00607 //-------------------------------------------------------------------------- 00608 void wxPLplotWindow::OnIdle( wxIdleEvent& WXUNUSED( event ) ) 00609 { 00610 // Log_Verbose( "wxPLplotWindow::OnIdle" ); 00611 00612 if ( refresh ) 00613 { 00614 if ( !m_dev->newclipregion ) 00615 { 00616 static wxRect rect; 00617 rect.x = m_dev->clipminx; 00618 rect.y = m_dev->clipminy; 00619 rect.width = m_dev->clipmaxx - m_dev->clipminx + 1; 00620 rect.height = m_dev->clipmaxy - m_dev->clipminy + 1; 00621 #if ( wxMAJOR_VERSION <= 2 ) & ( wxMINOR_VERSION <= 5 ) 00622 RefreshRect( rect ); 00623 #else 00624 RefreshRect( rect, false ); // don't erase background 00625 #endif 00626 m_dev->newclipregion = true; 00627 m_dev->clipminx = m_dev->width; 00628 m_dev->clipmaxx = 0; 00629 m_dev->clipminy = m_dev->height; 00630 m_dev->clipmaxy = 0; 00631 } 00632 else 00633 Refresh( false ); 00634 refresh = false; 00635 } 00636 } 00637 00638 00639 //-------------------------------------------------------------------------- 00640 // void wxPLplotWindow::OnErase( wxEraseEvent &WXUNUSED(event) ) 00641 // 00642 // Do nothing here to prevent flickering. 00643 //-------------------------------------------------------------------------- 00644 void wxPLplotWindow::OnErase( wxEraseEvent &WXUNUSED( event ) ) 00645 { 00646 // Log_Verbose( "wxPLplotWindow::OnErase" ); 00647 } 00648 00649 00650 //-------------------------------------------------------------------------- 00651 // void wxPLplotWindow::OnSize( wxSizeEvent & WXUNUSED(event) ) 00652 // 00653 // Allocate a bigger bitmap if necessary and redo the plot if the 00654 // window size was changed. 00655 //-------------------------------------------------------------------------- 00656 void wxPLplotWindow::OnSize( wxSizeEvent & WXUNUSED( event ) ) 00657 { 00658 // Log_Verbose( "wxPLplotWindow::OnSize" ); 00659 00660 int width, height; 00661 GetClientSize( &width, &height ); 00662 00663 if ( m_dev->waiting ) 00664 { 00665 if ( ( width != m_dev->width ) || ( height != m_dev->height ) ) 00666 { 00667 // get a new bitmap if new size is bigger as bitmap size 00668 if ( ( width > m_dev->bm_width ) || ( height > m_dev->bm_height ) ) 00669 { 00670 m_dev->bm_width = m_dev->bm_width > width ? m_dev->bm_width : width; 00671 m_dev->bm_height = m_dev->bm_height > height ? m_dev->bm_height : height; 00672 } 00673 00674 wx_set_size( m_pls, width, height ); 00675 m_dev->resizing = true; 00676 plRemakePlot( m_pls ); 00677 m_dev->resizing = false; 00678 Refresh(); 00679 } 00680 } 00681 } 00682 00683 00684 //-------------------------------------------------------------------------- 00685 // wxPLplotWindow::OnMaximize( wxMaximizeEvent & WXUNUSED(event) ) 00686 // 00687 // Add a size event if the Window is maximized. 00688 //-------------------------------------------------------------------------- 00689 void wxPLplotWindow::OnMaximize( wxMaximizeEvent & WXUNUSED( event ) ) 00690 { 00691 // Log_Verbose( "wxPLplotWindow::OnMax" ); 00692 00693 wxSizeEvent event( GetClientSize() ); 00694 AddPendingEvent( event ); 00695 } 00696 00697 00698 //-------------------------------------------------------------------------- 00699 // void wxPLplotWindow::OnMouse( wxMouseEvent &event ) 00700 // 00701 // Handle mouse events. 00702 //-------------------------------------------------------------------------- 00703 void wxPLplotWindow::OnMouse( wxMouseEvent &event ) 00704 { 00705 // Log_Verbose( "wxPLplotWindow::OnMouse" ); 00706 00707 wxPoint pos( event.GetPosition() ); 00708 mouse_x = pos.x; 00709 mouse_y = pos.y; 00710 00711 if ( event.ButtonDown() ) 00712 { 00713 PLGraphicsIn *gin = &( m_dev->gin ); 00714 00715 int width, height; 00716 GetClientSize( &width, &height ); 00717 00718 gin->pX = mouse_x; 00719 gin->pY = mouse_y; 00720 gin->dX = (PLFLT) mouse_x / ( width - 1 ); 00721 gin->dY = 1.0 - (PLFLT) mouse_y / ( height - 1 ); 00722 00723 if ( event.LeftDown() ) 00724 { 00725 gin->button = 1; // X11/X.h: #define Button1 1 00726 gin->state = 1 << 8; // X11/X.h: #define Button1Mask (1<<8) 00727 } 00728 else if ( event.MiddleDown() ) 00729 { 00730 gin->button = 2; // X11/X.h: #define Button2 2 00731 gin->state = 1 << 9; // X11/X.h: #define Button2Mask (1<<9) 00732 } 00733 else if ( event.RightDown() ) 00734 { 00735 gin->button = 3; // X11/X.h: #define Button3 3 00736 gin->state = 1 << 10; // X11/X.h: #define Button3Mask (1<<10) 00737 } 00738 gin->keysym = 0x20; // keysym for button event from xwin.c 00739 00740 if ( m_dev->locate_mode ) 00741 Locate(); 00742 else 00743 { 00744 // Call user event handler. Since this is called first, the user can 00745 // disable all PLplot internal event handling by setting gin->button to 0. 00746 if ( m_pls->ButtonEH != NULL ) 00747 { 00748 int advance = 0; 00749 ( *m_pls->ButtonEH )( gin, m_pls->ButtonEH_data, &advance ); 00750 if ( advance ) 00751 wxPLGetApp().SetAdvanceFlag(); 00752 } 00753 00754 // Handle internal events 00755 switch ( gin->button ) 00756 { 00757 case 3: // on right mouse button advance 00758 wxPLGetApp().SetAdvanceFlag(); 00759 break; 00760 default: 00761 break; 00762 } 00763 } 00764 } 00765 00766 DrawCrosshair(); 00767 } 00768 00769 00770 //-------------------------------------------------------------------------- 00771 // void wxPLplotWindow::Locate( void ) 00772 // 00773 // Take care of Locate mode, called by OnChar() and OnMouse(). 00774 //-------------------------------------------------------------------------- 00775 void wxPLplotWindow::Locate( void ) 00776 { 00777 // Log_Verbose( "wxPLplotWindow::Locate" ); 00778 00779 PLGraphicsIn *gin = &( m_dev->gin ); 00780 00781 // Some event (key, button) occured, and if the locate mode 00782 // was initiated by the API we need to return back to the 00783 // user program 00784 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_API ) 00785 wxPLGetApp().SetAdvanceFlag(); 00786 00787 // Call user locate mode handler if provided 00788 if ( m_pls->LocateEH != NULL ) 00789 { 00790 int locate_mode = m_dev->locate_mode; 00791 ( *m_pls->LocateEH )( gin, m_pls->LocateEH_data, &locate_mode ); 00792 if ( !locate_mode ) 00793 { 00794 m_dev->locate_mode = 0; 00795 m_dev->draw_xhair = false; 00796 } 00797 } 00798 else 00799 { 00800 if ( plTranslateCursor( gin ) ) 00801 { 00802 // If invoked by the API, we're done 00803 // Otherwise send report to stdout 00804 if ( m_dev->locate_mode == LOCATE_INVOKED_VIA_DRIVER ) 00805 { 00806 if ( gin->keysym < 0xFF && isprint( gin->keysym ) ) 00807 printf( "%f %f %c\n", gin->wX, gin->wY, gin->keysym ); 00808 else 00809 printf( "%f %f 0x%02x\n", gin->wX, gin->wY, gin->keysym ); 00810 } 00811 } 00812 else 00813 { 00814 // Selected point is out of bounds, so end locate mode 00815 m_dev->locate_mode = 0; 00816 m_dev->draw_xhair = false; 00817 } 00818 } 00819 DrawCrosshair(); 00820 } 00821 00822 00823 //-------------------------------------------------------------------------- 00824 // void wxPLplotWindow::DrawCrosshair() 00825 // 00826 // Draw a cross hair (inverted lines). 00827 //-------------------------------------------------------------------------- 00828 void wxPLplotWindow::DrawCrosshair() 00829 { 00830 // draw cross hair 00831 wxClientDC dc( this ); 00832 if ( m_dev->draw_xhair ) 00833 { 00834 if ( ( mouse_x != old_mouse_x ) || ( mouse_y != old_mouse_y ) ) 00835 { 00836 dc.SetLogicalFunction( wxINVERT ); 00837 if ( xhair_drawn ) 00838 dc.CrossHair( old_mouse_x, old_mouse_y ); 00839 dc.CrossHair( mouse_x, mouse_y ); 00840 dc.SetLogicalFunction( wxCOPY ); 00841 old_mouse_x = mouse_x; 00842 old_mouse_y = mouse_y; 00843 xhair_drawn = true; 00844 } 00845 } 00846 else 00847 { 00848 if ( xhair_drawn ) 00849 { 00850 dc.SetLogicalFunction( wxINVERT ); 00851 dc.CrossHair( old_mouse_x, old_mouse_y ); 00852 dc.SetLogicalFunction( wxCOPY ); 00853 xhair_drawn = false; 00854 old_mouse_x = old_mouse_y = -1; 00855 } 00856 } 00857 } 00858 00859 00860 //-------------------------------------------------------------------------- 00861 // void wxPLplotWindow::SetOrientation( int rot ) 00862 // 00863 // Set the orientation of the plot. 00864 //-------------------------------------------------------------------------- 00865 void wxPLplotWindow::SetOrientation( int rot ) 00866 { 00867 PLINT bgr, bgg, bgb; // red, green, blue 00868 00869 //plsstrm( m_pls ); 00870 plsdiori( rot ); 00871 m_dev->resizing = true; 00872 plgcolbg( &bgr, &bgg, &bgb ); // get background color information 00873 m_dev->ClearBackground( bgr, bgg, bgb ); 00874 plRemakePlot( m_pls ); 00875 m_dev->resizing = false; 00876 Refresh(); 00877 } 00878 00879 //-------------------------------------------------------------------------- 00880 // wxGetSizeDialog::wxGetSizeDialog( wxWindow *parent, ... ) 00881 // 00882 // Constructor of GetSizeDialog. 00883 //-------------------------------------------------------------------------- 00884 wxGetSizeDialog::wxGetSizeDialog( wxWindow *parent, wxWindowID id, const wxString &title, 00885 const wxPoint &position, const wxSize& size, long style, int width, int height ) : 00886 wxDialog( parent, id, title, position, size, style ) 00887 { 00888 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL ); 00889 00890 wxStaticBoxSizer *staticSizer = new wxStaticBoxSizer( new wxStaticBox( this, -1, wxT( "Size of plot" ) ), wxVERTICAL ); 00891 00892 wxFlexGridSizer *flexSizer = new wxFlexGridSizer( 2, 0, 0 ); 00893 flexSizer->AddGrowableCol( 1 ); 00894 00895 wxStaticText *textWidth = new wxStaticText( this, -1, wxT( "Width [pixels]:" ), wxDefaultPosition, wxDefaultSize, 0 ); 00896 flexSizer->Add( textWidth, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5 ); 00897 spinControlWidth = new wxSpinCtrl( this, -1, wxString::Format( wxT( "%d" ), width ), wxDefaultPosition, wxSize( 100, -1 ), wxSP_ARROW_KEYS, 10, 4096, width ); 00898 flexSizer->Add( spinControlWidth, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 ); 00899 wxStaticText *textHeight = new wxStaticText( this, -1, wxT( "Height [pixels]:" ), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); 00900 flexSizer->Add( textHeight, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5 ); 00901 spinControlHeight = new wxSpinCtrl( this, -1, wxString::Format( wxT( "%d" ), height ), wxDefaultPosition, wxSize( 100, -1 ), wxSP_ARROW_KEYS, 10, 4096, height ); 00902 flexSizer->Add( spinControlHeight, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 ); 00903 00904 staticSizer->Add( flexSizer, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 ); 00905 00906 sizer->Add( staticSizer, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxALL, 5 ); 00907 00908 wxBoxSizer *buttonSizer = new wxBoxSizer( wxHORIZONTAL ); 00909 wxButton *buttonOK = new wxButton( this, wxID_OK, wxT( "OK" ), wxDefaultPosition, wxDefaultSize, 0 ); 00910 buttonSizer->Add( buttonOK, 0, wxALIGN_CENTER | wxALL | wxEXPAND, 5 ); 00911 buttonSizer->Add( 20, 20, 1, wxALIGN_CENTER | wxALL, 5 ); 00912 wxButton *buttonCancel = new wxButton( this, wxID_CANCEL, wxT( "Cancel" ), wxDefaultPosition, wxDefaultSize, 0 ); 00913 buttonSizer->Add( buttonCancel, 0, wxALIGN_CENTER | wxALL | wxEXPAND, 5 ); 00914 00915 sizer->Add( buttonSizer, 0, wxGROW | wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 15 ); 00916 00917 this->SetSizer( sizer ); 00918 sizer->SetSizeHints( this ); 00919 } 00920 00921 #endif // PLD_wxwidgets