/* * KmPlot - a math. function plotter for the KDE-Desktop * * Copyright (C) 1998, 1999 Klaus-Dieter Möller * 2000, 2002 kd.moeller@t-online.de * * This file is part of the KDE Project. * KmPlot is part of the KDE-EDU Project. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ // TQt includes #include #include #include #include #include #include #include // KDE includes #include #include #include #include #include #include #include #include // local includes #include "editfunction.h" #include "keditparametric.h" #include "kminmax.h" #include "settings.h" #include "ksliderwindow.h" #include "View.h" #include "View.moc" //minimum and maximum x range. Should always be accessible. double View::xmin = 0; double View::xmax = 0; View::View(bool const r, bool &mo, TDEPopupMenu *p, TQWidget* parent, const char* name ) : DCOPObject("View"), TQWidget( parent, name , WStaticContents ), buffer( width(), height() ), m_popupmenu(p), m_modified(mo), m_readonly(r), m_dcop_client(TDEApplication::kApplication()->dcopClient()) { csmode = csparam = -1; cstype = 0; areaDraw = false; areaUfkt = 0; areaPMode = 0; areaMin = areaMax = 0.0; w = h = 0; s = 0.0; fcx = 0; fcy = 0; csxpos = 0.0; csypos = 0.0; rootflg = false; tlgx = tlgy = drskalx = drskaly = 0.0;; stepWidth = 0.0; ymin = 0.0;; ymax = 0.0;; m_printHeaderTable = false; stop_calculating = false; m_minmax = 0; isDrawing = false; m_popupmenushown = 0; m_parser = new XParser(mo); init(); csflg=0; csmode=-1; backgroundcolor = Settings::backgroundcolor(); invertColor(backgroundcolor,inverted_backgroundcolor); setBackgroundColor(backgroundcolor); setMouseTracking(true); rootflg = false; for( int number = 0; number < SLIDER_COUNT; number++ ) sliders[ number ] = 0; updateSliders(); m_popupmenushown = 0; m_popupmenu->insertTitle( "",10); zoom_mode = Z_Normal; isDrawing=false; areaDraw = false; } void View::setMinMaxDlg(KMinMax *minmaxdlg) { m_minmax = minmaxdlg; } View::~View() { delete m_parser; } XParser* View::parser() { return m_parser; } void View::draw(TQPaintDevice *dev, int form) { int lx, ly; float sf; TQRect rc; TQPainter DC; // our painter DC.begin(dev); // start painting widget rc=DC.viewport(); w=rc.width(); h=rc.height(); setPlotRange(); setScaling(); if(form==0) // screen { ref=TQPoint(120, 100); lx=(int)((xmax-xmin)*100.*drskalx/tlgx); ly=(int)((ymax-ymin)*100.*drskaly/tlgy); DC.scale((float)h/(float)(ly+2*ref.y()), (float)h/(float)(ly+2*ref.y())); if(DC.xForm(TQPoint(lx+2*ref.x(), ly)).x() > DC.viewport().right()) { DC.resetXForm(); DC.scale((float)w/(float)(lx+2*ref.x()), (float)w/(float)(lx+2*ref.x())); } wm=DC.worldMatrix(); s=DC.xForm(TQPoint(1000, 0)).x()/1000.; dgr.Create( ref, lx, ly, xmin, xmax, ymin, ymax ); } else if(form==1) // printer { sf=72./254.; // 72dpi ref=TQPoint(100, 100); lx=(int)((xmax-xmin)*100.*drskalx/tlgx); ly=(int)((ymax-ymin)*100.*drskaly/tlgy); DC.scale(sf, sf); s=1.; m_printHeaderTable = ( ( KPrinter* ) dev )->option( "app-kmplot-printtable" ) != "-1"; drawHeaderTable( &DC ); dgr.Create( ref, lx, ly, xmin, xmax, ymin, ymax ); if ( ( (KPrinter* )dev )->option( "app-kmplot-printbackground" ) == "-1" ) DC.fillRect( dgr.GetFrame(), backgroundcolor); //draw a colored background //DC.end(); //((TQPixmap *)dev)->fill(TQColor("#FF00FF")); //DC.begin(dev); } else if(form==2) // svg { ref=TQPoint(0, 0); lx=(int)((xmax-xmin)*100.*drskalx/tlgx); ly=(int)((ymax-ymin)*100.*drskaly/tlgy); dgr.Create( ref, lx, ly, xmin, xmax, ymin, ymax ); DC.translate(-dgr.GetFrame().left(), -dgr.GetFrame().top()); s=1.; } else if(form==3) // bmp, png { sf=180./254.; // 180dpi ref=TQPoint(0, 0); lx=(int)((xmax-xmin)*100.*drskalx/tlgx); ly=(int)((ymax-ymin)*100.*drskaly/tlgy); dgr.Create( ref, lx, ly, xmin, xmax, ymin, ymax ); DC.end(); ((TQPixmap *)dev)->resize((int)(dgr.GetFrame().width()*sf), (int)(dgr.GetFrame().height()*sf)); ((TQPixmap *)dev)->fill(backgroundcolor); DC.begin(dev); DC.translate(-dgr.GetFrame().left()*sf, -dgr.GetFrame().top()*sf); DC.scale(sf, sf); s=1.; } dgr.borderThickness=(uint)(4*s); dgr.axesLineWidth = (uint)( Settings::axesLineWidth()*s ); dgr.gridLineWidth = (uint)( Settings::gridLineWidth()*s ); dgr.ticWidth = (uint)( Settings::ticWidth()*s ); dgr.ticLength = (uint)( Settings::ticLength() ); dgr.axesColor = Settings::axesColor().rgb(); dgr.gridColor=Settings::gridColor().rgb(); dgr.Skal( tlgx, tlgy ); if ( form!=0 && areaDraw) { areaUnderGraph(areaUfkt, areaPMode, areaMin,areaMax, areaParameter, &DC); areaDraw = false; if (stop_calculating) return; } dgr.Plot(&DC); PlotArea=dgr.GetPlotArea(); area=DC.xForm(PlotArea); hline.resize(area.width(), 1); vline.resize(1, area.height()); stepWidth=Settings::stepWidth(); isDrawing=true; setCursor(TQt::WaitCursor ); stop_calculating = false; for(TQValueVector::iterator ufkt=m_parser->ufkt.begin(); ufkt!=m_parser->ufkt.end() && !stop_calculating; ++ufkt) if ( !ufkt->fname.isEmpty() ) plotfkt(ufkt, &DC); isDrawing=false; restoreCursor(); csflg=0; DC.end(); // painting done } void View::plotfkt(Ufkt *ufkt, TQPainter *pDC) { char p_mode; int iy, k, ke, mflg; double x, y, dmin, dmax; TQPoint p1, p2; TQPen pen; pen.setCapStyle(TQt::RoundCap); iy=0; y=0.0; char const fktmode=ufkt->fstr[0].latin1(); if(fktmode=='y') return ; dmin=ufkt->dmin; dmax=ufkt->dmax; if(!ufkt->usecustomxmin) { if(fktmode=='r') dmin=0.; else if ( fktmode == 'x' ) dmin = -M_PI; else dmin = xmin; } if(!ufkt->usecustomxmax) { if(fktmode=='r') dmax=2*M_PI; else if ( fktmode == 'x' ) dmax = M_PI; else dmax = xmax; } double dx; if(fktmode=='r') if ( Settings::useRelativeStepWidth() ) dx=stepWidth*0.05/(dmax-dmin); else dx=stepWidth; else if ( Settings::useRelativeStepWidth() ) dx=stepWidth*(dmax-dmin)/area.width(); else dx=stepWidth; if(fktmode=='x') iy = m_parser->ixValue(ufkt->id)+1; p_mode=0; pen.setWidth((int)(ufkt->linewidth*s) ); pen.setColor(ufkt->color); pDC->setPen(pen); while(1) { k=0; ke=ufkt->parameters.count(); do { kdDebug() << "drawing " << ufkt->id << endl; if ( p_mode == 3 && stop_calculating) break; if( ufkt->use_slider == -1 ) { if ( !ufkt->parameters.isEmpty() ) ufkt->setParameter( ufkt->parameters[k].value ); } else { if ( KSliderWindow * sw = sliders[ ufkt->use_slider ] ) ufkt->setParameter( sw->slider->value() ); } mflg=2; if ( p_mode == 3) { if ( ufkt->integral_use_precision ) if ( Settings::useRelativeStepWidth() ) dx = ufkt->integral_precision*(dmax-dmin)/area.width(); else dx = ufkt->integral_precision; startProgressBar((int)double((dmax-dmin)/dx)/2); x = ufkt->oldx = ufkt->startx; //the initial x-point ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); } else x=dmin; bool forward_direction; if (dmin<0 && dmax<0) forward_direction = false; else forward_direction = true; if ( p_mode != 0 || ufkt->f_mode) // if not the function is hidden while ((x>=dmin && x<=dmax) || (p_mode == 3 && x>=dmin && !forward_direction) || (p_mode == 3 && x<=dmax && forward_direction)) { if ( p_mode == 3 && stop_calculating) { p_mode=1; x=dmax+1; continue; } switch(p_mode) { case 0: y=m_parser->fkt(ufkt, x); break; case 1: y=m_parser->a1fkt(ufkt, x); break; case 2: y=m_parser->a2fkt(ufkt, x); break; case 3: { y = m_parser->euler_method(x, ufkt); if ( int(x*100)%2==0) { TDEApplication::kApplication()->processEvents(); //makes the program usable when drawing a complicated integral function increaseProgressBar(); } break; } } if(fktmode=='r') { p2.setX(dgr.Transx(y*cos(x))); p2.setY(dgr.Transy(y*sin(x))); } else if(fktmode=='x') { p2.setX(dgr.Transx(y)); p2.setY(dgr.Transy(m_parser->fkt(iy, x))); } else { p2.setX(dgr.Transx(x)); p2.setY(dgr.Transy(y)); } if ( dgr.xclipflg || dgr.yclipflg ) { //if(mflg>=1) p1=p2; /*else { pDC->drawLine(p1, p2); p1=p2; mflg=1; }*/ } else { if(mflg<=1) pDC->drawLine(p1, p2); p1=p2; mflg=0; } if (p_mode==3) { if ( forward_direction) { x=x+dx; if (x>dmax && p_mode== 3) { forward_direction = false; x = ufkt->oldx = ufkt->startx; ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); mflg=2; } } else x=x-dx; // go backwards } else x=x+dx; } } while(++kf1_mode==1 && p_mode< 1) //draw the 1st derivative { p_mode=1; pen.setWidth((int)(ufkt->f1_linewidth*s) ); pen.setColor(ufkt->f1_color); pDC->setPen(pen); } else if(ufkt->f2_mode==1 && p_mode< 2) //draw the 2nd derivative { p_mode=2; pen.setWidth((int)(ufkt->f2_linewidth*s) ); pen.setColor(ufkt->f2_color); pDC->setPen(pen); } else if( ufkt->integral_mode==1 && p_mode< 3) //draw the integral { p_mode=3; pen.setWidth((int)(ufkt->integral_linewidth*s) ); pen.setColor(ufkt->integral_color); pDC->setPen(pen); } else break; //otherwise stop } if ( stopProgressBar() ) if( stop_calculating) KMessageBox::error(this,i18n("The drawing was cancelled by the user.")); } void View::drawHeaderTable(TQPainter *pDC) { TQString alx, aly, atx, aty, dfx, dfy; if( m_printHeaderTable ) { pDC->translate(250., 150.); pDC->setPen(TQPen(black, (int)(5.*s))); pDC->setFont(TQFont( Settings::headerTableFont(), 30) ); puts( Settings::headerTableFont().latin1() ); TQString minStr = Settings::xMin(); TQString maxStr = Settings::xMax(); getMinMax( Settings::xRange(), minStr, maxStr); alx="[ "+minStr+" | "+maxStr+" ]"; minStr = Settings::yMin(); maxStr = Settings::yMax(); getMinMax( Settings::yRange(), minStr, maxStr); aly="[ "+minStr+" | "+maxStr+" ]"; setpi(&alx); setpi(&aly); atx="1E = "+tlgxstr; setpi(&atx); aty="1E = "+tlgystr; setpi(&aty); dfx="1E = "+drskalxstr+" cm"; setpi(&dfx); dfy="1E = "+drskalystr+" cm"; setpi(&dfy); pDC->drawRect(0, 0, 1500, 230); pDC->Lineh(0, 100, 1500); pDC->Linev(300, 0, 230); pDC->Linev(700, 0, 230); pDC->Linev(1100, 0, 230); pDC->drawText(0, 0, 300, 100, AlignCenter, i18n("Parameters:")); pDC->drawText(300, 0, 400, 100, AlignCenter, i18n("Plotting Area")); pDC->drawText(700, 0, 400, 100, AlignCenter, i18n("Axes Division")); pDC->drawText(1100, 0, 400, 100, AlignCenter, i18n("Printing Format")); pDC->drawText(0, 100, 300, 65, AlignCenter, i18n("x-Axis:")); pDC->drawText(0, 165, 300, 65, AlignCenter, i18n("y-Axis:")); pDC->drawText(300, 100, 400, 65, AlignCenter, alx); pDC->drawText(300, 165, 400, 65, AlignCenter, aly); pDC->drawText(700, 100, 400, 65, AlignCenter, atx); pDC->drawText(700, 165, 400, 65, AlignCenter, aty); pDC->drawText(1100, 100, 400, 65, AlignCenter, dfx); pDC->drawText(1100, 165, 400, 65, AlignCenter, dfy); pDC->drawText(0, 300, i18n("Functions:")); pDC->Lineh(0, 320, 700); int ypos = 380; //for(uint ix=0; ixcountFunctions() && !stop_calculating; ++ix) for(TQValueVector::iterator it=m_parser->ufkt.begin(); it!=m_parser->ufkt.end() && !stop_calculating; ++it) { pDC->drawText(100, ypos, it->fstr); ypos+=60; } pDC->translate(-60., ypos+100.); } else pDC->translate(150., 150.); } void View::getMinMax( int koord, TQString &mini, TQString &maxi ) { switch(koord) { case 0: mini="-8.0"; maxi="8.0"; break; case 1: mini="-5.0"; maxi="5.0"; break; case 2: mini="0.0"; maxi="16.0"; break; case 3: mini="0.0"; maxi="10.0"; } } void View::setpi(TQString *s) { int i; TQChar c(960); while((i=s->find('p')) != -1) s->replace(i, 2, &c, 1); } bool View::root(double *x0, Ufkt *it) { if(rootflg) return false; double yn; double x=csxpos; double y=fabs(csypos); double dx=0.1; while(1) { if((yn=fabs(m_parser->fkt(it, x-dx))) < y) { x-=dx; y=yn; } else if((yn=fabs(m_parser->fkt(it, x+dx))) < y) { x+=dx; y=yn; } else dx/=10.; printf("x=%g, dx=%g, y=%g\n", x, dx, y); if(y<1e-8) { *x0=x; return true; } if(fabs(dx)<1e-8) return false; if(xxmax) return false; } } void View::paintEvent(TQPaintEvent *) { TQPainter p; p.begin(this); bitBlt( this, 0, 0, &buffer, 0, 0, width(), height() ); p.end(); } void View::resizeEvent(TQResizeEvent *) { if (isDrawing) //stop drawing integrals { stop_calculating = true; //stop drawing return; } buffer.resize(size() ); drawPlot(); } void View::drawPlot() { if( m_minmax->isShown() ) m_minmax->updateFunctions(); buffer.fill(backgroundcolor); draw(&buffer, 0); TQPainter p; p.begin(this); bitBlt( this, 0, 0, &buffer, 0, 0, width(), height() ); p.end(); } void View::mouseMoveEvent(TQMouseEvent *e) { if ( isDrawing) return; if (zoom_mode==4 && e->stateAfter() != TQt::NoButton) { TQPainter p; p.begin(this); bitBlt( this, 0, 0, &buffer, 0, 0, width(), height() ); p.end(); TQPainter painter(this); TQPen pen(TQt::white, 1, TQt::DotLine); painter.setRasterOp (TQt::XorROP); painter.setPen(pen); painter.setBackgroundMode (TQt::OpaqueMode); painter.setBackgroundColor (TQt::blue); painter.drawRect(rectangle_point.x(), rectangle_point.y(), e->pos().x()-rectangle_point.x(), e->pos().y()-rectangle_point.y()); return; } if ( zoom_mode!=0) return; if( m_popupmenushown>0 && !m_popupmenu->isShown() ) { if ( m_popupmenushown==1) csmode=-1; m_popupmenushown = 0; return; } if(csflg==1) // Fadenkreuz l�chen { bitBlt(this, area.left(), fcy, &hline, 0, 0, area.width(), 1); bitBlt(this, fcx, area.top(), &vline, 0, 0, 1, area.height()); csflg=0; } if(area.contains(e->pos()) || (e->button()==TQt::LeftButton && e->state()==TQt::LeftButton && csxpos>xmin && csxpospos()); Ufkt *it = 0; if( csmode >= 0 && csmode <= (int)m_parser->countFunctions() ) { int const ix = m_parser->ixValue(csmode); if (ix!=-1 && ((!m_parser->ufkt[ix].usecustomxmin) || (m_parser->ufkt[ix].usecustomxmin && csxpos>m_parser->ufkt[ix].dmin)) && ((!m_parser->ufkt[ix].usecustomxmax)||(m_parser->ufkt[ix].usecustomxmax && csxposufkt[ix].dmax)) ) { it = &m_parser->ufkt[ix]; if( it->use_slider == -1 ) { if( it->parameters.isEmpty() ) it->setParameter( it->parameters[csparam].value ); } else it->setParameter(sliders[ it->use_slider ]->slider->value() ); if ( cstype == 0) ptl.setY(dgr.Transy(csypos=m_parser->fkt( it, csxpos=dgr.Transx(ptl.x())))); else if ( cstype == 1) ptl.setY(dgr.Transy(csypos=m_parser->a1fkt( it, csxpos=dgr.Transx(ptl.x()) ))); else if ( cstype == 2) ptl.setY(dgr.Transy(csypos=m_parser->a2fkt( it, csxpos=dgr.Transx(ptl.x())))); if ( csyposymax) //the ypoint is not visible out_of_bounds = true; else if(fabs(dgr.Transy(ptl.y())) < (xmax-xmin)/80) { double x0; if(root(&x0, it)) { TQString str=" "; str+=i18n("root"); setStatusBar(str+TQString().sprintf(": x0= %+.5f", x0), 3); rootflg=true; } } else { setStatusBar("", 3); rootflg=false; } } else { csxpos=dgr.Transx(ptl.x()); csypos=dgr.Transy(ptl.y()); csflg = 1; } } else { csxpos=dgr.Transx(ptl.x()); csypos=dgr.Transy(ptl.y()); } ptd=DC.xForm(ptl); DC.end(); TQString sx, sy; if (out_of_bounds) { sx = sy = ""; } else { sx.sprintf(" x= %+.2f", (float)dgr.Transx(ptl.x()));//csxpos); sy.sprintf(" y= %+.2f", csypos); } if(csflg==0) // Hintergrund speichern { bitBlt(&hline, 0, 0, this, area.left(), fcy=ptd.y(), area.width(), 1); bitBlt(&vline, 0, 0, this, fcx=ptd.x(), area.top(), 1, area.height()); // Fadenkreuz zeichnen TQPen pen; if ( csmode == -1) pen.setColor(inverted_backgroundcolor); else { if ( csmode == -1) pen.setColor(inverted_backgroundcolor); else { switch (cstype) { case 0: pen.setColor( it->color); break; case 1: pen.setColor( it->f1_color); break; case 2: pen.setColor( it->f2_color); break; default: pen.setColor(inverted_backgroundcolor); } if ( pen.color() == backgroundcolor) // if the "Fadenkreuz" has the same color as the background, the "Fadenkreuz" will have the inverted color of background so you can see it easier pen.setColor(inverted_backgroundcolor); } } DC.begin(this); DC.setPen(pen); DC.Lineh(area.left(), fcy, area.right()); DC.Linev(fcx, area.bottom(), area.top()); DC.end(); } csflg=1; setCursor(TQt::blankCursor); setStatusBar(sx, 1); setStatusBar(sy, 2); } else { setCursor(arrowCursor); setStatusBar("", 1); setStatusBar("", 2); } } void View::mousePressEvent(TQMouseEvent *e) { if ( m_popupmenushown>0) return; if (isDrawing) { stop_calculating = true; //stop drawing return; } if ( zoom_mode==Z_Rectangular ) //rectangle zoom { zoom_mode=Z_Center; rectangle_point = e->pos(); return; } else if ( zoom_mode==Z_ZoomIn ) //zoom in { TQPainter DC; DC.begin(this); DC.setWindow(0, 0, w, h); DC.setWorldMatrix(wm); double real = dgr.Transx(DC.xFormDev(e->pos()).x()); double const diffx = (xmax-xmin)*(double)Settings::zoomInStep()/100; double const diffy = (ymax-ymin)*(double)Settings::zoomInStep()/100; if ( diffx < 0.00001 || diffy < 0.00001) return; Settings::setXMin( Parser::number( real-double(diffx) ) ); Settings::setXMax( Parser::number( real+double(diffx) ) ); real = dgr.Transy(DC.xFormDev(e->pos()).y()); Settings::setYMin( Parser::number( real-double(diffy) ) ); Settings::setYMax( Parser::number( real+double(diffy) ) ); Settings::setXRange(4); //custom x-range Settings::setYRange(4); //custom y-range drawPlot(); //update all graphs return; } else if ( zoom_mode==3 ) //zoom out { TQPainter DC; DC.begin(this); DC.setWindow(0, 0, w, h); DC.setWorldMatrix(wm); double real = dgr.Transx(DC.xFormDev(e->pos()).x()); double const diffx = (xmax-xmin)*(((double)Settings::zoomOutStep()/100) +1); double const diffy = (ymax-ymin)*(((double)Settings::zoomOutStep()/100) +1); if ( diffx > 1000000 || diffy > 1000000) return; Settings::setXMin( Parser::number( real-double(diffx) ) ); Settings::setXMax( Parser::number( real+double(diffx) ) ); real = dgr.Transy(DC.xFormDev(e->pos()).y()); Settings::setYMin( Parser::number( real-double(diffy) ) ); Settings::setYMax( Parser::number( real+double(diffy) ) ); Settings::setXRange(4); //custom x-range Settings::setYRange(4); //custom y-range drawPlot(); //update all graphs return; } else if ( zoom_mode==5 ) //center { TQPainter DC; DC.begin(this); DC.setWindow(0, 0, w, h); DC.setWorldMatrix(wm); double real = dgr.Transx(DC.xFormDev(e->pos()).x()); double const diffx = (xmax-xmin)/2; double const diffy = (ymax-ymin)/2; Settings::setXMin( Parser::number( real-double(diffx) ) ); Settings::setXMax( Parser::number( real+double(diffx) ) ); real = dgr.Transy(DC.xFormDev(e->pos()).y()); Settings::setYMin( Parser::number( real-double(diffy) ) ); Settings::setYMax( Parser::number( real+double(diffy) ) ); Settings::setXRange(4); //custom x-range Settings::setYRange(4); //custom y-range drawPlot(); //update all graphs return; } double const g=tlgy*double(xmax-xmin)/(2*double(ymax-ymin)); if( !m_readonly && e->button()==TQt::RightButton) //clicking with the right mouse button { char function_type; for( TQValueVector::iterator it = m_parser->ufkt.begin(); it != m_parser->ufkt.end(); ++it) { function_type = it->fstr[0].latin1(); if ( function_type=='y' || function_type=='r' || it->fname.isEmpty()) continue; if (!(((!it->usecustomxmin) || (it->usecustomxmin && csxpos>it->dmin)) && ((!it->usecustomxmax)||(it->usecustomxmax && csxposdmax)) )) continue; kdDebug() << "it:" << it->fstr << endl; int k=0; int const ke=it->parameters.count(); do { if( it->use_slider == -1 ) { if ( !it->parameters.isEmpty()) it->setParameter(it->parameters[k].value); } else { if ( KSliderWindow * sw = sliders[ it->use_slider ] ) it->setParameter( sw->slider->value() ); } if ( function_type=='x' && fabs(csxpos-m_parser->fkt(it, csxpos))< g && it->fstr.contains('t')==1) //parametric plot { TQValueVector::iterator ufkt_y = it+1; if ( fabs(csypos-m_parser->fkt(ufkt_y, csxpos)fstr.contains('t')==1) { if ( csmode == -1) { csmode=it->id; cstype=0; csparam = k; m_popupmenushown = 1; } else m_popupmenushown = 2; TQString y_name( ufkt_y->fstr ); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-1),false); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-2),false); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-3),false); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-4),false); m_popupmenu->changeTitle(10,ufkt_y->fstr+";"+y_name); m_popupmenu->exec(TQCursor::pos()); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-1),true); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-2),true); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-3),true); m_popupmenu->setItemEnabled(m_popupmenu->idAt(m_popupmenu->count()-4),true); return; } } else if( fabs(csypos-m_parser->fkt(it, csxpos))< g && it->f_mode) { if ( csmode == -1) { csmode=it->id; cstype=0; csparam = k; m_popupmenushown = 1; } else m_popupmenushown = 2; m_popupmenu->changeTitle(10, it->fstr); m_popupmenu->exec(TQCursor::pos()); return; } else if(fabs(csypos-m_parser->a1fkt( it, csxpos))< g && it->f1_mode) { if ( csmode == -1) { csmode=it->id; cstype=1; csparam = k; m_popupmenushown = 1; } else m_popupmenushown = 2; TQString function = it->fstr; function = function.left(function.find('(')) + '\''; m_popupmenu->changeTitle(10, function); m_popupmenu->exec(TQCursor::pos()); return; } else if(fabs(csypos-m_parser->a2fkt(it, csxpos))< g && it->f2_mode) { if ( csmode == -1) { csmode=it->id; cstype=2; csparam = k; m_popupmenushown = 1; } else m_popupmenushown = 2; TQString function = it->fstr; function = function.left(function.find('(')) + "\'\'"; m_popupmenu->changeTitle(10, function); m_popupmenu->exec(TQCursor::pos()); return; } } while(++kbutton()!=TQt::LeftButton) return ; if(csmode>=0) //disable trace mode if trace mode is enable { csmode=-1; setStatusBar("",3); setStatusBar("",4); mouseMoveEvent(e); return ; } for( TQValueVector::iterator it = m_parser->ufkt.begin(); it != m_parser->ufkt.end(); ++it) { if (it->fname.isEmpty() ) continue; switch(it->fstr[0].latin1()) { case 'x': case 'y': case 'r': continue; // Not possible to catch } if (!(((!it->usecustomxmin) || (it->usecustomxmin && csxpos>it->dmin)) && ((!it->usecustomxmax)||(it->usecustomxmax && csxposdmax)) )) continue; int k=0; int const ke=it->parameters.count(); do { if( it->use_slider == -1 ) { if ( !it->parameters.isEmpty() ) it->setParameter( it->parameters[k].value ); } else { if ( KSliderWindow * sw = sliders[ it->use_slider ] ) it->setParameter( sw->slider->value() ); } if(fabs(csypos-m_parser->fkt(it, csxpos))< g && it->f_mode) { csmode=it->id; cstype=0; csparam = k; m_minmax->selectItem(); setStatusBar(it->fstr,4); mouseMoveEvent(e); return; } if(fabs(csypos-m_parser->a1fkt( it, csxpos))< g && it->f1_mode) { csmode=it->id; cstype=1; csparam = k; m_minmax->selectItem(); TQString function = it->fstr; function = function.left(function.find('(')) + '\''; setStatusBar(function,4); mouseMoveEvent(e); return; } if(fabs(csypos-m_parser->a2fkt(it, csxpos))< g && it->f2_mode) { csmode=it->id; cstype=2; csparam = k; m_minmax->selectItem(); TQString function = it->fstr; function = function.left(function.find('(')) + "\'\'"; setStatusBar(function,4); mouseMoveEvent(e); return; } } while(++kpos().x() - rectangle_point.x() >= -2) && (e->pos().x() - rectangle_point.x() <= 2) || (e->pos().y() - rectangle_point.y() >= -2) && (e->pos().y() - rectangle_point.y() <= 2) ) { update(); return; } TQPainter DC; DC.begin(this); bitBlt( this, 0, 0, &buffer, 0, 0, width(), height() ); DC.setWindow(0, 0, w, h); DC.setWorldMatrix(wm); TQPoint p=DC.xFormDev(e->pos()); double real1x = dgr.Transx(p.x() ) ; double real1y = dgr.Transy(p.y() ) ; p=DC.xFormDev(rectangle_point); double real2x = dgr.Transx(p.x() ) ; double real2y = dgr.Transy(p.y() ) ; if ( real1x>xmax || real2x>xmax || real1xymax || real2y>ymax || real1yeval( minStr ); max = m_parser->eval( maxStr ); } } void View::setPlotRange() { coordToMinMax( Settings::xRange(), Settings::xMin(), Settings::xMax(), xmin, xmax ); coordToMinMax( Settings::yRange(), Settings::yMin(), Settings::yMax(), ymin, ymax ); } void View::setScaling() { TQString units[ 9 ] = { "10", "5", "2", "1", "0.5", "pi/2", "pi/3", "pi/4",i18n("automatic") }; if( Settings::xScaling() == 8) //automatic x-scaling { tlgx = double(xmax-xmin)/16; tlgxstr = units[ Settings::xScaling() ]; } else { tlgxstr = units[ Settings::xScaling() ]; tlgx = m_parser->eval( tlgxstr ); } if( Settings::yScaling() == 8) //automatic y-scaling { tlgy = double(ymax-ymin)/16; tlgystr = units[ Settings::yScaling() ]; } else { tlgystr = units[ Settings::yScaling() ]; tlgy = m_parser->eval( tlgystr ); } drskalxstr = units[ Settings::xPrinting() ]; drskalx = m_parser->eval( drskalxstr ); drskalystr = units[ Settings::yPrinting() ]; drskaly = m_parser->eval( drskalystr ); } void View::getSettings() { m_parser->setAngleMode( Settings::anglemode() ); m_parser->linewidth0 = Settings::gridLineWidth(); backgroundcolor = Settings::backgroundcolor(); invertColor(backgroundcolor,inverted_backgroundcolor); setBackgroundColor(backgroundcolor); } void View::init() { getSettings(); TQValueVector::iterator it = m_parser->ufkt.begin(); it->fname=""; while ( m_parser->ufkt.count() > 1) m_parser->Parser::delfkt( &m_parser->ufkt.last() ); } void View::stopDrawing() { if (isDrawing) stop_calculating = true; } void View::findMinMaxValue(Ufkt *ufkt, char p_mode, bool minimum, double &dmin, double &dmax, const TQString &str_parameter) { double x, y = 0; double result_x = 0; double result_y = 0; bool start = true; // TODO: parameter sliders if ( !ufkt->parameters.isEmpty() ) { for ( TQValueList::Iterator it = ufkt->parameters.begin(); it != ufkt->parameters.end(); ++it ) { if ( (*it).expression == str_parameter) { ufkt->setParameter( (*it).value ); break; } } } isDrawing=true; setCursor(TQt::WaitCursor ); double dx; if ( p_mode == 3) { stop_calculating = false; if ( ufkt->integral_use_precision ) if ( ufkt->integral_use_precision ) dx = ufkt->integral_precision*(dmax-dmin)/area.width(); else dx = ufkt->integral_precision; else if ( ufkt->integral_use_precision ) dx = stepWidth*(dmax-dmin)/area.width(); else dx = stepWidth; startProgressBar((int)double((dmax-dmin)/dx)/2); x = ufkt->oldx = ufkt->startx; //the initial x-point ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); } else { dx = stepWidth*(dmax-dmin)/area.width(); x=dmin; } bool forward_direction; if (dmin<0 && dmax<0) forward_direction = false; else forward_direction = true; while ((x>=dmin && x<=dmax) || (p_mode == 3 && x>=dmin && !forward_direction) || (p_mode == 3 && x<=dmax && forward_direction)) { if ( p_mode == 3 && stop_calculating) { p_mode = 1; x=dmax+1; continue; } switch(p_mode) { case 0: y=m_parser->fkt(ufkt, x); break; case 1: { y=m_parser->a1fkt( ufkt, x); break; } case 2: { y=m_parser->a2fkt(ufkt, x); break; } case 3: { y = m_parser->euler_method(x, ufkt); if ( int(x*100)%2==0) { TDEApplication::kApplication()->processEvents(); //makes the program usable when drawing a complicated integral function increaseProgressBar(); } break; } } if ( !isnan(x) && !isnan(y) ) { kdDebug() << "x " << x << endl; kdDebug() << "y " << y << endl; if (x>=dmin && x<=dmax) { if ( start) { result_x = x; result_y = y; start=false; } else if ( minimum &&y <=result_y) { result_x = x; result_y = y; } else if ( !minimum && y >=result_y) { result_x = x; result_y = y; } } } if (p_mode==3) { if ( forward_direction) { x=x+dx; if (x>dmax && p_mode== 3) { forward_direction = false; x = ufkt->oldx = ufkt->startx; ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); } } else x=x-dx; // go backwards } else x=x+dx; } stopProgressBar(); isDrawing=false; restoreCursor(); dmin = int(result_x*1000)/double(1000); dmax = int(result_y*1000)/double(1000); switch (p_mode) { case 0: dmax=m_parser->fkt(ufkt, dmin); break; case 1: dmax=m_parser->a1fkt(ufkt, dmin); break; case 2: dmax=m_parser->a2fkt(ufkt, dmin); break; } } void View::getYValue(Ufkt *ufkt, char p_mode, double x, double &y, const TQString &str_parameter) { // TODO: parameter sliders if ( !ufkt->parameters.isEmpty() ) { for ( TQValueList::Iterator it = ufkt->parameters.begin(); it != ufkt->parameters.end(); ++it ) { if ( (*it).expression == str_parameter) { ufkt->setParameter((*it).value); break; } } } switch (p_mode) { case 0: y= m_parser->fkt(ufkt, x); break; case 1: y=m_parser->a1fkt( ufkt, x); break; case 2: y=m_parser->a2fkt( ufkt, x); break; case 3: double dmin = ufkt->dmin; double dmax = ufkt->dmax; const double target = x; //this is the x-value the user had chosen bool forward_direction; if ( target>=0) forward_direction = true; else forward_direction = false; if(dmin==dmax) //no special plot range is specified. Use the screen border instead. { dmin=xmin; dmax=xmax; } double dx; if ( ufkt->integral_use_precision ) dx = ufkt->integral_precision*(dmax-dmin)/area.width(); else dx=stepWidth*(dmax-dmin)/area.width(); stop_calculating = false; isDrawing=true; setCursor(TQt::WaitCursor ); bool target_found=false; startProgressBar((int) double((dmax-dmin)/dx)/2); x = ufkt->oldx = ufkt->startx; //the initial x-point ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); while (x>=dmin && !stop_calculating && !target_found) { y = m_parser->euler_method( x, ufkt ); if ( int(x*100)%2==0) { TDEApplication::kApplication()->processEvents(); //makes the program usable when drawing a complicated integral function increaseProgressBar(); } if ( (x+dx > target && forward_direction) || ( x+dx < target && !forward_direction)) //right x-value is found target_found = true; if (forward_direction) { x=x+dx; if (x>dmax) { forward_direction = false; x = ufkt->oldx = ufkt->startx; ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); } } else x=x-dx; // go backwards } stopProgressBar(); isDrawing=false; restoreCursor(); break; } } void View::keyPressEvent( TQKeyEvent * e) { if ( zoom_mode != Z_Normal && e->key() == TQt::Key_Escape ) { resetZoom(); return; } if ( zoom_mode == Z_Center) //drawing a rectangle { zoom_mode = Z_Rectangular; update(); return; } if (isDrawing) { stop_calculating=true; return; } if (csmode==-1 ) return; TQMouseEvent *event; if (e->key() == TQt::Key_Left ) event = new TQMouseEvent(TQEvent::MouseMove,TQPoint(fcx-1,fcy-1),TQt::LeftButton,TQt::LeftButton); else if (e->key() == TQt::Key_Right ) event = new TQMouseEvent(TQEvent::MouseMove,TQPoint(fcx+1,fcy+1),TQt::LeftButton,TQt::LeftButton); else if (e->key() == TQt::Key_Up || e->key() == TQt::Key_Down) //switch graph in trace mode { TQValueVector::iterator it = &m_parser->ufkt[m_parser->ixValue(csmode)]; int const ke=it->parameters.count(); if (ke>0) { csparam++; if (csparam >= ke) csparam=0; } if (csparam==0) { int const old_csmode=csmode; char const old_cstype = cstype; bool start = true; bool found = false; while ( 1 ) { if ( old_csmode==csmode && !start) { cstype=old_cstype; break; } kdDebug() << "csmode: " << csmode << endl; switch(it->fstr[0].latin1()) { case 'x': case 'y': case 'r': break; default: { for (cstype=0;cstype<3;cstype++) //going through the function, the first and the second derivative { if (start) { if ( cstype==2) cstype=0; else cstype=old_cstype+1; start=false; } kdDebug() << " cstype: " << (int)cstype << endl; switch (cstype) { case (0): if (it->f_mode ) found=true; break; case (1): if ( it->f1_mode ) found=true; break; case (2): if ( it->f2_mode ) found=true; break; } if (found) break; } break; } } if (found) break; if ( ++it == m_parser->ufkt.end()) it = m_parser->ufkt.begin(); csmode = it->id; } } kdDebug() << "************************" << endl; kdDebug() << "csmode: " << (int)csmode << endl; kdDebug() << "cstype: " << (int)cstype << endl; kdDebug() << "csparam: " << csparam << endl; //change function in the statusbar switch (cstype ) { case 0: setStatusBar(it->fstr,4); break; case 1: { TQString function = it->fstr; function = function.left(function.find('(')) + '\''; setStatusBar(function,4); break; } case 2: { TQString function = it->fstr; function = function.left(function.find('(')) + "\'\'"; setStatusBar(function,4); break; } } event = new TQMouseEvent(TQEvent::MouseMove,TQPoint(fcx,fcy),TQt::LeftButton,TQt::LeftButton); } else if ( e->key() == TQt::Key_Space ) { event = new TQMouseEvent(TQEvent::MouseButtonPress,TQCursor::pos(),TQt::RightButton,TQt::RightButton); mousePressEvent(event); delete event; return; } else { event = new TQMouseEvent(TQEvent::MouseButtonPress,TQPoint(fcx,fcy),TQt::LeftButton,TQt::LeftButton); mousePressEvent(event); delete event; return; } mouseMoveEvent(event); delete event; } void View::areaUnderGraph( Ufkt *ufkt, char const p_mode, double &dmin, double &dmax, const TQString &str_parameter, TQPainter *DC ) { double x, y = 0; float calculated_area=0; int rectheight; areaMin = dmin; TQPoint p; TQColor color; switch(p_mode) { case 0: color = ufkt->color; break; case 1: color = ufkt->f1_color; break; case 2: color = ufkt->f2_color; break; case 3: color = ufkt->integral_color; break; } if ( DC == 0) //screen { int ly; buffer.fill(backgroundcolor); DC = new TQPainter(&buffer); ly=(int)((ymax-ymin)*100.*drskaly/tlgy); DC->scale((float)h/(float)(ly+2*ref.y()), (float)h/(float)(ly+2*ref.y())); } if(dmin==dmax) //no special plot range is specified. Use the screen border instead. { dmin=xmin; dmax=xmax; } // TODO: parameter sliders if ( !ufkt->parameters.isEmpty() ) { for ( TQValueList::Iterator it = ufkt->parameters.begin(); it != ufkt->parameters.end(); ++it ) { if ( (*it).expression == str_parameter) { ufkt->setParameter((*it).value); break; } } } double dx; if ( p_mode == 3) { stop_calculating = false; if ( ufkt->integral_use_precision ) dx = ufkt->integral_precision*(dmax-dmin)/area.width(); else dx = stepWidth*(dmax-dmin)/area.width(); startProgressBar((int)double((dmax-dmin)/dx)/2); x = ufkt->oldx = ufkt->startx; //the initial x-point ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; //paintEvent(0); /*TQPainter p; p.begin(this); bitBlt( this, 0, 0, &buffer, 0, 0, width(), height() ); p.end();*/ } else { dx = stepWidth*(dmax-dmin)/area.width(); x=dmin; } int const origoy = dgr.Transy(0.0); int const rectwidth = dgr.Transx(dx)- dgr.Transx(0.0)+1; setCursor(TQt::WaitCursor ); isDrawing=true; bool forward_direction; if (dmin<0 && dmax<0) forward_direction = false; else forward_direction = true; int intervals = tqRound((dmax-dmin)/dx); int at = 0; while ((at<=intervals) || (p_mode == 3 && x>=dmin && !forward_direction) || (p_mode == 3 && x<=dmax && forward_direction)) { if ( p_mode != 3 ) x = (intervals-at)*dmin + at*dmax; ++at; if ( p_mode == 3 && stop_calculating) { if (forward_direction) x=dmin-1; else x=dmax+1; break; continue; } switch(p_mode) { case 0: y=m_parser->fkt( ufkt, x); break; case 1: y=m_parser->a1fkt( ufkt, x); break; case 2: y=m_parser->a2fkt( ufkt, x); break; case 3: { y = m_parser->euler_method(x, ufkt); if ( int(x*100)%2==0) { TDEApplication::kApplication()->processEvents(); //makes the program usable when drawing a complicated integral function increaseProgressBar(); } break; } } p.setX(dgr.Transx(x)); p.setY(dgr.Transy(y)); if (dmin<=x && x<=dmax) { if( dgr.xclipflg || dgr.yclipflg ) //out of bounds { if (y>-10e10 && y<10e10) { if ( y<0) rectheight = origoy-p.y() ; else rectheight= -1*( p.y()-origoy); calculated_area = calculated_area + ( dx*y); DC->fillRect(p.x(),p.y(),rectwidth,rectheight,color); } } else { if ( y<0) rectheight = origoy-p.y(); else rectheight = -1*( p.y()-origoy); calculated_area = calculated_area + (dx*y); /*kdDebug() << "Area: " << area << endl; kdDebug() << "x:" << p.height() << endl; kdDebug() << "y:" << p.y() << endl; kdDebug() << "*************" << endl;*/ DC->fillRect(p.x(),p.y(),rectwidth,rectheight,color); } } if (p_mode==3) { if ( forward_direction) { x=x+dx; if (x>dmax && p_mode== 3) { forward_direction = false; x = ufkt->oldx = ufkt->startx; ufkt->oldy = ufkt->starty; ufkt->oldyprim = ufkt->integral_precision; paintEvent(0); } } else x=x-dx; // go backwards } else x=x+dx; } if ( stopProgressBar() ) { if( stop_calculating) { KMessageBox::error(this,i18n("The drawing was cancelled by the user.")); isDrawing=false; restoreCursor(); return; } } isDrawing=false; restoreCursor(); areaUfkt = ufkt; areaPMode = p_mode; areaMax = dmax; areaParameter = str_parameter; if ( DC->device() == &buffer) //draw the graphs to the screen { areaDraw=true; DC->end(); setFocus(); update(); draw(&buffer,0); } if ( calculated_area>0) dmin = int(calculated_area*1000)/double(1000); else dmin = int(calculated_area*1000)/double(1000)*-1; //don't answer with a negative number } bool View::isCalculationStopped() { if ( stop_calculating) { stop_calculating = false; return true; } else return false; } void View::updateSliders() { for( int number = 0; number < SLIDER_COUNT; number++) { if (sliders[ number ]) { sliders[ number ]->hide(); mnuSliders[ number ]->setChecked(false); //uncheck the slider-item in the menu } } for(TQValueVector::iterator it=m_parser->ufkt.begin(); it!=m_parser->ufkt.end(); ++it) { if (it->fname.isEmpty() ) continue; if( it->use_slider > -1 && (it->f_mode || it->f1_mode || it->f2_mode || it->integral_mode)) { // create the slider if it not exists already if ( sliders[ it->use_slider ] == 0 ) { sliders[ it->use_slider ] = new KSliderWindow( this, it->use_slider); connect( sliders[ it->use_slider ]->slider, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( drawPlot() ) ); connect( sliders[ it->use_slider ], TQ_SIGNAL( windowClosed( int ) ), this , TQ_SLOT( sliderWindowClosed(int) ) ); mnuSliders[ it->use_slider ]->setChecked(true); //set the slider-item in the menu } sliders[ it->use_slider ]->show(); } } } void View::mnuHide_clicked() { if ( csmode == -1 ) return; Ufkt *ufkt = &m_parser->ufkt[ m_parser->ixValue(csmode)]; switch (cstype ) { case 0: ufkt->f_mode=0; break; case 1: ufkt->f1_mode=0; break; case 2: ufkt->f2_mode=0; break; } drawPlot(); m_modified = true; updateSliders(); if (csmode==-1) return; if ( !ufkt->f_mode && !ufkt->f1_mode && !ufkt->f2_mode) //all graphs for the function are hidden { csmode=-1; TQMouseEvent *event = new TQMouseEvent(TQMouseEvent::KeyPress,TQCursor::pos(),TQt::LeftButton,TQt::LeftButton); mousePressEvent(event); //leave trace mode delete event; return; } else { TQKeyEvent *event = new TQKeyEvent(TQKeyEvent::KeyPress,TQt::Key_Up ,TQt::Key_Up ,0); keyPressEvent(event); //change selected graph delete event; return; } } void View::mnuRemove_clicked() { if ( csmode == -1 ) return; if ( KMessageBox::warningContinueCancel(this,i18n("Are you sure you want to remove this function?"), TQString(), KStdGuiItem::del()) == KMessageBox::Continue ) { Ufkt *ufkt = &m_parser->ufkt[m_parser->ixValue(csmode)]; char const function_type = ufkt->fstr[0].latin1(); if (!m_parser->delfkt( ufkt )) return; if (csmode!=-1) // if trace mode is enabled { csmode=-1; TQMouseEvent *event = new TQMouseEvent(TQMouseEvent::KeyPress,TQCursor::pos(),TQt::LeftButton,TQt::LeftButton); mousePressEvent(event); //leave trace mode delete event; } drawPlot(); if ( function_type != 'x' && function_type != 'y' && function_type != 'r' ) updateSliders(); m_modified = true; } } void View::mnuEdit_clicked() { if ( csmode == -1 ) return; if ( m_parser->ufkt[m_parser->ixValue(csmode)].fstr[0] == 'x') // a parametric function { int y_index = csmode+1; //the y-function if ( y_index == (int)m_parser->countFunctions()) y_index=0; KEditParametric* editParametric = new KEditParametric( m_parser, this ); editParametric->setCaption(i18n( "New Parametric Plot" )); editParametric->initDialog( csmode,y_index ); if( editParametric->exec() == TQDialog::Accepted ) { drawPlot(); m_modified = true; } } else // a plot function { EditFunction* editFunction = new EditFunction( m_parser, this ); editFunction->setCaption(i18n( "Edit Function Plot" )); editFunction->initDialog( csmode ); if( editFunction->exec() == TQDialog::Accepted ) { drawPlot(); updateSliders(); m_modified = true; } } } void View::mnuCopy_clicked() { if ( csmode == -1 ) return; if ( m_parser->sendFunction(csmode) ) m_modified = true; } void View::mnuMove_clicked() { if ( csmode == -1 ) return; if ( m_parser->sendFunction(csmode) ) { if (!m_parser->delfkt(csmode) ) return; drawPlot(); m_modified = true; } } void View::mnuNoZoom_clicked() { setCursor(TQt::ArrowCursor); zoom_mode = Z_Normal; } void View::mnuRectangular_clicked() { if ( zoom_mode == Z_Rectangular ) resetZoom(); else { setCursor(TQt::CrossCursor); zoom_mode = Z_Rectangular; } } void View::mnuZoomIn_clicked() { if ( zoom_mode == Z_ZoomIn ) resetZoom(); else { setCursor( TQCursor( SmallIcon( "magnify", 32), 10, 10 ) ); zoom_mode = Z_ZoomIn; } } void View::mnuZoomOut_clicked() { if ( zoom_mode == Z_ZoomOut ) resetZoom(); else { setCursor( TQCursor( SmallIcon( "lessen", 32), 10, 10 ) ); zoom_mode = Z_ZoomOut; } } void View::mnuCenter_clicked() { if ( zoom_mode == Z_Center ) resetZoom(); else { setCursor(TQt::PointingHandCursor); zoom_mode = Z_Center; } } void View::mnuTrig_clicked() { if ( Settings::anglemode()==0 ) //radians { Settings::setXMin("-(47/24)pi"); Settings::setXMax("(47/24)pi"); } else //degrees { Settings::setXMin("-352.5" ); Settings::setXMax("352.5" ); } Settings::setYMin("-4"); Settings::setYMax("4"); Settings::setXRange(4); //custom x-range Settings::setYRange(4); //custom y-range drawPlot(); //update all graphs } void View::invertColor(TQColor &org, TQColor &inv) { int r = org.red()-255; if ( r<0) r=r*-1; int g = org.green()-255; if ( g<0) g=g*-1; int b = org.blue()-255; if ( b<0) b=b*-1; inv.setRgb(r,g,b); } void View::restoreCursor() { switch (zoom_mode) { case Z_Normal: //no zoom setCursor(TQt::ArrowCursor); break; case Z_Rectangular: //rectangle zoom setCursor(TQt::CrossCursor); break; case Z_ZoomIn: //zoom in setCursor( TQCursor( SmallIcon( "magnify", 32), 10, 10 ) ); break; case Z_ZoomOut: //zoom out setCursor( TQCursor( SmallIcon( "lessen", 32), 10, 10 ) ); break; case Z_Center: //center a point setCursor(TQt::PointingHandCursor); break; } } bool View::event( TQEvent * e ) { if ( e->type() == TQEvent::WindowDeactivate && isDrawing) { stop_calculating = true; return true; } return TQWidget::event(e); //send the information further } void View::setStatusBar(const TQString &text, const int id) { if ( m_readonly) //if KmPlot is shown as a KPart with e.g Konqueror, it is only possible to change the status bar in one way: to call setStatusBarText { switch (id) { case 1: m_statusbartext1 = text; break; case 2: m_statusbartext2 = text; break; case 3: m_statusbartext3 = text; break; case 4: m_statusbartext4 = text; break; default: return; } TQString statusbartext = m_statusbartext1; if ( !m_statusbartext1.isEmpty() && !m_statusbartext2.isEmpty() ) statusbartext.append(" | "); statusbartext.append(m_statusbartext2); if ( !m_statusbartext2.isEmpty() && !m_statusbartext3.isEmpty() ) statusbartext.append(" | "); statusbartext.append(m_statusbartext3); if ( (!m_statusbartext2.isEmpty() || !m_statusbartext3.isEmpty() ) && !m_statusbartext4.isEmpty() ) statusbartext.append(" | "); statusbartext.append(m_statusbartext4); emit setStatusBarText(statusbartext); } else { TQByteArray parameters; TQDataStream arg( parameters, IO_WriteOnly); arg << text << id; m_dcop_client->send(m_dcop_client->appId(), "KmPlotShell","setStatusBarText(TQString,int)", parameters); } } void View::startProgressBar(int steps) { TQByteArray data; TQDataStream stream(data, IO_WriteOnly); stream << steps; m_dcop_client->send(m_dcop_client->appId(), "KmPlotShell","startProgressBar(int)", data); } bool View::stopProgressBar() { TQCString replyType; TQByteArray replyData; m_dcop_client->call(m_dcop_client->appId(), "KmPlotShell","stopProgressBar()", TQByteArray(), replyType, replyData); bool result; TQDataStream stream(replyData, IO_ReadOnly); stream >> result; return result; } void View::increaseProgressBar() { m_dcop_client->send(m_dcop_client->appId(), "KmPlotShell","increaseProgressBar()", TQByteArray()); } void View::sliderWindowClosed(int num) { mnuSliders[num]->setChecked(false); }