probepositioner.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by David Saxton                                    *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "oscilloscope.h"
00012 #include "oscilloscopedata.h"
00013 #include "oscilloscopeview.h"
00014 #include "probepositioner.h"
00015 
00016 #include <qevent.h>
00017 #include <qpainter.h>
00018 #include <qpointarray.h>
00019 
00020 #include <algorithm>
00021 #include <cmath>
00022 
00023 ProbePositioner::ProbePositioner(QWidget *parent, const char *name)
00024         : QWidget( parent, name, WNoAutoErase )
00025 {
00026         m_probePosOffset = 0;
00027         p_draggedProbe = 0;
00028         setFixedWidth( int(probeArrowWidth) );
00029         setBackgroundMode(NoBackground);
00030         b_needRedraw = true;
00031         m_pixmap = 0;
00032 }
00033 
00034 ProbePositioner::~ProbePositioner()
00035 {
00036         delete m_pixmap;
00037 }
00038 
00039 void ProbePositioner::forceRepaint()
00040 {
00041         b_needRedraw = true;
00042         repaint(false);
00043 }
00044 
00045 int ProbePositioner::probeOutputHeight() const
00046 {
00047         int height = int( Oscilloscope::self()->oscilloscopeView->height() - probeArrowHeight );
00048         int numProbes = Oscilloscope::self()->numberOfProbes();
00049         if ( numProbes == 0 )
00050                 numProbes = 1;
00051         return height / numProbes;
00052 }
00053 
00054 
00055 int ProbePositioner::probePosition( ProbeData *probeData ) const
00056 {
00057         if (!probeData)
00058                 return -1;
00059         
00060         int spacing = probeOutputHeight();
00061         int probeNum = Oscilloscope::self()->probeNumber(probeData->id());
00062         
00063         return int( probeArrowHeight/2 + spacing*( probeNum + probeData->drawPosition() ) );
00064 }
00065 
00066 
00067 void ProbePositioner::setProbePosition( ProbeData *probeData, int position )
00068 {
00069         if (!probeData)
00070                 return;
00071         
00072         int height = int( Oscilloscope::self()->oscilloscopeView->height() - probeArrowHeight );
00073         int numProbes = Oscilloscope::self()->numberOfProbes();
00074         int spacing = height / numProbes;
00075         int probeNum = Oscilloscope::self()->probeNumber(probeData->id());
00076         
00077         int minPos = int(probeArrowHeight/2);
00078         int maxPos = int(Oscilloscope::self()->oscilloscopeView->height() - (probeArrowHeight/2)) - 1;
00079         if ( position < minPos )
00080                 position = minPos;
00081         else if ( position > maxPos )
00082                 position = maxPos;
00083         
00084         probeData->setDrawPosition( float(position - probeArrowHeight/2)/float(spacing) - probeNum );
00085         
00086         forceRepaint();
00087         Oscilloscope::self()->oscilloscopeView->updateView();
00088 }
00089 
00090 
00091 ProbeData* ProbePositioner::probeAtPosition( const QPoint &pos )
00092 {
00093         int relativeArrowHeight = int( probeArrowHeight * ( 1. - float(pos.x()/probeArrowWidth) ) );
00094         
00095         const ProbeDataMap::const_iterator end = m_probeDataMap.end();
00096         for ( ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it )
00097         {
00098                 ProbeData *probeData = it.data();
00099                 int currentPos = probePosition(probeData);
00100                 m_probePosOffset = pos.y() - currentPos;
00101                 if ( std::abs(m_probePosOffset) <= relativeArrowHeight )
00102                         return probeData;
00103         }
00104         m_probePosOffset = 0;
00105         return 0;
00106 }
00107 
00108 
00109 void ProbePositioner::slotProbeDataRegistered( int id, ProbeData *probe )
00110 {
00111         m_probeDataMap[id] = probe;
00112         connect( probe, SIGNAL(displayAttributeChanged()), this, SLOT(forceRepaint()) );
00113         // This connect doesn't really belong here, but it save a lot of code
00114         connect( probe, SIGNAL(displayAttributeChanged()), Oscilloscope::self()->oscilloscopeView, SLOT(updateView()) );
00115         forceRepaint();
00116         Oscilloscope::self()->oscilloscopeView->updateView();
00117 }
00118 
00119 
00120 void ProbePositioner::slotProbeDataUnregistered( int id )
00121 {
00122         m_probeDataMap.erase(id);
00123         // We "set" the position of each probe to force it into proper bounds
00124         
00125         const ProbeDataMap::const_iterator end = m_probeDataMap.end();
00126         for ( ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it )
00127                 setProbePosition( it.data(), probePosition( it.data() ) );
00128         
00129         forceRepaint();
00130 }
00131 
00132 
00133 void ProbePositioner::resizeEvent( QResizeEvent *e )
00134 {
00135         delete m_pixmap;
00136         m_pixmap = new QPixmap( e->size() );
00137         QWidget::resizeEvent(e);
00138         forceRepaint();
00139 }
00140 
00141                 
00142 void ProbePositioner::mousePressEvent( QMouseEvent * e )
00143 {
00144         p_draggedProbe = probeAtPosition(e->pos());
00145         if (p_draggedProbe)
00146                 e->accept();
00147         else
00148                 e->ignore();
00149 }
00150 
00151 
00152 void ProbePositioner::mouseReleaseEvent( QMouseEvent * e )
00153 {
00154         if (p_draggedProbe)
00155                 e->accept();
00156         else
00157                 e->ignore();
00158 }
00159 
00160 
00161 void ProbePositioner::mouseMoveEvent( QMouseEvent * e )
00162 {
00163         if (!p_draggedProbe)
00164         {
00165                 e->ignore();
00166                 return;
00167         }
00168         e->accept();
00169         
00170         setProbePosition( p_draggedProbe, e->pos().y() - m_probePosOffset );
00171         forceRepaint();
00172 }
00173 
00174 
00175 void ProbePositioner::paintEvent( QPaintEvent *e )
00176 {
00177         QRect r = e->rect();
00178         
00179         if (b_needRedraw)
00180         {
00181                 QPainter p;
00182                 m_pixmap->fill( paletteBackgroundColor() );
00183                 p.begin(m_pixmap);
00184                 p.setClipRegion(e->region());
00185                 
00186                 const ProbeDataMap::const_iterator end = m_probeDataMap.end();
00187                 for ( ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it )
00188                 {
00189                         ProbeData *probeData = it.data();
00190                         p.setBrush( probeData->color() );
00191                         int currentPos = probePosition(probeData);
00192                         
00193                         QPointArray pa(3);
00194                         pa[0] = QPoint( 0, int(currentPos-(probeArrowHeight/2)) );
00195                         pa[1] = QPoint( int(probeArrowWidth), currentPos );
00196                         pa[2] = QPoint( 0, int(currentPos+(probeArrowHeight/2)) );
00197                         
00198                         p.drawPolygon(pa);
00199                 }
00200                 b_needRedraw = false;
00201         }
00202         
00203         bitBlt( this, r.x(), r.y(), m_pixmap, r.x(), r.y(), r.width(), r.height() );
00204 }
00205 
00206 
00207 #include "probepositioner.moc"

Generated on Tue May 8 17:05:32 2007 for KTechLab by  doxygen 1.5.1