fltk/src/Fl_Widget.cxx
Michael R Sweet a3d0905c9e Copyright updates and prep for 1.1.5rc1.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@3391 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
2004-04-11 04:39:01 +00:00

250 lines
6.7 KiB
C++

//
// "$Id: Fl_Widget.cxx,v 1.5.2.4.2.23 2004/04/11 04:38:58 easysw Exp $"
//
// Base widget class for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2004 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 <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Tooltip.H>
#include <FL/fl_draw.H>
////////////////////////////////////////////////////////////////
// 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) {
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 = (uchar)FL_NORMAL_SIZE;
label_.color = FL_BLACK;
tooltip_ = 0;
callback_ = default_callback;
user_data_ = 0;
type_ = 0;
flags_ = VISIBLE_FOCUS;
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 (!visible_focus()) 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
}
void Fl_Widget::activate() {
if (!active()) {
clear_flag(INACTIVE);
if (active_r()) {
redraw();
redraw_label();
handle(FL_ACTIVATE);
if (inside(Fl::focus())) Fl::focus()->take_focus();
}
}
}
void Fl_Widget::deactivate() {
if (active_r()) {
set_flag(INACTIVE);
redraw();
redraw_label();
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();
redraw_label();
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.23 2004/04/11 04:38:58 easysw Exp $".
//