diff options
Diffstat (limited to 'clients/tde/src/widgets/sevensegment.cpp')
| -rw-r--r-- | clients/tde/src/widgets/sevensegment.cpp | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/clients/tde/src/widgets/sevensegment.cpp b/clients/tde/src/widgets/sevensegment.cpp new file mode 100644 index 0000000..f97c428 --- /dev/null +++ b/clients/tde/src/widgets/sevensegment.cpp @@ -0,0 +1,456 @@ +/* + * Remote Laboratory Seven Segment Display Widget + * + * 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 3 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. + * + * (c) 2012 - 2015 Timothy Pearson + * Raptor Engineering + * http://www.raptorengineeringinc.com + */ + +#include <stdlib.h> + +#include <tqpainter.h> + +#include "sevensegment.h" + +Display7Segment::Display7Segment( TQWidget *parent, const char *name ) + : TQFrame( parent, name ) +{ + init(); +} + +Display7Segment::~Display7Segment() { + free(m_prevSegments); + free(m_currentSegments); +} + +void Display7Segment::init() { + setFrameStyle(TQFrame::Box | TQFrame::Raised); + prevSegments = 0; + val = 0; + smallPoint = TRUE; + setSegmentStyle(Flat); + m_prevSegments = (char*)malloc(sizeof(char)*9); + m_currentSegments = (char*)malloc(sizeof(char)*9); + m_prevSegments[0] = 99; + m_currentSegments[0] = 99; + setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); +} + +void Display7Segment::setLitSegments(unsigned char segs) { + // This produces an array of up to 10 chars, with each char being the number of a lit segment, and the list being terminated with the number 99 + // The bit input in segs is active high + // The bit sequence, MSB to LSB, is dp a b c d e f g + // Segment letters are taken from ug130.pdf + + if (prevSegments != segs) { + int i = 0; + if (segs & 0x80) { m_currentSegments[i] = 7; i++; } + if (segs & 0x40) { m_currentSegments[i] = 0; i++; } + if (segs & 0x20) { m_currentSegments[i] = 2; i++; } + if (segs & 0x10) { m_currentSegments[i] = 5; i++; } + if (segs & 0x08) { m_currentSegments[i] = 6; i++; } + if (segs & 0x04) { m_currentSegments[i] = 4; i++; } + if (segs & 0x02) { m_currentSegments[i] = 1; i++; } + if (segs & 0x01) { m_currentSegments[i] = 3; i++; } + + m_currentSegments[i] = 99; + + update(); + } + + prevSegments = segs; +} + +void Display7Segment::drawContents( TQPainter *p ) +{ + // Draw all segments + TQPoint pos; + int digitSpace = smallPoint ? 2 : 1; + int xSegLen = width()*5/(1*(5 + digitSpace) + digitSpace); + int ySegLen = height()*5/12; + int segLen = ySegLen > xSegLen ? xSegLen : ySegLen; + int xAdvance = segLen*( 5 + 1 )/5; + int xOffset = ( width() - xAdvance + segLen/5 )/2; + int yOffset = ( height() - segLen*2 )/2; + + pos = TQPoint(xOffset, yOffset); + drawDigit(pos, *p, segLen, m_currentSegments); +} + +TQSize Display7Segment::sizeHint() const { + return TQSize(10 + 9 * (1 + (smallPoint ? 0 : 1)), 23); +} + +void Display7Segment::setSegmentStyle( SegmentStyle s ) { + fill = (s == Flat || s == Filled); + shadow = (s == Outline || s == Filled); + update(); +} + +Display7Segment::SegmentStyle Display7Segment::segmentStyle() const { + Q_ASSERT(fill || shadow); + if (!fill && shadow) { + return Outline; + } + if (fill && shadow) { + return Filled; + } + return Flat; +} + +static void addPoint( TQPointArray &a, const TQPoint &p ) { + uint n = a.size(); + a.resize(n + 1); + a.setPoint(n, p); +} + +void Display7Segment::drawDigit(const TQPoint &pos, TQPainter &p, int segLen, const char *newSegs) { + char updates[20][2]; // Can hold 2 times number of segments, only + // first 10 used if segment table is correct + int nErases; + int nUpdates; + const char *segs; + int i,j; + + const char erase = 0; + const char draw = 1; +// const char leaveAlone = 2; + + segs = m_prevSegments; + for ( nErases=0; segs[nErases] != 99; nErases++ ) { + updates[nErases][0] = erase; // Get segments to erase to + updates[nErases][1] = segs[nErases]; // remove old char + } + nUpdates = nErases; + segs = newSegs; + for(i = 0 ; segs[i] != 99 ; i++) { + for ( j=0; j<nErases; j++ ) { + if ( segs[i] == updates[j][1] ) { // Same segment ? +// FIXME +// Always redraw segments for now, as dragging windows in front of the LED display currently erases the occluded portion(s) of the display! +#if 0 + updates[j][0] = leaveAlone; // yes, already on screen + break; +#endif + } + } + if ( j == nErases ) { // If not already on screen + updates[nUpdates][0] = draw; + updates[nUpdates][1] = segs[i]; + nUpdates++; + } + } + for ( i=0; i<nUpdates; i++ ) { + if ( updates[i][0] == draw ) { + drawSegment( pos, updates[i][1], p, segLen ); + } + if (updates[i][0] == erase) { + drawSegment( pos, updates[i][1], p, segLen, TRUE ); + } + } + + memcpy(m_prevSegments, newSegs, sizeof(char)*9); +} + +void Display7Segment::drawSegment(const TQPoint &pos, char segmentNo, TQPainter &p, int segLen, bool erase) { + TQPoint pt = pos; + int width = segLen/5; + + const TQColorGroup & g = colorGroup(); + TQColor lightColor,darkColor,fgColor; + if (erase) { + lightColor = backgroundColor(); + darkColor = lightColor; + fgColor = lightColor; + } + else { + lightColor = g.light(); + darkColor = g.dark(); + fgColor = g.foreground(); + } + +#define LINETO(X,Y) addPoint( a, TQPoint(pt.x() + (X),pt.y() + (Y))) +#define LIGHT +#define DARK + + if ( fill ) { + TQPointArray a(0); + + //The following is an exact copy of the switch below. + //don't make any changes here + switch ( segmentNo ) { + case 0 : + p.moveTo(pt); + LIGHT; + LINETO(segLen - 1,0); + DARK; + LINETO(segLen - width - 1,width); + LINETO(width,width); + LINETO(0,0); + break; + case 1 : + pt += TQPoint(0 , 1); + p.moveTo(pt); + LIGHT; + LINETO(width,width); + DARK; + LINETO(width,segLen - width/2 - 2); + LINETO(0,segLen - 2); + LIGHT; + LINETO(0,0); + break; + case 2 : + pt += TQPoint(segLen - 1 , 1); + p.moveTo(pt); + DARK; + LINETO(0,segLen - 2); + LINETO(-width,segLen - width/2 - 2); + LIGHT; + LINETO(-width,width); + LINETO(0,0); + break; + case 3 : + pt += TQPoint(0 , segLen); + p.moveTo(pt); + LIGHT; + LINETO(width,-width/2); + LINETO(segLen - width - 1,-width/2); + LINETO(segLen - 1,0); + DARK; + if (width & 1) { // adjust for integer division error + LINETO(segLen - width - 3,width/2 + 1); + LINETO(width + 2,width/2 + 1); + } else { + LINETO(segLen - width - 1,width/2); + LINETO(width,width/2); + } + LINETO(0,0); + break; + case 4 : + pt += TQPoint(0 , segLen + 1); + p.moveTo(pt); + LIGHT; + LINETO(width,width/2); + DARK; + LINETO(width,segLen - width - 2); + LINETO(0,segLen - 2); + LIGHT; + LINETO(0,0); + break; + case 5 : + pt += TQPoint(segLen - 1 , segLen + 1); + p.moveTo(pt); + DARK; + LINETO(0,segLen - 2); + LINETO(-width,segLen - width - 2); + LIGHT; + LINETO(-width,width/2); + LINETO(0,0); + break; + case 6 : + pt += TQPoint(0 , segLen*2); + p.moveTo(pt); + LIGHT; + LINETO(width,-width); + LINETO(segLen - width - 1,-width); + LINETO(segLen - 1,0); + DARK; + LINETO(0,0); + break; + case 7 : + if ( smallPoint ) // if smallpoint place'.' between other digits + pt += TQPoint(segLen + width/2 , segLen*2); + else + pt += TQPoint(segLen/2 , segLen*2); + p.moveTo(pt); + DARK; + LINETO(width,0); + LINETO(width,-width); + LIGHT; + LINETO(0,-width); + LINETO(0,0); + break; + case 8 : + pt += TQPoint(segLen/2 - width/2 + 1 , segLen/2 + width); + p.moveTo(pt); + DARK; + LINETO(width,0); + LINETO(width,-width); + LIGHT; + LINETO(0,-width); + LINETO(0,0); + break; + case 9 : + pt += TQPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width); + p.moveTo(pt); + DARK; + LINETO(width,0); + LINETO(width,-width); + LIGHT; + LINETO(0,-width); + LINETO(0,0); + break; +#if defined(QT_CHECK_RANGE) + default : + tqWarning( "Display7Segment::drawSegment: (%s) Internal error." + " Illegal segment id: %d\n", + name( "unnamed" ), segmentNo ); +#endif + } + // End exact copy + p.setPen( fgColor ); + p.setBrush( fgColor ); + p.drawPolygon( a ); + p.setBrush( NoBrush ); + + pt = pos; + } +#undef LINETO +#undef LIGHT +#undef DARK + +#define LINETO(X,Y) p.lineTo(TQPoint(pt.x() + (X),pt.y() + (Y))) +#define LIGHT p.setPen(lightColor) +#define DARK p.setPen(darkColor) + if ( shadow ) { + switch ( segmentNo ) { + case 0 : + p.moveTo(pt); + LIGHT; + LINETO(segLen - 1,0); + DARK; + LINETO(segLen - width - 1,width); + LINETO(width,width); + LINETO(0,0); + break; + case 1 : + pt += TQPoint(0,1); + p.moveTo(pt); + LIGHT; + LINETO(width,width); + DARK; + LINETO(width,segLen - width/2 - 2); + LINETO(0,segLen - 2); + LIGHT; + LINETO(0,0); + break; + case 2 : + pt += TQPoint(segLen - 1 , 1); + p.moveTo(pt); + DARK; + LINETO(0,segLen - 2); + LINETO(-width,segLen - width/2 - 2); + LIGHT; + LINETO(-width,width); + LINETO(0,0); + break; + case 3 : + pt += TQPoint(0 , segLen); + p.moveTo(pt); + LIGHT; + LINETO(width,-width/2); + LINETO(segLen - width - 1,-width/2); + LINETO(segLen - 1,0); + DARK; + if (width & 1) { // adjust for integer division error + LINETO(segLen - width - 3,width/2 + 1); + LINETO(width + 2,width/2 + 1); + } else { + LINETO(segLen - width - 1,width/2); + LINETO(width,width/2); + } + LINETO(0,0); + break; + case 4 : + pt += TQPoint(0 , segLen + 1); + p.moveTo(pt); + LIGHT; + LINETO(width,width/2); + DARK; + LINETO(width,segLen - width - 2); + LINETO(0,segLen - 2); + LIGHT; + LINETO(0,0); + break; + case 5 : + pt += TQPoint(segLen - 1 , segLen + 1); + p.moveTo(pt); + DARK; + LINETO(0,segLen - 2); + LINETO(-width,segLen - width - 2); + LIGHT; + LINETO(-width,width/2); + LINETO(0,0); + break; + case 6 : + pt += TQPoint(0 , segLen*2); + p.moveTo(pt); + LIGHT; + LINETO(width,-width); + LINETO(segLen - width - 1,-width); + LINETO(segLen - 1,0); + DARK; + LINETO(0,0); + break; + case 7 : + if ( smallPoint ) // if smallpoint place'.' between other digits + pt += TQPoint(segLen + width/2 , segLen*2); + else + pt += TQPoint(segLen/2 , segLen*2); + p.moveTo(pt); + DARK; + LINETO(width,0); + LINETO(width,-width); + LIGHT; + LINETO(0,-width); + LINETO(0,0); + break; + case 8 : + pt += TQPoint(segLen/2 - width/2 + 1 , segLen/2 + width); + p.moveTo(pt); + DARK; + LINETO(width,0); + LINETO(width,-width); + LIGHT; + LINETO(0,-width); + LINETO(0,0); + break; + case 9 : + pt += TQPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width); + p.moveTo(pt); + DARK; + LINETO(width,0); + LINETO(width,-width); + LIGHT; + LINETO(0,-width); + LINETO(0,0); + break; +#if defined(QT_CHECK_RANGE) + default : + tqWarning( "Display7Segment::drawSegment: (%s) Internal error." + " Illegal segment id: %d\n", + name( "unnamed" ), segmentNo ); +#endif + } + } + +#undef LINETO +#undef LIGHT +#undef DARK +} + +#include "sevensegment.moc"
\ No newline at end of file |
