summaryrefslogtreecommitdiffstats
path: root/clients/tde/src/widgets/sevensegment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clients/tde/src/widgets/sevensegment.cpp')
-rw-r--r--clients/tde/src/widgets/sevensegment.cpp456
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