From fe29ca8b0bbcd71cf66f61b572c916e25d6be169 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 2 Apr 2018 17:34:30 +0300 Subject: code cleaning --- src/mir_app/src/BaseExtraIcon.cpp | 83 ------ src/mir_app/src/CallbackExtraIcon.cpp | 75 ----- src/mir_app/src/DefaultExtraIcons.cpp | 322 --------------------- src/mir_app/src/ExtraIcon.cpp | 75 ----- src/mir_app/src/ExtraIcon.h | 180 ------------ src/mir_app/src/ExtraIconGroup.cpp | 216 -------------- src/mir_app/src/IcolibExtraIcon.cpp | 118 -------- src/mir_app/src/ei_baseIcon.cpp | 83 ++++++ src/mir_app/src/ei_callbackIcon.cpp | 75 +++++ src/mir_app/src/ei_defaulticons.cpp | 321 +++++++++++++++++++++ src/mir_app/src/ei_extraIcon.cpp | 75 +++++ src/mir_app/src/ei_groupIcon.cpp | 216 ++++++++++++++ src/mir_app/src/ei_icolibIcon.cpp | 118 ++++++++ src/mir_app/src/ei_options.cpp | 465 +++++++++++++++++++++++++++++++ src/mir_app/src/ei_services.cpp | 510 ++++++++++++++++++++++++++++++++++ src/mir_app/src/extraicons.cpp | 510 ---------------------------------- src/mir_app/src/extraicons.h | 163 ++++++++++- src/mir_app/src/options_ei.cpp | 465 ------------------------------- 18 files changed, 2022 insertions(+), 2048 deletions(-) delete mode 100644 src/mir_app/src/BaseExtraIcon.cpp delete mode 100644 src/mir_app/src/CallbackExtraIcon.cpp delete mode 100644 src/mir_app/src/DefaultExtraIcons.cpp delete mode 100644 src/mir_app/src/ExtraIcon.cpp delete mode 100644 src/mir_app/src/ExtraIcon.h delete mode 100644 src/mir_app/src/ExtraIconGroup.cpp delete mode 100644 src/mir_app/src/IcolibExtraIcon.cpp create mode 100644 src/mir_app/src/ei_baseIcon.cpp create mode 100644 src/mir_app/src/ei_callbackIcon.cpp create mode 100644 src/mir_app/src/ei_defaulticons.cpp create mode 100644 src/mir_app/src/ei_extraIcon.cpp create mode 100644 src/mir_app/src/ei_groupIcon.cpp create mode 100644 src/mir_app/src/ei_icolibIcon.cpp create mode 100644 src/mir_app/src/ei_options.cpp create mode 100644 src/mir_app/src/ei_services.cpp delete mode 100644 src/mir_app/src/extraicons.cpp delete mode 100644 src/mir_app/src/options_ei.cpp (limited to 'src') diff --git a/src/mir_app/src/BaseExtraIcon.cpp b/src/mir_app/src/BaseExtraIcon.cpp deleted file mode 100644 index 8614eadde3..0000000000 --- a/src/mir_app/src/BaseExtraIcon.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "extraicons.h" - -BaseExtraIcon::BaseExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param) : - ExtraIcon(name), - m_id(id), - m_OnClick(OnClick), - m_onClickParam(param), - m_tszDescription(mir_wstrdup(description)), - m_szDescIcon(mir_strdup(descIcon)) -{ -} - -BaseExtraIcon::~BaseExtraIcon() -{ -} - -void BaseExtraIcon::setOnClick(MIRANDAHOOKPARAM pFunc, LPARAM pParam) -{ - m_OnClick = pFunc; - m_onClickParam = pParam; -} - -int BaseExtraIcon::getID() const -{ - return m_id; -} - -const wchar_t* BaseExtraIcon::getDescription() const -{ - return TranslateW_LP(m_tszDescription, m_hLangpack); -} - -void BaseExtraIcon::setDescription(const wchar_t *desc) -{ - m_tszDescription = mir_wstrdup(desc); -} - -const char* BaseExtraIcon::getDescIcon() const -{ - return m_szDescIcon; -} - -void BaseExtraIcon::setDescIcon(const char *icon) -{ - m_szDescIcon = mir_strdup(icon); -} - -void BaseExtraIcon::onClick(MCONTACT hContact) -{ - if (m_OnClick != nullptr) - m_OnClick(hContact, (LPARAM)ConvertToClistSlot(m_slot), m_onClickParam); -} - -int BaseExtraIcon::ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) -{ - ExtraIcon *tmp = extraIconsByHandle[m_id - 1]; - if (tmp != nullptr && tmp != this) - return tmp->ClistSetExtraIcon(hContact, hImage); - return Clist_SetExtraIcon(hContact, m_slot, hImage); -} diff --git a/src/mir_app/src/CallbackExtraIcon.cpp b/src/mir_app/src/CallbackExtraIcon.cpp deleted file mode 100644 index b9c0933826..0000000000 --- a/src/mir_app/src/CallbackExtraIcon.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "extraicons.h" - -CallbackExtraIcon::CallbackExtraIcon(int _id, const char *_name, const wchar_t *_description, const char *_descIcon, - MIRANDAHOOK _RebuildIcons, MIRANDAHOOK _ApplyIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) : - BaseExtraIcon(_id, _name, _description, _descIcon, _OnClick, _param), - m_pfnRebuildIcons(_RebuildIcons), m_pfnApplyIcon(_ApplyIcon), m_needToRebuild(true) -{ -} - -CallbackExtraIcon::~CallbackExtraIcon() -{ -} - -int CallbackExtraIcon::getType() const -{ - return EXTRAICON_TYPE_CALLBACK; -} - -void CallbackExtraIcon::rebuildIcons() -{ - if (!isEnabled()) { - m_needToRebuild = true; - return; - } - - m_needToRebuild = false; - m_pfnRebuildIcons(0, 0); -} - -void CallbackExtraIcon::applyIcon(MCONTACT hContact) -{ - if (!isEnabled() || hContact == 0) - return; - - if (m_needToRebuild) - rebuildIcons(); - - m_pfnApplyIcon(hContact, 0); -} - -int CallbackExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE icon) -{ - if (!isEnabled() || hContact == 0 || id != m_id) - return -1; - - return ClistSetExtraIcon(hContact, icon); -} - -int CallbackExtraIcon::setIconByName(int, MCONTACT, const char*) -{ - return -1; -} diff --git a/src/mir_app/src/DefaultExtraIcons.cpp b/src/mir_app/src/DefaultExtraIcons.cpp deleted file mode 100644 index a8906d8055..0000000000 --- a/src/mir_app/src/DefaultExtraIcons.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "m_cluiframes.h" - -#include "ExtraIcon.h" -#include "extraicons.h" - -ExtraIcon* GetExtraIcon(HANDLE id); - -//////////////////////////////////////////////////////////////////////////////////////// -// DB extra icons - -HANDLE hExtraVisibility, hExtraChat, hExtraGender, hExtraProto; - -static void SetVisibility(MCONTACT hContact, int apparentMode, bool clear) -{ - if (hContact == 0) - return; - - char *proto = GetContactProto(hContact); - if (IsEmpty(proto)) - return; - - if (apparentMode <= 0) - apparentMode = db_get_w(hContact, proto, "ApparentMode", 0); - - HANDLE hExtraIcon, hIcolib = nullptr; - - if (db_get_b(hContact, proto, "ChatRoom", 0)) { - // Is chat - hExtraIcon = hExtraChat; - if (apparentMode == ID_STATUS_OFFLINE) - hIcolib = IcoLib_GetIconHandle("ChatActivity"); - } - else { - // Not chat - hExtraIcon = hExtraVisibility; - if (apparentMode == ID_STATUS_OFFLINE) - hIcolib = Skin_GetIconHandle(SKINICON_OTHER_INVISIBLE_ALL); - else if (apparentMode == ID_STATUS_ONLINE) - hIcolib = Skin_GetIconHandle(SKINICON_OTHER_VISIBLE_ALL); - } - - if (hIcolib != nullptr || clear) { - ExtraIcon *extra = GetExtraIcon(hExtraIcon); - if (extra) - extra->setIcon((INT_PTR)hExtraIcon, hContact, hIcolib); - } -} - -static void SetGender(MCONTACT hContact, int gender, bool clear) -{ - if (hContact == 0) - return; - - char *proto = GetContactProto(hContact); - if (IsEmpty(proto)) - return; - - if (gender <= 0) - gender = db_get_b(hContact, proto, "Gender", 0); - if (gender <= 0) - gender = db_get_b(hContact, "UserInfo", "Gender", 0); - - const char *ico; - if (gender == 'M') - ico = "gender_male"; - else if (gender == 'F') - ico = "gender_female"; - else - ico = nullptr; - - if (ico != nullptr || clear) { - ExtraIcon *extra = GetExtraIcon(hExtraGender); - if (extra) - extra->setIconByName((INT_PTR)hExtraGender, hContact, ico); - } -} - -struct Info -{ - const char *name; - const char *desc; - int iSkinIcon; - const char *db[8]; - void(*OnClick)(Info *info, const char *text); - int flags; - - HANDLE hIcolib, hExtraIcon; -}; - -static void EmailOnClick(Info*, const char *text) -{ - char cmd[1024]; - mir_snprintf(cmd, "mailto:%s", text); - ShellExecuteA(nullptr, "open", cmd, nullptr, nullptr, SW_SHOW); -} - -static void HomepageOnClick(Info*, const char *text) -{ - ShellExecuteA(nullptr, "open", text, nullptr, nullptr, SW_SHOW); -} - -static Info infos[] = -{ - { "homepage", LPGEN("Homepage"), SKINICON_OTHER_MIRANDAWEB, - { nullptr, "Homepage", "UserInfo", "Homepage" }, - &HomepageOnClick, EIF_DISABLED_BY_DEFAULT }, - { "sms", LPGEN("Phone/SMS"), SKINICON_OTHER_SMS, - { nullptr, "Cellular", "UserInfo", "Cellular", "UserInfo", "Phone", "UserInfo", "MyPhone0" }, - nullptr, EIF_DISABLED_BY_DEFAULT }, - { "email", LPGEN("E-mail"), SKINICON_OTHER_SENDEMAIL, - { nullptr, "e-mail", "UserInfo", "e-mail", "UserInfo", "Mye-mail0" }, - &EmailOnClick, EIF_DISABLED_BY_DEFAULT }, -}; - -static void SetExtraIcons(MCONTACT hContact) -{ - if (hContact == 0) - return; - - char *proto = GetContactProto(hContact); - if ( IsEmpty(proto)) - return; - - for (auto &p : infos) { - for (unsigned int j = 0; j < _countof(p.db); j += 2) { - if (p.db[j + 1] == nullptr) - break; - - ptrA szValue(db_get_sa(hContact, p.db[j] == nullptr ? proto : p.db[j], p.db[j + 1])); - if (!IsEmpty(szValue)) { - ExtraIcon_SetIcon(p.hExtraIcon, hContact, p.hIcolib); - break; - } - } - } -} - -static int SettingChanged(WPARAM hContact, LPARAM lParam) -{ - if (hContact == 0) - return 0; - - char *proto = GetContactProto(hContact); - if (IsEmpty(proto)) - return 0; - - DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; - bool isProto = (strcmp(cws->szModule, proto) == 0); - if (isProto && strcmp(cws->szSetting, "ApparentMode") == 0) { - SetVisibility(hContact, cws->value.type == DBVT_DELETED ? 0 : cws->value.wVal, true); - return 0; - } - - if (strcmp(cws->szSetting, "Gender") == 0 && (isProto || strcmp(cws->szModule, "UserInfo") == 0)) { - SetGender(hContact, cws->value.type == DBVT_DELETED ? 0 : cws->value.bVal, true); - return 0; - } - - for (auto &p : infos) { - for (int j = 0; j < _countof(p.db); j += 2) { - if (p.db[j + 1] == nullptr) - break; - if (p.db[j] == nullptr && !isProto) - continue; - if (p.db[j] != nullptr && strcmp(cws->szModule, p.db[j])) - continue; - if (strcmp(cws->szSetting, p.db[j + 1])) - continue; - - bool show = (cws->value.type != DBVT_DELETED && !IsEmpty(cws->value.pszVal)); - ExtraIcon_SetIcon(p.hExtraIcon, hContact, show ? p.hIcolib : nullptr); - break; - } - } - - return 0; -} - -static int DefaultOnClick(WPARAM hContact, LPARAM, LPARAM param) -{ - Info *p = (Info*)param; - if (p == nullptr) - return 0; - - if (hContact == 0) - return 0; - - char *proto = GetContactProto(hContact); - if (IsEmpty(proto)) - return 0; - - bool found = false; - for (int j = 0; !found && j < _countof(p->db); j += 2) { - if (p->db[j + 1] == nullptr) - break; - - ptrA szValue(db_get_sa(hContact, p->db[j] == nullptr ? proto : p->db[j], p->db[j + 1])); - if (!IsEmpty(szValue)) { - p->OnClick(p, szValue); - found = true; - } - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// Protocol icon - -struct ProtoInfo -{ - ProtoInfo(LPCSTR _proto, HANDLE _image) : - proto(mir_strdup(_proto)), - hImage(_image) - {} - - ptrA proto; - HANDLE hImage; -}; - -static int CompareProtos(const ProtoInfo *p1, const ProtoInfo *p2) -{ return mir_strcmp(p1->proto, p2->proto); -} - -OBJLIST arProtos(10, CompareProtos); - -static int ProtocolRebuildIcons(WPARAM, LPARAM) -{ - arProtos.destroy(); - return 0; -} - -static ProtoInfo* FindProto(const char *proto) -{ - ProtoInfo *p = arProtos.find((ProtoInfo*)&proto); - if (p) - return p; - - HICON hIcon = Skin_LoadProtoIcon(proto, ID_STATUS_ONLINE); - if (hIcon == nullptr) - return nullptr; - - HANDLE hImage = ExtraIcon_AddIcon(hIcon); - if (hImage == INVALID_HANDLE_VALUE) - return nullptr; - - p = new ProtoInfo(proto, hImage); - arProtos.insert(p); - return p; -} - -static int ProtocolApplyIcon(WPARAM hContact, LPARAM) -{ - char *proto = GetContactProto(hContact); - if (IsEmpty(proto)) - return 0; - - HANDLE hImage = INVALID_HANDLE_VALUE; - ProtoInfo *pi = FindProto(proto); - if (pi != nullptr) - hImage = pi->hImage; - - ExtraIcon_SetIcon(hExtraProto, hContact, hImage); - return 0; -} - -static int ProtocolOnClick(WPARAM wParam, LPARAM, LPARAM) -{ - if (wParam) - CallService(MS_USERINFO_SHOWDIALOG, wParam, 0); - return 0; -} - -//////////////////////////////////////////////////////////////////////////////////////// - -void DefaultExtraIcons_Load() -{ - hExtraChat = ExtraIcon_RegisterIcolib("chat_activity", LPGEN("Chat activity"), "ChatActivity"); - hExtraVisibility = ExtraIcon_RegisterIcolib("visibility", "Visibility", Skin_GetIconName(SKINICON_OTHER_VISIBLE_ALL)); - hExtraGender = ExtraIcon_RegisterIcolib("gender", "Gender", "gender_male", nullptr, 0, EIF_DISABLED_BY_DEFAULT); - hExtraProto = ExtraIcon_RegisterCallback("protocol", "Account", Skin_GetIconName(SKINICON_OTHER_ACCMGR), - &ProtocolRebuildIcons, &ProtocolApplyIcon, &ProtocolOnClick, 0, EIF_DISABLED_BY_DEFAULT); - - for (auto &p : infos) { - p.hIcolib = Skin_GetIconHandle(p.iSkinIcon); - if (p.OnClick) - p.hExtraIcon = ExtraIcon_RegisterIcolib(p.name, p.desc, Skin_GetIconName(p.iSkinIcon), DefaultOnClick, (LPARAM)&p, p.flags); - else - p.hExtraIcon = ExtraIcon_RegisterIcolib(p.name, p.desc, Skin_GetIconName(p.iSkinIcon), nullptr, 0, p.flags); - } - - for (auto &hContact : Contacts()) { - SetExtraIcons(hContact); - SetVisibility(hContact, -1, false); - SetGender(hContact, -1, false); - } - - HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged); -} diff --git a/src/mir_app/src/ExtraIcon.cpp b/src/mir_app/src/ExtraIcon.cpp deleted file mode 100644 index 7aa92878a4..0000000000 --- a/src/mir_app/src/ExtraIcon.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "extraicons.h" - -ExtraIcon::ExtraIcon(const char *name) : - m_szName(mir_strdup(name)), m_slot(-1), m_position(1000), m_hLangpack(0) -{ -} - -ExtraIcon::~ExtraIcon() -{ -} - -const char *ExtraIcon::getName() const -{ - return m_szName; -} - -int ExtraIcon::getSlot() const -{ - return m_slot; -} - -void ExtraIcon::setSlot(int slot) -{ - m_slot = slot; -} - -int ExtraIcon::getPosition() const -{ - return m_position; -} - -void ExtraIcon::setPosition(int position) -{ - m_position = position; -} - -bool ExtraIcon::isEnabled() const -{ - return m_slot >= 0; -} - -void ExtraIcon::applyIcons() -{ - if (!isEnabled()) - return; - - for (auto &hContact : Contacts()) { - // Clear to assert that it will be cleared - Clist_SetExtraIcon(hContact, m_slot, INVALID_HANDLE_VALUE); - applyIcon(hContact); - } -} diff --git a/src/mir_app/src/ExtraIcon.h b/src/mir_app/src/ExtraIcon.h deleted file mode 100644 index 36834c1e50..0000000000 --- a/src/mir_app/src/ExtraIcon.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#ifndef __EXTRAICON_H__ -#define __EXTRAICON_H__ - -#define EXTRAICON_TYPE_GROUP -1 - -///////////////////////////////////////////////////////////////////////////////////////// -// ExtraIcon - base class for all extra icons - -class ExtraIcon -{ -public: - ExtraIcon(const char *name); - virtual ~ExtraIcon(); - - virtual void rebuildIcons() = 0; - virtual void applyIcons(); - virtual void applyIcon(MCONTACT hContact) = 0; - virtual void onClick(MCONTACT hContact) = 0; - - virtual int setIcon(int id, MCONTACT hContact, HANDLE icon) = 0; - virtual int setIconByName(int id, MCONTACT hContact, const char* icon) = 0; - virtual void storeIcon(MCONTACT, void*) {}; - - virtual const char *getName() const; - virtual const wchar_t *getDescription() const = 0; - virtual const char *getDescIcon() const = 0; - virtual int getType() const = 0; - - virtual int getSlot() const; - virtual void setSlot(int slot); - - virtual int getPosition() const; - virtual void setPosition(int position); - - virtual bool isEnabled() const; - - virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) = 0; - - int m_hLangpack; - -protected: - ptrA m_szName; - - int m_slot; - int m_position; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// BaseExtraIcon - basic class for all 'real' extra icons - -class BaseExtraIcon : public ExtraIcon -{ -public: - BaseExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); - virtual ~BaseExtraIcon(); - - virtual int getID() const; - virtual const wchar_t *getDescription() const; - virtual void setDescription(const wchar_t *desc); - virtual const char *getDescIcon() const; - virtual void setDescIcon(const char *icon); - virtual int getType() const =0; - - virtual void onClick(MCONTACT hContact); - virtual void setOnClick(MIRANDAHOOKPARAM OnClick, LPARAM param); - - virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage); - -protected: - int m_id; - ptrW m_tszDescription; - ptrA m_szDescIcon; - MIRANDAHOOKPARAM m_OnClick; - LPARAM m_onClickParam; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// CallbackExtraIcon - extra icon, implemented using callback functions - -class CallbackExtraIcon : public BaseExtraIcon -{ -public: - CallbackExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, - MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); - virtual ~CallbackExtraIcon(); - - virtual int getType() const; - - virtual void rebuildIcons(); - virtual void applyIcon(MCONTACT hContact); - - virtual int setIcon(int id, MCONTACT hContact, HANDLE icon); - virtual int setIconByName(int id, MCONTACT hContact, const char* icon); - -private: - int (*m_pfnRebuildIcons)(WPARAM wParam, LPARAM lParam); - int (*m_pfnApplyIcon)(WPARAM wParam, LPARAM lParam); - - bool m_needToRebuild; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// IcolibExtraIcon - extra icon, implemented using icolib - -class IcolibExtraIcon : public BaseExtraIcon -{ -public: - IcolibExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); - virtual ~IcolibExtraIcon(); - - virtual int getType() const; - - virtual void rebuildIcons(); - virtual void applyIcon(MCONTACT hContact); - - virtual int setIcon(int id, MCONTACT hContact, HANDLE icon); - virtual int setIconByName(int id, MCONTACT hContact, const char* icon); - virtual void storeIcon(MCONTACT hContact, void *icon); -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// ExtraIconGroup - joins some slots into one - -class ExtraIconGroup : public ExtraIcon -{ - int internalSetIcon(int id, MCONTACT hContact, HANDLE icon, bool bByName); -public: - ExtraIconGroup(const char *name); - virtual ~ExtraIconGroup(); - - virtual void addExtraIcon(BaseExtraIcon *extra); - - virtual void rebuildIcons(); - virtual void applyIcon(MCONTACT hContact); - virtual void onClick(MCONTACT hContact); - - virtual int setIcon(int id, MCONTACT hContact, HANDLE icon); - virtual int setIconByName(int id, MCONTACT hContact, const char *icon); - - virtual const wchar_t* getDescription() const; - virtual const char* getDescIcon() const; - virtual int getType() const; - - virtual int getPosition() const; - virtual void setSlot(int slot); - - LIST m_items; - - virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage); - -protected: - ptrW m_tszDescription; - bool m_setValidExtraIcon; - bool m_insideApply; - - virtual ExtraIcon *getCurrentItem(MCONTACT hContact) const; -}; - -#endif // __EXTRAICON_H__ diff --git a/src/mir_app/src/ExtraIconGroup.cpp b/src/mir_app/src/ExtraIconGroup.cpp deleted file mode 100644 index c7d8b6a453..0000000000 --- a/src/mir_app/src/ExtraIconGroup.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "extraicons.h" - -ExtraIconGroup::ExtraIconGroup(const char *_name) : - ExtraIcon(_name), m_setValidExtraIcon(false), m_insideApply(false), - m_items(1) -{ - db_set_resident(MODULE_NAME, _name); -} - -ExtraIconGroup::~ExtraIconGroup() -{ -} - -void ExtraIconGroup::addExtraIcon(BaseExtraIcon *extra) -{ - m_items.insert(extra); - - CMStringW description; - for (auto &p : m_items) { - if (!description.IsEmpty()) - description.Append(L" / "); - description += p->getDescription(); - } - - m_tszDescription = mir_wstrdup(description); -} - -void ExtraIconGroup::rebuildIcons() -{ - for (auto &p : m_items) - p->rebuildIcons(); -} - -void ExtraIconGroup::applyIcon(MCONTACT hContact) -{ - if (!isEnabled() || hContact == 0) - return; - - m_setValidExtraIcon = false; - m_insideApply = true; - - int i; - for (i = 0; i < m_items.getCount(); i++) { - m_items[i]->applyIcon(hContact); - if (m_setValidExtraIcon) - break; - } - - m_insideApply = false; - - db_set_dw(hContact, MODULE_NAME, m_szName, m_setValidExtraIcon ? m_items[i]->getID() : 0); -} - -int ExtraIconGroup::getPosition() const -{ - int pos = INT_MAX; - for (auto &p : m_items) - pos = min(pos, p->getPosition()); - return pos; -} - -void ExtraIconGroup::setSlot(int slot) -{ - ExtraIcon::setSlot(slot); - - for (auto &p : m_items) - p->setSlot(slot); -} - -ExtraIcon * ExtraIconGroup::getCurrentItem(MCONTACT hContact) const -{ - int id = (int)db_get_dw(hContact, MODULE_NAME, m_szName, 0); - if (id < 1) - return nullptr; - - for (auto &p : m_items) - if (id == p->getID()) - return p; - - return nullptr; -} - -void ExtraIconGroup::onClick(MCONTACT hContact) -{ - ExtraIcon *extra = getCurrentItem(hContact); - if (extra != nullptr) - extra->onClick(hContact); -} - -int ExtraIconGroup::setIcon(int id, MCONTACT hContact, HANDLE value) -{ - return internalSetIcon(id, hContact, (void*)value, false); -} - -int ExtraIconGroup::setIconByName(int id, MCONTACT hContact, const char *value) -{ - return internalSetIcon(id, hContact, (void*)value, true); -} - -int ExtraIconGroup::internalSetIcon(int id, MCONTACT hContact, HANDLE value, bool bByName) -{ - if (m_insideApply) { - for (auto &p : m_items) - if (p->getID() == id) { - if (bByName) - return p->setIconByName(id, hContact, (const char*)value); - return p->setIcon(id, hContact, value); - } - - return -1; - } - - ExtraIcon *current = getCurrentItem(hContact); - int currentPos = m_items.getCount(); - int storePos = m_items.getCount(); - for (int i = 0; i < m_items.getCount(); i++) { - if (m_items[i]->getID() == id) - storePos = i; - - if (m_items[i] == current) - currentPos = i; - } - - if (storePos == m_items.getCount()) - return -1; - - if (storePos > currentPos) { - m_items[storePos]->storeIcon(hContact, value); - return 0; - } - - // Ok, we have to set the icon, but we have to assert it is a valid icon - - m_setValidExtraIcon = false; - - int ret; - if (bByName) - ret = m_items[storePos]->setIconByName(id, hContact, (const char*)value); - else - ret = m_items[storePos]->setIcon(id, hContact, (HANDLE)value); - - if (storePos < currentPos) { - if (m_setValidExtraIcon) - db_set_dw(hContact, MODULE_NAME, m_szName, m_items[storePos]->getID()); - } - else if (storePos == currentPos) { - if (!m_setValidExtraIcon) { - db_set_dw(hContact, MODULE_NAME, m_szName, 0); - - m_insideApply = true; - - for (++storePos; storePos < m_items.getCount(); ++storePos) { - m_items[storePos]->applyIcon(hContact); - if (m_setValidExtraIcon) - break; - } - - m_insideApply = false; - - if (m_setValidExtraIcon && storePos < m_items.getCount()) - db_set_dw(hContact, MODULE_NAME, m_szName, m_items[storePos]->getID()); - } - } - - return ret; -} - -const wchar_t* ExtraIconGroup::getDescription() const -{ - return m_tszDescription; -} - -const char *ExtraIconGroup::getDescIcon() const -{ - for (auto &p : m_items) - if (!IsEmpty(p->getDescIcon())) - return p->getDescIcon(); - - return ""; -} - -int ExtraIconGroup::getType() const -{ - return EXTRAICON_TYPE_GROUP; -} - -int ExtraIconGroup::ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) -{ - if (hImage != INVALID_HANDLE_VALUE) - m_setValidExtraIcon = true; - - return Clist_SetExtraIcon(hContact, m_slot, hImage); -} diff --git a/src/mir_app/src/IcolibExtraIcon.cpp b/src/mir_app/src/IcolibExtraIcon.cpp deleted file mode 100644 index 70d5dd33ea..0000000000 --- a/src/mir_app/src/IcolibExtraIcon.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "extraicons.h" -#include "usedIcons.h" - -#include "IcoLib.h" - -IcolibExtraIcon::IcolibExtraIcon(int _id, const char *_name, const wchar_t *_description, const char *_descIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) : - BaseExtraIcon(_id, _name, _description, _descIcon, _OnClick, _param) -{ - db_set_resident(MODULE_NAME, _name); -} - -IcolibExtraIcon::~IcolibExtraIcon() -{ -} - -int IcolibExtraIcon::getType() const -{ - return EXTRAICON_TYPE_ICOLIB; -} - -void IcolibExtraIcon::rebuildIcons() -{ -} - -void IcolibExtraIcon::applyIcon(MCONTACT hContact) -{ - if (!isEnabled() || hContact == 0) - return; - - HANDLE hImage = INVALID_HANDLE_VALUE; - - ptrA szIconName(db_get_sa(hContact, MODULE_NAME, m_szName)); - if (!IsEmpty(szIconName)) - hImage = GetIcon(szIconName); - - ClistSetExtraIcon(hContact, hImage); -} - -int IcolibExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE hIcoLib) -{ - if (hContact == 0 || id != m_id) - return -1; - - if (hIcoLib == INVALID_HANDLE_VALUE) - hIcoLib = nullptr; - - if (isEnabled()) { - ptrA szIconName(db_get_sa(hContact, MODULE_NAME, m_szName)); - if (!IsEmpty(szIconName)) - RemoveIcon(szIconName); - } - - IcolibItem *p = (IcolibItem*)hIcoLib; - char *szName = (p) ? p->name : nullptr; - storeIcon(hContact, szName); - - if (isEnabled()) - return ClistSetExtraIcon(hContact, (hIcoLib == nullptr) ? INVALID_HANDLE_VALUE : AddIcon(szName)); - - return 0; -} - -int IcolibExtraIcon::setIconByName(int id, MCONTACT hContact, const char *icon) -{ - if (hContact == 0 || id != m_id) - return -1; - - if (icon == INVALID_HANDLE_VALUE) - icon = nullptr; - - if (isEnabled()) { - ptrA szIconName(db_get_sa(hContact, MODULE_NAME, m_szName)); - if (!IsEmpty(szIconName)) - RemoveIcon(szIconName); - } - - storeIcon(hContact, (char*)icon); - - if (isEnabled()) - return ClistSetExtraIcon(hContact, (IsEmpty(icon)) ? INVALID_HANDLE_VALUE : AddIcon(icon)); - - return 0; -} - -void IcolibExtraIcon::storeIcon(MCONTACT hContact, void *icon) -{ - if (hContact == 0) - return; - - const char *icolibName = (const char *)icon; - if (IsEmpty(icolibName)) - db_unset(hContact, MODULE_NAME, m_szName); - else - db_set_s(hContact, MODULE_NAME, m_szName, icolibName); -} diff --git a/src/mir_app/src/ei_baseIcon.cpp b/src/mir_app/src/ei_baseIcon.cpp new file mode 100644 index 0000000000..550bd97d69 --- /dev/null +++ b/src/mir_app/src/ei_baseIcon.cpp @@ -0,0 +1,83 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "extraicons.h" + +BaseExtraIcon::BaseExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param) : + ExtraIcon(name), + m_id(id), + m_OnClick(OnClick), + m_onClickParam(param), + m_tszDescription(mir_wstrdup(description)), + m_szDescIcon(mir_strdup(descIcon)) +{ +} + +BaseExtraIcon::~BaseExtraIcon() +{ +} + +void BaseExtraIcon::setOnClick(MIRANDAHOOKPARAM pFunc, LPARAM pParam) +{ + m_OnClick = pFunc; + m_onClickParam = pParam; +} + +int BaseExtraIcon::getID() const +{ + return m_id; +} + +const wchar_t* BaseExtraIcon::getDescription() const +{ + return TranslateW_LP(m_tszDescription, m_hLangpack); +} + +void BaseExtraIcon::setDescription(const wchar_t *desc) +{ + m_tszDescription = mir_wstrdup(desc); +} + +const char* BaseExtraIcon::getDescIcon() const +{ + return m_szDescIcon; +} + +void BaseExtraIcon::setDescIcon(const char *icon) +{ + m_szDescIcon = mir_strdup(icon); +} + +void BaseExtraIcon::onClick(MCONTACT hContact) +{ + if (m_OnClick != nullptr) + m_OnClick(hContact, (LPARAM)ConvertToClistSlot(m_slot), m_onClickParam); +} + +int BaseExtraIcon::ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) +{ + ExtraIcon *tmp = extraIconsByHandle[m_id - 1]; + if (tmp != nullptr && tmp != this) + return tmp->ClistSetExtraIcon(hContact, hImage); + return Clist_SetExtraIcon(hContact, m_slot, hImage); +} diff --git a/src/mir_app/src/ei_callbackIcon.cpp b/src/mir_app/src/ei_callbackIcon.cpp new file mode 100644 index 0000000000..c7cff67a09 --- /dev/null +++ b/src/mir_app/src/ei_callbackIcon.cpp @@ -0,0 +1,75 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "extraicons.h" + +CallbackExtraIcon::CallbackExtraIcon(int _id, const char *_name, const wchar_t *_description, const char *_descIcon, + MIRANDAHOOK _RebuildIcons, MIRANDAHOOK _ApplyIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) : + BaseExtraIcon(_id, _name, _description, _descIcon, _OnClick, _param), + m_pfnRebuildIcons(_RebuildIcons), m_pfnApplyIcon(_ApplyIcon), m_needToRebuild(true) +{ +} + +CallbackExtraIcon::~CallbackExtraIcon() +{ +} + +int CallbackExtraIcon::getType() const +{ + return EXTRAICON_TYPE_CALLBACK; +} + +void CallbackExtraIcon::rebuildIcons() +{ + if (!isEnabled()) { + m_needToRebuild = true; + return; + } + + m_needToRebuild = false; + m_pfnRebuildIcons(0, 0); +} + +void CallbackExtraIcon::applyIcon(MCONTACT hContact) +{ + if (!isEnabled() || hContact == 0) + return; + + if (m_needToRebuild) + rebuildIcons(); + + m_pfnApplyIcon(hContact, 0); +} + +int CallbackExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE icon) +{ + if (!isEnabled() || hContact == 0 || id != m_id) + return -1; + + return ClistSetExtraIcon(hContact, icon); +} + +int CallbackExtraIcon::setIconByName(int, MCONTACT, const char*) +{ + return -1; +} diff --git a/src/mir_app/src/ei_defaulticons.cpp b/src/mir_app/src/ei_defaulticons.cpp new file mode 100644 index 0000000000..1a523d7a36 --- /dev/null +++ b/src/mir_app/src/ei_defaulticons.cpp @@ -0,0 +1,321 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "m_cluiframes.h" + +#include "extraicons.h" + +ExtraIcon* GetExtraIcon(HANDLE id); + +//////////////////////////////////////////////////////////////////////////////////////// +// DB extra icons + +HANDLE hExtraVisibility, hExtraChat, hExtraGender, hExtraProto; + +static void SetVisibility(MCONTACT hContact, int apparentMode, bool clear) +{ + if (hContact == 0) + return; + + char *proto = GetContactProto(hContact); + if (IsEmpty(proto)) + return; + + if (apparentMode <= 0) + apparentMode = db_get_w(hContact, proto, "ApparentMode", 0); + + HANDLE hExtraIcon, hIcolib = nullptr; + + if (db_get_b(hContact, proto, "ChatRoom", 0)) { + // Is chat + hExtraIcon = hExtraChat; + if (apparentMode == ID_STATUS_OFFLINE) + hIcolib = IcoLib_GetIconHandle("ChatActivity"); + } + else { + // Not chat + hExtraIcon = hExtraVisibility; + if (apparentMode == ID_STATUS_OFFLINE) + hIcolib = Skin_GetIconHandle(SKINICON_OTHER_INVISIBLE_ALL); + else if (apparentMode == ID_STATUS_ONLINE) + hIcolib = Skin_GetIconHandle(SKINICON_OTHER_VISIBLE_ALL); + } + + if (hIcolib != nullptr || clear) { + ExtraIcon *extra = GetExtraIcon(hExtraIcon); + if (extra) + extra->setIcon((INT_PTR)hExtraIcon, hContact, hIcolib); + } +} + +static void SetGender(MCONTACT hContact, int gender, bool clear) +{ + if (hContact == 0) + return; + + char *proto = GetContactProto(hContact); + if (IsEmpty(proto)) + return; + + if (gender <= 0) + gender = db_get_b(hContact, proto, "Gender", 0); + if (gender <= 0) + gender = db_get_b(hContact, "UserInfo", "Gender", 0); + + const char *ico; + if (gender == 'M') + ico = "gender_male"; + else if (gender == 'F') + ico = "gender_female"; + else + ico = nullptr; + + if (ico != nullptr || clear) { + ExtraIcon *extra = GetExtraIcon(hExtraGender); + if (extra) + extra->setIconByName((INT_PTR)hExtraGender, hContact, ico); + } +} + +struct Info +{ + const char *name; + const char *desc; + int iSkinIcon; + const char *db[8]; + void(*OnClick)(Info *info, const char *text); + int flags; + + HANDLE hIcolib, hExtraIcon; +}; + +static void EmailOnClick(Info*, const char *text) +{ + char cmd[1024]; + mir_snprintf(cmd, "mailto:%s", text); + ShellExecuteA(nullptr, "open", cmd, nullptr, nullptr, SW_SHOW); +} + +static void HomepageOnClick(Info*, const char *text) +{ + ShellExecuteA(nullptr, "open", text, nullptr, nullptr, SW_SHOW); +} + +static Info infos[] = +{ + { "homepage", LPGEN("Homepage"), SKINICON_OTHER_MIRANDAWEB, + { nullptr, "Homepage", "UserInfo", "Homepage" }, + &HomepageOnClick, EIF_DISABLED_BY_DEFAULT }, + { "sms", LPGEN("Phone/SMS"), SKINICON_OTHER_SMS, + { nullptr, "Cellular", "UserInfo", "Cellular", "UserInfo", "Phone", "UserInfo", "MyPhone0" }, + nullptr, EIF_DISABLED_BY_DEFAULT }, + { "email", LPGEN("E-mail"), SKINICON_OTHER_SENDEMAIL, + { nullptr, "e-mail", "UserInfo", "e-mail", "UserInfo", "Mye-mail0" }, + &EmailOnClick, EIF_DISABLED_BY_DEFAULT }, +}; + +static void SetExtraIcons(MCONTACT hContact) +{ + if (hContact == 0) + return; + + char *proto = GetContactProto(hContact); + if ( IsEmpty(proto)) + return; + + for (auto &p : infos) { + for (unsigned int j = 0; j < _countof(p.db); j += 2) { + if (p.db[j + 1] == nullptr) + break; + + ptrA szValue(db_get_sa(hContact, p.db[j] == nullptr ? proto : p.db[j], p.db[j + 1])); + if (!IsEmpty(szValue)) { + ExtraIcon_SetIcon(p.hExtraIcon, hContact, p.hIcolib); + break; + } + } + } +} + +static int SettingChanged(WPARAM hContact, LPARAM lParam) +{ + if (hContact == 0) + return 0; + + char *proto = GetContactProto(hContact); + if (IsEmpty(proto)) + return 0; + + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; + bool isProto = (strcmp(cws->szModule, proto) == 0); + if (isProto && strcmp(cws->szSetting, "ApparentMode") == 0) { + SetVisibility(hContact, cws->value.type == DBVT_DELETED ? 0 : cws->value.wVal, true); + return 0; + } + + if (strcmp(cws->szSetting, "Gender") == 0 && (isProto || strcmp(cws->szModule, "UserInfo") == 0)) { + SetGender(hContact, cws->value.type == DBVT_DELETED ? 0 : cws->value.bVal, true); + return 0; + } + + for (auto &p : infos) { + for (int j = 0; j < _countof(p.db); j += 2) { + if (p.db[j + 1] == nullptr) + break; + if (p.db[j] == nullptr && !isProto) + continue; + if (p.db[j] != nullptr && strcmp(cws->szModule, p.db[j])) + continue; + if (strcmp(cws->szSetting, p.db[j + 1])) + continue; + + bool show = (cws->value.type != DBVT_DELETED && !IsEmpty(cws->value.pszVal)); + ExtraIcon_SetIcon(p.hExtraIcon, hContact, show ? p.hIcolib : nullptr); + break; + } + } + + return 0; +} + +static int DefaultOnClick(WPARAM hContact, LPARAM, LPARAM param) +{ + Info *p = (Info*)param; + if (p == nullptr) + return 0; + + if (hContact == 0) + return 0; + + char *proto = GetContactProto(hContact); + if (IsEmpty(proto)) + return 0; + + bool found = false; + for (int j = 0; !found && j < _countof(p->db); j += 2) { + if (p->db[j + 1] == nullptr) + break; + + ptrA szValue(db_get_sa(hContact, p->db[j] == nullptr ? proto : p->db[j], p->db[j + 1])); + if (!IsEmpty(szValue)) { + p->OnClick(p, szValue); + found = true; + } + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Protocol icon + +struct ProtoInfo +{ + ProtoInfo(LPCSTR _proto, HANDLE _image) : + proto(mir_strdup(_proto)), + hImage(_image) + {} + + ptrA proto; + HANDLE hImage; +}; + +static int CompareProtos(const ProtoInfo *p1, const ProtoInfo *p2) +{ return mir_strcmp(p1->proto, p2->proto); +} + +OBJLIST arProtos(10, CompareProtos); + +static int ProtocolRebuildIcons(WPARAM, LPARAM) +{ + arProtos.destroy(); + return 0; +} + +static ProtoInfo* FindProto(const char *proto) +{ + ProtoInfo *p = arProtos.find((ProtoInfo*)&proto); + if (p) + return p; + + HICON hIcon = Skin_LoadProtoIcon(proto, ID_STATUS_ONLINE); + if (hIcon == nullptr) + return nullptr; + + HANDLE hImage = ExtraIcon_AddIcon(hIcon); + if (hImage == INVALID_HANDLE_VALUE) + return nullptr; + + p = new ProtoInfo(proto, hImage); + arProtos.insert(p); + return p; +} + +static int ProtocolApplyIcon(WPARAM hContact, LPARAM) +{ + char *proto = GetContactProto(hContact); + if (IsEmpty(proto)) + return 0; + + HANDLE hImage = INVALID_HANDLE_VALUE; + ProtoInfo *pi = FindProto(proto); + if (pi != nullptr) + hImage = pi->hImage; + + ExtraIcon_SetIcon(hExtraProto, hContact, hImage); + return 0; +} + +static int ProtocolOnClick(WPARAM wParam, LPARAM, LPARAM) +{ + if (wParam) + CallService(MS_USERINFO_SHOWDIALOG, wParam, 0); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// + +void DefaultExtraIcons_Load() +{ + hExtraChat = ExtraIcon_RegisterIcolib("chat_activity", LPGEN("Chat activity"), "ChatActivity"); + hExtraVisibility = ExtraIcon_RegisterIcolib("visibility", "Visibility", Skin_GetIconName(SKINICON_OTHER_VISIBLE_ALL)); + hExtraGender = ExtraIcon_RegisterIcolib("gender", "Gender", "gender_male", nullptr, 0, EIF_DISABLED_BY_DEFAULT); + hExtraProto = ExtraIcon_RegisterCallback("protocol", "Account", Skin_GetIconName(SKINICON_OTHER_ACCMGR), + &ProtocolRebuildIcons, &ProtocolApplyIcon, &ProtocolOnClick, 0, EIF_DISABLED_BY_DEFAULT); + + for (auto &p : infos) { + p.hIcolib = Skin_GetIconHandle(p.iSkinIcon); + if (p.OnClick) + p.hExtraIcon = ExtraIcon_RegisterIcolib(p.name, p.desc, Skin_GetIconName(p.iSkinIcon), DefaultOnClick, (LPARAM)&p, p.flags); + else + p.hExtraIcon = ExtraIcon_RegisterIcolib(p.name, p.desc, Skin_GetIconName(p.iSkinIcon), nullptr, 0, p.flags); + } + + for (auto &hContact : Contacts()) { + SetExtraIcons(hContact); + SetVisibility(hContact, -1, false); + SetGender(hContact, -1, false); + } + + HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged); +} diff --git a/src/mir_app/src/ei_extraIcon.cpp b/src/mir_app/src/ei_extraIcon.cpp new file mode 100644 index 0000000000..a0b0283fee --- /dev/null +++ b/src/mir_app/src/ei_extraIcon.cpp @@ -0,0 +1,75 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "extraicons.h" + +ExtraIcon::ExtraIcon(const char *name) : + m_szName(mir_strdup(name)), m_slot(-1), m_position(1000), m_hLangpack(0) +{ +} + +ExtraIcon::~ExtraIcon() +{ +} + +const char *ExtraIcon::getName() const +{ + return m_szName; +} + +int ExtraIcon::getSlot() const +{ + return m_slot; +} + +void ExtraIcon::setSlot(int slot) +{ + m_slot = slot; +} + +int ExtraIcon::getPosition() const +{ + return m_position; +} + +void ExtraIcon::setPosition(int position) +{ + m_position = position; +} + +bool ExtraIcon::isEnabled() const +{ + return m_slot >= 0; +} + +void ExtraIcon::applyIcons() +{ + if (!isEnabled()) + return; + + for (auto &hContact : Contacts()) { + // Clear to assert that it will be cleared + Clist_SetExtraIcon(hContact, m_slot, INVALID_HANDLE_VALUE); + applyIcon(hContact); + } +} diff --git a/src/mir_app/src/ei_groupIcon.cpp b/src/mir_app/src/ei_groupIcon.cpp new file mode 100644 index 0000000000..b46ce97dcc --- /dev/null +++ b/src/mir_app/src/ei_groupIcon.cpp @@ -0,0 +1,216 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "extraicons.h" + +ExtraIconGroup::ExtraIconGroup(const char *_name) : + ExtraIcon(_name), m_setValidExtraIcon(false), m_insideApply(false), + m_items(1) +{ + db_set_resident(MODULE_NAME, _name); +} + +ExtraIconGroup::~ExtraIconGroup() +{ +} + +void ExtraIconGroup::addExtraIcon(BaseExtraIcon *extra) +{ + m_items.insert(extra); + + CMStringW description; + for (auto &p : m_items) { + if (!description.IsEmpty()) + description.Append(L" / "); + description += p->getDescription(); + } + + m_tszDescription = mir_wstrdup(description); +} + +void ExtraIconGroup::rebuildIcons() +{ + for (auto &p : m_items) + p->rebuildIcons(); +} + +void ExtraIconGroup::applyIcon(MCONTACT hContact) +{ + if (!isEnabled() || hContact == 0) + return; + + m_setValidExtraIcon = false; + m_insideApply = true; + + int i; + for (i = 0; i < m_items.getCount(); i++) { + m_items[i]->applyIcon(hContact); + if (m_setValidExtraIcon) + break; + } + + m_insideApply = false; + + db_set_dw(hContact, MODULE_NAME, m_szName, m_setValidExtraIcon ? m_items[i]->getID() : 0); +} + +int ExtraIconGroup::getPosition() const +{ + int pos = INT_MAX; + for (auto &p : m_items) + pos = min(pos, p->getPosition()); + return pos; +} + +void ExtraIconGroup::setSlot(int slot) +{ + ExtraIcon::setSlot(slot); + + for (auto &p : m_items) + p->setSlot(slot); +} + +ExtraIcon * ExtraIconGroup::getCurrentItem(MCONTACT hContact) const +{ + int id = (int)db_get_dw(hContact, MODULE_NAME, m_szName, 0); + if (id < 1) + return nullptr; + + for (auto &p : m_items) + if (id == p->getID()) + return p; + + return nullptr; +} + +void ExtraIconGroup::onClick(MCONTACT hContact) +{ + ExtraIcon *extra = getCurrentItem(hContact); + if (extra != nullptr) + extra->onClick(hContact); +} + +int ExtraIconGroup::setIcon(int id, MCONTACT hContact, HANDLE value) +{ + return internalSetIcon(id, hContact, (void*)value, false); +} + +int ExtraIconGroup::setIconByName(int id, MCONTACT hContact, const char *value) +{ + return internalSetIcon(id, hContact, (void*)value, true); +} + +int ExtraIconGroup::internalSetIcon(int id, MCONTACT hContact, HANDLE value, bool bByName) +{ + if (m_insideApply) { + for (auto &p : m_items) + if (p->getID() == id) { + if (bByName) + return p->setIconByName(id, hContact, (const char*)value); + return p->setIcon(id, hContact, value); + } + + return -1; + } + + ExtraIcon *current = getCurrentItem(hContact); + int currentPos = m_items.getCount(); + int storePos = m_items.getCount(); + for (int i = 0; i < m_items.getCount(); i++) { + if (m_items[i]->getID() == id) + storePos = i; + + if (m_items[i] == current) + currentPos = i; + } + + if (storePos == m_items.getCount()) + return -1; + + if (storePos > currentPos) { + m_items[storePos]->storeIcon(hContact, value); + return 0; + } + + // Ok, we have to set the icon, but we have to assert it is a valid icon + + m_setValidExtraIcon = false; + + int ret; + if (bByName) + ret = m_items[storePos]->setIconByName(id, hContact, (const char*)value); + else + ret = m_items[storePos]->setIcon(id, hContact, (HANDLE)value); + + if (storePos < currentPos) { + if (m_setValidExtraIcon) + db_set_dw(hContact, MODULE_NAME, m_szName, m_items[storePos]->getID()); + } + else if (storePos == currentPos) { + if (!m_setValidExtraIcon) { + db_set_dw(hContact, MODULE_NAME, m_szName, 0); + + m_insideApply = true; + + for (++storePos; storePos < m_items.getCount(); ++storePos) { + m_items[storePos]->applyIcon(hContact); + if (m_setValidExtraIcon) + break; + } + + m_insideApply = false; + + if (m_setValidExtraIcon && storePos < m_items.getCount()) + db_set_dw(hContact, MODULE_NAME, m_szName, m_items[storePos]->getID()); + } + } + + return ret; +} + +const wchar_t* ExtraIconGroup::getDescription() const +{ + return m_tszDescription; +} + +const char *ExtraIconGroup::getDescIcon() const +{ + for (auto &p : m_items) + if (!IsEmpty(p->getDescIcon())) + return p->getDescIcon(); + + return ""; +} + +int ExtraIconGroup::getType() const +{ + return EXTRAICON_TYPE_GROUP; +} + +int ExtraIconGroup::ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) +{ + if (hImage != INVALID_HANDLE_VALUE) + m_setValidExtraIcon = true; + + return Clist_SetExtraIcon(hContact, m_slot, hImage); +} diff --git a/src/mir_app/src/ei_icolibIcon.cpp b/src/mir_app/src/ei_icolibIcon.cpp new file mode 100644 index 0000000000..44cd0ab8b1 --- /dev/null +++ b/src/mir_app/src/ei_icolibIcon.cpp @@ -0,0 +1,118 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "extraicons.h" +#include "usedIcons.h" + +#include "IcoLib.h" + +IcolibExtraIcon::IcolibExtraIcon(int _id, const char *_name, const wchar_t *_description, const char *_descIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) : + BaseExtraIcon(_id, _name, _description, _descIcon, _OnClick, _param) +{ + db_set_resident(MODULE_NAME, _name); +} + +IcolibExtraIcon::~IcolibExtraIcon() +{ +} + +int IcolibExtraIcon::getType() const +{ + return EXTRAICON_TYPE_ICOLIB; +} + +void IcolibExtraIcon::rebuildIcons() +{ +} + +void IcolibExtraIcon::applyIcon(MCONTACT hContact) +{ + if (!isEnabled() || hContact == 0) + return; + + HANDLE hImage = INVALID_HANDLE_VALUE; + + ptrA szIconName(db_get_sa(hContact, MODULE_NAME, m_szName)); + if (!IsEmpty(szIconName)) + hImage = GetIcon(szIconName); + + ClistSetExtraIcon(hContact, hImage); +} + +int IcolibExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE hIcoLib) +{ + if (hContact == 0 || id != m_id) + return -1; + + if (hIcoLib == INVALID_HANDLE_VALUE) + hIcoLib = nullptr; + + if (isEnabled()) { + ptrA szIconName(db_get_sa(hContact, MODULE_NAME, m_szName)); + if (!IsEmpty(szIconName)) + RemoveIcon(szIconName); + } + + IcolibItem *p = (IcolibItem*)hIcoLib; + char *szName = (p) ? p->name : nullptr; + storeIcon(hContact, szName); + + if (isEnabled()) + return ClistSetExtraIcon(hContact, (hIcoLib == nullptr) ? INVALID_HANDLE_VALUE : AddIcon(szName)); + + return 0; +} + +int IcolibExtraIcon::setIconByName(int id, MCONTACT hContact, const char *icon) +{ + if (hContact == 0 || id != m_id) + return -1; + + if (icon == INVALID_HANDLE_VALUE) + icon = nullptr; + + if (isEnabled()) { + ptrA szIconName(db_get_sa(hContact, MODULE_NAME, m_szName)); + if (!IsEmpty(szIconName)) + RemoveIcon(szIconName); + } + + storeIcon(hContact, (char*)icon); + + if (isEnabled()) + return ClistSetExtraIcon(hContact, (IsEmpty(icon)) ? INVALID_HANDLE_VALUE : AddIcon(icon)); + + return 0; +} + +void IcolibExtraIcon::storeIcon(MCONTACT hContact, void *icon) +{ + if (hContact == 0) + return; + + const char *icolibName = (const char *)icon; + if (IsEmpty(icolibName)) + db_unset(hContact, MODULE_NAME, m_szName); + else + db_set_s(hContact, MODULE_NAME, m_szName, icolibName); +} diff --git a/src/mir_app/src/ei_options.cpp b/src/mir_app/src/ei_options.cpp new file mode 100644 index 0000000000..7999b88b34 --- /dev/null +++ b/src/mir_app/src/ei_options.cpp @@ -0,0 +1,465 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "extraicons.h" + +#define ICON_SIZE 16 + +int SortFunc(const ExtraIcon *p1, const ExtraIcon *p2); + +struct intlist +{ + intlist() : count(0), data(nullptr) {} + ~intlist() { mir_free(data); } + + void add(int val) + { + data = (int*)mir_realloc(data, sizeof(int)*(count + 1)); + data[count++] = val; + } + + int count; + int *data; +}; + +static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM) +{ + intlist *a = (intlist*)lParam1; + intlist *b = (intlist*)lParam2; + return SortFunc(registeredExtraIcons[a->data[0] - 1], registeredExtraIcons[b->data[0] - 1]); +} + +// Functions ////////////////////////////////////////////////////////////////////////////////////// + +BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) +{ + POINT pt; + pt.x = lpRect->left; + pt.y = lpRect->top; + + BOOL ret = ScreenToClient(hWnd, &pt); + if (!ret) + return ret; + + lpRect->left = pt.x; + lpRect->top = pt.y; + + pt.x = lpRect->right; + pt.y = lpRect->bottom; + + ret = ScreenToClient(hWnd, &pt); + + lpRect->right = pt.x; + lpRect->bottom = pt.y; + + return ret; +} + +static void RemoveExtraIcons(int slot) +{ + for (auto &hContact : Contacts()) + Clist_SetExtraIcon(hContact, slot, INVALID_HANDLE_VALUE); +} + +class CExtraIconOptsDlg : public CDlgBase +{ + intlist* Tree_GetIDs(HTREEITEM hItem) + { + TVITEMEX tvi; + tvi.mask = TVIF_HANDLE | TVIF_PARAM; + tvi.hItem = hItem; + m_tree.GetItem(&tvi); + return (intlist*)tvi.lParam; + } + + HTREEITEM Tree_AddExtraIcon(BaseExtraIcon *extra, bool selected, HTREEITEM hAfter = TVI_LAST) + { + intlist *ids = new intlist(); + ids->add(extra->getID()); + + TVINSERTSTRUCT tvis = {}; + tvis.hInsertAfter = hAfter; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.iSelectedImage = tvis.item.iImage = extra->getID(); + tvis.item.lParam = (LPARAM)ids; + tvis.item.pszText = (LPTSTR)extra->getDescription(); + tvis.item.state = INDEXTOSTATEIMAGEMASK(selected ? 2 : 1); + return m_tree.InsertItem(&tvis); + } + + HTREEITEM Tree_AddExtraIconGroup(intlist &group, bool selected, HTREEITEM hAfter = TVI_LAST) + { + intlist *ids = new intlist(); + CMStringW desc; + int img = 0; + for (int i = 0; i < group.count; i++) { + BaseExtraIcon *extra = registeredExtraIcons[group.data[i] - 1]; + ids->add(extra->getID()); + + if (img == 0 && !IsEmpty(extra->getDescIcon())) + img = extra->getID(); + + if (i > 0) + desc += L" / "; + desc += extra->getDescription(); + } + + TVINSERTSTRUCT tvis = {}; + tvis.hInsertAfter = hAfter; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.iSelectedImage = tvis.item.iImage = img; + tvis.item.lParam = (LPARAM)ids; + tvis.item.pszText = (wchar_t*)desc.c_str(); + tvis.item.state = INDEXTOSTATEIMAGEMASK(selected ? 2 : 1); + return m_tree.InsertItem(&tvis); + } + + void GroupSelectedItems() + { + LIST<_TREEITEM> toRemove(1); + intlist ids; + bool selected = false; + HTREEITEM hPlace = nullptr; + + // Find items + HTREEITEM hItem = m_tree.GetRoot(); + TVITEMEX tvi = { 0 }; + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + while (hItem) { + if (m_tree.IsSelected(hItem)) { + if (hPlace == nullptr) + hPlace = hItem; + + tvi.hItem = hItem; + m_tree.GetItem(&tvi); + + intlist *iids = (intlist*)tvi.lParam; + for (int i = 0; i < iids->count; i++) + ids.add(iids->data[i]); + + if ((tvi.state & INDEXTOSTATEIMAGEMASK(3)) == INDEXTOSTATEIMAGEMASK(2)) + selected = true; + + toRemove.insert(hItem); + } + + hItem = m_tree.GetNextSibling(hItem); + } + + if (hPlace != nullptr) { + // Add new + HTREEITEM hNew = Tree_AddExtraIconGroup(ids, selected, hPlace); + + // Remove old + for (auto &p : toRemove) { + delete Tree_GetIDs(p); + m_tree.DeleteItem(p); + } + + // Select + m_tree.UnselectAll(); + m_tree.SelectItem(hNew); + } + } + + void UngroupSelectedItems() + { + HTREEITEM hItem = m_tree.GetSelection(); + if (hItem == nullptr) + return; + + intlist *ids = Tree_GetIDs(hItem); + if (ids->count < 2) + return; + + bool selected = m_tree.IsSelected(hItem); + + for (int i = ids->count - 1; i >= 0; i--) { + BaseExtraIcon *extra = registeredExtraIcons[ids->data[i] - 1]; + Tree_AddExtraIcon(extra, selected, hItem); + } + + delete ids; + m_tree.DeleteItem(hItem); + + m_tree.UnselectAll(); + } + + int ShowPopup(int popup) + { + // Fix selection + HTREEITEM hSelected = m_tree.GetDropHilight(); + HTREEITEM hItem = m_tree.GetRoot(); + while (hItem) { + if (hItem != hSelected && m_tree.IsSelected(hItem)) + m_tree.DropHilite(hItem); + + hItem = m_tree.GetNextSibling(hItem); + } + + HMENU menu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_OPT_POPUP)); + HMENU submenu = GetSubMenu(menu, popup); + TranslateMenu(submenu); + + DWORD pos = GetMessagePos(); + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_LEFTALIGN, LOWORD(pos), HIWORD(pos), 0, m_hwnd, nullptr); + + DestroyMenu(menu); + + // Revert selection + hItem = m_tree.GetRoot(); + while (hItem) { + if (hItem != hSelected && m_tree.IsSelected(hItem)) + m_tree.DropUnhilite(hItem); + hItem = m_tree.GetNextSibling(hItem); + } + + return ret; + } + + CCtrlTreeView m_tree; + +public: + CExtraIconOptsDlg() : + CDlgBase(g_hInst, IDD_EI_OPTIONS), + m_tree(this, IDC_EXTRAORDER) + { + m_tree.SetFlags(MTREE_DND | MTREE_MULTISELECT); + } + + virtual void OnInitDialog() + { + int numSlots = GetNumberOfSlots(); + if (numSlots < (int)registeredExtraIcons.getCount()) { + HWND label = GetDlgItem(m_hwnd, IDC_MAX_ICONS_L); + SetWindowText(label, CMStringW(FORMAT, TranslateT("*only the first %d icons will be shown"), numSlots)); + ShowWindow(label, SW_SHOW); + } + + int cx = g_iIconSX; + HIMAGELIST hImageList = ImageList_Create(cx, cx, ILC_COLOR32 | ILC_MASK, 2, 2); + + HICON hBlankIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, cx, cx, 0); + ImageList_AddIcon(hImageList, hBlankIcon); + + for (auto &extra : registeredExtraIcons) { + HICON hIcon = IcoLib_GetIcon(extra->getDescIcon()); + if (hIcon == nullptr) + ImageList_AddIcon(hImageList, hBlankIcon); + else { + ImageList_AddIcon(hImageList, hIcon); + IcoLib_ReleaseIcon(hIcon); + } + } + m_tree.SetImageList(hImageList, TVSIL_NORMAL); + DestroyIcon(hBlankIcon); + + for (auto &extra : extraIconsBySlot) { + if (extra->getType() == EXTRAICON_TYPE_GROUP) { + ExtraIconGroup *group = (ExtraIconGroup *)extra; + intlist ids; + for (auto &p : group->m_items) + ids.add(p->getID()); + Tree_AddExtraIconGroup(ids, extra->isEnabled()); + } + else Tree_AddExtraIcon((BaseExtraIcon *)extra, extra->isEnabled()); + } + + TVSORTCB sort = {}; + sort.hParent = nullptr; + sort.lParam = 0; + sort.lpfnCompare = CompareFunc; + m_tree.SortChildrenCB(&sort, 0); + } + + virtual void OnApply() + { + // Store old slots + int *oldSlots = new int[registeredExtraIcons.getCount()]; + int lastUsedSlot = -1; + for (int i = 0; i < registeredExtraIcons.getCount(); i++) { + if (extraIconsByHandle[i] == registeredExtraIcons[i]) + oldSlots[i] = registeredExtraIcons[i]->getSlot(); + else + // Remove old slot for groups to re-set images + oldSlots[i] = -1; + lastUsedSlot = max(lastUsedSlot, registeredExtraIcons[i]->getSlot()); + } + lastUsedSlot = min(lastUsedSlot, GetNumberOfSlots()); + + // Get user data and create new groups + LIST groups(1); + + BYTE pos = 0; + int firstEmptySlot = 0; + HTREEITEM ht = m_tree.GetRoot(); + TVITEMEX tvi; + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; + tvi.stateMask = TVIS_STATEIMAGEMASK; + while (ht) { + tvi.hItem = ht; + m_tree.GetItem(&tvi); + + intlist*ids = (intlist*)tvi.lParam; + if (ids == nullptr || ids->count < 1) + continue; // ??? + + bool enabled = ((tvi.state & INDEXTOSTATEIMAGEMASK(3)) == INDEXTOSTATEIMAGEMASK(2)); + int slot = (enabled ? firstEmptySlot++ : -1); + if (slot >= GetNumberOfSlots()) + slot = -1; + + if (ids->count == 1) { + BaseExtraIcon *extra = registeredExtraIcons[ids->data[0] - 1]; + extra->setPosition(pos++); + extra->setSlot(slot); + } + else { + char name[128]; + mir_snprintf(name, "__group_%d", groups.getCount()); + + ExtraIconGroup *group = new ExtraIconGroup(name); + + for (int i = 0; i < ids->count; i++) { + BaseExtraIcon *extra = registeredExtraIcons[ids->data[i] - 1]; + extra->setPosition(pos++); + + group->addExtraIcon(extra); + } + + group->setSlot(slot); + groups.insert(group); + } + + ht = m_tree.GetNextSibling(ht); + } + + // Store data + for (auto &extra : registeredExtraIcons) { + char setting[512]; + mir_snprintf(setting, "Position_%s", extra->getName()); + db_set_w(0, MODULE_NAME, setting, extra->getPosition()); + + mir_snprintf(setting, "Slot_%s", extra->getName()); + db_set_w(0, MODULE_NAME, setting, extra->getSlot()); + } + + db_delete_module(0, MODULE_NAME "Groups"); + db_set_w(0, MODULE_NAME "Groups", "Count", groups.getCount()); + for (int k = 0; k < groups.getCount(); k++) { + ExtraIconGroup *group = groups[k]; + + char setting[512]; + mir_snprintf(setting, "%d_count", k); + db_set_w(0, MODULE_NAME "Groups", setting, (WORD)group->m_items.getCount()); + + for (int j = 0; j < group->m_items.getCount(); j++) { + BaseExtraIcon *extra = group->m_items[j]; + + mir_snprintf(setting, "%d_%d", k, j); + db_set_s(0, MODULE_NAME "Groups", setting, extra->getName()); + } + } + + // Clean removed slots + for (int j = firstEmptySlot; j <= lastUsedSlot; j++) + RemoveExtraIcons(j); + + // Apply icons to new slots + RebuildListsBasedOnGroups(groups); + for (auto &extra : extraIconsBySlot) { + if (extra->getType() != EXTRAICON_TYPE_GROUP) + if (oldSlots[((BaseExtraIcon *)extra)->getID() - 1] == extra->getSlot()) + continue; + + if (extra->isEnabled()) + extra->applyIcons(); + } + + delete[] oldSlots; + } + + virtual void OnDestroy() + { + HTREEITEM hItem = m_tree.GetRoot(); + while (hItem) { + delete Tree_GetIDs(hItem); + hItem = m_tree.GetNextSibling(hItem); + } + + ImageList_Destroy(m_tree.GetImageList(TVSIL_NORMAL)); + } + + virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) + { + if (msg == WM_NOTIFY) { + LPNMHDR lpnmhdr = (LPNMHDR)lParam; + if (lpnmhdr->idFrom == IDC_EXTRAORDER && lpnmhdr->code == NM_RCLICK) { + HTREEITEM hSelected = m_tree.GetDropHilight(); + if (hSelected != nullptr && !m_tree.IsSelected(hSelected)) { + m_tree.UnselectAll(); + m_tree.SelectItem(hSelected); + } + + int sels = m_tree.GetNumSelected(); + if (sels > 1) { + if (ShowPopup(0) == ID_GROUP) { + GroupSelectedItems(); + NotifyChange(); + } + } + else if (sels == 1) { + HTREEITEM hItem = m_tree.GetSelection(); + intlist *ids = Tree_GetIDs(hItem); + if (ids->count > 1) { + if (ShowPopup(1) == ID_UNGROUP) { + UngroupSelectedItems(); + NotifyChange(); + } + } + } + } + } + + return CDlgBase::DlgProc(msg, wParam, lParam); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +int InitOptionsCallback(WPARAM wParam, LPARAM) +{ + if (GetNumberOfSlots() < 1) + return 0; + + OPTIONSDIALOGPAGE odp = { 0 }; + odp.szGroup.a = LPGEN("Contact list"); + odp.szTitle.a = LPGEN("Extra icons"); + odp.szTab.a = LPGEN("General"); + odp.flags = ODPF_BOLDGROUPS; + odp.pDialog = new CExtraIconOptsDlg(); + Options_AddPage(wParam, &odp); + return 0; +} diff --git a/src/mir_app/src/ei_services.cpp b/src/mir_app/src/ei_services.cpp new file mode 100644 index 0000000000..d35adfeeda --- /dev/null +++ b/src/mir_app/src/ei_services.cpp @@ -0,0 +1,510 @@ +/* + +Copyright (C) 2009 Ricardo Pescuma Domenecci +Copyright (C) 2012-18 Miranda NG team + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include "m_cluiframes.h" + +#include "extraicons.h" +#include "usedIcons.h" +#include "clc.h" + +// Prototypes /////////////////////////////////////////////////////////////////////////// + +int SortFunc(const ExtraIcon *p1, const ExtraIcon *p2) +{ + int ret = p1->getPosition() - p2->getPosition(); + if (ret != 0) + return ret; + + int id1 = (p1->getType() != EXTRAICON_TYPE_GROUP) ? ((BaseExtraIcon*)p1)->getID() : 0; + int id2 = (p2->getType() != EXTRAICON_TYPE_GROUP) ? ((BaseExtraIcon*)p2)->getID() : 0; + return id1 - id2; +} + +LIST extraIconsByHandle(10), extraIconsBySlot(10, SortFunc); +LIST registeredExtraIcons(10); + +BOOL clistRebuildAlreadyCalled = FALSE; +BOOL clistApplyAlreadyCalled = FALSE; + +// Functions //////////////////////////////////////////////////////////////////////////// + +int InitOptionsCallback(WPARAM wParam, LPARAM lParam); + +// Called when all the modules are loaded +int ModulesLoaded(WPARAM, LPARAM) +{ + HookEvent(ME_OPT_INITIALISE, InitOptionsCallback); + return 0; +} + +int GetNumberOfSlots() +{ + return EXTRA_ICON_COUNT; +} + +int ConvertToClistSlot(int slot) +{ + if (slot < 0) + return slot; + + return slot + 1; +} + +int ExtraImage_ExtraIDToColumnNum(int extra) +{ + return (extra < 1 || extra > EXTRA_ICON_COUNT) ? -1 : extra - 1; +} + +int Clist_SetExtraIcon(MCONTACT hContact, int slot, HANDLE hImage) +{ + if (cli.hwndContactTree == nullptr) + return -1; + + int icol = ExtraImage_ExtraIDToColumnNum(ConvertToClistSlot(slot)); + if (icol == -1) + return -1; + + HANDLE hItem = (HANDLE)SendMessage(cli.hwndContactTree, CLM_FINDCONTACT, hContact, 0); + if (hItem == nullptr) + return -1; + + SendMessage(cli.hwndContactTree, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(icol, hImage)); + return 0; +} + +ExtraIcon* GetExtraIcon(HANDLE id) +{ + int i = (INT_PTR)id; + if (i < 1 || i > extraIconsByHandle.getCount()) + return nullptr; + + return extraIconsByHandle[i - 1]; +} + +ExtraIcon* GetExtraIconBySlot(int slot) +{ + for (auto &extra : extraIconsBySlot) + if (extra->getSlot() == slot) + return extra; + + return nullptr; +} + +BaseExtraIcon* GetExtraIconByName(const char *name) +{ + for (auto &extra : registeredExtraIcons) + if (mir_strcmp(name, extra->getName()) == 0) + return extra; + + return nullptr; +} + +static void LoadGroups(LIST &groups) +{ + int count = db_get_w(0, MODULE_NAME "Groups", "Count", 0); + for (int i = 0; i < count; i++) { + char setting[512]; + mir_snprintf(setting, "%d_count", i); + unsigned int items = db_get_w(0, MODULE_NAME "Groups", setting, 0); + if (items < 1) + continue; + + mir_snprintf(setting, "__group_%d", i); + ExtraIconGroup *group = new ExtraIconGroup(setting); + + for (unsigned int j = 0; j < items; j++) { + mir_snprintf(setting, "%d_%d", i, j); + ptrA szIconName(db_get_sa(0, MODULE_NAME "Groups", setting)); + if (IsEmpty(szIconName)) + continue; + + BaseExtraIcon *extra = GetExtraIconByName(szIconName); + if (extra == nullptr) + continue; + + group->m_items.insert(extra); + if (extra->getSlot() >= 0) + group->setSlot(extra->getSlot()); + } + + if (group->m_items.getCount() < 2) { + delete group; + continue; + } + + groups.insert(group); + } +} + +static ExtraIconGroup* IsInGroup(LIST &groups, BaseExtraIcon *extra) +{ + for (auto &group : groups) + for (auto &it : group->m_items) + if (extra == it) + return group; + + return nullptr; +} + +void RebuildListsBasedOnGroups(LIST &groups) +{ + extraIconsByHandle.destroy(); + + for (auto &it : registeredExtraIcons) + extraIconsByHandle.insert(it); + + for (auto &extra : extraIconsBySlot) + if (extra->getType() == EXTRAICON_TYPE_GROUP) + delete extra; + extraIconsBySlot.destroy(); + + for (auto &group : groups) { + for (auto &it : group->m_items) + extraIconsByHandle.put(it->getID()-1, group); + + extraIconsBySlot.insert(group); + } + + for (auto &extra : extraIconsByHandle) + if (extra->getType() != EXTRAICON_TYPE_GROUP) + extraIconsBySlot.insert(extra); +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_APP_DLL(void) KillModuleExtraIcons(int _hLang) +{ + LIST arDeleted(1); + + auto T = registeredExtraIcons.rev_iter(); + for (auto &it : T) + if (it->m_hLangpack == _hLang) { + arDeleted.insert(it); + registeredExtraIcons.remove(T.indexOf(&it)); + } + + if (arDeleted.getCount() == 0) + return; + + LIST groups(1); + LoadGroups(groups); + RebuildListsBasedOnGroups(groups); + + for (auto &it : arDeleted) + delete it; +} + +/////////////////////////////////////////////////////////////////////////////// + +int ClistExtraListRebuild(WPARAM, LPARAM) +{ + clistRebuildAlreadyCalled = TRUE; + + ResetIcons(); + + for (auto &it : extraIconsBySlot) + it->rebuildIcons(); + + return 0; +} + +int ClistExtraImageApply(WPARAM hContact, LPARAM) +{ + if (hContact == 0) + return 0; + + clistApplyAlreadyCalled = TRUE; + + for (auto &it : extraIconsBySlot) + it->applyIcon(hContact); + + return 0; +} + +int ClistExtraClick(WPARAM hContact, LPARAM lParam) +{ + if (hContact == 0) + return 0; + + int clistSlot = (int)lParam; + + for (auto &extra : extraIconsBySlot) { + if (ConvertToClistSlot(extra->getSlot()) == clistSlot) { + extra->onClick(hContact); + break; + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// Extra image list functions + +HANDLE hEventExtraImageListRebuilding, hEventExtraImageApplying, hEventExtraClick; + +static bool bImageCreated = false; +static HIMAGELIST hExtraImageList; + +MIR_APP_DLL(HANDLE) ExtraIcon_AddIcon(HICON hIcon) +{ + if (hExtraImageList == nullptr || hIcon == nullptr) + return INVALID_HANDLE_VALUE; + + int res = ImageList_AddIcon(hExtraImageList, hIcon); + return (res > 0xFFFE) ? INVALID_HANDLE_VALUE : (HANDLE)res; +} + +void fnReloadExtraIcons() +{ + SendMessage(cli.hwndContactTree, CLM_SETEXTRASPACE, db_get_b(0, "CLUI", "ExtraColumnSpace", 18), 0); + SendMessage(cli.hwndContactTree, CLM_SETEXTRAIMAGELIST, 0, 0); + + if (hExtraImageList) + ImageList_Destroy(hExtraImageList); + + hExtraImageList = ImageList_Create(g_iIconSX, g_iIconSY, ILC_COLOR32 | ILC_MASK, 1, 256); + + SendMessage(cli.hwndContactTree, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hExtraImageList); + SendMessage(cli.hwndContactTree, CLM_SETEXTRACOLUMNS, EXTRA_ICON_COUNT, 0); + NotifyEventHooks(hEventExtraImageListRebuilding, 0, 0); + bImageCreated = true; +} + +void fnSetAllExtraIcons(MCONTACT hContact) +{ + if (cli.hwndContactTree == nullptr) + return; + + bool hcontgiven = (hContact != 0); + + if (!bImageCreated) + cli.pfnReloadExtraIcons(); + + SendMessage(cli.hwndContactTree, CLM_SETEXTRACOLUMNS, EXTRA_ICON_COUNT, 0); + + if (hContact == 0) + hContact = db_find_first(); + + for (; hContact; hContact = db_find_next(hContact)) { + NotifyEventHooks(hEventExtraImageApplying, hContact, 0); + if (hcontgiven) + break; + } + + cli.pfnInvalidateRect(cli.hwndContactTree, nullptr, FALSE); +} + +/////////////////////////////////////////////////////////////////////////////// +// external functions + +static void EI_PostCreate(BaseExtraIcon *extra, const char *name, int flags) +{ + char setting[512]; + mir_snprintf(setting, "Position_%s", name); + extra->setPosition(db_get_w(0, MODULE_NAME, setting, 1000)); + + mir_snprintf(setting, "Slot_%s", name); + int slot = db_get_w(0, MODULE_NAME, setting, -100); + if (slot == EMPTY_EXTRA_ICON) + slot = -1; + else if (slot == -100) { + if (flags & EIF_DISABLED_BY_DEFAULT) { + db_set_w(0, MODULE_NAME, setting, EMPTY_EXTRA_ICON); + slot = -1; + } + else slot = 1; + } + extra->setSlot(slot); + + registeredExtraIcons.insert(extra); + extraIconsByHandle.insert(extra); + + LIST groups(1); + LoadGroups(groups); + + ExtraIconGroup *group = IsInGroup(groups, extra); + if (group != nullptr) + RebuildListsBasedOnGroups(groups); + else { + for (auto &it : groups) + delete it; + + extraIconsBySlot.insert(extra); + } + + if (slot >= 0 || group != nullptr) { + if (clistRebuildAlreadyCalled) + extra->rebuildIcons(); + + slot = 0; + for (auto &ex : extraIconsBySlot) { + if (ex->getSlot() < 0) + continue; + + int oldSlot = ex->getSlot(); + ex->setSlot(slot++); + + if (clistApplyAlreadyCalled && (ex == group || ex == extra || oldSlot != slot)) + extra->applyIcons(); + } + } +} + +EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterCallback(const char *name, const char *description, const char *descIcon, + MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, + MIRANDAHOOKPARAM OnClick, LPARAM onClickParam, int flags, int _hLang) +{ + // EXTRAICON_TYPE_CALLBACK + if (IsEmpty(name) || IsEmpty(description)) + return nullptr; + + if (ApplyIcon == nullptr || RebuildIcons == nullptr) + return nullptr; + + // no way to merge + if (GetExtraIconByName(name) != nullptr) + return nullptr; + + ptrW tszDesc(mir_a2u(description)); + + int id = registeredExtraIcons.getCount() + 1; + BaseExtraIcon *extra = new CallbackExtraIcon(id, name, tszDesc, descIcon == nullptr ? "" : descIcon, RebuildIcons, ApplyIcon, OnClick, onClickParam); + extra->m_hLangpack = _hLang; + EI_PostCreate(extra, name, flags); + return (HANDLE)id; +} + +EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterIcolib(const char *name, const char *description, const char *descIcon, + MIRANDAHOOKPARAM OnClick, LPARAM onClickParam, int flags, int _hLang) +{ + if (IsEmpty(name) || IsEmpty(description)) + return nullptr; + + ptrW tszDesc(mir_a2u(description)); + + BaseExtraIcon *extra = GetExtraIconByName(name); + if (extra != nullptr) { + if (extra->getType() != EXTRAICON_TYPE_ICOLIB) + return nullptr; + + // Found one, now merge it + if (!IsEmpty(descIcon)) + extra->setDescIcon(descIcon); + + if (OnClick != nullptr) + extra->setOnClick(OnClick, onClickParam); + + if (extra->getSlot() > 0) { + if (clistRebuildAlreadyCalled) + extra->rebuildIcons(); + if (clistApplyAlreadyCalled) + extraIconsByHandle[extra->getID() - 1]->applyIcons(); + } + + return (HANDLE)extra->getID(); + } + + int id = registeredExtraIcons.getCount() + 1; + extra = new IcolibExtraIcon(id, name, tszDesc, descIcon == nullptr ? "" : descIcon, OnClick, onClickParam); + extra->m_hLangpack = _hLang; + EI_PostCreate(extra, name, flags); + return (HANDLE)id; +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_APP_DLL(int) ExtraIcon_SetIcon(HANDLE hExtraIcon, MCONTACT hContact, HANDLE hImage) +{ + if (hExtraIcon == nullptr || hContact == 0) + return -1; + + ExtraIcon *extra = GetExtraIcon(hExtraIcon); + if (extra == nullptr) + return -1; + + return extra->setIcon((INT_PTR)hExtraIcon, hContact, hImage); +} + +MIR_APP_DLL(int) ExtraIcon_SetIconByName(HANDLE hExtraIcon, MCONTACT hContact, const char *icoName) +{ + if (hExtraIcon == nullptr || hContact == 0) + return -1; + + ExtraIcon *extra = GetExtraIcon(hExtraIcon); + if (extra == nullptr) + return -1; + + return extra->setIconByName((INT_PTR)hExtraIcon, hContact, icoName); +} + +MIR_APP_DLL(int) ExtraIcon_Clear(HANDLE hExtraIcon, MCONTACT hContact) +{ + if (hExtraIcon == nullptr || hContact == 0) + return -1; + + ExtraIcon *extra = GetExtraIcon(hExtraIcon); + if (extra == nullptr) + return -1; + + return extra->setIcon((INT_PTR)hExtraIcon, hContact, nullptr); +} + +/////////////////////////////////////////////////////////////////////////////// + +static IconItem iconList[] = +{ + { LPGEN("Chat activity"), "ChatActivity", IDI_CHAT }, + { LPGEN("Male"), "gender_male", IDI_MALE }, + { LPGEN("Female"), "gender_female", IDI_FEMALE } +}; + +void LoadExtraIconsModule() +{ + // Events + hEventExtraClick = CreateHookableEvent(ME_CLIST_EXTRA_CLICK); + hEventExtraImageApplying = CreateHookableEvent(ME_CLIST_EXTRA_IMAGE_APPLY); + hEventExtraImageListRebuilding = CreateHookableEvent(ME_CLIST_EXTRA_LIST_REBUILD); + + // Icons + Icon_Register(g_hInst, LPGEN("Contact list"), iconList, _countof(iconList)); + + // Hooks + HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + + HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, ClistExtraListRebuild); + HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, ClistExtraImageApply); + HookEvent(ME_CLIST_EXTRA_CLICK, ClistExtraClick); + + DefaultExtraIcons_Load(); +} + +void UnloadExtraIconsModule(void) +{ + for (auto &extra : extraIconsBySlot) + if (extra->getType() == EXTRAICON_TYPE_GROUP) + delete extra; + + for (auto &it : registeredExtraIcons) + delete it; +} diff --git a/src/mir_app/src/extraicons.cpp b/src/mir_app/src/extraicons.cpp deleted file mode 100644 index 1e905d12ae..0000000000 --- a/src/mir_app/src/extraicons.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "m_cluiframes.h" - -#include "extraicons.h" -#include "usedIcons.h" -#include "clc.h" - -// Prototypes /////////////////////////////////////////////////////////////////////////// - -int SortFunc(const ExtraIcon *p1, const ExtraIcon *p2) -{ - int ret = p1->getPosition() - p2->getPosition(); - if (ret != 0) - return ret; - - int id1 = (p1->getType() != EXTRAICON_TYPE_GROUP) ? ((BaseExtraIcon*)p1)->getID() : 0; - int id2 = (p2->getType() != EXTRAICON_TYPE_GROUP) ? ((BaseExtraIcon*)p2)->getID() : 0; - return id1 - id2; -} - -LIST extraIconsByHandle(10), extraIconsBySlot(10, SortFunc); -LIST registeredExtraIcons(10); - -BOOL clistRebuildAlreadyCalled = FALSE; -BOOL clistApplyAlreadyCalled = FALSE; - -// Functions //////////////////////////////////////////////////////////////////////////// - -int InitOptionsCallback(WPARAM wParam, LPARAM lParam); - -// Called when all the modules are loaded -int ModulesLoaded(WPARAM, LPARAM) -{ - HookEvent(ME_OPT_INITIALISE, InitOptionsCallback); - return 0; -} - -int GetNumberOfSlots() -{ - return EXTRA_ICON_COUNT; -} - -int ConvertToClistSlot(int slot) -{ - if (slot < 0) - return slot; - - return slot + 1; -} - -int ExtraImage_ExtraIDToColumnNum(int extra) -{ - return (extra < 1 || extra > EXTRA_ICON_COUNT) ? -1 : extra - 1; -} - -int Clist_SetExtraIcon(MCONTACT hContact, int slot, HANDLE hImage) -{ - if (cli.hwndContactTree == nullptr) - return -1; - - int icol = ExtraImage_ExtraIDToColumnNum(ConvertToClistSlot(slot)); - if (icol == -1) - return -1; - - HANDLE hItem = (HANDLE)SendMessage(cli.hwndContactTree, CLM_FINDCONTACT, hContact, 0); - if (hItem == nullptr) - return -1; - - SendMessage(cli.hwndContactTree, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(icol, hImage)); - return 0; -} - -ExtraIcon* GetExtraIcon(HANDLE id) -{ - int i = (INT_PTR)id; - if (i < 1 || i > extraIconsByHandle.getCount()) - return nullptr; - - return extraIconsByHandle[i - 1]; -} - -ExtraIcon* GetExtraIconBySlot(int slot) -{ - for (auto &extra : extraIconsBySlot) - if (extra->getSlot() == slot) - return extra; - - return nullptr; -} - -BaseExtraIcon* GetExtraIconByName(const char *name) -{ - for (auto &extra : registeredExtraIcons) - if (mir_strcmp(name, extra->getName()) == 0) - return extra; - - return nullptr; -} - -static void LoadGroups(LIST &groups) -{ - int count = db_get_w(0, MODULE_NAME "Groups", "Count", 0); - for (int i = 0; i < count; i++) { - char setting[512]; - mir_snprintf(setting, "%d_count", i); - unsigned int items = db_get_w(0, MODULE_NAME "Groups", setting, 0); - if (items < 1) - continue; - - mir_snprintf(setting, "__group_%d", i); - ExtraIconGroup *group = new ExtraIconGroup(setting); - - for (unsigned int j = 0; j < items; j++) { - mir_snprintf(setting, "%d_%d", i, j); - ptrA szIconName(db_get_sa(0, MODULE_NAME "Groups", setting)); - if (IsEmpty(szIconName)) - continue; - - BaseExtraIcon *extra = GetExtraIconByName(szIconName); - if (extra == nullptr) - continue; - - group->m_items.insert(extra); - if (extra->getSlot() >= 0) - group->setSlot(extra->getSlot()); - } - - if (group->m_items.getCount() < 2) { - delete group; - continue; - } - - groups.insert(group); - } -} - -static ExtraIconGroup* IsInGroup(LIST &groups, BaseExtraIcon *extra) -{ - for (auto &group : groups) - for (auto &it : group->m_items) - if (extra == it) - return group; - - return nullptr; -} - -void RebuildListsBasedOnGroups(LIST &groups) -{ - extraIconsByHandle.destroy(); - - for (auto &it : registeredExtraIcons) - extraIconsByHandle.insert(it); - - for (auto &extra : extraIconsBySlot) - if (extra->getType() == EXTRAICON_TYPE_GROUP) - delete extra; - extraIconsBySlot.destroy(); - - for (auto &group : groups) { - for (auto &it : group->m_items) - extraIconsByHandle.put(it->getID()-1, group); - - extraIconsBySlot.insert(group); - } - - for (auto &extra : extraIconsByHandle) - if (extra->getType() != EXTRAICON_TYPE_GROUP) - extraIconsBySlot.insert(extra); -} - -/////////////////////////////////////////////////////////////////////////////// - -MIR_APP_DLL(void) KillModuleExtraIcons(int _hLang) -{ - LIST arDeleted(1); - - auto T = registeredExtraIcons.rev_iter(); - for (auto &it : T) - if (it->m_hLangpack == _hLang) { - arDeleted.insert(it); - registeredExtraIcons.remove(T.indexOf(&it)); - } - - if (arDeleted.getCount() == 0) - return; - - LIST groups(1); - LoadGroups(groups); - RebuildListsBasedOnGroups(groups); - - for (auto &it : arDeleted) - delete it; -} - -/////////////////////////////////////////////////////////////////////////////// - -int ClistExtraListRebuild(WPARAM, LPARAM) -{ - clistRebuildAlreadyCalled = TRUE; - - ResetIcons(); - - for (auto &it : extraIconsBySlot) - it->rebuildIcons(); - - return 0; -} - -int ClistExtraImageApply(WPARAM hContact, LPARAM) -{ - if (hContact == 0) - return 0; - - clistApplyAlreadyCalled = TRUE; - - for (auto &it : extraIconsBySlot) - it->applyIcon(hContact); - - return 0; -} - -int ClistExtraClick(WPARAM hContact, LPARAM lParam) -{ - if (hContact == 0) - return 0; - - int clistSlot = (int)lParam; - - for (auto &extra : extraIconsBySlot) { - if (ConvertToClistSlot(extra->getSlot()) == clistSlot) { - extra->onClick(hContact); - break; - } - } - - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// -// Extra image list functions - -HANDLE hEventExtraImageListRebuilding, hEventExtraImageApplying, hEventExtraClick; - -static bool bImageCreated = false; -static HIMAGELIST hExtraImageList; - -MIR_APP_DLL(HANDLE) ExtraIcon_AddIcon(HICON hIcon) -{ - if (hExtraImageList == nullptr || hIcon == nullptr) - return INVALID_HANDLE_VALUE; - - int res = ImageList_AddIcon(hExtraImageList, hIcon); - return (res > 0xFFFE) ? INVALID_HANDLE_VALUE : (HANDLE)res; -} - -void fnReloadExtraIcons() -{ - SendMessage(cli.hwndContactTree, CLM_SETEXTRASPACE, db_get_b(0, "CLUI", "ExtraColumnSpace", 18), 0); - SendMessage(cli.hwndContactTree, CLM_SETEXTRAIMAGELIST, 0, 0); - - if (hExtraImageList) - ImageList_Destroy(hExtraImageList); - - hExtraImageList = ImageList_Create(g_iIconSX, g_iIconSY, ILC_COLOR32 | ILC_MASK, 1, 256); - - SendMessage(cli.hwndContactTree, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hExtraImageList); - SendMessage(cli.hwndContactTree, CLM_SETEXTRACOLUMNS, EXTRA_ICON_COUNT, 0); - NotifyEventHooks(hEventExtraImageListRebuilding, 0, 0); - bImageCreated = true; -} - -void fnSetAllExtraIcons(MCONTACT hContact) -{ - if (cli.hwndContactTree == nullptr) - return; - - bool hcontgiven = (hContact != 0); - - if (!bImageCreated) - cli.pfnReloadExtraIcons(); - - SendMessage(cli.hwndContactTree, CLM_SETEXTRACOLUMNS, EXTRA_ICON_COUNT, 0); - - if (hContact == 0) - hContact = db_find_first(); - - for (; hContact; hContact = db_find_next(hContact)) { - NotifyEventHooks(hEventExtraImageApplying, hContact, 0); - if (hcontgiven) - break; - } - - cli.pfnInvalidateRect(cli.hwndContactTree, nullptr, FALSE); -} - -/////////////////////////////////////////////////////////////////////////////// -// external functions - -static void EI_PostCreate(BaseExtraIcon *extra, const char *name, int flags) -{ - char setting[512]; - mir_snprintf(setting, "Position_%s", name); - extra->setPosition(db_get_w(0, MODULE_NAME, setting, 1000)); - - mir_snprintf(setting, "Slot_%s", name); - int slot = db_get_w(0, MODULE_NAME, setting, -100); - if (slot == EMPTY_EXTRA_ICON) - slot = -1; - else if (slot == -100) { - if (flags & EIF_DISABLED_BY_DEFAULT) { - db_set_w(0, MODULE_NAME, setting, EMPTY_EXTRA_ICON); - slot = -1; - } - else slot = 1; - } - extra->setSlot(slot); - - registeredExtraIcons.insert(extra); - extraIconsByHandle.insert(extra); - - LIST groups(1); - LoadGroups(groups); - - ExtraIconGroup *group = IsInGroup(groups, extra); - if (group != nullptr) - RebuildListsBasedOnGroups(groups); - else { - for (auto &it : groups) - delete it; - - extraIconsBySlot.insert(extra); - } - - if (slot >= 0 || group != nullptr) { - if (clistRebuildAlreadyCalled) - extra->rebuildIcons(); - - slot = 0; - for (auto &ex : extraIconsBySlot) { - if (ex->getSlot() < 0) - continue; - - int oldSlot = ex->getSlot(); - ex->setSlot(slot++); - - if (clistApplyAlreadyCalled && (ex == group || ex == extra || oldSlot != slot)) - extra->applyIcons(); - } - } -} - -EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterCallback(const char *name, const char *description, const char *descIcon, - MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, - MIRANDAHOOKPARAM OnClick, LPARAM onClickParam, int flags, int _hLang) -{ - // EXTRAICON_TYPE_CALLBACK - if (IsEmpty(name) || IsEmpty(description)) - return nullptr; - - if (ApplyIcon == nullptr || RebuildIcons == nullptr) - return nullptr; - - // no way to merge - if (GetExtraIconByName(name) != nullptr) - return nullptr; - - ptrW tszDesc(mir_a2u(description)); - - int id = registeredExtraIcons.getCount() + 1; - BaseExtraIcon *extra = new CallbackExtraIcon(id, name, tszDesc, descIcon == nullptr ? "" : descIcon, RebuildIcons, ApplyIcon, OnClick, onClickParam); - extra->m_hLangpack = _hLang; - EI_PostCreate(extra, name, flags); - return (HANDLE)id; -} - -EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterIcolib(const char *name, const char *description, const char *descIcon, - MIRANDAHOOKPARAM OnClick, LPARAM onClickParam, int flags, int _hLang) -{ - if (IsEmpty(name) || IsEmpty(description)) - return nullptr; - - ptrW tszDesc(mir_a2u(description)); - - BaseExtraIcon *extra = GetExtraIconByName(name); - if (extra != nullptr) { - if (extra->getType() != EXTRAICON_TYPE_ICOLIB) - return nullptr; - - // Found one, now merge it - if (!IsEmpty(descIcon)) - extra->setDescIcon(descIcon); - - if (OnClick != nullptr) - extra->setOnClick(OnClick, onClickParam); - - if (extra->getSlot() > 0) { - if (clistRebuildAlreadyCalled) - extra->rebuildIcons(); - if (clistApplyAlreadyCalled) - extraIconsByHandle[extra->getID() - 1]->applyIcons(); - } - - return (HANDLE)extra->getID(); - } - - int id = registeredExtraIcons.getCount() + 1; - extra = new IcolibExtraIcon(id, name, tszDesc, descIcon == nullptr ? "" : descIcon, OnClick, onClickParam); - extra->m_hLangpack = _hLang; - EI_PostCreate(extra, name, flags); - return (HANDLE)id; -} - -/////////////////////////////////////////////////////////////////////////////// - -MIR_APP_DLL(int) ExtraIcon_SetIcon(HANDLE hExtraIcon, MCONTACT hContact, HANDLE hImage) -{ - if (hExtraIcon == nullptr || hContact == 0) - return -1; - - ExtraIcon *extra = GetExtraIcon(hExtraIcon); - if (extra == nullptr) - return -1; - - return extra->setIcon((INT_PTR)hExtraIcon, hContact, hImage); -} - -MIR_APP_DLL(int) ExtraIcon_SetIconByName(HANDLE hExtraIcon, MCONTACT hContact, const char *icoName) -{ - if (hExtraIcon == nullptr || hContact == 0) - return -1; - - ExtraIcon *extra = GetExtraIcon(hExtraIcon); - if (extra == nullptr) - return -1; - - return extra->setIconByName((INT_PTR)hExtraIcon, hContact, icoName); -} - -MIR_APP_DLL(int) ExtraIcon_Clear(HANDLE hExtraIcon, MCONTACT hContact) -{ - if (hExtraIcon == nullptr || hContact == 0) - return -1; - - ExtraIcon *extra = GetExtraIcon(hExtraIcon); - if (extra == nullptr) - return -1; - - return extra->setIcon((INT_PTR)hExtraIcon, hContact, nullptr); -} - -/////////////////////////////////////////////////////////////////////////////// - -static IconItem iconList[] = -{ - { LPGEN("Chat activity"), "ChatActivity", IDI_CHAT }, - { LPGEN("Male"), "gender_male", IDI_MALE }, - { LPGEN("Female"), "gender_female", IDI_FEMALE } -}; - -void LoadExtraIconsModule() -{ - // Events - hEventExtraClick = CreateHookableEvent(ME_CLIST_EXTRA_CLICK); - hEventExtraImageApplying = CreateHookableEvent(ME_CLIST_EXTRA_IMAGE_APPLY); - hEventExtraImageListRebuilding = CreateHookableEvent(ME_CLIST_EXTRA_LIST_REBUILD); - - // Icons - Icon_Register(g_hInst, LPGEN("Contact list"), iconList, _countof(iconList)); - - // Hooks - HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); - - HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, ClistExtraListRebuild); - HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, ClistExtraImageApply); - HookEvent(ME_CLIST_EXTRA_CLICK, ClistExtraClick); - - DefaultExtraIcons_Load(); -} - -void UnloadExtraIconsModule(void) -{ - for (auto &extra : extraIconsBySlot) - if (extra->getType() == EXTRAICON_TYPE_GROUP) - delete extra; - - for (auto &it : registeredExtraIcons) - delete it; -} diff --git a/src/mir_app/src/extraicons.h b/src/mir_app/src/extraicons.h index 3df435035e..6c059ca4d7 100644 --- a/src/mir_app/src/extraicons.h +++ b/src/mir_app/src/extraicons.h @@ -19,8 +19,8 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __COMMONS_H__ -# define __COMMONS_H__ +#ifndef __EXTRAICONS_H__ +# define __EXTRAICONS_H__ #define MODULE_NAME "ExtraIcons" @@ -28,7 +28,162 @@ Boston, MA 02111-1307, USA. #define ICON_SIZE 16 -#include "Extraicon.h" +#define EXTRAICON_TYPE_GROUP -1 + +///////////////////////////////////////////////////////////////////////////////////////// +// ExtraIcon - base class for all extra icons + +class ExtraIcon +{ +public: + ExtraIcon(const char *name); + virtual ~ExtraIcon(); + + virtual void rebuildIcons() = 0; + virtual void applyIcons(); + virtual void applyIcon(MCONTACT hContact) = 0; + virtual void onClick(MCONTACT hContact) = 0; + + virtual int setIcon(int id, MCONTACT hContact, HANDLE icon) = 0; + virtual int setIconByName(int id, MCONTACT hContact, const char* icon) = 0; + virtual void storeIcon(MCONTACT, void*) {}; + + virtual const char *getName() const; + virtual const wchar_t *getDescription() const = 0; + virtual const char *getDescIcon() const = 0; + virtual int getType() const = 0; + + virtual int getSlot() const; + virtual void setSlot(int slot); + + virtual int getPosition() const; + virtual void setPosition(int position); + + virtual bool isEnabled() const; + + virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) = 0; + + int m_hLangpack; + +protected: + ptrA m_szName; + + int m_slot; + int m_position; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// BaseExtraIcon - basic class for all 'real' extra icons + +class BaseExtraIcon : public ExtraIcon +{ +public: + BaseExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); + virtual ~BaseExtraIcon(); + + virtual int getID() const; + virtual const wchar_t *getDescription() const; + virtual void setDescription(const wchar_t *desc); + virtual const char *getDescIcon() const; + virtual void setDescIcon(const char *icon); + virtual int getType() const =0; + + virtual void onClick(MCONTACT hContact); + virtual void setOnClick(MIRANDAHOOKPARAM OnClick, LPARAM param); + + virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage); + +protected: + int m_id; + ptrW m_tszDescription; + ptrA m_szDescIcon; + MIRANDAHOOKPARAM m_OnClick; + LPARAM m_onClickParam; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// CallbackExtraIcon - extra icon, implemented using callback functions + +class CallbackExtraIcon : public BaseExtraIcon +{ +public: + CallbackExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, + MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); + virtual ~CallbackExtraIcon(); + + virtual int getType() const; + + virtual void rebuildIcons(); + virtual void applyIcon(MCONTACT hContact); + + virtual int setIcon(int id, MCONTACT hContact, HANDLE icon); + virtual int setIconByName(int id, MCONTACT hContact, const char* icon); + +private: + int (*m_pfnRebuildIcons)(WPARAM wParam, LPARAM lParam); + int (*m_pfnApplyIcon)(WPARAM wParam, LPARAM lParam); + + bool m_needToRebuild; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// IcolibExtraIcon - extra icon, implemented using icolib + +class IcolibExtraIcon : public BaseExtraIcon +{ +public: + IcolibExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); + virtual ~IcolibExtraIcon(); + + virtual int getType() const; + + virtual void rebuildIcons(); + virtual void applyIcon(MCONTACT hContact); + + virtual int setIcon(int id, MCONTACT hContact, HANDLE icon); + virtual int setIconByName(int id, MCONTACT hContact, const char* icon); + virtual void storeIcon(MCONTACT hContact, void *icon); +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// ExtraIconGroup - joins some slots into one + +class ExtraIconGroup : public ExtraIcon +{ + int internalSetIcon(int id, MCONTACT hContact, HANDLE icon, bool bByName); +public: + ExtraIconGroup(const char *name); + virtual ~ExtraIconGroup(); + + virtual void addExtraIcon(BaseExtraIcon *extra); + + virtual void rebuildIcons(); + virtual void applyIcon(MCONTACT hContact); + virtual void onClick(MCONTACT hContact); + + virtual int setIcon(int id, MCONTACT hContact, HANDLE icon); + virtual int setIconByName(int id, MCONTACT hContact, const char *icon); + + virtual const wchar_t* getDescription() const; + virtual const char* getDescIcon() const; + virtual int getType() const; + + virtual int getPosition() const; + virtual void setSlot(int slot); + + LIST m_items; + + virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage); + +protected: + ptrW m_tszDescription; + bool m_setValidExtraIcon; + bool m_insideApply; + + virtual ExtraIcon *getCurrentItem(MCONTACT hContact) const; +}; + +///////////////////////////////////////////////////////////////////////////////////////// extern LIST registeredExtraIcons; extern LIST extraIconsByHandle, extraIconsBySlot; @@ -50,4 +205,4 @@ static inline BOOL IsEmpty(const char *str) return str == nullptr || str[0] == 0; } -#endif // __COMMONS_H__ +#endif // __EXTRAICONS_H__ diff --git a/src/mir_app/src/options_ei.cpp b/src/mir_app/src/options_ei.cpp deleted file mode 100644 index 0afc0b9b98..0000000000 --- a/src/mir_app/src/options_ei.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* - -Copyright (C) 2009 Ricardo Pescuma Domenecci -Copyright (C) 2012-18 Miranda NG team - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include "extraicons.h" - -#define ICON_SIZE 16 - -int SortFunc(const ExtraIcon *p1, const ExtraIcon *p2); - -struct intlist -{ - intlist() : count(0), data(nullptr) {} - ~intlist() { mir_free(data); } - - void add(int val) - { - data = (int*)mir_realloc(data, sizeof(int)*(count + 1)); - data[count++] = val; - } - - int count; - int *data; -}; - -static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM) -{ - intlist *a = (intlist*)lParam1; - intlist *b = (intlist*)lParam2; - return SortFunc(registeredExtraIcons[a->data[0] - 1], registeredExtraIcons[b->data[0] - 1]); -} - -// Functions ////////////////////////////////////////////////////////////////////////////////////// - -BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) -{ - POINT pt; - pt.x = lpRect->left; - pt.y = lpRect->top; - - BOOL ret = ScreenToClient(hWnd, &pt); - if (!ret) - return ret; - - lpRect->left = pt.x; - lpRect->top = pt.y; - - pt.x = lpRect->right; - pt.y = lpRect->bottom; - - ret = ScreenToClient(hWnd, &pt); - - lpRect->right = pt.x; - lpRect->bottom = pt.y; - - return ret; -} - -static void RemoveExtraIcons(int slot) -{ - for (auto &hContact : Contacts()) - Clist_SetExtraIcon(hContact, slot, INVALID_HANDLE_VALUE); -} - -class CExtraIconOptsDlg : public CDlgBase -{ - intlist* Tree_GetIDs(HTREEITEM hItem) - { - TVITEMEX tvi; - tvi.mask = TVIF_HANDLE | TVIF_PARAM; - tvi.hItem = hItem; - m_tree.GetItem(&tvi); - return (intlist*)tvi.lParam; - } - - HTREEITEM Tree_AddExtraIcon(BaseExtraIcon *extra, bool selected, HTREEITEM hAfter = TVI_LAST) - { - intlist *ids = new intlist(); - ids->add(extra->getID()); - - TVINSERTSTRUCT tvis = {}; - tvis.hInsertAfter = hAfter; - tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; - tvis.item.stateMask = TVIS_STATEIMAGEMASK; - tvis.item.iSelectedImage = tvis.item.iImage = extra->getID(); - tvis.item.lParam = (LPARAM)ids; - tvis.item.pszText = (LPTSTR)extra->getDescription(); - tvis.item.state = INDEXTOSTATEIMAGEMASK(selected ? 2 : 1); - return m_tree.InsertItem(&tvis); - } - - HTREEITEM Tree_AddExtraIconGroup(intlist &group, bool selected, HTREEITEM hAfter = TVI_LAST) - { - intlist *ids = new intlist(); - CMStringW desc; - int img = 0; - for (int i = 0; i < group.count; i++) { - BaseExtraIcon *extra = registeredExtraIcons[group.data[i] - 1]; - ids->add(extra->getID()); - - if (img == 0 && !IsEmpty(extra->getDescIcon())) - img = extra->getID(); - - if (i > 0) - desc += L" / "; - desc += extra->getDescription(); - } - - TVINSERTSTRUCT tvis = {}; - tvis.hInsertAfter = hAfter; - tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; - tvis.item.stateMask = TVIS_STATEIMAGEMASK; - tvis.item.iSelectedImage = tvis.item.iImage = img; - tvis.item.lParam = (LPARAM)ids; - tvis.item.pszText = (wchar_t*)desc.c_str(); - tvis.item.state = INDEXTOSTATEIMAGEMASK(selected ? 2 : 1); - return m_tree.InsertItem(&tvis); - } - - void GroupSelectedItems() - { - LIST<_TREEITEM> toRemove(1); - intlist ids; - bool selected = false; - HTREEITEM hPlace = nullptr; - - // Find items - HTREEITEM hItem = m_tree.GetRoot(); - TVITEMEX tvi = { 0 }; - tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_STATE; - while (hItem) { - if (m_tree.IsSelected(hItem)) { - if (hPlace == nullptr) - hPlace = hItem; - - tvi.hItem = hItem; - m_tree.GetItem(&tvi); - - intlist *iids = (intlist*)tvi.lParam; - for (int i = 0; i < iids->count; i++) - ids.add(iids->data[i]); - - if ((tvi.state & INDEXTOSTATEIMAGEMASK(3)) == INDEXTOSTATEIMAGEMASK(2)) - selected = true; - - toRemove.insert(hItem); - } - - hItem = m_tree.GetNextSibling(hItem); - } - - if (hPlace != nullptr) { - // Add new - HTREEITEM hNew = Tree_AddExtraIconGroup(ids, selected, hPlace); - - // Remove old - for (auto &p : toRemove) { - delete Tree_GetIDs(p); - m_tree.DeleteItem(p); - } - - // Select - m_tree.UnselectAll(); - m_tree.SelectItem(hNew); - } - } - - void UngroupSelectedItems() - { - HTREEITEM hItem = m_tree.GetSelection(); - if (hItem == nullptr) - return; - - intlist *ids = Tree_GetIDs(hItem); - if (ids->count < 2) - return; - - bool selected = m_tree.IsSelected(hItem); - - for (int i = ids->count - 1; i >= 0; i--) { - BaseExtraIcon *extra = registeredExtraIcons[ids->data[i] - 1]; - Tree_AddExtraIcon(extra, selected, hItem); - } - - delete ids; - m_tree.DeleteItem(hItem); - - m_tree.UnselectAll(); - } - - int ShowPopup(int popup) - { - // Fix selection - HTREEITEM hSelected = m_tree.GetDropHilight(); - HTREEITEM hItem = m_tree.GetRoot(); - while (hItem) { - if (hItem != hSelected && m_tree.IsSelected(hItem)) - m_tree.DropHilite(hItem); - - hItem = m_tree.GetNextSibling(hItem); - } - - HMENU menu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_OPT_POPUP)); - HMENU submenu = GetSubMenu(menu, popup); - TranslateMenu(submenu); - - DWORD pos = GetMessagePos(); - int ret = TrackPopupMenu(submenu, TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_LEFTALIGN, LOWORD(pos), HIWORD(pos), 0, m_hwnd, nullptr); - - DestroyMenu(menu); - - // Revert selection - hItem = m_tree.GetRoot(); - while (hItem) { - if (hItem != hSelected && m_tree.IsSelected(hItem)) - m_tree.DropUnhilite(hItem); - hItem = m_tree.GetNextSibling(hItem); - } - - return ret; - } - - CCtrlTreeView m_tree; - -public: - CExtraIconOptsDlg() : - CDlgBase(g_hInst, IDD_EI_OPTIONS), - m_tree(this, IDC_EXTRAORDER) - { - m_tree.SetFlags(MTREE_DND | MTREE_MULTISELECT); - } - - virtual void OnInitDialog() - { - int numSlots = GetNumberOfSlots(); - if (numSlots < (int)registeredExtraIcons.getCount()) { - HWND label = GetDlgItem(m_hwnd, IDC_MAX_ICONS_L); - SetWindowText(label, CMStringW(FORMAT, TranslateT("*only the first %d icons will be shown"), numSlots)); - ShowWindow(label, SW_SHOW); - } - - int cx = g_iIconSX; - HIMAGELIST hImageList = ImageList_Create(cx, cx, ILC_COLOR32 | ILC_MASK, 2, 2); - - HICON hBlankIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, cx, cx, 0); - ImageList_AddIcon(hImageList, hBlankIcon); - - for (auto &extra : registeredExtraIcons) { - HICON hIcon = IcoLib_GetIcon(extra->getDescIcon()); - if (hIcon == nullptr) - ImageList_AddIcon(hImageList, hBlankIcon); - else { - ImageList_AddIcon(hImageList, hIcon); - IcoLib_ReleaseIcon(hIcon); - } - } - m_tree.SetImageList(hImageList, TVSIL_NORMAL); - DestroyIcon(hBlankIcon); - - for (auto &extra : extraIconsBySlot) { - if (extra->getType() == EXTRAICON_TYPE_GROUP) { - ExtraIconGroup *group = (ExtraIconGroup *)extra; - intlist ids; - for (auto &p : group->m_items) - ids.add(p->getID()); - Tree_AddExtraIconGroup(ids, extra->isEnabled()); - } - else Tree_AddExtraIcon((BaseExtraIcon *)extra, extra->isEnabled()); - } - - TVSORTCB sort = {}; - sort.hParent = nullptr; - sort.lParam = 0; - sort.lpfnCompare = CompareFunc; - m_tree.SortChildrenCB(&sort, 0); - } - - virtual void OnApply() - { - // Store old slots - int *oldSlots = new int[registeredExtraIcons.getCount()]; - int lastUsedSlot = -1; - for (int i = 0; i < registeredExtraIcons.getCount(); i++) { - if (extraIconsByHandle[i] == registeredExtraIcons[i]) - oldSlots[i] = registeredExtraIcons[i]->getSlot(); - else - // Remove old slot for groups to re-set images - oldSlots[i] = -1; - lastUsedSlot = max(lastUsedSlot, registeredExtraIcons[i]->getSlot()); - } - lastUsedSlot = min(lastUsedSlot, GetNumberOfSlots()); - - // Get user data and create new groups - LIST groups(1); - - BYTE pos = 0; - int firstEmptySlot = 0; - HTREEITEM ht = m_tree.GetRoot(); - TVITEMEX tvi; - tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; - tvi.stateMask = TVIS_STATEIMAGEMASK; - while (ht) { - tvi.hItem = ht; - m_tree.GetItem(&tvi); - - intlist*ids = (intlist*)tvi.lParam; - if (ids == nullptr || ids->count < 1) - continue; // ??? - - bool enabled = ((tvi.state & INDEXTOSTATEIMAGEMASK(3)) == INDEXTOSTATEIMAGEMASK(2)); - int slot = (enabled ? firstEmptySlot++ : -1); - if (slot >= GetNumberOfSlots()) - slot = -1; - - if (ids->count == 1) { - BaseExtraIcon *extra = registeredExtraIcons[ids->data[0] - 1]; - extra->setPosition(pos++); - extra->setSlot(slot); - } - else { - char name[128]; - mir_snprintf(name, "__group_%d", groups.getCount()); - - ExtraIconGroup *group = new ExtraIconGroup(name); - - for (int i = 0; i < ids->count; i++) { - BaseExtraIcon *extra = registeredExtraIcons[ids->data[i] - 1]; - extra->setPosition(pos++); - - group->addExtraIcon(extra); - } - - group->setSlot(slot); - groups.insert(group); - } - - ht = m_tree.GetNextSibling(ht); - } - - // Store data - for (auto &extra : registeredExtraIcons) { - char setting[512]; - mir_snprintf(setting, "Position_%s", extra->getName()); - db_set_w(0, MODULE_NAME, setting, extra->getPosition()); - - mir_snprintf(setting, "Slot_%s", extra->getName()); - db_set_w(0, MODULE_NAME, setting, extra->getSlot()); - } - - db_delete_module(0, MODULE_NAME "Groups"); - db_set_w(0, MODULE_NAME "Groups", "Count", groups.getCount()); - for (int k = 0; k < groups.getCount(); k++) { - ExtraIconGroup *group = groups[k]; - - char setting[512]; - mir_snprintf(setting, "%d_count", k); - db_set_w(0, MODULE_NAME "Groups", setting, (WORD)group->m_items.getCount()); - - for (int j = 0; j < group->m_items.getCount(); j++) { - BaseExtraIcon *extra = group->m_items[j]; - - mir_snprintf(setting, "%d_%d", k, j); - db_set_s(0, MODULE_NAME "Groups", setting, extra->getName()); - } - } - - // Clean removed slots - for (int j = firstEmptySlot; j <= lastUsedSlot; j++) - RemoveExtraIcons(j); - - // Apply icons to new slots - RebuildListsBasedOnGroups(groups); - for (auto &extra : extraIconsBySlot) { - if (extra->getType() != EXTRAICON_TYPE_GROUP) - if (oldSlots[((BaseExtraIcon *)extra)->getID() - 1] == extra->getSlot()) - continue; - - if (extra->isEnabled()) - extra->applyIcons(); - } - - delete[] oldSlots; - } - - virtual void OnDestroy() - { - HTREEITEM hItem = m_tree.GetRoot(); - while (hItem) { - delete Tree_GetIDs(hItem); - hItem = m_tree.GetNextSibling(hItem); - } - - ImageList_Destroy(m_tree.GetImageList(TVSIL_NORMAL)); - } - - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) - { - if (msg == WM_NOTIFY) { - LPNMHDR lpnmhdr = (LPNMHDR)lParam; - if (lpnmhdr->idFrom == IDC_EXTRAORDER && lpnmhdr->code == NM_RCLICK) { - HTREEITEM hSelected = m_tree.GetDropHilight(); - if (hSelected != nullptr && !m_tree.IsSelected(hSelected)) { - m_tree.UnselectAll(); - m_tree.SelectItem(hSelected); - } - - int sels = m_tree.GetNumSelected(); - if (sels > 1) { - if (ShowPopup(0) == ID_GROUP) { - GroupSelectedItems(); - NotifyChange(); - } - } - else if (sels == 1) { - HTREEITEM hItem = m_tree.GetSelection(); - intlist *ids = Tree_GetIDs(hItem); - if (ids->count > 1) { - if (ShowPopup(1) == ID_UNGROUP) { - UngroupSelectedItems(); - NotifyChange(); - } - } - } - } - } - - return CDlgBase::DlgProc(msg, wParam, lParam); - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -int InitOptionsCallback(WPARAM wParam, LPARAM) -{ - if (GetNumberOfSlots() < 1) - return 0; - - OPTIONSDIALOGPAGE odp = { 0 }; - odp.szGroup.a = LPGEN("Contact list"); - odp.szTitle.a = LPGEN("Extra icons"); - odp.szTab.a = LPGEN("General"); - odp.flags = ODPF_BOLDGROUPS; - odp.pDialog = new CExtraIconOptsDlg(); - Options_AddPage(wParam, &odp); - return 0; -} -- cgit v1.2.3