/* TUIpeer works in conjunction with an implementation of java.awt.Toolkit to provide a Text User Interface for programs using the Java AWT. 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. */ #pragma implementation #include "listcomp.h" #include "textdraw.h" #include "wincomp.h" #include #include #include #include struct Choice::StrList: StringList, TextArray { StrList(); const char *operator[](int i); string &getItem(int i) { return StringList::operator[](i); } int size() { return StringList::size(); } void add(const string &s) { StringList::add(s); } ~StrList(); }; Choice::StrList::StrList() { } const char *Choice::StrList::operator[](int i) { if (i >= 0 && i < size()) return getItem(i).c_str(); return ""; } Choice::StrList::~StrList() { } Choice::Choice(): txt(*new StrList) { maxwidth = 0; cursel = -1; inPopup = false; } Choice::~Choice() { delete &txt; } void Choice::addItem(const string &s,int i) { if (i >= 0 && i < txt.size()) txt.getItem(i) = s; else txt.add(s); int len = s.length(); if (len > maxwidth) maxwidth = len; if (cursel < 0) cursel = 0; } void Choice::remove(int i) { if (i >= 0 && i < txt.size()) { txt.deleteln(i); invalidate(); } } void Choice::select(int i) { int n = txt.size(); if (n > 0) { int nc = i % n; if (nc != cursel) { cursel = nc; invalidate(); } } } void Choice::paint(DrawingContext *dc) { dc->fillRect(dc->clipRect(),' '| textAttr); dc->writeStr(0,0,getSelectedItem(),textAttr); } int Choice::getSelectedIndex() const { return cursel; } int Choice::countItems() const { return txt.size(); } const string &Choice::getItem(int i) const { return txt.getItem(i); } const string &Choice::getSelectedItem() const { return getItem(cursel); } void Choice::getfocus() { Component::getfocus(); setCursor(0,0); } void Choice::key(int ky) { switch (ky) { case KEY_ENTER: if (!inPopup) { inPopup = true; bmsListBox lb(getSelectedItem().c_str(),txt); lb.setphys(Rect(absLocation(),maxwidth,countItems())); setfocus(&lb); int key = lb.run(); int newchoice = lb.get(); if (newchoice != cursel) { //select(newchoice); // will be done by server toolkit->callMethod(compID,SELECTCHOICE,newchoice); } if (key != KEY_ENTER) Component::key(key); inPopup = false; return; } } Component::key(ky); } void Choice::remoteMethod(int cmd) { switch (cmd) { case SELECTCHOICE: select(readShort()); return; case REMOVECHOICE: remove(readShort()); return; case ADDCHOICEITEM: string s(readUTF()); int i = readShort(); addItem(s,i); return; } Component::remoteMethod(cmd); } struct LongSet: VHSet { LongSet(int i): VHSet(10) { } }; ListComponent::ListComponent(): txt(*new StringList), selected(*new LongSet(10)) { multi = false; topline = 0; curline = 0; } ListComponent::~ListComponent() { delete &txt; } void ListComponent::remoteMethod(int cmd) { switch (cmd) { case SELECTCHOICE: select(readShort()); return; case DESELECT: deselect(readShort()); return; case DELITEMS: { int beg = readShort(); int end = readShort(); remove(beg,end); return; } case CLEARLIST: removeAll(); return; case ADDCHOICEITEM: { string s(readUTF()); int i = (short)readShort(); addItem(s,i); return; } case SETMULTIPLE: setMultipleMode(readShort() != 0); return; case MAKEVISIBLE: makeVisible(readShort()); return; } Component::remoteMethod(cmd); } void ListComponent::addItem(const string &s,int i) { if (i < 0) i = txt.size(); if (i < txt.size()) txt[i] = s; else txt.add(s); i -= topline; if (i >= 0 && i < height) repaint(Rect(i,0,i,width)); } void ListComponent::remove(int beg,int end) { while (beg < txt.size() && beg <= end) { txt.deleteln(beg); --end; } } void ListComponent::removeAll() { txt.clear(); selected.clear(); invalidate(); } void ListComponent::select(int i) { long idx = i; if (!selected.contains(idx)) { selected.add(idx); repaint(Rect(i - topline,0,i - topline,width)); } } void ListComponent::deselect(int i) { long idx = i; if (selected.contains(idx)) { selected.del(idx); repaint(Rect(i - topline,0,i - topline,width)); } } void ListComponent::makeVisible(int i) { if (i < topline) { topline = i; invalidate(); return; } if (i - topline >= height) { topline = i - height + 1; invalidate(); return; } } void ListComponent::paint(DrawingContext *dc) { Rect r(dc->clipRect()); for (int i = r.r1; i <= r.r2; ++i) { long row = topline + i; CHTYPE a = textAttr; if (selected.contains(row)) a ^= A_STANDOUT; dc->writeStr(0,i,width,txt[row],a); } } void ListComponent::key(int ky) { switch (ky) { case KEY_ENTER: { toolkit->callMethod(compID,SELECTCHOICE,curline); return; } case KEY_UP: if (curline > 0) { makeVisible(--curline); setCursor(0,curline - topline); } return; case KEY_DOWN: if (curline < txt.size() - 1) { makeVisible(++curline); setCursor(0,curline - topline); } return; } Component::key(ky); } void ListComponent::getfocus() { makeVisible(curline); setCursor(0,curline - topline); Component::getfocus(); }