You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ktechlab/src/gui/probepositioner.cpp

211 lines
5.5 KiB

/***************************************************************************
* Copyright (C) 2005 by David Saxton *
* david@bluehaze.org *
* *
* 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. *
***************************************************************************/
#include "oscilloscope.h"
#include "oscilloscopedata.h"
#include "oscilloscopeview.h"
#include "probepositioner.h"
#include <tqevent.h>
#include <tqpainter.h>
#include <tqpointarray.h>
#include <algorithm>
#include <cmath>
ProbePositioner::ProbePositioner(TQWidget *parent, const char *name)
: TQWidget( parent, name, WNoAutoErase )
{
m_probePosOffset = 0;
p_draggedProbe = 0l;
setFixedWidth( int(probeArrowWidth) );
setBackgroundMode(NoBackground);
b_needRedraw = true;
m_pixmap = 0l;
}
ProbePositioner::~ProbePositioner()
{
delete m_pixmap;
}
void ProbePositioner::forceRepaint()
{
b_needRedraw = true;
repaint(false);
}
int ProbePositioner::probeOutputHeight() const
{
int height = int( Oscilloscope::self()->oscilloscopeView->height() - probeArrowHeight );
int numProbes = Oscilloscope::self()->numberOfProbes();
if ( numProbes == 0 )
numProbes = 1;
return height / numProbes;
}
int ProbePositioner::probePosition( ProbeData *probeData ) const
{
if (!probeData)
return -1;
int spacing = probeOutputHeight();
int probeNum = Oscilloscope::self()->probeNumber(probeData->id());
return int( probeArrowHeight/2 + spacing*( probeNum + probeData->drawPosition() ) );
}
void ProbePositioner::setProbePosition( ProbeData *probeData, int position )
{
if (!probeData)
return;
int height = int( Oscilloscope::self()->oscilloscopeView->height() - probeArrowHeight );
int numProbes = Oscilloscope::self()->numberOfProbes();
int spacing = height / numProbes;
int probeNum = Oscilloscope::self()->probeNumber(probeData->id());
int minPos = int(probeArrowHeight/2);
int maxPos = int(Oscilloscope::self()->oscilloscopeView->height() - (probeArrowHeight/2)) - 1;
if ( position < minPos )
position = minPos;
else if ( position > maxPos )
position = maxPos;
probeData->setDrawPosition( float(position - probeArrowHeight/2)/float(spacing) - probeNum );
forceRepaint();
Oscilloscope::self()->oscilloscopeView->updateView();
}
ProbeData* ProbePositioner::probeAtPosition( const TQPoint &pos )
{
int relativeArrowHeight = int( probeArrowHeight * ( 1. - float(pos.x()/probeArrowWidth) ) );
const ProbeDataMap::const_iterator end = m_probeDataMap.end();
for ( ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it )
{
ProbeData *probeData = it.data();
int currentPos = probePosition(probeData);
m_probePosOffset = pos.y() - currentPos;
if ( std::abs(m_probePosOffset) <= relativeArrowHeight )
return probeData;
}
m_probePosOffset = 0;
return 0l;
}
void ProbePositioner::slotProbeDataRegistered( int id, ProbeData *probe )
{
m_probeDataMap[id] = probe;
connect( probe, TQT_SIGNAL(displayAttributeChanged()), this, TQT_SLOT(forceRepaint()) );
// This connect doesn't really belong here, but it save a lot of code
connect( probe, TQT_SIGNAL(displayAttributeChanged()), Oscilloscope::self()->oscilloscopeView, TQT_SLOT(updateView()) );
forceRepaint();
Oscilloscope::self()->oscilloscopeView->updateView();
}
void ProbePositioner::slotProbeDataUnregistered( int id )
{
m_probeDataMap.erase(id);
// We "set" the position of each probe to force it into proper bounds
const ProbeDataMap::const_iterator end = m_probeDataMap.end();
for ( ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it )
setProbePosition( it.data(), probePosition( it.data() ) );
forceRepaint();
}
void ProbePositioner::resizeEvent( TQResizeEvent *e )
{
delete m_pixmap;
m_pixmap = new TQPixmap( e->size() );
TQWidget::resizeEvent(e);
forceRepaint();
}
void ProbePositioner::mousePressEvent( TQMouseEvent * e )
{
p_draggedProbe = probeAtPosition(e->pos());
if (p_draggedProbe)
e->accept();
else
e->ignore();
}
void ProbePositioner::mouseReleaseEvent( TQMouseEvent * e )
{
if (p_draggedProbe)
e->accept();
else
e->ignore();
}
void ProbePositioner::mouseMoveEvent( TQMouseEvent * e )
{
if (!p_draggedProbe)
{
e->ignore();
return;
}
e->accept();
setProbePosition( p_draggedProbe, e->pos().y() - m_probePosOffset );
forceRepaint();
}
void ProbePositioner::paintEvent( TQPaintEvent *e )
{
TQRect r = e->rect();
if (b_needRedraw)
{
TQPainter p;
m_pixmap->fill( paletteBackgroundColor() );
p.begin(m_pixmap);
p.setClipRegion(e->region());
const ProbeDataMap::const_iterator end = m_probeDataMap.end();
for ( ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it )
{
ProbeData *probeData = it.data();
p.setBrush( probeData->color() );
int currentPos = probePosition(probeData);
TQPointArray pa(3);
pa[0] = TQPoint( 0, int(currentPos-(probeArrowHeight/2)) );
pa[1] = TQPoint( int(probeArrowWidth), currentPos );
pa[2] = TQPoint( 0, int(currentPos+(probeArrowHeight/2)) );
p.drawPolygon(pa);
}
b_needRedraw = false;
}
bitBlt( this, r.x(), r.y(), m_pixmap, r.x(), r.y(), r.width(), r.height() );
}
#include "probepositioner.moc"