diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:19:49 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:19:49 +0200 |
commit | c8e0e909b4a8d18319fc65434a10dc446434817c (patch) | |
tree | eee91e7d2ce229dd043811eae8f1e2bd78061916 /wx+ | |
parent | 5.2 (diff) | |
download | FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.tar.gz FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.tar.bz2 FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.zip |
5.3
Diffstat (limited to 'wx+')
-rw-r--r-- | wx+/context_menu.h | 40 | ||||
-rw-r--r-- | wx+/graph.cpp | 3 | ||||
-rw-r--r-- | wx+/grid.cpp | 21 | ||||
-rw-r--r-- | wx+/serialize.h | 109 | ||||
-rw-r--r-- | wx+/shell_execute.h | 36 | ||||
-rw-r--r-- | wx+/string_conv.h | 8 | ||||
-rw-r--r-- | wx+/toggle_button.h | 8 |
7 files changed, 155 insertions, 70 deletions
diff --git a/wx+/context_menu.h b/wx+/context_menu.h index 8f80fac2..663596f9 100644 --- a/wx+/context_menu.h +++ b/wx+/context_menu.h @@ -7,6 +7,7 @@ #ifndef CONTEXT_HEADER_18047302153418174632141234 #define CONTEXT_HEADER_18047302153418174632141234 +#include <map> #include <vector> #include <functional> #include <wx/menu.h> @@ -17,7 +18,7 @@ A context menu supporting C++11 lambda callbacks! Usage: ContextMenu menu; - menu.addItem(L"Some Label", [&]{ ...do something... }); -> capture by reference is fine, as long as captured variables have at least scope of ContextMenu::show()! + menu.addItem(L"Some Label", [&]{ ...do something... }); -> capture by reference is fine, as long as captured variables have at least scope of ContextMenu::popup()! ... menu.popup(wnd); */ @@ -27,36 +28,52 @@ namespace zen class ContextMenu : private wxEvtHandler { public: + ContextMenu() : menu(new wxMenu) {} + void addItem(const wxString& label, const std::function<void()>& command, const wxBitmap* bmp = nullptr, bool enabled = true) { - wxMenuItem* newItem = new wxMenuItem(&menu, wxID_ANY, label); + wxMenuItem* newItem = new wxMenuItem(menu.get(), wxID_ANY, label); //menu owns item! if (bmp) newItem->SetBitmap(*bmp); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason - menu.Append(newItem); + menu->Append(newItem); if (!enabled) newItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason - menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); + commandList[newItem->GetId()] = command; //defer event connection, this may be a submenu only! } void addCheckBox(const wxString& label, const std::function<void()>& command, bool checked, bool enabled = true) { - wxMenuItem* newItem = menu.AppendCheckItem(wxID_ANY, label); + wxMenuItem* newItem = menu->AppendCheckItem(wxID_ANY, label); newItem->Check(checked); if (!enabled) newItem->Enable(false); - menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); + commandList[newItem->GetId()] = command; } void addRadio(const wxString& label, const std::function<void()>& command, bool checked, bool enabled = true) { - wxMenuItem* newItem = menu.AppendRadioItem(wxID_ANY, label); + wxMenuItem* newItem = menu->AppendRadioItem(wxID_ANY, label); newItem->Check(checked); if (!enabled) newItem->Enable(false); - menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); + commandList[newItem->GetId()] = command; } - void addSeparator() { menu.AppendSeparator(); } + void addSeparator() { menu->AppendSeparator(); } + + void addSubmenu(const wxString& label, ContextMenu& submenu, const wxBitmap* bmp = nullptr) //invalidates submenu! + { + wxMenuItem* newItem = new wxMenuItem(menu.get(), wxID_ANY, label, L"", wxITEM_NORMAL, submenu.menu.release()); //menu owns item! + if (bmp) newItem->SetBitmap(*bmp); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason + menu->Append(newItem); + //transfer submenu commands: + commandList.insert(submenu.commandList.begin(), submenu.commandList.end()); + submenu.commandList.clear(); + } void popup(wxWindow& wnd) //show popup menu + process lambdas { - wnd.PopupMenu(&menu); + //eventually all events from submenu items will be received by this menu + for (auto iter = commandList.begin(); iter != commandList.end(); ++iter) + menu->Connect(iter->first, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(iter->second), /*pass ownership*/ this); + + wnd.PopupMenu(menu.get()); wxTheApp->ProcessPendingEvents(); //make sure lambdas are evaluated before going out of scope; //although all events seem to be processed within wxWindows::PopupMenu, we shouldn't trust wxWidgets in this regard } @@ -74,7 +91,8 @@ private: std::function<void()> fun_; }; - wxMenu menu; + std::unique_ptr<wxMenu> menu; + std::map<int, std::function<void()>> commandList; //(item id, command) }; } diff --git a/wx+/graph.cpp b/wx+/graph.cpp index 185121f1..9a64b3dd 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -411,7 +411,8 @@ void Graph2D::render(wxDC& dc) const if (iter->first.get()) { const GraphData& graph = *iter->first; - assert(graph.getXBegin() <= graph.getXEnd()); + assert(graph.getXBegin() <= graph.getXEnd() + 1.0e-9); + //GCC fucks up bad when comparing two *binary identical* doubles and finds "begin > end" with diff of 1e-18 if (attr.minXauto) minWndX = std::min(minWndX, graph.getXBegin()); diff --git a/wx+/grid.cpp b/wx+/grid.cpp index 10e427ef..89891879 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -6,7 +6,6 @@ #include "grid.h" #include <cassert> -#include <ctime> #include <set> #include <wx/dcbuffer.h> //for macro: wxALWAYS_NATIVE_DOUBLE_BUFFER #include <wx/settings.h> @@ -14,6 +13,7 @@ #include <wx/tooltip.h> #include <wx/timer.h> #include <wx/utils.h> +#include <zen/tick_count.h> #include <zen/string_tools.h> #include <zen/scope_guard.h> #include "format_unit.h" @@ -1257,7 +1257,9 @@ private: { public: MouseSelection(MainWin& wnd, ptrdiff_t rowStart, size_t compPos, bool positiveSelect) : - wnd_(wnd), rowStart_(rowStart), compPos_(compPos), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0), tickCountLast(clock()) + wnd_(wnd), rowStart_(rowStart), compPos_(compPos), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0), + tickCountLast(getTicks()), + ticksPerSec_(ticksPerSec()) { wnd_.CaptureMouse(); timer.Connect(wxEVT_TIMER, wxEventHandler(MouseSelection::onTimer), nullptr, this); @@ -1273,9 +1275,13 @@ private: void evalMousePos() { - const clock_t now = std::clock(); - const double deltaTime = static_cast<double>(now - tickCountLast) / CLOCKS_PER_SEC; //unit: [sec] - tickCountLast = now; + double deltaTime = 0; + if (ticksPerSec_ > 0) + { + const TickVal now = getTicks(); //0 on error + deltaTime = static_cast<double>(now - tickCountLast) / ticksPerSec_; //unit: [sec] + tickCountLast = now; + } wxMouseState mouseState = wxGetMouseState(); const wxPoint clientPos = wnd_.ScreenToClient(wxPoint(mouseState.GetX(), mouseState.GetY())); @@ -1345,7 +1351,8 @@ private: wxTimer timer; double toScrollX; //count outstanding scroll units to scroll while dragging mouse double toScrollY; // - clock_t tickCountLast; + TickVal tickCountLast; + const std::int64_t ticksPerSec_; }; virtual void ScrollWindow(int dx, int dy, const wxRect* rect) @@ -1853,6 +1860,8 @@ void Grid::selectRange(ptrdiff_t rowFrom, ptrdiff_t rowTo, size_t compPos, bool GridRangeSelectEvent selectionEvent(rowFrom, rowTo, compPos, positive); if (wxEvtHandler* evtHandler = GetEventHandler()) evtHandler->ProcessEvent(selectionEvent); + + mainWin_->Refresh(); } } diff --git a/wx+/serialize.h b/wx+/serialize.h index b6a478cd..f49bff04 100644 --- a/wx+/serialize.h +++ b/wx+/serialize.h @@ -15,10 +15,12 @@ namespace zen { //unchecked, unformatted serialization -template <class T> T readPOD (wxInputStream& stream); +template <class T> T readPOD (wxInputStream& stream); +template <class T> void readPOD (wxInputStream& stream, T& pod); template <class T> void writePOD(wxOutputStream& stream, const T& pod); template <class S> S readString (wxInputStream& stream); +template <class S> void readString (wxInputStream& stream, S& str); template <class S> void writeString(wxOutputStream& stream, const S& str); @@ -53,6 +55,9 @@ private: class CheckedIo { +public: + virtual void throwException() const = 0; + protected: CheckedIo(wxStreamBase& stream) : stream_(stream) {} @@ -61,7 +66,6 @@ protected: if (stream_.GetLastError() != wxSTREAM_NO_ERROR) throwException(); } - virtual void throwException() const = 0; private: wxStreamBase& stream_; @@ -69,7 +73,7 @@ private: //wxInputStream proxy throwing exception on error -class CheckedReader : private CheckedIo +class CheckedReader : public CheckedIo { public: CheckedReader(wxInputStream& stream) : CheckedIo(stream), stream_(stream) {} @@ -77,26 +81,36 @@ public: template <class T> T readPOD() const; //throw! + template <class T> + void readPOD(T& pod) const; //throw! + template <class S> S readString() const; //throw! + template <class S> + void readString(S& str) const; //throw! + + void readArray(void* data, size_t len) const; //throw! + private: wxInputStream& stream_; }; //wxOutputStream proxy throwing FileError on error -class CheckedWriter : private CheckedIo +class CheckedWriter : public CheckedIo { public: CheckedWriter(wxOutputStream& stream) : CheckedIo(stream), stream_(stream) {} template <class T> - void writePOD(T number) const; //throw! + void writePOD(const T& pod) const; //throw! template <class S> void writeString(const S& str) const; //throw! + void writeArray(const void* data, size_t len) const; //throw! + private: wxOutputStream& stream_; }; @@ -129,12 +143,19 @@ template <class T> inline T readPOD(wxInputStream& stream) { T pod = 0; - stream.Read(reinterpret_cast<char*>(&pod), sizeof(T)); + readPOD(stream, pod); return pod; } template <class T> inline +void readPOD(wxInputStream& stream, T& pod) +{ + stream.Read(reinterpret_cast<char*>(&pod), sizeof(T)); +} + + +template <class T> inline void writePOD(wxOutputStream& stream, const T& pod) { stream.Write(reinterpret_cast<const char*>(&pod), sizeof(T)); @@ -144,64 +165,96 @@ void writePOD(wxOutputStream& stream, const T& pod) template <class S> inline S readString(wxInputStream& stream) { - //don't even consider UTF8 conversions here! "string" is expected to handle arbitrary binary data! + S str; + readString(stream, str); + return str; +} - typedef typename S::value_type CharType; + +template <class S> inline +void readString(wxInputStream& stream, S& str) +{ + //don't even consider UTF8 conversions here! "string" is expected to handle arbitrary binary data! const auto strLength = readPOD<std::uint32_t>(stream); - S output; + str.resize(strLength); //throw std::bad_alloc if (strLength > 0) - { - output.resize(strLength); //throw std::bad_alloc - stream.Read(&*output.begin(), sizeof(CharType) * strLength); - } - return output; + stream.Read(&*str.begin(), sizeof(typename S::value_type) * strLength); } template <class S> inline void writeString(wxOutputStream& stream, const S& str) { - writePOD(stream, static_cast<std::uint32_t>(str.length())); - stream.Write(str.c_str(), sizeof(typename S::value_type) * str.length()); + const auto strLength = str.length(); + writePOD(stream, static_cast<std::uint32_t>(strLength)); + if (strLength > 0) + stream.Write(&*str.begin(), sizeof(typename S::value_type) * strLength); //don't use c_str(), but access uniformly via STL interface } -template <class T> inline -T CheckedReader::readPOD() const //checked read operation +void CheckedReader::readArray(void* data, size_t len) const //throw! { - T output = zen::readPOD<T>(stream_); + stream_.Read(data, len); check(); - return output; +} + + +template <class T> inline +T CheckedReader::readPOD() const //checked read operation +{ + T pod = 0; + readPOD(pod); + return pod; +} + + +template <class T> inline +void CheckedReader::readPOD(T& pod) const //checked read operation +{ + readArray(&pod, sizeof(T)); } template <class S> inline S CheckedReader::readString() const //checked read operation { - S output; + S str; + readString(str); + return str; +} + + +template <class S> inline +void CheckedReader::readString(S& str) const //checked read operation +{ try { - output = zen::readString<S>(stream_); //throw std::bad_alloc + zen::readString<S>(stream_, str); //throw std::bad_alloc } catch (std::exception&) { throwException(); } - check(); - if (stream_.LastRead() != output.length() * sizeof(typename S::value_type)) //some additional check + if (stream_.LastRead() != str.length() * sizeof(typename S::value_type)) //some additional check throwException(); - return output; } -template <class T> inline -void CheckedWriter::writePOD(T number) const //checked write operation +inline +void CheckedWriter::writeArray(const void* data, size_t len) const //throw! { - zen::writePOD<T>(stream_, number); + stream_.Write(data, len); check(); } +template <class T> inline +void CheckedWriter::writePOD(const T& pod) const //checked write opera +{ + writeArray(&pod, sizeof(T)); +} + + template <class S> inline void CheckedWriter::writeString(const S& str) const //checked write operation { diff --git a/wx+/shell_execute.h b/wx+/shell_execute.h index 3468a1c8..9de30980 100644 --- a/wx+/shell_execute.h +++ b/wx+/shell_execute.h @@ -14,10 +14,12 @@ #include <zen/string_tools.h> #include <zen/i18n.h> #include <zen/win.h> //includes "windows.h" +//#include <zen/scope_guard.h> #elif defined FFS_LINUX #include <stdlib.h> #include <wx/utils.h> +#include <wx/log.h> #endif @@ -38,11 +40,10 @@ void shellExecute(const wxString& command, ExecutionType type = EXEC_TYPE_ASYNC) #ifdef FFS_WIN //parse commandline std::vector<std::wstring> argv; + int argc = 0; + if (LPWSTR* tmp = ::CommandLineToArgvW(command.c_str(), &argc)) { - int argc = 0; - LPWSTR* tmp = ::CommandLineToArgvW(command.c_str(), &argc); - for (int i = 0; i < argc; ++i) - argv.push_back(tmp[i]); + std::copy(tmp, tmp + argc, std::back_inserter(argv)); ::LocalFree(tmp); } @@ -57,44 +58,38 @@ void shellExecute(const wxString& command, ExecutionType type = EXEC_TYPE_ASYNC) } SHELLEXECUTEINFO execInfo = {}; - execInfo.cbSize = sizeof(execInfo); + execInfo.cbSize = sizeof(execInfo); //SEE_MASK_NOASYNC is equal to SEE_MASK_FLAG_DDEWAIT, but former is defined not before Win SDK 6.0 execInfo.fMask = type == EXEC_TYPE_SYNC ? (SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT) : 0; //don't use SEE_MASK_ASYNCOK -> returns successful despite errors! execInfo.fMask |= SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI; //::ShellExecuteEx() shows a non-blocking pop-up dialog on errors -> we want a blocking one - execInfo.lpVerb = L"open"; + execInfo.lpVerb = nullptr; execInfo.lpFile = filename.c_str(); execInfo.lpParameters = arguments.c_str(); execInfo.nShow = SW_SHOWNORMAL; if (!::ShellExecuteEx(&execInfo)) //__inout LPSHELLEXECUTEINFO lpExecInfo { - wxString errorMsg = _("Invalid command line: %x"); - wxString cmdFmt = wxString(L"\nFile: ") + filename + L"\nArg: " + arguments; - - errorMsg.Replace(L"%x", cmdFmt); - wxMessageBox(errorMsg + L"\n\n" + getLastErrorFormatted()); + wxString cmdFmt = L"File: " + filename + L"\nArg: " + arguments; + wxMessageBox(replaceCpy(_("Invalid command line: %x"), L"%x", L"\n" + cmdFmt) + L"\n\n" + getLastErrorFormatted()); return; } - if (type == EXEC_TYPE_SYNC) + if (execInfo.hProcess) { - if (execInfo.hProcess != 0) - { + if (type == EXEC_TYPE_SYNC) ::WaitForSingleObject(execInfo.hProcess, INFINITE); - ::CloseHandle(execInfo.hProcess); - } + ::CloseHandle(execInfo.hProcess); } #elif defined FFS_LINUX if (type == EXEC_TYPE_SYNC) { + //Posix::system - execute a shell command int rv = ::system(utf8CvrtTo<std::string>(command).c_str()); //do NOT use std::system as its documentation says nothing about "WEXITSTATUS(rv)", ect... if (rv == -1 || WEXITSTATUS(rv) == 127) //http://linux.die.net/man/3/system "In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127)" { - wxString errorMsg = _("Invalid command line: %x"); - replace(errorMsg, L"%x", L"\n" + command); - wxMessageBox(errorMsg); + wxMessageBox(replaceCpy(_("Invalid command line: %x"), L"%x", L"\n" + command)); return; } } @@ -103,9 +98,10 @@ void shellExecute(const wxString& command, ExecutionType type = EXEC_TYPE_ASYNC) // ! unfortunately it seems there is no way on Linux to get a failure notification for calling an invalid command line asynchronously ! //by default wxExecute uses a zero sized dummy window as a hack to keep focus which leaves a useless empty icon in ALT-TAB list - //=> use wxEXEC_NODISABLE and roll our own window disabler! (see comment in app.cpp: void *wxGUIAppTraits::BeforeChildWaitLoop()) + //=> use wxEXEC_NODISABLE and roll our own window disabler! (see comment in app.cpp: void *wxGUIAppTraits::BeforeChildWaitLoop()) wxWindowDisabler dummy; //disables all top level windows wxExecute(command, wxEXEC_ASYNC | wxEXEC_NODISABLE); + wxLog::FlushActive(); //show wxWidgets error messages (if any) } #endif } diff --git a/wx+/string_conv.h b/wx+/string_conv.h index 65764b1f..b23f6947 100644 --- a/wx+/string_conv.h +++ b/wx+/string_conv.h @@ -16,6 +16,14 @@ namespace zen //conversion between Zstring and wxString inline wxString toWx(const Zstring& str) { return utf8CvrtTo<wxString>(str); } inline Zstring toZ(const wxString& str) { return utf8CvrtTo<Zstring>(str); } + +inline std::vector<Zstring> toZ(const std::vector<wxString>& strList) +{ + std::vector<Zstring> tmp; + std::transform(strList.begin(), strList.end(), std::back_inserter(tmp), [](const wxString& str) { return toZ(str); }); + return tmp; +} + } #endif // STRINGCONV_H_INCLUDED diff --git a/wx+/toggle_button.h b/wx+/toggle_button.h index cce7f5b2..74f90974 100644 --- a/wx+/toggle_button.h +++ b/wx+/toggle_button.h @@ -27,9 +27,9 @@ public: } void init(const wxBitmap& activeBmp, - const wxString& activeTooltip, const wxBitmap& inactiveBmp, - const wxString& inactiveTooltip); + const wxString& activeTooltip, + const wxString& inactiveTooltip = wxString()); void setActive(bool value); bool isActive() const { return active; } @@ -60,14 +60,14 @@ private: //######################## implementation ######################## inline void ToggleButton::init(const wxBitmap& activeBmp, - const wxString& activeTooltip, const wxBitmap& inactiveBmp, + const wxString& activeTooltip, const wxString& inactiveTooltip) { m_activeBmp = activeBmp; m_activeTooltip = activeTooltip; m_inactiveBmp = inactiveBmp; - m_inactiveTooltip = inactiveTooltip; + m_inactiveTooltip = inactiveTooltip.empty() ? activeTooltip : inactiveTooltip; //load resources setActive(active); |