void DebuggerManager::OnSettingsChanged(CodeBlocksEvent& event) { if (event.GetInt() == cbSettingsType::Compiler || event.GetInt() == cbSettingsType::Debugger) { if (m_useTargetsDefault) FindTargetsDebugger(); } }
void PythonDebugger::OnValueTooltip(CodeBlocksEvent& event) { event.Skip(); if (!m_DebuggerActive) return; if (!IsStopped()) return; EditorBase* base = event.GetEditor(); cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : 0; if (!ed) return; if(ed->IsContextMenuOpened()) { return; } // get rid of other calltips (if any) [for example the code completion one, at this time we // want the debugger value call/tool-tip to win and be shown] if(ed->GetControl()->CallTipActive()) { ed->GetControl()->CallTipCancel(); } const int style = event.GetInt(); if (style != wxSCI_P_DEFAULT && style != wxSCI_P_OPERATOR && style != wxSCI_P_IDENTIFIER && style != wxSCI_P_CLASSNAME) return; wxPoint pt; pt.x = event.GetX(); pt.y = event.GetY(); int pos = ed->GetControl()->PositionFromPoint(pt); int start = ed->GetControl()->WordStartPosition(pos, true); int end = ed->GetControl()->WordEndPosition(pos, true); while(ed->GetControl()->GetCharAt(start-1)==_T('.')) start=ed->GetControl()->WordStartPosition(start-2, true); wxString token; if (start >= ed->GetControl()->GetSelectionStart() && end <= ed->GetControl()->GetSelectionEnd()) { token = ed->GetControl()->GetSelectedText(); } else token = ed->GetControl()->GetTextRange(start,end); if (token.IsEmpty()) return; wxString cmd; cmd+=_T("pw ")+token+_T("\n"); DispatchCommands(cmd,DBGCMDTYPE_WATCHTOOLTIP,true); m_watch_tooltip_pos=pos; }
void cbDebuggerPlugin::ProcessValueTooltip(CodeBlocksEvent& event) { event.Skip(); if (cbDebuggerCommonConfig::GetFlag(cbDebuggerCommonConfig::RequireCtrlForTooltips)) { if (!wxGetKeyState(WXK_CONTROL)) return; } if (Manager::Get()->GetDebuggerManager()->GetInterfaceFactory()->IsValueTooltipShown()) return; if (!ShowValueTooltip(event.GetInt())) return; EditorBase* base = event.GetEditor(); cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : nullptr; if (!ed) return; if (ed->IsContextMenuOpened()) return; // get rid of other calltips (if any) [for example the code completion one, at this time we // want the debugger value call/tool-tip to win and be shown] if (ed->GetControl()->CallTipActive()) ed->GetControl()->CallTipCancel(); wxPoint pt; pt.x = event.GetX(); pt.y = event.GetY(); const wxString &token = GetEditorWordAtCaret(&pt); if (!token.empty()) { pt = ed->GetControl()->ClientToScreen(pt); OnValueTooltip(token, wxRect(pt.x - 5, pt.y, 10, 10)); } }
void SpellCheckerPlugin::OnEditorTooltip(CodeBlocksEvent& event) { if ( !IsAttached() || wxGetKeyState(WXK_CONTROL) || !(m_sccfg->GetEnableSpellTooltips() || m_sccfg->GetEnableThesaurusTooltips())) { event.Skip(); return; } EditorBase* base = event.GetEditor(); cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : 0; if ( !ed || ed->IsContextMenuOpened() || wxWindow::FindFocus() != static_cast<wxWindow*>(ed->GetControl()) ) { event.Skip(); return; } cbStyledTextCtrl* stc = ed->GetControl(); if (!stc) return; int pos = stc->PositionFromPointClose(event.GetX(), event.GetY()); if (pos < 0 || pos >= stc->GetLength()) { event.Skip(); return; } wxString tip; int wordstart = pos, wordend = pos; while (wordstart) { if ( m_pSpellHelper->IsWhiteSpace( stc->GetCharAt(wordstart - 1) ) ) break; --wordstart; } while ( wordend < stc->GetLength() ) { if ( m_pSpellHelper->IsWhiteSpace( stc->GetCharAt(++wordend) ) ) break; } int tipWidth = 0; if ( m_sccfg->GetEnableSpellTooltips() && m_pSpellChecker->IsInitialized() && stc->IndicatorValueAt(m_pOnlineChecker->GetIndicator(), pos)) { // indicator is on -> check if we can find a suggestion wxString misspelledWord = stc->GetTextRange(wordstart, wordend); m_suggestions = m_pSpellChecker->GetSuggestions(misspelledWord); if (!m_suggestions.IsEmpty()) { // allow maximum 12 entries in 3 rows int lineWidth = 0; for (size_t i = 0; i < 12 && i < m_suggestions.size(); ++i) { tip << m_suggestions[i]; lineWidth += m_suggestions[i].Length(); if (i % 4 == 3) { tip << wxT(",\n"); if (lineWidth > tipWidth) tipWidth = lineWidth; lineWidth = 0; } else { tip << wxT(", "); lineWidth += 2; } } tip.RemoveLast(2); lineWidth -= 2; if (lineWidth > tipWidth) // in case the last line was not full, and thereby not checked tipWidth = lineWidth; } } else if ( m_sccfg->GetEnableThesaurusTooltips() && m_pThesaurus->IsOk() && m_pSpellHelper->HasStyleToBeChecked(ed->GetColourSet()->GetLanguageName(ed->GetLanguage()), event.GetInt())) { wxString word = stc->GetTextRange(wordstart, wordend); synonyms syn = m_pThesaurus->GetSynonyms(word); if (!syn.size()) // if not found, try lower case syn = m_pThesaurus->GetSynonyms(word.Lower()); if (syn.size()) { wxArrayString usedSyns; // avoid duplicate synonyms // allow maximum 12 entries in 4 rows synonyms::iterator it = syn.begin(); for (size_t i = 0; i < 4 && it != syn.end(); ++i, ++it) { wxString tipLine(it->first + wxT(": ")); std::vector< wxString > syns = syn[it->first]; size_t j = 0; for (size_t k = 0; k < 3 && j < syns.size(); ++j, ++k) { if (usedSyns.Index(syns[j]) == wxNOT_FOUND) { tipLine << syns[j] << wxT(", "); usedSyns.Add(syns[j]); } else --k; // synonym already listed, look for another word } tipLine.RemoveLast(2); if (tipLine.Length() > static_cast<size_t>(tipWidth)) tipWidth = tipLine.Length(); tip << tipLine << wxT("\n"); } tip.RemoveLast(); } } if (tip.IsEmpty()) { event.Skip(); return; } if (stc->CallTipActive()) stc->CallTipCancel(); // calculation from CC const int lnStart = stc->PositionFromLine(stc->LineFromPosition(pos)); // pos - lnStart == distance from start of line // + tipWidth + 1 == projected virtual position of tip end (with a 1 character buffer) from start of line // - (width_of_editor_in_pixels / width_of_character) == distance tip extends past window edge // horizontal scrolling is accounted for by PointFromPosition().x const int offset = tipWidth + pos + 1 - lnStart - (stc->GetSize().x - stc->PointFromPosition(lnStart).x) / stc->TextWidth(wxSCI_STYLE_LINENUMBER, _T("W")); if (offset > 0) pos -= offset; if (pos < lnStart) // do not go to previous line if tip is wider than editor pos = lnStart; stc->CallTipShow(pos, tip); event.SetExtraLong(1); // notify CC not to cancel this tooltip event.Skip(); }
// cbEVT_SHOW_CALL_TIP void CCManager::OnShowCallTip(CodeBlocksEvent& event) { event.Skip(); cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor(); if (!ed) return; cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed); if (!ccPlugin) return; cbStyledTextCtrl* stc = ed->GetControl(); int pos = stc->GetCurrentPos(); int argsPos = wxSCI_INVALID_POSITION; wxString curTip; if (!m_CallTips.empty()) curTip = m_CurCallTip->tip; m_CallTips = ccPlugin->GetCallTips(pos, stc->GetStyleAt(pos), ed, argsPos); if (!m_CallTips.empty() && (event.GetInt() != FROM_TIMER || argsPos == m_CallTipActive)) { int lnStart = stc->PositionFromLine(stc->LineFromPosition(pos)); while (wxIsspace(stc->GetCharAt(lnStart))) ++lnStart; // do not show too far left on multi-line call tips if ( m_CallTips.size() > 1 && !Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadBool(wxT("multi_page_tips"), true) ) { wxString tip; int hlStart, hlEnd; hlStart = hlEnd = wxSCI_INVALID_POSITION; for (CallTipVec::const_iterator itr = m_CallTips.begin(); itr != m_CallTips.end(); ++itr) { if (hlStart == hlEnd && itr->hlStart != itr->hlEnd) { hlStart = tip.Length() + itr->hlStart; hlEnd = tip.Length() + itr->hlEnd; } tip += itr->tip + wxT('\n'); } m_CallTips.clear(); m_CallTips.push_back(cbCodeCompletionPlugin::CCCallTip(tip.RemoveLast(), hlStart, hlEnd)); } m_CurCallTip = m_CallTips.begin(); if (m_CallTips.size() > 1) { // search long term recall std::map<int, size_t>::const_iterator choiceItr = m_CallTipChoiceDict.find(CCManagerHelper::CallTipToInt(m_CurCallTip->tip, m_CallTips.size())); if (choiceItr != m_CallTipChoiceDict.end() && choiceItr->second < m_CallTips.size()) m_CurCallTip = m_CallTips.begin() + choiceItr->second; if (choiceItr == m_CallTipChoiceDict.end() || argsPos == m_CallTipActive) { int prefixEndPos = argsPos; while (prefixEndPos > 0 && wxIsspace(stc->GetCharAt(prefixEndPos - 1))) --prefixEndPos; const wxString& prefix = stc->GetTextRange(stc->WordStartPosition(prefixEndPos, true), prefixEndPos); choiceItr = m_CallTipFuzzyChoiceDict.find(CCManagerHelper::CallTipToInt(prefix, m_CallTips.size())); if (choiceItr != m_CallTipFuzzyChoiceDict.end() && choiceItr->second < m_CallTips.size()) m_CurCallTip = m_CallTips.begin() + choiceItr->second; } // search short term recall for (CallTipVec::const_iterator itr = m_CallTips.begin(); itr != m_CallTips.end(); ++itr) { if (itr->tip == curTip) { m_CurCallTip = itr; break; } } } m_CallTipActive = argsPos; DoUpdateCallTip(ed); } else if (m_CallTipActive != wxSCI_INVALID_POSITION) { static_cast<wxScintilla*>(stc)->CallTipCancel(); m_CallTipActive = wxSCI_INVALID_POSITION; } }
// 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; }
// cbEVT_COMPLETE_CODE void CCManager::OnCompleteCode(CodeBlocksEvent& event) { event.Skip(); cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor(); if (!ed) return; cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed); if (!ccPlugin) return; cbStyledTextCtrl* stc = ed->GetControl(); int tknEnd = stc->GetCurrentPos(); if (tknEnd == m_LastACLaunchState[lsCaretStart] && !m_AutocompTokens.empty()) { DoBufferedCC(stc); return; } int tknStart = stc->WordStartPosition(tknEnd, true); m_AutocompTokens = ccPlugin->GetAutocompList(event.GetInt() == FROM_TIMER, ed, tknStart, tknEnd); if (m_AutocompTokens.empty()) return; bool isPureAlphabetical = true; TokenSorter sortFunctor(isPureAlphabetical); std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor); if (isPureAlphabetical) stc->AutoCompSetOrder(wxSCI_ORDER_PRESORTED); else stc->AutoCompSetOrder(wxSCI_ORDER_CUSTOM); wxString items; // experimentally, the average length per token seems to be 23 for the main CC plugin items.Alloc(m_AutocompTokens.size() * 20); // TODO: measure performance for (size_t i = 0; i < m_AutocompTokens.size(); ++i) { items += m_AutocompTokens[i].displayName; if (m_AutocompTokens[i].category == -1) items += wxT("\r"); else items += F(wxT("\n%d\r"), m_AutocompTokens[i].category); } items.RemoveLast(); if (!stc->CallTipActive() && !stc->AutoCompActive()) m_CallTipActive = wxSCI_INVALID_POSITION; stc->AutoCompSetIgnoreCase(true); stc->AutoCompSetMaxHeight(14); stc->AutoCompSetTypeSeparator(wxT('\n')); stc->AutoCompSetSeparator(wxT('\r')); stc->AutoCompShow(tknEnd - tknStart, items); m_OwnsAutocomp = true; if (isPureAlphabetical) { const wxString& contextStr = stc->GetTextRange(tknStart, stc->WordEndPosition(tknEnd, true)); std::vector<cbCodeCompletionPlugin::CCToken>::const_iterator tknIt = std::lower_bound(m_AutocompTokens.begin(), m_AutocompTokens.end(), cbCodeCompletionPlugin::CCToken(-1, contextStr), sortFunctor); if (tknIt != m_AutocompTokens.end() && tknIt->displayName.StartsWith(contextStr)) stc->AutoCompSelect(tknIt->displayName); } m_LastACLaunchState[lsTknStart] = tknStart; m_LastACLaunchState[lsCaretStart] = tknEnd; }
void ToolsManager::OnToolTerminated(CodeBlocksEvent& event) { m_Pid = 0; m_pProcess = 0; Manager::Get()->GetLogManager()->Log(F(_T("Tool execution terminated with status %d"), event.GetInt())); }