⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fl_menu.cxx

📁 PIXIL is a small footprint operating environment, complete with PDA PIM applications, a browser and
💻 CXX
📖 第 1 页 / 共 2 页
字号:
    if (!itemheight) {		// menubar	int x = 3;	int i = 0;	const Fl_Menu_Item *m = menu;	for (;; m = m->next(), i++) {	    if (!m->text)		return -1;	    x += m->measure(0, button) + 16;	    if (x > mx)		break;	}	return i;    }    if (mx < Fl::box_dx(box()) || mx >= w())	return -1;    int i = (my - Fl::box_dx(box()) - 1) / itemheight;    if (i < 0 || i >= numitems)	return -1;    return i;}// return horizontal position for item i in a menubar:intmenuwindow::titlex(int i){    const Fl_Menu_Item *m;    int x = 3;    for (m = menu; i--; m = m->next())	x += m->measure(0, button) + 16;    return x;}// match shortcuts & label shortcuts, don't search submenus:// returns menu item and indexconst Fl_Menu_Item *Fl_Menu_Item::find_shortcut(int *ip) const{    const Fl_Menu_Item *m1 = this;    for (int ii = 0; m1 && m1->text; m1 = m1->next(1), ii++) {	if (m1->activevisible() && (Fl::test_shortcut(m1->shortcut_)				    || Fl_Widget::test_shortcut(m1->text))) {	    if (ip)		*ip = ii;	    return m1;	}    }    return 0;}////////////////////////////////////////////////////////////////// Fl_Menu_Item::popup(...)// Because Fl::grab() is done, all events go to one of the menu windows.// But the handle method needs to look at all of them to find out// what item the user is pointing at.  And it needs a whole lot// of other state variables to determine what is going on with// the currently displayed menus.// So the main loop (handlemenu()) puts all the state in a structure// and puts a pointer to it in a static location, so the handle()// on menus can refer to it and alter it.  The handle() method// changes variables in this state to indicate what item is// picked, but does not actually alter the display, instead the// main loop does that.  This is because the X mapping and unmapping// of windows is slow, and we don't want to fall behind the events.// values for menustate.state:#define INITIAL_STATE 0		// no mouse up or down since popup() called#define PUSH_STATE 1		// mouse has been pushed on a normal item#define DONE_STATE 2		// exit the popup, the current item was picked#define MENU_PUSH_STATE 3	// mouse has been pushed on a menu titlestruct menustate{    const Fl_Menu_Item *current_item;	// what mouse is pointing at    int menu_number;		// which menu it is in    int item_number;		// which item in that menu, -1 if none    menuwindow *p[20];		// pointers to menus    int nummenus;    int menubar;		// if true p[0] is a menubar    int state;};static menustate *p;static inline voidsetitem(const Fl_Menu_Item * i, int m, int n){    p->current_item = i;    p->menu_number = m;    p->item_number = n;}static voidsetitem(int m, int n){    menustate & p = *(::p);    p.current_item = (n >= 0) ? p.p[m]->menu->next(n) : 0;    p.menu_number = m;    p.item_number = n;}static intforward(int menu){				// go to next item in menu menu if possible    menustate & p = *(::p);    menuwindow & m = *(p.p[menu]);    int item = (menu == p.menu_number) ? p.item_number : m.selected;    while (++item < m.numitems) {	const Fl_Menu_Item *m1 = m.menu->next(item);	if (m1->activevisible()) {	    setitem(m1, menu, item);	    return 1;	}    }    return 0;}static intbackward(int menu){				// previous item in menu menu if possible    menustate & p = *(::p);    menuwindow & m = *(p.p[menu]);    int item = (menu == p.menu_number) ? p.item_number : m.selected;    if (item < 0)	item = m.numitems;    while (--item >= 0) {	const Fl_Menu_Item *m1 = m.menu->next(item);	if (m1->activevisible()) {	    setitem(m1, menu, item);	    return 1;	}    }    return 0;}intmenuwindow::handle(int e){    menustate & p = *(::p);    switch (e) {    case FL_KEYBOARD:	switch (Fl::event_key()) {	case FL_Tab:	    if (Fl::event_shift() & FL_SHIFT)		goto BACKTAB;	case ' ':	    if (!forward(p.menu_number)) {		p.item_number = -1;		forward(p.menu_number);	    }	    return 1;	case FL_BackSpace:	case 0xFE20:		// backtab	  BACKTAB:	    if (!backward(p.menu_number)) {		p.item_number = -1;		backward(p.menu_number);	    }	    return 1;	case FL_Up:	    if (p.menubar && p.menu_number == 0);	    else if (backward(p.menu_number));	    else if (p.menubar && p.menu_number == 1)		setitem(0, p.p[0]->selected);	    return 1;	case FL_Down:	    if (p.menu_number || !p.menubar)		forward(p.menu_number);	    else if (p.menu_number < p.nummenus - 1)		forward(p.menu_number + 1);	    return 1;	case FL_Right:	    if (p.menubar		&& (p.menu_number <= 0 || p.menu_number == 1		    && p.nummenus == 2))		forward(0);	    else if (p.menu_number < p.nummenus - 1)		forward(p.menu_number + 1);	    return 1;	case FL_Left:	    if (p.menubar && p.menu_number <= 1)		backward(0);	    else if (p.menu_number > 0)		setitem(p.menu_number - 1, p.p[p.menu_number - 1]->selected);	    return 1;	case FL_Enter:	    p.state = DONE_STATE;	    return 1;	case FL_Escape:	    setitem(0, -1, 0);	    p.state = DONE_STATE;	    return 1;	}	break;    case FL_SHORTCUT:{	    for (int menu = p.nummenus; menu--;) {		menuwindow & mw = *(p.p[menu]);		int item;		const Fl_Menu_Item *m = mw.menu->find_shortcut(&item);		if (m) {		    setitem(m, menu, item);		    if (!m->submenu())			p.state = DONE_STATE;		    return 1;		}	    }	}	break;    case FL_PUSH:	//case FL_MOVE:    case FL_DRAG:{	    int mx = Fl::event_x() + x();	    int my = Fl::event_y() + y();	    int item = 0;	    int menu;	    for (menu = p.nummenus - 1;; menu--) {		item = p.p[menu]->find_selected(mx, my);		if (item >= 0)		    break;		if (menu <= 0)		    break;	    }	    setitem(menu, item);	    if (e == FL_PUSH) {		if (p.current_item && p.current_item->submenu()	// this is a menu title		    && item != p.p[menu]->selected	// and it is not already on		    && !p.current_item->callback_)	// and it does not have a callback		    p.state = MENU_PUSH_STATE;		else		    p.state = PUSH_STATE;	    }	}	return 1;    case FL_RELEASE:	// do nothing if they try to pick inactive items	if (p.current_item && !p.current_item->activevisible())	    return 1;	// Mouse must either be held down/dragged some, or this must be	// the second click (not the one that popped up the menu):	if (!Fl::event_is_click() || p.state == PUSH_STATE || p.menubar && p.current_item && !p.current_item->submenu()	// button	    ) {#if 0				// makes the check/radio items leave the menu up	    const Fl_Menu_Item *m = p.current_item;	    if (m && button && (m->flags & (FL_MENU_TOGGLE | FL_MENU_RADIO))) {		((Fl_Menu_ *) button)->picked(m);		p.p[p.menu_number]->redraw();	    } else#endif		p.state = DONE_STATE;	}	return 1;    }    return Fl_Window::handle(e);}const Fl_Menu_Item *Fl_Menu_Item::pulldown(int X, int Y, int W, int H,		       const Fl_Menu_Item * initial_item,		       const Fl_Menu_ * pbutton,		       const Fl_Menu_Item * t, int menubar) const{    Fl_Group::current(0);	// fix possible user error...    button = pbutton;    if (pbutton) {	for (Fl_Window * w = pbutton->window(); w; w = w->window()) {	    X += w->x();	    Y += w->y();	}    } else {	X += Fl::event_x_root() - Fl::event_x();	Y += Fl::event_y_root() - Fl::event_y();    }    menuwindow mw(this, X, Y, W, H, initial_item, t, menubar);    Fl::grab(mw);    menustate p;    ::p = &p;    p.p[0] = &mw;    p.nummenus = 1;    p.menubar = menubar;    p.state = INITIAL_STATE;    menuwindow *fakemenu = 0;	// kludge for buttons in menubar    // preselected item, pop up submenus if necessary:    if (initial_item && mw.selected >= 0) {	setitem(0, mw.selected);	goto STARTUP;    }    p.current_item = 0;    p.menu_number = 0;    p.item_number = -1;    if (menubar)	mw.handle(FL_DRAG);	// find the initial menu    initial_item = p.current_item;    if (initial_item)	goto STARTUP;    // the main loop, runs until p.state goes to DONE_STATE:    for (;;) {	// make sure all the menus are shown:	{	    for (int k = menubar; k < p.nummenus; k++)		if (!p.p[k]->shown()) {		    if (p.p[k]->title)			p.p[k]->title->show();		    p.p[k]->show();		}	}	// get events:	{	    const Fl_Menu_Item *oldi = p.current_item;	    Fl::wait();	    if (p.state == DONE_STATE)		break;		// done.	    if (p.current_item == oldi)		continue;	}	// only do rest if item changes:	delete fakemenu;	fakemenu = 0;		// turn off "menubar button"	if (!p.current_item) {	// pointing at nothing	    // turn off selection in deepest menu, but don't erase other menus:	    p.p[p.nummenus - 1]->set_selected(-1);	    continue;	}	delete fakemenu;	fakemenu = 0;	initial_item = 0;	// stop the startup code	p.p[p.menu_number]->autoscroll(p.item_number);      STARTUP:	menuwindow & cw = *p.p[p.menu_number];	const Fl_Menu_Item *m = p.current_item;	if (!m->activevisible()) {	// pointing at inactive item	    cw.set_selected(-1);	    initial_item = 0;	// turn off startup code	    continue;	}	cw.set_selected(p.item_number);	if (m == initial_item)	    initial_item = 0;	// stop the startup code if item found	if (m->submenu()) {	    const Fl_Menu_Item *title = m;	    const Fl_Menu_Item *menutable;	    if (m->flags & FL_SUBMENU)		menutable = m + 1;	    else		menutable = (Fl_Menu_Item *) (m)->user_data_;	    // figure out where new menu goes:	    int nX, nY;	    if (!p.menu_number && p.menubar) {	// menu off a menubar:		nX = cw.x() + cw.titlex(p.item_number);		nY = cw.y() + cw.h();		initial_item = 0;	    } else {		nX = cw.x() + cw.w();		nY = cw.y() + 1 + p.item_number * cw.itemheight;		title = 0;	    }	    if (initial_item) {	// bring up submenu containing initial item:		menuwindow *n =		    new menuwindow(menutable, X, Y, W, H, initial_item,				   title);		p.p[p.nummenus++] = n;		// move all earlier menus to line up with this new one:		if (n->selected >= 0) {		    int dy = n->y() - nY;		    int dx = n->x() - nX;		    for (int menu = 0; menu <= p.menu_number; menu++) {			menuwindow *t = p.p[menu];			int nx = t->x() + dx;			if (nx < 0) {			    nx = 0;			    dx = -t->x();			}			int ny = t->y() + dy + 1;			if (ny < 0) {			    ny = 0;			    dy = -t->y() - 1;			}			t->position(nx, ny);		    }		    setitem(p.nummenus - 1, n->selected);		    goto STARTUP;		}	    } else if (p.nummenus > p.menu_number + 1 &&		       p.p[p.menu_number + 1]->menu == menutable) {		// the menu is already up:		while (p.nummenus > p.menu_number + 2)		    delete p.p[--p.nummenus];		p.p[p.nummenus - 1]->set_selected(-1);	    } else {		// delete all the old menus and create new one:		while (p.nummenus > p.menu_number + 1)		    delete p.p[--p.nummenus];		p.p[p.nummenus++] = new menuwindow(menutable, nX, nY,						   title ? 1 : 0, 0, 0, title,						   0, menubar);	    }	} else {		// !m->submenu():	    while (p.nummenus > p.menu_number + 1)		delete p.p[--p.nummenus];	    if (!p.menu_number && p.menubar) {		// kludge so "menubar buttons" turn "on" by using menu title:		fakemenu = new menuwindow(0,					  cw.x() + cw.titlex(p.item_number),					  cw.y() + cw.h(), 0, 0, 0, m, 0, 1);		fakemenu->title->show();	    }	}    }    const Fl_Menu_Item *m = p.current_item;    delete fakemenu;    while (p.nummenus > 1)	delete p.p[--p.nummenus];    mw.hide();    Fl::release();    return m;}const Fl_Menu_Item *Fl_Menu_Item::popup(int X, int Y,		    const char *title,		    const Fl_Menu_Item * picked,		    const Fl_Menu_ * button) const{    static Fl_Menu_Item dummy;	// static so it is all zeros    dummy.text = title;    return pulldown(X, Y, 0, 0, picked, button, title ? &dummy : 0);}const Fl_Menu_Item *Fl_Menu_Item::test_shortcut() const{    const Fl_Menu_Item *m = this;    const Fl_Menu_Item *ret = 0;    if (m)	for (; m->text; m = m->next()) {	    if (m->activevisible()) {		// return immediately any match of an item in top level menu:		if (Fl::test_shortcut(m->shortcut_))		    return m;		// if (Fl_Widget::test_shortcut(m->text)) return m;		// only return matches from lower menu if nothing found in top menu:		if (!ret && m->submenu()) {		    const Fl_Menu_Item *s =			(m->flags & FL_SUBMENU) ? m +			1 : (const Fl_Menu_Item *) m->user_data_;		    ret = s->test_shortcut();		}	    }	}    return ret;}//// End of "$Id: Fl_Menu.cxx,v 1.1.1.1 2003/08/07 21:18:40 jasonk Exp $".//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -