📄 fl_menu.cxx
字号:
//// "$Id: Fl_Menu.cxx,v 1.1.1.1 2003/08/07 21:18:40 jasonk Exp $"//// Menu code for the Fast Light Tool Kit (FLTK).//// Copyright 1998-1999 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@easysw.com".//// Warning: this menu code is quite a mess!// This file contains code for implementing Fl_Menu_Item, and for// methods for bringing up popup menu hierarchies without using the// Fl_Menu_ widget.#include <FL/Fl.H>#include <FL/Fl_Menu_Window.H>#include <FL/Fl_Menu_.H>#include <stdio.h>#include <FL/fl_draw.H>intFl_Menu_Item::size() const{ const Fl_Menu_Item *m = this; int nest = 0; for (;;) { if (!m->text) { if (!nest) return (m - this + 1); nest--; } else if (m->flags & FL_SUBMENU) { nest++; } m++; }}const Fl_Menu_Item *Fl_Menu_Item::next(int n) const{ if (n < 0) return 0; // this is so selected==-1 returns NULL const Fl_Menu_Item *m = this; int nest = 0; while (n > 0) { if (!m->text) { if (!nest) return m; nest--; } else if (m->flags & FL_SUBMENU) { nest++; } m++; if (!nest && m->visible()) n--; } return m;}// appearance of current menus are pulled from this parent widget:static const Fl_Menu_ *button;////////////////////////////////////////////////////////////////// tiny window for title of menu:class menutitle:public Fl_Menu_Window{ void draw(); public: const Fl_Menu_Item *menu; menutitle(int X, int Y, int W, int H, const Fl_Menu_Item *);};// each vertical menu has one of these:class menuwindow:public Fl_Menu_Window{ void draw(); void drawentry(const Fl_Menu_Item *, int i, int erase); public: menutitle * title; int handle(int); int itemheight; // zero == menubar int numitems; int selected; int drawn_selected; // last redraw has this selected const Fl_Menu_Item *menu; menuwindow(const Fl_Menu_Item * m, int X, int Y, int W, int H, const Fl_Menu_Item * picked, const Fl_Menu_Item * title, int menubar = 0, int menubar_title = 0); ~menuwindow(); void set_selected(int); int find_selected(int mx, int my); int titlex(int); void autoscroll(int); void position(int x, int y);};#define LEADING 4 // extra vertical leadingextern char fl_draw_shortcut;// width of label, including effect of & characters:intFl_Menu_Item::measure(int *hp, const Fl_Menu_ * m) const{ Fl_Label l; l.value = text; l.type = labeltype_; l.font = labelsize_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA); l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE; l.color = labelcolor_; fl_draw_shortcut = 1; int w = 0; int h = 0; l.measure(w, hp ? *hp : h); fl_draw_shortcut = 0; if (flags & (FL_MENU_TOGGLE | FL_MENU_RADIO)) w += 14; return w;}voidFl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_ * m, int selected) const{ Fl_Label l; l.value = text; l.type = labeltype_; l.font = labelsize_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA); l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE; l.color = labelcolor_ ? labelcolor_ : m ? m->textcolor() : int (FL_BLACK); if (!active()) l.color = inactive((Fl_Color) l.color); Fl_Color color = m ? m->color() : FL_GRAY; if (selected) { Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR; Fl_Boxtype b = m && m->down_box()? m->down_box() : FL_FLAT_BOX; if (contrast(r, color) != r) { // back compatability boxtypes if (selected == 2) { // menu title r = color; b = m ? m->box() : FL_UP_BOX; } else { r = (Fl_Color) (FL_COLOR_CUBE - 1); // white l.color = contrast((Fl_Color) labelcolor_, r); } } else { l.color = contrast((Fl_Color) labelcolor_, r); } if (selected == 2) { // menu title fl_draw_box(b, x, y, w, h, r); x += 3; w -= 8; } else { //fl_draw_box(b, x+1, y-1, w-2, h+2, r); fl_draw_box(b, x + 1, y - 1, w - 1, h + 3, r); } } if (flags & (FL_MENU_TOGGLE | FL_MENU_RADIO)) { int y1 = y + (h - 14) / 2; fl_color(FL_DARK3); if (flags & FL_MENU_RADIO) { fl_line(x + 2, y1 + 7, x + 8, y1 + 1, x + 14, y1 + 7); if (selected) { fl_color(color); fl_polygon(x + 3, y1 + 7, x + 8, y1 + 2, x + 13, y1 + 7, x + 8, y1 + 12); } fl_color(FL_LIGHT3); fl_line(x + 14, y1 + 7, x + 8, y1 + 13, x + 2, y1 + 7); if (value()) { fl_color(FL_BLACK); fl_polygon(x + 4, y1 + 7, x + 8, y1 + 3, x + 12, y1 + 7, x + 8, y1 + 11); } } else { fl_yxline(x + 3, y1 + 11, y1 + 2, x + 12); if (selected) { fl_color(color); fl_rectf(x + 4, y1 + 3, 9, 9); } fl_color(FL_LIGHT3); fl_xyline(x + 4, y1 + 12, x + 13, y1 + 3); if (value()) { fl_color(FL_BLACK); fl_rectf(x + 5, y1 + 4, 7, 7); } } x += 14; w -= 14; } if (!fl_draw_shortcut) fl_draw_shortcut = 1; l.draw(x + 3, y, w, h, FL_ALIGN_LEFT); fl_draw_shortcut = 0;}menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item * L):Fl_Menu_Window(X, Y, W, H, 0){ end(); set_modal(); clear_border(); menu = L; if (L->labelcolor_) clear_overlay();}menuwindow::menuwindow(const Fl_Menu_Item * m, int X, int Y, int Wp, int Hp, const Fl_Menu_Item * picked, const Fl_Menu_Item * t, int menubar, int menubar_title) :Fl_Menu_Window(X, Y, Wp, Hp, 0){ end(); set_modal(); clear_border(); menu = m; drawn_selected = -1; box(button && button->box()? button->box() : FL_UP_BOX); color(button ? button->color() : FL_GRAY); selected = -1; { int i = 0; if (m) for (const Fl_Menu_Item * m1 = m;; m1 = m1->next(), i++) { if (picked) { if (m1 == picked) { selected = i; picked = 0; } else if (m1 > picked) { selected = i - 1; picked = 0; Wp = Hp = 0; } } if (!m1->text) break; } numitems = i; } if (menubar) { itemheight = 0; title = 0; return; } itemheight = 1; int hotKeysw = 0; int Wtitle = 0; int Htitle = 0; if (t) Wtitle = t->measure(&Htitle, button) + 12; int W = 0; if (m) for (; m->text; m = m->next()) { int h; int w1 = m->measure(&h, button); if (h + LEADING > itemheight) itemheight = h + LEADING; if (m->flags & (FL_SUBMENU | FL_SUBMENU_POINTER)) w1 += 14; if (w1 > W) W = w1; if (m->shortcut_) { w1 = int (fl_width(fl_shortcut_label(m->shortcut_))) + 8; if (w1 > hotKeysw) hotKeysw = w1; } if (m->labelcolor_) clear_overlay(); } if (selected >= 0 && !Wp) X -= W / 2; int BW = Fl::box_dx(box()); W += hotKeysw + 2 * BW + 7; if (Wp > W) W = Wp; if (Wtitle > W) W = Wtitle; if (!Wp) { if (X < 0) X = 0; if (X > Fl::w() - W) X = Fl::w() - W; } x(X); w(W); h((numitems ? itemheight * numitems - LEADING : 0) + 2 * BW + 5); if (selected >= 0) Y = Y + (Hp - itemheight) / 2 - selected * itemheight - BW + 1; else Y = Y + Hp; if (m) y(Y - 1); else { y(Y - 3); w(1); h(1); } if (t) { int ht = menubar_title ? button->h() - 6 : Htitle + 2 * BW + 3; title = new menutitle(X, Y - ht - 3, Wtitle, ht, t); } else title = 0;}menuwindow::~menuwindow(){ delete title;}voidmenuwindow::position(int X, int Y){ if (title) { title->position(X, title->y() + Y - y()); } Fl_Menu_Window::position(X, Y); // x(X); y(Y); // don't wait for response from X}// scroll so item i is visible on screenvoidmenuwindow::autoscroll(int i){ int Y = y() + Fl::box_dx(box()) + 2 + i * itemheight; if (Y <= Fl::y()) Y = Fl::y() - Y + 10; else { Y = Y + itemheight - Fl::h() - Fl::y(); if (Y < 0) return; Y = -Y - 10; } Fl_Menu_Window::position(x(), y() + Y); // y(y()+Y); // don't wait for response from X}////////////////////////////////////////////////////////////////voidmenuwindow::drawentry(const Fl_Menu_Item * m, int i, int erase){ if (!m) return; // this happens if -1 is selected item and redrawn int BW = Fl::box_dx(box()); int x = BW; int W = this->w(); int w = W - 2 * BW - 1; int y = BW + 2 + i * itemheight; int h = itemheight - LEADING; if (erase && i != selected) { fl_color(button ? button->color() : FL_GRAY); // fl_rectf(x+1, y-1, w-2, h+2); fl_rectf(x + 1, y - 1, w - 1, h + 3); } m->draw(x, y, w, h, button, i == selected); // the shortcuts and arrows assumme fl_color() was left set by draw(): if (m->submenu()) { int y1 = y + (h - 14) / 2; fl_polygon(x + w - 13, y1 + 2, x + w - 13, y1 + 2 + 10, x + w - 3, y1 + 2 + 5); } else if (m->shortcut_) { Fl_Font f = button ? button->textfont() : FL_HELVETICA; fl_font(f, button ? button->textsize() : FL_NORMAL_SIZE); fl_draw(fl_shortcut_label(m->shortcut_), x, y, w - 3, h, FL_ALIGN_RIGHT); } if (m->flags & FL_MENU_DIVIDER) { fl_color(FL_DARK3); fl_xyline(BW - 1, y + h + 1, W - 2 * BW + 2); fl_color(FL_LIGHT3); fl_xyline(BW - 1, y + h + 2, W - 2 * BW + 2); }}voidmenutitle::draw(){ menu->draw(0, 0, w(), h(), button, 2);}voidmenuwindow::draw(){ if (damage() != FL_DAMAGE_CHILD) { // complete redraw fl_draw_box(box(), 0, 0, w(), h(), color()); if (menu) { const Fl_Menu_Item *m; int i; for (m = menu, i = 0; m->text; i++, m = m->next()) drawentry(m, i, 0); } } else { if (damage() & FL_DAMAGE_CHILD && selected != drawn_selected) { // change selection drawentry(menu->next(drawn_selected), drawn_selected, 1); drawentry(menu->next(selected), selected, 1); } } drawn_selected = selected;}voidmenuwindow::set_selected(int i){ if (i != selected) { selected = i; damage(FL_DAMAGE_CHILD); }}////////////////////////////////////////////////////////////////intmenuwindow::find_selected(int mx, int my){ if (!menu || !menu->text) return -1; mx -= x(); my -= y(); if (my < 0 || my >= h()) return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -