soc.2009.vulture: ab2e8a21: Show status text in buddy list.
gdick at soc.pidgin.im
gdick at soc.pidgin.im
Wed Jul 29 16:05:35 EDT 2009
-----------------------------------------------------------------
Revision: ab2e8a210fef618b45ef09fad85b8750f7bc6175
Ancestor: 064b8c11a5801e9a418c183c6830e59e738a2887
Author: gdick at soc.pidgin.im
Date: 2009-07-29T19:57:44
Branch: im.pidgin.soc.2009.vulture
URL: http://d.pidgin.im/viewmtn/revision/info/ab2e8a210fef618b45ef09fad85b8750f7bc6175
Modified files:
vulture/purpleblist.c vulture/resource.h
vulture/vulture-res.rc vulture/vultureblist.c
vulture/vultureblist.h
ChangeLog:
Show status text in buddy list.
-------------- next part --------------
============================================================
--- vulture/purpleblist.c 83e5696f6aa63724f75141c830407f63f3e61dcd
+++ vulture/purpleblist.c 4000dfae5d0ab34ce674b793b4acc6e1279d9bf9
@@ -36,6 +36,7 @@ static void DeleteBuddyFromAccount(Purpl
static BOOL ShouldShowNode(PurpleBlistNode *lpblistnode);
static void AddCommonMenuItems(HMENU hmenu, PurpleBlistNode *lpblistnode, GList **lplpglistVMA, PurpleConnection *lpconnection, int iProtoIndex, int iExtendedIndex);
static void DeleteBuddyFromAccount(PurpleBuddy *lpbuddy);
+static void UpdateStatusText(PurpleBlistNode *lpblistnode);
@@ -74,6 +75,7 @@ void PurpleBlistUpdateNode(PurpleBuddyLi
lpvbn->lRefCount = 1;
lpvbn->lpvbnParent = NULL;
lpvbn->bExpanded = FALSE;
+ lpvbn->szStatusText = NULL;
InitializeCriticalSection(&lpvbn->cs);
}
@@ -89,6 +91,8 @@ void PurpleBlistUpdateNode(PurpleBuddyLi
lpvbn->nodetype = lpblistnode->type;
+ UpdateStatusText(lpblistnode);
+
switch(lpblistnode->type)
{
case PURPLE_BLIST_GROUP_NODE:
@@ -107,6 +111,12 @@ void PurpleBlistUpdateNode(PurpleBuddyLi
break;
case PURPLE_BLIST_BUDDY_NODE:
+
+ /* Maybe our contact needs to update its status
+ * text.
+ */
+ UpdateStatusText(lpblistnode->parent);
+
szNodeText = purple_buddy_get_alias((PurpleBuddy*)lpblistnode);
if(szNodeText && *szNodeText)
@@ -129,19 +139,22 @@ void PurpleBlistUpdateNode(PurpleBuddyLi
if(lpvbn->lpvbnParent && !lpvbn->lpvbnParent->hti)
PurpleBlistUpdateNode(lpbuddylist, lpvbn->lpvbnParent->lpblistnode);
- /* If we're a buddy and our contact is
- * collapsed, give up at the last minute. We
- * still needed all the processing for other
- * nodes as if we'd been visible, but we want
- * to stop short of actually showing ourselves.
+ /* Update either our own node or our parent's,
+ * if we're a collapsed buddy.
*/
if(!PURPLE_BLIST_NODE_IS_BUDDY(lpblistnode) ||
- (lpblistnode->parent->ui_data &&
+ (lpblistnode->parent &&
+ lpblistnode->parent->ui_data &&
((VULTURE_BLIST_NODE*)lpblistnode->parent->ui_data)->bExpanded))
{
VultureBListNodeAddRef(lpvbn);
VulturePostUIMessage(VUIMSG_UPDATEBLISTNODE, lpvbn);
}
+ else if(lpblistnode->parent && lpblistnode->parent->ui_data)
+ {
+ VultureBListNodeAddRef(lpblistnode->parent->ui_data);
+ VulturePostUIMessage(VUIMSG_UPDATEBLISTNODE, lpblistnode->parent->ui_data);
+ }
}
}
else if(lpvbn->hti)
@@ -252,6 +265,7 @@ void VultureBListNodeRelease(VULTURE_BLI
if(lpvblnode->lpvbnParent) VultureBListNodeRelease(lpvblnode->lpvbnParent);
if(lpvblnode->szNodeText) g_free(lpvblnode->szNodeText);
+ if(lpvblnode->szStatusText) g_free(lpvblnode->szStatusText);
DeleteCriticalSection(&lpvblnode->cs);
g_free(lpvblnode);
@@ -295,19 +309,31 @@ LPTSTR PurpleBuddyGetStatusText(PurpleBu
{
PurplePlugin *lppluginPrpl;
- /* Find prpl for buddy. */
- if(lpbuddy && (lppluginPrpl = purple_find_prpl(purple_account_get_protocol_id(lpbuddy->account))))
+ if(!lpbuddy)
+ return NULL;
+
+ if(PURPLE_BUDDY_IS_ONLINE(lpbuddy))
{
- PurplePluginProtocolInfo *lpprplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(lppluginPrpl);
-
- /* If prpl supports status text, get the text. */
- if(lpprplinfo && lpprplinfo->status_text)
+ /* Find prpl for buddy. */
+ if((lppluginPrpl = purple_find_prpl(purple_account_get_protocol_id(lpbuddy->account))))
{
- char *szStatus = lpprplinfo->status_text(lpbuddy);
+ PurplePluginProtocolInfo *lpprplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(lppluginPrpl);
- return szStatus ? VultureUTF8ToTCHAR(szStatus) : NULL;
+ /* If prpl supports status text, get the text. */
+ if(lpprplinfo && lpprplinfo->status_text)
+ {
+ char *szStatus = lpprplinfo->status_text(lpbuddy);
+
+ return szStatus ? VultureUTF8ToTCHAR(szStatus) : NULL;
+ }
}
}
+ else
+ {
+ TCHAR szBuffer[128];
+ LoadString(g_hInstance, IDS_OFFLINE, szBuffer, NUM_ELEMENTS(szBuffer));
+ return g_memdup(szBuffer, sizeof(szBuffer));
+ }
return NULL;
}
@@ -322,8 +348,27 @@ void PurpleBuddyStatusChanged(PurpleBudd
*/
void PurpleBuddyStatusChanged(PurpleBuddy *lpbuddy, PurpleStatus *lpstatusOld, PurpleStatus *lpstatusNew)
{
+ PurpleConversation *lpconv;
+ VULTURE_BLIST_NODE *lpvbnContact = ((PurpleBlistNode*)lpbuddy)->parent ? ((PurpleBlistNode*)lpbuddy)->parent->ui_data : NULL;
+
+ UpdateStatusText((PurpleBlistNode*)lpbuddy);
+ UpdateStatusText(((PurpleBlistNode*)lpbuddy)->parent);
+
+ if(lpvbnContact)
+ {
+ if(lpvbnContact->bExpanded)
+ {
+ VULTURE_BLIST_NODE *lpvbn = ((PurpleBlistNode*)lpbuddy)->ui_data;
+ VultureBListNodeAddRef(lpvbn);
+ VulturePostUIMessage(VUIMSG_UPDATEBLISTNODE, ((PurpleBlistNode*)lpbuddy)->ui_data);
+ }
+
+ VultureBListNodeAddRef(lpvbnContact);
+ VulturePostUIMessage(VUIMSG_UPDATEBLISTNODE, lpvbnContact);
+ }
+
/* Are we speaking to this buddy? */
- PurpleConversation *lpconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, lpbuddy->name, lpbuddy->account);
+ lpconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, lpbuddy->name, lpbuddy->account);
/* If so, tell the UI to update the status message in the conversation.
*/
@@ -576,3 +621,36 @@ static void DeleteBuddyFromAccount(Purpl
if(purple_account_is_connected(lpaccount))
purple_account_remove_buddy(lpaccount, lpbuddy, purple_buddy_get_group(lpbuddy));
}
+
+
+/**
+ * Updates the status text cached in a buddy-list node.
+ *
+ * @param lpblistnode Buddy-list node.
+ */
+static void UpdateStatusText(PurpleBlistNode *lpblistnode)
+{
+ VULTURE_BLIST_NODE *lpvblistnode;
+
+ if(!lpblistnode || !lpblistnode->ui_data)
+ return;
+
+ lpvblistnode = lpblistnode->ui_data;
+
+ EnterCriticalSection(&lpvblistnode->cs);
+ {
+ if(lpvblistnode->szStatusText) g_free(lpvblistnode->szStatusText);
+ lpvblistnode->szStatusText = NULL;
+
+ if(PURPLE_BLIST_NODE_IS_BUDDY(lpblistnode))
+ lpvblistnode->szStatusText = PurpleBuddyGetStatusText((PurpleBuddy*)lpblistnode);
+ else if(PURPLE_BLIST_NODE_IS_CONTACT(lpblistnode))
+ {
+ PurpleBuddy *lpbuddy = purple_contact_get_priority_buddy((PurpleContact*)lpblistnode);
+
+ if(lpbuddy)
+ lpvblistnode->szStatusText = PurpleBuddyGetStatusText(lpbuddy);
+ }
+ }
+ LeaveCriticalSection(&lpvblistnode->cs);
+}
============================================================
--- vulture/resource.h c60b43d575373f275229fe49057eb7cc9923cde7
+++ vulture/resource.h 4806444826b8f8ce52dfdfad6cc050a5ecaec786
@@ -76,3 +76,4 @@
#define IDS_QUERY_DELCONTACT 8
#define IDS_BUDDYICON_FILTER 9
#define IDS_BUDDYICON_TITLE 10
+#define IDS_OFFLINE 11
============================================================
--- vulture/vulture-res.rc cdc489321f0878a09c10307c09e48a89f520efeb
+++ vulture/vulture-res.rc e2d01a0597f1e5b47b5809f0b7c72b95e4be85fd
@@ -219,6 +219,7 @@ STRINGTABLE
IDS_QUERY_DELCONTACT "Deleting this contact will also delete all buddies associated with it. Do you wish to continue?"
IDS_BUDDYICON_FILTER "Image Files\t*.bmp;*.png;*.gif;*.jpg\tAll Files (*.*)\t*.*\t"
IDS_BUDDYICON_TITLE "Choose Custom Icon"
+ IDS_OFFLINE "Offline"
}
============================================================
--- vulture/vultureblist.c 3ef1a8be976cd15568c8b695e2fdc97914dc7aa2
+++ vulture/vultureblist.c e8956ec9ef47112af9bce18e6e08890b7c17fa00
@@ -60,6 +60,8 @@ static void RemoveNodeRequest(HWND hwndB
static BOOL RunCommonMenuCmd(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode, HMENU hmenu, int iCmd);
static void RunChatMenuCmd(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode, HMENU hmenu, int iCmd);
static void RemoveNodeRequest(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode);
+static void UpdateBListNode(HWND hwndBlistTree, VULTURE_BLIST_NODE *lpvbn);
+static void DrawBListNodeExtra(LPNMTVCUSTOMDRAW lpnmtvcdraw);
#define BLIST_MARGIN 6
@@ -272,57 +274,11 @@ static LRESULT CALLBACK MainWndProc(HWND
break;
case VUIMSG_UPDATEBLISTNODE:
- {
- HWND hwndBlistTree = GetDlgItem(g_hwndBListDlg, IDC_TREE_BLIST);
- VULTURE_BLIST_NODE *lpvbn = (VULTURE_BLIST_NODE*)lParam;
+ UpdateBListNode(GetDlgItem(g_hwndBListDlg, IDC_TREE_BLIST), (VULTURE_BLIST_NODE*)lParam);
- EnterCriticalSection(&lpvbn->cs);
- {
- TVITEM tvitem;
+ /* Release the reference for this call. */
+ VultureBListNodeRelease((VULTURE_BLIST_NODE*)lParam);
- if(lpvbn->hti)
- {
- HTREEITEM htiParent = TreeView_GetParent(hwndBlistTree, lpvbn->hti);
-
- /* If the parent doesn't match, we need
- * to recreate.
- */
- if((lpvbn->lpvbnParent && lpvbn->lpvbnParent->hti != htiParent) ||
- (!lpvbn->lpvbnParent && htiParent))
- {
- RemoveBListNode(hwndBlistTree, lpvbn);
- }
- }
-
-
- /* New node? */
- if(!lpvbn->hti)
- {
- TVINSERTSTRUCT tvis;
-
- /* We cache this in the tree-view. */
- VultureBListNodeAddRef(lpvbn);
-
- tvis.hParent = lpvbn->lpvbnParent ? lpvbn->lpvbnParent->hti : TVI_ROOT;
- tvis.hInsertAfter = TVI_SORT;
- tvis.itemex.mask = TVIF_PARAM;
- tvis.itemex.lParam = (LPARAM)lpvbn;
-
- lpvbn->hti = TreeView_InsertItem(hwndBlistTree, &tvis);
- }
-
- /* Set text. */
- tvitem.mask = TVIF_TEXT | TVIF_HANDLE;
- tvitem.hItem = lpvbn->hti;
- tvitem.pszText = lpvbn->szNodeText;
- TreeView_SetItem(hwndBlistTree, &tvitem);
- }
- LeaveCriticalSection(&lpvbn->cs);
-
- /* Release the reference for this call. */
- VultureBListNodeRelease(lpvbn);
- }
-
break;
case VUIMSG_REMOVEBLISTNODE:
@@ -747,6 +703,31 @@ static INT_PTR CALLBACK BuddyListDlgProc
}
return TRUE;
+
+ case NM_CUSTOMDRAW:
+ {
+ LPNMTVCUSTOMDRAW lpnmtvcdraw = (LPNMTVCUSTOMDRAW)lParam;
+
+ switch(lpnmtvcdraw->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ /* Ask for notifications for each item. */
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
+ break;
+
+ case CDDS_ITEMPREPAINT:
+ /* Tell me when you've finished painting. */
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_NOTIFYPOSTPAINT);
+ break;
+
+ case CDDS_ITEMPOSTPAINT:
+ DrawBListNodeExtra(lpnmtvcdraw);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_DODEFAULT);
+ break;
+ }
+ }
+
+ return TRUE;
}
}
}
@@ -967,7 +948,7 @@ static void SetStatusMsg(HWND hwndStatus
/**
* Removes a buddy-list node, doing the requisite housekeeping.
*
- * @param hwndStatusDlg Buddy-list tree-view handle.
+ * @param hwndBlistTree Buddy-list tree-view handle.
* @param lpvbn Node to delete.
*/
static void RemoveBListNode(HWND hwndBlistTree, VULTURE_BLIST_NODE *lpvbn)
@@ -1027,6 +1008,9 @@ static void RunBuddyMenuCmd(HWND hwndBud
}
LeaveCriticalSection(&lpvblistnode->cs);
+ /* Update tree node. */
+ UpdateBListNode(hwndBuddies, lpvblistnode);
+
break;
case IDM_BLIST_CONTEXT_EXPAND:
@@ -1034,6 +1018,9 @@ static void RunBuddyMenuCmd(HWND hwndBud
VultureSingleSyncPurpleCall(PC_UPDATEBLISTCHILDREN, lpvblistnode);
PostMessage(hwndBuddies, TVM_EXPAND, TVE_EXPAND, (LPARAM)lpvblistnode->hti);
+ /* Update tree node. */
+ UpdateBListNode(hwndBuddies, lpvblistnode);
+
break;
}
}
@@ -1175,3 +1162,116 @@ static void RemoveNodeRequest(HWND hwndB
if(bDelete)
VultureSingleSyncPurpleCall(PC_REMOVEBLISTNODE, lpvblistnode);
}
+
+
+/**
+ * Updates a buddy-list node in the tree, according to its data.
+ *
+ * @param hwndBlistTree Buddy-list tree-view handle.
+ * @param lpvbn Node to update.
+ */
+static void UpdateBListNode(HWND hwndBlistTree, VULTURE_BLIST_NODE *lpvbn)
+{
+ EnterCriticalSection(&lpvbn->cs);
+ {
+ TVITEMEX tvitemex;
+
+ if(lpvbn->hti)
+ {
+ HTREEITEM htiParent = TreeView_GetParent(hwndBlistTree, lpvbn->hti);
+
+ /* If the parent doesn't match, we need
+ * to recreate.
+ */
+ if((lpvbn->lpvbnParent && lpvbn->lpvbnParent->hti != htiParent) ||
+ (!lpvbn->lpvbnParent && htiParent))
+ {
+ RemoveBListNode(hwndBlistTree, lpvbn);
+ }
+ }
+
+
+ /* New node? */
+ if(!lpvbn->hti)
+ {
+ TVINSERTSTRUCT tvis;
+
+ /* We cache this in the tree-view. */
+ VultureBListNodeAddRef(lpvbn);
+
+ tvis.hParent = lpvbn->lpvbnParent ? lpvbn->lpvbnParent->hti : TVI_ROOT;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.itemex.mask = TVIF_PARAM;
+ tvis.itemex.lParam = (LPARAM)lpvbn;
+
+ lpvbn->hti = TreeView_InsertItem(hwndBlistTree, &tvis);
+ }
+
+ /* Set text and height. */
+ tvitemex.mask = TVIF_HANDLE | TVIF_INTEGRAL;
+ tvitemex.hItem = lpvbn->hti;
+ tvitemex.iIntegral =
+ ((lpvbn->nodetype == PURPLE_BLIST_CONTACT_NODE && lpvbn->bExpanded) || lpvbn->nodetype == PURPLE_BLIST_GROUP_NODE) ?
+ 1 :
+ 2;
+ TreeView_SetItem(hwndBlistTree, &tvitemex);
+ }
+ LeaveCriticalSection(&lpvbn->cs);
+}
+
+
+/**
+ * Draws custom stuff for a buddy-list node.
+ *
+ * @param lpnmtvcdraw Custom-draw data for node.
+ */
+static void DrawBListNodeExtra(LPNMTVCUSTOMDRAW lpnmtvcdraw)
+{
+ RECT rcText, rcClient;
+ COLORREF crOldFG, crOldBG;
+ VULTURE_BLIST_NODE *lpvblistnode = (VULTURE_BLIST_NODE*)lpnmtvcdraw->nmcd.lItemlParam;
+
+ GetClientRect(lpnmtvcdraw->nmcd.hdr.hwndFrom, &rcClient);
+
+ /* Get the rectangle in which the control would render its text if it
+ * were doing so itself, and extend it to the right width.
+ */
+ TreeView_GetItemRect(lpnmtvcdraw->nmcd.hdr.hwndFrom, (HTREEITEM)lpnmtvcdraw->nmcd.dwItemSpec, &rcText, TRUE);
+ rcText.right = rcClient.right;
+ InflateRect(&rcText, -1, -1);
+
+ crOldBG = SetBkColor(lpnmtvcdraw->nmcd.hdc, lpnmtvcdraw->clrTextBk);
+ crOldFG = SetTextColor(lpnmtvcdraw->nmcd.hdc, lpnmtvcdraw->clrText);
+
+ EnterCriticalSection(&lpvblistnode->cs);
+ {
+ if(lpvblistnode->szStatusText &&
+ ((lpvblistnode->nodetype == PURPLE_BLIST_CONTACT_NODE && !lpvblistnode->bExpanded) ||
+ lpvblistnode->nodetype == PURPLE_BLIST_BUDDY_NODE))
+ {
+ HTREEITEM htiSel, htiDrop;
+
+ /* Render main text. */
+ if(lpvblistnode->szNodeText)
+ DrawText(lpnmtvcdraw->nmcd.hdc, lpvblistnode->szNodeText, -1, &rcText, DT_END_ELLIPSIS | DT_SINGLELINE);
+
+ /* Render secondary text. */
+ htiSel = TreeView_GetSelection(lpnmtvcdraw->nmcd.hdr.hwndFrom);
+ htiDrop = TreeView_GetDropHilight(lpnmtvcdraw->nmcd.hdr.hwndFrom);
+ if(htiDrop != (HTREEITEM)lpnmtvcdraw->nmcd.dwItemSpec &&
+ (htiSel != (HTREEITEM)lpnmtvcdraw->nmcd.dwItemSpec || htiDrop != NULL))
+ SetTextColor(lpnmtvcdraw->nmcd.hdc, 0x808080);
+ DrawText(lpnmtvcdraw->nmcd.hdc, lpvblistnode->szStatusText, -1, &rcText, DT_BOTTOM | DT_END_ELLIPSIS | DT_SINGLELINE);
+ }
+ else
+ {
+ /* No secondary text; render main text only. */
+ if(lpvblistnode->szNodeText)
+ DrawText(lpnmtvcdraw->nmcd.hdc, lpvblistnode->szNodeText, -1, &rcText, DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE);
+ }
+ }
+ LeaveCriticalSection(&lpvblistnode->cs);
+
+ SetTextColor(lpnmtvcdraw->nmcd.hdc, crOldFG);
+ SetBkColor(lpnmtvcdraw->nmcd.hdc, crOldBG);
+}
============================================================
--- vulture/vultureblist.h 166afd028ea80d8397fe633ecd5396a3236e6d9e
+++ vulture/vultureblist.h 516f25b18eb0dc962795616b27cea8c7e491c601
@@ -35,10 +35,13 @@ typedef struct _VULTURE_BLIST_NODE
PurpleBlistNode *lpblistnode;
PurpleBlistNodeType nodetype;
LPTSTR szNodeText;
+ LPTSTR szStatusText;
HTREEITEM hti;
struct _VULTURE_BLIST_NODE *lpvbnParent;
LONG lRefCount;
CRITICAL_SECTION cs;
+
+ /* For contacts. */
BOOL bExpanded;
} VULTURE_BLIST_NODE;
More information about the Commits
mailing list