summaryrefslogtreecommitdiff
path: root/src/mir_app
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2016-12-01 19:33:16 +0300
committerGeorge Hazan <ghazan@miranda.im>2016-12-01 19:33:35 +0300
commit06fc3d811d71a44b92d45e1263e5fb0099a7304e (patch)
treecbcdafbcddacab601a6d47321ec09aac5d5e5c0c /src/mir_app
parentbd408d296ccfa16dba379f3820a2007ff6963a6a (diff)
toolbar icons processing code moved to mir_app
Diffstat (limited to 'src/mir_app')
-rw-r--r--src/mir_app/res/resource.rc16
-rw-r--r--src/mir_app/src/chat_svc.cpp3
-rw-r--r--src/mir_app/src/mir_app.def10
-rw-r--r--src/mir_app/src/mir_app64.def10
-rw-r--r--src/mir_app/src/miranda.h1
-rw-r--r--src/mir_app/src/newplugins.cpp1
-rw-r--r--src/mir_app/src/resource.h8
-rw-r--r--src/mir_app/src/srmm_statusicon.cpp7
-rw-r--r--src/mir_app/src/srmm_toolbar.cpp739
9 files changed, 795 insertions, 0 deletions
diff --git a/src/mir_app/res/resource.rc b/src/mir_app/res/resource.rc
index 35eba4afd8..e994096bb2 100644
--- a/src/mir_app/res/resource.rc
+++ b/src/mir_app/res/resource.rc
@@ -791,6 +791,22 @@ BEGIN
CTEXT "",IDC_COLORTEXT,0,0,197,12,SS_CENTERIMAGE
END
+IDD_OPT_TOOLBAR DIALOGEX 0, 0, 303, 229
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_TOOLBARTREE,"SysTreeView32",TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | TVS_NOHSCROLL | TVS_CHECKBOXES | TVS_FULLROWSELECT | WS_HSCROLL | WS_TABSTOP,1,4,301,171,WS_EX_CLIENTEDGE
+ PUSHBUTTON "Reset",IDC_BBRESET,250,211,53,15
+ CONTROL "Show in IM chats",IDC_IMCHECK,"Button",BS_AUTOCHECKBOX | BS_VCENTER | BS_MULTILINE | WS_TABSTOP,4,181,127,12
+ CONTROL "Show in chat rooms",IDC_CHATCHECK,"Button",BS_AUTOCHECKBOX | BS_VCENTER | BS_MULTILINE | WS_TABSTOP,4,196,127,12
+ CONTROL "",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_GROUP,272,183,11,12
+ RTEXT "Gap between buttons:",IDC_STATIC,136,183,104,12,SS_CENTERIMAGE
+ CONTROL "Hide if there isn't enough space",IDC_CANBEHIDDEN,
+ "Button",BS_AUTOCHECKBOX | BS_VCENTER | BS_MULTILINE | WS_TABSTOP,4,209,131,17
+ PUSHBUTTON "Insert separator",IDC_SEPARATOR,137,211,103,15,BS_MULTILINE
+END
+
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
diff --git a/src/mir_app/src/chat_svc.cpp b/src/mir_app/src/chat_svc.cpp
index 3ce6a8417d..879fab56c9 100644
--- a/src/mir_app/src/chat_svc.cpp
+++ b/src/mir_app/src/chat_svc.cpp
@@ -741,6 +741,7 @@ int LoadChatModule(void)
HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown);
HookEvent(ME_SKIN_ICONSCHANGED, IconsChanged);
+ chatApi.hWindowList = WindowList_Create();
chatApi.hSendEvent = CreateHookableEvent(ME_GC_EVENT);
chatApi.hBuildMenuEvent = CreateHookableEvent(ME_GC_BUILDMENU);
hHookEvent = CreateHookableEvent(ME_GC_HOOK_EVENT);
@@ -763,6 +764,8 @@ void UnloadChatModule(void)
FreeMsgLogBitmaps();
OptionsUnInit();
+ WindowList_Destroy(chatApi.hWindowList);
+
DestroyHookableEvent(chatApi.hSendEvent);
DestroyHookableEvent(chatApi.hBuildMenuEvent);
DestroyHookableEvent(hHookEvent);
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def
index cb33d7d808..75a8b9629c 100644
--- a/src/mir_app/src/mir_app.def
+++ b/src/mir_app/src/mir_app.def
@@ -327,3 +327,13 @@ Options_AddPage @327
Options_Open @328
Options_OpenPage @329
Chat_HoverMouse @330
+Srmm_ModifyButton @331
+Srmm_AddButton @332
+Srmm_GetButtonState @333
+Srmm_RemoveButton @334
+Srmm_ResetToolbar @335
+Srmm_SetButtonState @336
+Srmm_UpdateToolbarIcons @337
+Srmm_RedrawToolbarIcons @338
+Srmm_GetNthButton @339
+Srmm_GetButtonCount @340
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def
index 6bf981dead..5d571223a0 100644
--- a/src/mir_app/src/mir_app64.def
+++ b/src/mir_app/src/mir_app64.def
@@ -327,3 +327,13 @@ Options_AddPage @327
Options_Open @328
Options_OpenPage @329
Chat_HoverMouse @330
+Srmm_ModifyButton @331
+Srmm_AddButton @332
+Srmm_GetButtonState @333
+Srmm_RemoveButton @334
+Srmm_ResetToolbar @335
+Srmm_SetButtonState @336
+Srmm_UpdateToolbarIcons @337
+Srmm_RedrawToolbarIcons @338
+Srmm_GetNthButton @339
+Srmm_GetButtonCount @340
diff --git a/src/mir_app/src/miranda.h b/src/mir_app/src/miranda.h
index a440c951ad..cf54e15b4a 100644
--- a/src/mir_app/src/miranda.h
+++ b/src/mir_app/src/miranda.h
@@ -78,6 +78,7 @@ void InitPathVar(void);
/**** srmm.cpp *************************************************************************/
void KillModuleSrmmIcons(int hLangpack);
+void KillModuleToolbarIcons(int hLangpack);
/**** utf.cpp **************************************************************************/
diff --git a/src/mir_app/src/newplugins.cpp b/src/mir_app/src/newplugins.cpp
index e282f4aa26..9fbb3e9b4a 100644
--- a/src/mir_app/src/newplugins.cpp
+++ b/src/mir_app/src/newplugins.cpp
@@ -358,6 +358,7 @@ int Plugin_UnloadDyn(pluginEntry *p)
KillModuleSounds(_hLang);
KillModuleExtraIcons(_hLang);
KillModuleSrmmIcons(_hLang);
+ KillModuleToolbarIcons(_hLang);
}
NotifyFastHook(hevUnloadModule, (WPARAM)p->bpi.pluginInfo, (LPARAM)p->bpi.hInst);
diff --git a/src/mir_app/src/resource.h b/src/mir_app/src/resource.h
index e126bcb0fb..eb56125575 100644
--- a/src/mir_app/src/resource.h
+++ b/src/mir_app/src/resource.h
@@ -12,6 +12,7 @@
#define IDI_SMS 103
#define IDI_ONLINE 104
#define IDI_OFFLINE 105
+#define IDD_OPT_TOOLBAR 106
#define IDD_OPT_FONTS 107
#define IDD_OPT_GENMENU 108
#define IDD_OPT_PROTOCOLORDER 109
@@ -220,6 +221,7 @@
#define IDC_URLS 1037
#define IDC_COLORTEXT 1038
#define IDC_REPLY 1039
+#define IDC_TOOLBARTREE 1040
#define IDC_URL 1041
#define IDC_FONTGROUP 1042
#define IDC_BTN_RESET 1045
@@ -230,6 +232,7 @@
#define IDC_NAMENICK 1049
#define IDC_NAMEFIRST 1050
#define IDC_NAMELAST 1051
+#define IDC_BBRESET 1052
#define IDC_NICK 1053
#define IDC_BTN_EXPORT 1054
#define IDC_FONTLIST 1056
@@ -278,6 +281,11 @@
#define IDC_TXT_PASSWORD 1097
#define IDC_TXT_COMBO 1098
#define IDC_TXT_RICHEDIT 1099
+#define IDC_IMCHECK 1100
+#define IDC_CHATCHECK 1101
+#define IDC_CANBEHIDDEN 1102
+#define IDC_SPIN1 1103
+#define IDC_SEPARATOR 1104
#define IDC_BUILDTIME 1108
#define IDC_CREDITSFILE 1109
#define IDC_NUMBER 1113
diff --git a/src/mir_app/src/srmm_statusicon.cpp b/src/mir_app/src/srmm_statusicon.cpp
index eb2ded0671..a780effdcb 100644
--- a/src/mir_app/src/srmm_statusicon.cpp
+++ b/src/mir_app/src/srmm_statusicon.cpp
@@ -23,6 +23,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
+void LoadSrmmToolbarModule();
+void UnloadSrmmToolbarModule();
+
void SafeDestroyIcon(HICON hIcon)
{
if (hIcon != NULL)
@@ -202,6 +205,8 @@ void KillModuleSrmmIcons(int _hLang)
int LoadSrmmModule()
{
+ LoadSrmmToolbarModule();
+
hHookIconsChanged = CreateHookableEvent(ME_MSG_ICONSCHANGED);
return 0;
}
@@ -211,4 +216,6 @@ void UnloadSrmmModule()
arIcons.destroy();
NotifyEventHooks(hHookIconsChanged, NULL, NULL);
DestroyHookableEvent(hHookIconsChanged);
+
+ UnloadSrmmToolbarModule();
}
diff --git a/src/mir_app/src/srmm_toolbar.cpp b/src/mir_app/src/srmm_toolbar.cpp
new file mode 100644
index 0000000000..ce6cf921cf
--- /dev/null
+++ b/src/mir_app/src/srmm_toolbar.cpp
@@ -0,0 +1,739 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (ñ) 2012-16 Miranda NG project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+#define MODULENAME "SRMsg"
+
+#define DPISCALEY_S(argY) ((int)((double)(argY) * g_DPIscaleY))
+#define DPISCALEX_S(argX) ((int)((double)(argX) * g_DPIscaleX))
+
+static double g_DPIscaleX, g_DPIscaleY;
+
+static int SortButtons(const CustomButtonData *p1, const CustomButtonData *p2)
+{
+ if (p1->m_bRSided != p2->m_bRSided)
+ return (p2->m_bRSided) ? -1 : 1;
+ return p1->m_dwPosition - p2->m_dwPosition;
+}
+
+static LIST<CustomButtonData> arButtonsList(1, SortButtons);
+
+DWORD LastCID = 4000;
+DWORD dwSepCount = 0;
+
+static mir_cs csToolBar;
+static HANDLE hHookToolBarLoadedEvt;
+
+static void wipeList(LIST<CustomButtonData> &list)
+{
+ for (int i = list.getCount() - 1; i >= 0; i--) {
+ delete list[i];
+ list.remove(i);
+ }
+}
+
+static int sstSortButtons(const void *p1, const void *p2)
+{
+ return SortButtons(*(CustomButtonData**)p1, *(CustomButtonData**)p2);
+}
+
+static void CB_RegisterSeparators()
+{
+ BBButton bbd = { 0 };
+ bbd.pszModuleName = "Tabsrmm_sep";
+ for (DWORD i = 0; dwSepCount > i; i++) {
+ bbd.bbbFlags = BBBF_ISDUMMYBUTTON | BBBF_ISIMBUTTON;
+ bbd.dwButtonID = i + 1;
+ bbd.dwDefPos = 410 + i;
+ Srmm_AddButton(&bbd);
+ }
+}
+
+static void CB_GetButtonSettings(MCONTACT hContact, CustomButtonData *cbd)
+{
+ DBVARIANT dbv = { 0 };
+ char SettingName[1024];
+ char* token = NULL;
+
+ // modulename_buttonID, position_inIM_inCHAT_isLSide_isRSide_CanBeHidden
+
+ mir_snprintf(SettingName, "%s_%d", cbd->m_pszModuleName, cbd->m_dwButtonOrigID);
+
+ if (!db_get_s(hContact, "TabSRMM_Toolbar", SettingName, &dbv)) {
+ token = strtok(dbv.pszVal, "_");
+ cbd->m_dwPosition = (DWORD)atoi(token);
+ token = strtok(NULL, "_");
+ cbd->m_bIMButton = atoi(token) != 0;
+ token = strtok(NULL, "_");
+ cbd->m_bChatButton = atoi(token) != 0;
+ token = strtok(NULL, "_");
+ token = strtok(NULL, "_");
+ cbd->m_bRSided = atoi(token) != 0;
+ token = strtok(NULL, "_");
+ cbd->m_bCanBeHidden = atoi(token) != 0;
+
+ db_free(&dbv);
+ }
+}
+
+MIR_APP_DLL(CustomButtonData*) Srmm_GetNthButton(int i)
+{
+ return arButtonsList[i];
+}
+
+MIR_APP_DLL(int) Srmm_GetButtonCount(void)
+{
+ return arButtonsList.getCount();
+}
+
+MIR_APP_DLL(int) Srmm_AddButton(const BBButton *bbdi, int _hLang)
+{
+ if (bbdi == NULL)
+ return 1;
+
+ CustomButtonData *cbd = new CustomButtonData();
+ if (!bbdi->iButtonWidth && (bbdi->bbbFlags & BBBF_ISARROWBUTTON))
+ cbd->m_iButtonWidth = DPISCALEX_S(34);
+ else if (!bbdi->iButtonWidth)
+ cbd->m_iButtonWidth = DPISCALEX_S(22);
+ else
+ cbd->m_iButtonWidth = DPISCALEX_S(bbdi->iButtonWidth);
+
+ cbd->m_pszModuleName = mir_strdup(bbdi->pszModuleName);
+ cbd->m_pwszTooltip = mir_wstrdup(bbdi->pwszTooltip);
+
+ cbd->m_dwButtonOrigID = bbdi->dwButtonID;
+ cbd->m_hIcon = bbdi->hIcon;
+ cbd->m_dwPosition = bbdi->dwDefPos;
+ cbd->m_dwButtonCID = (bbdi->bbbFlags & BBBF_CREATEBYID) ? bbdi->dwButtonID : LastCID;
+ cbd->m_dwArrowCID = (bbdi->bbbFlags & BBBF_ISARROWBUTTON) ? cbd->m_dwButtonCID + 1 : 0;
+ cbd->m_bHidden = (bbdi->bbbFlags & BBBF_HIDDEN) != 0;
+ cbd->m_bRSided = (bbdi->bbbFlags & BBBF_ISRSIDEBUTTON) != 0;
+ cbd->m_bCanBeHidden = (bbdi->bbbFlags & BBBF_CANBEHIDDEN) != 0;
+ cbd->m_bSeparator = (bbdi->bbbFlags & BBBF_ISDUMMYBUTTON) != 0;
+ cbd->m_bChatButton = (bbdi->bbbFlags & BBBF_ISCHATBUTTON) != 0;
+ cbd->m_bIMButton = (bbdi->bbbFlags & BBBF_ISIMBUTTON) != 0;
+ cbd->m_bDisabled = (bbdi->bbbFlags & BBBF_DISABLED) != 0;
+ cbd->m_bPushButton = (bbdi->bbbFlags & BBBF_ISPUSHBUTTON) != 0;
+ cbd->m_hLangpack = _hLang;
+
+ // download database settings
+ CB_GetButtonSettings(NULL, cbd);
+
+ arButtonsList.insert(cbd);
+
+ if (cbd->m_dwButtonCID != cbd->m_dwButtonOrigID)
+ LastCID++;
+ if (cbd->m_dwArrowCID == LastCID)
+ LastCID++;
+
+ WindowList_Broadcast(chatApi.hWindowList, WM_CBD_UPDATED, 0, 0);
+ return 0;
+}
+
+MIR_APP_DLL(int) Srmm_GetButtonState(HWND hwndDlg, BBButton *bbdi)
+{
+ if (hwndDlg == NULL || bbdi == NULL)
+ return 1;
+
+ DWORD tempCID = 0;
+ bool realbutton = false;
+ bbdi->bbbFlags = 0;
+ for (int i = 0; i < arButtonsList.getCount(); i++) {
+ CustomButtonData *cbd = arButtonsList[i];
+ if (!mir_strcmp(cbd->m_pszModuleName, bbdi->pszModuleName) && (cbd->m_dwButtonOrigID == bbdi->dwButtonID)) {
+ realbutton = true;
+ tempCID = cbd->m_dwButtonCID;
+ }
+ }
+ if (!realbutton)
+ return 1;
+
+ HWND hwndBtn = GetDlgItem(hwndDlg, tempCID);
+ bbdi->bbbFlags = (IsDlgButtonChecked(hwndDlg, tempCID) ? BBSF_PUSHED : BBSF_RELEASED) | (IsWindowVisible(hwndBtn) ? 0 : BBSF_HIDDEN) | (IsWindowEnabled(hwndBtn) ? 0 : BBSF_DISABLED);
+ return 0;
+}
+
+MIR_APP_DLL(int) Srmm_SetButtonState(MCONTACT hContact, BBButton *bbdi)
+{
+ if (hContact == NULL || bbdi == NULL)
+ return 1;
+
+ bool realbutton = false;
+ DWORD tempCID = 0;
+ for (int i = 0; i < arButtonsList.getCount(); i++) {
+ CustomButtonData *cbd = arButtonsList[i];
+ if (!mir_strcmp(cbd->m_pszModuleName, bbdi->pszModuleName) && (cbd->m_dwButtonOrigID == bbdi->dwButtonID)) {
+ realbutton = true;
+ tempCID = cbd->m_dwButtonCID;
+ }
+ }
+ if (!realbutton)
+ return 1;
+
+ HWND hwndDlg = WindowList_Find(NULL, hContact);
+ if (hwndDlg == NULL)
+ return 1;
+
+ HWND hwndBtn = GetDlgItem(hwndDlg, tempCID);
+ if (hwndBtn == NULL)
+ return 1;
+
+ SetWindowTextA(hwndBtn, bbdi->pszModuleName);
+ if (bbdi->hIcon)
+ SendMessage(hwndBtn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIconByHandle(bbdi->hIcon));
+ if (bbdi->pwszTooltip)
+ SendMessage(hwndBtn, BUTTONADDTOOLTIP, (WPARAM)bbdi->pwszTooltip, BATF_UNICODE);
+ if (bbdi->bbbFlags) {
+ ShowWindow(hwndBtn, (bbdi->bbbFlags & BBSF_HIDDEN) ? SW_HIDE : SW_SHOW);
+ EnableWindow(hwndBtn, !(bbdi->bbbFlags & BBSF_DISABLED));
+ Button_SetCheck(hwndBtn, (bbdi->bbbFlags & BBSF_PUSHED) != 0);
+ Button_SetCheck(hwndBtn, (bbdi->bbbFlags & BBSF_RELEASED) != 0);
+ }
+ return 0;
+}
+
+MIR_APP_DLL(int) Srmm_RemoveButton(BBButton *bbdi)
+{
+ if (!bbdi)
+ return 1;
+
+ CustomButtonData *pFound = NULL;
+ {
+ mir_cslock lck(csToolBar);
+
+ for (int i = arButtonsList.getCount() - 1; i >= 0; i--) {
+ CustomButtonData *cbd = arButtonsList[i];
+ if (!mir_strcmp(cbd->m_pszModuleName, bbdi->pszModuleName) && cbd->m_dwButtonOrigID == bbdi->dwButtonID) {
+ pFound = cbd;
+ arButtonsList.remove(i);
+ }
+ }
+ }
+
+ if (pFound) {
+ WindowList_Broadcast(chatApi.hWindowList, WM_CBD_REMOVED, pFound->m_dwButtonCID, (LPARAM)pFound);
+ delete pFound;
+ }
+ return 0;
+}
+
+MIR_APP_DLL(int) Srmm_ModifyButton(BBButton *bbdi)
+{
+ if (!bbdi)
+ return 1;
+
+ bool bFound = false;
+ CustomButtonData *cbd = NULL;
+ {
+ mir_cslock lck(csToolBar);
+
+ for (int i = 0; i < arButtonsList.getCount(); i++) {
+ cbd = arButtonsList[i];
+ if (!mir_strcmp(cbd->m_pszModuleName, bbdi->pszModuleName) && (cbd->m_dwButtonOrigID == bbdi->dwButtonID)) {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (bFound) {
+ if (bbdi->pwszTooltip)
+ cbd->m_pwszTooltip = mir_wstrdup(bbdi->pwszTooltip);
+ if (bbdi->hIcon)
+ cbd->m_hIcon = bbdi->hIcon;
+ if (bbdi->bbbFlags) {
+ cbd->m_bHidden = (bbdi->bbbFlags & BBBF_HIDDEN) != 0;
+ cbd->m_bRSided = (bbdi->bbbFlags & BBBF_ISRSIDEBUTTON) != 0;
+ cbd->m_bCanBeHidden = (bbdi->bbbFlags & BBBF_CANBEHIDDEN) != 0;
+ cbd->m_bChatButton = (bbdi->bbbFlags & BBBF_ISCHATBUTTON) != 0;
+ cbd->m_bIMButton = (bbdi->bbbFlags & BBBF_ISIMBUTTON) != 0;
+ cbd->m_bDisabled = (bbdi->bbbFlags & BBBF_DISABLED) != 0;
+ }
+ }
+ }
+
+ if (bFound)
+ WindowList_Broadcast(chatApi.hWindowList, WM_CBD_UPDATED, 0, (LPARAM)cbd);
+ return 0;
+}
+
+MIR_APP_DLL(void) Srmm_ResetToolbar()
+{
+ { mir_cslock lck(csToolBar);
+ wipeList(arButtonsList);
+ }
+ LastCID = 4000;
+ dwSepCount = 0;
+}
+
+MIR_APP_DLL(void) Srmm_UpdateToolbarIcons(HWND hwndDlg)
+{
+ for (int i = 0; i < arButtonsList.getCount(); i++) {
+ CustomButtonData *cbd = arButtonsList[i];
+ if (cbd) {
+ if (!cbd->m_bSeparator) {
+ HWND hwndBtn = GetDlgItem(hwndDlg, cbd->m_dwButtonCID);
+ if (hwndBtn && cbd->m_hIcon)
+ SendMessage(hwndBtn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIconByHandle(cbd->m_hIcon));
+ }
+ }
+ }
+}
+
+MIR_APP_DLL(void) Srmm_RedrawToolbarIcons(HWND hwndDlg)
+{
+ for (int i = 0; i < arButtonsList.getCount(); i++) {
+ CustomButtonData *cbd = arButtonsList[i];
+ HWND hwnd = GetDlgItem(hwndDlg, cbd->m_dwButtonCID);
+ if (hwnd)
+ InvalidateRect(hwnd, 0, TRUE);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void CB_HardReInit()
+{
+ WindowList_Broadcast(chatApi.hWindowList, WM_CBD_REMOVED, 0, 0);
+
+ Srmm_ResetToolbar();
+ NotifyEventHooks(hHookToolBarLoadedEvt, 0, 0);
+}
+
+static void CB_ReInitCustomButtons()
+{
+ for (int i = arButtonsList.getCount() - 1; i >= 0; i--) {
+ CustomButtonData *cbd = arButtonsList[i];
+
+ if (cbd->m_opFlags & (BBSF_NTBSWAPED | BBSF_NTBDESTRUCT)) {
+ cbd->m_opFlags ^= BBSF_NTBSWAPED;
+
+ if (cbd->m_opFlags & BBSF_NTBDESTRUCT)
+ arButtonsList.remove(i);
+ }
+ }
+ qsort(arButtonsList.getArray(), arButtonsList.getCount(), sizeof(void*), sstSortButtons);
+
+ WindowList_Broadcast(chatApi.hWindowList, WM_CBD_UPDATED, 0, 0);
+ WindowList_Broadcast(chatApi.hWindowList, WM_CBD_LOADICONS, 0, 0);
+}
+
+static void CB_WriteButtonSettings(MCONTACT hContact, CustomButtonData *cbd)
+{
+ char SettingName[1024];
+ char SettingParameter[1024];
+
+ //modulename_buttonID, position_inIM_inCHAT_isLSide_isRSide_CanBeHidden
+
+ mir_snprintf(SettingName, "%s_%d", cbd->m_pszModuleName, cbd->m_dwButtonOrigID);
+ mir_snprintf(SettingParameter, "%d_%u_%u_%u_%u_%u", cbd->m_dwPosition, cbd->m_bIMButton, cbd->m_bChatButton, 0, cbd->m_bRSided, cbd->m_bCanBeHidden);
+ if (!(cbd->m_opFlags & BBSF_NTBDESTRUCT))
+ db_set_s(hContact, "TabSRMM_Toolbar", SettingName, SettingParameter);
+ else
+ db_unset(hContact, "TabSRMM_Toolbar", SettingName);
+}
+
+#define MIDDLE_SEPARATOR L">-------M-------<"
+
+class CSrmmToolbarOptions : public CDlgBase
+{
+ CCtrlTreeView m_toolBar;
+ CCtrlCheck m_btnIM, m_btnChat, m_btnHidden;
+ CCtrlButton m_btnReset, m_btnSeparator;
+ CCtrlSpin m_gap;
+
+ HIMAGELIST m_hImgl;
+
+ void SaveTree()
+ {
+ bool RSide = false;
+ int count = 10;
+ DWORD loc_sepcout = 0;
+ wchar_t strbuf[128];
+
+ TVITEMEX tvi;
+ tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE;
+ tvi.hItem = m_toolBar.GetRoot();
+ tvi.pszText = strbuf;
+ tvi.cchTextMax = _countof(strbuf);
+ {
+ mir_cslock lck(csToolBar);
+
+ while (tvi.hItem != NULL) {
+ m_toolBar.GetItem(&tvi);
+
+ if (mir_wstrcmp(tvi.pszText, MIDDLE_SEPARATOR) == 0) {
+ RSide = true;
+ count = m_toolBar.GetCount() * 10 - count;
+ tvi.hItem = m_toolBar.GetNextSibling(tvi.hItem);
+ continue;
+ }
+ CustomButtonData *cbd = (CustomButtonData*)tvi.lParam;
+ if (cbd) {
+ if (cbd->m_opFlags) {
+ cbd->m_bIMButton = (cbd->m_opFlags & BBSF_IMBUTTON) != 0;
+ cbd->m_bChatButton = (cbd->m_opFlags & BBSF_CHATBUTTON) != 0;
+ cbd->m_bCanBeHidden = (cbd->m_opFlags & BBSF_CANBEHIDDEN) != 0;
+ }
+ if (RSide && !cbd->m_bRSided) {
+ cbd->m_bRSided = true;
+ cbd->m_opFlags |= BBSF_NTBSWAPED;
+ }
+ else if (!RSide && cbd->m_bRSided) {
+ cbd->m_bRSided = false;
+ cbd->m_opFlags |= BBSF_NTBSWAPED;
+ }
+ if (!m_toolBar.GetCheckState(tvi.hItem)) {
+ cbd->m_bIMButton = false;
+ cbd->m_bChatButton = false;
+
+ if (cbd->m_bSeparator && !mir_strcmp(cbd->m_pszModuleName, "Tabsrmm_sep"))
+ cbd->m_opFlags = BBSF_NTBDESTRUCT;
+ }
+ else {
+ if (!cbd->m_bIMButton && !cbd->m_bChatButton)
+ cbd->m_bIMButton = true;
+ if (cbd->m_bSeparator && !mir_strcmp(cbd->m_pszModuleName, "Tabsrmm_sep")) {
+ cbd->m_bHidden = 0;
+ cbd->m_opFlags &= ~BBSF_NTBDESTRUCT;
+ ++loc_sepcout;
+ }
+ }
+
+ cbd->m_dwPosition = (DWORD)count;
+ CB_WriteButtonSettings(NULL, cbd);
+
+ if (!(cbd->m_opFlags & BBSF_NTBDESTRUCT))
+ (RSide) ? (count -= 10) : (count += 10);
+ }
+
+ HTREEITEM hItem = m_toolBar.GetNextSibling(tvi.hItem);
+ if (cbd->m_opFlags & BBSF_NTBDESTRUCT)
+ m_toolBar.DeleteItem(tvi.hItem);
+ tvi.hItem = hItem;
+ }
+
+ qsort(arButtonsList.getArray(), arButtonsList.getCount(), sizeof(void*), sstSortButtons);
+ }
+ db_set_dw(0, "TabSRMM_Toolbar", "SeparatorsCount", loc_sepcout);
+ dwSepCount = loc_sepcout;
+ }
+
+ void BuildMenuObjectsTree()
+ {
+ HTREEITEM hti;
+ int iImage = 0;
+
+ TVINSERTSTRUCT tvis;
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE;
+
+ m_toolBar.DeleteAllItems();
+
+ m_hImgl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 2, 2);
+ ImageList_AddIcon(m_hImgl, Skin_LoadIcon(SKINICON_OTHER_SMALLDOT));
+ ImageList_Destroy(m_toolBar.GetImageList(TVSIL_NORMAL));
+ m_toolBar.SetImageList(m_hImgl, TVSIL_NORMAL);
+
+ if (arButtonsList.getCount() == 0)
+ return;
+
+ bool bPrevSide = false;
+ mir_cslock lck(csToolBar);
+
+ for (int i = 0; i < arButtonsList.getCount(); i++) {
+ CustomButtonData *cbd = arButtonsList[i];
+
+ if (bPrevSide != cbd->m_bRSided) {
+ bPrevSide = true;
+
+ TVINSERTSTRUCT tvis2 = {};
+ tvis.hInsertAfter = TVI_LAST;
+ tvis2.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_STATE;
+ tvis2.item.pszText = MIDDLE_SEPARATOR;
+ tvis2.item.stateMask = TVIS_BOLD;
+ tvis2.item.state = TVIS_BOLD;
+ tvis2.item.iImage = tvis.item.iSelectedImage = -1;
+ tvis.hInsertAfter = hti = m_toolBar.InsertItem(&tvis2);
+ m_toolBar.SetCheckState(hti, 1);
+ }
+
+ tvis.item.lParam = (LPARAM)cbd;
+
+ if (cbd->m_bSeparator) {
+ tvis.item.pszText = TranslateT("<Separator>");
+ tvis.item.iImage = tvis.item.iSelectedImage = 0;
+ }
+ else {
+ tvis.item.pszText = TranslateW(cbd->m_pwszTooltip);
+ iImage = ImageList_AddIcon(m_hImgl, IcoLib_GetIconByHandle(cbd->m_hIcon));
+ tvis.item.iImage = tvis.item.iSelectedImage = iImage;
+ }
+ cbd->m_opFlags = 0;
+ hti = m_toolBar.InsertItem(&tvis);
+
+ m_toolBar.SetCheckState(hti, (cbd->m_bIMButton || cbd->m_bChatButton));
+ }
+ }
+
+public:
+ CSrmmToolbarOptions() :
+ CDlgBase(g_hInst, IDD_OPT_TOOLBAR),
+ m_gap(this, IDC_SPIN1),
+ m_btnIM(this, IDC_IMCHECK),
+ m_btnChat(this, IDC_CHATCHECK),
+ m_toolBar(this, IDC_TOOLBARTREE),
+ m_btnReset(this, IDC_BBRESET),
+ m_btnHidden(this, IDC_CANBEHIDDEN),
+ m_btnSeparator(this, IDC_SEPARATOR),
+ m_hImgl(NULL)
+ {
+ m_toolBar.SetFlags(MTREE_DND); // enable drag-n-drop
+
+ m_btnReset.OnClick = Callback(this, &CSrmmToolbarOptions::btnResetClicked);
+ m_btnSeparator.OnClick = Callback(this, &CSrmmToolbarOptions::btnSeparatorClicked);
+ }
+
+ virtual void OnInitDialog() override
+ {
+ BuildMenuObjectsTree();
+
+ m_btnIM.Disable();
+ m_btnChat.Disable();
+ m_btnHidden.Disable();
+
+ m_gap.SetRange(10);
+ m_gap.SetPosition(db_get_b(NULL, MODULENAME, "ButtonsBarGap", 1));
+ }
+
+ virtual void OnDestroy() override
+ {
+ ImageList_Destroy(m_toolBar.GetImageList(TVSIL_NORMAL));
+ ImageList_Destroy(m_toolBar.GetImageList(TVSIL_STATE));
+ }
+
+ virtual void OnApply() override
+ {
+ HTREEITEM hItem = m_toolBar.GetSelection();
+ if (hItem) {
+ TVITEMEX tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hItem;
+ m_toolBar.GetItem(&tvi);
+
+ if (tvi.lParam) {
+ CustomButtonData *cbd = (CustomButtonData*)tvi.lParam;
+ if (cbd) {
+ cbd->m_bIMButton = m_btnIM.Enabled() != 0;
+ cbd->m_bChatButton = m_btnChat.Enabled() != 0;
+ cbd->m_bCanBeHidden = m_btnHidden.Enabled() != 0;
+ }
+ }
+ }
+
+ SaveTree();
+ CB_ReInitCustomButtons();
+
+ BYTE newGap = (BYTE)SendDlgItemMessage(m_hwnd, IDC_SPIN1, UDM_GETPOS, 0, 0);
+ if (newGap != db_get_b(NULL, MODULENAME, "ButtonsBarGap", 1))
+ WindowList_BroadcastAsync(chatApi.hWindowList, WM_SIZE, 0, 0);
+
+ db_set_b(0, MODULENAME, "ButtonsBarGap", newGap);
+
+ BuildMenuObjectsTree();
+
+ m_btnIM.Disable();
+ m_btnChat.Disable();
+ m_btnHidden.Disable();
+ }
+
+ virtual void OnReset() override
+ {
+ CB_ReInitCustomButtons();
+ dwSepCount = db_get_dw(NULL, MODULENAME, "SeparatorsCount", 0);
+ }
+
+ void btnResetClicked(void*)
+ {
+ db_delete_module(NULL, MODULENAME);
+ CB_HardReInit();
+ BuildMenuObjectsTree();
+ }
+
+ void btnSeparatorClicked(void*)
+ {
+ HTREEITEM hItem = m_toolBar.GetSelection();
+ if (!hItem)
+ hItem = TVI_FIRST;
+
+ CustomButtonData *cbd = new CustomButtonData();
+ cbd->m_bSeparator = cbd->m_bHidden = cbd->m_bIMButton = true;
+ cbd->m_dwButtonOrigID = ++dwSepCount;
+ cbd->m_pszModuleName = "Tabsrmm_sep";
+ cbd->m_iButtonWidth = 22;
+ cbd->m_opFlags = BBSF_NTBDESTRUCT;
+ arButtonsList.insert(cbd);
+
+ TVINSERTSTRUCT tvis;
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = hItem;
+ tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+
+ tvis.item.pszText = TranslateT("<Separator>");
+ tvis.item.iImage = tvis.item.iSelectedImage = -1;
+ tvis.item.lParam = (LPARAM)cbd;
+ hItem = m_toolBar.InsertItem(&tvis);
+
+ m_toolBar.SetCheckState(hItem, (cbd->m_bIMButton || cbd->m_bChatButton));
+ }
+
+ void OnTreeSelChanging(void*)
+ {
+ HTREEITEM hItem = m_toolBar.GetSelection();
+ if (hItem == NULL)
+ return;
+
+ wchar_t strbuf[128];
+ TVITEMEX tvi;
+ tvi.hItem = hItem;
+ tvi.pszText = strbuf;
+ tvi.cchTextMax = _countof(strbuf);
+ tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
+ m_toolBar.GetItem(&tvi);
+
+ if (tvi.lParam == 0 || !m_toolBar.GetCheckState(tvi.hItem) || !mir_wstrcmp(tvi.pszText, MIDDLE_SEPARATOR))
+ return;
+
+ CustomButtonData *cbd = (CustomButtonData*)tvi.lParam;
+ cbd->m_bIMButton = m_btnIM.GetState() != 0;
+ cbd->m_bChatButton = m_btnChat.GetState() != 0;
+ cbd->m_bCanBeHidden = m_btnHidden.GetState() != 0;
+ cbd->m_opFlags = (cbd->m_bIMButton ? BBSF_IMBUTTON : 0) + (cbd->m_bChatButton ? BBSF_CHATBUTTON : 0) + (cbd->m_bCanBeHidden ? BBSF_CANBEHIDDEN : 0);
+ }
+
+ void OnTreeSelChanged(void*)
+ {
+ HTREEITEM hItem = m_toolBar.GetSelection();
+ if (hItem == NULL)
+ return;
+
+ wchar_t strbuf[128];
+ TVITEMEX tvi;
+ tvi.pszText = strbuf;
+ tvi.cchTextMax = _countof(strbuf);
+ tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hItem;
+ m_toolBar.GetItem(&tvi);
+
+ if (!m_toolBar.GetCheckState(tvi.hItem) || !mir_wstrcmp(tvi.pszText, MIDDLE_SEPARATOR)) {
+ m_btnIM.Disable();
+ m_btnChat.Disable();
+ m_btnHidden.Disable();
+ return;
+ }
+
+ if (tvi.lParam == 0)
+ return;
+
+ CustomButtonData *cbd = (CustomButtonData*)tvi.lParam;
+ m_btnIM.Enable(); m_btnIM.SetState(cbd->m_bIMButton);
+ m_btnChat.Enable(); m_btnChat.SetState(cbd->m_bChatButton);
+ m_btnHidden.Enable(); m_btnHidden.SetState(cbd->m_bCanBeHidden);
+ }
+
+ void OnTreeClicked(void*)
+ {
+ TVHITTESTINFO hti = { 0 };
+ GetCursorPos(&hti.pt);
+ ScreenToClient(m_toolBar.GetHwnd(), &hti.pt);
+ if (m_toolBar.HitTest(&hti)) {
+ if (hti.flags & TVHT_ONITEMSTATEICON) {
+ NotifyChange();
+ int iNewState = m_toolBar.GetCheckState(hti.hItem);
+ m_btnIM.Enable(iNewState);
+ m_btnChat.Enable(iNewState);
+ m_btnHidden.Enable(iNewState);
+ if (iNewState)
+ m_btnIM.SetState(true);
+
+ m_toolBar.SelectItem(hti.hItem);
+ }
+ }
+ }
+};
+
+static int SrmmOptionsInit(WPARAM wParam, LPARAM)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.position = 910000000;
+ odp.hInstance = g_hInst;
+ odp.szGroup.a = LPGEN("Message sessions");
+ odp.szTitle.a = LPGEN("Toolbar");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pDialog = new CSrmmToolbarOptions();
+ Options_AddPage(wParam, &odp);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void KillModuleToolbarIcons(int _hLang)
+{
+ for (int i = arButtonsList.getCount() - 1; i >= 0; i--) {
+ CustomButtonData *cbd = arButtonsList[i];
+ if (cbd->m_hLangpack == _hLang) {
+ arButtonsList.remove(i);
+ delete cbd;
+ }
+ }
+}
+
+static int SrmmModulesLoaded(WPARAM, LPARAM)
+{
+ NotifyEventHooks(hHookToolBarLoadedEvt, 0, 0);
+ return 0;
+}
+
+void LoadSrmmToolbarModule()
+{
+ HookEvent(ME_OPT_INITIALISE, SrmmOptionsInit);
+ HookEvent(ME_SYSTEM_MODULESLOADED, SrmmModulesLoaded);
+
+ hHookToolBarLoadedEvt = CreateHookableEvent(ME_MSG_TOOLBARLOADED);
+
+ HDC hScrnDC = GetDC(0);
+ g_DPIscaleX = GetDeviceCaps(hScrnDC, LOGPIXELSX) / 96.0;
+ g_DPIscaleY = GetDeviceCaps(hScrnDC, LOGPIXELSY) / 96.0;
+ ReleaseDC(0, hScrnDC);
+
+ dwSepCount = db_get_dw(NULL, "TabSRMM_Toolbar", "SeparatorsCount", 0);
+ CB_RegisterSeparators();
+}
+
+void UnloadSrmmToolbarModule()
+{
+ DestroyHookableEvent(hHookToolBarLoadedEvt);
+ wipeList(arButtonsList);
+}