// // "$Id: Fl_Widget.cxx,v 1.5.2.4.2.15 2002/04/09 17:20:24 easysw Exp $" // // Base widget class for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2002 by Bill Spitzak and others. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library 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 // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // // Please report all bugs and problems to "fltk-bugs@fltk.org". // #include #include #include #include #include //////////////////////////////////////////////////////////////// // for compatability with Forms, all widgets without callbacks are // inserted into a "queue" when they are activated, and the forms // compatability interaction functions (fl_do_events, etc) will // read one widget at a time from this queue and return it: const int QUEUE_SIZE = 20; static Fl_Widget *obj_queue[QUEUE_SIZE]; static int obj_head, obj_tail; void Fl_Widget::default_callback(Fl_Widget *o, void * /*v*/) { #if 0 // This is necessary for strict forms compatability but is confusing. // Use the parent's callback if this widget does not have one. for (Fl_Widget *p = o->parent(); p; p = p->parent()) if (p->callback() != default_callback) { p->do_callback(o,v); return; } #endif obj_queue[obj_head++] = o; if (obj_head >= QUEUE_SIZE) obj_head = 0; if (obj_head == obj_tail) { obj_tail++; if (obj_tail >= QUEUE_SIZE) obj_tail = 0; } } Fl_Widget *Fl::readqueue() { if (obj_tail==obj_head) return 0; Fl_Widget *o = obj_queue[obj_tail++]; if (obj_tail >= QUEUE_SIZE) obj_tail = 0; return o; } //////////////////////////////////////////////////////////////// int Fl_Widget::handle(int event) { if (event == FL_ENTER || event == FL_LEAVE) return 1; else return 0; } int FL_NORMAL_SIZE = 14; Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) { x_ = X; y_ = Y; w_ = W; h_ = H; label_.value = L; label_.image = 0; label_.deimage = 0; label_.type = FL_NORMAL_LABEL; label_.font = FL_HELVETICA; label_.size = FL_NORMAL_SIZE; label_.color = FL_BLACK; tooltip_ = 0; callback_ = default_callback; user_data_ = 0; type_ = 0; flags_ = 0; damage_ = 0; box_ = FL_NO_BOX; color_ = FL_GRAY; color2_ = FL_GRAY; align_ = FL_ALIGN_CENTER; when_ = FL_WHEN_RELEASE; parent_ = 0; if (Fl_Group::current()) Fl_Group::current()->add(this); } void Fl_Widget::resize(int X, int Y, int W, int H) { x_ = X; y_ = Y; w_ = W; h_ = H; } // this is useful for parent widgets to call to resize children: int Fl_Widget::damage_resize(int X, int Y, int W, int H) { if (x() == X && y() == Y && w() == W && h() == H) return 0; resize(X, Y, W, H); redraw(); return 1; } int Fl_Widget::take_focus() { if (!takesevents()) return 0; if (!handle(FL_FOCUS)) return 0; // see if it wants it if (contains(Fl::focus())) return 1; // it called Fl::focus for us Fl::focus(this); return 1; } extern void fl_throw_focus(Fl_Widget*); // in Fl_x.cxx // Destruction does not remove from any parent group! And groups when // destroyed destroy all their children. This is convienent and fast. // However, it is only legal to destroy a "root" such as an Fl_Window, // and automatic destructors may be called. Fl_Widget::~Fl_Widget() { parent_ = 0; // Don't throw focus to a parent widget. fl_throw_focus(this); } // draw a focus box for the widget... void Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const { if (!Fl::visible_focus()) return; switch (B) { case FL_DOWN_BOX: case FL_DOWN_FRAME: case FL_THIN_DOWN_BOX: case FL_THIN_DOWN_FRAME: X ++; Y ++; default: break; } fl_color(fl_contrast(FL_BLACK, color())); #if defined(WIN32) || defined(__APPLE__) // Windows 95/98/ME do not implement the dotted line style, so draw // every other pixel around the focus area... // // Also, QuickDraw (MacOS) does not support line styles specifically, // and the hack we use in fl_line_style() will not draw horizontal lines // on odd-numbered rows... int i, xx, yy; X += Fl::box_dx(B); Y += Fl::box_dy(B); W -= Fl::box_dw(B) + 2; H -= Fl::box_dh(B) + 2; for (xx = 0, i = 1; xx < W; xx ++, i ++) if (i & 1) fl_point(X + xx, Y); for (yy = 0; yy < H; yy ++, i ++) if (i & 1) fl_point(X + W, Y + yy); for (xx = W; xx > 0; xx --, i ++) if (i & 1) fl_point(X + xx, Y + H); for (yy = H; yy > 0; yy --, i ++) if (i & 1) fl_point(X, Y + yy); #else fl_line_style(FL_DOT); fl_rect(X + Fl::box_dx(B), Y + Fl::box_dy(B), W - Fl::box_dw(B) - 1, H - Fl::box_dh(B) - 1); fl_line_style(FL_SOLID); #endif // WIN32 } // redraw this, plus redraw opaque object if there is an outside label static void redraw_label(Fl_Widget* w) { w->redraw(); if (w->label() && (w->align()&15) && !(w->align() & FL_ALIGN_INSIDE)) { for (Fl_Widget *p = w->parent(); p; p = p->parent()) if (p->box() || !p->parent()) {p->redraw(); break;} } } void Fl_Widget::activate() { if (!active()) { clear_flag(INACTIVE); if (active_r()) { redraw_label(this); handle(FL_ACTIVATE); if (inside(Fl::focus())) Fl::focus()->take_focus(); } } } void Fl_Widget::deactivate() { if (active_r()) { set_flag(INACTIVE); redraw_label(this); handle(FL_DEACTIVATE); fl_throw_focus(this); } else { set_flag(INACTIVE); } } int Fl_Widget::active_r() const { for (const Fl_Widget* o = this; o; o = o->parent()) if (!o->active()) return 0; return 1; } void Fl_Widget::show() { if (!visible()) { clear_flag(INVISIBLE); if (visible_r()) { redraw_label(this); handle(FL_SHOW); if (inside(Fl::focus())) Fl::focus()->take_focus(); } } } void Fl_Widget::hide() { if (visible_r()) { set_flag(INVISIBLE); for (Fl_Widget *p = parent(); p; p = p->parent()) if (p->box() || !p->parent()) {p->redraw(); break;} handle(FL_HIDE); fl_throw_focus(this); } else { set_flag(INVISIBLE); } } int Fl_Widget::visible_r() const { for (const Fl_Widget* o = this; o; o = o->parent()) if (!o->visible()) return 0; return 1; } // return true if widget is inside (or equal to) this: // Returns false for null widgets. int Fl_Widget::contains(const Fl_Widget *o) const { for (; o; o = o->parent_) if (o == this) return 1; return 0; } // // End of "$Id: Fl_Widget.cxx,v 1.5.2.4.2.15 2002/04/09 17:20:24 easysw Exp $". //