/* TUIpeer works in conjunction with an implementation of java.awt.Toolkit to provide a Text User Interface for programs using the Java AWT. Component is the base class for the various TUI component implementations. Copyright (C) 1997-2000 Stuart D. Gathman 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. 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Log: component.cc,v $ * Revision 1.1.1.1 2000/12/16 20:44:50 stuart * Released TUIPeer sources * * Revision 1.1 2000/12/14 20:55:17 stuart * Initial revision * */ #pragma implementation #include #include #include "component.h" #include "menucomp.h" #include "wincomp.h" #include "textdraw.h" Component::Component() { popup = 0; compID = -1; toolkit = 0; parent = 0; posx = posy = 0; width = height = 0; bgColor = 0; cursor = 1; enabled = true; visible = false; localtabs = true; } TextContext::TextContext() { fgColor = 2; textStyle = 0; textSize = 1; textAttr = A_NORMAL; dc = 0; } void TextContext::setDC(IndirectContext *t) { delete dc; dc = t; } void TextContext::operator=(const TextContext &that) { fontname = that.fontname; textStyle = that.textStyle; textSize = that.textSize; textAttr = that.textAttr; fgColor = that.fgColor; } TextContext::~TextContext() { delete dc; } Component::~Component() { if (toolkit) toolkit->removeComponentAt(compID); setParent(0); } // must delete through toolkit void Component::setParent(ContainerComponent *c) { if (parent != c) { ContainerComponent *oldparent = parent; parent = 0; if (oldparent) { oldparent->remove(this); oldparent->repaint(bounds()); } if (c) { parent = c; c->add(this); } setDC(); invalidate(); } } IndirectContext *Component::getDC() { if (!parent || !visible) return 0; IndirectContext *dc = parent->getDC(); if (dc) { dc->clipRect(bounds()); dc->translate(posx,posy); } return dc; } int Component::descale(short val,int s) { return (val /*+ s/2 */) / s; } void Component::remoteMethod(int cmd) { switch (cmd) { case DISABLE: enabled = false; return; case ENABLE: enabled = true; return; case HIDE: show(false); return; case SHOW: show(true); return; case NEXTFOCUS: nextFocus(); return; case REQUESTFOCUS: if (parent) parent->setfocus(this); else toolkit->setfocus(this); return; case SETBACKGROUND: bgColor = readShort(); textAttr = getAttr(); invalidate(); return; case SETFOREGROUND: fgColor = readShort(); textAttr = getAttr(); invalidate(); return; case SETFONT: fontname = readUTF(); textSize = readShort(); textStyle = readShort(); textAttr = getAttr(); invalidate(); return; case SETCURSOR: { int ctype = readShort(); if (ctype == 0) // default cursor wanted ctype = 1; setCursor(ctype); return; } case REPAINT: { short x,y,w,h; x = descale(readShort(),toolkit->scalex); y = descale(readShort(),toolkit->scaley); w = descale(readShort(),toolkit->scalex); h = descale(readShort(),toolkit->scaley); repaint(Rect(Point(y,x),w,h)); return; } case RESHAPE: { short x,y,w,h; x = descale(readShort(),toolkit->scalex); y = descale(readShort(),toolkit->scaley); w = descale(readShort(),toolkit->scalex); h = descale(readShort(),toolkit->scaley); reshape(x,y,w,h); return; } } fflush(stderr); abort(); } void Component::nextFocus() { if (parent) parent->nextFocus(); else setfocus(0); } void Component::prevFocus() { if (parent) parent->prevFocus(); else setfocus(0); } Rect Component::bounds() const { return Rect(Point(posy,posx),width,height); } Point Component::location() const { return Point(posy,posx); } void Component::reshape(int x,int y,int w,int h) { bool wasvisible = visible; show(false); posx = x; posy = y; width = w; height = h; show(wasvisible); //fprintf(stderr,"reshape(%d,%d,%d,%d)\n",x,y,w,h); } unsigned short TextContext::drawAttr(int x,int y) const { CHTYPE a = dc->get(x,y) & (A_REVERSE | A_DIM); if (textStyle & BOLD) a |= A_BOLD; if (textStyle & ITALIC) a |= A_UNDERLINE; if (fgColor < 2 && !(a & A_REVERSE)) a |= A_DIM; return a; } unsigned short TextContext::getAttr(short c) const { CHTYPE a = A_INVIS; switch (c) { case 0: a = A_NORMAL; break; case 1: a = A_REVERSE|A_DIM; break; case 2: a = A_REVERSE; break; } if (textStyle & BOLD) a |= A_BOLD; if (textStyle & ITALIC) a |= A_UNDERLINE; return a; } unsigned short TextContext::getAttr() const { CHTYPE a = TextContext::getAttr(bgColor); //if (fgColor == bgColor) // a |= A_INVIS; if (fgColor < 2 && !(a & A_REVERSE)) a |= A_DIM; return a; } void Component::setDC() { TextContext::setDC(getDC()); } void Component::show(bool b) { if (visible != b) { visible = b; setDC(); if (parent) parent->repaint(bounds()); } } void Component::invalidate() { repaint(Rect(0,0,height - 1,width - 1)); } void Component::repaint(const Rect &r) { if (visible && parent && !r.isempty()) parent->repaint(r.moverel(posy,posx)); } void Component::paint(DrawingContext *dc) { dc->fillRect(dc->clipRect(),TextContext::getAttr(bgColor)); } void Component::setCursor(int x,int y) { //fprintf(stderr,"Component%d::curpos(%d,%d)\n",compID,x,y); if (parent) parent->setCursor(posx + x, posy + y); } void Component::getfocus() { if (!isEnabled()) { setfocus(0); return; } if (parent) parent->setCursor(cursor); toolkit->callMethod(compID,REQUESTFOCUS); } void Component::losefocus() { //toolkit->callMethod(compID,NEXTFOCUS); } void Component::setCursor(int t) { if (cursor != t) { cursor = t; if (parent && hasFocus()) parent->setCursor(cursor); } } enum { VK_ENTER = 10, VK_BACK_SPACE = 8, VK_TAB = 9, VK_CANCEL = 3, VK_CLEAR = 12, VK_SHIFT = 16, VK_CONTROL = 17, VK_ALT = 18, VK_PAUSE = 19, VK_CAPS_LOCK = 20, VK_ESCAPE = 27, VK_SPACE = 32, VK_PAGE_UP = 33, VK_PAGE_DOWN = 34, VK_END = 35, VK_HOME = 36, VK_LEFT = 37, VK_UP = 38, VK_RIGHT = 39, VK_DOWN = 40, VK_NUMPAD0 = 96, VK_NUMPAD1 = 97, VK_NUMPAD2 = 98, VK_NUMPAD3 = 99, VK_NUMPAD4 = 100, VK_NUMPAD5 = 101, VK_NUMPAD6 = 102, VK_NUMPAD7 = 103, VK_NUMPAD8 = 104, VK_NUMPAD9 = 105, VK_MULTIPLY = 106, VK_ADD = 107, VK_SEPARATER = 108, VK_SUBTRACT = 109, VK_DECIMAL = 110, VK_DIVIDE = 111, VK_F1 = 112, VK_F2 = 113, VK_F3 = 114, VK_F4 = 115, VK_F5 = 116, VK_F6 = 117, VK_F7 = 118, VK_F8 = 119, VK_F9 = 120, VK_F10 = 121, VK_F11 = 122, VK_F12 = 123, VK_DELETE = 127, VK_NUM_LOCK = 144, VK_SCROLL_LOCK = 145, VK_PRINTSCREEN = 154, VK_INSERT = 155, VK_HELP = 156, VK_META = 157, VK_BACK_QUOTE = 192, VK_QUOTE = 222, VK_FINAL = 24, VK_CONVERT = 28, VK_NONCONVERT = 29, VK_ACCEPT = 30, VK_MODECHANGE = 31, VK_KANA = 21, VK_KANJI = 25, VK_UNDEFINED = 0 }; void Component::key(int k) { if (k == -1) return; //fprintf(stderr,"compID=%d key=0%o\n",compID,k); static const struct { short key, code; } keytab[] = { { KEY_HOME, VK_HOME }, { KEY_END, VK_END }, { KEY_PPAGE, VK_PAGE_UP }, { KEY_NPAGE, VK_PAGE_DOWN }, { KEY_UP, VK_UP }, { KEY_DOWN, VK_DOWN }, { KEY_LEFT, VK_LEFT }, { KEY_RIGHT, VK_RIGHT }, { KEY_IC, VK_INSERT }, { KEY_DC, VK_DELETE }, { KEY_HELP, VK_HELP }, { KEY_TAB, VK_TAB }, { KEY_BTAB, -VK_TAB }, { KEY_ENTER, VK_ENTER }, { KEY_LL, -VK_ENTER }, { KEY_F(1), VK_F1 }, // used to close window { KEY_F(2), VK_F2 }, { KEY_F(3), VK_F3 }, { KEY_F(4), VK_F4 }, { KEY_F(5), VK_F5 }, { KEY_F(6), VK_F6 }, { KEY_F(7), VK_F7 }, { KEY_F(8), VK_F8 }, { KEY_F(9), VK_F9 }, { KEY_F(10), VK_F10 }, // used to display menu { KEY_F(11), -VK_F1 }, { KEY_F(12), -VK_F2 }, { KEY_F(13), -VK_F3 }, { KEY_F(14), -VK_F4 }, // { KEY_F(15), -VK_F5 }, // used to size Window { KEY_F(16), -VK_F6 }, // { KEY_F(17), -VK_F7 }, // used to zoom Window { KEY_F(18), -VK_F8 }, { KEY_F(19), -VK_F9 }, { KEY_F(20), -VK_F10 }, // used to select Window from list { KEY_SHOME, -VK_HOME }, { KEY_SEND, -VK_END }, { KEY_SLEFT, -VK_LEFT }, { KEY_SRIGHT, -VK_RIGHT }, { KEY_SHELP, -VK_HELP }, { 0, 0 } }; if (toolkit->localtabs && localtabs) { Component *c = getTab(); if (c) switch (k) { case KEY_TAB: case KEY_ENTER: c->nextFocus(); return; case KEY_BTAB: c->prevFocus(); return; } } for (int i = 0; keytab[i].key; ++i) if (keytab[i].key == k) { int code = keytab[i].code; if (code < 0) toolkit->callMethod(compID,KEYPRESS,-code,1); else toolkit->callMethod(compID,KEYPRESS,code,0); return; } if (parent) parent->key(k); else Controller::key(k); } bool Component::inside(int x,int y) const { return (0 <= x && x < width && 0 <= y && y < height); } bool Component::isVisible() const { return visible; // && (!parent || parent->isVisible()); } bool Component::isEnabled() const { return enabled && (!parent || parent->isEnabled()) && visible; } bool Component::focusForward() { return isEnabled(); } bool Component::focusBackward() { return isEnabled(); } void Component::setSize(int w,int h) { reshape(posx,posy,w,h); } Point Component::absLocation() const { Point p = location(); ContainerComponent *par = getParent(); while (par) { p += par->location(); par = par->getParent(); } return p; }