mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-08 04:20:09 +00:00
New class: DropShadow, and a complete refactoring of the way shadows are rendered. The DropShadowEffect and DropShadower classes now take a DropShadow object to describe their shadow parameters, instead of the raw numbers.
This commit is contained in:
parent
591ce2a396
commit
3ddc6dd43d
16 changed files with 286 additions and 248 deletions
|
|
@ -35,7 +35,7 @@ public:
|
|||
{
|
||||
Random random;
|
||||
|
||||
const int size = 10 + random.nextInt (30);
|
||||
const float size = 10.0f + random.nextInt (30);
|
||||
|
||||
ballBounds.setBounds (random.nextFloat() * 100.0f,
|
||||
random.nextFloat() * 100.0f,
|
||||
|
|
@ -186,9 +186,9 @@ public:
|
|||
void timerCallback()
|
||||
{
|
||||
Random random;
|
||||
blobPosition.setBounds (random.nextInt (getWidth()),
|
||||
random.nextInt (getHeight()),
|
||||
40, 30);
|
||||
blobPosition.setBounds ((float) random.nextInt (getWidth()),
|
||||
(float) random.nextInt (getHeight()),
|
||||
40.0f, 30.0f);
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ public:
|
|||
numIns (0),
|
||||
numOuts (0)
|
||||
{
|
||||
shadow.setShadowProperties (2.5f, 0.5f, -1, 0);
|
||||
shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 3, Point<int> (0, 1));
|
||||
setComponentEffect (&shadow);
|
||||
|
||||
setSize (150, 60);
|
||||
|
|
|
|||
|
|
@ -27,86 +27,145 @@
|
|||
#pragma optimize ("t", on)
|
||||
#endif
|
||||
|
||||
static void blurSingleChannelImage (uint8* const data, const int width, const int height,
|
||||
const int lineStride, const int repetitions) noexcept
|
||||
{
|
||||
uint8* line = data;
|
||||
|
||||
for (int y = height; --y >= 0;)
|
||||
{
|
||||
for (int i = repetitions; --i >= 0;)
|
||||
{
|
||||
uint8* p = line;
|
||||
*p++ = (((int) p[0]) + p[1]) / 2;
|
||||
|
||||
for (int x = width - 2; --x >= 0;)
|
||||
*p++ = (((int) p[-1]) + p[0] + p[1] + 1) / 3;
|
||||
|
||||
*p = (((int) p[0]) + p[-1]) / 2;
|
||||
}
|
||||
|
||||
line += lineStride;
|
||||
}
|
||||
|
||||
for (int i = repetitions; --i >= 0;)
|
||||
{
|
||||
line = data;
|
||||
|
||||
{
|
||||
uint8* p1 = line;
|
||||
uint8* p2 = line + lineStride;
|
||||
|
||||
for (int x = width; --x >= 0;)
|
||||
*p1++ = (((int) *p1) + *p2++) / 2;
|
||||
}
|
||||
|
||||
line += lineStride;
|
||||
|
||||
for (int y = height - 2; --y >= 0;)
|
||||
{
|
||||
uint8* p1 = line;
|
||||
uint8* p2 = line - lineStride;
|
||||
uint8* p3 = line + lineStride;
|
||||
|
||||
for (int x = width; --x >= 0;)
|
||||
*p1++ = (((int) *p1) + *p2++ + *p3++ + 1) / 3;
|
||||
|
||||
line += lineStride;
|
||||
}
|
||||
|
||||
uint8* p1 = line;
|
||||
uint8* p2 = line - lineStride;
|
||||
|
||||
for (int x = width; --x >= 0;)
|
||||
*p1++ = (((int) *p1) + *p2++) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void blurSingleChannelImage (Image& image, int radius)
|
||||
{
|
||||
const Image::BitmapData bm (image, Image::BitmapData::readWrite);
|
||||
blurSingleChannelImage (bm.data, bm.width, bm.height, bm.lineStride, 2 * radius);
|
||||
}
|
||||
|
||||
#if JUCE_MSVC && JUCE_DEBUG
|
||||
#pragma optimize ("", on) // resets optimisations to the project defaults
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
DropShadowEffect::DropShadowEffect()
|
||||
: offsetX (0),
|
||||
offsetY (0),
|
||||
radius (4),
|
||||
opacity (0.6f)
|
||||
DropShadow::DropShadow() noexcept
|
||||
: colour (0x90000000), radius (4)
|
||||
{
|
||||
}
|
||||
|
||||
DropShadowEffect::~DropShadowEffect()
|
||||
DropShadow::DropShadow (const Colour& shadowColour, const int r, const Point<int>& o) noexcept
|
||||
: colour (shadowColour), radius (r), offset (o)
|
||||
{
|
||||
jassert (radius > 0);
|
||||
}
|
||||
|
||||
void DropShadowEffect::setShadowProperties (const float newRadius,
|
||||
const float newOpacity,
|
||||
const int newShadowOffsetX,
|
||||
const int newShadowOffsetY)
|
||||
void DropShadow::drawForImage (Graphics& g, const Image& srcImage) const
|
||||
{
|
||||
radius = jmax (1.1f, newRadius);
|
||||
offsetX = newShadowOffsetX;
|
||||
offsetY = newShadowOffsetY;
|
||||
opacity = newOpacity;
|
||||
}
|
||||
jassert (radius > 0);
|
||||
|
||||
void DropShadowEffect::drawShadow (Graphics& g, const Image& srcImage,
|
||||
float radius, float alpha, int offsetX, int offsetY)
|
||||
{
|
||||
const int w = srcImage.getWidth();
|
||||
const int h = srcImage.getHeight();
|
||||
|
||||
Image shadowImage (Image::SingleChannel, w, h, false);
|
||||
|
||||
const Image::BitmapData srcData (srcImage, Image::BitmapData::readOnly);
|
||||
const Image::BitmapData destData (shadowImage, Image::BitmapData::readWrite);
|
||||
|
||||
const int filter = roundToInt (63.0f / radius);
|
||||
const int radiusMinus1 = roundToInt ((radius - 1.0f) * 63.0f);
|
||||
|
||||
for (int x = w; --x >= 0;)
|
||||
if (srcImage.isValid())
|
||||
{
|
||||
int shadowAlpha = 0;
|
||||
Image shadowImage (srcImage.convertedToFormat (Image::SingleChannel));
|
||||
shadowImage.duplicateIfShared();
|
||||
|
||||
const PixelARGB* src = ((const PixelARGB*) srcData.data) + x;
|
||||
uint8* shadowPix = destData.data + x;
|
||||
blurSingleChannelImage (shadowImage, radius);
|
||||
|
||||
for (int y = h; --y >= 0;)
|
||||
{
|
||||
shadowAlpha = ((shadowAlpha * radiusMinus1 + (src->getAlpha() << 6)) * filter) >> 12;
|
||||
|
||||
*shadowPix = (uint8) shadowAlpha;
|
||||
src = addBytesToPointer (src, srcData.lineStride);
|
||||
shadowPix += destData.lineStride;
|
||||
}
|
||||
g.setColour (colour);
|
||||
g.drawImageAt (shadowImage, offset.x, offset.y, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = h; --y >= 0;)
|
||||
void DropShadow::drawForPath (Graphics& g, const Path& path) const
|
||||
{
|
||||
jassert (radius > 0);
|
||||
|
||||
const Rectangle<int> area (path.getBounds().translated ((float) offset.x, (float) offset.y)
|
||||
.getSmallestIntegerContainer()
|
||||
.getIntersection (g.getClipBounds())
|
||||
.expanded (radius + 1, radius + 1));
|
||||
|
||||
if (area.getWidth() > 2 && area.getHeight() > 2)
|
||||
{
|
||||
int shadowAlpha = 0;
|
||||
uint8* shadowPix = destData.getLinePointer (y);
|
||||
Image renderedPath (Image::SingleChannel, area.getWidth(), area.getHeight(), true);
|
||||
|
||||
for (int x = w; --x >= 0;)
|
||||
{
|
||||
shadowAlpha = ((shadowAlpha * radiusMinus1 + (*shadowPix << 6)) * filter) >> 12;
|
||||
*shadowPix++ = (uint8) shadowAlpha;
|
||||
Graphics g2 (renderedPath);
|
||||
g2.setColour (Colours::white);
|
||||
g2.fillPath (path, AffineTransform::translation ((float) (offset.x - area.getX()),
|
||||
(float) (offset.y - area.getY())));
|
||||
}
|
||||
}
|
||||
|
||||
g.setColour (Colours::black.withAlpha (alpha));
|
||||
g.drawImageAt (shadowImage, offsetX, offsetY, true);
|
||||
blurSingleChannelImage (renderedPath, radius);
|
||||
|
||||
g.setColour (colour);
|
||||
g.drawImageAt (renderedPath, area.getX(), area.getY(), true);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
DropShadowEffect::DropShadowEffect() {}
|
||||
DropShadowEffect::~DropShadowEffect() {}
|
||||
|
||||
void DropShadowEffect::setShadowProperties (const DropShadow& newShadow)
|
||||
{
|
||||
shadow = newShadow;
|
||||
}
|
||||
|
||||
void DropShadowEffect::applyEffect (Image& image, Graphics& g, float scaleFactor, float alpha)
|
||||
{
|
||||
drawShadow (g, image, radius * scaleFactor, opacity * alpha,
|
||||
(int) (offsetX * scaleFactor), (int) (offsetY * scaleFactor));
|
||||
DropShadow s (shadow);
|
||||
s.radius = roundToInt (s.radius * scaleFactor);
|
||||
s.colour = s.colour.withMultipliedAlpha (alpha);
|
||||
s.offset.x = roundToInt (s.offset.x * scaleFactor);
|
||||
s.offset.y = roundToInt (s.offset.y * scaleFactor);
|
||||
|
||||
s.drawForImage (g, image);
|
||||
|
||||
g.setOpacity (alpha);
|
||||
g.drawImageAt (image, 0, 0);
|
||||
}
|
||||
|
||||
#if JUCE_MSVC && JUCE_DEBUG
|
||||
#pragma optimize ("", on) // resets optimisations to the project defaults
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,37 @@
|
|||
#include "juce_ImageEffectFilter.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Defines a drop-shadow effect.
|
||||
*/
|
||||
struct JUCE_API DropShadow
|
||||
{
|
||||
/** Creates a default drop-shadow effect. */
|
||||
DropShadow() noexcept;
|
||||
|
||||
/** Creates a drop-shadow object with the given parameters. */
|
||||
DropShadow (const Colour& shadowColour, int radius, const Point<int>& offset) noexcept;
|
||||
|
||||
/** Renders a drop-shadow based on the alpha-channel of the given image. */
|
||||
void drawForImage (Graphics& g, const Image& srcImage) const;
|
||||
|
||||
/** Renders a drop-shadow based on the shape of a path. */
|
||||
void drawForPath (Graphics& g, const Path& path) const;
|
||||
|
||||
/** The colour with which to render the shadow.
|
||||
In most cases you'll probably want to leave this as black with an alpha
|
||||
value of around 0.5
|
||||
*/
|
||||
Colour colour;
|
||||
|
||||
/** The approximate spread of the shadow. */
|
||||
int radius;
|
||||
|
||||
/** The offset of the shadow. */
|
||||
Point<int> offset;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An effect filter that adds a drop-shadow behind the image's content.
|
||||
|
|
@ -50,9 +81,7 @@ class JUCE_API DropShadowEffect : public ImageEffectFilter
|
|||
public:
|
||||
//==============================================================================
|
||||
/** Creates a default drop-shadow effect.
|
||||
|
||||
To customise the shadow's appearance, use the setShadowProperties()
|
||||
method.
|
||||
To customise the shadow's appearance, use the setShadowProperties() method.
|
||||
*/
|
||||
DropShadowEffect();
|
||||
|
||||
|
|
@ -60,23 +89,8 @@ public:
|
|||
~DropShadowEffect();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets up parameters affecting the shadow's appearance.
|
||||
|
||||
@param newRadius the (approximate) radius of the blur used
|
||||
@param newOpacity the opacity with which the shadow is rendered
|
||||
@param newShadowOffsetX allows the shadow to be shifted in relation to the
|
||||
component's contents
|
||||
@param newShadowOffsetY allows the shadow to be shifted in relation to the
|
||||
component's contents
|
||||
*/
|
||||
void setShadowProperties (float newRadius,
|
||||
float newOpacity,
|
||||
int newShadowOffsetX,
|
||||
int newShadowOffsetY);
|
||||
|
||||
|
||||
static void drawShadow (Graphics& g, const Image& srcImage,
|
||||
float radius, float alpha, int offsetX, int offsetY);
|
||||
/** Sets up parameters affecting the shadow's appearance. */
|
||||
void setShadowProperties (const DropShadow& newShadow);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
|
|
@ -85,8 +99,7 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
int offsetX, offsetY;
|
||||
float radius, opacity;
|
||||
DropShadow shadow;
|
||||
|
||||
JUCE_LEAK_DETECTOR (DropShadowEffect);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -241,4 +241,51 @@ void ImageConvolutionKernel::applyToImage (Image& destImage,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (destData.pixelStride == 1)
|
||||
{
|
||||
for (int y = area.getY(); y < bottom; ++y)
|
||||
{
|
||||
uint8* dest = line;
|
||||
line += destData.lineStride;
|
||||
|
||||
for (int x = area.getX(); x < right; ++x)
|
||||
{
|
||||
float c1 = 0;
|
||||
|
||||
for (int yy = 0; yy < size; ++yy)
|
||||
{
|
||||
const int sy = y + yy - (size >> 1);
|
||||
|
||||
if (sy >= srcData.height)
|
||||
break;
|
||||
|
||||
if (sy >= 0)
|
||||
{
|
||||
int sx = x - (size >> 1);
|
||||
const uint8* src = srcData.getPixelPointer (sx, sy);
|
||||
|
||||
for (int xx = 0; xx < size; ++xx)
|
||||
{
|
||||
if (sx >= srcData.width)
|
||||
break;
|
||||
|
||||
if (sx >= 0)
|
||||
{
|
||||
const float kernelMult = values [xx + yy * size];
|
||||
c1 += kernelMult * *src++;
|
||||
}
|
||||
else
|
||||
{
|
||||
src += 3;
|
||||
}
|
||||
|
||||
++sx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*dest++ = (uint8) roundToInt (c1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,49 +23,24 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
ArrowButton::ArrowButton (const String& name,
|
||||
float arrowDirectionInRadians,
|
||||
const Colour& arrowColour)
|
||||
: Button (name),
|
||||
colour (arrowColour)
|
||||
ArrowButton::ArrowButton (const String& name, float arrowDirectionInRadians, const Colour& arrowColour)
|
||||
: Button (name), colour (arrowColour)
|
||||
{
|
||||
path.lineTo (0.0f, 1.0f);
|
||||
path.lineTo (1.0f, 0.5f);
|
||||
path.closeSubPath();
|
||||
|
||||
path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * arrowDirectionInRadians,
|
||||
0.5f, 0.5f));
|
||||
|
||||
setComponentEffect (&shadow);
|
||||
updateShadowAndOffset();
|
||||
path.addTriangle (0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
|
||||
path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * arrowDirectionInRadians, 0.5f, 0.5f));
|
||||
}
|
||||
|
||||
ArrowButton::~ArrowButton()
|
||||
{
|
||||
}
|
||||
ArrowButton::~ArrowButton() {}
|
||||
|
||||
void ArrowButton::paintButton (Graphics& g,
|
||||
bool /*isMouseOverButton*/,
|
||||
bool /*isButtonDown*/)
|
||||
void ArrowButton::paintButton (Graphics& g, bool /*isMouseOverButton*/, bool isButtonDown)
|
||||
{
|
||||
Path p (path);
|
||||
|
||||
const float offset = isButtonDown ? 1.0f : 0.0f;
|
||||
p.applyTransform (path.getTransformToScaleToFit (offset, offset, getWidth() - 3.0f, getHeight() - 3.0f, false));
|
||||
|
||||
DropShadow (Colours::black.withAlpha (0.3f), isButtonDown ? 2 : 4, Point<int>()).drawForPath (g, p);
|
||||
|
||||
g.setColour (colour);
|
||||
|
||||
g.fillPath (path, path.getTransformToScaleToFit ((float) offset,
|
||||
(float) offset,
|
||||
(float) (getWidth() - 3),
|
||||
(float) (getHeight() - 3),
|
||||
false));
|
||||
}
|
||||
|
||||
void ArrowButton::buttonStateChanged()
|
||||
{
|
||||
updateShadowAndOffset();
|
||||
}
|
||||
|
||||
void ArrowButton::updateShadowAndOffset()
|
||||
{
|
||||
offset = (isDown()) ? 1 : 0;
|
||||
|
||||
shadow.setShadowProperties ((isDown()) ? 1.2f : 3.0f,
|
||||
0.3f, -1, 0);
|
||||
g.fillPath (p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,23 +55,12 @@ public:
|
|||
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paintButton (Graphics& g,
|
||||
bool isMouseOverButton,
|
||||
bool isButtonDown);
|
||||
|
||||
/** @internal */
|
||||
void buttonStateChanged();
|
||||
void paintButton (Graphics&, bool isMouseOverButton, bool isButtonDown);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Colour colour;
|
||||
DropShadowEffect shadow;
|
||||
Path path;
|
||||
int offset;
|
||||
|
||||
void updateShadowAndOffset();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ArrowButton);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ void ShapeButton::setShape (const Path& newShape,
|
|||
shape = newShape;
|
||||
maintainShapeProportions = maintainShapeProportions_;
|
||||
|
||||
shadow.setShadowProperties (3.0f, 0.5f, 0, 0);
|
||||
setComponentEffect ((hasShadow) ? &shadow : 0);
|
||||
shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 3, Point<int>()));
|
||||
setComponentEffect (hasShadow ? &shadow : nullptr);
|
||||
|
||||
if (resizeNowToFitThisShape)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,13 +24,8 @@
|
|||
*/
|
||||
|
||||
TabBarButton::TabBarButton (const String& name, TabbedButtonBar& owner_)
|
||||
: Button (name),
|
||||
owner (owner_),
|
||||
overlapPixels (0),
|
||||
extraCompPlacement (afterText)
|
||||
: Button (name), owner (owner_), overlapPixels (0), extraCompPlacement (afterText)
|
||||
{
|
||||
shadow.setShadowProperties (2.2f, 0.7f, 0, 0);
|
||||
setComponentEffect (&shadow);
|
||||
setWantsKeyboardFocus (false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ public:
|
|||
protected:
|
||||
friend class TabbedButtonBar;
|
||||
TabbedButtonBar& owner;
|
||||
DropShadowEffect shadow;
|
||||
int overlapPixels;
|
||||
|
||||
ScopedPointer<Component> extraComponent;
|
||||
|
|
|
|||
|
|
@ -1977,10 +1977,9 @@ int LookAndFeel::getDefaultMenuBarHeight()
|
|||
//==============================================================================
|
||||
DropShadower* LookAndFeel::createDropShadowerForComponent (Component*)
|
||||
{
|
||||
return new DropShadower (0.4f, 1, 5, 10);
|
||||
return new DropShadower (DropShadow (Colours::black.withAlpha (0.4f), 10, Point<int> (0, 2)));
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void LookAndFeel::drawStretchableLayoutResizerBar (Graphics& g,
|
||||
int w, int h,
|
||||
|
|
@ -2085,7 +2084,7 @@ int LookAndFeel::getTabButtonBestWidth (TabBarButton& button, int tabDepth)
|
|||
+ getTabButtonOverlap (tabDepth) * 2;
|
||||
}
|
||||
|
||||
void LookAndFeel::createTabButtonShape (TabBarButton& button, Path& p, bool isMouseOver, bool isMouseDown)
|
||||
void LookAndFeel::createTabButtonShape (TabBarButton& button, Path& p, bool /*isMouseOver*/, bool /*isMouseDown*/)
|
||||
{
|
||||
const Rectangle<int> activeArea (button.getActiveArea());
|
||||
const float w = (float) activeArea.getWidth();
|
||||
|
|
@ -2144,7 +2143,7 @@ void LookAndFeel::createTabButtonShape (TabBarButton& button, Path& p, bool isMo
|
|||
p = p.createPathWithRoundedCorners (3.0f);
|
||||
}
|
||||
|
||||
void LookAndFeel::fillTabButtonShape (TabBarButton& button, Graphics& g, const Path& path, bool isMouseOver, bool isMouseDown)
|
||||
void LookAndFeel::fillTabButtonShape (TabBarButton& button, Graphics& g, const Path& path, bool /*isMouseOver*/, bool /*isMouseDown*/)
|
||||
{
|
||||
const Colour tabBackground (button.getTabBackgroundColour());
|
||||
const bool isFrontTab = button.isFrontTab();
|
||||
|
|
@ -2165,8 +2164,8 @@ void LookAndFeel::drawTabButtonText (TabBarButton& button, Graphics& g, bool isM
|
|||
{
|
||||
const Rectangle<float> area (button.getTextArea().toFloat());
|
||||
|
||||
int length = area.getWidth();
|
||||
int depth = area.getHeight();
|
||||
float length = area.getWidth();
|
||||
float depth = area.getHeight();
|
||||
|
||||
if (button.getTabbedButtonBar().isVertical())
|
||||
std::swap (length, depth);
|
||||
|
|
@ -2178,7 +2177,7 @@ void LookAndFeel::drawTabButtonText (TabBarButton& button, Graphics& g, bool isM
|
|||
textLayout.addFittedText (font, button.getButtonText().trim(),
|
||||
0.0f, 0.0f, (float) length, (float) depth,
|
||||
Justification::centred,
|
||||
jmax (1, depth / 12));
|
||||
jmax (1, ((int) depth) / 12));
|
||||
|
||||
AffineTransform t;
|
||||
|
||||
|
|
@ -2191,21 +2190,20 @@ void LookAndFeel::drawTabButtonText (TabBarButton& button, Graphics& g, bool isM
|
|||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
Colour col;
|
||||
|
||||
if (button.isFrontTab() && (button.isColourSpecified (TabbedButtonBar::frontTextColourId)
|
||||
|| isColourSpecified (TabbedButtonBar::frontTextColourId)))
|
||||
g.setColour (findColour (TabbedButtonBar::frontTextColourId));
|
||||
col = findColour (TabbedButtonBar::frontTextColourId);
|
||||
else if (button.isColourSpecified (TabbedButtonBar::tabTextColourId)
|
||||
|| isColourSpecified (TabbedButtonBar::tabTextColourId))
|
||||
g.setColour (findColour (TabbedButtonBar::tabTextColourId));
|
||||
col = findColour (TabbedButtonBar::tabTextColourId);
|
||||
else
|
||||
g.setColour (button.getTabBackgroundColour().contrasting());
|
||||
col = button.getTabBackgroundColour().contrasting();
|
||||
|
||||
if (! (isMouseOver || isMouseDown))
|
||||
g.setOpacity (0.8f);
|
||||
|
||||
if (! button.isEnabled())
|
||||
g.setOpacity (0.3f);
|
||||
const float alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
|
||||
|
||||
g.setColour (col.withMultipliedAlpha (alpha));
|
||||
textLayout.draw (g, t);
|
||||
}
|
||||
|
||||
|
|
@ -2218,8 +2216,9 @@ void LookAndFeel::drawTabButton (TabBarButton& button, Graphics& g, bool isMouse
|
|||
tabShape.applyTransform (AffineTransform::translation ((float) activeArea.getX(),
|
||||
(float) activeArea.getY()));
|
||||
|
||||
fillTabButtonShape (button, g, tabShape, isMouseOver, isMouseDown);
|
||||
DropShadow (Colours::black.withAlpha (0.5f), 2, Point<int> (0, 1)).drawForPath (g, tabShape);
|
||||
|
||||
fillTabButtonShape (button, g, tabShape, isMouseOver, isMouseDown);
|
||||
drawTabButtonText (button, g, isMouseOver, isMouseDown);
|
||||
}
|
||||
|
||||
|
|
@ -2458,21 +2457,10 @@ void LookAndFeel::drawCallOutBoxBackground (CallOutBox& box, Graphics& g,
|
|||
{
|
||||
if (cachedImage.isNull())
|
||||
{
|
||||
const int w = box.getWidth();
|
||||
const int h = box.getHeight();
|
||||
|
||||
Image renderedPath (Image::ARGB, w, h, true);
|
||||
|
||||
{
|
||||
Graphics g2 (renderedPath);
|
||||
|
||||
g2.setColour (Colour::greyLevel (0.23f).withAlpha (0.9f));
|
||||
g2.fillPath (path);
|
||||
}
|
||||
|
||||
cachedImage = Image (Image::ARGB, w, h, true);
|
||||
cachedImage = Image (Image::ARGB, box.getWidth(), box.getHeight(), true);
|
||||
Graphics g2 (cachedImage);
|
||||
DropShadowEffect::drawShadow (g2, renderedPath, 5.0f, 0.4f, 0, 2);
|
||||
|
||||
DropShadow (Colours::black.withAlpha (0.7f), 8, Point<int> (0, 2)).drawForPath (g2, path);
|
||||
}
|
||||
|
||||
g.setColour (Colours::black);
|
||||
|
|
@ -2779,16 +2767,16 @@ void LookAndFeel::drawShinyButtonShape (Graphics& g,
|
|||
|
||||
Path outline;
|
||||
LookAndFeelHelpers::createRoundedPath (outline, x, y, w, h, cs,
|
||||
! (flatOnLeft || flatOnTop),
|
||||
! (flatOnLeft || flatOnTop),
|
||||
! (flatOnRight || flatOnTop),
|
||||
! (flatOnLeft || flatOnBottom),
|
||||
! (flatOnLeft || flatOnBottom),
|
||||
! (flatOnRight || flatOnBottom));
|
||||
|
||||
ColourGradient cg (baseColour, 0.0f, y,
|
||||
baseColour.overlaidWith (Colour (0x070000ff)), 0.0f, y + h,
|
||||
false);
|
||||
|
||||
cg.addColour (0.5, baseColour.overlaidWith (Colour (0x33ffffff)));
|
||||
cg.addColour (0.5, baseColour.overlaidWith (Colour (0x33ffffff)));
|
||||
cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff)));
|
||||
|
||||
g.setGradientFill (cg);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ BubbleComponent::BubbleComponent()
|
|||
{
|
||||
setInterceptsMouseClicks (false, false);
|
||||
|
||||
shadow.setShadowProperties (5.0f, 0.35f, 0, 0);
|
||||
shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.35f), 5, Point<int>()));
|
||||
setComponentEffect (&shadow);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,16 +97,8 @@ private:
|
|||
|
||||
|
||||
//==============================================================================
|
||||
DropShadower::DropShadower (const float alpha_,
|
||||
const int xOffset_,
|
||||
const int yOffset_,
|
||||
const float blurRadius_)
|
||||
: owner (nullptr),
|
||||
xOffset (xOffset_),
|
||||
yOffset (yOffset_),
|
||||
alpha (alpha_),
|
||||
blurRadius (blurRadius_),
|
||||
reentrant (false)
|
||||
DropShadower::DropShadower (const DropShadow& shadow_)
|
||||
: owner (nullptr), shadow (shadow_), reentrant (false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -179,55 +171,51 @@ void DropShadower::updateShadows()
|
|||
{
|
||||
const ScopedValueSetter<bool> setter (reentrant, true, false);
|
||||
|
||||
const int shadowEdge = jmax (xOffset, yOffset) + (int) blurRadius;
|
||||
const int shadowEdge = jmax (shadow.offset.x, shadow.offset.y) + shadow.radius;
|
||||
|
||||
if (createShadowWindows)
|
||||
{
|
||||
// keep a cached version of the image to save doing the gaussian too often
|
||||
String imageId;
|
||||
imageId << shadowEdge << ',' << xOffset << ',' << yOffset << ',' << alpha;
|
||||
const int shadowEdge2 = shadowEdge * 2;
|
||||
const int imageSize = shadowEdge * 5;
|
||||
|
||||
const int hash = imageId.hashCode();
|
||||
// keep a cached version of the image to save doing the gaussian too often
|
||||
int64 hash = shadow.radius ^ 0x2342dfa7;
|
||||
hash = hash * 101 + shadow.offset.x;
|
||||
hash = hash * 101 + shadow.offset.y;
|
||||
hash = hash * 65537 + shadow.colour.getARGB();
|
||||
|
||||
Image bigIm (ImageCache::getFromHashCode (hash));
|
||||
|
||||
if (bigIm.isNull())
|
||||
{
|
||||
bigIm = Image (Image::ARGB, shadowEdge * 5, shadowEdge * 5, true);
|
||||
bigIm = Image (Image::ARGB, imageSize, imageSize, true);
|
||||
Graphics g (bigIm);
|
||||
|
||||
Graphics bigG (bigIm);
|
||||
bigG.setColour (Colours::black.withAlpha (alpha));
|
||||
bigG.fillRect (shadowEdge + xOffset,
|
||||
shadowEdge + yOffset,
|
||||
bigIm.getWidth() - (shadowEdge * 2),
|
||||
bigIm.getHeight() - (shadowEdge * 2));
|
||||
Path p;
|
||||
p.addRectangle ((float) (shadowEdge + shadow.offset.x),
|
||||
(float) (shadowEdge + shadow.offset.y),
|
||||
(float) (imageSize - shadowEdge2),
|
||||
(float) (imageSize - shadowEdge2));
|
||||
|
||||
ImageConvolutionKernel blurKernel (roundToInt (blurRadius * 2.0f));
|
||||
blurKernel.createGaussianBlur (blurRadius);
|
||||
|
||||
blurKernel.applyToImage (bigIm, bigIm,
|
||||
Rectangle<int> (xOffset, yOffset,
|
||||
bigIm.getWidth(), bigIm.getHeight()));
|
||||
shadow.drawForPath (g, p);
|
||||
|
||||
ImageCache::addImageToCache (bigIm, hash);
|
||||
}
|
||||
|
||||
const int iw = bigIm.getWidth();
|
||||
const int ih = bigIm.getHeight();
|
||||
const int shadowEdge2 = shadowEdge * 2;
|
||||
jassert (imageSize == bigIm.getWidth() && imageSize == bigIm.getHeight());
|
||||
|
||||
setShadowImage (bigIm, 0, shadowEdge, shadowEdge2, 0, 0);
|
||||
setShadowImage (bigIm, 1, shadowEdge, shadowEdge2, 0, ih - shadowEdge2);
|
||||
setShadowImage (bigIm, 2, shadowEdge, shadowEdge, 0, shadowEdge2);
|
||||
setShadowImage (bigIm, 3, shadowEdge, shadowEdge2, iw - shadowEdge, 0);
|
||||
setShadowImage (bigIm, 4, shadowEdge, shadowEdge2, iw - shadowEdge, ih - shadowEdge2);
|
||||
setShadowImage (bigIm, 5, shadowEdge, shadowEdge, iw - shadowEdge, shadowEdge2);
|
||||
setShadowImage (bigIm, 6, shadowEdge, shadowEdge, shadowEdge, 0);
|
||||
setShadowImage (bigIm, 7, shadowEdge, shadowEdge, iw - shadowEdge2, 0);
|
||||
setShadowImage (bigIm, 8, shadowEdge, shadowEdge, shadowEdge2, 0);
|
||||
setShadowImage (bigIm, 9, shadowEdge, shadowEdge, shadowEdge, ih - shadowEdge);
|
||||
setShadowImage (bigIm, 10, shadowEdge, shadowEdge, iw - shadowEdge2, ih - shadowEdge);
|
||||
setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge);
|
||||
setShadowImage (bigIm, 0, shadowEdge, shadowEdge2, 0, 0);
|
||||
setShadowImage (bigIm, 1, shadowEdge, shadowEdge2, 0, imageSize - shadowEdge2);
|
||||
setShadowImage (bigIm, 2, shadowEdge, shadowEdge, 0, shadowEdge2);
|
||||
setShadowImage (bigIm, 3, shadowEdge, shadowEdge2, imageSize - shadowEdge, 0);
|
||||
setShadowImage (bigIm, 4, shadowEdge, shadowEdge2, imageSize - shadowEdge, imageSize - shadowEdge2);
|
||||
setShadowImage (bigIm, 5, shadowEdge, shadowEdge, imageSize - shadowEdge, shadowEdge2);
|
||||
setShadowImage (bigIm, 6, shadowEdge, shadowEdge, shadowEdge, 0);
|
||||
setShadowImage (bigIm, 7, shadowEdge, shadowEdge, imageSize - shadowEdge2, 0);
|
||||
setShadowImage (bigIm, 8, shadowEdge, shadowEdge, shadowEdge2, 0);
|
||||
setShadowImage (bigIm, 9, shadowEdge, shadowEdge, shadowEdge, imageSize - shadowEdge);
|
||||
setShadowImage (bigIm, 10, shadowEdge, shadowEdge, imageSize - shadowEdge2, imageSize - shadowEdge);
|
||||
setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, imageSize - shadowEdge);
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
shadowWindows.add (new ShadowWindow (*owner, i, shadowImageSections));
|
||||
|
|
|
|||
|
|
@ -43,50 +43,35 @@
|
|||
Component::addToDesktop(), and the system will create one of these if it's
|
||||
needed (which it obviously isn't on the Mac, for example).
|
||||
*/
|
||||
class JUCE_API DropShadower : public ComponentListener
|
||||
class JUCE_API DropShadower : private ComponentListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a DropShadower.
|
||||
|
||||
@param alpha the opacity of the shadows, from 0 to 1.0
|
||||
@param xOffset the horizontal displacement of the shadow, in pixels
|
||||
@param yOffset the vertical displacement of the shadow, in pixels
|
||||
@param blurRadius the radius of the blur to use for creating the shadow
|
||||
*/
|
||||
DropShadower (float alpha = 0.5f,
|
||||
int xOffset = 1,
|
||||
int yOffset = 5,
|
||||
float blurRadius = 10.0f);
|
||||
/** Creates a DropShadower. */
|
||||
DropShadower (const DropShadow& shadowType);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~DropShadower();
|
||||
~DropShadower();
|
||||
|
||||
/** Attaches the DropShadower to the component you want to shadow. */
|
||||
void setOwner (Component* componentToFollow);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized);
|
||||
/** @internal */
|
||||
void componentBroughtToFront (Component& component);
|
||||
/** @internal */
|
||||
void componentParentHierarchyChanged (Component& component);
|
||||
/** @internal */
|
||||
void componentVisibilityChanged (Component& component);
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Component* owner;
|
||||
OwnedArray<Component> shadowWindows;
|
||||
Image shadowImageSections[12];
|
||||
const int xOffset, yOffset;
|
||||
const float alpha, blurRadius;
|
||||
DropShadow shadow;
|
||||
bool reentrant;
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool);
|
||||
void componentBroughtToFront (Component&);
|
||||
void componentParentHierarchyChanged (Component&);
|
||||
void componentVisibilityChanged (Component&);
|
||||
|
||||
void updateShadows();
|
||||
void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy);
|
||||
void setShadowImage (const Image&, int num, int w, int h, int sx, int sy);
|
||||
void bringShadowWindowsToFront();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower);
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ public:
|
|||
shouldDeactivateTitleBar = oldDeactivate;
|
||||
|
||||
if (shadower != nullptr)
|
||||
shadower->componentBroughtToFront (*component);
|
||||
handleBroughtToFront();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ OldSchoolLookAndFeel::OldSchoolLookAndFeel()
|
|||
setColour (PopupMenu::highlightedTextColourId, Colours::black);
|
||||
setColour (TextEditor::focusedOutlineColourId, findColour (TextButton::buttonColourId));
|
||||
|
||||
scrollbarShadow.setShadowProperties (2.2f, 0.5f, 0, 0);
|
||||
scrollbarShadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 2, Point<int>()));
|
||||
}
|
||||
|
||||
OldSchoolLookAndFeel::~OldSchoolLookAndFeel()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue