summaryrefslogtreecommitdiff
path: root/ping_protocol/pinggraph.cpp
diff options
context:
space:
mode:
authorsje <sje@4f64403b-2f21-0410-a795-97e2b3489a10>2006-11-01 14:44:34 +0000
committersje <sje@4f64403b-2f21-0410-a795-97e2b3489a10>2006-11-01 14:44:34 +0000
commit49b4d6dd9d4d35adc9f02df4010a1a6b33faba63 (patch)
tree403d0508eed3d1e1c9b336251eff931f3f2511b1 /ping_protocol/pinggraph.cpp
parentb61df7acc1235b3b2a66217d0d7358199c5d37f9 (diff)
git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@12 4f64403b-2f21-0410-a795-97e2b3489a10
Diffstat (limited to 'ping_protocol/pinggraph.cpp')
-rw-r--r--ping_protocol/pinggraph.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/ping_protocol/pinggraph.cpp b/ping_protocol/pinggraph.cpp
new file mode 100644
index 0000000..f6a9da5
--- /dev/null
+++ b/ping_protocol/pinggraph.cpp
@@ -0,0 +1,250 @@
+#include "stdafx.h"
+#include "pinggraph.h"
+
+#include <map>
+
+#define ID_REPAINT_TIMER 10101
+
+struct WindowData {
+ HANDLE hContact;
+ HistoryList list;
+};
+
+#define WM_REBUILDLIST (WM_USER + 1)
+
+LRESULT CALLBACK GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_REBUILDLIST:
+ {
+ WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ bool found = false;
+ EnterCriticalSection(&data_list_cs);
+ for(PINGLIST::iterator i = data_list.begin(); i != data_list.end(); i++) {
+ if(i->hContact == wd->hContact) {
+ wd->list = i->history;
+ found = true;
+ break;
+ }
+ }
+ LeaveCriticalSection(&data_list_cs);
+
+ if(!found) {
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return TRUE;
+ }
+
+ InvalidateRect(hwnd, 0, FALSE);
+ }
+ return TRUE;
+ case WM_SHOWWINDOW:
+ if(wParam == TRUE && lParam == 0) {
+ WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ KillTimer(hwnd, ID_REPAINT_TIMER);
+#ifdef min
+ SetTimer(hwnd, ID_REPAINT_TIMER, min(options.ping_period * 1000, 5000), 0);
+#else
+ SetTimer(hwnd, ID_REPAINT_TIMER, std::min(options.ping_period * 1000, 5000), 0);
+#endif
+
+ SendMessage(hwnd, WM_REBUILDLIST, 0, 0);
+ }
+ break;
+
+ case WM_TIMER:
+ {
+ SendMessage(hwnd, WM_REBUILDLIST, 0, 0);
+ }
+ return TRUE;
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc;
+ RECT r;
+ WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ if(hdc = BeginPaint(hwnd, &ps)) {
+ GetClientRect(hwnd, &r);
+ FillRect(hdc, &r, GetSysColorBrush(COLOR_WINDOW));
+
+ short max_value = -1; // this is minimum graph height, in ms
+ for(HistoryList::iterator hli = wd->list.begin(); hli != wd->list.end(); hli++) {
+ if(hli->first > max_value) max_value = hli->first;
+ }
+
+ max_value = (int)(max_value * 1.2f);
+ if(max_value < MIN_GRAPH_HEIGHT) max_value = MIN_GRAPH_HEIGHT;
+
+#ifdef max
+ float unit_width = (r.right - r.left) / (float)max((int)wd->list.size(), MIN_BARS), // space for at least MIN_BARS bars
+#else
+ float unit_width = (r.right - r.left) / (float)std::max((int)wd->list.size(), MIN_BARS), // space for at least MIN_BARS bars
+#endif
+ unit_height = (r.bottom - r.top) / (float)max_value;
+
+ RECT bar;
+ bar.bottom = r.bottom;
+ float x = r.right - (unit_width * wd->list.size() + 0.5f);
+ bar.left = (int)(x + 0.5f);
+ bar.right = (int)(x + unit_width + 0.5f);
+
+ DWORD last_time = 0, time, start_time = 0;
+ if(wd->list.size())
+ start_time = wd->list.begin()->second;
+
+ HPEN hPenOld, hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
+ hPenOld = (HPEN)SelectObject(hdc, hPen);
+
+ for(HistoryList::iterator hi = wd->list.begin(); hi != wd->list.end(); hi++) {
+ if(hi->first != -1) {
+ bar.top = bar.bottom - (int)(hi->first * unit_height + 0.5f);
+ FillRect(hdc, &bar, GetSysColorBrush(COLOR_HOTLIGHT));
+ }
+
+ time = hi->second - start_time;
+ if(time / MARK_PERIOD != last_time / MARK_PERIOD) {
+ MoveToEx(hdc, bar.left, r.bottom, 0);
+ LineTo(hdc, bar.left, r.top);
+ }
+
+ last_time = time;
+
+ x += unit_width;
+ bar.left = bar.right;
+ bar.right = (int)(x + unit_width + 0.5f);
+ }
+
+ // draw horizontal lines to mark every 100ms
+ for(int li = 0; li < max_value; li += MARK_TIME) {
+ MoveToEx(hdc, r.left, r.bottom - (int)(li * unit_height + 0.5f), 0);
+ LineTo(hdc, r.right, r.bottom - (int)(li * unit_height + 0.5f));
+ }
+
+ SelectObject(hdc, hPenOld);
+ DeleteObject(hPen);
+
+ SetBkMode(hdc, TRANSPARENT);
+ SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW));
+ char buff[64];
+ sprintf(buff, "%dms", MARK_TIME);
+ TextOut(hdc, r.left + 10, r.bottom - (int)(unit_height * MARK_TIME + 0.5f), buff, 5);
+
+ EndPaint(hwnd, &ps);
+ }
+ }
+ return TRUE;
+
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_SIZE:
+ InvalidateRect(hwnd, 0, FALSE);
+ break;
+ case WM_CLOSE:
+ {
+ KillTimer(hwnd, ID_REPAINT_TIMER);
+ WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ if(CallService(MS_DB_CONTACT_IS, (WPARAM)wd->hContact, 0))
+ Utils_SaveWindowPosition(hwnd, wd->hContact, PROTO, "pinggraphwnd");
+ }
+ break;
+ case WM_DESTROY:
+ {
+ WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA);
+ DBDeleteContactSetting(wd->hContact, PROTO, "WindowHandle");
+ delete wd;
+ }
+ // drop through
+ };
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+int ShowGraph(WPARAM wParam, LPARAM lParam) {
+ HWND hGraphWnd = (HWND)DBGetContactSettingDword((HANDLE)wParam, PROTO, "WindowHandle", 0);
+ if(hGraphWnd) {
+ ShowWindow(hGraphWnd, SW_SHOW);
+ SetWindowPos(hGraphWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ return 0;
+ }
+
+ WNDCLASS wndclass;
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = GraphWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = LoadSkinnedProtoIcon(PROTO, ID_STATUS_ONLINE);
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = PROTO "GraphWindow";
+ RegisterClass(&wndclass);
+
+ DBVARIANT dbv;
+ char title[256];
+ strcpy(title, "Ping Graph");
+ if(!DBGetContactSetting((HANDLE)wParam, PROTO, "Nick", &dbv)) {
+ strcat(title, " - ");
+ strncat(title, dbv.pszVal, 256 - 13);
+ DBFreeVariant(&dbv);
+ }
+
+ HWND parent = 0;
+ hGraphWnd = CreateWindowEx(0, PROTO "GraphWindow", title,
+ (WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN) & ~CS_VREDRAW & ~CS_HREDRAW,
+ 0,0,800,600,parent,NULL,hInst,NULL);
+
+ DBWriteContactSettingDword((HANDLE)wParam, PROTO, "WindowHandle", (DWORD)hGraphWnd);
+
+ WindowData *wd = new WindowData;
+ wd->hContact = (HANDLE)wParam; // wParam is contact handle
+
+ SetWindowLong(hGraphWnd, GWL_USERDATA, (LONG)wd);
+
+ if(CallService(MS_DB_CONTACT_IS, (WPARAM)wd->hContact, 0))
+ Utils_RestoreWindowPosition(hGraphWnd, wd->hContact, PROTO, "pinggraphwnd");
+
+ if(!IsWindowVisible(hGraphWnd))
+ ShowWindow(hGraphWnd, SW_SHOW);
+
+ return 0;
+}
+
+// save window positions, close windows
+void graphs_cleanup() {
+ HWND hwnd;
+ char *proto;
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL )
+ {
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (proto && lstrcmp( PROTO, proto) == 0) {
+ if((hwnd = (HWND)DBGetContactSettingDword(hContact, PROTO, "WindowHandle", 0)) != 0) {
+ DestroyWindow(hwnd);
+ DBWriteContactSettingByte(hContact, PROTO, "WindowWasOpen", 1);
+ }
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+}
+
+// restore windows that were open when cleanup was called last
+void graphs_init() {
+ char *proto;
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL )
+ {
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (proto && lstrcmp( PROTO, proto) == 0) {
+ if(DBGetContactSettingByte(hContact, PROTO, "WindowWasOpen", 0) != 0) {
+ ShowGraph((WPARAM)hContact, 0);
+ DBWriteContactSettingByte(hContact, PROTO, "WindowWasOpen", 0);
+ }
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+}