toolbar.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 890 行 · 第 1/2 页

CPP
890
字号
/////////////////////////////////////////////////////////////////////////////
// Name:        src/univ/toolbar.cpp
// Purpose:     implementation of wxToolBar for wxUniversal
// Author:      Robert Roebling, Vadim Zeitlin (universalization)
// Modified by:
// Created:     20.02.02
// Id:          $Id: toolbar.cpp,v 1.34.2.2 2006/03/11 14:49:23 JS Exp $
// Copyright:   (c) 2001 Robert Roebling,
//              (c) 2002 SciTech Software, Inc. (www.scitechsoft.com)
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declarations
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
    #pragma implementation "univtoolbar.h"
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#if wxUSE_TOOLBAR

#ifndef WX_PRECOMP
    #include "wx/utils.h"
    #include "wx/app.h"
#endif

#include "wx/univ/renderer.h"

#include "wx/frame.h"
#include "wx/toolbar.h"
#include "wx/image.h"
#include "wx/log.h"

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

// value meaning that m_widthSeparator is not initialized
static const wxCoord INVALID_WIDTH = wxDefaultCoord;

// ----------------------------------------------------------------------------
// wxToolBarTool: our implementation of wxToolBarToolBase
// ----------------------------------------------------------------------------

class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
{
public:
    wxToolBarTool(wxToolBar *tbar,
                  int id,
                  const wxString& label,
                  const wxBitmap& bmpNormal,
                  const wxBitmap& bmpDisabled,
                  wxItemKind kind,
                  wxObject *clientData,
                  const wxString& shortHelp,
                  const wxString& longHelp)
        : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
                            clientData, shortHelp, longHelp)
    {
        // no position yet
        m_x =
        m_y = wxDefaultCoord;
        m_width =
        m_height = 0;

        // not pressed yet
        m_isInverted = false;

        // mouse not here yet
        m_underMouse = false;
    }

    wxToolBarTool(wxToolBar *tbar, wxControl *control)
        : wxToolBarToolBase(tbar, control)
    {
        // no position yet
        m_x =
        m_y = wxDefaultCoord;
        m_width =
        m_height = 0;

        // not pressed yet
        m_isInverted = false;

        // mouse not here yet
        m_underMouse = false;
    }

    // is this tool pressed, even temporarily? (this is different from being
    // permanently toggled which is what IsToggled() returns)
    bool IsPressed() const
        { return CanBeToggled() ? IsToggled() != m_isInverted : m_isInverted; }

    // are we temporarily pressed/unpressed?
    bool IsInverted() const { return m_isInverted; }

    // press the tool temporarily by inverting its toggle state
    void Invert() { m_isInverted = !m_isInverted; }

    // Set underMouse
    void SetUnderMouse( bool under = true ) { m_underMouse = under; }
    bool IsUnderMouse() { return m_underMouse; }

public:
    // the tool position (for controls)
    wxCoord m_x;
    wxCoord m_y;
    wxCoord m_width;
    wxCoord m_height;

private:
    // true if the tool is pressed
    bool m_isInverted;

    // true if the tool is under the mouse
    bool m_underMouse;
};

// ============================================================================
// wxToolBar implementation
// ============================================================================

IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl);

// ----------------------------------------------------------------------------
// wxToolBar creation
// ----------------------------------------------------------------------------

void wxToolBar::Init()
{
    // no tools yet
    m_needsLayout = false;

    // unknown widths for the tools and separators
    m_widthSeparator = INVALID_WIDTH;

    m_maxWidth =
    m_maxHeight = 0;

    wxRenderer *renderer = GetRenderer();

    SetToolBitmapSize(renderer->GetToolBarButtonSize(&m_widthSeparator));
    SetMargins(renderer->GetToolBarMargin());
}

bool wxToolBar::Create(wxWindow *parent,
                       wxWindowID id,
                       const wxPoint& pos,
                       const wxSize& size,
                       long style,
                       const wxString& name)
{
    if ( !wxToolBarBase::Create(parent, id, pos, size, style,
                                wxDefaultValidator, name) )
    {
        return false;
    }

    CreateInputHandler(wxINP_HANDLER_TOOLBAR);

    SetBestSize(size);

    return true;
}

wxToolBar::~wxToolBar()
{
    // Make sure the toolbar is removed from the parent.
    SetSize(0,0);
}

void wxToolBar::SetMargins(int x, int y)
{
    // This required for similar visual effects under
    // native platforms and wxUniv.
    wxToolBarBase::SetMargins( x + 3, y + 3 );
}

// ----------------------------------------------------------------------------
// wxToolBar tool-related methods
// ----------------------------------------------------------------------------

wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
{
    // check the "other" direction first: it must be inside the toolbar or we
    // don't risk finding anything
    if ( IsVertical() )
    {
        if ( x < 0 || x > m_maxWidth )
            return NULL;

        // we always use x, even for a vertical toolbar, this makes the code
        // below simpler
        x = y;
    }
    else // horizontal
    {
        if ( y < 0 || y > m_maxHeight )
            return NULL;
    }

    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
          node;
          node = node->GetNext() )
    {
        wxToolBarToolBase *tool =  node->GetData();
        wxRect rectTool = GetToolRect(tool);

        wxCoord startTool, endTool;
        GetRectLimits(rectTool, &startTool, &endTool);

        if ( x >= startTool && x <= endTool )
        {
            // don't return the separators from here, they don't accept any
            // input anyhow
            return tool->IsSeparator() ? NULL : tool;
        }
    }

    return NULL;
}

void wxToolBar::SetToolShortHelp(int id, const wxString& help)
{
    wxToolBarToolBase *tool = FindById(id);

    wxCHECK_RET( tool, _T("SetToolShortHelp: no such tool") );

    tool->SetShortHelp(help);
}

bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
                             wxToolBarToolBase * WXUNUSED(tool))
{
    // recalculate the toolbar geometry before redrawing it the next time
    m_needsLayout = true;

    // and ensure that we indeed are going to redraw
    Refresh();

    return true;
}

bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
                             wxToolBarToolBase * WXUNUSED(tool))
{
    // as above
    m_needsLayout = true;

    Refresh();

    return true;
}

void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
{
    // created disabled-state bitmap on demand
    if ( !enable && !tool->GetDisabledBitmap().Ok() )
    {
        wxImage image( tool->GetNormalBitmap().ConvertToImage() );

        // TODO: don't hardcode 180
        unsigned char bg_red = 180;
        unsigned char bg_green = 180;
        unsigned char bg_blue = 180;

        unsigned char mask_red = image.GetMaskRed();
        unsigned char mask_green = image.GetMaskGreen();
        unsigned char mask_blue = image.GetMaskBlue();

        bool has_mask = image.HasMask();

        int x,y;
        for (y = 0; y < image.GetHeight(); y++)
        {
            for (x = 0; x < image.GetWidth(); x++)
            {
                unsigned char red = image.GetRed(x,y);
                unsigned char green = image.GetGreen(x,y);
                unsigned char blue = image.GetBlue(x,y);
                if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
                {
                    red = (unsigned char)((((wxInt32) red  - bg_red) >> 1) + bg_red);
                    green = (unsigned char)((((wxInt32) green  - bg_green) >> 1) + bg_green);
                    blue = (unsigned char)((((wxInt32) blue  - bg_blue) >> 1) + bg_blue);
                    image.SetRGB( x, y, red, green, blue );
                }
            }
        }

        for (y = 0; y < image.GetHeight(); y++)
        {
            for (x = y % 2; x < image.GetWidth(); x += 2)
            {
                unsigned char red = image.GetRed(x,y);
                unsigned char green = image.GetGreen(x,y);
                unsigned char blue = image.GetBlue(x,y);
                if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
                {
                    red = (unsigned char)((((wxInt32) red  - bg_red) >> 1) + bg_red);
                    green = (unsigned char)((((wxInt32) green  - bg_green) >> 1) + bg_green);
                    blue = (unsigned char)((((wxInt32) blue  - bg_blue) >> 1) + bg_blue);
                    image.SetRGB( x, y, red, green, blue );
                }
            }
        }

        tool->SetDisabledBitmap(image);
    }

    RefreshTool(tool);
}

void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
{
    // note that if we're called the tool did change state (the base class
    // checks for it), so it's not necessary to check for this again here
    RefreshTool(tool);
}

void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
{
    RefreshTool(tool);
}

wxToolBarToolBase *wxToolBar::CreateTool(int id,
                                         const wxString& label,
                                         const wxBitmap& bmpNormal,
                                         const wxBitmap& bmpDisabled,
                                         wxItemKind kind,
                                         wxObject *clientData,
                                         const wxString& shortHelp,
                                         const wxString& longHelp)
{
    return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
                             clientData, shortHelp, longHelp);
}

wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
{
    return new wxToolBarTool(this, control);
}

// ----------------------------------------------------------------------------
// wxToolBar geometry
// ----------------------------------------------------------------------------

wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
{
    const wxToolBarTool *tool = (wxToolBarTool *)toolBase;

    wxRect rect;

    wxCHECK_MSG( tool, rect, _T("GetToolRect: NULL tool") );

    // ensure that we always have the valid tool position
    if ( m_needsLayout )
    {
        wxConstCast(this, wxToolBar)->DoLayout();
    }

    rect.x = tool->m_x - m_xMargin;
    rect.y = tool->m_y - m_yMargin;

    if ( IsVertical() )
    {
        if (tool->IsButton())
        {
            rect.width = m_defaultWidth;
            rect.height = m_defaultHeight;
        }
        else if (tool->IsSeparator())
        {
            rect.width = m_defaultWidth;
            rect.height = m_widthSeparator;
        }
        else // control
        {
            rect.width = tool->m_width;
            rect.height = tool->m_height;
        }
    }
    else // horizontal
    {
        if (tool->IsButton())
        {
            rect.width = m_defaultWidth;
            rect.height = m_defaultHeight;
        }
        else if (tool->IsSeparator())
        {
            rect.width = m_widthSeparator;
            rect.height = m_defaultHeight;
        }
        else // control
        {
            rect.width = tool->m_width;
            rect.height = tool->m_height;
        }
    }

    rect.width += 2*m_xMargin;
    rect.height += 2*m_yMargin;

    return rect;
}

bool wxToolBar::Realize()
{
    if ( !wxToolBarBase::Realize() )
        return false;

    m_needsLayout = true;
    DoLayout();

    SetBestSize(wxDefaultSize);

    return true;
}

void wxToolBar::DoLayout()
{
    wxASSERT_MSG( m_needsLayout, _T("why are we called?") );

    m_needsLayout = false;

    wxCoord x = m_xMargin,
            y = m_yMargin;

    const wxCoord widthTool = IsVertical() ? m_defaultHeight : m_defaultWidth;
    wxCoord margin = IsVertical() ? m_xMargin : m_yMargin;
    wxCoord *pCur = IsVertical() ? &y : &x;

⌨️ 快捷键说明

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