#include <config.h>
#include <utils/gui/div/GUIDesigns.h>
#include "MFXSevenSegment.h"
#define ASCII_ZERO 48
FXDEFMAP(MFXSevenSegment) MFXSevenSegmentMap[] = {
FXMAPFUNC(SEL_PAINT, 0, MFXSevenSegment::onPaint),
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETVALUE, MFXSevenSegment::onCmdSetValue),
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETINTVALUE, MFXSevenSegment::onCmdSetIntValue),
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETINTVALUE, MFXSevenSegment::onCmdGetIntValue),
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE, MFXSevenSegment::onCmdSetStringValue),
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETSTRINGVALUE, MFXSevenSegment::onCmdGetStringValue),
};
FXIMPLEMENT(MFXSevenSegment, FXFrame, MFXSevenSegmentMap, ARRAYNUMBER(MFXSevenSegmentMap))
MFXSevenSegment::MFXSevenSegment(FXComposite* p, FXObject* tgt, FXSelector sel, FXuint opts, FXint pl, FXint pr, FXint pt, FXint pb) :
FXFrame(p, opts, 0, 0, 0, 0, pl, pr, pt, pb),
myValue(' '),
myLCDTextColor(FXRGB(0, 255, 0)),
myBackGroundColor(GUIDesignTextColorBlack),
myHorizontalSegmentLength(8),
myVerticalSegmentLength(8),
mySegmentThickness(3),
myGroove(1) {
setTarget(tgt);
setSelector(sel);
enable();
}
FXint
MFXSevenSegment::getDefaultWidth() {
return padleft + (myGroove << 1) + myHorizontalSegmentLength + padright + (border << 1);
}
FXint
MFXSevenSegment::getDefaultHeight() {
return padtop + (myGroove << 2) + (myVerticalSegmentLength << 1) + padbottom + (border << 1);
}
void
MFXSevenSegment::setText(FXchar val) {
if (FXString(val, 1).upper() != FXString(myValue, 1).upper()) {
myValue = val;
recalc();
update();
}
}
void
MFXSevenSegment::setFgColor(const FXColor clr) {
if (myLCDTextColor != clr) {
myLCDTextColor = clr;
recalc();
update();
}
}
void
MFXSevenSegment::setBgColor(const FXColor clr) {
if (myBackGroundColor != clr) {
myBackGroundColor = clr;
recalc();
update();
}
}
void
MFXSevenSegment::setHorizontal(const FXint len) {
if (len != myHorizontalSegmentLength) {
myHorizontalSegmentLength = (FXshort)len;
checkSize();
recalc();
update();
}
}
void
MFXSevenSegment::setVertical(const FXint len) {
if (len != myVerticalSegmentLength) {
myVerticalSegmentLength = (FXshort)len;
checkSize();
recalc();
update();
}
}
void
MFXSevenSegment::setThickness(const FXint w) {
if (w != mySegmentThickness) {
mySegmentThickness = (FXshort)w;
checkSize();
recalc();
update();
}
}
void
MFXSevenSegment::setGroove(const FXint w) {
if (w != myGroove) {
myGroove = (FXshort)w;
checkSize();
recalc();
update();
}
}
long
MFXSevenSegment::onPaint(FXObject*, FXSelector, void* ptr) {
FXEvent* event = (FXEvent*) ptr;
FXDCWindow dc(this, event);
drawFrame(dc, 0, 0, width, height);
dc.setForeground(myBackGroundColor);
dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
dc.setForeground(myLCDTextColor);
drawFigure(dc, myValue);
return 1;
}
long
MFXSevenSegment::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
FXchar* c = (FXchar*)ptr;
if (c[0] != '\0') {
setText(c[0]);
}
return 1;
}
long
MFXSevenSegment::onCmdGetIntValue(FXObject* sender, FXSelector, void*) {
FXint i = myValue - ASCII_ZERO;
if (i < 0) {
i = 0;
}
if (i > 9) {
i = 9;
}
sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&i);
return 1;
}
long
MFXSevenSegment::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
FXint i = *((FXint*)ptr);
if (i < 0) {
i = 0;
}
if (i > 9) {
i = 9;
}
setText((FXchar)(i + ASCII_ZERO));
return 1;
}
long
MFXSevenSegment::onCmdGetStringValue(FXObject* sender, FXSelector, void*) {
FXString s(myValue, 1);
sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&s);
return 1;
}
long
MFXSevenSegment::onCmdSetStringValue(FXObject*, FXSelector, void* ptr) {
FXString* s = (FXString*)ptr;
if (s->length()) {
setText(s->at(0));
}
return 1;
}
void
MFXSevenSegment::save(FXStream& store) const {
FXFrame::save(store);
store << myValue;
store << myLCDTextColor;
store << myBackGroundColor;
store << myHorizontalSegmentLength;
store << myVerticalSegmentLength;
store << mySegmentThickness;
store << myGroove;
}
void
MFXSevenSegment::load(FXStream& store) {
FXFrame::load(store);
store >> myValue;
store >> myLCDTextColor;
store >> myBackGroundColor;
store >> myHorizontalSegmentLength;
store >> myVerticalSegmentLength;
store >> mySegmentThickness;
store >> myGroove;
}
long
MFXSevenSegment::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
if (getParent()) {
return getParent()->handle(sender, sel, ptr);
}
return 0;
}
long
MFXSevenSegment::onQueryHelp(FXObject* sender, FXSelector sel, void* ptr) {
if (getParent()) {
return getParent()->handle(sender, sel, ptr);
}
return 0;
}
void
MFXSevenSegment::drawTopSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[4];
points[0].x = x;
points[0].y = y;
points[1].x = x + myHorizontalSegmentLength;
points[1].y = y;
points[2].x = x + myHorizontalSegmentLength - mySegmentThickness;
points[2].y = y + mySegmentThickness;
points[3].x = x + mySegmentThickness;
points[3].y = y + mySegmentThickness;
dc.fillPolygon(points, 4);
}
void
MFXSevenSegment::drawLeftTopSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[4];
points[0].x = x;
points[0].y = y;
points[1].x = x + mySegmentThickness;
points[1].y = y + mySegmentThickness;
points[2].x = x + mySegmentThickness;
points[2].y = y + myVerticalSegmentLength - (mySegmentThickness >> 1);
points[3].x = x;
points[3].y = y + myVerticalSegmentLength;
dc.fillPolygon(points, 4);
}
void
MFXSevenSegment::drawRightTopSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[4];
points[0].x = x + mySegmentThickness;
points[0].y = y;
points[1].x = x + mySegmentThickness;
points[1].y = y + myVerticalSegmentLength;
points[2].x = x;
points[2].y = y + myVerticalSegmentLength - (mySegmentThickness >> 1);
points[3].x = x;
points[3].y = y + mySegmentThickness;
dc.fillPolygon(points, 4);
}
void
MFXSevenSegment::drawMiddleSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[6];
points[0].x = x + mySegmentThickness;
points[0].y = y;
points[1].x = x + myHorizontalSegmentLength - mySegmentThickness;
points[1].y = y;
points[2].x = x + myHorizontalSegmentLength;
points[2].y = y + (mySegmentThickness >> 1);
points[3].x = x + myHorizontalSegmentLength - mySegmentThickness;
points[3].y = y + mySegmentThickness;
points[4].x = x + mySegmentThickness;
points[4].y = y + mySegmentThickness;
points[5].x = x;
points[5].y = y + (mySegmentThickness >> 1);
dc.fillPolygon(points, 6);
}
void
MFXSevenSegment::drawLeftBottomSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[4];
points[0].x = x;
points[0].y = y;
points[1].x = x + mySegmentThickness;
points[1].y = y + (mySegmentThickness >> 1);
points[2].x = x + mySegmentThickness;
points[2].y = y + myVerticalSegmentLength - mySegmentThickness;
points[3].x = x;
points[3].y = y + myVerticalSegmentLength;
dc.fillPolygon(points, 4);
}
void
MFXSevenSegment::drawRightBottomSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[4];
points[0].x = x + mySegmentThickness;
points[0].y = y;
points[1].x = x + mySegmentThickness;
points[1].y = y + myVerticalSegmentLength;
points[2].x = x;
points[2].y = y + myVerticalSegmentLength - mySegmentThickness;
points[3].x = x;
points[3].y = y + (mySegmentThickness >> 1);
dc.fillPolygon(points, 4);
}
void
MFXSevenSegment::drawBottomSegment(FXDCWindow& dc, FXshort x, FXshort y) {
FXPoint points[4];
points[0].x = x + mySegmentThickness;
points[0].y = y;
points[1].x = x + myHorizontalSegmentLength - mySegmentThickness;
points[1].y = y;
points[2].x = x + myHorizontalSegmentLength;
points[2].y = y + mySegmentThickness;
points[3].x = x;
points[3].y = y + mySegmentThickness;
dc.fillPolygon(points, 4);
}
void
MFXSevenSegment::drawSegments(FXDCWindow& dc, FXbool s1, FXbool s2, FXbool s3, FXbool s4, FXbool s5, FXbool s6, FXbool s7) {
FXshort sx = (FXshort)(border + padleft), sy = (FXshort)(border + padtop);
FXshort x, y;
if (options & LAYOUT_FILL) {
if (options & LAYOUT_FILL_X) {
myHorizontalSegmentLength = (FXshort)(width - padleft - padright - (border << 1));
if (myHorizontalSegmentLength < 4) {
myHorizontalSegmentLength = 4;
}
}
if (options & LAYOUT_FILL_Y) {
myVerticalSegmentLength = (FXshort)(height - padtop - padbottom - (border << 1)) >> 1;
if (myVerticalSegmentLength < 4) {
myVerticalSegmentLength = 4;
}
}
mySegmentThickness = FXMIN(myHorizontalSegmentLength, myVerticalSegmentLength) / 4;
myGroove = mySegmentThickness / 4;
if (mySegmentThickness < 1) {
mySegmentThickness = 1;
}
if (myGroove < 1) {
myGroove = 1;
}
if (options & LAYOUT_FILL_X) {
myHorizontalSegmentLength -= myGroove << 1;
}
if (options & LAYOUT_FILL_Y) {
myVerticalSegmentLength -= myGroove << 1;
}
}
if (s1) {
x = sx + myGroove;
y = sy;
drawTopSegment(dc, x, y);
}
if (s2) {
x = sx;
y = sy + myGroove;
drawLeftTopSegment(dc, x, y);
}
if (s3) {
x = sx + myGroove + myHorizontalSegmentLength - mySegmentThickness + myGroove;
y = sy + myGroove;
drawRightTopSegment(dc, x, y);
}
if (s4) {
x = sx + myGroove;
y = sy + myGroove + myVerticalSegmentLength - (mySegmentThickness >> 1) + myGroove;
drawMiddleSegment(dc, x, y);
}
if (s5) {
x = sx;
y = sy + (myGroove << 1) + myVerticalSegmentLength + myGroove;
drawLeftBottomSegment(dc, x, y);
}
if (s6) {
x = sx + myGroove + myHorizontalSegmentLength - mySegmentThickness + myGroove;
y = sy + (myGroove << 1) + myVerticalSegmentLength + myGroove;
drawRightBottomSegment(dc, x, y);
}
if (s7) {
x = sx + myGroove;
y = sy + (myGroove << 1) + myVerticalSegmentLength + myGroove + myVerticalSegmentLength + myGroove - mySegmentThickness;
drawBottomSegment(dc, x, y);
}
}
void
MFXSevenSegment::drawFigure(FXDCWindow& dc, FXchar figure) {
switch (figure) {
case ' ' :
drawSegments(dc, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
break;
case '(' :
drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
break;
case ')' :
drawSegments(dc, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE);
break;
case '[' :
drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
break;
case ']' :
drawSegments(dc, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE);
break;
case '=' :
drawSegments(dc, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE);
break;
case '-' :
case ':' :
drawSegments(dc, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE);
break;
case '_' :
case '.' :
case ',' :
drawSegments(dc, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE);
break;
case '0' :
drawSegments(dc, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE);
break;
case '1' :
drawSegments(dc, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE);
break;
case '2' :
drawSegments(dc, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE);
break;
case '3' :
drawSegments(dc, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE);
break;
case '4' :
drawSegments(dc, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE);
break;
case '5' :
drawSegments(dc, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE);
break;
case '6' :
drawSegments(dc, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE);
break;
case '7' :
drawSegments(dc, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE);
break;
case '8' :
drawSegments(dc, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
break;
case '9' :
drawSegments(dc, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE);
break;
case 'a' :
case 'A' :
drawSegments(dc, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE);
break;
case 'b' :
case 'B' :
drawSegments(dc, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE);
break;
case 'c' :
case 'C' :
drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
break;
case 'd' :
case 'D' :
drawSegments(dc, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE);
break;
case 'e' :
case 'E' :
drawSegments(dc, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE);
break;
case 'f' :
case 'F' :
drawSegments(dc, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE);
break;
case 'g' :
case 'G' :
drawSegments(dc, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE);
break;
case 'h' :
case 'H' :
drawSegments(dc, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE);
break;
case 'i' :
case 'I' :
drawSegments(dc, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
break;
case 'j' :
case 'J' :
drawSegments(dc, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE);
break;
case 'l' :
case 'L' :
drawSegments(dc, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE);
break;
case 'n' :
case 'N' :
drawSegments(dc, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE);
break;
case 'o' :
case 'O' :
drawSegments(dc, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE);
break;
case 'p' :
case 'P' :
drawSegments(dc, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE);
break;
case 'q' :
case 'Q' :
drawSegments(dc, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE);
break;
case 'r' :
case 'R' :
drawSegments(dc, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE);
break;
case 's' :
case 'S' :
drawSegments(dc, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE);
break;
case 't' :
case 'T' :
drawSegments(dc, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE);
break;
case 'u' :
case 'U' :
drawSegments(dc, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE);
break;
case 'x' :
case 'X' :
drawSegments(dc, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE);
break;
case 'y' :
case 'Y' :
drawSegments(dc, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE);
break;
default :
fxerror("MFXSevenSegment doesn't support: %c\n", figure);
}
}
void
MFXSevenSegment::checkSize() {
if (myHorizontalSegmentLength < 3) {
myHorizontalSegmentLength = 3;
mySegmentThickness = 1;
}
if (myVerticalSegmentLength < 3) {
myVerticalSegmentLength = 3;
mySegmentThickness = 1;
}
if (mySegmentThickness < 1) {
mySegmentThickness = 1;
}
if (myHorizontalSegmentLength < (mySegmentThickness << 1)) {
myHorizontalSegmentLength = (mySegmentThickness << 1) + 1;
}
if (myVerticalSegmentLength < (mySegmentThickness << 1)) {
myVerticalSegmentLength = (mySegmentThickness << 1) + 1;
}
if (myHorizontalSegmentLength < 8 || myVerticalSegmentLength < 8) {
myGroove = 2;
}
if (myHorizontalSegmentLength < 1 || myVerticalSegmentLength < 3 || mySegmentThickness < 3) {
myGroove = 1;
}
if (myGroove >= mySegmentThickness) {
myGroove = mySegmentThickness - 1;
}
}