[Ieleak-commit] SF.net SVN: ieleak: [92] trunk/drip/src
Brought to you by:
matthiasmiller
From: <mat...@us...> - 2006-06-24 23:02:24
|
Revision: 92 Author: matthiasmiller Date: 2006-06-24 16:02:09 -0700 (Sat, 24 Jun 2006) ViewCVS: http://svn.sourceforge.net/ieleak/?rev=92&view=rev Log Message: ----------- add series for DOM node usage and allow mouse-hover to find specific details about memory usage (now uses generic MemDCCtrl with a separate graph control responsible for all updating, as well as a context menu to control update speed) Modified Paths: -------------- trunk/drip/src/Graph.cpp trunk/drip/src/Graph.h trunk/drip/src/MainBrowserDlg.cpp trunk/drip/src/MainBrowserDlg.hpp trunk/drip/src/drip.rc trunk/drip/src/drip.vcproj Added Paths: ----------- trunk/drip/src/MemDCCtrl.cpp trunk/drip/src/MemDCCtrl.h trunk/drip/src/MemoryGraphCtrl.cpp trunk/drip/src/MemoryGraphCtrl.h Modified: trunk/drip/src/Graph.cpp =================================================================== --- trunk/drip/src/Graph.cpp 2006-06-23 10:25:06 UTC (rev 91) +++ trunk/drip/src/Graph.cpp 2006-06-24 23:02:09 UTC (rev 92) @@ -22,13 +22,19 @@ { SetBackgroundColor(RGB(0,0,0)); SetGridLineColor(RGB(0, 128, 64)); - SetGraphLineColor(RGB(0, 255, 0)); SetGridLineStep(12, 12); m_PointStep = 1; } CGraph::~CGraph() { + vector<Series*>::iterator iter = m_Series.begin(); + while (iter != m_Series.end()) + { + delete *iter; + iter++; + } + m_Series.clear(); } void CGraph::SetBackgroundColor(COLORREF cl) @@ -41,26 +47,81 @@ m_GridLineColor = cl; } -void CGraph::SetGraphLineColor(COLORREF cl) -{ - m_GraphLineColor = cl; -} - void CGraph::SetGridLineStep(int x, int y) { m_VertStep = x; m_HorzStep = y; } -void CGraph::AddPoint(int y) +size_t CGraph::GetNumSeries() { - m_Values.push_back(y); + return m_Series.size(); } +size_t CGraph::AddSeries(COLORREF color) +{ + Series* series = new Series; + series->color = color; + m_Series.push_back(series); + return m_Series.size()-1; +} + +COLORREF CGraph::GetSeriesColor(size_t series) +{ + ASSERT(series >= 0 && series < m_Series.size()); + return m_Series.at(series)->color; +} + +void CGraph::AddPoint(size_t series, int y) +{ + ASSERT(series >= 0 && series < m_Series.size()); + m_Series.at(series)->values.push_back(y); +} + +int CGraph::GetLeftMostPointInAnySeries(CRect zone) +{ + size_t maxItems = 0; + + // count the number of items + vector<Series*>::iterator iter = m_Series.begin(); + while (iter != m_Series.end()) + { + maxItems = max(maxItems, (*iter)->values.size()); + iter++; + } + + if (maxItems == 0) + return zone.right; + else if (maxItems > (size_t)zone.Width()) + return zone.left; + else + return zone.right - (int)maxItems + 1; +} + +bool CGraph::GetValueAtPoint(size_t series, CRect zone, int x, OUT int& value) +{ + ASSERT(series >= 0 && series < m_Series.size()); + vector<int>* values = &m_Series.at(series)->values; + size_t numItems = values->size(); + + size_t index = numItems - 1 - (zone.right - x); + if (index < 0 || index >= numItems) + return false; + + value = values->at(index); + return true; +} + void CGraph::DrawGraph(CDC* pDC, CRect zone) { DrawGridLines(pDC, zone); - DrawGraphLine(pDC, zone); + + vector<Series*>::iterator iter = m_Series.begin(); + while (iter != m_Series.end()) + { + DrawGraphLine(*iter, pDC, zone); + iter++; + } } void CGraph::DrawGridLines(CDC* pDC, CRect zone) @@ -106,27 +167,27 @@ } } -void CGraph::DrawGraphLine(CDC* pDC, CRect zone) +void CGraph::DrawGraphLine(Series* series, CDC* pDC, CRect zone) { - CPen vPen(PS_SOLID, 1, m_GraphLineColor); + CPen vPen(PS_SOLID, 1, series->color); CPen* pOld = pDC->SelectObject(&vPen); // Draw all points, starting from the right. Do not draw more than PtCnt points. - list<int>::reverse_iterator iter = m_Values.rbegin(); + vector<int>::reverse_iterator iter = series->values.rbegin(); int numPoints = zone.Width() / m_PointStep; int curPoint = numPoints-1; int min, max; - CalcMinMax(numPoints, min, max); + CalcMinMax(series, numPoints, min, max); - while (iter != m_Values.rend() && curPoint >= 0) + while (iter != series->values.rend() && curPoint >= 0) { CPoint pt; pt.x = zone.left + zone.Width() * curPoint / numPoints; pt.y = CalcYPlotPos(zone, min, max, *iter); - if (iter == m_Values.rbegin()) + if (iter == series->values.rbegin()) pDC->MoveTo(pt); else pDC->LineTo(pt); @@ -160,7 +221,7 @@ return adjZone.bottom - (int)offset; } -void CGraph::CalcMinMax(int numPoints, int& min, int& max) +void CGraph::CalcMinMax(Series* series, int numPoints, int& min, int& max) { min = 0; max = 0; @@ -168,8 +229,8 @@ bool hasMinMax = false; int i = 0; - list<int>::reverse_iterator iter = m_Values.rbegin(); - while (iter != m_Values.rend() && i < numPoints) + vector<int>::reverse_iterator iter = series->values.rbegin(); + while (iter != series->values.rend() && i < numPoints) { if (hasMinMax) { @@ -187,93 +248,3 @@ iter++; } } - - - - -///////////////////////////////////////////////////////////////////////////// -// CGraphCtrl - -CGraphCtrl::CGraphCtrl() -{ - m_pBitmap = NULL; -} - -CGraphCtrl::~CGraphCtrl() -{ - ResetPaintCache(); -} - - -BEGIN_MESSAGE_MAP(CGraphCtrl, CStatic) - //{{AFX_MSG_MAP(CGraphCtrl) - ON_WM_PAINT() - //}}AFX_MSG_MAP - ON_WM_ERASEBKGND() -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CGraphCtrl message handlers - -void CGraphCtrl::OnPaint() -{ - CPaintDC dc(this); // device context for painting - - // Ensure that the bitmap has been created and is up-to-date - CRect zone; - GetClientRect(zone); - if (m_pBitmap && m_pBitmap->GetBitmapDimension() != CSize(zone.BottomRight())) - ResetPaintCache(); - - if (!m_pBitmap) - { - // Get the number of color planes and color bits used on the current display - HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL, NULL); - int iPlanes = GetDeviceCaps(hdcScreen, PLANES); - int iBitCount = GetDeviceCaps(hdcScreen, BITSPIXEL); - DeleteDC(hdcScreen); - - // Allocate and create the bitmap - m_pBitmap = new CBitmap; - m_pBitmap->CreateBitmap(zone.Width(), zone.Height(), iPlanes, iBitCount, NULL); - - // Save the dimensions of the bitmap. - m_pBitmap->SetBitmapDimension(zone.Width(), zone.Height()); - - CDC dcBitmapCache; - dcBitmapCache.CreateCompatibleDC(&dc); - dcBitmapCache.SelectObject(m_pBitmap); - m_Graph.DrawGraph(&dcBitmapCache, zone); - } - - // Copy to the DC - CDC dcBitmap; - dcBitmap.CreateCompatibleDC(&dc); - dcBitmap.SelectObject(m_pBitmap); - dc.BitBlt(zone.left, zone.top, zone.Width(), zone.Height(), &dcBitmap, 0, 0, SRCCOPY); -} - -void CGraphCtrl::ResetPaintCache() -{ - delete m_pBitmap; - m_pBitmap = NULL; -} - -void CGraphCtrl::AddPoint(int y) -{ - m_Graph.AddPoint(y); - ResetPaintCache(); - RedrawWindow(); -} - -void CGraphCtrl::DrawControl(CDC* pDC) -{ - CRect zone; - GetClientRect(zone); - m_Graph.DrawGraph(pDC, zone); -} - -BOOL CGraphCtrl::OnEraseBkgnd(CDC* pDC) -{ - return false; -} Modified: trunk/drip/src/Graph.h =================================================================== --- trunk/drip/src/Graph.h 2006-06-23 10:25:06 UTC (rev 91) +++ trunk/drip/src/Graph.h 2006-06-24 23:02:09 UTC (rev 92) @@ -21,73 +21,39 @@ void SetBackgroundColor(COLORREF cl); void SetGridLineColor(COLORREF cl); - void SetGraphLineColor(COLORREF cl); void SetGridLineStep(int x, int y); - void AddPoint(int y); + size_t GetNumSeries(); + size_t AddSeries(COLORREF color); + COLORREF GetSeriesColor(size_t series); + void AddPoint(size_t series, int y); + + // returns the right edge if there are no points + int GetLeftMostPointInAnySeries(CRect zone); + bool GetValueAtPoint(size_t series, CRect zone, int x, OUT int& value); + void DrawGraph(CDC* pDC, CRect Zone); private: - COLORREF m_BackgroundColor, m_GridLineColor, m_GraphLineColor; + COLORREF m_BackgroundColor, m_GridLineColor; int m_VertStep, m_HorzStep, m_PointStep; - list<int> m_Values; + struct Series + { + COLORREF color; + vector<int> values; + }; + vector<Series*> m_Series; void DrawGridLines(CDC* pDC, CRect zone); void DrawHorzGridLines(CDC* pDC, CRect zone); void DrawVertGridLines(CDC* pDC, CRect zone); - void DrawGraphLine(CDC* pDC, CRect Zone); + void DrawGraphLine(Series* series, CDC* pDC, CRect Zone); int CalcYPlotPos(CRect zone, int min, int max, int y); - void CalcMinMax(int numPoints, int& min, int& max); + void CalcMinMax(Series* series, int numPoints, int& min, int& max); }; - -class CGraphCtrl : public CStatic -{ -// Construction -public: - CGraphCtrl(); - - void ResetPaintCache(); - -private: - void UpdatePaintCache(); - CBitmap* m_pBitmap; - - void DrawGraph(CDC* pDC); - -// Attributes -public: - -// Operations -public: - void AddPoint(int y); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CGraphCtrl) - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CGraphCtrl(); - - // Generated message map functions -protected: - //{{AFX_MSG(CGraphCtrl) - afx_msg void OnPaint(); - //}}AFX_MSG - - DECLARE_MESSAGE_MAP() - - virtual void DrawControl(CDC* pDC); - CGraph m_Graph; -public: - afx_msg BOOL OnEraseBkgnd(CDC* pDC); -}; - - #endif // !defined(AFX_GRAPH_H__43C3693F_1CD5_11D6_A6FF_CA0C1DCB2838__INCLUDED_) Modified: trunk/drip/src/MainBrowserDlg.cpp =================================================================== --- trunk/drip/src/MainBrowserDlg.cpp 2006-06-23 10:25:06 UTC (rev 91) +++ trunk/drip/src/MainBrowserDlg.cpp 2006-06-24 23:02:09 UTC (rev 92) @@ -9,8 +9,7 @@ #include <afxpriv.h> #define TIMER_AUTO_REFRESH 0 -#define TIMER_MONITOR_MEMORY 1 -#define TIMER_CHECK_LEAKS 2 +#define TIMER_CHECK_LEAKS 1 #if (_WIN32_WINNT < 0x0501) @@ -54,7 +53,7 @@ END_MESSAGE_MAP() CMainBrowserDlg::CMainBrowserDlg(CComObject<JSHook>* hook, CWnd* pParent) : CBrowserHostDlg(hook, IDC_EXPLORER, CMainBrowserDlg::IDD, pParent), - m_waitingForDoc(false), m_waitingForBlankDoc(false), m_autoRefreshMode(false), m_checkLeakDoc(NULL) + m_waitingForDoc(false), m_waitingForBlankDoc(false), m_autoRefreshMode(false), m_checkLeakDoc(NULL), m_memGraph(hook) { //{{AFX_DATA_INIT(CMainBrowserDlg) // NOTE: the ClassWizard will add member initialization here @@ -113,10 +112,6 @@ // m_editURL.SetFocus(); - // Enable memory monitoring - // - SetTimer(TIMER_MONITOR_MEMORY, 100, NULL); - // Set up resizing m_resizeHelper.Init(m_hWnd); m_resizeHelper.Fix(IDC_AUTOREFRESH, DlgResizeHelper::kWidthRight, DlgResizeHelper::kHeightTop); @@ -226,20 +221,6 @@ go(); break; - case TIMER_MONITOR_MEMORY: - { - // Update the node count and memory usage - // - CStringW nodes; - nodes.Format(L"%i", getHook()->getNodeCount()); - m_CurrentDOMNodesBox.SetWindowText(nodes); - - size_t usage = GetMemoryUsage(); - m_memGraph.AddPoint((int)usage); - m_CurrentMemoryBox.SetWindowText(GetMemoryUsageStr()); - } - break; - case TIMER_CHECK_LEAKS: if (m_checkLeakDoc == NULL) { KillTimer(nIDEvent); Modified: trunk/drip/src/MainBrowserDlg.hpp =================================================================== --- trunk/drip/src/MainBrowserDlg.hpp 2006-06-23 10:25:06 UTC (rev 91) +++ trunk/drip/src/MainBrowserDlg.hpp 2006-06-24 23:02:09 UTC (rev 92) @@ -3,7 +3,7 @@ #include "resource.h" #include "DlgResizeHelper.h" #include "BrowserHostDlg.hpp" -#include "Graph.h" +#include "MemoryGraphCtrl.h" #include "afxwin.h" // Forward declaration @@ -75,5 +75,5 @@ CEdit m_editURL; CEdit m_CurrentMemoryBox, m_CurrentDOMNodesBox; CListBox m_memList; - CGraphCtrl m_memGraph; + CMemoryGraphCtrl m_memGraph; }; Copied: trunk/drip/src/MemDCCtrl.cpp (from rev 82, trunk/drip/src/Graph.cpp) =================================================================== --- trunk/drip/src/MemDCCtrl.cpp (rev 0) +++ trunk/drip/src/MemDCCtrl.cpp 2006-06-24 23:02:09 UTC (rev 92) @@ -0,0 +1,79 @@ +// MemDCCtrl.cpp : implementation file +// + +#include "stdafx.h" +#include "MemDCCtrl.h" + + +// CMemDCCtrl + +IMPLEMENT_DYNAMIC(CMemDCCtrl, CStatic) +CMemDCCtrl::CMemDCCtrl() { + m_bitmap = NULL; +} + +CMemDCCtrl::~CMemDCCtrl() { + emptyPaintCache(); +} + +BEGIN_MESSAGE_MAP(CMemDCCtrl, CStatic) + //{{AFX_MSG_MAP(CMemDCCtrl) + ON_WM_PAINT() + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// CMemDCCtrl message handlers + +void CMemDCCtrl::OnPaint() { + CPaintDC dc(this); // device context for painting + + // Ensure that the bitmap has been created and is up-to-date + CRect zone; + GetClientRect(zone); + if (m_bitmap && shouldRedrawControl(zone)) + emptyPaintCache(); + + if (!m_bitmap) { + // Get the number of color planes and color bits used on the current display + HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL, NULL); + int iPlanes = GetDeviceCaps(hdcScreen, PLANES); + int iBitCount = GetDeviceCaps(hdcScreen, BITSPIXEL); + DeleteDC(hdcScreen); + + // Allocate and create the bitmap + m_bitmap = new CBitmap; + m_bitmap->CreateBitmap(zone.Width(), zone.Height(), iPlanes, iBitCount, NULL); + + // Save the dimensions of the bitmap. + m_bitmap->SetBitmapDimension(zone.Width(), zone.Height()); + + CDC dcBitmapCache; + dcBitmapCache.CreateCompatibleDC(&dc); + dcBitmapCache.SelectObject(m_bitmap); + drawControl(&dcBitmapCache, zone); + } + + // Copy to the DC + CDC dcBitmap; + dcBitmap.CreateCompatibleDC(&dc); + dcBitmap.SelectObject(m_bitmap); + dc.BitBlt(zone.left, zone.top, zone.Width(), zone.Height(), &dcBitmap, 0, 0, SRCCOPY); +} + +BOOL CMemDCCtrl::OnEraseBkgnd(CDC* pDC) { + return false; +} + +void CMemDCCtrl::emptyPaintCache() { + delete m_bitmap; + m_bitmap = NULL; +} + +bool CMemDCCtrl::shouldRedrawControl(CRect zone) { + // Redraw the control when it's resized. + if (m_bitmap->GetBitmapDimension() != CSize(zone.BottomRight())) + return true; + + return false; +} Copied: trunk/drip/src/MemDCCtrl.h (from rev 82, trunk/drip/src/Graph.h) =================================================================== --- trunk/drip/src/MemDCCtrl.h (rev 0) +++ trunk/drip/src/MemDCCtrl.h 2006-06-24 23:02:09 UTC (rev 92) @@ -0,0 +1,43 @@ +#pragma once + + +// CMemDCCtrl + +class CMemDCCtrl : public CStatic +{ + DECLARE_DYNAMIC(CMemDCCtrl) + +public: + CMemDCCtrl(); + virtual ~CMemDCCtrl(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMemDCCtrl) + //}}AFX_VIRTUAL + +// Implementation + // Generated message map functions +protected: + //{{AFX_MSG(CMemDCCtrl) + afx_msg void OnPaint(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() + + virtual bool shouldRedrawControl(CRect zone); + virtual void drawControl(CDC* pDC, CRect zone)=0; + +protected: + void emptyPaintCache(); + +private: + CBitmap* m_bitmap; +}; Copied: trunk/drip/src/MemoryGraphCtrl.cpp (from rev 82, trunk/drip/src/Graph.cpp) =================================================================== --- trunk/drip/src/MemoryGraphCtrl.cpp (rev 0) +++ trunk/drip/src/MemoryGraphCtrl.cpp 2006-06-24 23:02:09 UTC (rev 92) @@ -0,0 +1,267 @@ +// MemoryGraphCtrl.cpp : implementation file +// + +#include "stdafx.h" +#include "MainBrowserDlg.hpp" +#include "MemoryGraphCtrl.h" +#include ".\memorygraphctrl.h" + +#define TIMER_STATS 0 + +// CMemoryGraphCtrl + +IMPLEMENT_DYNAMIC(CMemoryGraphCtrl, CMemDCCtrl) +CMemoryGraphCtrl::CMemoryGraphCtrl(CComObject<JSHook>* hook) { + m_hook = hook; + m_hook->AddRef(); + + m_displayedMouseXPos = -1; + m_memSeries = m_graph.AddSeries(RGB(0,255,0)); + m_domSeries = m_graph.AddSeries(RGB(255,255,0)); + VERIFY(m_statsFont.CreatePointFont(90, L"Sans Serif")); + + m_updateSpeed = kPaused; +} + +CMemoryGraphCtrl::~CMemoryGraphCtrl() { + m_hook->Release(); + m_hook = NULL; +} + + +BEGIN_MESSAGE_MAP(CMemoryGraphCtrl, CMemDCCtrl) + //{{AFX_MSG_MAP(CMemoryGraphCtrl) + ON_WM_CREATE() + ON_WM_MOUSEMOVE() + ON_WM_TIMER() + ON_WM_RBUTTONUP() + ON_WM_NCHITTEST() + ON_COMMAND(ID_GRAPHUPDATESPEED_HIGH, OnGraphUpdateSpeedHigh) + ON_COMMAND(ID_GRAPHUPDATESPEED_LOW, OnGraphUpdateSpeedLow) + ON_COMMAND(ID_GRAPHUPDATESPEED_NORMAL, OnGraphUpdateSpeedNormal) + ON_COMMAND(ID_GRAPHUPDATESPEED_PAUSED, OnGraphUpdateSpeedPaused) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMemoryGraphCtrl message handlers + +void CMemoryGraphCtrl::PreSubclassWindow() { + CStatic::PreSubclassWindow(); + setUpdateSpeed(kNormal); +} + +int CMemoryGraphCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { + setUpdateSpeed(kNormal); + return CStatic::OnCreate(lpCreateStruct); +} + +void CMemoryGraphCtrl::OnMouseMove(UINT nFlags, CPoint point) +{ + Invalidate(); + + CMemDCCtrl::OnMouseMove(nFlags, point); +} + +void CMemoryGraphCtrl::OnTimer(UINT_PTR nIDEvent) { + if (nIDEvent == TIMER_STATS) { + // Update the node count and memory usage + // + size_t usage = CMainBrowserDlg::GetMemoryUsage(); + addPoint((int)usage, (int)m_hook->getNodeCount()); + } + + CStatic::OnTimer(nIDEvent); +} + +void CMemoryGraphCtrl::addPoint(int memUsage, int domNodes) { + m_graph.AddPoint(m_memSeries, memUsage); + m_graph.AddPoint(m_domSeries, domNodes); + emptyPaintCache(); + RedrawWindow(); +} + +bool CMemoryGraphCtrl::shouldRedrawControl(CRect zone) { + if (CMemDCCtrl::shouldRedrawControl(zone)) + return true; + + // The control will be invalidated every time a point is added, + // so only force a redraw if the mouse has moved. + if (m_displayedMouseXPos != getMouseXPos(zone)) + return true; + + return false; +} + +void CMemoryGraphCtrl::drawControl(CDC* pDC, CRect zone) { + m_graph.DrawGraph(pDC, zone); + + // Draw a line where the mouse is currently positioned. + m_displayedMouseXPos = getMouseXPos(zone); + CPen mousePen(PS_SOLID, 1, RGB(255,255,255)); + CPen* oldPen = pDC->SelectObject(&mousePen); + pDC->MoveTo(m_displayedMouseXPos, 0); + pDC->LineTo(m_displayedMouseXPos, zone.bottom); + pDC->SelectObject(oldPen); + + // Determine the statistics to display + vector<string> stats; + + int mem = 0; + if (m_graph.GetValueAtPoint(m_memSeries, zone, m_displayedMouseXPos, mem)) { + stats.push_back("Memory Usage: "); + CStringA memStats; + memStats.Format("%i", mem); + stats.push_back((const char*)memStats); + } + else { + stats.push_back(""); + stats.push_back(""); + } + + int nodes = 0; + if (m_graph.GetValueAtPoint(m_domSeries, zone, m_displayedMouseXPos, nodes)) { + CStringA nodeStats; + nodeStats.Format("%i", nodes); + stats.push_back("Total DOM Nodes: "); + stats.push_back((const char*)nodeStats); + } + else { + stats.push_back(""); + stats.push_back(""); + } + + ASSERT(stats.size() == m_graph.GetNumSeries()*2); + + // Determine the positions of the stats + const int margin = 5; + int xPos = zone.left + margin; + int yPos = zone.top + margin; + + vector<CRect> statPos; + CRect dimensions(xPos, yPos, xPos, yPos); + for (size_t i = 0; i < stats.size(); i++) { + // determine the position of the stat + CPoint size = pDC->GetTextExtent(stats.at(i).c_str()); + CRect pos(xPos, yPos, xPos + size.x, yPos + size.y); + statPos.push_back(pos); + dimensions.UnionRect(&dimensions, &pos); + + yPos += size.y + margin; + } + + // Draw the stats, if possible + if (zone.PtInRect(dimensions.TopLeft()) && zone.PtInRect(dimensions.BottomRight())) { + int oldMode = pDC->SetBkMode(TRANSPARENT); + CFont* oldFont = pDC->SelectObject(&m_statsFont); + + for (size_t i = 0; i < stats.size(); i++) { + CPoint pos = statPos.at(i).TopLeft(); + + int oldColor = pDC->SetTextColor(m_graph.GetSeriesColor(i/2)); + pDC->TextOut(pos.x, pos.y, stats.at(i).c_str()); + pDC->SetTextColor(oldColor); + } + + pDC->SelectObject(oldFont); + pDC->SetBkMode(oldMode); + } +} + +int CMemoryGraphCtrl::getMouseXPos(CRect zone) { + int x = zone.right; + + // get the cursor position relative to the control + CPoint cursor; + if (GetCursorPos(&cursor)) { + ScreenToClient(&cursor); + if (zone.PtInRect(cursor)) + x = cursor.x; + } + + int min = m_graph.GetLeftMostPointInAnySeries(zone); + if (x < min) + x = min; + + return x; +} + +void CMemoryGraphCtrl::setUpdateSpeed(UpdateSpeed speed) +{ + m_updateSpeed = speed; + + KillTimer(TIMER_STATS); + + // determine the new update interval + int interval; + switch (m_updateSpeed) { + case kHigh: + interval = 500; + break; + case kNormal: + interval = 2000; + break; + case kLow: + interval = 4000; + break; + case kPaused: + return; + default: + ASSERT(false); + return; + } + SetTimer(TIMER_STATS, interval, NULL); +} + +void CMemoryGraphCtrl::OnRButtonUp(UINT nFlags, CPoint point) +{ + // the event's point is relative to the client, but the menu is displayed relative to the screen. + CPoint screen = point; + ClientToScreen(&screen); + + // load the menu + CMenu* menu = CMenu::FromHandle(LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_GRAPH_MENU))); + menu = menu->GetSubMenu(0); + + // set the radio button for the update speed + UINT id = 0; + switch (m_updateSpeed) { + case kHigh: id = ID_GRAPHUPDATESPEED_HIGH; break; + case kNormal: id = ID_GRAPHUPDATESPEED_NORMAL; break; + case kLow: id = ID_GRAPHUPDATESPEED_LOW; break; + case kPaused: id = ID_GRAPHUPDATESPEED_PAUSED; break; + default: ASSERT(false); break; + } + CMenu* updateSpeedMenu = menu->GetSubMenu(0); + updateSpeedMenu->CheckMenuRadioItem(ID_GRAPHUPDATESPEED_HIGH, ID_GRAPHUPDATESPEED_PAUSED, id, MF_BYCOMMAND); + + menu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_RIGHTBUTTON, screen.x, screen.y, this, NULL); + + CMemDCCtrl::OnRButtonUp(nFlags, point); +} + +UINT CMemoryGraphCtrl::OnNcHitTest(CPoint point) +{ + // to allow right-click events (instead of the SS_NOTIFY style) + return HTCLIENT; +} + +void CMemoryGraphCtrl::OnGraphUpdateSpeedHigh() +{ + setUpdateSpeed(kHigh); +} + +void CMemoryGraphCtrl::OnGraphUpdateSpeedNormal() +{ + setUpdateSpeed(kNormal); +} + +void CMemoryGraphCtrl::OnGraphUpdateSpeedLow() +{ + setUpdateSpeed(kLow); +} + +void CMemoryGraphCtrl::OnGraphUpdateSpeedPaused() +{ + setUpdateSpeed(kPaused); +} Copied: trunk/drip/src/MemoryGraphCtrl.h (from rev 82, trunk/drip/src/Graph.h) =================================================================== --- trunk/drip/src/MemoryGraphCtrl.h (rev 0) +++ trunk/drip/src/MemoryGraphCtrl.h 2006-06-24 23:02:09 UTC (rev 92) @@ -0,0 +1,68 @@ +#pragma once + +#include "Graph.h" +#include "JSHook.hpp" +#include "MemDCCtrl.h" + +// CMemoryGraphCtrl + +class CMemoryGraphCtrl : public CMemDCCtrl +{ + DECLARE_DYNAMIC(CMemoryGraphCtrl) + +public: + CMemoryGraphCtrl(CComObject<JSHook>* hook); + virtual ~CMemoryGraphCtrl(); + +// Attributes +public: + +// Operations +public: + void addPoint(int memUsage, int domNodes); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGraphCtrl) + virtual void PreSubclassWindow(); + //}}AFX_VIRTUAL + + // Generated message map functions +protected: + //{{AFX_MSG(CGraphCtrl) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnPaint(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnTimer(UINT_PTR nIDEvent); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg UINT OnNcHitTest(CPoint point); + afx_msg void OnGraphUpdateSpeedHigh(); + afx_msg void OnGraphUpdateSpeedLow(); + afx_msg void OnGraphUpdateSpeedNormal(); + afx_msg void OnGraphUpdateSpeedPaused(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() + + virtual bool shouldRedrawControl(CRect zone); + virtual void drawControl(CDC* pDC, CRect zone); + +private: + enum UpdateSpeed { + kHigh, + kNormal, + kLow, + kPaused + }; + + int getMouseXPos(CRect zone); + void setUpdateSpeed(UpdateSpeed speed); + + CComObject<JSHook>* m_hook; + CGraph m_graph; + size_t m_memSeries, m_domSeries; + int m_displayedMouseXPos; + CFont m_statsFont; + + UpdateSpeed m_updateSpeed; +}; Modified: trunk/drip/src/drip.rc =================================================================== --- trunk/drip/src/drip.rc 2006-06-23 10:25:06 UTC (rev 91) +++ trunk/drip/src/drip.rc 2006-06-24 23:02:09 UTC (rev 92) @@ -273,6 +273,28 @@ // IDR_DRIP_JS HTML "res\\drip.js" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_GRAPH_MENU MENU +BEGIN + POPUP "Graph Menu" + BEGIN + POPUP "&Update Speed" + BEGIN + MENUITEM "&High", ID_GRAPHUPDATESPEED_HIGH + MENUITEM "&Normal", ID_GRAPHUPDATESPEED_NORMAL + + MENUITEM "&Low", ID_GRAPHUPDATESPEED_LOW + MENUITEM "&Paused", ID_GRAPHUPDATESPEED_PAUSED + + END + END +END + #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// Modified: trunk/drip/src/drip.vcproj =================================================================== --- trunk/drip/src/drip.vcproj 2006-06-23 10:25:06 UTC (rev 91) +++ trunk/drip/src/drip.vcproj 2006-06-24 23:02:09 UTC (rev 92) @@ -144,6 +144,9 @@ RelativePath=".\MainBrowserDlg.cpp"> </File> <File + RelativePath=".\MemoryGraphCtrl.cpp"> + </File> + <File RelativePath=".\UnitTests\MemoryUsageTest.cpp"> </File> <File @@ -188,6 +191,15 @@ RelativePath=".\MainBrowserDlg.hpp"> </File> <File + RelativePath=".\MemDCCtrl.cpp"> + </File> + <File + RelativePath=".\MemDCCtrl.h"> + </File> + <File + RelativePath=".\MemoryGraphCtrl.h"> + </File> + <File RelativePath=".\UnitTests\MemoryUsageTest.h"> </File> <File @@ -197,13 +209,13 @@ RelativePath=".\resource.h"> </File> <File - RelativePath=".\UnitTests\stdafx.h"> + RelativePath=".\NanoCppUnit\stdafx.h"> </File> <File RelativePath=".\stdafx.h"> </File> <File - RelativePath=".\NanoCppUnit\stdafx.h"> + RelativePath=".\UnitTests\stdafx.h"> </File> <File RelativePath=".\NanoCppUnit\test.h"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |