diff options
Diffstat (limited to 'wx+')
-rw-r--r-- | wx+/button.cpp | 51 | ||||
-rw-r--r-- | wx+/graph.cpp | 5 | ||||
-rw-r--r-- | wx+/grid.cpp | 100 | ||||
-rw-r--r-- | wx+/grid.h | 4 | ||||
-rw-r--r-- | wx+/shell_execute.h | 42 | ||||
-rw-r--r-- | wx+/tooltip.cpp | 57 | ||||
-rw-r--r-- | wx+/tooltip.h | 15 |
7 files changed, 150 insertions, 124 deletions
diff --git a/wx+/button.cpp b/wx+/button.cpp index 75e4bfe1..806c0969 100644 --- a/wx+/button.cpp +++ b/wx+/button.cpp @@ -71,10 +71,11 @@ void BitmapButton::setBitmapBack(const wxBitmap& bitmap, int spaceBefore) } +namespace +{ void makeWhiteTransparent(wxImage& image) //assume black text on white background { - unsigned char* alphaFirst = image.GetAlpha(); - if (alphaFirst) + if (unsigned char* alphaFirst = image.GetAlpha()) { unsigned char* alphaLast = alphaFirst + image.GetWidth() * image.GetHeight(); @@ -86,11 +87,13 @@ void makeWhiteTransparent(wxImage& image) //assume black text on white backgroun for (unsigned char* j = alphaFirst; j != alphaLast; ++j) { unsigned char r = *bytePos++; // - unsigned char g = *bytePos++; //each pixel consists of three chars + unsigned char g = *bytePos++; //each pixel consists of three bytes unsigned char b = *bytePos++; // //dist((r,g,b), white) - double distColWhite = std::sqrt((255.0 - r) * (255.0 - r) + (255.0 - g) * (255.0 - g) + (255.0 - b) * (255.0 - b)); + double distColWhite = std::sqrt((255.0 - r) * (255.0 - r) + + (255.0 - g) * (255.0 - g) + + (255.0 - b) * (255.0 - b)); //black(0,0,0) becomes fully opaque(255), while white(255,255,255) becomes transparent(0) *j = distColWhite / distBlackWhite * wxIMAGE_ALPHA_OPAQUE; @@ -101,16 +104,16 @@ void makeWhiteTransparent(wxImage& image) //assume black text on white backgroun wxSize getSizeNeeded(const wxString& text, wxFont& font) { - const wxString& textFormatted = replaceCpy(text, L"&", L"", false); //remove accelerator - wxCoord width = 0; wxCoord height = 0; - wxMemoryDC dc; - dc.GetMultiLineTextExtent(textFormatted, &width, &height, nullptr, &font); + //the context used for bitmaps... + wxMemoryDC().GetMultiLineTextExtent(replaceCpy(text, L"&", L"", false), //remove accelerator + &width, &height, nullptr, &font); return wxSize(width, height); } +} wxBitmap BitmapButton::createBitmapFromText(const wxString& text) @@ -134,29 +137,22 @@ wxBitmap BitmapButton::createBitmapFromText(const wxString& text) dc.Clear(); //find position of accelerator - int indexAccel = -1; - wxString textLabelFormatted = text; - size_t accelPos = text.find(L"&"); - if (accelPos != wxString::npos) - { - replace(textLabelFormatted, L"&", L"", false); //remove accelerator - indexAccel = static_cast<int>(accelPos); - } + const size_t accelPos = text.find(L"&"); + const int indexAccel = accelPos != wxString::npos ? static_cast<int>(accelPos) : -1; dc.SetTextForeground(*wxBLACK); //for use in makeWhiteTransparent dc.SetTextBackground(*wxWHITE); // dc.SetFont(currentFont); - dc.DrawLabel(textLabelFormatted, wxNullBitmap, wxRect(0, 0, newBitmap.GetWidth(), newBitmap.GetHeight()), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, indexAccel); + dc.DrawLabel(replaceCpy(text, L"&", L"", false), //remove accelerator + wxNullBitmap, wxRect(0, 0, newBitmap.GetWidth(), newBitmap.GetHeight()), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, indexAccel); } //add alpha channel to image wxImage finalImage(newBitmap.ConvertToImage()); finalImage.SetAlpha(); - //linearInterpolation(finalImage); - - //calculate values for alpha channel + //set values for alpha channel makeWhiteTransparent(finalImage); //now apply real text color @@ -261,20 +257,12 @@ void writeToImage(const wxImage& source, const wxPoint& pos, wxImage& target) } -namespace -{ -inline -wxSize getSize(const wxBitmap& bmp) -{ - return bmp.IsOk() ? wxSize(bmp.GetWidth(), bmp.GetHeight()) : wxSize(0, 0); -} -} - - void BitmapButton::refreshButtonLabel() { wxBitmap bitmapText = createBitmapFromText(GetLabel()); + auto getSize = [](const wxBitmap& bmp) { return bmp.IsOk() ? wxSize(bmp.GetWidth(), bmp.GetHeight()) : wxSize(0, 0); }; + wxSize szFront = getSize(bitmapFront); // wxSize szText = getSize(bitmapText); //make sure to NOT access null-bitmaps! wxSize szBack = getSize(bitmapBack); // @@ -309,7 +297,8 @@ void BitmapButton::refreshButtonLabel() wxSize minSize = GetMinSize(); //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work corretly - wxBitmapButton::SetMinSize(wxSize(std::max(width + 2 * innerBorderSize, minSize.GetWidth()), std::max(height + 2 * innerBorderSize, minSize.GetHeight()))); + wxBitmapButton::SetMinSize(wxSize(std::max(width + 2 * innerBorderSize, minSize.GetWidth()), + std::max(height + 2 * innerBorderSize, minSize.GetHeight()))); //finally set bitmap wxBitmapButton::SetBitmapLabel(wxBitmap(transparentImage)); diff --git a/wx+/graph.cpp b/wx+/graph.cpp index 540f86a5..0d14ae69 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -131,7 +131,6 @@ void drawXLabel(wxDC& dc, double xMin, double xMax, int blockCount, const Conver wxDCPenChanger dummy(dc, wxPen(wxColor(192, 192, 192))); //light grey wxDCTextColourChanger dummy2(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels - dc.SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Arial")); const double valRangePerBlock = (xMax - xMin) / blockCount; @@ -160,7 +159,6 @@ void drawYLabel(wxDC& dc, double yMin, double yMax, int blockCount, const Conver wxDCPenChanger dummy(dc, wxPen(wxColor(192, 192, 192))); //light grey wxDCTextColourChanger dummy2(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels - dc.SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Arial")); const double valRangePerBlock = (yMax - yMin) / blockCount; @@ -304,6 +302,9 @@ void Graph2D::render(wxDC& dc) const { using namespace numeric; + //set label font right at the start so that it is considered by wxDC::GetTextExtent below! + dc.SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Arial")); + const wxRect clientRect = GetClientRect(); //DON'T use wxDC::GetSize()! DC may be larger than visible area! { //clear complete client area; set label background color diff --git a/wx+/grid.cpp b/wx+/grid.cpp index 4eb3b00e..750c4241 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -476,6 +476,10 @@ public: { wxClientDC dc(this); + wxFont labelFont = GetFont(); + labelFont.SetWeight(wxFONTWEIGHT_BOLD); + dc.SetFont(labelFont); //harmonize with RowLabelWin::render()! + int bestWidth = 0; for (ptrdiff_t i = rowFrom; i <= rowTo; ++i) bestWidth = std::max(bestWidth, dc.GetTextExtent(formatRow(i)).GetWidth() + 2 * ROW_LABEL_BORDER); @@ -527,7 +531,7 @@ private: wxFont labelFont = GetFont(); labelFont.SetWeight(wxFONTWEIGHT_BOLD); - dc.SetFont(labelFont); + dc.SetFont(labelFont); //harmonize with RowLabelWin::getBestWidth()! auto rowRange = getRowsOnClient(rect); //returns range [begin, end) for (auto row = rowRange.first; row < rowRange.second; ++row) @@ -637,7 +641,6 @@ private: } //---------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------- class Grid::ColLabelWin : public SubWindow { @@ -948,7 +951,7 @@ private: else clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - dc.SetFont(GetFont()); + dc.SetFont(GetFont()); //harmonize with Grid::getBestColumnSize() wxDCTextColourChanger dummy(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels @@ -1503,6 +1506,8 @@ void Grid::updateWindowSizes(bool updateScrollbar) //break this vicious circle: + //harmonize with Grid::GetSizeAvailableForScrollTarget()! + //1. calculate row label width independent from scrollbars const int mainWinHeightGross = std::max(GetSize().GetHeight() - colLabelHeight, 0); //independent from client sizes and scrollbars! const ptrdiff_t logicalHeight = rowLabelWin_->getLogicalHeight(); // @@ -1605,6 +1610,32 @@ void Grid::updateWindowSizes(bool updateScrollbar) } +wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size) +{ + //harmonize with Grid::updateWindowSizes()! + + //1. calculate row label width independent from scrollbars + const int mainWinHeightGross = std::max(size.GetHeight() - colLabelHeight, 0); //independent from client sizes and scrollbars! + const ptrdiff_t logicalHeight = rowLabelWin_->getLogicalHeight(); // + + int rowLabelWidth = 0; + if (drawRowLabel && logicalHeight > 0) + { + ptrdiff_t yFrom = CalcUnscrolledPosition(wxPoint(0, 0)).y; + ptrdiff_t yTo = CalcUnscrolledPosition(wxPoint(0, mainWinHeightGross - 1)).y ; + numeric::confine<ptrdiff_t>(yFrom, 0, logicalHeight - 1); + numeric::confine<ptrdiff_t>(yTo, 0, logicalHeight - 1); + + const ptrdiff_t rowFrom = rowLabelWin_->getRowAtPos(yFrom); + const ptrdiff_t rowTo = rowLabelWin_->getRowAtPos(yTo); + if (rowFrom >= 0 && rowTo >= 0) + rowLabelWidth = rowLabelWin_->getBestWidth(rowFrom, rowTo); + } + + return size - wxSize(rowLabelWidth, colLabelHeight); +} + + void Grid::onPaintEvent(wxPaintEvent& event) { wxPaintDC dc(this); } @@ -1750,25 +1781,9 @@ void Grid::showScrollBars(Grid::ScrollBarStatus horizontal, Grid::ScrollBarStatu showScrollbarX = horizontal; showScrollbarY = vertical; -#if wxCHECK_VERSION(2, 9, 0) - auto mapStatus = [](ScrollBarStatus sbStatus) -> wxScrollbarVisibility - { - switch (sbStatus) - { - case SB_SHOW_AUTOMATIC: - return wxSHOW_SB_DEFAULT; - case SB_SHOW_ALWAYS: - return wxSHOW_SB_ALWAYS; - case SB_SHOW_NEVER: - return wxSHOW_SB_NEVER; - } - assert(false); - return wxSHOW_SB_DEFAULT; - }; - ShowScrollbars(mapStatus(horizontal), mapStatus(vertical)); -#else //support older wxWidgets API - -#ifdef FFS_LINUX //get rid of scrollbars, but preserve scrolling behavior! +#if defined FFS_WIN || defined FFS_MAC + //handled by Grid::SetScrollbar +#elif defined FFS_LINUX //get rid of scrollbars, but preserve scrolling behavior! //the following wxGTK approach is pretty much identical to wxWidgets 2.9 ShowScrollbars() code! auto mapStatus = [](ScrollBarStatus sbStatus) -> GtkPolicyType @@ -1788,18 +1803,38 @@ void Grid::showScrollBars(Grid::ScrollBarStatus horizontal, Grid::ScrollBarStatu GtkWidget* gridWidget = wxWindow::m_widget; GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(gridWidget); - gtk_scrolled_window_set_policy(scrolledWindow, - mapStatus(horizontal), - mapStatus(vertical)); -#elif defined FFS_MAC -#error function not implemented! Upgrade to wxWidgets 2.9 or newer -#endif + ::gtk_scrolled_window_set_policy(scrolledWindow, + mapStatus(horizontal), + mapStatus(vertical)); #endif updateWindowSizes(); + + /* + wxWidgets >= 2.9 ShowScrollbars() is next to useless since it doesn't + honor wxSHOW_SB_ALWAYS on OS X, so let's ditch it and avoid more non-portability surprises + + #if wxCHECK_VERSION(2, 9, 0) + auto mapStatus = [](ScrollBarStatus sbStatus) -> wxScrollbarVisibility + { + switch (sbStatus) + { + case SB_SHOW_AUTOMATIC: + return wxSHOW_SB_DEFAULT; + case SB_SHOW_ALWAYS: + return wxSHOW_SB_ALWAYS; + case SB_SHOW_NEVER: + return wxSHOW_SB_NEVER; + } + assert(false); + return wxSHOW_SB_DEFAULT; + }; + ShowScrollbars(mapStatus(horizontal), mapStatus(vertical)); + #endif + */ } -#if defined FFS_WIN && !wxCHECK_VERSION(2, 9, 0) //support older wxWidgets API +#if defined FFS_WIN || defined FFS_MAC void Grid::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh) { ScrollBarStatus sbStatus = SB_SHOW_AUTOMATIC; @@ -1830,8 +1865,9 @@ void Grid::SetScrollbar(int orientation, int position, int thumbSize, int range, } #endif -#ifdef FFS_WIN //get rid of scrollbars, but preserve scrolling behavior! -#ifndef WM_MOUSEHWHEEL //MinGW is clueless... + //get rid of scrollbars, but preserve scrolling behavior! +#ifdef FFS_WIN +#ifdef __MINGW32__ //MinGW is clueless... #define WM_MOUSEHWHEEL 0x020E #endif @@ -2131,7 +2167,7 @@ ptrdiff_t Grid::getBestColumnSize(size_t col, size_t compPos) const const ColumnType type = visibleCols[col].type_; wxClientDC dc(mainWin_); - dc.SetFont(mainWin_->GetFont()); + dc.SetFont(mainWin_->GetFont()); //harmonize with MainWin::render() size_t maxSize = 0; @@ -202,7 +202,9 @@ private: void redirectRowLabelEvent(wxMouseEvent& event); -#if defined FFS_WIN && !wxCHECK_VERSION(2, 9, 0) + virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size); //required since wxWidgets 2.9 if SetTargetWindow() is used + +#if defined FFS_WIN || defined FFS_MAC virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh); //get rid of scrollbars, but preserve scrolling behavior! #endif diff --git a/wx+/shell_execute.h b/wx+/shell_execute.h index a07f40cb..acf84794 100644 --- a/wx+/shell_execute.h +++ b/wx+/shell_execute.h @@ -8,19 +8,21 @@ #define EXECUTE_HEADER_23482134578134134 #include <zen/zstring.h> +#include <zen/scope_guard.h> +#include <zen/i18n.h> +#include <zen/utf.h> #include <wx/msgdlg.h> #ifdef FFS_WIN #include <zen/last_error.h> -#include <zen/string_tools.h> -#include <zen/i18n.h> +//#include <zen/string_tools.h> #include <zen/win.h> //includes "windows.h" -//#include <zen/scope_guard.h> #elif defined FFS_LINUX || defined FFS_MAC -#include <stdlib.h> -#include <wx/utils.h> -#include <wx/log.h> +#include <zen/thread.h> +#include <stdlib.h> //::system() +//#include <wx/utils.h> +//#include <wx/log.h> #endif @@ -28,14 +30,14 @@ namespace zen { //launch commandline and report errors via popup dialog //windows: COM needs to be initialized before calling this function! -namespace -{ enum ExecutionType { EXEC_TYPE_SYNC, EXEC_TYPE_ASYNC }; +namespace +{ void shellExecute(const Zstring& command, ExecutionType type = EXEC_TYPE_ASYNC) { #ifdef FFS_WIN @@ -78,32 +80,30 @@ void shellExecute(const Zstring& command, ExecutionType type = EXEC_TYPE_ASYNC) if (execInfo.hProcess) { + ZEN_ON_SCOPE_EXIT(::CloseHandle(execInfo.hProcess)); + if (type == EXEC_TYPE_SYNC) ::WaitForSingleObject(execInfo.hProcess, INFINITE); - ::CloseHandle(execInfo.hProcess); } #elif defined FFS_LINUX || defined FFS_MAC + /* + we cannot use wxExecute due to various issues: + - screws up encoding on OS X for non-ASCII characters + - does not provide any reasonable error information + - uses a zero-sized dummy window as a hack to keep focus which leaves a useless empty icon in ALT-TAB list + */ + if (type == EXEC_TYPE_SYNC) { //Posix::system - execute a shell command int rv = ::system(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)" - { wxMessageBox(_("Invalid command line:") + L"\n" + utfCvrtTo<wxString>(command)); - return; - } } else - { - // ! 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()) - wxWindowDisabler dummy; //disables all top level windows - wxExecute(utfCvrtTo<wxString>(command), wxEXEC_ASYNC | wxEXEC_NODISABLE); - wxLog::FlushActive(); //show wxWidgets error messages (if any) - } + async([=] { /*int rv = */ ::system(command.c_str()); }); + //unfortunately we are not allowed to show a wxMessageBox from a worker thread #endif } } diff --git a/wx+/tooltip.cpp b/wx+/tooltip.cpp index 3431e339..5dc64c90 100644 --- a/wx+/tooltip.cpp +++ b/wx+/tooltip.cpp @@ -5,6 +5,7 @@ // ************************************************************************** #include "tooltip.h" +#include <wx/dialog.h> #include <wx/stattext.h> #include <wx/sizer.h> #include <wx/statbmp.h> @@ -15,23 +16,23 @@ using namespace zen; -class Tooltip::PopupFrameGenerated : public wxFrame +class Tooltip::PopupDialogGenerated : public wxDialog { public: - PopupFrameGenerated(wxWindow* parent, - wxWindowID id = wxID_ANY, - const wxString& title = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxSize( -1, -1 ), - long style = wxFRAME_NO_TASKBAR | wxSTAY_ON_TOP | wxSTATIC_BORDER) : wxFrame(parent, id, title, pos, size, style) + PopupDialogGenerated(wxWindow* parent, + wxWindowID id = wxID_ANY, + const wxString& title = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0) : wxDialog(parent, id, title, pos, size, style) { + //Suse Linux/X11: needs parent window, else there are z-order issues + this->SetSizeHints(wxDefaultSize, wxDefaultSize); this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK)); //both required: on Ubuntu background is black, foreground white! this->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT)); // - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer(wxHORIZONTAL); - + wxBoxSizer* bSizer158 = new wxBoxSizer(wxHORIZONTAL); m_bitmapLeft = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0); bSizer158->Add(m_bitmapLeft, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); @@ -41,6 +42,10 @@ public: this->SetSizer(bSizer158); this->Layout(); bSizer158->Fit(this); + +#if defined FFS_WIN //prevent window stealing focus! + Disable(); //= dark/grey text and image on Linux; no visible difference on OS X +#endif } wxStaticText* m_staticTextMain; @@ -48,23 +53,11 @@ public: }; -Tooltip::Tooltip() : tipWindow(new PopupFrameGenerated(nullptr)) -{ -#if defined FFS_WIN //prevent window stealing focus! - tipWindow->Disable(); //neither looks good nor works at all on Linux; no visible difference on OS X -#endif - hide(); -} - - -Tooltip::~Tooltip() -{ - tipWindow->Destroy(); -} - - void Tooltip::show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp) { + if (!tipWindow) + tipWindow = new PopupDialogGenerated(&parent_); //ownership passed to parent + const wxBitmap& newBmp = bmp ? *bmp : wxNullBitmap; if (!isEqual(tipWindow->m_bitmapLeft->GetBitmap(), newBmp)) @@ -97,12 +90,14 @@ void Tooltip::show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp) void Tooltip::hide() { + if (tipWindow) + { #ifdef FFS_LINUX - //on wxGTK the tip window occassionally goes blank and stays that way. This is somehow triggered by wxWindow::Hide() and doesn't seem to be a wxWidgets bug (=> GTK?) - //apply brute force: - tipWindow->Destroy(); - tipWindow = new PopupFrameGenerated(nullptr); + //on wxGTK the tooltip is sometimes not shown again after it was hidden: e.g. drag-selection on middle grid + tipWindow->Destroy(); //apply brute force: + tipWindow = nullptr; // +#else + tipWindow->Hide(); #endif - - tipWindow->Hide(); + } } diff --git a/wx+/tooltip.h b/wx+/tooltip.h index 9060c127..d17e650e 100644 --- a/wx+/tooltip.h +++ b/wx+/tooltip.h @@ -7,22 +7,25 @@ #ifndef CUSTOMTOOLTIP_H_INCLUDED #define CUSTOMTOOLTIP_H_INCLUDED -#include <wx/frame.h> +#include <wx/window.h> namespace zen { class Tooltip { public: - Tooltip(); - ~Tooltip(); + Tooltip(wxWindow& parent) : //parent needs to live at least as long as this instance! + tipWindow(nullptr), parent_(parent) {} - void show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp = nullptr); //absolute screen coordinates + void show(const wxString& text, + wxPoint mousePos, //absolute screen coordinates + const wxBitmap* bmp = nullptr); void hide(); private: - class PopupFrameGenerated; - PopupFrameGenerated* tipWindow; + class PopupDialogGenerated; + PopupDialogGenerated* tipWindow; + wxWindow& parent_; }; } |