diff options
Diffstat (limited to 'src/mir_app')
-rw-r--r-- | src/mir_app/res/resource.rc | 16 | ||||
-rw-r--r-- | src/mir_app/src/chat_svc.cpp | 3 | ||||
-rw-r--r-- | src/mir_app/src/mir_app.def | 10 | ||||
-rw-r--r-- | src/mir_app/src/mir_app64.def | 10 | ||||
-rw-r--r-- | src/mir_app/src/miranda.h | 1 | ||||
-rw-r--r-- | src/mir_app/src/newplugins.cpp | 1 | ||||
-rw-r--r-- | src/mir_app/src/resource.h | 8 | ||||
-rw-r--r-- | src/mir_app/src/srmm_statusicon.cpp | 7 | ||||
-rw-r--r-- | src/mir_app/src/srmm_toolbar.cpp | 739 |
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); +} |