diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index bbf22c9698..6a7e1c0da0 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -4111,7 +4111,7 @@ class var::VariantType_Void : public var::VariantType { public: VariantType_Void() {} - static const VariantType_Void* getInstance() { static const VariantType_Void i; return &i; } + static const VariantType_Void instance; bool isVoid() const throw() { return true; } bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const throw() { return otherType.isVoid(); } @@ -4122,14 +4122,13 @@ class var::VariantType_Int : public var::VariantType { public: VariantType_Int() {} - static const VariantType_Int* getInstance() { static const VariantType_Int i; return &i; } + static const VariantType_Int instance; - int toInt (const ValueUnion& data) const { return data.intValue; }; - double toDouble (const ValueUnion& data) const { return (double) data.intValue; } - const String toString (const ValueUnion& data) const { return String (data.intValue); } - bool toBool (const ValueUnion& data) const { return data.intValue != 0; } - - bool isInt() const throw() { return true; } + int toInt (const ValueUnion& data) const { return data.intValue; }; + double toDouble (const ValueUnion& data) const { return (double) data.intValue; } + const String toString (const ValueUnion& data) const { return String (data.intValue); } + bool toBool (const ValueUnion& data) const { return data.intValue != 0; } + bool isInt() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -4148,14 +4147,13 @@ class var::VariantType_Double : public var::VariantType { public: VariantType_Double() {} - static const VariantType_Double* getInstance() { static const VariantType_Double i; return &i; } - - int toInt (const ValueUnion& data) const { return (int) data.doubleValue; }; - double toDouble (const ValueUnion& data) const { return data.doubleValue; } - const String toString (const ValueUnion& data) const { return String (data.doubleValue); } - bool toBool (const ValueUnion& data) const { return data.doubleValue != 0; } + static const VariantType_Double instance; - bool isDouble() const throw() { return true; } + int toInt (const ValueUnion& data) const { return (int) data.doubleValue; }; + double toDouble (const ValueUnion& data) const { return data.doubleValue; } + const String toString (const ValueUnion& data) const { return String (data.doubleValue); } + bool toBool (const ValueUnion& data) const { return data.doubleValue != 0; } + bool isDouble() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -4174,14 +4172,13 @@ class var::VariantType_Bool : public var::VariantType { public: VariantType_Bool() {} - static const VariantType_Bool* getInstance() { static const VariantType_Bool i; return &i; } - - int toInt (const ValueUnion& data) const { return data.boolValue ? 1 : 0; }; - double toDouble (const ValueUnion& data) const { return data.boolValue ? 1.0 : 0.0; } - const String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? '1' : '0'); } - bool toBool (const ValueUnion& data) const { return data.boolValue; } + static const VariantType_Bool instance; - bool isBool() const throw() { return true; } + int toInt (const ValueUnion& data) const { return data.boolValue ? 1 : 0; }; + double toDouble (const ValueUnion& data) const { return data.boolValue ? 1.0 : 0.0; } + const String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? '1' : '0'); } + bool toBool (const ValueUnion& data) const { return data.boolValue; } + bool isBool() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -4199,19 +4196,18 @@ class var::VariantType_String : public var::VariantType { public: VariantType_String() {} - static const VariantType_String* getInstance() { static const VariantType_String i; return &i; } + static const VariantType_String instance; void cleanUp (ValueUnion& data) const throw() { delete data.stringValue; } void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.stringValue = new String (*source.stringValue); } - int toInt (const ValueUnion& data) const { return data.stringValue->getIntValue(); }; - double toDouble (const ValueUnion& data) const { return data.stringValue->getDoubleValue(); } + int toInt (const ValueUnion& data) const { return data.stringValue->getIntValue(); }; + double toDouble (const ValueUnion& data) const { return data.stringValue->getDoubleValue(); } const String toString (const ValueUnion& data) const { return *data.stringValue; } bool toBool (const ValueUnion& data) const { return data.stringValue->getIntValue() != 0 - || data.stringValue->trim().equalsIgnoreCase ("true") - || data.stringValue->trim().equalsIgnoreCase ("yes"); } - - bool isString() const throw() { return true; } + || data.stringValue->trim().equalsIgnoreCase ("true") + || data.stringValue->trim().equalsIgnoreCase ("yes"); } + bool isString() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -4233,7 +4229,7 @@ class var::VariantType_Object : public var::VariantType { public: VariantType_Object() {} - static const VariantType_Object* getInstance() { static const VariantType_Object i; return &i; } + static const VariantType_Object instance; void cleanUp (ValueUnion& data) const throw() { if (data.objectValue != 0) data.objectValue->decReferenceCount(); } void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.objectValue = source.objectValue; if (dest.objectValue != 0) dest.objectValue->incReferenceCount(); } @@ -4241,8 +4237,7 @@ public: const String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); } bool toBool (const ValueUnion& data) const { return data.objectValue != 0; } DynamicObject* toObject (const ValueUnion& data) const { return data.objectValue; } - - bool isObject() const throw() { return true; } + bool isObject() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -4260,12 +4255,11 @@ class var::VariantType_Method : public var::VariantType { public: VariantType_Method() {} - static const VariantType_Method* getInstance() { static const VariantType_Method i; return &i; } + static const VariantType_Method instance; const String toString (const ValueUnion&) const { return "Method"; } bool toBool (const ValueUnion& data) const { return data.methodValue != 0; } - - bool isMethod() const throw() { return true; } + bool isMethod() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -4279,8 +4273,15 @@ public: } }; -var::var() throw() - : type (VariantType_Void::getInstance()) +const var::VariantType_Void var::VariantType_Void::instance; +const var::VariantType_Int var::VariantType_Int::instance; +const var::VariantType_Bool var::VariantType_Bool::instance; +const var::VariantType_Double var::VariantType_Double::instance; +const var::VariantType_String var::VariantType_String::instance; +const var::VariantType_Object var::VariantType_Object::instance; +const var::VariantType_Method var::VariantType_Method::instance; + +var::var() throw() : type (&VariantType_Void::instance) { } @@ -4296,37 +4297,37 @@ var::var (const var& valueToCopy) : type (valueToCopy.type) type->createCopy (value, valueToCopy.value); } -var::var (const int value_) throw() : type (VariantType_Int::getInstance()) +var::var (const int value_) throw() : type (&VariantType_Int::instance) { value.intValue = value_; } -var::var (const bool value_) throw() : type (VariantType_Bool::getInstance()) +var::var (const bool value_) throw() : type (&VariantType_Bool::instance) { value.boolValue = value_; } -var::var (const double value_) throw() : type (VariantType_Double::getInstance()) +var::var (const double value_) throw() : type (&VariantType_Double::instance) { value.doubleValue = value_; } -var::var (const String& value_) : type (VariantType_String::getInstance()) +var::var (const String& value_) : type (&VariantType_String::instance) { value.stringValue = new String (value_); } -var::var (const char* const value_) : type (VariantType_String::getInstance()) +var::var (const char* const value_) : type (&VariantType_String::instance) { value.stringValue = new String (value_); } -var::var (const juce_wchar* const value_) : type (VariantType_String::getInstance()) +var::var (const juce_wchar* const value_) : type (&VariantType_String::instance) { value.stringValue = new String (value_); } -var::var (DynamicObject* const object) : type (VariantType_Object::getInstance()) +var::var (DynamicObject* const object) : type (&VariantType_Object::instance) { value.objectValue = object; @@ -4334,7 +4335,7 @@ var::var (DynamicObject* const object) : type (VariantType_Object::getInstance( object->incReferenceCount(); } -var::var (MethodFunction method_) throw() : type (VariantType_Method::getInstance()) +var::var (MethodFunction method_) throw() : type (&VariantType_Method::instance) { value.methodValue = method_; } @@ -41426,36 +41427,46 @@ void Component::internalRepaint (int x, int y, int w, int h) } } -void Component::renderComponent (Graphics& g) +void Component::paintComponent (Graphics& g) { - const Rectangle clipBounds (g.getClipBounds()); + if (flags.bufferToImageFlag) + { + if (bufferedImage_.isNull()) + { + bufferedImage_ = Image (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); - g.saveState(); - clipObscuredRegions (g, clipBounds, 0, 0); + Graphics imG (bufferedImage_); + paint (imG); + } - if (! g.isClipEmpty()) + g.setColour (Colours::black.withAlpha (getAlpha())); + g.drawImageAt (bufferedImage_, 0, 0); + } + else { - if (flags.bufferToImageFlag) - { - if (bufferedImage_.isNull()) - { - bufferedImage_ = Image (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); + paint (g); + } +} - Graphics imG (bufferedImage_); - paint (imG); - } +void Component::paintComponentAndChildren (Graphics& g) +{ + const Rectangle clipBounds (g.getClipBounds()); - g.setColour (Colours::black.withAlpha (getAlpha())); - g.drawImageAt (bufferedImage_, 0, 0); - } - else - { - paint (g); - } + if (flags.dontClipGraphicsFlag) + { + paintComponent (g); } + else + { + g.saveState(); + clipObscuredRegions (g, clipBounds, 0, 0); - g.restoreState(); + if (! g.isClipEmpty()) + paintComponent (g); + + g.restoreState(); + } for (int i = 0; i < childComponentList_.size(); ++i) { @@ -41465,20 +41476,33 @@ void Component::renderComponent (Graphics& g) { g.saveState(); - if (g.reduceClipRegion (child->getBounds())) + if (child->flags.dontClipGraphicsFlag) { - for (int j = i + 1; j < childComponentList_.size(); ++j) + g.setOrigin (child->getX(), child->getY()); + child->paintEntireComponent (g, false); + } + else + { + if (g.reduceClipRegion (child->getBounds())) { - const Component* const sibling = childComponentList_.getUnchecked (j); + bool nothingClipped = true; - if (sibling->flags.opaqueFlag && sibling->isVisible()) - g.excludeClipRegion (sibling->getBounds()); - } + for (int j = i + 1; j < childComponentList_.size(); ++j) + { + const Component* const sibling = childComponentList_.getUnchecked (j); - if (! g.isClipEmpty()) - { - g.setOrigin (child->getX(), child->getY()); - child->paintEntireComponent (g, false); + if (sibling->flags.opaqueFlag && sibling->isVisible()) + { + nothingClipped = false; + g.excludeClipRegion (sibling->getBounds()); + } + } + + if (nothingClipped || ! g.isClipEmpty()) + { + g.setOrigin (child->getX(), child->getY()); + child->paintEntireComponent (g, false); + } } } @@ -41491,7 +41515,7 @@ void Component::renderComponent (Graphics& g) g.restoreState(); } -void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel) +void Component::paintEntireComponent (Graphics& g, const bool ignoreAlphaLevel) { jassert (! g.isClipEmpty()); @@ -41505,34 +41529,31 @@ void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel) getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); { Graphics g2 (effectImage); - renderComponent (g2); + paintComponentAndChildren (g2); } effect_->applyEffect (effectImage, g, ignoreAlphaLevel ? 1.0f : getAlpha()); } - else + else if (componentTransparency > 0 && ! ignoreAlphaLevel) { - if (componentTransparency > 0 && ! ignoreAlphaLevel) + if (componentTransparency < 255) { - if (componentTransparency < 255) - { - Image temp (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); + Image temp (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); - { - Graphics tempG (temp); - tempG.reduceClipRegion (g.getClipBounds()); - paintEntireComponent (tempG, true); - } - - g.setColour (Colours::black.withAlpha (getAlpha())); - g.drawImageAt (temp, 0, 0); + { + Graphics tempG (temp); + tempG.reduceClipRegion (g.getClipBounds()); + paintEntireComponent (tempG, true); } + + g.setColour (Colours::black.withAlpha (getAlpha())); + g.drawImageAt (temp, 0, 0); } - else - { - renderComponent (g); - } + } + else + { + paintComponentAndChildren (g); } #if JUCE_DEBUG @@ -41540,6 +41561,11 @@ void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel) #endif } +void Component::setPaintingIsUnclipped (const bool shouldPaintWithoutClipping) throw() +{ + flags.dontClipGraphicsFlag = shouldPaintWithoutClipping; +} + const Image Component::createComponentSnapshot (const Rectangle& areaToGrab, const bool clipImageToComponentBounds) { @@ -51904,7 +51930,7 @@ public: } comp = model->refreshComponentForCell (row, columnId, isSelected, comp); - columnComponents.set (i, comp); + columnComponents.set (i, comp, false); if (comp != 0) { @@ -62532,13 +62558,20 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_ResizableBorderComponent.cpp ***/ BEGIN_JUCE_NAMESPACE -ResizableBorderComponent::Zone::Zone (int zoneFlags) throw() +ResizableBorderComponent::Zone::Zone (const int zoneFlags) throw() : zone (zoneFlags) +{} + +ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) throw() + : zone (other.zone) +{} + +ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) throw() { + zone = other.zone; + return *this; } -ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) throw() : zone (other.zone) {} -ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) throw() { zone = other.zone; return *this; } bool ResizableBorderComponent::Zone::operator== (const ResizableBorderComponent::Zone& other) const throw() { return zone == other.zone; } bool ResizableBorderComponent::Zone::operator!= (const ResizableBorderComponent::Zone& other) const throw() { return zone != other.zone; } @@ -62552,15 +62585,15 @@ const ResizableBorderComponent::Zone ResizableBorderComponent::Zone::fromPositio && ! border.subtractedFrom (totalSize).contains (position)) { const int minW = jmax (totalSize.getWidth() / 10, jmin (10, totalSize.getWidth() / 3)); - if (position.getX() < jmax (border.getLeft(), minW)) + if (position.getX() < jmax (border.getLeft(), minW) && border.getLeft() > 0) z |= left; - else if (position.getX() >= totalSize.getWidth() - jmax (border.getRight(), minW)) + else if (position.getX() >= totalSize.getWidth() - jmax (border.getRight(), minW) && border.getRight() > 0) z |= right; const int minH = jmax (totalSize.getHeight() / 10, jmin (10, totalSize.getHeight() / 3)); - if (position.getY() < jmax (border.getTop(), minH)) + if (position.getY() < jmax (border.getTop(), minH) && border.getTop() > 0) z |= top; - else if (position.getY() >= totalSize.getHeight() - jmax (border.getBottom(), minH)) + else if (position.getY() >= totalSize.getHeight() - jmax (border.getBottom(), minH) && border.getBottom() > 0) z |= bottom; } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 67aa103149..270eb40c96 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -26870,6 +26870,19 @@ public: */ void paintEntireComponent (Graphics& context, bool ignoreAlphaLevel); + /** This allows you to indicate that this component doesn't require its graphics + context to be clipped when it is being painted. + + Most people will never need to use this setting, but in situations where you have a very large + number of simple components being rendered, and where they are guaranteed never to do any drawing + beyond their own boundaries, setting this to true will reduce the overhead involved in clipping + the graphics context that gets passed to the component's paint() callback. + If you enable this mode, you'll need to make sure your paint method doesn't call anything like + Graphics::fillAll(), and doesn't draw beyond the component's bounds, because that'll produce + artifacts. + */ + void setPaintingIsUnclipped (bool shouldPaintWithoutClipping) throw(); + /** Adds an effect filter to alter the component's appearance. When a component has an effect filter set, then this is applied to the @@ -28018,6 +28031,7 @@ private: bool currentlyModalFlag : 1; bool isDisabledFlag : 1; bool childCompFocusedFlag : 1; + bool dontClipGraphicsFlag : 1; #if JUCE_DEBUG bool isInsidePaintCall : 1; #endif @@ -28046,7 +28060,8 @@ private: void internalModifierKeysChanged(); void internalChildrenChanged(); void internalHierarchyChanged(); - void renderComponent (Graphics& g); + void paintComponentAndChildren (Graphics& g); + void paintComponent (Graphics& g); void sendMovedResizedMessages (bool wasMoved, bool wasResized); void repaintParent(); void sendFakeMouseMove() const; diff --git a/src/containers/juce_Variant.cpp b/src/containers/juce_Variant.cpp index dec3b25991..593f57a1ff 100644 --- a/src/containers/juce_Variant.cpp +++ b/src/containers/juce_Variant.cpp @@ -64,7 +64,7 @@ class var::VariantType_Void : public var::VariantType { public: VariantType_Void() {} - static const VariantType_Void* getInstance() { static const VariantType_Void i; return &i; } + static const VariantType_Void instance; bool isVoid() const throw() { return true; } bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const throw() { return otherType.isVoid(); } @@ -76,14 +76,13 @@ class var::VariantType_Int : public var::VariantType { public: VariantType_Int() {} - static const VariantType_Int* getInstance() { static const VariantType_Int i; return &i; } + static const VariantType_Int instance; - int toInt (const ValueUnion& data) const { return data.intValue; }; - double toDouble (const ValueUnion& data) const { return (double) data.intValue; } - const String toString (const ValueUnion& data) const { return String (data.intValue); } - bool toBool (const ValueUnion& data) const { return data.intValue != 0; } - - bool isInt() const throw() { return true; } + int toInt (const ValueUnion& data) const { return data.intValue; }; + double toDouble (const ValueUnion& data) const { return (double) data.intValue; } + const String toString (const ValueUnion& data) const { return String (data.intValue); } + bool toBool (const ValueUnion& data) const { return data.intValue != 0; } + bool isInt() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -103,14 +102,13 @@ class var::VariantType_Double : public var::VariantType { public: VariantType_Double() {} - static const VariantType_Double* getInstance() { static const VariantType_Double i; return &i; } - - int toInt (const ValueUnion& data) const { return (int) data.doubleValue; }; - double toDouble (const ValueUnion& data) const { return data.doubleValue; } - const String toString (const ValueUnion& data) const { return String (data.doubleValue); } - bool toBool (const ValueUnion& data) const { return data.doubleValue != 0; } + static const VariantType_Double instance; - bool isDouble() const throw() { return true; } + int toInt (const ValueUnion& data) const { return (int) data.doubleValue; }; + double toDouble (const ValueUnion& data) const { return data.doubleValue; } + const String toString (const ValueUnion& data) const { return String (data.doubleValue); } + bool toBool (const ValueUnion& data) const { return data.doubleValue != 0; } + bool isDouble() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -130,14 +128,13 @@ class var::VariantType_Bool : public var::VariantType { public: VariantType_Bool() {} - static const VariantType_Bool* getInstance() { static const VariantType_Bool i; return &i; } + static const VariantType_Bool instance; - int toInt (const ValueUnion& data) const { return data.boolValue ? 1 : 0; }; - double toDouble (const ValueUnion& data) const { return data.boolValue ? 1.0 : 0.0; } - const String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? '1' : '0'); } - bool toBool (const ValueUnion& data) const { return data.boolValue; } - - bool isBool() const throw() { return true; } + int toInt (const ValueUnion& data) const { return data.boolValue ? 1 : 0; }; + double toDouble (const ValueUnion& data) const { return data.boolValue ? 1.0 : 0.0; } + const String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? '1' : '0'); } + bool toBool (const ValueUnion& data) const { return data.boolValue; } + bool isBool() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -156,19 +153,18 @@ class var::VariantType_String : public var::VariantType { public: VariantType_String() {} - static const VariantType_String* getInstance() { static const VariantType_String i; return &i; } + static const VariantType_String instance; void cleanUp (ValueUnion& data) const throw() { delete data.stringValue; } void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.stringValue = new String (*source.stringValue); } - int toInt (const ValueUnion& data) const { return data.stringValue->getIntValue(); }; - double toDouble (const ValueUnion& data) const { return data.stringValue->getDoubleValue(); } - const String toString (const ValueUnion& data) const { return *data.stringValue; } - bool toBool (const ValueUnion& data) const { return data.stringValue->getIntValue() != 0 - || data.stringValue->trim().equalsIgnoreCase ("true") - || data.stringValue->trim().equalsIgnoreCase ("yes"); } - - bool isString() const throw() { return true; } + int toInt (const ValueUnion& data) const { return data.stringValue->getIntValue(); }; + double toDouble (const ValueUnion& data) const { return data.stringValue->getDoubleValue(); } + const String toString (const ValueUnion& data) const { return *data.stringValue; } + bool toBool (const ValueUnion& data) const { return data.stringValue->getIntValue() != 0 + || data.stringValue->trim().equalsIgnoreCase ("true") + || data.stringValue->trim().equalsIgnoreCase ("yes"); } + bool isString() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -191,7 +187,7 @@ class var::VariantType_Object : public var::VariantType { public: VariantType_Object() {} - static const VariantType_Object* getInstance() { static const VariantType_Object i; return &i; } + static const VariantType_Object instance; void cleanUp (ValueUnion& data) const throw() { if (data.objectValue != 0) data.objectValue->decReferenceCount(); } void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.objectValue = source.objectValue; if (dest.objectValue != 0) dest.objectValue->incReferenceCount(); } @@ -199,8 +195,7 @@ public: const String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); } bool toBool (const ValueUnion& data) const { return data.objectValue != 0; } DynamicObject* toObject (const ValueUnion& data) const { return data.objectValue; } - - bool isObject() const throw() { return true; } + bool isObject() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -219,12 +214,11 @@ class var::VariantType_Method : public var::VariantType { public: VariantType_Method() {} - static const VariantType_Method* getInstance() { static const VariantType_Method i; return &i; } + static const VariantType_Method instance; const String toString (const ValueUnion&) const { return "Method"; } bool toBool (const ValueUnion& data) const { return data.methodValue != 0; } - - bool isMethod() const throw() { return true; } + bool isMethod() const throw() { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() { @@ -238,10 +232,18 @@ public: } }; +//============================================================================== +const var::VariantType_Void var::VariantType_Void::instance; +const var::VariantType_Int var::VariantType_Int::instance; +const var::VariantType_Bool var::VariantType_Bool::instance; +const var::VariantType_Double var::VariantType_Double::instance; +const var::VariantType_String var::VariantType_String::instance; +const var::VariantType_Object var::VariantType_Object::instance; +const var::VariantType_Method var::VariantType_Method::instance; + //============================================================================== -var::var() throw() - : type (VariantType_Void::getInstance()) +var::var() throw() : type (&VariantType_Void::instance) { } @@ -258,37 +260,37 @@ var::var (const var& valueToCopy) : type (valueToCopy.type) type->createCopy (value, valueToCopy.value); } -var::var (const int value_) throw() : type (VariantType_Int::getInstance()) +var::var (const int value_) throw() : type (&VariantType_Int::instance) { value.intValue = value_; } -var::var (const bool value_) throw() : type (VariantType_Bool::getInstance()) +var::var (const bool value_) throw() : type (&VariantType_Bool::instance) { value.boolValue = value_; } -var::var (const double value_) throw() : type (VariantType_Double::getInstance()) +var::var (const double value_) throw() : type (&VariantType_Double::instance) { value.doubleValue = value_; } -var::var (const String& value_) : type (VariantType_String::getInstance()) +var::var (const String& value_) : type (&VariantType_String::instance) { value.stringValue = new String (value_); } -var::var (const char* const value_) : type (VariantType_String::getInstance()) +var::var (const char* const value_) : type (&VariantType_String::instance) { value.stringValue = new String (value_); } -var::var (const juce_wchar* const value_) : type (VariantType_String::getInstance()) +var::var (const juce_wchar* const value_) : type (&VariantType_String::instance) { value.stringValue = new String (value_); } -var::var (DynamicObject* const object) : type (VariantType_Object::getInstance()) +var::var (DynamicObject* const object) : type (&VariantType_Object::instance) { value.objectValue = object; @@ -296,7 +298,7 @@ var::var (DynamicObject* const object) : type (VariantType_Object::getInstance( object->incReferenceCount(); } -var::var (MethodFunction method_) throw() : type (VariantType_Method::getInstance()) +var::var (MethodFunction method_) throw() : type (&VariantType_Method::instance) { value.methodValue = method_; } diff --git a/src/gui/components/controls/juce_TableListBox.cpp b/src/gui/components/controls/juce_TableListBox.cpp index b7ac55e31c..9db062e52a 100644 --- a/src/gui/components/controls/juce_TableListBox.cpp +++ b/src/gui/components/controls/juce_TableListBox.cpp @@ -103,7 +103,7 @@ public: } comp = model->refreshComponentForCell (row, columnId, isSelected, comp); - columnComponents.set (i, comp); + columnComponents.set (i, comp, false); if (comp != 0) { diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index 94f18bfc4e..354328e322 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -1654,36 +1654,46 @@ void Component::internalRepaint (int x, int y, int w, int h) } //============================================================================== -void Component::renderComponent (Graphics& g) +void Component::paintComponent (Graphics& g) { - const Rectangle clipBounds (g.getClipBounds()); + if (flags.bufferToImageFlag) + { + if (bufferedImage_.isNull()) + { + bufferedImage_ = Image (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); - g.saveState(); - clipObscuredRegions (g, clipBounds, 0, 0); + Graphics imG (bufferedImage_); + paint (imG); + } - if (! g.isClipEmpty()) + g.setColour (Colours::black.withAlpha (getAlpha())); + g.drawImageAt (bufferedImage_, 0, 0); + } + else { - if (flags.bufferToImageFlag) - { - if (bufferedImage_.isNull()) - { - bufferedImage_ = Image (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); + paint (g); + } +} - Graphics imG (bufferedImage_); - paint (imG); - } +void Component::paintComponentAndChildren (Graphics& g) +{ + const Rectangle clipBounds (g.getClipBounds()); - g.setColour (Colours::black.withAlpha (getAlpha())); - g.drawImageAt (bufferedImage_, 0, 0); - } - else - { - paint (g); - } + if (flags.dontClipGraphicsFlag) + { + paintComponent (g); } + else + { + g.saveState(); + clipObscuredRegions (g, clipBounds, 0, 0); - g.restoreState(); + if (! g.isClipEmpty()) + paintComponent (g); + + g.restoreState(); + } for (int i = 0; i < childComponentList_.size(); ++i) { @@ -1693,20 +1703,33 @@ void Component::renderComponent (Graphics& g) { g.saveState(); - if (g.reduceClipRegion (child->getBounds())) + if (child->flags.dontClipGraphicsFlag) + { + g.setOrigin (child->getX(), child->getY()); + child->paintEntireComponent (g, false); + } + else { - for (int j = i + 1; j < childComponentList_.size(); ++j) + if (g.reduceClipRegion (child->getBounds())) { - const Component* const sibling = childComponentList_.getUnchecked (j); + bool nothingClipped = true; - if (sibling->flags.opaqueFlag && sibling->isVisible()) - g.excludeClipRegion (sibling->getBounds()); - } + for (int j = i + 1; j < childComponentList_.size(); ++j) + { + const Component* const sibling = childComponentList_.getUnchecked (j); - if (! g.isClipEmpty()) - { - g.setOrigin (child->getX(), child->getY()); - child->paintEntireComponent (g, false); + if (sibling->flags.opaqueFlag && sibling->isVisible()) + { + nothingClipped = false; + g.excludeClipRegion (sibling->getBounds()); + } + } + + if (nothingClipped || ! g.isClipEmpty()) + { + g.setOrigin (child->getX(), child->getY()); + child->paintEntireComponent (g, false); + } } } @@ -1719,7 +1742,7 @@ void Component::renderComponent (Graphics& g) g.restoreState(); } -void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel) +void Component::paintEntireComponent (Graphics& g, const bool ignoreAlphaLevel) { jassert (! g.isClipEmpty()); @@ -1733,41 +1756,43 @@ void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel) getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); { Graphics g2 (effectImage); - renderComponent (g2); + paintComponentAndChildren (g2); } effect_->applyEffect (effectImage, g, ignoreAlphaLevel ? 1.0f : getAlpha()); } - else + else if (componentTransparency > 0 && ! ignoreAlphaLevel) { - if (componentTransparency > 0 && ! ignoreAlphaLevel) + if (componentTransparency < 255) { - if (componentTransparency < 255) - { - Image temp (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); - - { - Graphics tempG (temp); - tempG.reduceClipRegion (g.getClipBounds()); - paintEntireComponent (tempG, true); - } + Image temp (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); - g.setColour (Colours::black.withAlpha (getAlpha())); - g.drawImageAt (temp, 0, 0); + { + Graphics tempG (temp); + tempG.reduceClipRegion (g.getClipBounds()); + paintEntireComponent (tempG, true); } - } - else - { - renderComponent (g); + + g.setColour (Colours::black.withAlpha (getAlpha())); + g.drawImageAt (temp, 0, 0); } } + else + { + paintComponentAndChildren (g); + } #if JUCE_DEBUG flags.isInsidePaintCall = false; #endif } +void Component::setPaintingIsUnclipped (const bool shouldPaintWithoutClipping) throw() +{ + flags.dontClipGraphicsFlag = shouldPaintWithoutClipping; +} + //============================================================================== const Image Component::createComponentSnapshot (const Rectangle& areaToGrab, const bool clipImageToComponentBounds) diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index 5e4f2f6ba8..1e8a499b07 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -879,6 +879,18 @@ public: */ void paintEntireComponent (Graphics& context, bool ignoreAlphaLevel); + /** This allows you to indicate that this component doesn't require its graphics + context to be clipped when it is being painted. + + Most people will never need to use this setting, but in situations where you have a very large + number of simple components being rendered, and where they are guaranteed never to do any drawing + beyond their own boundaries, setting this to true will reduce the overhead involved in clipping + the graphics context that gets passed to the component's paint() callback. + If you enable this mode, you'll need to make sure your paint method doesn't call anything like + Graphics::fillAll(), and doesn't draw beyond the component's bounds, because that'll produce + artifacts. + */ + void setPaintingIsUnclipped (bool shouldPaintWithoutClipping) throw(); //============================================================================== /** Adds an effect filter to alter the component's appearance. @@ -2058,6 +2070,7 @@ private: bool currentlyModalFlag : 1; bool isDisabledFlag : 1; bool childCompFocusedFlag : 1; + bool dontClipGraphicsFlag : 1; #if JUCE_DEBUG bool isInsidePaintCall : 1; #endif @@ -2087,7 +2100,8 @@ private: void internalModifierKeysChanged(); void internalChildrenChanged(); void internalHierarchyChanged(); - void renderComponent (Graphics& g); + void paintComponentAndChildren (Graphics& g); + void paintComponent (Graphics& g); void sendMovedResizedMessages (bool wasMoved, bool wasResized); void repaintParent(); void sendFakeMouseMove() const; diff --git a/src/gui/components/layout/juce_ResizableBorderComponent.cpp b/src/gui/components/layout/juce_ResizableBorderComponent.cpp index ec755d4e01..5d61eadf66 100644 --- a/src/gui/components/layout/juce_ResizableBorderComponent.cpp +++ b/src/gui/components/layout/juce_ResizableBorderComponent.cpp @@ -35,13 +35,20 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -ResizableBorderComponent::Zone::Zone (int zoneFlags) throw() +ResizableBorderComponent::Zone::Zone (const int zoneFlags) throw() : zone (zoneFlags) +{} + +ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) throw() + : zone (other.zone) +{} + +ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) throw() { + zone = other.zone; + return *this; } -ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) throw() : zone (other.zone) {} -ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) throw() { zone = other.zone; return *this; } bool ResizableBorderComponent::Zone::operator== (const ResizableBorderComponent::Zone& other) const throw() { return zone == other.zone; } bool ResizableBorderComponent::Zone::operator!= (const ResizableBorderComponent::Zone& other) const throw() { return zone != other.zone; } @@ -55,15 +62,15 @@ const ResizableBorderComponent::Zone ResizableBorderComponent::Zone::fromPositio && ! border.subtractedFrom (totalSize).contains (position)) { const int minW = jmax (totalSize.getWidth() / 10, jmin (10, totalSize.getWidth() / 3)); - if (position.getX() < jmax (border.getLeft(), minW)) + if (position.getX() < jmax (border.getLeft(), minW) && border.getLeft() > 0) z |= left; - else if (position.getX() >= totalSize.getWidth() - jmax (border.getRight(), minW)) + else if (position.getX() >= totalSize.getWidth() - jmax (border.getRight(), minW) && border.getRight() > 0) z |= right; const int minH = jmax (totalSize.getHeight() / 10, jmin (10, totalSize.getHeight() / 3)); - if (position.getY() < jmax (border.getTop(), minH)) + if (position.getY() < jmax (border.getTop(), minH) && border.getTop() > 0) z |= top; - else if (position.getY() >= totalSize.getHeight() - jmax (border.getBottom(), minH)) + else if (position.getY() >= totalSize.getHeight() - jmax (border.getBottom(), minH) && border.getBottom() > 0) z |= bottom; }