//Copyright (c) Microsoft Corporation. All rights reserved.
// Connect.cpp : Implementation of CConnect
#include "stdafx.h"
#include "AddIn.h"
#include "Connect.h"
#include <string>
#include "metricdlg.h"
#include "funcmetricdlg.h"
#include <fstream>
#include "filegenerator.h"
#include "graphpreparator.h"
// CConnect
HRESULT CConnect::AddCommandsAndCommandBars()
{
HRESULT hr = S_OK;
CComPtr<EnvDTE::Commands> pCommands;
CComPtr<IDispatch> pDispatch;
hr = m_pDTE->get_Commands(&pCommands);
// create the toolbar
if (SUCCEEDED(hr))
{
CComPtr<EnvDTE::Command> pCreatedCommand;
hr = pCommands->Item(CComVariant(L"CCMetricViewer.Connect.CalculateMetrics"), 2, &pCreatedCommand);
if (SUCCEEDED(hr) && pCreatedCommand)
{
pCreatedCommand->Delete();
pCreatedCommand = NULL;
}
hr = pCommands->Item(CComVariant(L"CCMetricViewer.Connect.CalculateMetric"), 1, &pCreatedCommand);
if (SUCCEEDED(hr) && pCreatedCommand)
{
pCreatedCommand->Delete();
pCreatedCommand = NULL;
}
hr = pCommands->AddCommandBar(CComBSTR("Metric Viewer"), EnvDTE::vsCommandBarTypeToolbar, NULL, 0, &pDispatch);
// cast/QI the IDispatch for Office::CommandBar interface
CComQIPtr<Office::CommandBar> pMenuBarCommandBar = pDispatch;
CComPtr<Office::CommandBarControl> pCommandBarControl;
if (SUCCEEDED(hr))
{
hr = pCommands->AddNamedCommand(
m_pAddInInstance,
CComBSTR("CalculateMetric"),
CComBSTR("Calculate Metric"),
CComBSTR("Calculates the cyclomatic complexity metric for the currently selected function"),
VARIANT_FALSE,
IDB_LOGO_1,
NULL,
EnvDTE::vsCommandStatusSupported+EnvDTE::vsCommandStatusEnabled,
&pCreatedCommand);
if (SUCCEEDED(hr))
{
hr = pCreatedCommand->AddControl(pMenuBarCommandBar, 1, &pCommandBarControl);
if (SUCCEEDED(hr))
{
CComQIPtr<Office::_CommandBarButton> pButton(pCommandBarControl);
if (pButton)
pButton->put_Style(Office::msoButtonAutomatic);
}
}
pCreatedCommand.Release();
pCommandBarControl.Release();
// add the named commands and controls to the toolbar
hr = pCommands->AddNamedCommand(
m_pAddInInstance,
CComBSTR("CalculateMetrics"),
CComBSTR("Calculate All Metrics"),
CComBSTR("Calculates the cyclomatic complexity metric for each function in the loaded solution"),
VARIANT_FALSE,
IDB_LOGO_2,
NULL,
EnvDTE::vsCommandStatusSupported+EnvDTE::vsCommandStatusEnabled,
&pCreatedCommand);
if (SUCCEEDED(hr))
{
hr = pCreatedCommand->AddControl(pMenuBarCommandBar, 2, &pCommandBarControl);
if (SUCCEEDED(hr))
{
CComQIPtr<Office::_CommandBarButton> pButton(pCommandBarControl);
if (pButton)
pButton->put_Style(Office::msoButtonIcon);
}
}
//original place for: pMenuBarCommandBar->put_Visible(VARIANT_TRUE);
}
pMenuBarCommandBar->put_Visible(VARIANT_TRUE);
}
return S_OK;
}
HRESULT CConnect::RemoveCommandsAndCommandBars()
{
HRESULT hr = S_OK;
CComPtr<EnvDTE::Commands> pCommands;
CComPtr<Office::_CommandBars> pCommandBars;
hr = m_pDTE->get_Commands(&pCommands);
if(FAILED(hr))
return hr;
hr = m_pDTE->get_CommandBars(&pCommandBars);
if(FAILED(hr))
return hr;
CComPtr<EnvDTE::Command> pCreatedCommand;
CComPtr<Office::CommandBar> pMenuBarCommandBar;
CComPtr<Office::CommandBarControl> pCommandBarControl;
if (SUCCEEDED(pCommandBars->get_Item(CComVariant("Tools"),&pMenuBarCommandBar)))
{
// remove the named commands
if (SUCCEEDED(pCommands->Item(CComVariant("CCMetricViewer.Connect.CalculateMetrics"), 2, &pCreatedCommand)))
{
pCreatedCommand->AddControl(pMenuBarCommandBar, 1, &pCommandBarControl);
pCreatedCommand->Delete();
pCreatedCommand.Release();
pCommandBarControl.Release();
}
if (SUCCEEDED(pCommands->Item(CComVariant("CCMetricViewer.Connect.CalculateMetric"), 1, &pCreatedCommand)))
{
pCreatedCommand->AddControl(pMenuBarCommandBar, 1, &pCommandBarControl);
pCreatedCommand->Delete();
pCreatedCommand.Release();
pCommandBarControl.Release();
}
pMenuBarCommandBar.Release();
}
// remove the toolbar
if (SUCCEEDED(pCommandBars->get_Item(CComVariant("Metric Viewer"),&pMenuBarCommandBar)))
{
hr = pCommands->RemoveCommandBar(pMenuBarCommandBar);
hr = pMenuBarCommandBar->Delete();
}
return S_OK;
}
STDMETHODIMP CConnect::OnConnection(IDispatch *pApplication, AddInDesignerObjects::ext_ConnectMode ConnectMode, IDispatch *pAddInInst, SAFEARRAY ** /*custom*/ )
{
HRESULT hr = S_OK;
pApplication->QueryInterface(__uuidof(EnvDTE::_DTE), (LPVOID*)&m_pDTE);
pAddInInst->QueryInterface(__uuidof(EnvDTE::AddIn), (LPVOID*)&m_pAddInInstance);
if(ConnectMode == 5) //5 == AddInDesignerObjects::ext_cm_UISetup
{
// add named commands and toolbars
hr = AddCommandsAndCommandBars();
if (FAILED(hr))
{
// clean up if something went wrong
hr = RemoveCommandsAndCommandBars();
return hr;
}
}
CComPtr<Office::_CommandBars> pCommandBars;
CComPtr<Office::CommandBar> pMenuBarCommandBar;
if (SUCCEEDED(m_pDTE->get_CommandBars(&pCommandBars)))
{
if (SUCCEEDED(pCommandBars->get_Item(CComVariant("Metric Viewer"),&pMenuBarCommandBar)))
{
pMenuBarCommandBar->put_Visible(VARIANT_TRUE);
}
}
return S_OK;
}
STDMETHODIMP CConnect::OnDisconnection(AddInDesignerObjects::ext_DisconnectMode /*RemoveMode*/, SAFEARRAY ** /*custom*/ )
{
CComPtr<Office::_CommandBars> pCommandBars;
CComPtr<Office::CommandBar> pMenuBarCommandBar;
if (SUCCEEDED(m_pDTE->get_CommandBars(&pCommandBars)))
{
if (SUCCEEDED(pCommandBars->get_Item(CComVariant("Metric Viewer"),&pMenuBarCommandBar)))
pMenuBarCommandBar->put_Visible(VARIANT_FALSE);
}
m_pDTE = NULL;
return S_OK;
}
STDMETHODIMP CConnect::OnAddInsUpdate (SAFEARRAY ** /*custom*/ )
{
return S_OK;
}
STDMETHODIMP CConnect::OnStartupComplete (SAFEARRAY ** /*custom*/ )
{
return S_OK;
}
STDMETHODIMP CConnect::OnBeginShutdown (SAFEARRAY ** /*custom*/ )
{
CComPtr<Office::_CommandBars> pCommandBars;
CComPtr<Office::CommandBar> pMenuBarCommandBar;
if (SUCCEEDED(m_pDTE->get_CommandBars(&pCommandBars)))
{
if (SUCCEEDED(pCommandBars->get_Item(CComVariant("Metric Viewer"),&pMenuBarCommandBar)))
pMenuBarCommandBar->put_Visible(VARIANT_FALSE);
}
return S_OK;
}
STDMETHODIMP CConnect::QueryStatus(BSTR bstrCmdName, EnvDTE::vsCommandStatusTextWanted NeededText, EnvDTE::vsCommandStatus* pStatusOption, VARIANT* pvarCommandText)
{
if (NeededText == EnvDTE::vsCommandStatusTextWantedNone)
{
if (!_wcsicmp(bstrCmdName, L"CCMetricViewer.Connect.CalculateMetric"))
*pStatusOption = (EnvDTE::vsCommandStatus)(EnvDTE::vsCommandStatusEnabled | EnvDTE::vsCommandStatusSupported);
if (!_wcsicmp(bstrCmdName, L"CCMetricViewer.Connect.CalculateMetrics"))
*pStatusOption = (EnvDTE::vsCommandStatus)(EnvDTE::vsCommandStatusEnabled | EnvDTE::vsCommandStatusSupported);
}
return S_OK;
}
STDMETHODIMP CConnect::Exec(BSTR bstrCmdName, EnvDTE::vsCommandExecOption ExecuteOption, VARIANT* /*pvarVariantIn*/, VARIANT* /*pvarVariantOut*/, VARIANT_BOOL* pvbHandled)
{
*pvbHandled = VARIANT_FALSE;
if (ExecuteOption == EnvDTE::vsCommandExecOptionDoDefault)
{
if (!_wcsicmp(bstrCmdName, L"CCMetricViewer.Connect.CalculateMetrics"))
{
ObtainSolutionData();
CMetricDlg dlg;
dlg.LoadData(metric_data, CW2A(LPCWSTR(explorer->GetSolutionName())));
dlg.DoModal();
*pvbHandled = VARIANT_TRUE;
return S_OK;
}
if (!_wcsicmp(bstrCmdName, L"CCMetricViewer.Connect.CalculateMetric"))
{
int value;
CComBSTR name;
if (ObtainSelectedFuncMetric(value, name))
{
/* DrawGraph(std::wstring(LPCWSTR(name)));
CComPtr<EnvDTE::Windows> pWindows;
CComPtr<IDispatch> pCtrlObject;
CComPtr<EnvDTE::Window> pWindow;
m_pDTE->get_Windows(&pWindows);
pWindows->CreateToolWindow(m_pAddInInstance, CComBSTR("GraphViewer.CGraphViewerCtrl.1"), CComBSTR("CCM Graph"), CComBSTR("{DA8D1868-9ADC-4B6F-8400-DC92BD73EC63}"), &pCtrlObject, &pWindow);
pWindow->put_Visible(VARIANT_TRUE);
*/ CFuncMetricDlg dlg;
dlg.LoadData(value, name, L"");
dlg.DoModal();
}
*pvbHandled = VARIANT_TRUE;
return S_OK;
}
}
return S_OK;
}
void CConnect::ObtainSolutionData()
{
explorer = new SolutionExplorer(m_pDTE);
long num_projects = explorer->GetProjectCount();
//Go through each project in the solution
for (long i = 1; i <= num_projects; i++)
{
if (explorer->SetProject(i))
{
metric_data = explorer->GetMetrics();
#ifdef _DEBUG
CGraphPreparator debugger;
debugger.WriteVector("output.txt");
#endif
explorer->ReleaseProject();
}
}
}
bool CConnect::ObtainSelectedFuncMetric(int& value, CComBSTR& name)
{
explorer = new SolutionExplorer(m_pDTE);
CComBSTR text;
if (explorer->GetFunctionText(text))
{
const wchar_t* w_bodytext = LPCWSTR(text);
name = explorer->GetFunctionName(const_cast<wchar_t*>(w_bodytext));
value = explorer->GetMetric(w_bodytext);
return true;
}
else
return false;
}
bool CConnect::DrawGraph(std::wstring& filename)
{
string name = "\\.\\output.dot";
CFileGenerator filebuilder(name);
filebuilder.WriteFile();
wstring parameter = L"-Tpng ";
parameter += reinterpret_cast<const wchar_t*>(name.c_str());
parameter += L" -o ";
parameter += filename;
if (!ShellExecute(NULL, L"open", L"dot.exe", parameter.c_str(), L"C:\\", SW_HIDE))
return false;
return true;
}