Exemplo n.º 1
0
// cbEVT_EDITOR_TOOLTIP
void CCManager::OnEditorTooltip(CodeBlocksEvent& event)
{
    event.Skip();

    if (wxGetKeyState(WXK_CONTROL))
        return;

    EditorBase* base = event.GetEditor();
    cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : nullptr;
    if (!ed || ed->IsContextMenuOpened())
        return;

    cbStyledTextCtrl* stc = ed->GetControl();
    cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
    int pos = stc->PositionFromPointClose(event.GetX(), event.GetY());
    if (!ccPlugin || pos < 0 || pos >= stc->GetLength())
    {
        if (stc->CallTipActive() && event.GetExtraLong() == 0 && m_CallTipActive == wxSCI_INVALID_POSITION)
            static_cast<wxScintilla*>(stc)->CallTipCancel();
        return;
    }

    int hlStart, hlEnd, argsPos;
    hlStart = hlEnd = argsPos = wxSCI_INVALID_POSITION;
    bool allowCallTip = true;
    const std::vector<cbCodeCompletionPlugin::CCToken>& tokens = ccPlugin->GetTokenAt(pos, ed, allowCallTip);
    std::set<wxString> uniqueTips;
    for (size_t i = 0; i < tokens.size(); ++i)
        uniqueTips.insert(tokens[i].displayName);
    wxStringVec tips(uniqueTips.begin(), uniqueTips.end());

    const int style = event.GetInt();
    if (!tips.empty())
    {
        const int tknStart = stc->WordStartPosition(pos, true);
        const int tknEnd   = stc->WordEndPosition(pos,   true);
        if (tknEnd - tknStart > 2)
        {
            for (size_t i = 0; i < tips[0].Length(); ++i)
            {
                size_t hlLoc = tips[0].find(stc->GetTextRange(tknStart, tknEnd), i);
                if (hlLoc == wxString::npos)
                    break;
                hlStart = hlLoc;
                hlEnd = hlStart + tknEnd - tknStart;
                if (   (hlStart > 0 && (tips[0][hlStart - 1] == wxT('_') || wxIsalpha(tips[0][hlStart - 1])))
                    || (hlEnd < static_cast<int>(tips[0].Length()) - 1 && (tips[0][hlEnd] == wxT('_') || wxIsalpha(tips[0][hlEnd]))) )
                {
                    i = hlEnd;
                    hlStart = hlEnd = wxSCI_INVALID_POSITION;
                }
                else
                    break;
            }
        }
    }
    else if (  allowCallTip
             && !(   stc->IsString(style)
                  || stc->IsComment(style)
                  || stc->IsCharacter(style)
                  || stc->IsPreprocessor(style) ) )
    {
        const int line = stc->LineFromPosition(pos);
        if (pos + 4 > stc->PositionFromLine(line) + (int)ed->GetLineIndentString(line).Length())
        {
            const CallTipVec& cTips = ccPlugin->GetCallTips(pos, style, ed, argsPos);
            for (size_t i = 0; i < cTips.size(); ++i)
                tips.push_back(cTips[i].tip);
            if (!tips.empty())
            {
                hlStart = cTips[0].hlStart;
                hlEnd   = cTips[0].hlEnd;
            }
        }
    }
    if (tips.empty())
    {
        if (stc->CallTipActive() && event.GetExtraLong() == 0 && m_CallTipActive == wxSCI_INVALID_POSITION)
            static_cast<wxScintilla*>(stc)->CallTipCancel();
    }
    else
    {
        DoShowTips(tips, stc, pos, argsPos, hlStart, hlEnd);
        event.SetExtraLong(1);
    }
    m_CallTipActive = wxSCI_INVALID_POSITION;
}