#include "AnalyseGui.h" #include "Analyse.h" #define IMAGECLASS Images #define IMAGEFILE #include String defaultCode = "/*" " This tool measures certain source code metrics.\n" " You can type, paste, or load the code you would like measure into this text area.\n" " Metrics provided are:\n" " - Cyclomatic complexity 1: counts the decision points per method, thus estimating the\n" " number of testcases needed for each method.\n" " - Cyclomatic complexity 2: CC1 extended with the implicit decisions created by the\n" " && || and ?: operators. Evaluation:\n" " CC2 1-10 simple, low risk method\n" " CC2 10-20 moderate complexity & risk method\n" " CC2 21-50 high complexity & risk method\n" " CC2 >50 too complex, untestable method, should be refactored\n" " - Depth: measures deepest scope embedding level per method. This estimates the human\n" " memory needed to keep in mind the current context. Any methods with depth > 5 is\n" " considered too complex, and candidate for refactoring\n" " - Logical Lines Of Code: estimates the amount of source code per method in a way\n" " which is mostly independent from code formatting style. Methods longer than 80 LLOC are\n" " too long, and should be refactored.\n" "*/\n" "int main()\n" "{\n" " return 0;\n" "}\n"; String defaultTitle = "CodeMetric GUI"; WarningDisplay::WarningDisplay(int limit, Color warningColor) : limit(limit), warningColor(warningColor) { } void WarningDisplay::PaintBackground(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const { int v = (int)q; if(v >= limit) paper = warningColor; Display::PaintBackground(w, r, q, ink, paper, style); } void AnalyseGui::MainMenu(Bar &bar) { bar.Add("Load file", THISBACK(Open)); } void AnalyseGui::Open() { FileSelector fsel; fsel.ExecuteOpen("Select file"); String fileName = fsel.Get(); if(fileName == "") return; source <<= LoadFile(fileName); UpdateMetric(); Title(defaultTitle + " [" + fileName + "]"); } void AnalyseGui::UpdateMetric() { String s = ~source; CodeMetric metric(s); chart.Clear(); for(int i = 0; i < metric.functions.GetCount(); i++) { CodeMetric::FunctionEntry & entry = metric.functions[i]; chart.Add(entry.name, entry.pos, entry.cyclomaticComplexity1, entry.cyclomaticComplexity2, entry.logicalLinesOfCode, entry.scopeDepth); } textMetric.SetData(metric.ToString()); } void AnalyseGui::GotoFunction() { int cursor = chart.GetCursor(); if(cursor >= 0 && cursor < chart.GetCount()) { int pos = (int)chart.Get(cursor, 1); source.SetCursor( source.GetPos(pos) ); source.CenterCursor(); } } AnalyseGui::AnalyseGui() : ccDisplay(50), llocDisplay(80), depthDisplay(5) { Title(defaultTitle); Icon(Images::GaugeIcon); AddFrame(menu); menu.Set( THISBACK(MainMenu) ); source <<= THISBACK(UpdateMetric); source <<= defaultCode; textMetric.SetEditable(false); chart.AddColumn("Function", 80); chart.AddColumn("Pos", 15); chart.AddColumn("CC1", 15).SetDisplay(ccDisplay); chart.AddColumn("CC2", 15).SetDisplay(ccDisplay); chart.AddColumn("LLOC", 15).SetDisplay(llocDisplay); chart.AddColumn("Depth", 15).SetDisplay(depthDisplay); chart.WhenLeftDouble = THISBACK(GotoFunction); UpdateMetric(); splitter.Vert() << source << chart << textMetric; splitter.SetPos(9000, 1); splitter.SetPos(6500, 0); Add(splitter.SizePos()); Sizeable().Zoomable(); } GUI_APP_MAIN { AnalyseGui().Run(); }