menu_window.cpp

来自「ncbi源码」· C++ 代码 · 共 1,678 行 · 第 1/4 页

CPP
1,678
字号
/* * =========================================================================== * 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////////////////////////////////////////////////////////////////////////////////// CMenuPropertiesCMenu::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 rightconst static int    kSubMarkerW = 12; // submenu marker widthconst static int    kBorderSize = 3; // menu borderconst static int    kSpace = 2; // spacing around icons, labelsconst static int    kAccelSpace = 8; // spacing between item label and accelerator labelconst static int    kItemOffsetY = 3;const static int    kItemOffsetX = 4; // horz spacing between items  const static int    kSubmenuOffsetX = 8; // horz spacing between submenusconst static int    kSeparatorSize = 1 + 2 * kItemOffsetX;const static char   kAccessKeyMarker = '&';const static double kMenuDelay = 0.4;////////////////////////////////////////////////////////////////////////////////// class CMenu - base class for all menusCMenu::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 originvoid    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 areavoid    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;

⌨️ 快捷键说明

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