toolbar.cpp

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

CPP
890
字号
    // calculate the positions of all elements
    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
          node;
          node = node->GetNext() )
    {
        wxToolBarTool *tool = (wxToolBarTool *) node->GetData();

        tool->m_x = x;
        tool->m_y = y;

        // TODO ugly number fiddling
        if (tool->IsButton())
        {
            *pCur += widthTool;
        }
        else if (tool->IsSeparator())
        {
            *pCur += m_widthSeparator;
        }
        else if (!IsVertical()) // horizontal control
        {
            wxControl *control = tool->GetControl();
            wxSize size = control->GetSize();
            tool->m_y += (m_defaultHeight - size.y)/2;
            tool->m_width = size.x;
            tool->m_height = size.y;

            *pCur += tool->m_width;
        }
        *pCur += margin;
    }

    // calculate the total toolbar size
    wxCoord xMin = m_defaultWidth + 2*m_xMargin,
            yMin = m_defaultHeight + 2*m_yMargin;

    m_maxWidth = x < xMin ? xMin : x;
    m_maxHeight = y < yMin ? yMin : y;
}

wxSize wxToolBar::DoGetBestClientSize() const
{
    return wxSize(m_maxWidth, m_maxHeight);
}

void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
    int old_width, old_height;
    GetSize(&old_width, &old_height);

    wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);

    // Correct width and height if needed.
    if ( width == wxDefaultCoord || height == wxDefaultCoord )
    {
        int tmp_width, tmp_height;
        GetSize(&tmp_width, &tmp_height);

        if ( width == wxDefaultCoord )
            width = tmp_width;
        if ( height == wxDefaultCoord )
            height = tmp_height;
    }

    // We must refresh the frame size when the toolbar changes size
    // otherwise the toolbar can be shown incorrectly
    if ( old_width != width || old_height != height )
    {
        // But before we send the size event check it
        // we have a frame that is not being deleted.
        wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
        if ( frame && !frame->IsBeingDeleted() )
        {
            frame->SendSizeEvent();
        }
    }
}

// ----------------------------------------------------------------------------
// wxToolBar drawing
// ----------------------------------------------------------------------------

void wxToolBar::RefreshTool(wxToolBarToolBase *tool)
{
    RefreshRect(GetToolRect(tool));
}

void wxToolBar::GetRectLimits(const wxRect& rect,
                              wxCoord *start,
                              wxCoord *end) const
{
    wxCHECK_RET( start && end, _T("NULL pointer in GetRectLimits") );

    if ( IsVertical() )
    {
        *start = rect.GetTop();
        *end = rect.GetBottom();
    }
    else // horizontal
    {
        *start = rect.GetLeft();
        *end = rect.GetRight();
    }
}

void wxToolBar::DoDraw(wxControlRenderer *renderer)
{
    // prepare the variables used below
    wxDC& dc = renderer->GetDC();
    wxRenderer *rend = renderer->GetRenderer();
    // dc.SetFont(GetFont()); -- uncomment when we support labels

    // draw the border separating us from the menubar (if there is no menubar
    // we probably shouldn't draw it?)
    if ( !IsVertical() )
    {
        rend->DrawHorizontalLine(dc, 0, 0, GetClientSize().x);
    }

    // get the update rect and its limits depending on the orientation
    wxRect rectUpdate = GetUpdateClientRect();
    wxCoord start, end;
    GetRectLimits(rectUpdate, &start, &end);

    // and redraw all the tools intersecting it
    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
          node;
          node = node->GetNext() )
    {
        wxToolBarTool *tool = (wxToolBarTool*) node->GetData();
        wxRect rectTool = GetToolRect(tool);
        wxCoord startTool, endTool;
        GetRectLimits(rectTool, &startTool, &endTool);

        if ( endTool < start )
        {
            // we're still to the left of the area to redraw
            continue;
        }

        if ( startTool > end )
        {
            // we're beyond the area to redraw, nothing left to do
            break;
        }

        if (tool->IsSeparator() && !HasFlag(wxTB_FLAT))
        {
            // Draw separators only in flat mode
            continue;
        }

        // deal with the flags
        int flags = 0;

        if ( tool->IsEnabled() )
        {
            // The toolbars without wxTB_FLAT don't react to the mouse hovering
            if ( !HasFlag(wxTB_FLAT) || tool->IsUnderMouse() )
                flags |= wxCONTROL_CURRENT;
        }
        else // disabled tool
        {
            flags |= wxCONTROL_DISABLED;
        }

        //if ( tool == m_toolCaptured )
        //    flags |= wxCONTROL_FOCUSED;

        if ( tool->IsPressed() )
            flags = wxCONTROL_PRESSED;

        wxString label;
        wxBitmap bitmap;
        if ( !tool->IsSeparator() )
        {
            // label = tool->GetLabel();
            bitmap = tool->GetBitmap();
        }
        //else: leave both the label and the bitmap invalid to draw a separator

        if ( !tool->IsControl() )
        {
            rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags, tool->GetStyle());
        }
        else // control
        {
            wxControl *control = tool->GetControl();
            control->Move(tool->m_x, tool->m_y);
        }
    }
}

// ----------------------------------------------------------------------------
// wxToolBar actions
// ----------------------------------------------------------------------------

bool wxToolBar::PerformAction(const wxControlAction& action,
                              long numArg,
                              const wxString& strArg)
{
    wxToolBarTool *tool = (wxToolBarTool*) FindById(numArg);
    if (!tool)
        return false;

    if ( action == wxACTION_TOOLBAR_TOGGLE )
    {
        PerformAction( wxACTION_BUTTON_RELEASE, numArg );

        PerformAction( wxACTION_BUTTON_CLICK, numArg );
                        
        // Write by Danny Raynor to change state again.                
        // Check button still pressed or not
        if( tool->IsInverted() )
        {        
            PerformAction( wxACTION_TOOLBAR_RELEASE, numArg );      
        }
    
        // Set mouse leave toolbar button range (If still in the range,
        // toolbar button would get focus again
        PerformAction( wxACTION_TOOLBAR_LEAVE, numArg );
    }
    else if ( action == wxACTION_TOOLBAR_PRESS )
    {
        wxLogTrace(_T("toolbar"), _T("Button '%s' pressed."), tool->GetShortHelp().c_str());

        tool->Invert();

        RefreshTool( tool );
    }
    else if ( action == wxACTION_TOOLBAR_RELEASE )
    {
        wxLogTrace(_T("toolbar"), _T("Button '%s' released."), tool->GetShortHelp().c_str());

        wxASSERT_MSG( tool->IsInverted(), _T("release unpressed button?") );

        tool->Invert();

        RefreshTool( tool );
    }
    else if ( action == wxACTION_TOOLBAR_CLICK )
    {
        bool isToggled;
        if ( tool->CanBeToggled() )
        {
            tool->Toggle();

            RefreshTool( tool );

            isToggled = tool->IsToggled();
        }
        else // simple non-checkable tool
        {
            isToggled = false;
        }
        OnLeftClick( tool->GetId(), isToggled );
    }
    else if ( action == wxACTION_TOOLBAR_ENTER )
    {
        wxCHECK_MSG( tool, false, _T("no tool to enter?") );

        if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
        {
            tool->SetUnderMouse( true );

            if ( !tool->IsToggled() )
                RefreshTool( tool );
        }
    }
    else if ( action == wxACTION_TOOLBAR_LEAVE )
    {
        wxCHECK_MSG( tool, false, _T("no tool to leave?") );

        if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
        {
            tool->SetUnderMouse( false );

            if ( !tool->IsToggled() )
                RefreshTool( tool );
        }
    }
    else
        return wxControl::PerformAction(action, numArg, strArg);

    return true;
}

// ============================================================================
// wxStdToolbarInputHandler implementation
// ============================================================================

wxStdToolbarInputHandler::wxStdToolbarInputHandler(wxInputHandler *handler)
                        : wxStdInputHandler(handler)
{
    m_winCapture = NULL;
    m_toolCapture = NULL;
    m_toolLast = NULL;
}

bool wxStdToolbarInputHandler::HandleKey(wxInputConsumer *consumer,
                                         const wxKeyEvent& event,
                                         bool pressed)
{
    // TODO: when we have a current button we should allow the arrow
    //       keys to move it
    return wxStdInputHandler::HandleKey(consumer, event, pressed);
}

bool wxStdToolbarInputHandler::HandleMouse(wxInputConsumer *consumer,
                                           const wxMouseEvent& event)
{
    wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
    wxToolBarToolBase *tool = tbar->FindToolForPosition(event.GetX(), event.GetY());

    if ( event.Button(1) )
    {

        if ( event.LeftDown() || event.LeftDClick() )
        {
            if ( !tool || !tool->IsEnabled() )
                return true;

            m_winCapture = tbar;
            m_winCapture->CaptureMouse();

            m_toolCapture = tool;

            consumer->PerformAction( wxACTION_BUTTON_PRESS, tool->GetId() );

            return true;
        }
        else if ( event.LeftUp() )
        {
            if ( m_winCapture )
            {
                m_winCapture->ReleaseMouse();
                m_winCapture = NULL;
            }

            if (m_toolCapture)
            {
                if ( tool == m_toolCapture )
                    consumer->PerformAction( wxACTION_BUTTON_TOGGLE, m_toolCapture->GetId() );
                else
                    consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
            }

            m_toolCapture = NULL;

            return true;
        }
        //else: don't do anything special about the double click
    }

    return wxStdInputHandler::HandleMouse(consumer, event);
}

bool wxStdToolbarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
                                               const wxMouseEvent& event)
{
    if ( !wxStdInputHandler::HandleMouseMove(consumer, event) )
    {
        wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);

        wxToolBarTool *tool;
        if ( event.Leaving() )
        {
            // We cannot possibly be over a tool when
            // leaving the toolbar
            tool = NULL;
        }
        else
        {
            tool = (wxToolBarTool*) tbar->FindToolForPosition( event.GetX(), event.GetY() );
        }

        if (m_toolCapture)
        {
            // During capture we only care of the captured tool
            if (tool && (tool != m_toolCapture))
                tool = NULL;

            if (tool == m_toolLast)
                return true;

            if (tool)
                consumer->PerformAction( wxACTION_BUTTON_PRESS, m_toolCapture->GetId() );
            else
                consumer->PerformAction( wxACTION_BUTTON_RELEASE, m_toolCapture->GetId() );

            m_toolLast = tool;
        }
        else
        {
            if (tool == m_toolLast)
               return true;

            if (m_toolLast)
            {
                // Leave old tool if any
                consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolLast->GetId() );
            }

            if (tool)
            {
                // Enter new tool if any
                consumer->PerformAction( wxACTION_TOOLBAR_ENTER, tool->GetId() );
            }

            m_toolLast = tool;
        }

        return true;
    }

    return false;
}

bool wxStdToolbarInputHandler::HandleFocus(wxInputConsumer *consumer,
                                           const wxFocusEvent& WXUNUSED(event))
{
    if ( m_toolCapture )
    {
        // We shouldn't be left with a highlighted button
        consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
    }

    return true;
}

bool wxStdToolbarInputHandler::HandleActivation(wxInputConsumer *consumer,
                                                bool activated)
{
    if (m_toolCapture && !activated)
    {
        // We shouldn't be left with a highlighted button
        consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
    }

    return true;
}

#endif // wxUSE_TOOLBAR

⌨️ 快捷键说明

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