summaryrefslogtreecommitdiff
path: root/wx+/button.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:27:42 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:27:42 +0200
commitb916407a2a06f8452e82b74dc44c54acbcc572b0 (patch)
tree46358e0bb035fca0f42edb4b5b8aa5f1613814af /wx+/button.cpp
parent5.20 (diff)
downloadFreeFileSync-b916407a2a06f8452e82b74dc44c54acbcc572b0.tar.gz
FreeFileSync-b916407a2a06f8452e82b74dc44c54acbcc572b0.tar.bz2
FreeFileSync-b916407a2a06f8452e82b74dc44c54acbcc572b0.zip
5.21
Diffstat (limited to 'wx+/button.cpp')
-rw-r--r--wx+/button.cpp305
1 files changed, 0 insertions, 305 deletions
diff --git a/wx+/button.cpp b/wx+/button.cpp
deleted file mode 100644
index 806c0969..00000000
--- a/wx+/button.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "button.h"
-#include <algorithm>
-#include <limits>
-#include <cmath>
-#include <zen/string_tools.h>
-#include <wx/dcmemory.h>
-#include <wx/image.h>
-#include "image_tools.h"
-
-using namespace zen;
-
-
-void zen::setImage(wxBitmapButton& button, const wxBitmap& bmp)
-{
- if (!isEqual(button.GetBitmapLabel(), bmp))
- button.SetBitmapLabel(bmp);
-}
-
-
-BitmapButton::BitmapButton(wxWindow* parent,
- wxWindowID id,
- const wxString& label,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxValidator& validator,
- const wxString& name) :
- wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name),
- spaceAfter_(0),
- spaceBefore_(0),
- innerBorderSize(5)
-{
- SetLabel(label);
-}
-
-
-void BitmapButton::setBitmapFront(const wxBitmap& bitmap, int spaceAfter)
-{
- if (!isEqual(bitmap, bitmapFront) || spaceAfter_ != spaceAfter) //avoid flicker
- {
- bitmapFront = bitmap;
- spaceAfter_ = spaceAfter;
- refreshButtonLabel();
- }
-}
-
-
-void BitmapButton::SetLabel(const wxString& label)
-{
- if (wxBitmapButton::GetLabel() != label) //avoid flicker
- {
- wxBitmapButton::SetLabel(label);
- refreshButtonLabel();
- }
-}
-
-void BitmapButton::setBitmapBack(const wxBitmap& bitmap, int spaceBefore)
-{
- if (!isEqual(bitmap, bitmapBack) || spaceBefore_ != spaceBefore) //avoid flicker
- {
- bitmapBack = bitmap;
- spaceBefore_ = spaceBefore;
- refreshButtonLabel();
- }
-}
-
-
-namespace
-{
-void makeWhiteTransparent(wxImage& image) //assume black text on white background
-{
- if (unsigned char* alphaFirst = image.GetAlpha())
- {
- unsigned char* alphaLast = alphaFirst + image.GetWidth() * image.GetHeight();
-
- //dist(black, white)
- const double distBlackWhite = 255 * std::sqrt(3.0);
-
- const unsigned char* bytePos = image.GetData();
-
- for (unsigned char* j = alphaFirst; j != alphaLast; ++j)
- {
- unsigned char r = *bytePos++; //
- 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));
-
- //black(0,0,0) becomes fully opaque(255), while white(255,255,255) becomes transparent(0)
- *j = distColWhite / distBlackWhite * wxIMAGE_ALPHA_OPAQUE;
- }
- }
-}
-
-
-wxSize getSizeNeeded(const wxString& text, wxFont& font)
-{
- wxCoord width = 0;
- wxCoord height = 0;
-
- //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)
-{
- //wxDC::DrawLabel() doesn't respect alpha channel at all => apply workaround to calculate alpha values manually:
-
- if (text.empty())
- return wxBitmap();
-
- wxFont currentFont = wxBitmapButton::GetFont();
- wxColor textColor = wxBitmapButton::GetForegroundColour();
-
- wxSize sizeNeeded = getSizeNeeded(text, currentFont);
- wxBitmap newBitmap(sizeNeeded.GetWidth(), sizeNeeded.GetHeight());
-
- {
- wxMemoryDC dc(newBitmap);
-
- //set up white background
- dc.SetBackground(*wxWHITE_BRUSH);
- dc.Clear();
-
- //find position of accelerator
- 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(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();
-
- //set values for alpha channel
- makeWhiteTransparent(finalImage);
-
- //now apply real text color
- unsigned char* bytePos = finalImage.GetData();
- const int pixelCount = finalImage.GetWidth() * finalImage.GetHeight();
- for (int i = 0; i < pixelCount; ++ i)
- {
- *bytePos++ = textColor.Red();
- *bytePos++ = textColor.Green();
- *bytePos++ = textColor.Blue();
- }
-
- return wxBitmap(finalImage);
-}
-
-
-//copy one image into another, allowing arbitrary overlapping! (pos may contain negative numbers)
-void writeToImage(const wxImage& source, const wxPoint& pos, wxImage& target)
-{
- //determine startpositions in source and target image, as well as width and height to be copied
- wxPoint posSrc, posTrg;
- int width, height;
-
- //X-axis
- if (pos.x < 0)
- {
- posSrc.x = -pos.x;
- posTrg.x = 0;
- width = std::min(pos.x + source.GetWidth(), target.GetWidth());
- }
- else
- {
- posSrc.x = 0;
- posTrg.x = pos.x;
- width = std::min(target.GetWidth() - pos.x, source.GetWidth());
- }
-
- //Y-axis
- if (pos.y < 0)
- {
- posSrc.y = -pos.y;
- posTrg.y = 0;
- height = std::min(pos.y + source.GetHeight(), target.GetHeight());
- }
- else
- {
- posSrc.y = 0;
- posTrg.y = pos.y;
- height = std::min(target.GetHeight() - pos.y, source.GetHeight());
- }
-
-
- if (width > 0 && height > 0)
- {
- {
- //copy source to target respecting overlapping parts
- const unsigned char* sourcePtr = source.GetData() + 3 * (posSrc.x + posSrc.y * source.GetWidth());
- const unsigned char* const sourcePtrEnd = source.GetData() + 3 * (posSrc.x + (posSrc.y + height) * source.GetWidth());
- unsigned char* targetPtr = target.GetData() + 3 * (posTrg.x + posTrg.y * target.GetWidth());
-
- while (sourcePtr < sourcePtrEnd)
- {
- memcpy(targetPtr, sourcePtr, 3 * width);
- sourcePtr += 3 * source.GetWidth();
- targetPtr += 3 * target.GetWidth();
- }
- }
-
- //handle different cases concerning alpha channel
- if (source.HasAlpha())
- {
- if (!target.HasAlpha())
- {
- target.SetAlpha();
- memset(target.GetAlpha(), wxIMAGE_ALPHA_OPAQUE, target.GetWidth() * target.GetHeight());
- }
-
- //copy alpha channel
- const unsigned char* sourcePtr = source.GetAlpha() + (posSrc.x + posSrc.y * source.GetWidth());
- const unsigned char* const sourcePtrEnd = source.GetAlpha() + (posSrc.x + (posSrc.y + height) * source.GetWidth());
- unsigned char* targetPtr = target.GetAlpha() + (posTrg.x + posTrg.y * target.GetWidth());
-
- while (sourcePtr < sourcePtrEnd)
- {
- memcpy(targetPtr, sourcePtr, width);
- sourcePtr += source.GetWidth();
- targetPtr += target.GetWidth();
- }
- }
- else if (target.HasAlpha())
- {
- unsigned char* targetPtr = target.GetAlpha() + (posTrg.x + posTrg.y * target.GetWidth());
- const unsigned char* const targetPtrEnd = target.GetAlpha() + (posTrg.x + (posTrg.y + height) * target.GetWidth());
-
- while (targetPtr < targetPtrEnd)
- {
- memset(targetPtr, wxIMAGE_ALPHA_OPAQUE, width);
- targetPtr += target.GetWidth();
- }
- }
- }
-}
-
-
-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); //
-
- //calculate dimensions of new button
- const int height = std::max(std::max(szFront.GetHeight(), szText.GetHeight()), szBack.GetHeight());
- const int width = szFront.GetWidth() + spaceAfter_ + szText.GetWidth() + spaceBefore_ + szBack.GetWidth();
-
- //create a transparent image
- wxImage transparentImage(width, height, false);
- transparentImage.SetAlpha();
- unsigned char* alpha = transparentImage.GetAlpha();
- ::memset(alpha, wxIMAGE_ALPHA_TRANSPARENT, width * height);
-
- //wxDC::DrawLabel() unfortunately isn't working for transparent images on Linux, so we need to use custom image-concatenation
- if (bitmapFront.IsOk())
- writeToImage(bitmapFront.ConvertToImage(),
- wxPoint(0, (transparentImage.GetHeight() - bitmapFront.GetHeight()) / 2),
- transparentImage);
-
- if (bitmapText.IsOk())
- writeToImage(bitmapText.ConvertToImage(),
- wxPoint(szFront.GetWidth() + spaceAfter_, (transparentImage.GetHeight() - bitmapText.GetHeight()) / 2),
- transparentImage);
-
- if (bitmapBack.IsOk())
- writeToImage(bitmapBack.ConvertToImage(),
- wxPoint(szFront.GetWidth() + spaceAfter_ + szText.GetWidth() + spaceBefore_, (transparentImage.GetHeight() - bitmapBack.GetHeight()) / 2),
- transparentImage);
-
- //adjust button size
- 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())));
-
- //finally set bitmap
- wxBitmapButton::SetBitmapLabel(wxBitmap(transparentImage));
-}
bgstack15