1
// ----------------------------------------------------------------------------
6
// This is free software; you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation; either version 3 of the License, or
9
// (at your option) any later version.
11
// This software is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
// ----------------------------------------------------------------------------
25
#include <FL/fl_draw.H>
30
void popbrwsr_cb (Fl_Widget *v, long d);
32
Fl_PopBrowser::Fl_PopBrowser (int X, int Y, int W, int H, const char *label)
33
: Fl_Window (X, Y, W, H, label)
39
align(FL_ALIGN_INSIDE);
41
popbrwsr = new Fl_Select_Browser(0,0,wRow,hRow, "");
42
popbrwsr->callback ( (Fl_Callback*)popbrwsr_cb);
43
popbrwsr->align(FL_ALIGN_INSIDE);
49
Fl_PopBrowser::~Fl_PopBrowser ()
54
int Fl_PopBrowser::handle(int event)
56
Fl_ComboBox *cbx = (Fl_ComboBox*)this->parent();
57
if (!Fl::event_inside( child(0) ) && event == FL_PUSH) {
61
if (event == FL_KEYDOWN) {
62
int kbd = Fl::event_key();
63
char key = Fl::event_text()[0];
65
if (popbrwsr->value() < popbrwsr->size())
66
popbrwsr->select(popbrwsr->value() + 1);
67
popbrwsr->bottomline(popbrwsr->value());
70
if (kbd == FL_Up && popbrwsr->value() > 1) {
71
popbrwsr->select(popbrwsr->value() - 1);
74
if (key == '\r' || kbd == FL_Enter) { // kbd test for OS X
75
int n = popbrwsr->value() - 1;
81
if (key == '\b' || kbd == FL_BackSpace) { // kbd test for OS X
82
if (!keystrokes.empty())
83
keystrokes.erase(keystrokes.length() - 1, 1);
86
if (key == 0x1b || kbd == FL_Escape) { // kbd test for OS X
90
if (key >= ' ' || key <= 0x7f) {
92
for (int i = 0; i < cbx->listsize; i++) {
93
if (strncasecmp(keystrokes.c_str(),
95
keystrokes.length()) == 0) {
96
popbrwsr->select(i+1);
104
return Fl_Group::handle(event);
107
void Fl_PopBrowser::add(char *s, void *d)
112
void Fl_PopBrowser::clear()
117
void Fl_PopBrowser::sort()
122
void Fl_PopBrowser::popshow (int x, int y)
124
int nRows = parentCB->numrows();
125
int fh = fl_height();
126
int height = nRows * fh + 4;
128
if (popbrwsr->size() == 0) return;
129
if (nRows > parentCB->lsize()) nRows = parentCB->lsize();
131
// locate first occurance of inp string value in the list
132
// and display that if found
133
int i = parentCB->index();
134
if (!(i >= 0 && i < parentCB->listsize)) {
135
for (i = 0; i < parentCB->listsize; i++)
136
if (parentCB->type_ == COMBOBOX) {
137
if (!strcmp(parentCB->val->value(), parentCB->datalist[i]->s))
140
if (!strcmp(parentCB->valbox->label(), parentCB->datalist[i]->s))
143
if (i == parentCB->listsize)
147
// resize and reposition the popup to insure that it is within the bounds
148
// of the uppermost parent widget
149
// preferred position is just below and at the same x position as the
152
Fl_Widget *gparent = parentCB;
153
int hp = gparent->h();
155
while ((gparent = gparent->parent())) {
157
parentWindow = gparent;
160
int nu = nRows, nl = nRows;
161
int hu = nu * fh + 4, hl = nl * fh + 4;
162
int yu = parentCB->y() - hu;
165
while (nl > 1 && (yl + hl > hp)) { nl--; hl -= fh; }
166
while (nu > 1 && yu < 0) { nu--; yu += fh; hu -= fh; }
174
popbrwsr->size (wRow, height);
175
resize (x, y, wRow, height);
177
popbrwsr->topline (i);
182
for (const Fl_Widget* o = popbrwsr; o; o = o->parent())
183
((Fl_Widget *)o)->set_visible();
185
parentWindow->damage(FL_DAMAGE_ALL);
186
parentWindow->redraw();
191
void Fl_PopBrowser::pophide ()
195
parentWindow->damage(FL_DAMAGE_ALL);
196
parentWindow->redraw();
199
Fl::focus(((Fl_ComboBox*)parent())->btn);
202
void Fl_PopBrowser::popbrwsr_cb_i (Fl_Widget *v, long d)
204
// update the return values
205
Fl_Select_Browser *SB = (Fl_Select_Browser *)(v);
206
Fl_PopBrowser *PB = (Fl_PopBrowser *)(SB->parent());
207
Fl_ComboBox *CB = (Fl_ComboBox *)(PB->parent());
209
int row = SB->value();
211
if (row == 0) return;
214
CB->value(SB->text(row));
224
void popbrwsr_cb (Fl_Widget *v, long d)
226
((Fl_PopBrowser *)(v))->popbrwsr_cb_i (v, d);
231
void Fl_ComboBox::fl_popbrwsr(Fl_Widget *p)
233
int xpos = p->x(), ypos = p->h() + p->y();
234
// pass the calling widget to the popup browser so that the
235
// correct callback function can be called when the user selects an item
236
// from the browser list
237
Brwsr->parentCB = (Fl_ComboBox *) p;
239
Brwsr->popshow(xpos, ypos);
243
void btnComboBox_cb (Fl_Widget *v, void *d)
245
Fl_ComboBox *p = (Fl_ComboBox *)(v->parent());
250
Fl_ComboBox::Fl_ComboBox (int X,int Y,int W,int H, const char *lbl, int wtype)
251
: Fl_Group (X, Y, W, H, lbl),
254
width = W; height = H;
256
if (type_ == LISTBOX) {
257
valbox = new Fl_Box (FL_DOWN_BOX, X, Y, W-H, H, "");
258
valbox->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
259
valbox->color(FL_BACKGROUND2_COLOR);
261
val = new Fl_Input (X, Y, W-H, H, "");
262
val->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
266
btn = new Fl_Button (X + W - H + 1, Y, H - 1, H, "@2>");
267
btn->callback ((Fl_Callback *)btnComboBox_cb, 0);
270
datalist = new datambr *[FL_COMBO_LIST_INCR];
271
maxsize = FL_COMBO_LIST_INCR;
272
for (int i = 0; i < FL_COMBO_LIST_INCR; i++) datalist[i] = 0;
276
Brwsr = new Fl_PopBrowser(X, Y, W, H, "");
277
Brwsr->align(FL_ALIGN_INSIDE);
286
Fl_ComboBox::~Fl_ComboBox()
289
for (int i = 0; i < listsize; i++) {
291
if (datalist[i]->s) delete [] datalist[i]->s;
298
int Fl_ComboBox::handle(int event)
300
if (event == FL_KEYDOWN) {
301
int kbd = Fl::event_key();
302
if (kbd == FL_Down) {
307
return Fl_Group::handle(event);
310
void Fl_ComboBox::type (int t)
315
void Fl_ComboBox::readonly(bool yes)
317
if (type_ == LISTBOX) return;
320
val->selection_color(fl_rgb_color(173,216,230));
322
val->selection_color(FL_SELECTION_COLOR);
325
// ComboBox value is contained in the val widget
327
const char *Fl_ComboBox::value()
329
if (type_ == LISTBOX)
330
return valbox->label();
335
void Fl_ComboBox::value( const char *s )
338
if ((listtype & FL_COMBO_UNIQUE_NOCASE) == FL_COMBO_UNIQUE_NOCASE) {
339
for (i = 0; i < listsize; i++) {
340
if (strcasecmp (s, datalist[i]->s) == 0)
344
for (i = 0; i < listsize; i++) {
345
if (strcmp (s, datalist[i]->s) == 0)
351
if (type_ == LISTBOX) {
352
valbox->label(datalist[idx]->s);
353
valbox->redraw_label();
355
val->value(datalist[idx]->s);
359
void Fl_ComboBox::put_value(const char *s)
364
void Fl_ComboBox::index(int i)
366
if (i >= 0 && i < listsize) {
368
if (type_ == LISTBOX) {
369
valbox->label(datalist[idx]->s);
370
valbox->redraw_label();
372
val->value( datalist[idx]->s);
376
int Fl_ComboBox::index() {
380
void * Fl_ComboBox::data() {
384
void Fl_ComboBox::insert(const char *str, void *d)
386
datalist[listsize] = new datambr;
387
datalist[listsize]->s = new char [strlen(str) + 1];
388
datalist[listsize]->s[0] = 0;
389
strcpy (datalist[listsize]->s, str);
390
datalist[listsize]->d = 0;
391
Brwsr->add(datalist[listsize]->s,d);
393
if (listsize == maxsize) {
394
int nusize = maxsize + FL_COMBO_LIST_INCR;
395
datambr **temparray = new datambr *[nusize];
396
for (int i = 0; i < listsize; i++)
397
temparray[i] = datalist[i];
399
datalist = temparray;
404
void Fl_ComboBox::add( const char *s, void * d)
408
size_t p = str.find("|");
410
if (p != std::string::npos) {
411
while (p != std::string::npos) {
412
sinsert = str.substr(0, p);
415
if ((listtype & FL_COMBO_UNIQUE_NOCASE) == FL_COMBO_UNIQUE_NOCASE) {
416
for (int i = 0; i < listsize; i++) {
417
if (sinsert == datalist[i]->s) {
423
// not in list, so add this entry
424
if (!found) insert(sinsert.c_str(), 0);
429
insert(str.c_str(), 0);
434
void Fl_ComboBox::clear()
438
if (listsize == 0) return;
439
for (int i = 0; i < listsize; i++) {
440
delete [] datalist[i]->s;
446
int DataCompare( const void *x1, const void *x2 )
450
X1 = *(datambr **)(x1);
451
X2 = *(datambr **)(x2);
452
cmp = strcasecmp (X1->s, X2->s);
460
void Fl_ComboBox::sort() {
466
for (int i = 0; i < listsize; i++)
467
Brwsr->add (datalist[i]->s, datalist[i]->d);
470
void Fl_ComboBox::textfont (int fnt)
472
if (type_ == LISTBOX)
473
valbox->labelfont (fnt);
478
void Fl_ComboBox::textsize (uchar n)
480
if (type_ == LISTBOX)
481
valbox->labelsize(n);
486
void Fl_ComboBox::textcolor( Fl_Color c)
488
if (type_ == LISTBOX)
489
valbox->labelcolor (c);
494
void Fl_ComboBox::color(Fl_Color c)
497
if (type_ == LISTBOX)
501
if (Brwsr) Brwsr->color(c);