Changeset 455 in PSPA for Interface_Web/trunk/pspaWT/sources/userInterface/src/GWt_accelerator.cc
- Timestamp:
- Dec 16, 2013, 5:16:54 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Interface_Web/trunk/pspaWT/sources/userInterface/src/GWt_accelerator.cc
r446 r455 8 8 #include <Wt/WHBoxLayout> 9 9 #include <Wt/WComboBox> 10 #include <Wt/WRadioButton> 10 11 #include <Wt/WPushButton> 11 12 #include <Wt/WGroupBox> 13 #include <Wt/WStandardItemModel> 12 14 13 15 #include <string> 14 16 15 GWt_accelerator::GWt_accelerator(WContainerWidget* parent, PspaApplication* pspa) :17 GWt_accelerator::GWt_accelerator(WContainerWidget* parent, dataManager* dt) : 16 18 WContainerWidget(parent), 17 pspa_(pspa)19 dataManager_(dt) 18 20 { 19 21 setObjectName("accelerator"); 20 22 addStyleClass("acceleratorPanel"); 21 23 nameOfCase_ = "pspa"; // default // FIXME 24 25 22 26 WContainerWidget* menu = new WContainerWidget(this); 23 27 menu->addStyleClass("acceleratorMenu"); … … 59 63 runParameters->setMinimumSize(32,32); 60 64 65 WPushButton* boutongraphicalAnalysis = new WPushButton("",menu); 66 boutongraphicalAnalysis->setStyleClass("histoButton"); 67 boutongraphicalAnalysis->setToolTip ("analyse graphique"); 68 boutongraphicalAnalysis->setMaximumSize(32,32); 69 boutongraphicalAnalysis->setMinimumSize(32,32); 70 71 61 72 new WBreak(this); 62 73 … … 79 90 addSectorParameters->clicked().connect(this,&GWt_accelerator::addSector); 80 91 runParameters->clicked().connect(this,&GWt_accelerator::run); 81 92 boutongraphicalAnalysis->clicked().connect(this, &GWt_accelerator::dialogOnGraphics); 93 94 graphicsDialog_ = new GWt_dialog("graphical analysis",createDrawingWidget(),false); 95 graphicsDialog_->setMinimumSize(400,400); 96 graphicsDialog_->setClosable(true); 97 graphicsDialog_->hide(); 82 98 83 99 } … … 90 106 void GWt_accelerator::addSector() 91 107 { 92 sector* sect = pspa_->getDataManager()->addNewSector();108 sector* sect = getDataManager()->addNewSector(); 93 109 GWt_sector* addedSector = new GWt_sector(this,sect); 94 110 } … … 97 113 { 98 114 } 115 116 void GWt_accelerator::faireDessin() 117 { 118 choixElementDessin_->clear(); 119 choixHistoDessin_->clear(); 120 121 for (unsigned k = 0; k < getDataManager()->getSectors().size(); k++) { 122 sector* sector = getDataManager()->getSectors()[k]; 123 for (unsigned l = 0; l < sector->getSectionsToExecute().size(); l++) { 124 sectionToExecute* section = sector->getSectionsToExecute()[l]; 125 for (unsigned m = 0; m < section->getElements().size(); m++) { 126 127 abstractElement* elPtr = section->getElements()[m]; 128 // if(elPtr->getNomdElement().getElementType() == snapshot) continue; 129 130 choixElementDessin_->addItem(elPtr->getLabel()); 131 choixHistoDessin_->addItem(elPtr->getLabel()); 132 } 133 } 134 } 135 } 136 137 WContainerWidget* GWt_accelerator::createDrawingWidget() 138 { 139 WGridLayout *glayout= new WGridLayout(); 140 WContainerWidget* dessin = new WContainerWidget(); 141 dessin->setLayout(glayout); 142 143 group_ = new Wt::WButtonGroup(this); 144 145 ///////////////////////////////////////////////////////////////////// 146 147 choixEnveloppeDessin_ = new WComboBox(); 148 choixEnveloppeDessin_->addItem("x"); 149 // choixEnveloppeDessin_->addItem("y"); 150 Wt::WRadioButton *button1= new WRadioButton(" enveloppe"); 151 group_->addButton(button1,1); 152 glayout->addWidget(button1,0,1); 153 glayout->addWidget(choixEnveloppeDessin_,0,2); 154 ///////////////////////////////////////////////////////////////////// 155 156 choixElementDessin_ = new WComboBox(); 157 choixElementDessin_->setMinimumSize(50,10); 158 choixTypeDessinFaisceau_ = new WComboBox(); 159 choixTypeDessinFaisceau_->addItem("courant_snyder"); 160 choixTypeDessinFaisceau_->addItem("macroparticles"); 161 Wt::WRadioButton *button2= new WRadioButton(" phase space after element"); 162 163 choixAbsPhase_ = new WComboBox(); 164 choixAbsPhase_->addItem("x"); 165 choixAbsPhase_->addItem("y"); 166 choixAbsPhase_->addItem("dz"); 167 choixAbsPhase_->addItem("xp"); 168 choixAbsPhase_->addItem("yp"); 169 choixAbsPhase_->addItem("dE/E"); 170 choixAbsPhase_->setCurrentIndex(0); 171 172 choixOrdPhase_ = new WComboBox(); 173 choixOrdPhase_->addItem("x"); 174 choixOrdPhase_->addItem("y"); 175 choixOrdPhase_->addItem("dz"); 176 choixOrdPhase_->addItem("xp"); 177 choixOrdPhase_->addItem("yp"); 178 choixOrdPhase_->addItem("dE/E"); 179 choixOrdPhase_->setCurrentIndex(3); 180 181 group_->addButton(button2,2); 182 glayout->addWidget(button2,1,1); 183 glayout->addWidget(choixElementDessin_,1,2); 184 glayout->addWidget(choixTypeDessinFaisceau_,1,3); 185 // glayout->addWidget(new WText("abs. :"),2,2); 186 glayout->addWidget(choixAbsPhase_,2,2); 187 // glayout->addWidget(new WText("ord. :"),2,4); 188 glayout->addWidget(choixOrdPhase_,2,3); 189 ///////////////////////////////////////////////////////////////////// 190 191 choixVariableHisto_= new WComboBox(); 192 choixVariableHisto_->addItem("x"); 193 choixVariableHisto_->addItem("y"); 194 choixVariableHisto_->addItem("z"); 195 choixVariableHisto_->addItem("xp"); 196 choixVariableHisto_->addItem("yp"); 197 choixVariableHisto_->addItem("dE/E"); 198 choixVariableHisto_->setCurrentIndex(5); 199 200 choixHistoDessin_ = new WComboBox(); 201 Wt::WRadioButton *button3= new WRadioButton(" histogram after element "); 202 group_->addButton(button3,3); 203 204 glayout->addWidget(button3,3,1); 205 glayout->addWidget(choixHistoDessin_,3,2); 206 glayout->addWidget(choixVariableHisto_,3,3); 207 ///////////////////////////////////////////////////////////////////// 208 209 WPushButton *close= new WPushButton("close"); 210 glayout->addWidget(close,4,1); 211 close->clicked().connect(this,&GWt_accelerator::closeGraphicDialog); 212 213 WPushButton *draw= new WPushButton("draw"); 214 glayout->addWidget(draw,4,2,2,1); 215 draw->clicked().connect(this,&GWt_accelerator::dessiner); 216 ///////////////////////////////////////////////////////////////////// 217 218 toto_ = new WContainerWidget(); 219 dessin->addWidget(toto_); 220 return dessin; 221 } 222 223 224 void GWt_accelerator::dialogOnGraphics() 225 { 226 graphicsDialog_->show(); 227 } 228 229 230 void GWt_accelerator::closeGraphicDialog() 231 { 232 cout << " close graphicsDialog_" << endl; 233 for(unsigned i = 0; i < eDialog_.size(); i++) eDialog_[i]->done(WDialog::Rejected); 234 eDialog_.clear(); 235 graphicsDialog_->done(WDialog::Rejected); 236 } 237 238 239 240 void GWt_accelerator::dessiner() 241 { 242 int k= group_->checkedId(); 243 cout << "dessiner k= " << k << endl; 244 245 switch(k) { 246 case 1: 247 dessinerEnveloppe(); 248 break; 249 case 2: 250 dessinerPhaseSpace(); 251 break; 252 case 3: 253 dessinerHistogramme(); 254 break; 255 default: 256 GWt_dialog graphicalWarning("graphical analysis","select a button",GWt_dialog::Warning,false,true); 257 graphicalWarning.exec(); 258 break; 259 } 260 } 261 262 void GWt_accelerator::dessinerPhaseSpace() 263 { 264 265 int typeFaisceau = choixTypeDessinFaisceau_->currentIndex(); 266 // int index = choixElementDessin_->currentIndex(); 267 string nameAbs = choixAbsPhase_->currentText().toUTF8(); 268 string nameOrd = choixOrdPhase_->currentText().toUTF8(); 269 if ( nameAbs == nameOrd ) { 270 GWt_dialog phaseSpaceError(" graphical analysis", "the beam coordinates must be different !", GWt_dialog::Error, false,true); 271 phaseSpaceError.exec(); 272 return; 273 } 274 string elementLabel = choixElementDessin_->currentText().toUTF8(); 275 particleBeam* beam = dataManager_->getDiagnosticBeam_deprecated(elementLabel); 276 // particleBeam* beam = dtmanage_->getDiagnosticBeam(index); 277 278 if ( beam == NULL ) { 279 GWt_dialog warningBeamState(" graphical analysis", "the beam does not exist at the end of this element !", GWt_dialog::Error, false,true); 280 warningBeamState.exec(); 281 return; 282 } 283 284 toto_->clear(); 285 faireDessinPhaseSpace(toto_, beam, elementLabel, nameAbs, nameOrd, typeFaisceau); 286 287 // if ( typeFaisceau == 0 ) 288 // { 289 // if ( !beam->momentRepresentationOk() ) beam->buildMomentRepresentation(); 290 // faireDessinTransport(toto_, beam, nameAbs, nameOrd ); 291 // } 292 // else if ( typeFaisceau == 1 ) 293 // { 294 // if ( beam->particleRepresentationOk() ) faireDessinParmela(toto_, beam, nameAbs, nameOrd ); 295 // else { 296 // GWt_dialog warningBeamState(" graphical analysis", "the beam state does not allow providing a drawing with macroparticles !", GWt_dialog::Error, false,true); 297 // warningBeamState.exec(); 298 // } 299 // } 300 // else { 301 // GWt_dialog warningTypeDrawing(" graphical analysis", "type of drawing not programmed !", GWt_dialog::Error, false,true); 302 // warningTypeDrawing.exec(); 303 // } 304 } 305 306 void GWt_accelerator::dessinerEnveloppe() 307 { 308 toto_->clear(); 309 310 int typeEnveloppe = choixEnveloppeDessin_->currentIndex(); 311 if ( typeEnveloppe == 0 ) 312 { 313 faireDessinEnveloppe(toto_, "x"); 314 } 315 else { 316 GWt_dialog warningTypeEnveloppe(" graphical analysis", "type of enveloppe drawing not programmed !", GWt_dialog::Error, false,true); 317 warningTypeEnveloppe.exec(); 318 } 319 } 320 321 void GWt_accelerator::faireDessinEnveloppe(WContainerWidget* toto, string type) 322 { 323 324 std::time_t result = std::time(NULL); 325 326 GWt_dialog* envDialog = new GWt_dialog(WString("enveloppe (")+std::asctime(std::localtime(&result))+")",toto,false); 327 eDialog_.push_back(envDialog); 328 envDialog->setMinimumSize(400,400); 329 envDialog->setClosable(true); 330 envDialog->show(); 331 332 // unsigned nbel = dtmanage_->getBeamLineSize(); 333 vector<double> xcor; 334 vector<double> ycor; 335 string titre; 336 string legendx; 337 string legendy; 338 dataManager_->donneesRmsEnveloppe(type,xcor,ycor,titre,legendx,legendy); 339 340 Wt::Chart::SeriesType seriesType = Wt::Chart::LineSeries; 341 Wt::Chart::FillRangeType fillRange = Wt::Chart::NoFill; 342 Wt::Chart::AxisValue location = Wt::Chart::ZeroValue; 343 bool isGridLinesEnabled = false; 344 chartPlot2vec(envDialog->contents(),xcor,ycor,seriesType,fillRange,location,isGridLinesEnabled,titre,legendx,legendy,500,300); 345 } 346 347 void GWt_accelerator::faireDessinPhaseSpace(WContainerWidget* toto, particleBeam* beam, string elementLabel, string namex, string namey, int typeFaisceau) 348 { 349 350 vector<double> xcor; 351 vector<double> ycor; 352 vector<string> legende; 353 string titre; 354 Wt::Chart::SeriesType seriesType; 355 356 if ( typeFaisceau == 0 ) { 357 seriesType = Wt::Chart::LineSeries; 358 titre = "phase space rms"; 359 beam->donneesDessinEllipse(xcor,ycor,legende,namex,namey); 360 } else if ( typeFaisceau == 1 ) { 361 seriesType = Wt::Chart::PointSeries; 362 titre = " phase space "; 363 beam->particlesPhaseSpaceData(xcor,ycor,legende,namex,namey); 364 // for ( int kk=0; kk < xcor.size(); kk++) 365 // { 366 // cout << " dess. phas. x= " << xcor.at(kk) << " x'= " << ycor.at(kk) << endl; 367 // } 368 } else { 369 GWt_dialog warningBeamState(" graphical analysis", "the beam state does not allow providing a drawing with macroparticles !", GWt_dialog::Error, false,true); 370 warningBeamState.exec(); 371 return; 372 } 373 374 std::time_t result = std::time(NULL); 375 GWt_dialog* phaseSpaceDialog = new GWt_dialog(WString("phase space (")+std::asctime(std::localtime(&result))+")",toto,false); 376 eDialog_.push_back(phaseSpaceDialog); 377 phaseSpaceDialog->setMinimumSize(400,400); 378 phaseSpaceDialog->setClosable(true); 379 new WText(" case : " + nameOfCase_, phaseSpaceDialog->contents()); 380 new WBreak(phaseSpaceDialog->contents()); 381 new WText(" after element : " + elementLabel, phaseSpaceDialog->contents()); 382 383 for (int k=0 ; k < (int)legende.size(); k++) { 384 new WBreak(phaseSpaceDialog->contents()); 385 new WText(legende.at(k), phaseSpaceDialog->contents()); 386 } 387 388 Wt::Chart::FillRangeType fillRange = Wt::Chart::NoFill; 389 Wt::Chart::AxisValue location = Wt::Chart::ZeroValue; 390 bool isGridLinesEnabled = false; 391 chartPlot2vec(phaseSpaceDialog->contents(),xcor,ycor,seriesType,fillRange,location,isGridLinesEnabled,titre,namex,namey,500,300); 392 393 phaseSpaceDialog->show(); 394 } 395 396 397 void GWt_accelerator::dessinerHistogramme() 398 { 399 toto_->clear(); 400 401 // std::time_t result = std::time(NULL); 402 // GWt_dialog* histoDialog = new GWt_dialog(WString("histogramme (")+std::asctime(std::localtime(&result))+")",toto_,false); 403 // eDialog_.push_back(histoDialog); 404 // histoDialog->setMinimumSize(400,400); 405 // histoDialog->setClosable(true); 406 407 string elementLabel = choixHistoDessin_->currentText().toUTF8(); 408 particleBeam* beam = dataManager_->getDiagnosticBeam_deprecated(elementLabel); 409 if (beam == NULL) { 410 GWt_dialog warningBeamState("histogram","the beam does not exist at the end of this element !", GWt_dialog::Error, false,true); 411 warningBeamState.exec(); 412 return; 413 } 414 415 if (!beam->particleRepresentationOk()) { 416 GWt_dialog warningBeamState("histogram", "the beam state does not allow providing a drawing with macroparticles !", GWt_dialog::Error, false,true); 417 warningBeamState.exec(); 418 return; 419 } 420 421 unsigned iabs= choixVariableHisto_->currentIndex(); 422 vector<double> xcor; 423 vector<int> hist; 424 // double out[3]= {0.0}; 425 vector<string> legende; 426 beam->histogramme(iabs,xcor,hist,legende); 427 428 cout<<"xcor.size()= "<<xcor.size()<<", hist.size()= "<<hist.size()<<endl; 429 ////////////////////////////////////////////////////////////////////////////////// 430 431 int n = hist.size(); 432 vector<double> x; 433 x.resize(2*n+2); 434 vector<double> y; 435 y.resize(2*n+2); 436 437 int j= 0; 438 x.at(j)= xcor[0]; 439 y.at(j)= 0.0; 440 j++; 441 x.at(j)= xcor[0]; 442 y.at(j)= hist[0]; 443 j++; 444 445 for (int i = 1; i < n; ++i) { 446 x.at(j)= xcor[i]; 447 y.at(j)= hist[i-1]; 448 j++; 449 x.at(j)= xcor[i]; 450 y.at(j)= hist[i]; 451 j++; 452 } 453 454 x.at(j)= xcor[n]; 455 y.at(j)= hist[n-1]; 456 j++; 457 x.at(j)= xcor[n]; 458 y.at(j)= 0.0; 459 ////////////////////////////////////////////////////////////////////////////////// 460 std::time_t result = std::time(NULL); 461 GWt_dialog* histoDialog = new GWt_dialog(WString("histogramme (")+std::asctime(std::localtime(&result))+")",toto_,false); 462 eDialog_.push_back(histoDialog); 463 histoDialog->setMinimumSize(400,400); 464 histoDialog->setClosable(true); 465 466 histoDialog->show(); 467 468 WContainerWidget *w= histoDialog->contents(); 469 470 // // legendes 471 // string unites[2]; 472 // if(iabs == 0 || iabs == 1 || iabs == 2) { 473 // unites[0]= unites[1]= " mm"; 474 // } 475 // if(iabs == 3 || iabs == 4) { 476 // unites[0]= unites[1]= " mrad"; 477 // } 478 // if(iabs == 5) { 479 // unites[0]= " MeV"; unites[1]= " KeV"; 480 // } 481 482 new WText(" case : " + nameOfCase_, w); 483 new WBreak(w); 484 new WText(" after element : " + elementLabel, w); 485 486 for (int k=0 ; k < (int)legende.size(); k++) { 487 new WBreak(w); 488 new WText(legende.at(k), w); 489 } 490 491 492 // new WText(" entries : "+ mixedTools::intToString((int)out[0]),w); 493 // new WBreak(w); 494 // new WText(" mean : "+ mixedTools::doubleToString(out[1])+unites[0],w); 495 // new WBreak(w); 496 // new WText(" sigma rms : "+ mixedTools::doubleToString(out[2])+unites[1],w); 497 ////////////////////////////////////////////////////////////////////////////////// 498 499 string titre; 500 if(iabs == 0) titre="x-coordinate"; 501 if(iabs == 1) titre="y-coordinate"; 502 if(iabs == 2) titre="z-coordinate"; 503 if(iabs == 3) titre="xp-divergence"; 504 if(iabs == 4) titre="yp-devergence"; 505 if(iabs == 5) titre="kinetic energy"; 506 507 string xname; 508 if(iabs == 0) xname=" x (mm)"; 509 if(iabs == 1) xname=" y (mm)"; 510 if(iabs == 2) xname=" z (mm)"; 511 if(iabs == 3) xname=" xp (mrad)"; 512 if(iabs == 4) xname=" yp (mrad)"; 513 if(iabs == 5) xname=" dEcin/Ecin (%)"; 514 515 string yname; 516 Wt::Chart::SeriesType seriesType = Wt::Chart::LineSeries; 517 Wt::Chart::FillRangeType fillRange = Wt::Chart::ZeroValueFill; 518 Wt::Chart::AxisValue location = Wt::Chart::MinimumValue; 519 bool isGridLinesEnabled = true; 520 chartPlot2vec(w,x,y,seriesType,fillRange,location,isGridLinesEnabled,titre,xname,yname,500,300); 521 } 522 523 524 525 void GWt_accelerator::chartPlot2vec(WContainerWidget* toto,vector<double>& xcor,vector<double>& ycor,Wt::Chart::SeriesType seriesType,Wt::Chart::FillRangeType fillRange,Wt::Chart::AxisValue value,bool isGridLinesEnables,string title,string legendx,string legendy,int width,int height,bool makeIcon) 526 { 527 int nbpts = xcor.size(); 528 cout << " PspaApplication::chartPlot2vec nbpts = " << nbpts << endl; 529 530 WStandardItemModel *model = new WStandardItemModel(nbpts, 2, toto); 531 for (int i = 0; i < nbpts; ++i) { 532 model->setData(i, 0, xcor.at(i)); 533 model->setData(i, 1, ycor.at(i)); 534 // cout << " PspaApplication::chartPlot2vec el= " << i+1 << " x= " << xcor.at(i) << " y= " << ycor.at(i) << endl; 535 } 536 // cout << " PspaApplication::chartPlot2vec FLAG 0 " << endl; 537 Wt::Chart::WCartesianChart *chart = new Wt::Chart::WCartesianChart(toto); 538 if (!makeIcon) chart->setTitle(title); 539 chart->initLayout(); 540 chart->setModel(model); // set the model 541 chart->setXSeriesColumn(0); // set the column that holds the X data 542 543 chart->setType(Wt::Chart::ScatterPlot); // set type to ScatterPlot 544 chart->setLegendEnabled(false); // enable the legend 545 546 // Provide space for the X and Y axis and title. 547 chart->setPlotAreaPadding(80, Left); 548 chart->setPlotAreaPadding(40, Bottom); 549 chart->setPlotAreaPadding(60, Top); 550 551 // Typically, for mathematical functions, you want the axes to cross 552 // at the 0 mark (value= ZeroValue) 553 chart->axis(Wt::Chart::XAxis).setLocation(value); 554 chart->axis(Wt::Chart::YAxis).setLocation(value); 555 556 // cout << " PspaApplication::chartPlot2vec FLAG 1 " << endl; 557 558 Wt::Chart::WDataSeries s(1,seriesType); 559 s.setPen(WColor("red")); 560 s.setFillRange(fillRange); 561 chart->addSeries(s); 562 563 Wt::Chart::WAxis& axis = chart->axis(Wt::Chart::XAxis); 564 axis.setLabelFormat("%.3f"); 565 axis.setTitle(legendx); 566 567 chart->axis(Wt::Chart::Y1Axis).setTitle(legendy); 568 569 if(isGridLinesEnables) { 570 axis.setGridLinesEnabled(true); 571 chart->axis(Wt::Chart::Y1Axis).setGridLinesEnabled(true); 572 } 573 // cout << " PspaApplication::chartPlot2vec FLAG 2 " << endl; 574 575 chart->resize(width,height); // WPaintedWidget must be given explicit size 576 chart->setMargin(10, Top | Bottom); // ? 577 chart->setMargin(WLength::Auto, Left | Right); //? 578 579 if (makeIcon) { 580 chart->setLegendEnabled(false); // enable the legend 581 chart->setPlotAreaPadding(0); 582 chart->setAxisPadding(0); 583 WFont xAxisFont = chart->axis(Wt::Chart::XAxis).labelFont(); 584 xAxisFont.setSize(8); 585 WFont yAxisFont = chart->axis(Wt::Chart::YAxis).labelFont(); 586 yAxisFont.setSize(8); 587 chart->axis(Wt::Chart::XAxis).setLabelFont(xAxisFont); 588 chart->axis(Wt::Chart::YAxis).setLabelFont(yAxisFont); 589 } 590 // cout << " PspaApplication::chartPlot2vec FLAG 3 " << endl; 591 592 #ifdef HAS_IMAGEMAGIC 593 594 // cout << " PspaApplication::chartPlot2vec FLAG MAGIC " << endl; 595 596 // no background 597 chart->setBackground(WBrush(Wt::NoBrush)); 598 599 // axis black 600 chart->axis(XAxis).setPen(WColor("black")); 601 chart->axis(YAxis).setPen(WColor("black")); 602 603 std::string name; 604 /* 605 Wt::WRasterImage pngImage("png", 1000, 1000); 606 Wt::WPainter p(&pngImage); 607 chart->paint(p); 608 name = workingDir_ + "/chart-"+sessionId ()+".png"; 609 std::ofstream f(name.c_str(), std::ios::out |std::ios::trunc | std::ios::binary); 610 pngImage.write(f); 611 */ 612 613 Wt::WPdfImage pdfImage("1000", "600"); 614 { 615 Wt::WPainter p1(&pdfImage); 616 chart->paint(p1); 617 } 618 619 name = workingDir_ + "/chart-"+sessionId ()+".pdf"; 620 std::ofstream f1(name.c_str(), std::ios::out | std::ios::binary); 621 pdfImage.write(f1); 622 623 new WText("<a href='workingArea/chart-"+sessionId ()+".pdf' target='_blank'>Sauvegarder l'image</a>",toto); 624 625 #endif 626 // cout << " PspaApplication::chartPlot2vec FLAG FIN" << endl; 627 628 } 629 630 631 632
Note: See TracChangeset
for help on using the changeset viewer.