menu_window.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:49k
- /*
- * ===========================================================================
- * PRODUCTION $Log: menu_window.cpp,v $
- * PRODUCTION Revision 1000.0 2004/06/01 21:29:21 gouriano
- * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.7
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: menu_window.cpp,v 1000.0 2004/06/01 21:29:21 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Andrey Yazhuk
- *
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbistd.hpp>
- #include <algorithm>
- #include <gui/utils/accel_table.hpp>
- #include <gui/widgets/fl/menu_window.hpp>
- #include <FL/fl_draw.H>
- #include <FL/Fl_Image.H>
- #include <FL/Enumerations.H>
- #include <FL/Fl.H>
- #include <math.h>
- BEGIN_NCBI_SCOPE
- ///////////////////////////////////////////////////////////////////////////////
- /// CMenuProperties
- CMenu::CProperties::CProperties()
- {
- m_FontType = FL_HELVETICA;
- m_FontSize = 12;
- m_Colors[eBack] = fl_rgb_color(216, 216, 216);
- m_Colors[eFocusedBack] = fl_rgb_color(192, 192, 216);
- m_Colors[eCheckedBack] = fl_rgb_color(200, 200, 216);
- m_Colors[ePushedBack] = fl_rgb_color(128, 128, 192);
- m_Colors[ePopupBack] = fl_rgb_color(248, 248, 255);
- m_Colors[eFrame] = fl_rgb_color(64, 64, 64);
- m_Colors[eText] = fl_rgb_color(0, 0, 0);
- m_Colors[eDisabledText] = fl_rgb_color(196, 196, 196);
- m_Colors[eFocusedDisabledText] = fl_rgb_color(224, 224, 224);
- m_Colors[ePushedText] = fl_rgb_color(255, 255, 255);
- m_Colors[eFocusedFrame] = fl_rgb_color(0, 0, 128);
- m_Colors[eIconArea] = fl_rgb_color(232, 232, 240);
- m_Colors[eBorder] = fl_rgb_color(255, 255, 255);
- }
- const static int kDefaultIconSize = 16;
- const static int kCheckSize = 16;
- const static int kRadioSize = 16;
- const static int kSubMarkerH = 7; // submenu marker height
- const static int kSubMarkerOffset = 7; // submenu marker offset from the right
- const static int kSubMarkerW = 12; // submenu marker width
- const static int kBorderSize = 3; // menu border
- const static int kSpace = 2; // spacing around icons, labels
- const static int kAccelSpace = 8; // spacing between item label and accelerator label
- const static int kItemOffsetY = 3;
- const static int kItemOffsetX = 4; // horz spacing between items
- const static int kSubmenuOffsetX = 8; // horz spacing between submenus
- const static int kSeparatorSize = 1 + 2 * kItemOffsetX;
- const static char kAccessKeyMarker = '&';
- const static double kMenuDelay = 0.4;
- ///////////////////////////////////////////////////////////////////////////////
- /// class CMenu - base class for all menus
- CMenu::CProperties CMenu::sm_Props;
- CRef<CResourceManager> CMenu::sm_ResManager;
- CRef<CResourceManager> CMenu::GetResourceManager(void)
- {
- return sm_ResManager;
- }
- CMenu::TCmdToHintMap CMenu::sm_CmdToHint;
- void CMenu::SetResourceManager(CRef<CResourceManager> manager)
- {
- sm_ResManager = manager;
- if(sm_ResManager) {
- manager->RegisterAlias("menu::check", "check.png");
- manager->RegisterAlias("menu::radio", "radio.png");
- }
- }
- void CMenu::SetCmdHint(TCmdID cmd, const string& hint)
- {
- sm_CmdToHint[cmd] = hint;
- }
- string CMenu::GetCmdHint(TCmdID cmd)
- {
- TCmdToHintMap::iterator it = sm_CmdToHint.find(cmd);
- return (it != sm_CmdToHint.end()) ? it->second : "";
- }
- CMenu::CMenu()
- : m_RootItem(NULL),
- m_bOwnItems(false),
- m_CmdTarget(NULL),
- m_Listener(NULL),
- m_Width(0),
- m_Height(0),
- m_Border(0),
- m_IconSize(kDefaultIconSize),
- m_MaxLabelW(0),
- m_BackColor(eBack),
- m_Selected(NULL),
- m_PushedItem(NULL),
- m_bKeyActivated(false)
- {
- }
- CMenu::~CMenu()
- {
- x_Clear();
- }
- void CMenu::SetCmdTarget(CCommandTarget* target)
- {
- m_CmdTarget = target;
- }
- CCommandTarget* CMenu::GetCmdTarget(void)
- {
- return m_CmdTarget;
- }
- void CMenu::SetItemImageSize(int size)
- {
- _ASSERT(size >= 0 && size < 100);
- m_IconSize = size;
- }
- bool CMenu::x_IsKeyActivated() const
- {
- return m_bKeyActivated;
- }
- /// Creates a menu described by array of SMenuItem-s. CMenuBar creates a separate
- /// copy of a menu, so that it can be modified at run-time.
- void CMenu::SetItems(const SMenuItemRec* items)
- {
- CMenuItem* root = CreateMenuItems(items);
- x_SetItems(root, true);
- }
- void CMenu::SetItems(CMenuItem* root_item)
- {
- x_SetItems(root_item, true);
- }
- void CMenu::SetHintListener(IMenuHintListener* listener)
- {
- m_Listener = listener;
- }
- IMenuHintListener* CMenu::GetHintListener()
- {
- return m_Listener;
- }
- void CMenu::x_SetItems(CMenuItem* root_item, bool take_ownership)
- {
- x_Clear();
- m_RootItem = root_item;
- m_bOwnItems = take_ownership;
-
- if(m_RootItem) {
- CResourceManager* manager = GetResourceManager();
- _ASSERT(manager);
- m_hCheckIcon = manager->GetImage("menu::check");
- m_hRadioIcon = manager->GetImage("menu::radio");
- for(CMenuItem::TChildItem_CI it = m_RootItem->SubItemsBegin();
- it != m_RootItem->SubItemsEnd(); ++it) {
- CMenuItem* item = (*it)->GetValue();
-
- // create entry for a menu item
- SItemEntry entry;
- entry.m_Item = item;
- if(item->HasImage()) {
- entry.m_hIcon = manager->GetImage(item->GetImageAlias()); // preloading images
- }
- entry.m_Size = 0;
- // create access key entry
- const string& label = item->GetLabel();
- string::size_type pos = label.find(kAccessKeyMarker);
- if(pos != string::npos && pos + 1 < label.size()) {
- char ch = label[pos + 1];
- ch = tolower(ch);
-
- TAccessKeyToItemMap::const_iterator it = m_AccessKeyToItem.find(ch);
- if(it == m_AccessKeyToItem.end()) { // OK
- m_AccessKeyToItem[ch] = item;
- } else {
- ERR_POST("CMenuItem "" << label << "" specifies accelerator that is already defined in this menu.");
- }
- }
-
- // lookup item accelerator
- if(item->IsItem()) {
- TCmdID cmd = item->GetCommand();
- int accel = 0;
- if(CAccelTable::GetAccelByCommand(cmd, accel)) {
- entry.m_AccelLabel = CAccelTable::GetAccelLabel(accel);
- }
- }
- m_Entries.push_back(entry);
- }
- }
-
- x_Layout();
- }
- void CMenu::x_Clear(void)
- {
- m_AccessKeyToItem.clear();
- m_Entries.clear();
- m_Selected = NULL;
-
- if(m_bOwnItems) {
- delete m_RootItem;
- }
- m_RootItem = NULL;
- }
- void CMenu::x_UpdateItems(void)
- {
- CCommandTarget* target = GetCmdTarget();
- if(target) {
- NON_CONST_ITERATE(TEntries, it, m_Entries) {
- CMenuItem& item = *it->m_Item;
- if(item.IsItem()) {
- CMenuCmdUI CmdUI(item);
-
- target->OnUpdateCommand(item.GetCommand(), &CmdUI);
- }
- }
- }
- }
- // all coordinates calculated are relative to widget's origin
- void CMenu::x_Layout(void)
- {
- m_Width = 0;
- m_Height = 0;
- m_MaxLabelW = 0;
- int text_w = 0;
- int marker_w = 0;
-
- fl_font(sm_Props.m_FontType, sm_Props.m_FontSize);
- const int item_h = max(m_IconSize, fl_height()) + kItemOffsetY * 2;
- bool b_horz = x_IsHorizontal();
- int i = 0; // iterate by items
- ITERATE(TEntries, it, m_Entries) {
- const CMenuItem& item = *it->m_Item;
-
- x_MeasureItem(*it, text_w); // measure text length
-
- if(b_horz) {
- int icon_space = m_Entries[i].m_hIcon ?
- (m_IconSize + kSpace) : 0;
- int w = item.IsSeparator() ? kSeparatorSize :
- (icon_space + text_w + 2 * (item.IsItem() ? kItemOffsetX : kSubmenuOffsetX));
- m_Entries[i].m_Size = w;
- m_Width += w;
- } else { // vertical orientation
- int h = 0;
- if(item.IsSeparator()) {
- h = kSeparatorSize;
- } else {
- if(item.IsSubmenu()) {
- marker_w = kSubMarkerW;
- }
- m_MaxLabelW = max(m_MaxLabelW, text_w);
- h = item_h;
- }
- m_Entries[i].m_Size = h;
- m_Height += h;
- }
- i++;
- }
- if(b_horz) {
- m_Height = item_h;
- } else {
- m_Width = (m_IconSize + 2 * kSpace) + kSpace + m_MaxLabelW
- + (marker_w + 2 * kSpace) + 2 * kItemOffsetX;
- }
- m_Width += 2 * m_Border;
- m_Height += 2 * m_Border;
- }
- CPoint CMenu::GetPreferredSize(void) const
- {
- return CPoint(m_Width, m_Height);
- }
- void CMenu::SetSelected(CMenuItem* item)
- {
- if(m_Selected != item) {
- m_Selected = item;
- GetWidget().damage(FL_DAMAGE_OVERLAY);//redraw();
- }
- }
- CMenuItem* CMenu::GetRootItem(void)
- {
- return m_RootItem;
- }
- int CMenu::GetBorder(void) const
- {
- return m_Border;
- }
- void CMenu::x_Draw(int x, int y)
- {
- Fl_Widget& wid = GetWidget();
- int w = wid.w(), h = wid.h();
- fl_clip(x, y, w, h);
- if(m_Border > 0) { // draw frame and border
- fl_color(sm_Props.GetColor(eFrame));
- fl_rect(x, y, w, h); // frame
- fl_color(sm_Props.GetColor(eBorder));
- for( int i = 1; i < m_Border; i++ ) { // border
- fl_rect(i, i, w - 2 * i, h - 2 * i);
- }
- }
- // fill background not filled by items
- fl_color(sm_Props.GetColor(m_BackColor));
- // fill the right part
- int x_off = m_Width - m_Border;
- fl_rectf(x + x_off, y + m_Border, w - m_Border - x_off, h - 2 * m_Border);
- // fill the bottom part
- int y_off = m_Height - m_Border;
- fl_rectf(x + m_Border, y + y_off, m_Width - 2 * m_Border, h - m_Border - y_off);
- x_DrawItems(x + m_Border, y + m_Border);
- fl_pop_clip();
- }
- void CMenu::x_DrawItems(int x, int y)
- {
- bool b_horz = x_IsHorizontal();
- if(m_RootItem) {
- fl_font(sm_Props.m_FontType, sm_Props.m_FontSize);
- int i = 0;
- NON_CONST_ITERATE(TEntries, it, m_Entries) {
- int size = it->m_Size;
- if(b_horz) {
- x_DrawItem(*it, x, y, size, m_Height - 2 * m_Border);
- x += size;
- } else {
- x_DrawItem(*it, x, y, m_Width - 2 * m_Border, size);
- y += size;
- }
- i++;
- }
- }
- }
- /// draw single menu item in the given rectangular area
- void CMenu::x_DrawItem(CMenu::SItemEntry& entry, int x, int y, int w, int h)
- {
- CMenuItem& item = *entry.m_Item;
-
- bool b_icon = (bool)(entry.m_hIcon);
- int icon_w = x_IsHorizontal() ? (m_IconSize + kSpace)
- : (m_IconSize + 2 * kSpace);
- bool b_focused = false;
- bool b_pushed = false;
- if(x_IsSubMenuPushed()) {
- b_focused = (m_Selected == &item) && item.IsEnabled();
- } else if(x_IsItemPushed()) {
- b_focused = (m_Selected != m_PushedItem) && (m_PushedItem == &item);
- b_pushed = (m_Selected == m_PushedItem) && (m_PushedItem == &item);
- } else {
- b_focused = (m_Selected == &item) &&
- (! x_IsHorizontal() || Fl::belowmouse() == &GetWidget() || x_IsKeyActivated());
- }
- bool b_check = item.IsChecked() || item.IsRadioSelected(); // item checked
-
- Fl_Color back_color = FL_RED;
- if(b_focused || b_pushed) { // draw focused item with frame
- EColorType color = (x_IsHorizontal() && item.IsSubmenu())
- ? (m_PushedItem ? ePopupBack : eFocusedBack)
- : (b_pushed ? ePushedBack : eFocusedBack);
- back_color = sm_Props.GetColor(color);
- fl_color(back_color);
- fl_rectf(x, y, w, h);
- // draw focused frame
- fl_color(sm_Props.GetColor(x_IsItemPushed() ? eFocusedFrame : eFrame));
- fl_rect(x, y, w, h);
- } else { // draw unfocused item
- back_color = sm_Props.GetColor(m_BackColor);
- if(x_IsHorizontal()) {
- if(b_check) {
- fl_color(sm_Props.GetColor(eCheckedBack));
- fl_rectf(x, y, w, h);
- fl_color(sm_Props.GetColor(eFocusedFrame));
- fl_rect(x, y, w, h);
- } else {
- fl_color(back_color);
- fl_rectf(x, y, w, h);
- }
- } else {
- fl_color(back_color);
- fl_rectf(x + icon_w, y, w - icon_w, h); // fill text background
- back_color = sm_Props.GetColor(eIconArea);
- fl_color(back_color);
- fl_rectf(x, y, icon_w, h); // draw icon placeholder
- }
- }
- int y_c = y + h / 2;
-
- if(item.IsSeparator()) { //draw separation line
- fl_color(sm_Props.GetColor(eDisabledText));
- if(x_IsHorizontal()) {
- int x_c = x + w / 2;
- fl_line(x_c, y + 1, x_c, y + h - 2); // horz line
- } else {
- fl_line(x + icon_w + 1, y_c, x + w - 2, y_c); // vert line
- }
- } else {
- // draw Icon
- int x_off = x_IsHorizontal() ? (item.IsItem() ? kItemOffsetX : kSubmenuOffsetX)
- : kSpace;
- x_DrawItemIcon(entry, x + x_off, y_c - m_IconSize / 2, back_color);
- // draw Label adn Accelerator Label
- EColorType text_color = b_focused ? eFocusedDisabledText : eDisabledText;
- if(item.IsEnabled()) {
- text_color = b_pushed ? ePushedText : eText;
- }
- fl_color(sm_Props.GetColor(text_color));
- int text_off = x_off;
- if(x_IsHorizontal()) {
- text_off += b_icon ? (icon_w + kSpace) : 0;
- } else {
- text_off = icon_w + kSpace * 2;
- }
- x_DrawItemText(entry, x + text_off, y, w, h);
-
- // draw submenu marker
- if(! x_IsHorizontal() && item.IsSubmenu()) {
- int N = kSubMarkerH / 2;
- int m_x = x + (w - 1) - kSubMarkerOffset;
- int y_c = y + h / 2;
-
- fl_color(sm_Props.GetColor(eText));
- for( int i = 0; i <= N; i++ ) { // draw triangle as series of lines
- fl_line(m_x - i, y_c - i, m_x - i, y_c + i);
- }
- }
- }
- }
- /// draws item's label and accelerator label (if any)
- void CMenu::x_DrawItemText(const CMenu::SItemEntry& entry, int x, int y, int w, int h)
- {
- const CMenuItem& item = *entry.m_Item;
- const string& text = item.GetLabel();
- int text_x = x;
- int y_c = y + h / 2;
- int text_y = y_c + fl_height() / 2 - 2;
-
- int label_len = 0;
- string::size_type pos = text.find(kAccessKeyMarker); // find accelerator marker
- if(pos != string::npos && pos + 1 < text.size()) { // there is an accelerator
- int line_x = text_x;
- if(pos > 0) {
- fl_draw(text.c_str(), pos, text_x, text_y); // draw all the text before marker
- line_x += (int) ceil(fl_width(text.c_str(), pos));
- }
-
- int line_len = (int) ceil(fl_width(text.c_str() + pos + 1, 1));
- fl_draw(text.c_str() + pos + 1, line_x, text_y); // draw text after Marker
-
- int line_y = text_y + 2;
- fl_line(line_x, line_y, line_x + line_len - 1, line_y); // draw Underscore
- }
- else { // no accelerator - draw plain text
- fl_draw(text.c_str(), text_x, text_y);
- }
- // draw accelerator label
- if(! x_IsHorizontal()) {
- int len = (int) ceil(fl_width(entry.m_AccelLabel.c_str()));
- fl_draw(entry.m_AccelLabel.c_str(), x + m_MaxLabelW - len, text_y);
- }
- }
- void CMenu::x_DrawItemIcon(CMenu::SItemEntry& entry, int x, int y, Fl_Color back_color)
- {
- CMenuItem& item = *entry.m_Item;
- CFLTKImageHandle hIcon;
- if(item.IsChecked()) {
- hIcon = m_hCheckIcon;
- } else if(item.IsRadioSelected()) {
- hIcon = m_hRadioIcon;
- } else {
- hIcon = entry.m_hIcon;
- }
- if(hIcon) { //draw icon if any
- Fl_Image* image = &(*hIcon);
- bool disabled = ! item.IsEnabled();
- CPNGImageExt* ext_image = dynamic_cast<CPNGImageExt*>(image);
- if(ext_image) {
- ext_image->DrawTransparent(back_color, x, y, m_IconSize, m_IconSize, disabled);
- } else {
- if(disabled) {
- image = image->copy();
- image->inactive();
- }
- image->draw(x, y, m_IconSize, m_IconSize);
- if(disabled) {
- delete image;
- }
- }
- }
- }
- void CMenu::x_MeasureItem(const SItemEntry& entry, int& text_w) const
- {
- CMenuItem& item = *entry.m_Item;
- if(item.IsSeparator()) {
- text_w = 0;
- } else {
- fl_font(sm_Props.m_FontType, sm_Props.m_FontSize);
- const string& text = item.GetLabel();
- text_w = (int) ceil(fl_width(text.c_str()));
- string::size_type pos = text.find(kAccessKeyMarker); // find accelerator marker
- if(pos != string::npos && pos + 1 < text.size()) { // there is an accelerator
- text_w -= (int) ceil(fl_width("&"));
- }
- if(! x_IsHorizontal()) {
- // measure accelerator label
- text_w += kAccelSpace;
- text_w += (int) ceil(fl_width(entry.m_AccelLabel.c_str()));
- }
- }
- }
- CRect CMenu::x_GetPopupItemRect(const CMenuItem& r_item)
- {
- bool b_horz = x_IsHorizontal();
- int pos = m_Border;
- if(m_RootItem) {
- for( size_t i = 0; i < m_Entries.size(); i++ ) {
- const CMenuItem* item = m_Entries[i].m_Item;
- int size = m_Entries[i].m_Size;
-
- if(item == &r_item) { // found r_item
- if(b_horz) {
- return CRect(pos, m_Border, pos + size - 1, m_Height - m_Border - 1);
- } else {
- return CRect(m_Border, pos, m_Width - m_Border - 1, pos + size - 1);
- }
- break;
- } else {
- pos += size;
- }
- }
- }
- return CRect(0, 0);
- }
- // returns item containing (x, y) point
- CMenuItem* CMenu::x_HitTest(int x, int y)
- {
- Fl_Widget& wid = GetWidget();
- bool b_horz = x_IsHorizontal();
-
- // to local coords
- x -= wid.x();
- y -= wid.y();
- int i_x = m_Border;
- int i_y = m_Border;
-
- bool b_hit_rect = (b_horz && y >= m_Border && y < m_Border + m_Height)
- || (! b_horz && x >= m_Border && x < m_Border + m_Width);
- if(b_hit_rect && m_RootItem) {
- fl_font(sm_Props.m_FontType, sm_Props.m_FontSize);
- int i = 0;
- for( CMenuItem::TChildItem_I it = m_RootItem->SubItemsBegin();
- it != m_RootItem->SubItemsEnd(); ++it, i++ ) {
- CMenuItem& item = *(*it)->GetValue();
- int size = m_Entries[i].m_Size;
- if(b_horz) {
- if(x >= i_x && x < i_x + size) {
- return &item;
- } else i_x += size;
- } else {
- if(y >= i_y && y < i_y + size) {
- return &item;
- } else i_y += size;
- }
- }
- }
- return NULL;
- }
- void CMenu::x_ExecuteCommand(const CMenuItem& item)
- {
- if(item.IsEnabled() && item.IsItem()) {
- TCmdID cmd = item.GetCommand();
- if(GetCmdTarget()) {
- GetCmdTarget()->OnCommand(cmd);
- } else {
- ERR_POST("CMenu - cannot execute command, not command target specified");
- }
- }
- }
- void WidgetToScreen(const Fl_Widget& widget, int& wx, int& wy)
- {
- for( Fl_Window* w = widget.window(); w; w = w->window()) {
- wx += w->x();
- wy += w->y();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- /// CMenuCmdUI
- CMenuCmdUI::CMenuCmdUI(CMenuItem& item)
- : m_Item(item)
- {
- }
- TCmdID CMenuCmdUI::GetCommand() const
- {
- return m_Item.GetCommand();
- }
- void CMenuCmdUI::Enable(bool en)
- {
- m_Item.Enable(en);
- }
- void CMenuCmdUI::SetCheck(bool set)
- {
- m_Item.SetCheck(set);
- }
- void CMenuCmdUI::SetRadio(bool set)
- {
- m_Item.SelectRadio(set);
- }
- void CMenuCmdUI::SetLabel(const string& label)
- {
- m_Item.SetLabel(label);
- }
- ///////////////////////////////////////////////////////////////////////////////
- /// CPopupMenu1
- CPopupMenu1::TPopupVector CPopupMenu1::sm_Popups;
- CMenuItem* CPopupMenu1::sm_CurrItem = NULL;
- CPopupMenu1* CPopupMenu1::sm_CurrPopup = NULL;
- CPopupMenu1::EState CPopupMenu1::sm_State;
- bool CPopupMenu1::sm_bMenubar;
- CPopupMenu1::CPopupMenu1(int x, int y, CMenuItem* root_item,
- CCommandTarget* target, IMenuHintListener* listener)
- : TPopupMenuParent(x, y, 0, 0)
- {
- x_Init(x, y, x, y, root_item, target, listener, true);
- }
- CPopupMenu1::CPopupMenu1(int x, int y, const SMenuItemRec* items,
- CCommandTarget* target, IMenuHintListener* listener)
- : TPopupMenuParent(x, y, 0, 0)
- {
- CMenuItem* root_item = CreateMenuItems(items);
- x_Init(x, y, x, y, root_item, target, listener, true);
- }
- // this is a protected constructor used only within CMenu subsystem
- // creates a child popup menu.
- CPopupMenu1::CPopupMenu1(int x, int y, int left, int top, CMenuItem* root_item,
- CCommandTarget* target, IMenuHintListener* listener)
- : TPopupMenuParent(x, y, 0, 0)
- {
- x_Init(x, y, left, top, root_item, target, listener, false);
- }
- void CPopupMenu1::x_Init(int x, int y, int left, int top, CMenuItem* root_item,
- CCommandTarget* target, IMenuHintListener* listener, bool root_popup)
- {
- m_MenuBar = NULL; // popup mode
- position(x, y);
- m_Left = left;
- m_Top = top;
-
- m_bSkipFirstRelease = root_popup;
-
- m_Cmd = eCmdInvalid;
- m_Border = kBorderSize;
- m_BackColor = ePopupBack; // override standard color
- end(); // prevent adding child widgets
- set_modal();
- clear_border(); // hide frame
- x_SetItems(root_item, root_popup); // own items only if this is a root popup menu
- SetCmdTarget(target);
- SetHintListener(listener);
- }
- /// Creates root popup menu stub for a menubar
- CPopupMenu1::CPopupMenu1(CMenuBar1& menubar, CMenuItem* root_item, CMenuItem* sel_item,
- IMenuHintListener* listener)
- : TPopupMenuParent(0, 0, 0, 0),
- m_Left(0), m_Top(0),
- m_MenuBar(&menubar),
- m_bSkipFirstRelease(true),
- m_Cmd(eCmdInvalid)
- {
- end(); // prevent adding child widgets
- set_modal();
- clear_border(); // hide frame
-
- m_Border = m_MenuBar->GetBorder();
-
- m_bKeyActivated = menubar.m_bKeyActivated;
- x_SetItems(root_item, false); // share items with the caller
- SetSelected(sel_item);
- SetHintListener(listener);
- }
- void CPopupMenu1::x_AdjustRectangle()
- {
- if(m_MenuBar) {
- CRect rc = m_MenuBar->GetPopupRect();
-
- const Fl_Widget& wid = m_MenuBar->GetWidget();
- int x = 0, y = 0;
- WidgetToScreen(wid, x,y); // upper-left corner to screen coords
- rc.Offset(x, y);
- resize(rc.Left(), rc.Top(), rc.Width(), rc.Height());
- } else {
- // adjsut size
- TPopupMenuParent::size(m_Width, m_Height);
- int X = x(), Y = y();
- //adjust position on screen
- if(X + m_Width > Fl::w()) { // not enough space to the right
- if(m_Left == X) {
- X = Fl::w() - m_Width;
- } else {
- X = m_Left - (m_Width -1); // place to the left
- }
- }
- X = max(X, 0);
- x(X);
-
- if(Y + m_Height > Fl::h()) { // not enought space to the bottom
- if(m_Top == Y) {
- Y = Fl::h() - m_Height; // scroll up
- } else {
- Y = m_Top - (m_Height - 1); // flip up
- }
- }
- Y = max(Y, 0);
- y(Y);
- }
- }
- void CPopupMenu1::SetSelected(CMenuItem* item)
- {
- if(m_MenuBar) { // delegate
- CMenuItem* new_item = NULL;
- if(item) {
- CMenuItem* root = m_MenuBar->GetRootItem();
- new_item = root->FindEqualSubItem(*item);
- _ASSERT(new_item); // must exist
- }
- m_MenuBar->SetSelected(new_item);
- }
- CMenu::SetSelected(item);
- }
- CRect CPopupMenu1::x_GetPopupItemRect(const CMenuItem& item)
- {
- CRect rc = CMenu::x_GetPopupItemRect(item);
- if(! x_IsMenuBar()) {
- rc.Inflate(m_Border, 0);
- }
- return rc;
- }
- /// this functions shows Popup menu and all its submenus and provides event
- /// loop for handling all events.
- void CPopupMenu1::Popup()
- {
- if(sm_Popups.size()) {
- ERR_POST("CPopupMenu1::Popup() - must not be called recursively.");
- return;
- }
- sm_Popups.push_back(this);
- sm_bMenubar = (this->m_MenuBar != NULL);
- Fl_Group::current(0);
- //grab events and do initialization
- Fl_Window* prev_grab = Fl::grab();
- Fl::grab(*this);
- // set initial state for this menu
- if(sm_bMenubar) {
- sm_CurrItem = m_Selected; // inherit selection from menubar
- if(m_MenuBar->x_IsKeyActivated()) { // do not expand submenus automatically
- sm_State = eIdle;
- } else {
- m_Selected = NULL; // to trigger submenu expansion
- sm_State = eTrackSubmenus;
- }
- } else {
- sm_CurrItem = NULL;
- sm_State = eIdle;
- }
- sm_CurrPopup = this;
-
- CMenuItem* prev_item = NULL;
- m_Timer.Init(1, kMenuDelay, false, this);
-
- do { // message loop - works while popup menus are on screen
- // show hidden menus
- for( size_t i_popup = 0; i_popup < sm_Popups.size(); i_popup++ ) {
- CPopupMenu1* p_popup = sm_Popups[i_popup];
- if(! p_popup->shown()) {
- p_popup->show();
- }
- }
-
- Fl::wait(); // handle events and calculate new state
- if(sm_CurrItem != prev_item) {
- x_UpdateListener();
- }
- // performs actions depending on cuurent state
- switch(sm_State) {
- case eIdle:
- case eDone: break;
- case eHide: { //hide one popup
- if(sm_Popups.size() > 1) { // except the first one
- CPopupMenu1* dead_menu = sm_Popups.back();
- delete dead_menu;
- sm_Popups.pop_back();
- }
- sm_State = eIdle;
- }; break;
- default:
- if(sm_CurrItem == NULL) {
- // turn off selection in deepest menu, but don't erase other menus:
- if(sm_Popups.size()) {
- sm_Popups.back()->SetSelected(NULL);
- }
- } else if(! sm_CurrItem->IsSeparator()) { // change selected itme (if it isn;t a separator)
-
- if(sm_State == eTrackSubmenus && sm_CurrPopup->m_Selected == sm_CurrItem) {
- sm_State = eIdle; // nothing changed
- } else {
- TPopupVector::iterator it = std::find(sm_Popups.begin(), sm_Popups.end(), sm_CurrPopup);
- CMenuItem* item = sm_CurrItem;
- for( int i = it - sm_Popups.begin(); i >= 0; i-- ) {
- sm_Popups[i]->SetSelected(item);
- item = item->GetParent();
- }
- }
-
- sm_CurrPopup->SetSelected(sm_CurrItem);
- switch(sm_State) {
- case eTrack: {
- x_CollapseToCurrent(); // close expanded submenus
- }; break;
- case eExpand: {
- x_ShowCurrItemSubmenu(true); //expand submenu and select item
- sm_State = eIdle;
- }; break;
- case eMenuPush:
- {
- x_CollapseToCurrent(); // close expanded submenus
- x_ShowCurrItemSubmenu(false); //expand new submenu
- }; break;
- case eTrackSubmenus: {
- if(sm_CurrPopup && sm_CurrPopup->x_IsMenuBar()) {
- x_CollapseToCurrent(); // close expanded submenus
- x_ShowCurrItemSubmenu(false); //expand new submenu
- } else {
- m_Timer.ReStart();
- }
- }; break;
- default: break;
- }; //switch
- sm_State = eIdle; // procesing finished - go to neutral state
- };
- prev_item = sm_CurrItem;
- }//switch
- } while(sm_State != eDone);
- _ASSERT(sm_State == eDone); // check exit condition
- m_Timer.Stop();
- for( size_t i = 1; i < sm_Popups.size(); i++ ) {
- delete sm_Popups[i];
- }
- sm_Popups.clear();
-
- hide(); // close window
- Fl::grab(prev_grab); //return grab to previous owner
- sm_CurrItem = NULL;
- sm_CurrPopup = NULL;
- sm_State = eIdle;
- if(m_Cmd != eCmdInvalid) {
- if(GetCmdTarget()) {
- GetCmdTarget()->OnCommand(m_Cmd);
- } else {
- ERR_POST("CMenu cannot execute command - no command target specifed.");
- }
- }
- }
- // close all submenus up to current menu
- void CPopupMenu1::x_CollapseToCurrent(void)
- {
- // delete all submenus from the last one to "sm_CurrPopup"
- while(sm_Popups.size() > 1) { // except the first one
- CPopupMenu1* dead_menu = sm_Popups.back();
- if(dead_menu != sm_CurrPopup) {
- delete dead_menu;
- sm_Popups.pop_back();
- } else break;
- }
- }
- void CPopupMenu1::x_ShowCurrItemSubmenu(bool b_select)
- {
- _ASSERT(sm_CurrItem);
- if(sm_CurrItem->IsSubmenu() && ! sm_CurrItem->IsSubmenuEmpty()) { // show submenu
- CRect rc = sm_CurrPopup->x_GetPopupItemRect(*sm_CurrItem);
- rc.Offset(sm_CurrPopup->x(), sm_CurrPopup->y()); // to screen coords
- int x, y;
- if(sm_CurrPopup->x_IsMenuBar()) {
- x = rc.Left();
- y = rc.Bottom();
- } else {
- x = rc.Right();
- y = rc.Top();
- }
- int left = rc.Left();
- int top = rc.Top();
- CPopupMenu1* submenu = new CPopupMenu1(x, y, left, top, sm_CurrItem,
- GetCmdTarget(), GetHintListener());
- sm_Popups.push_back(submenu);
-
- sm_CurrPopup = submenu;
- if(b_select) {
- x_SelectNextItem();
- } else {
- sm_CurrItem = NULL;
- }
- sm_CurrPopup->SetSelected(sm_CurrItem);
- sm_CurrPopup->show();
- }
- }
- // changes current item's state to opposite
- void CPopupMenu1::x_TogglePushItem()
- {
- _ASSERT(m_bKeyActivated); // not supposed to be used overwise
-
- if(m_PushedItem == NULL) {
- m_MenuBar->m_PushedItem = m_PushedItem = sm_CurrItem;
- } else {
- m_MenuBar->m_PushedItem = m_PushedItem = NULL;
- redraw();
- x_CloseItemSubmenu(); // collapse menu hierarhy
- }
- redraw();
- }
- /// handles events for all CPopupMenu-s being active at the moment
- int CPopupMenu1::handle(int event)
- {
- m_Event.OnFLTKEvent(event);
- switch(event) {
- case FL_KEYDOWN: return x_HandleKeyboard();
- case FL_ENTER:
- case FL_LEAVE:
- case FL_MOVE:
- case FL_DRAG:
- case FL_PUSH:
- case FL_RELEASE: {
- // locate menu item being hit
- CPopupMenu1* popup = NULL;
- CMenuItem* item = NULL;
- int i_popup = sm_Popups.size() - 1;
- while(item == NULL && i_popup >= 0) {
- popup = sm_Popups[i_popup];
- int x = Fl::event_x_root();
- int y = Fl::event_y_root();
- item = popup->x_HitTest(x, y);
- if(item == NULL) {
- i_popup--;
- }
- }
- if(item && item->IsSeparator()) {
- item = NULL;
- }
-
- switch(event) {
- case FL_PUSH: {
- sm_CurrItem = item;
- sm_CurrPopup = item ? popup : NULL;
- // if m_bSkipFirstRelease is "true" then Popup was shown on FL_RELEASE
- // and we do not need to skip next FL_RELEASE
- m_bSkipFirstRelease = false;
-
- if(sm_CurrItem && sm_CurrItem->IsSubmenu()) {
- if(x_IsKeyActivated()) {
- x_TogglePushItem();
- sm_State = m_PushedItem ? eMenuPush : eHide;
- return 1;
- }
- sm_State = eMenuPush;
- } else {
- sm_State = ePush;
- }
- }; break;
- case FL_RELEASE: {
- if(m_bSkipFirstRelease) {
- m_bSkipFirstRelease = false;
- } else {
- bool b_skip = x_IsKeyActivated() || (item && ! item->IsEnabled());
- if(! b_skip) {
- if(item == NULL || item->IsItem()) // command item pushed
- {
- if(item) {
- x_SetExecuteCommand(*item);
- }
- sm_State = eDone;
- } else if(popup && popup->m_MenuBar) {
- sm_State = eDone;
- }
- }
- }
- }; break;
- default: {
- if(! x_IsKeyActivated() || item) {
- sm_CurrItem = item;
- sm_CurrPopup = item ? popup : NULL;
- }
- sm_State = (! x_IsKeyActivated() || m_PushedItem) ? eTrackSubmenus : eTrack;
- };
- };
- if(event == FL_ENTER || event == FL_LEAVE) {
- redraw(); // we need to repaint itseld to reflect changes in "focused" state
- }
- return 1;
- };
- };// switch
- return Fl_Window::handle(event);
- }
- int CPopupMenu1::x_HandleKeyboard()
- {
- if(x_HandleShortcuts()) {
- return 1;
- }
- int key = Fl::event_key();
- if(key == FL_Tab) {
- key = (Fl::event_shift()) ? FL_BackSpace : FL_Down;
- }
-
- switch(key) {
- case FL_Down: {
- if(! sm_CurrPopup->x_IsMenuBar()) { // Up-Down works only in submenus
- x_SelectNextItem();
- } else if(x_IsKeyActivated()) {
- x_TogglePushItem();
- sm_State = eExpand;
- }
- return 1;
- };
- case FL_Up: {
- if(! sm_CurrPopup->x_IsMenuBar()) { // Up-Down works only in submenus
- x_SelectPrevItem();
- }
- return 1;
- };
- case FL_Right: {
- x_OnRightPressed();
- return 1;
- };
- case FL_Left: {
- x_OnLeftPressed();
- return 1;
- };
- case FL_Page_Up:
- case FL_Home: {
- x_SelectTopItem();
- return 1;
- };
- case FL_Page_Down:
- case FL_End: {
- x_SelectBottomItem();
- return 1;
- };
- case FL_Enter:
- case ' ': {
- if(sm_CurrItem && sm_CurrItem->IsEnabled()) {
- if(sm_CurrItem->IsItem()) {
- x_SetExecuteCommand(*sm_CurrItem);
- sm_State = eDone;
- } else {
- sm_State = eExpand;
- }
- }
- return 1;
- };
- case FL_Escape: {
- if(x_IsMenuBar() && x_IsKeyActivated() && sm_Popups.size() > 1) {
- x_TogglePushItem(); // "unpush" selected item and close submenus
- } else {
- sm_CurrPopup = NULL;
- sm_State = eDone; // exit menus
- }
- return 1;
- };
- };
- return 0;
- }
- // handle both type of keyboard shortcuts - Access Keys and Accelerators
- int CPopupMenu1::x_HandleShortcuts(void)
- {
- // first try accelerators
- int accel = m_Event.GetAccelByEvent();
- TCmdID cmd = eCmdInvalid;
- if(CAccelTable::GetCommandByAccel(accel, cmd)) {
- m_Cmd = cmd;
- sm_State = eDone;
- return 1;
- }
- // now handling access keys
- if(sm_CurrPopup) {
- char ch = tolower(Fl::event_key());
- TAccessKeyToItemMap::const_iterator it = sm_CurrPopup->m_AccessKeyToItem.find(ch);
-
- if(it != sm_CurrPopup->m_AccessKeyToItem.end()) {
- sm_CurrItem = it->second;
- if(sm_CurrItem && sm_CurrItem->IsEnabled()) {
- if(sm_CurrItem->IsItem()) {
- x_SetExecuteCommand(*sm_CurrItem);
- sm_State = eDone;
- } else if(sm_CurrItem->IsSubmenu()) {
- sm_State = sm_CurrPopup->x_IsMenuBar() ? eTrackSubmenus : eTrack;
- }
- }
- return 1;
- }
- }
- return 0;
- }
- void CPopupMenu1::x_OnLeftPressed(void)
- {
- if(x_IsMenuBar()) { // root menu is MenuBar
- if(sm_Popups.size() > 2) { // close last menu
- x_CloseItemSubmenu();
- } else { // select previos item in MenuBar
- sm_CurrPopup = this;
- x_SelectPrevItem();
- }
- } else { // root menu is Popup
- x_CloseItemSubmenu();
- }
- }
- void CPopupMenu1::x_OnRightPressed(void)
- {
- if(sm_CurrPopup->m_Selected && ! sm_CurrPopup->m_Selected->IsSubmenuEmpty() && m_PushedItem) {
- sm_State = eExpand;
- } else {
- if(x_IsMenuBar()) {// && sm_Popups.size() > 1 && sm_CurrPopup == sm_Popups[1]) {
- // if current popup is MenuBar's submenu
- sm_CurrPopup = this; // MenuBar
- x_SelectNextItem(); // select next item (to the right) in MenuBar
- }
- }
- }
- // selects next item in the current menu (Popup or MenuBar)
- void CPopupMenu1::x_SelectNextItem(void)
- {
- _ASSERT(sm_CurrPopup);
- CMenuItem& root = *sm_CurrPopup->m_RootItem;
- if(! root.IsSubmenuEmpty()) {
- // find selected ot first if nothing is selected
- CMenuItem::TChildItem_I it = sm_CurrPopup->m_Selected ?
- root.FindSubItem(*sm_CurrPopup->m_Selected) : --root.SubItemsEnd();
-
- _ASSERT(it != root.SubItemsEnd());
-
- CMenuItem* item = NULL;
- do {
- ++it;
- if(it == root.SubItemsEnd()) {
- it = root.SubItemsBegin();
- }
- item = (*it)->GetValue();
- } while(item->IsSeparator() && item != sm_CurrPopup->m_Selected);
-
- sm_CurrItem = item;
- sm_State = (sm_CurrPopup->x_IsMenuBar() && ! sm_CurrItem->IsSubmenuEmpty() && m_PushedItem) ? eTrackSubmenus : eTrack;
- }
- }
- // selects next item in the current menu (Popup or MenuBar)
- void CPopupMenu1::x_SelectPrevItem(void)
- {
- _ASSERT(sm_CurrPopup);
- CMenuItem& root = *sm_CurrPopup->m_RootItem;
- if(! root.IsSubmenuEmpty()) {
- // find selected ot fisrt if nothing is selected
- CMenuItem::TChildItem_I it = sm_CurrPopup->m_Selected ?
- root.FindSubItem(*sm_CurrPopup->m_Selected) : root.SubItemsBegin();
-
- _ASSERT(it != root.SubItemsEnd());
-
- CMenuItem* item = NULL;
- do {
- if(it == root.SubItemsBegin()) {
- it = root.SubItemsEnd();
- }
- --it;
- item = (*it)->GetValue();
- } while(item->IsSeparator() && item != sm_CurrPopup->m_Selected);
-
- sm_CurrItem = item;
- //sm_State = sm_CurrPopup->x_IsMenuBar() ? eTrackSubmenus : eTrack;
- sm_State = (sm_CurrPopup->x_IsMenuBar() && ! sm_CurrItem->IsSubmenuEmpty() && m_PushedItem) ? eTrackSubmenus : eTrack;
- }
- }
- void CPopupMenu1::x_SelectTopItem(void)
- {
- if(! sm_CurrPopup->x_IsMenuBar()) {
- for(size_t i = 0; i < sm_CurrPopup->m_Entries.size(); i++ ) {
- SItemEntry& entry = sm_CurrPopup->m_Entries[i];
- CMenuItem* item = entry.m_Item;
- if(! item->IsSeparator() && item->IsEnabled()) {
- sm_CurrItem = item;
- sm_State = eTrack; // select
- return;
- }
- }
- }
- }
- void CPopupMenu1::x_SelectBottomItem(void)
- {
- if(! sm_CurrPopup->x_IsMenuBar()) {
- for(int i = sm_CurrPopup->m_Entries.size() - 1; i >= 0; i-- ) {
- SItemEntry& entry = sm_CurrPopup->m_Entries[i];
- CMenuItem* item = entry.m_Item;
- if(! item->IsSeparator() && item->IsEnabled()) {
- sm_CurrItem = item;
- sm_State = eTrack; // select
- return;
- }
- }
- }
- }
- void CPopupMenu1::x_CloseItemSubmenu(void)
- {
- if(sm_Popups.size() > 1) {
- CPopupMenu1* menu = sm_Popups.back();
- if(sm_CurrPopup == menu) { // select previous one
- sm_CurrPopup = sm_Popups[sm_Popups.size() - 2];
- sm_CurrItem = sm_CurrPopup->m_Selected;
- }
- sm_State = eHide;
- }
- }
- /// sets command that will be executed on exit
- void CPopupMenu1::x_SetExecuteCommand(const CMenuItem& item)
- {
- if(item.IsEnabled() && item.IsItem()) {
- m_Cmd = item.GetCommand();
- } else {
- m_Cmd = eCmdInvalid;
- }
- }
- /// depending on selected item generates text string and supplies it to the
- /// listener
- void CPopupMenu1::x_UpdateListener()
- {
- if(m_Listener) {
- string hint;
- if(sm_CurrItem && sm_CurrItem->IsItem()) {
- hint = GetCmdHint(sm_CurrItem->GetCommand());
- }
- m_Listener->OnHint(hint);
- }
- }
- void CPopupMenu1::show(void)
- {
- x_AdjustRectangle();
- x_UpdateItems();
-
- TPopupMenuParent::show();
- }
- void CPopupMenu1::draw(void)
- {
- if(m_MenuBar) { // delegate draing to hosting MenuBar
- m_MenuBar->x_Draw(0, 0);
- } else {
- CMenu::x_Draw(0, 0);
- }
- }
- Fl_Widget& CPopupMenu1::GetWidget(void)
- {
- return *static_cast<Fl_Widget*>(this);
- }
- const Fl_Widget& CPopupMenu1::GetWidget(void) const
- {
- return *static_cast<const Fl_Widget*>(this);
- }
- bool CPopupMenu1::x_IsHorizontal(void) const
- {
- return m_MenuBar != NULL;
- }
- void CPopupMenu1::OnTimeout(int timer_id)
- {
- m_Timer.Stop();
- if(timer_id == 1) {
- if(sm_CurrPopup && sm_CurrItem) {
- x_CollapseToCurrent(); // close expanded submenus
- x_ShowCurrItemSubmenu(false); //expand new submenu
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- /// CMenuBar1
- CMenuBar1::CMenuBar1(int x, int y, int w, int h)
- : Fl_Widget(x, y, w, h),
- m_TooltipItem(NULL)
- {
- m_Border = 2;
-
- m_Tooltip.SetMode(CTooltip::eStayOnMove);
- m_Tooltip.EnableActiveMode(this);
- }
- void CMenuBar1::EnableTooltips(bool b_en)
- {
- m_Tooltip.Enable(b_en);
- }
- void CMenuBar1::Activate()
- {
- if(m_RootItem && ! m_RootItem->IsSubmenuEmpty()) {
- CMenuItem* item = (* m_RootItem->SubItemsBegin())->GetValue();
-
- SetSelected(item);
- m_PushedItem = NULL; // not pushed by default
- m_bKeyActivated = true;
-
- x_ShowSubMenu();
-
- m_bKeyActivated = false;
- }
- }
- void CMenuBar1::draw(void)
- {
- Fl_Widget& wid = GetWidget();
- x_Draw(wid.x(), wid.y());
- }
- void CMenuBar1::x_Draw(int x, int y)
- {
- CMenu::x_Draw(x, y);
-
- Fl_Widget& wid = GetWidget();
- fl_draw_box(FL_THIN_UP_FRAME, x, y, wid.w(), wid.h(), sm_Props.GetColor(eBack));
- }
- Fl_Widget& CMenuBar1::GetWidget(void)
- {
- return *static_cast<Fl_Widget*>(this);
- }
- const Fl_Widget& CMenuBar1::GetWidget() const
- {
- return *static_cast<const Fl_Widget*>(this);
- }
- CRect CMenuBar1::GetPopupRect(void) const
- {
- int w = GetWidget().w();
- int h = GetWidget().h();
- return CRect(x(), y(), x() + w -1, y() + h - 1);
- }
- int CMenuBar1::handle(int event)
- {
- int res = x_Handle(event);
- return res ? res : Fl_Widget::handle(event);
- }
- int CMenuBar1::x_Handle(int event)
- {
- m_Tooltip.Handle(event);
- switch(event) {
- case FL_ENTER:
- case FL_MOVE:
- case FL_DRAG:
- case FL_PUSH:
- case FL_LEAVE: {
- CMenuItem* item = x_HitTest(Fl::event_x(), Fl::event_y());
- if(item && item->IsSeparator()) {
- item = NULL;
- }
- SetSelected(item);
-
- switch(event) {
- case FL_PUSH: {
- m_PushedItem = item;
- if(m_Selected && m_Selected->IsEnabledSubmenu()) {
- // FL_RELEASE for this FL_PUSH will be handled inside popup menu stub
- x_ShowSubMenu();
- // when we return from x_ShowSubMenu() it should not be considered pressed
- m_PushedItem = NULL;
- }
- GetWidget().redraw();
- }; break;
- case FL_ENTER:
- case FL_LEAVE: {
- redraw();
- }; break;
- };
- return 1;
- };
- case FL_RELEASE: {
- CMenuItem* item = x_HitTest(Fl::event_x(), Fl::event_y());
- if(item && item == m_PushedItem //&& Fl::event_is_click()
- && x_IsItemPushed()) {
- x_ExecuteCommand(*m_PushedItem);
- }
- m_PushedItem = NULL;
- GetWidget().redraw();
- return 1;
- }
- };
- return 0;
- }
- int CMenuBar1::x_HandleShortcuts(void)
- {
- char ch = tolower(Fl::event_key());
- TAccessKeyToItemMap::const_iterator it = m_AccessKeyToItem.find(ch);
-
- if(it != m_AccessKeyToItem.end()) {
- SetSelected(it->second);
- x_ShowSubMenu();
- return 1;
- }
- return 0;
- }
- void CMenuBar1::x_ShowSubMenu(void)
- {
- if(m_Selected->IsEnabled()) {
- if(m_Selected->IsSubmenu() && ! m_Selected->IsSubmenuEmpty()) { // show popup menu
- CPopupMenu1 popup(*this, m_RootItem, m_Selected, GetHintListener());
- popup.SetCmdTarget(GetCmdTarget());
- popup.Popup();
- SetSelected(NULL);
- }
- }
- }
- bool CMenuBar1::x_IsHorizontal(void) const
- {
- return true;
- }
- bool CMenuBar1::TC_NeedTooltip(int x, int y)
- {
- m_TooltipItem = x_HitTest(x, y);
- bool en = m_TooltipItem && ! m_TooltipItem->IsSeparator();
- return en;
- }
- string CMenuBar1::TC_GetTooltip(int& x, int& y, int& w, int& h)
- {
- _ASSERT(m_TooltipItem);
- CRect rc = x_GetPopupItemRect(*m_TooltipItem);
- x = rc.Left();
- y = rc.Top();
- w = rc.Width();
- h = rc.Height();
- return x_GetTooltip(*m_TooltipItem);
- }
- string CMenuBar1::x_GetTooltip(const CMenuItem& item) const
- {
- // find accelerator label if any
- string s_accel;
- ITERATE(TEntries, it, m_Entries) {
- if(it->m_Item == &item) {
- s_accel = it->m_AccelLabel;
- break;
- }
- }
- string label = item.GetLabel();
- string::size_type pos = label.find(kAccessKeyMarker); // find accelerator marker
- if(pos != string::npos && pos + 1 < label.size()) { // there is an accelerator
- label.erase(pos, 1);
- }
-
- if(s_accel.size()) {
- label += " (";
- label += s_accel + ")";
- }
- return label;
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: menu_window.cpp,v $
- * Revision 1000.0 2004/06/01 21:29:21 gouriano
- * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.7
- *
- * Revision 1.7 2004/05/21 22:27:53 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.6 2004/05/13 17:29:39 yazhuk
- * Added support for accelerators, keyboard activated menus
- *
- * Revision 1.5 2004/05/10 20:58:11 ucko
- * +<math.h> for ceil
- *
- * Revision 1.4 2004/05/10 16:25:40 yazhuk
- * Addressed GCC warnings
- *
- * Revision 1.3 2004/05/07 14:19:29 yazhuk
- * Added UpdateItems(), fixed focus handling
- *
- * Revision 1.2 2004/05/03 19:47:36 yazhuk
- * Refactoring; support for command updates
- *
- * Revision 1.1 2004/04/22 16:56:35 yazhuk
- * Initial revision
- *
- * ===========================================================================
- */