📄 fl_group.cxx
字号:
//
// "$Id: Fl_Group.cxx,v 1.1.1.1 2003/06/03 22:25:42 agno Exp $"
//
// Group widget for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2003 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".
//
// The Fl_Group is the only defined container type in FLTK.
// Fl_Window itself is a subclass of this, and most of the event
// handling is designed so windows themselves work correctly.
#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>
#include <stdlib.h>
Fl_Group* Fl_Group::current_;
// Hack: A single child is stored in the pointer to the array, while
// multiple children are stored in an allocated array:
Fl_Widget*const* Fl_Group::array() const {
return children_ <= 1 ? (Fl_Widget**)(&array_) : array_;
}
int Fl_Group::find(const Fl_Widget* o) const {
Fl_Widget*const* a = array();
int i; for (i=0; i < children_; i++) if (*a++ == o) break;
return i;
}
// Metrowerks CodeWarrior and others can't export the static
// class member: current_, so these methods can't be inlined...
void Fl_Group::begin() {current_ = this;}
void Fl_Group::end() {current_ = (Fl_Group*)parent();}
Fl_Group *Fl_Group::current() {return current_;}
void Fl_Group::current(Fl_Group *g) {current_ = g;}
extern Fl_Widget* fl_oldfocus; // set by Fl::focus
// For back-compatability, we must adjust all events sent to child
// windows so they are relative to that window.
static int send(Fl_Widget* o, int event) {
if (o->type() < FL_WINDOW) return o->handle(event);
switch ( event )
{
case FL_DND_ENTER:
case FL_DND_DRAG:
// figure out correct type of event:
event = (o->contains(Fl::belowmouse())) ? FL_DND_DRAG : FL_DND_ENTER;
}
int save_x = Fl::e_x; Fl::e_x -= o->x();
int save_y = Fl::e_y; Fl::e_y -= o->y();
int ret = o->handle(event);
Fl::e_y = save_y;
Fl::e_x = save_x;
switch ( event )
{
case FL_ENTER:
case FL_DND_ENTER:
// Successful completion of FL_ENTER means the widget is now the
// belowmouse widget, but only call Fl::belowmouse if the child
// widget did not do so:
if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
break;
}
return ret;
}
// translate the current keystroke into up/down/left/right for navigation:
#define ctrl(x) (x^0x40)
static int navkey() {
switch (Fl::event_key()) {
case 0: // not an FL_KEYBOARD/FL_SHORTCUT event
break;
case FL_Tab:
if (!Fl::event_state(FL_SHIFT)) return FL_Right;
case 0xfe20: // XK_ISO_Left_Tab
return FL_Left;
case FL_Right:
return FL_Right;
case FL_Left:
return FL_Left;
case FL_Up:
return FL_Up;
case FL_Down:
return FL_Down;
default:
switch (Fl::event_text()[0]) {
case ctrl('N') : return FL_Down;
case ctrl('P') : return FL_Up;
case ctrl('F') : return FL_Right;
case ctrl('B') : return FL_Left;
}
}
return 0;
}
int Fl_Group::handle(int event) {
Fl_Widget*const* a = array();
int i;
Fl_Widget* o;
switch (event) {
case FL_FOCUS:
switch (navkey()) {
default:
if (savedfocus_ && savedfocus_->take_focus()) return 1;
case FL_Right:
case FL_Down:
for (i = children(); i--;) if ((*a++)->take_focus()) return 1;
break;
case FL_Left:
case FL_Up:
for (i = children(); i--;) if (a[i]->take_focus()) return 1;
break;
}
return 0;
case FL_UNFOCUS:
savedfocus_ = fl_oldfocus;
return 0;
case FL_KEYBOARD:
return navigation(navkey());
case FL_SHORTCUT:
for (i = children(); i--;) {
o = a[i];
if (o->takesevents() && Fl::event_inside(o) && send(o,FL_SHORTCUT))
return 1;
}
for (i = children(); i--;) {
o = a[i];
if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_SHORTCUT))
return 1;
}
if (Fl::event_key() == FL_Enter) return navigation(FL_Down);
return 0;
case FL_ENTER:
case FL_MOVE:
for (i = children(); i--;) {
o = a[i];
if (o->visible() && Fl::event_inside(o)) {
if (o->contains(Fl::belowmouse())) {
return send(o,FL_MOVE);
} else {
if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
if (send(o,FL_ENTER)) return 1;
}
}
}
Fl::belowmouse(this);
return 1;
case FL_DND_ENTER:
case FL_DND_DRAG:
for (i = children(); i--;) {
o = a[i];
if (o->takesevents() && Fl::event_inside(o)) {
if (o->contains(Fl::belowmouse())) {
return send(o,FL_DND_DRAG);
} else if (send(o,FL_DND_ENTER)) {
if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
return 1;
}
}
}
Fl::belowmouse(this);
return 0;
case FL_PUSH:
for (i = children(); i--;) {
o = a[i];
if (o->takesevents() && Fl::event_inside(o)) {
if (send(o,FL_PUSH)) {
if (Fl::pushed() && !o->contains(Fl::pushed())) Fl::pushed(o);
return 1;
}
}
}
return 0;
case FL_RELEASE:
case FL_DRAG:
o = Fl::pushed();
if (o == this) return 0;
else if (o) send(o,event);
else {
for (i = children(); i--;) {
o = a[i];
if (o->takesevents() && Fl::event_inside(o)) {
if (send(o,event)) return 1;
}
}
}
return 0;
case FL_DEACTIVATE:
case FL_ACTIVATE:
for (i = children(); i--;) {
o = *a++;
if (o->active()) o->handle(event);
}
return 1;
case FL_SHOW:
case FL_HIDE:
for (i = children(); i--;) {
o = *a++;
if (o->visible()) o->handle(event);
}
return 1;
default:
// For all other events, try to give to each child, starting at focus:
for (i = 0; i < children(); i ++)
if (Fl::focus_ == a[i]) break;
if (i >= children()) i = 0;
if (children()) {
for (int j = i;;) {
if (a[j]->takesevents() || event != FL_MOUSEWHEEL) {
if (send(a[j], event)) return 1;
}
j++;
if (j >= children()) j = 0;
if (j == i) break;
}
}
return 0;
}
}
//void Fl_Group::focus(Fl_Widget *o) {Fl::focus(o); o->handle(FL_FOCUS);}
#if 0
const char *nameof(Fl_Widget *o) {
if (!o) return "NULL";
if (!o->label()) return "<no label>";
return o->label();
}
#endif
// try to move the focus in response to a keystroke:
int Fl_Group::navigation(int key) {
if (children() <= 1) return 0;
int i;
for (i = 0; ; i++) {
if (i >= children_) return 0;
if (array_[i]->contains(Fl::focus())) break;
}
Fl_Widget *previous = array_[i];
for (;;) {
switch (key) {
case FL_Right:
case FL_Down:
i++;
if (i >= children_) {
if (parent()) return 0;
i = 0;
}
break;
case FL_Left:
case FL_Up:
if (i) i--;
else {
if (parent()) return 0;
i = children_-1;
}
break;
default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -