Browse Source

Refactored Path::addBubble, BubbleMessageComponent and BubbleComponent classes to work better and avoid duplicated code.

tags/2021-05-28
jules 13 years ago
parent
commit
27f1901fe6
11 changed files with 152 additions and 284 deletions
  1. +1
    -1
      extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp
  2. +1
    -1
      extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h
  3. +48
    -62
      modules/juce_graphics/geometry/juce_Path.cpp
  4. +13
    -20
      modules/juce_graphics/geometry/juce_Path.h
  5. +5
    -5
      modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp
  6. +5
    -18
      modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp
  7. +42
    -85
      modules/juce_gui_basics/misc/juce_BubbleComponent.cpp
  8. +3
    -4
      modules/juce_gui_basics/misc/juce_BubbleComponent.h
  9. +4
    -58
      modules/juce_gui_basics/windows/juce_CallOutBox.cpp
  10. +27
    -27
      modules/juce_gui_extra/misc/juce_BubbleMessageComponent.cpp
  11. +3
    -3
      modules/juce_gui_extra/misc/juce_BubbleMessageComponent.h

+ 1
- 1
extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp View File

@@ -507,7 +507,7 @@ bool ProjectContentComponent::reinvokeCommandAfterClosingPropertyEditors (const
return false;
}
void ProjectContentComponent::showBubbleMessage (const Point<int>& pos, const String& text)
void ProjectContentComponent::showBubbleMessage (const Rectangle<int>& pos, const String& text)
{
addChildComponent (&bubbleMessage);
bubbleMessage.setAlwaysOnTop (true);


+ 1
- 1
extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h View File

@@ -58,7 +58,7 @@ public:
void updateMissingFileStatuses();
virtual void createProjectTabs();
void showBubbleMessage (const Point<int>& pos, const String& text);
void showBubbleMessage (const Rectangle<int>& pos, const String& text);
void changeListenerCallback (ChangeBroadcaster*);


+ 48
- 62
modules/juce_graphics/geometry/juce_Path.cpp View File

@@ -688,80 +688,66 @@ void Path::addStar (const Point<float>& centre, const int numberOfPoints,
}
}
void Path::addBubble (float x, float y,
float w, float h,
float cs,
float tipX,
float tipY,
int whichSide,
float arrowPos,
float arrowWidth)
{
if (w > 1.0f && h > 1.0f)
{
cs = jmin (cs, w * 0.5f, h * 0.5f);
const float cs2 = 2.0f * cs;
startNewSubPath (x + cs, y);
if (whichSide == 0)
{
const float halfArrowW = jmin (arrowWidth, w - cs2) * 0.5f;
const float arrowX1 = x + cs + jmax (0.0f, (w - cs2 - arrowWidth) * arrowPos - halfArrowW);
lineTo (arrowX1, y);
lineTo (tipX, tipY);
lineTo (arrowX1 + halfArrowW * 2.0f, y);
}
void Path::addBubble (const Rectangle<float>& bodyArea,
const Rectangle<float>& maximumArea,
const Point<float>& arrowTip,
const float cornerSize,
const float arrowBaseWidth)
{
const float cornerSize2 = 2.0f * cornerSize;
lineTo (x + w - cs, y);
startNewSubPath (bodyArea.getX() + cornerSize, bodyArea.getY());
if (cs > 0.0f)
addArc (x + w - cs2, y, cs2, cs2, 0, float_Pi * 0.5f);
const float targetLimitX = bodyArea.getX() + cornerSize + arrowBaseWidth;
const float targetLimitW = bodyArea.getWidth() - cornerSize2 - arrowBaseWidth * 2.0f;
if (whichSide == 3)
{
const float halfArrowH = jmin (arrowWidth, h - cs2) * 0.5f;
const float arrowY1 = y + cs + jmax (0.0f, (h - cs2 - arrowWidth) * arrowPos - halfArrowH);
lineTo (x + w, arrowY1);
lineTo (tipX, tipY);
lineTo (x + w, arrowY1 + halfArrowH * 2.0f);
}
const float targetLimitY = bodyArea.getY() + cornerSize + arrowBaseWidth;
const float targetLimitH = bodyArea.getHeight() - cornerSize2 - arrowBaseWidth * 2.0f;
lineTo (x + w, y + h - cs);
if (Rectangle<float> (targetLimitX, maximumArea.getY(),
targetLimitW, bodyArea.getY() - maximumArea.getY()).contains (arrowTip))
{
lineTo (arrowTip.x - arrowBaseWidth, bodyArea.getY());
lineTo (arrowTip.x, arrowTip.y);
lineTo (arrowTip.x + arrowBaseWidth, bodyArea.getY());
}
if (cs > 0.0f)
addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi);
lineTo (bodyArea.getRight() - cornerSize, bodyArea.getY());
addArc (bodyArea.getRight() - cornerSize2, bodyArea.getY(), cornerSize2, cornerSize2, 0, float_Pi * 0.5f);
if (whichSide == 2)
{
const float halfArrowW = jmin (arrowWidth, w - cs2) * 0.5f;
const float arrowX1 = x + cs + jmax (0.0f, (w - cs2 - arrowWidth) * arrowPos - halfArrowW);
lineTo (arrowX1 + halfArrowW * 2.0f, y + h);
lineTo (tipX, tipY);
lineTo (arrowX1, y + h);
}
if (Rectangle<float> (bodyArea.getRight(), targetLimitY,
maximumArea.getRight() - bodyArea.getRight(), targetLimitH).contains (arrowTip))
{
lineTo (bodyArea.getRight(), arrowTip.y - arrowBaseWidth);
lineTo (arrowTip.x, arrowTip.y);
lineTo (bodyArea.getRight(), arrowTip.y + arrowBaseWidth);
}
lineTo (x + cs, y + h);
lineTo (bodyArea.getRight(), bodyArea.getBottom() - cornerSize);
addArc (bodyArea.getRight() - cornerSize2, bodyArea.getBottom() - cornerSize2, cornerSize2, cornerSize2, float_Pi * 0.5f, float_Pi);
if (cs > 0.0f)
addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f);
if (Rectangle<float> (targetLimitX, bodyArea.getBottom(),
targetLimitW, maximumArea.getBottom() - bodyArea.getBottom()).contains (arrowTip))
{
lineTo (arrowTip.x + arrowBaseWidth, bodyArea.getBottom());
lineTo (arrowTip.x, arrowTip.y);
lineTo (arrowTip.x - arrowBaseWidth, bodyArea.getBottom());
}
if (whichSide == 1)
{
const float halfArrowH = jmin (arrowWidth, h - cs2) * 0.5f;
const float arrowY1 = y + cs + jmax (0.0f, (h - cs2 - arrowWidth) * arrowPos - halfArrowH);
lineTo (x, arrowY1 + halfArrowH * 2.0f);
lineTo (tipX, tipY);
lineTo (x, arrowY1);
}
lineTo (bodyArea.getX() + cornerSize, bodyArea.getBottom());
addArc (bodyArea.getX(), bodyArea.getBottom() - cornerSize2, cornerSize2, cornerSize2, float_Pi, float_Pi * 1.5f);
lineTo (x, y + cs);
if (Rectangle<float> (maximumArea.getX(), targetLimitY, bodyArea.getX() - maximumArea.getX(), targetLimitH).contains (arrowTip))
{
lineTo (bodyArea.getX(), arrowTip.y + arrowBaseWidth);
lineTo (arrowTip.x, arrowTip.y);
lineTo (bodyArea.getX(), arrowTip.y - arrowBaseWidth);
}
if (cs > 0.0f)
addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f - PathHelpers::ellipseAngularIncrement);
lineTo (bodyArea.getX(), bodyArea.getY() + cornerSize);
addArc (bodyArea.getX(), bodyArea.getY(), cornerSize2, cornerSize2, float_Pi * 1.5f, float_Pi * 2.0f - 0.05f);
closeSubPath();
}
closeSubPath();
}
void Path::addPath (const Path& other)


+ 13
- 20
modules/juce_graphics/geometry/juce_Path.h View File

@@ -519,26 +519,19 @@ public:
/** Adds a speech-bubble shape to the path.
@param bodyX the left of the main body area of the bubble
@param bodyY the top of the main body area of the bubble
@param bodyW the width of the main body area of the bubble
@param bodyH the height of the main body area of the bubble
@param cornerSize the amount by which to round off the corners of the main body rectangle
@param arrowTipX the x position that the tip of the arrow should connect to
@param arrowTipY the y position that the tip of the arrow should connect to
@param whichSide the side to connect the arrow to: 0 = top, 1 = left, 2 = bottom, 3 = right
@param arrowPositionAlongEdgeProportional how far along the edge of the main rectangle the
arrow's base should be - this is a proportional distance between 0 and 1.0
@param arrowWidth how wide the base of the arrow should be where it joins the main rectangle
*/
void addBubble (float bodyX, float bodyY,
float bodyW, float bodyH,
float cornerSize,
float arrowTipX,
float arrowTipY,
int whichSide,
float arrowPositionAlongEdgeProportional,
float arrowWidth);
@param bodyArea the area of the body of the bubble shape
@param maximumArea an area which encloses the body area and defines the limits within which
the arrow tip can be drawn - if the tip lies outside this area, the bubble
will be drawn without an arrow
@param arrowTipPosition the location of the tip of the arrow
@param cornerSize the size of the rounded corners
@param arrowBaseWidth the width of the base of the arrow where it joins the main rectangle
*/
void addBubble (const Rectangle<float>& bodyArea,
const Rectangle<float>& maximumArea,
const Point<float>& arrowTipPosition,
const float cornerSize,
const float arrowBaseWidth);
/** Adds another path to this one.


+ 5
- 5
modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp View File

@@ -46,11 +46,11 @@ public:
isMoving = (finalBounds != component->getBounds());
isChangingAlpha = (finalAlpha != component->getAlpha());
left = component->getX();
top = component->getY();
right = component->getRight();
bottom = component->getBottom();
alpha = component->getAlpha();
left = component->getX();
top = component->getY();
right = component->getRight();
bottom = component->getBottom();
alpha = component->getAlpha();
const double invTotalDistance = 4.0 / (startSpeed_ + endSpeed_ + 2.0);
startSpeed = jmax (0.0, startSpeed_ * invTotalDistance);


+ 5
- 18
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp View File

@@ -949,26 +949,13 @@ void LookAndFeel::drawBubble (Graphics& g,
float boxX, float boxY,
float boxW, float boxH)
{
int side = 0;
const Rectangle<float> body (boxX, boxY, boxW, boxH);
if (tipX < boxX)
side = 1;
else if (tipX > boxX + boxW)
side = 3;
else if (tipY > boxY + boxH)
side = 2;
const float indent = 2.0f;
Path p;
p.addBubble (boxX + indent,
boxY + indent,
boxW - indent * 2.0f,
boxH - indent * 2.0f,
5.0f,
tipX, tipY,
side,
0.5f,
jmin (15.0f, boxW * 0.3f, boxH * 0.3f));
p.addBubble (body,
body.getUnion (Rectangle<float> (tipX, tipY, 1.0f, 1.0f)),
Point<float> (tipX, tipY),
5.0f, jmin (15.0f, boxW * 0.2f, boxH * 0.2f));
//xxx need to take comp as param for colour
g.setColour (findColour (TooltipWindow::backgroundColourId).withAlpha (0.9f));


+ 42
- 85
modules/juce_gui_basics/misc/juce_BubbleComponent.cpp View File

@@ -24,10 +24,7 @@
*/
BubbleComponent::BubbleComponent()
: side (0),
allowablePlacements (above | below | left | right),
arrowTipX (0.0f),
arrowTipY (0.0f)
: allowablePlacements (above | below | left | right)
{
setInterceptsMouseClicks (false, false);
@@ -42,41 +39,14 @@ BubbleComponent::~BubbleComponent()
//==============================================================================
void BubbleComponent::paint (Graphics& g)
{
int x = content.getX();
int y = content.getY();
int w = content.getWidth();
int h = content.getHeight();
getLookAndFeel().drawBubble (g, arrowTip.x, arrowTip.y,
(float) content.getX(), (float) content.getY(),
(float) content.getWidth(), (float) content.getHeight());
int cw, ch;
getContentSize (cw, ch);
g.setOrigin (content.getX(), content.getY());
g.reduceClipRegion (0, 0, content.getWidth(), content.getHeight());
if (side == 3)
x += w - cw;
else if (side != 1)
x += (w - cw) / 2;
w = cw;
if (side == 2)
y += h - ch;
else if (side != 0)
y += (h - ch) / 2;
h = ch;
getLookAndFeel().drawBubble (g, arrowTipX, arrowTipY,
(float) x, (float) y,
(float) w, (float) h);
const int cx = x + (w - cw) / 2;
const int cy = y + (h - ch) / 2;
const int indent = 3;
g.setOrigin (cx + indent, cy + indent);
g.reduceClipRegion (0, 0, cw - indent * 2, ch - indent * 2);
paintContent (g, cw - indent * 2, ch - indent * 2);
paintContent (g, content.getWidth(), content.getHeight());
}
//==============================================================================
@@ -89,102 +59,89 @@ void BubbleComponent::setPosition (Component* componentToPointTo)
{
jassert (componentToPointTo != nullptr);
Point<int> pos;
if (getParentComponent() != nullptr)
pos = getParentComponent()->getLocalPoint (componentToPointTo, pos);
setPosition (getParentComponent()->getLocalArea (componentToPointTo, componentToPointTo->getLocalBounds()));
else
pos = componentToPointTo->localPointToGlobal (pos);
setPosition (Rectangle<int> (pos.x, pos.y, componentToPointTo->getWidth(), componentToPointTo->getHeight()));
setPosition (componentToPointTo->getScreenBounds());
}
void BubbleComponent::setPosition (const int arrowTipX_,
const int arrowTipY_)
void BubbleComponent::setPosition (const Point<int>& pos)
{
setPosition (Rectangle<int> (arrowTipX_, arrowTipY_, 1, 1));
setPosition (Rectangle<int> (pos.x, pos.y, 1, 1));
}
//==============================================================================
void BubbleComponent::setPosition (const Rectangle<int>& rectangleToPointTo)
{
Rectangle<int> availableSpace (getParentComponent() != nullptr ? getParentComponent()->getLocalBounds()
: getParentMonitorArea());
int x = 0;
int y = 0;
int w = 150;
int h = 30;
const int edgeSpace = 15;
const int arrowLength = 10;
{
int contentW = 150, contentH = 30;
getContentSize (contentW, contentH);
content.setBounds (edgeSpace, edgeSpace, contentW, contentH);
}
getContentSize (w, h);
w += 30;
h += 30;
int totalW = content.getWidth() + edgeSpace * 2;
int totalH = content.getHeight() + edgeSpace * 2;
int targetX, targetY;
const float edgeIndent = 2.0f;
const int arrowLength = jmin (10, h / 3, w / 3);
const Rectangle<int> availableSpace (getParentComponent() != nullptr ? getParentComponent()->getLocalBounds()
: getParentMonitorArea());
int spaceAbove = ((allowablePlacements & above) != 0) ? jmax (0, rectangleToPointTo.getY() - availableSpace.getY()) : -1;
int spaceAbove = ((allowablePlacements & above) != 0) ? jmax (0, rectangleToPointTo.getY() - availableSpace.getY()) : -1;
int spaceBelow = ((allowablePlacements & below) != 0) ? jmax (0, availableSpace.getBottom() - rectangleToPointTo.getBottom()) : -1;
int spaceLeft = ((allowablePlacements & left) != 0) ? jmax (0, rectangleToPointTo.getX() - availableSpace.getX()) : -1;
int spaceRight = ((allowablePlacements & right) != 0) ? jmax (0, availableSpace.getRight() - rectangleToPointTo.getRight()) : -1;
int spaceLeft = ((allowablePlacements & left) != 0) ? jmax (0, rectangleToPointTo.getX() - availableSpace.getX()) : -1;
int spaceRight = ((allowablePlacements & right) != 0) ? jmax (0, availableSpace.getRight() - rectangleToPointTo.getRight()) : -1;
// look at whether the component is elongated, and if so, try to position next to its longer dimension.
if (rectangleToPointTo.getWidth() > rectangleToPointTo.getHeight() * 2
&& (spaceAbove > h + 20 || spaceBelow > h + 20))
&& (spaceAbove > totalH + 20 || spaceBelow > totalH + 20))
{
spaceLeft = spaceRight = 0;
}
else if (rectangleToPointTo.getWidth() < rectangleToPointTo.getHeight() / 2
&& (spaceLeft > w + 20 || spaceRight > w + 20))
&& (spaceLeft > totalW + 20 || spaceRight > totalW + 20))
{
spaceAbove = spaceBelow = 0;
}
if (jmax (spaceAbove, spaceBelow) >= jmax (spaceLeft, spaceRight))
{
x = rectangleToPointTo.getX() + (rectangleToPointTo.getWidth() - w) / 2;
arrowTipX = w * 0.5f;
content.setSize (w, h - arrowLength);
targetX = rectangleToPointTo.getCentre().x;
arrowTip.x = totalW * 0.5f;
if (spaceAbove >= spaceBelow)
{
// above
y = rectangleToPointTo.getY() - h;
content.setPosition (0, 0);
arrowTipY = h - edgeIndent;
side = 2;
targetY = rectangleToPointTo.getY();
arrowTip.y = content.getBottom() + arrowLength;
}
else
{
// below
y = rectangleToPointTo.getBottom();
content.setPosition (0, arrowLength);
arrowTipY = edgeIndent;
side = 0;
targetY = rectangleToPointTo.getBottom();
arrowTip.y = content.getY() - arrowLength;
}
}
else
{
y = rectangleToPointTo.getY() + (rectangleToPointTo.getHeight() - h) / 2;
arrowTipY = h * 0.5f;
content.setSize (w - arrowLength, h);
targetY = rectangleToPointTo.getCentre().y;
arrowTip.y = totalH * 0.5f;
if (spaceLeft > spaceRight)
{
// on the left
x = rectangleToPointTo.getX() - w;
content.setPosition (0, 0);
arrowTipX = w - edgeIndent;
side = 3;
targetX = rectangleToPointTo.getX();
arrowTip.x = content.getRight() + arrowLength;
}
else
{
// on the right
x = rectangleToPointTo.getRight();
content.setPosition (arrowLength, 0);
arrowTipX = edgeIndent;
side = 1;
targetX = rectangleToPointTo.getRight();
arrowTip.x = content.getX() - arrowLength;
}
}
setBounds (x, y, w, h);
setBounds (targetX - arrowTip.x, targetY - arrowTip.y, totalW, totalH);
}

+ 3
- 4
modules/juce_gui_basics/misc/juce_BubbleComponent.h View File

@@ -108,8 +108,7 @@ public:
on where there's the most space, honouring any restrictions that were set
with setAllowedPlacement().
*/
void setPosition (int arrowTipX,
int arrowTipY);
void setPosition (const Point<int>& arrowTipPosition);
/** Moves and resizes the bubble to point at a given rectangle.
@@ -145,8 +144,8 @@ public:
private:
Rectangle<int> content;
int side, allowablePlacements;
float arrowTipX, arrowTipY;
Point<float> arrowTip;
int allowablePlacements;
DropShadowEffect shadow;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BubbleComponent);


+ 4
- 58
modules/juce_gui_basics/windows/juce_CallOutBox.cpp View File

@@ -199,63 +199,9 @@ void CallOutBox::refreshPath()
outline.clear();
const float gap = 4.5f;
const float cornerSize = 9.0f;
const float cornerSize2 = 2.0f * cornerSize;
const float arrowBaseWidth = arrowSize * 0.7f;
const Rectangle<float> area (content.getBounds().toFloat().expanded (gap, gap));
const Point<float> target (targetPoint - getPosition().toFloat());
outline.startNewSubPath (area.getX() + cornerSize, area.getY());
const float targetLimitX = area.getX() + cornerSize + arrowBaseWidth;
const float targetLimitW = area.getWidth() - cornerSize2 - arrowBaseWidth * 2.0f;
const float targetLimitY = area.getY() + cornerSize + arrowBaseWidth;
const float targetLimitH = area.getHeight() - cornerSize2 - arrowBaseWidth * 2.0f;
if (Rectangle<float> (targetLimitX, 1.0f,
targetLimitW, area.getY() - 2.0f).contains (target))
{
outline.lineTo (target.x - arrowBaseWidth, area.getY());
outline.lineTo (target.x, target.y);
outline.lineTo (target.x + arrowBaseWidth, area.getY());
}
outline.lineTo (area.getRight() - cornerSize, area.getY());
outline.addArc (area.getRight() - cornerSize2, area.getY(), cornerSize2, cornerSize2, 0, float_Pi * 0.5f);
if (Rectangle<float> (area.getRight() + 1.0f, targetLimitY,
getWidth() - area.getRight() - 2.0f, targetLimitH).contains (target))
{
outline.lineTo (area.getRight(), target.y - arrowBaseWidth);
outline.lineTo (target.x, target.y);
outline.lineTo (area.getRight(), target.y + arrowBaseWidth);
}
outline.lineTo (area.getRight(), area.getBottom() - cornerSize);
outline.addArc (area.getRight() - cornerSize2, area.getBottom() - cornerSize2, cornerSize2, cornerSize2, float_Pi * 0.5f, float_Pi);
if (Rectangle<float> (targetLimitX, area.getBottom() + 1.0f,
targetLimitW, getHeight() - area.getBottom() - 2.0f).contains (target))
{
outline.lineTo (target.x + arrowBaseWidth, area.getBottom());
outline.lineTo (target.x, target.y);
outline.lineTo (target.x - arrowBaseWidth, area.getBottom());
}
outline.lineTo (area.getX() + cornerSize, area.getBottom());
outline.addArc (area.getX(), area.getBottom() - cornerSize2, cornerSize2, cornerSize2, float_Pi, float_Pi * 1.5f);
if (Rectangle<float> (1.0f, targetLimitY, area.getX() - 2.0f, targetLimitH).contains (target))
{
outline.lineTo (area.getX(), target.y + arrowBaseWidth);
outline.lineTo (target.x, target.y);
outline.lineTo (area.getX(), target.y - arrowBaseWidth);
}
outline.lineTo (area.getX(), area.getY() + cornerSize);
outline.addArc (area.getX(), area.getY(), cornerSize2, cornerSize2, float_Pi * 1.5f, float_Pi * 2.0f - 0.05f);
outline.closeSubPath();
outline.addBubble (content.getBounds().toFloat().expanded (gap, gap),
getLocalBounds().toFloat(),
targetPoint - getPosition().toFloat(),
9.0f, arrowSize * 0.7f);
}

+ 27
- 27
modules/juce_gui_extra/misc/juce_BubbleMessageComponent.cpp View File

@@ -31,17 +31,16 @@ BubbleMessageComponent::BubbleMessageComponent (int fadeOutLengthMs)
BubbleMessageComponent::~BubbleMessageComponent()
{
Desktop::getInstance().getAnimator().fadeOut (this, fadeOutLength);
}
void BubbleMessageComponent::showAt (int x, int y,
void BubbleMessageComponent::showAt (const Rectangle<int>& pos,
const AttributedString& text,
const int numMillisecondsBeforeRemoving,
const bool removeWhenMouseClicked,
const bool deleteSelfAfterUse)
{
createLayout (text);
setPosition (x, y);
setPosition (pos);
init (numMillisecondsBeforeRemoving, removeWhenMouseClicked, deleteSelfAfterUse);
}
@@ -65,55 +64,56 @@ void BubbleMessageComponent::init (const int numMillisecondsBeforeRemoving,
const bool removeWhenMouseClicked,
const bool deleteSelfAfterUse)
{
setAlpha (1.0f);
setVisible (true);
deleteAfterUse = deleteSelfAfterUse;
if (numMillisecondsBeforeRemoving > 0)
expiryTime = Time::getMillisecondCounter() + numMillisecondsBeforeRemoving;
else
expiryTime = 0;
startTimer (77);
expiryTime = numMillisecondsBeforeRemoving > 0
? (Time::getMillisecondCounter() + numMillisecondsBeforeRemoving) : 0;
mouseClickCounter = Desktop::getInstance().getMouseButtonClickCounter();
if (! (removeWhenMouseClicked && isShowing()))
mouseClickCounter += 0xfffff;
startTimer (77);
repaint();
}
const float bubblePaddingX = 20.0f;
const float bubblePaddingY = 14.0f;
void BubbleMessageComponent::getContentSize (int& w, int& h)
{
w = 20 + (int) textLayout.getWidth();
h = 20 + (int) textLayout.getHeight();
w = (int) (bubblePaddingX + textLayout.getWidth());
h = (int) (bubblePaddingY + textLayout.getHeight());
}
void BubbleMessageComponent::paintContent (Graphics& g, int w, int h)
{
g.setColour (findColour (TooltipWindow::textColourId));
textLayout.draw (g, Rectangle<float> (6.0f, 6.0f, w - 12.0f, h - 12.0f));
textLayout.draw (g, Rectangle<float> (bubblePaddingX / 2.0f, bubblePaddingY / 2.0f,
w - bubblePaddingX, h - bubblePaddingY));
}
void BubbleMessageComponent::timerCallback()
{
if (Desktop::getInstance().getMouseButtonClickCounter() > mouseClickCounter)
{
stopTimer();
hide (false);
else if (expiryTime != 0 && Time::getMillisecondCounter() > expiryTime)
hide (true);
}
void BubbleMessageComponent::hide (const bool fadeOut)
{
stopTimer();
if (fadeOut)
Desktop::getInstance().getAnimator().fadeOut (this, fadeOutLength);
else
setVisible (false);
if (deleteAfterUse)
delete this;
}
else if (expiryTime != 0 && Time::getMillisecondCounter() > expiryTime)
{
stopTimer();
if (deleteAfterUse)
delete this;
else
Desktop::getInstance().getAnimator().fadeOut (this, fadeOutLength);
}
if (deleteAfterUse)
delete this;
}

+ 3
- 3
modules/juce_gui_extra/misc/juce_BubbleMessageComponent.h View File

@@ -65,8 +65,7 @@ public:
For details about exactly how it decides where to position itself, see
BubbleComponent::updatePosition().
@param x the x co-ordinate of end of the bubble's tail
@param y the y co-ordinate of end of the bubble's tail
@param position the coords of the object to point to
@param message the text to display
@param numMillisecondsBeforeRemoving how long to leave it on the screen before removing itself
from its parent compnent. If this is 0 or less, it
@@ -76,7 +75,7 @@ public:
@param deleteSelfAfterUse if true, then the component will delete itself after
it becomes invisible
*/
void showAt (int x, int y,
void showAt (const Rectangle<int>& position,
const AttributedString& message,
int numMillisecondsBeforeRemoving,
bool removeWhenMouseClicked = true,
@@ -125,6 +124,7 @@ private:
void init (int numMillisecondsBeforeRemoving,
bool removeWhenMouseClicked,
bool deleteSelfAfterUse);
void hide (bool fadeOut);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BubbleMessageComponent);
};


Loading…
Cancel
Save