// // Copyright (C) 1996 Ben Ross // // You may distribute under the terms of the GNU General Public // License as specified in the COPYING file. // // $Id: XeToggle.C,v 1.1 1996/11/17 09:53:31 ben Exp $ #include #include #define SIZE 12 XeToggle::XeToggle(XeObject* parent, const char* name, const char* className) : XeLabel(parent, name, className) { _borderWidth = 2; _inset = 0; _type = XE_TOGGLE; _inButton = TRUE; _autoSize = FALSE; _toggleState = FALSE; _justify = XeLabel::XE_JUSTIFY_RIGHT; XGCValues values; ulong valmask; valmask = GCForeground; values.foreground = lookupColour(this, "grey40"); _shadowGC = getGC(this, &values, valmask); values.foreground = lookupColour(this, "grey90"); _rshadowGC = getGC(this, &values, valmask); values.foreground = lookupColour(this, "grey55"); _hiliteGC = getGC(this, &values, valmask); values.foreground = _background; _backGC = getGC(this, &values, valmask); XSelectInput(gDisplay, _window, (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask)); // This should use the overridden version of setLabel setLabel(name); } XeToggle::~XeToggle(void) { } void XeToggle::setState(bool state) { _toggleState = state; hilite(_toggleState); } int XeToggle::doEvent(XEvent* theEvent) { switch(theEvent->type) { case Expose: hilite(_toggleState, TRUE); drawText(); break; case ButtonPress: case ButtonRelease: doButton((XButtonEvent *)theEvent); break; case MotionNotify: doMotion((XMotionEvent *)theEvent); break; default: XeObject::doEvent(theEvent); } return 0; } void XeToggle::setLabel(const char* label) { XeLabel::setLabel(label); // resize to widget size: int height = _font->ascent + _font->descent; int size = (_type == XE_RADIO) ? 14 : 12; int width = _borderWidth * 3 + size + XTextWidth(_font, _label, strlen(_label)); resize(width, height); } void XeToggle::doButton(XButtonEvent *event) { if(_toggleState && _type == XE_RADIO) return; if(event->type == ButtonPress) { _inButton = TRUE; hilite(!_toggleState); } else if(event->type == ButtonRelease) { if(_inButton) { _toggleState = !_toggleState; callCallbacks(XE_CB_ACTIVATE, &_toggleState); } } } void XeToggle::doMotion(XMotionEvent* event) { if(_toggleState && _type == XE_RADIO) return; int x = event->x; int y = event->y; if((x <= 0 || y <= 0 || x >= int(_width) || y >= int(_height)) && _inButton) { hilite(_toggleState); _inButton = FALSE; } else if((x >= 0 && y >= 0 && x <= int(_width) && y <= int(_height)) && !_inButton) { hilite(!_toggleState); _inButton = TRUE; } } void XeToggle::hilite(bool state, bool fromExpose) { XRectangle r1, r2; int size = (_type == XE_RADIO) ? 14 : 12; r2.x = 0; r2.y = _height/2 - size/2 - 1; r2.width = size; r2.height = size; r1.x = r2.x + _borderWidth; r1.y = r2.y + _borderWidth; r1.width = r2.width - 2 * _borderWidth; r1.height = r2.height - 2 * _borderWidth; if(_type == XE_TOGGLE) { if(state) { XFillRectangle(gDisplay, _window, _hiliteGC, r1.x, r1.y, r1.width, r1.height); drawBorder(r2, _borderWidth, _shadowGC, _rshadowGC); } else { if(!fromExpose) XClearArea(gDisplay, _window, r1.x, r1.y, r1.width, r1.height, False); drawBorder(r2, _borderWidth, _rshadowGC, _shadowGC); } } else { drawDiamond(r2, state); } } void XeToggle::drawDiamond(XRectangle& r, bool state) { XPoint tpts[6], ipts[4]; int x1 = r.x + r.width; int y1 = r.y + r.height; GC gc; tpts[0].x = r.x; tpts[0].y = r.y + r.height/2; tpts[1].x = r.x + r.width/2; tpts[1].y = r.y; tpts[2].x = x1; tpts[2].y = tpts[0].y; tpts[3].x = x1 - _borderWidth; tpts[3].y = tpts[0].y; tpts[4].x = tpts[1].x; tpts[4].y = r.y + _borderWidth; tpts[5].x = r.x + _borderWidth; tpts[5].y = tpts[0].y; ipts[1] = tpts[4]; gc = (state) ? _shadowGC : _rshadowGC; XFillPolygon(gDisplay, _window, gc, tpts, 6, Nonconvex, CoordModeOrigin); tpts[1].y = y1; tpts[4].y = y1 - _borderWidth; gc = (state) ? _rshadowGC : _shadowGC; XFillPolygon(gDisplay, _window, gc, tpts, 6, Nonconvex, CoordModeOrigin); ipts[0] = tpts[5]; ipts[2] = tpts[3]; ipts[3] = tpts[4]; gc = (state) ? _hiliteGC : _backGC; XFillPolygon(gDisplay, _window, gc, ipts, 4, Convex, CoordModeOrigin); }