#include "StdAfx.h" #include "QuotesProviderCurrencyConverter.h" #define WINDOW_PREFIX "CurrenyConverter_" #define DB_STR_CC_QUOTE_FROM_ID "CurrencyConverter_FromID" #define DB_STR_CC_QUOTE_TO_ID "CurrencyConverter_ToID" #define DB_STR_CC_AMOUNT "CurrencyConverter_Amount" static CQuotesProviderCurrencyConverter* get_currency_converter_provider() { CModuleInfo::TQuotesProvidersPtr pProviders = CModuleInfo::GetQuoteProvidersPtr(); const CQuotesProviders::TQuotesProviders& rapQuotesProviders = pProviders->GetProviders(); for (CQuotesProviders::TQuotesProviders::const_iterator i = rapQuotesProviders.begin(); i != rapQuotesProviders.end(); ++i) { const CQuotesProviders::TQuotesProviderPtr& pProvider = *i; if (auto p = dynamic_cast(pProvider.get())) { return p; } } assert(!"We should never get here!"); return nullptr; } CQuotesProviderBase::CQuoteSection get_quotes(const CQuotesProviderCurrencyConverter* pProvider = nullptr) { if (nullptr == pProvider) pProvider = get_currency_converter_provider(); if (pProvider) { const auto& rQuotes = pProvider->GetQuotes(); if (rQuotes.GetSectionCount() > 0) return rQuotes.GetSection(0); } return CQuotesProviderBase::CQuoteSection(); } inline tstring make_quote_name(const CQuotesProviderBase::CQuote& rQuote) { const tstring& rsDesc = rQuote.GetName(); return((false == rsDesc.empty()) ? rsDesc : rQuote.GetSymbol()); } inline void update_convert_button(HWND hDlg) { int nFrom = static_cast(::SendDlgItemMessage(hDlg, IDC_COMBO_CONVERT_FROM, CB_GETCURSEL, 0, 0)); int nTo = static_cast(::SendDlgItemMessage(hDlg, IDC_COMBO_CONVERT_INTO, CB_GETCURSEL, 0, 0)); bool bEnableButton = ((CB_ERR != nFrom) && (CB_ERR != nTo) && (nFrom != nTo) && (GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT_VALUE)) > 0)); EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_CONVERT), bEnableButton); } inline void update_swap_button(HWND hDlg) { int nFrom = static_cast(::SendDlgItemMessage(hDlg, IDC_COMBO_CONVERT_FROM, CB_GETCURSEL, 0, 0)); int nTo = static_cast(::SendDlgItemMessage(hDlg, IDC_COMBO_CONVERT_INTO, CB_GETCURSEL, 0, 0)); bool bEnableButton = ((CB_ERR != nFrom) && (CB_ERR != nTo) && (nFrom != nTo)); EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_SWAP), bEnableButton); } inline tstring double2str(double dValue) { tostringstream output; output.imbue(GetSystemLocale()); output << std::fixed << std::setprecision(2) << dValue; return output.str(); } inline bool str2double(const tstring& s, double& d) { tistringstream input(s); input.imbue(GetSystemLocale()); input >> d; return ((false == input.bad()) && (false == input.fail())); } INT_PTR CALLBACK CurrencyConverterDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hDlg); { MWindowList hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX, false); assert(hWL); WindowList_Add(hWL, hDlg); Window_SetIcon_IcoLib(hDlg, Quotes_GetIconHandle(IDI_ICON_CURRENCY_CONVERTER)); HWND hcbxFrom = ::GetDlgItem(hDlg, IDC_COMBO_CONVERT_FROM); HWND hcbxTo = ::GetDlgItem(hDlg, IDC_COMBO_CONVERT_INTO); tstring sFromQuoteID = Quotes_DBGetStringT(NULL, QUOTES_MODULE_NAME, DB_STR_CC_QUOTE_FROM_ID); tstring sToQuoteID = Quotes_DBGetStringT(NULL, QUOTES_MODULE_NAME, DB_STR_CC_QUOTE_TO_ID); const auto pProvider = get_currency_converter_provider(); const auto& rSection = get_quotes(pProvider); auto cQuotes = rSection.GetQuoteCount(); for (auto i = 0u; i < cQuotes; ++i) { const auto& rQuote = rSection.GetQuote(i); tstring sName = make_quote_name(rQuote); LPCTSTR pszName = sName.c_str(); LRESULT nFrom = ::SendMessage(hcbxFrom, CB_ADDSTRING, 0, reinterpret_cast(pszName)); LRESULT nTo = ::SendMessage(hcbxTo, CB_ADDSTRING, 0, reinterpret_cast(pszName)); if (0 == mir_wstrcmpi(rQuote.GetID().c_str(), sFromQuoteID.c_str())) { ::SendMessage(hcbxFrom, CB_SETCURSEL, nFrom, 0); } if (0 == mir_wstrcmpi(rQuote.GetID().c_str(), sToQuoteID.c_str())) { ::SendMessage(hcbxTo, CB_SETCURSEL, nTo, 0); } } double dAmount = 1.0; Quotes_DBReadDouble(NULL, QUOTES_MODULE_NAME, DB_STR_CC_AMOUNT, dAmount); ::SetDlgItemText(hDlg, IDC_EDIT_VALUE, double2str(dAmount).c_str()); const IQuotesProvider::CProviderInfo& pi = pProvider->GetInfo(); tostringstream o; o << TranslateT("Info provided by") << L" " << pi.m_sName << L""; ::SetDlgItemText(hDlg, IDC_SYSLINK_PROVIDER, o.str().c_str()); ::SendDlgItemMessage(hDlg, IDC_BUTTON_SWAP, BM_SETIMAGE, IMAGE_ICON, LPARAM(Quotes_LoadIconEx(IDI_ICON_SWAP))); update_convert_button(hDlg); update_swap_button(hDlg); Utils_RestoreWindowPositionNoSize(hDlg, NULL, QUOTES_PROTOCOL_NAME, WINDOW_PREFIX); ::ShowWindow(hDlg, SW_SHOW); } return TRUE; case WM_CLOSE: { MWindowList hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX, false); assert(hWL); WindowList_Remove(hWL, hDlg); Utils_SaveWindowPosition(hDlg, NULL, QUOTES_PROTOCOL_NAME, WINDOW_PREFIX); EndDialog(hDlg, 0); } return TRUE; case WM_DESTROY: Window_FreeIcon_IcoLib(hDlg); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDC_COMBO_CONVERT_FROM: case IDC_COMBO_CONVERT_INTO: if (CBN_SELCHANGE == HIWORD(wp)) { update_convert_button(hDlg); update_swap_button(hDlg); } return TRUE; case IDC_EDIT_VALUE: if (EN_CHANGE == HIWORD(wp)) update_convert_button(hDlg); return TRUE; case IDCANCEL: SendMessage(hDlg, WM_CLOSE, 0, 0); return TRUE; case IDC_BUTTON_SWAP: { HWND wndFrom = ::GetDlgItem(hDlg, IDC_COMBO_CONVERT_FROM); HWND wndTo = ::GetDlgItem(hDlg, IDC_COMBO_CONVERT_INTO); WPARAM nFrom = ::SendMessage(wndFrom, CB_GETCURSEL, 0, 0); WPARAM nTo = ::SendMessage(wndTo, CB_GETCURSEL, 0, 0); ::SendMessage(wndFrom, CB_SETCURSEL, nTo, 0); ::SendMessage(wndTo, CB_SETCURSEL, nFrom, 0); } return TRUE; case IDC_BUTTON_CONVERT: { HWND hwndAmount = GetDlgItem(hDlg, IDC_EDIT_VALUE); tstring sText = get_window_text(hwndAmount); double dAmount = 1.0; if ((true == str2double(sText, dAmount)) && (dAmount > 0.0)) { Quotes_DBWriteDouble(NULL, QUOTES_MODULE_NAME, DB_STR_CC_AMOUNT, dAmount); size_t nFrom = static_cast(::SendDlgItemMessage(hDlg, IDC_COMBO_CONVERT_FROM, CB_GETCURSEL, 0, 0)); size_t nTo = static_cast(::SendDlgItemMessage(hDlg, IDC_COMBO_CONVERT_INTO, CB_GETCURSEL, 0, 0)); if ((CB_ERR != nFrom) && (CB_ERR != nTo) && (nFrom != nTo)) { const auto& rSection = get_quotes(); size_t cQuotes = rSection.GetQuoteCount(); if ((nFrom < cQuotes) && (nTo < cQuotes)) { auto from = rSection.GetQuote(nFrom); auto to = rSection.GetQuote(nTo); db_set_ws(NULL, QUOTES_MODULE_NAME, DB_STR_CC_QUOTE_FROM_ID, from.GetID().c_str()); db_set_ws(NULL, QUOTES_MODULE_NAME, DB_STR_CC_QUOTE_TO_ID, to.GetID().c_str()); const auto pProvider = get_currency_converter_provider(); assert(pProvider); if (pProvider) { tstring sResult; std::string sError; try { double dResult = pProvider->Convert(dAmount, from, to); tostringstream ss; ss.imbue(GetSystemLocale()); ss << std::fixed << std::setprecision(2) << dAmount << " " << from.GetName() << " = " << dResult << " " << to.GetName(); sResult = ss.str(); } catch (std::exception& e) { sError = e.what(); } if (false == sError.empty()) sResult = quotes_a2t(sError.c_str());//A2T(sError.c_str()); SetDlgItemText(hDlg, IDC_EDIT_RESULT, sResult.c_str()); } } } } else { Quotes_MessageBox(hDlg, TranslateT("Enter positive number."), MB_OK | MB_ICONERROR); prepare_edit_ctrl_for_error(GetDlgItem(hDlg, IDC_EDIT_VALUE)); } } return TRUE; } break; case WM_NOTIFY: LPNMHDR pNMHDR = reinterpret_cast(lp); switch (pNMHDR->code) { case NM_CLICK: if (IDC_SYSLINK_PROVIDER == wp) { PNMLINK pNMLink = reinterpret_cast(pNMHDR); ::ShellExecute(hDlg, L"open", pNMLink->item.szUrl, nullptr, nullptr, SW_SHOWNORMAL); } break; } break; } return (FALSE); } INT_PTR QuotesMenu_CurrencyConverter(WPARAM, LPARAM) { MWindowList hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX, true); HWND hWnd = WindowList_Find(hWL, NULL); if (nullptr != hWnd) { SetForegroundWindow(hWnd); SetFocus(hWnd); } else CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_CURRENCY_CONVERTER), nullptr, CurrencyConverterDlgProc, 0); return 0; }