Browse Source

Fixed a couple of messaging problems on the mac; reduced the number of messages used by timers; improved ProgressBar performance; fixed a bug in ThreadWithProgressWindow; added tooltips to TreeView items; slightly tweaked the look of tooltips and improved their behaviour; stopped tab keystrokes being consumed unless they're needed; fixed a small bug in ZipFile.

tags/2021-05-28
jules 16 years ago
parent
commit
ec0557e7b6
16 changed files with 1716 additions and 1635 deletions
  1. +7
    -4
      build/macosx/platform_specific_code/juce_mac_MessageManager.mm
  2. +1435
    -1435
      extras/juce demo/src/demos/WidgetsDemo.cpp
  3. +129
    -96
      juce_amalgamated.cpp
  4. +10
    -3
      juce_amalgamated.h
  5. +1
    -1
      src/juce_appframework/events/juce_MessageManager.cpp
  6. +0
    -1
      src/juce_appframework/events/juce_Timer.cpp
  7. +9
    -3
      src/juce_appframework/gui/components/controls/juce_ProgressBar.cpp
  8. +1
    -0
      src/juce_appframework/gui/components/controls/juce_ProgressBar.h
  9. +21
    -1
      src/juce_appframework/gui/components/controls/juce_TreeView.cpp
  10. +5
    -0
      src/juce_appframework/gui/components/controls/juce_TreeView.h
  11. +6
    -6
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp
  12. +4
    -5
      src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp
  13. +6
    -8
      src/juce_appframework/gui/components/windows/juce_ThreadWithProgressWindow.cpp
  14. +77
    -68
      src/juce_appframework/gui/components/windows/juce_TooltipWindow.cpp
  15. +4
    -3
      src/juce_appframework/gui/components/windows/juce_TooltipWindow.h
  16. +1
    -1
      src/juce_core/misc/juce_ZipFile.cpp

+ 7
- 4
build/macosx/platform_specific_code/juce_mac_MessageManager.mm View File

@@ -254,12 +254,15 @@ static JuceAppDelegate* juceAppDelegate = 0;
void MessageManager::runDispatchLoop()
{
const ScopedAutoReleasePool pool;
if (! quitMessagePosted) // check that the quit message wasn't already posted..
{
const ScopedAutoReleasePool pool;
// must only be called by the message thread!
jassert (isThisTheMessageThread());
// must only be called by the message thread!
jassert (isThisTheMessageThread());
[NSApp run];
[NSApp run];
}
}
void MessageManager::stopDispatchLoop()


+ 1435
- 1435
extras/juce demo/src/demos/WidgetsDemo.cpp
File diff suppressed because it is too large
View File


+ 129
- 96
juce_amalgamated.cpp View File

@@ -8636,7 +8636,7 @@ public:

bool isExhausted() throw()
{
return pos >= zipEntryInfo.compressedSize;
return headerSize <= 0 || pos >= zipEntryInfo.compressedSize;
}

int64 getPosition() throw()
@@ -37043,7 +37043,7 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
{
if (MessageManager::instance->currentThreadHasLockedMessageManager())
{
locked = true; // either we're on the message thread, or this it's a re-entrant call.
locked = true; // either we're on the message thread, or this is a re-entrant call.
}
else
{
@@ -37422,7 +37422,6 @@ public:
addTimer (t);

const ScopedUnlock ul (lock);
callbackNeeded = false;

JUCE_TRY
{
@@ -44946,7 +44945,8 @@ BEGIN_JUCE_NAMESPACE

ProgressBar::ProgressBar (double& progress_)
: progress (progress_),
displayPercentage (true)
displayPercentage (true),
lastCallbackTime (0)
{
currentValue = jlimit (0.0, 1.0, progress);
}
@@ -45014,9 +45014,14 @@ void ProgressBar::timerCallback()
{
if (currentValue < newProgress
&& newProgress >= 0 && newProgress < 1.0
&& currentValue >= 0 && newProgress < 1.0)
&& currentValue >= 0 && currentValue < 1.0)
{
newProgress = jmin (currentValue + 0.02, newProgress);
const uint32 now = Time::getMillisecondCounter();
const int timeSinceLastCallback = (int) (now - lastCallbackTime);
lastCallbackTime = now;

newProgress = jmin (currentValue + 0.00018 * timeSinceLastCallback,
newProgress);
}

currentValue = newProgress;
@@ -51606,7 +51611,8 @@ END_JUCE_NAMESPACE

BEGIN_JUCE_NAMESPACE

class TreeViewContentComponent : public Component
class TreeViewContentComponent : public Component,
public TooltipClient
{
public:
TreeViewContentComponent (TreeView* const owner_)
@@ -51868,6 +51874,20 @@ public:
owner->itemsChanged();
}

const String getTooltip()
{
int x, y;
getMouseXYRelative (x, y);
Rectangle pos;

TreeViewItem* const item = findItemAt (y, pos);

if (item != 0)
return item->getTooltip();

return owner->getTooltip();
}

juce_UseDebuggingNewOperator

private:
@@ -52533,6 +52553,11 @@ void TreeViewItem::itemSelectionChanged (bool)
{
}

const String TreeViewItem::getTooltip()
{
return String::empty;
}

const String TreeViewItem::getDragSourceDescription()
{
return String::empty;
@@ -60487,10 +60512,8 @@ AlertWindow* LookAndFeel::createAlertWindow (const String& title,
aw->addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut);
aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut);
}
else
else if (numButtons == 3)
{
jassert (numButtons == 3);

aw->addButton (button1, 1, button1ShortCut);
aw->addButton (button2, 2, button2ShortCut);
aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0));
@@ -61571,7 +61594,7 @@ ImageEffectFilter* LookAndFeel::getSliderEffect()

static const TextLayout layoutTooltipText (const String& text) throw()
{
const float tooltipFontSize = 15.0f;
const float tooltipFontSize = 12.0f;
const int maxToolTipWidth = 400;

const Font f (tooltipFontSize, Font::bold);
@@ -61586,7 +61609,7 @@ void LookAndFeel::getTooltipSize (const String& tipText, int& width, int& height
const TextLayout tl (layoutTooltipText (tipText));

width = tl.getWidth() + 14;
height = tl.getHeight() + 10;
height = tl.getHeight() + 6;
}

void LookAndFeel::drawTooltip (Graphics& g, const String& text, int width, int height)
@@ -61595,8 +61618,10 @@ void LookAndFeel::drawTooltip (Graphics& g, const String& text, int width, int h

const Colour textCol (findColour (TooltipWindow::textColourId));

#if ! JUCE_MAC // The mac windows already have a non-optional 1 pix outline, so don't double it here..
g.setColour (findColour (TooltipWindow::outlineColourId));
g.drawRect (0, 0, width, height);
g.drawRect (0, 0, width, height, 1);
#endif

const TextLayout tl (layoutTooltipText (text));

@@ -72476,10 +72501,9 @@ bool ComponentPeer::handleKeyPress (const int keyCode,

if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0)
{
Component::getCurrentlyFocusedComponent()
->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown());

keyWasUsed = true;
Component* const currentlyFocused = Component::getCurrentlyFocusedComponent();
currentlyFocused->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown());
keyWasUsed = (currentlyFocused != Component::getCurrentlyFocusedComponent());
break;
}

@@ -73869,14 +73893,12 @@ ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title,
timeOutMsWhenCancelling (timeOutMsWhenCancelling_)
{
alertWindow = LookAndFeel::getDefaultLookAndFeel()
.createAlertWindow (title, String::empty, cancelButtonText, String::empty, String::empty,
AlertWindow::NoIcon, 1, 0);
.createAlertWindow (title, String::empty, cancelButtonText,
String::empty, String::empty,
AlertWindow::NoIcon, hasCancelButton ? 1 : 0, 0);

if (hasProgressBar)
alertWindow->addProgressBarComponent (progress);

if (hasCancelButton)
alertWindow->addButton (cancelButtonText, 1);
}

ThreadWithProgressWindow::~ThreadWithProgressWindow()
@@ -73895,13 +73917,13 @@ bool ThreadWithProgressWindow::runThread (const int priority)
alertWindow->setMessage (message);
}

const bool wasCancelled = alertWindow->runModalLoop() != 0;
const bool finishedNaturally = alertWindow->runModalLoop() != 0;

stopThread (timeOutMsWhenCancelling);

alertWindow->setVisible (false);

return ! wasCancelled;
return finishedNaturally;
}

void ThreadWithProgressWindow::setProgress (const double newProgress)
@@ -73920,7 +73942,7 @@ void ThreadWithProgressWindow::timerCallback()
if (! isThreadRunning())
{
// thread has finished normally..
alertWindow->exitModalState (0);
alertWindow->exitModalState (1);
alertWindow->setVisible (false);
}
else
@@ -73943,7 +73965,6 @@ TooltipWindow::TooltipWindow (Component* const parentComponent,
millisecondsBeforeTipAppears (millisecondsBeforeTipAppears_),
mouseX (0),
mouseY (0),
lastMouseMoveTime (0),
lastHideTime (0),
lastComponentUnderMouse (0),
changedCompsSinceShown (true)
@@ -73964,7 +73985,7 @@ TooltipWindow::~TooltipWindow()

void TooltipWindow::paint (Graphics& g)
{
getLookAndFeel().drawTooltip (g, tip, getWidth(), getHeight());
getLookAndFeel().drawTooltip (g, tipShowing, getWidth(), getHeight());
}

void TooltipWindow::mouseEnter (const MouseEvent&)
@@ -73972,104 +73993,113 @@ void TooltipWindow::mouseEnter (const MouseEvent&)
hide();
}

void TooltipWindow::showFor (Component* const c)
void TooltipWindow::showFor (Component* const c, const String& tip)
{
TooltipClient* const ttc = dynamic_cast <TooltipClient*> (c);
jassert (tip.isNotEmpty());
tipShowing = tip;

if (ttc != 0 && ! c->isCurrentlyBlockedByAnotherModalComponent())
tip = ttc->getTooltip();
else
tip = String::empty;
int mx, my;
Desktop::getMousePosition (mx, my);

if (tip.isEmpty())
{
hide();
}
else
{
int mx, my;
Desktop::getMousePosition (mx, my);
if (getParentComponent() != 0)
getParentComponent()->globalPositionToRelative (mx, my);

if (getParentComponent() != 0)
getParentComponent()->globalPositionToRelative (mx, my);
int x, y, w, h;
getLookAndFeel().getTooltipSize (tip, w, h);

int x, y, w, h;
getLookAndFeel().getTooltipSize (tip, w, h);
if (mx > getParentWidth() / 2)
x = mx - (w + 12);
else
x = mx + 24;

if (mx > getParentWidth() / 2)
x = mx - (w + 12);
else
x = mx + 24;
if (my > getParentHeight() / 2)
y = my - (h + 6);
else
y = my + 6;

if (my > getParentHeight() / 2)
y = my - (h + 6);
else
y = my + 6;
setBounds (x, y, w, h);
setVisible (true);

setBounds (x, y, w, h);
setVisible (true);
if (getParentComponent() == 0)
{
addToDesktop (ComponentPeer::windowHasDropShadow
| ComponentPeer::windowIsTemporary);
}

if (getParentComponent() == 0)
{
addToDesktop (ComponentPeer::windowHasDropShadow
| ComponentPeer::windowIsTemporary);
}
toFront (false);
}

toFront (false);
const String TooltipWindow::getTipFor (Component* const c)
{
if (c->isValidComponent() && Process::isForegroundProcess())
{
TooltipClient* const ttc = dynamic_cast <TooltipClient*> (c);

if (ttc != 0 && ! c->isCurrentlyBlockedByAnotherModalComponent())
return ttc->getTooltip();
}

return String::empty;
}

void TooltipWindow::hide()
{
tipShowing = String::empty;
removeFromDesktop();
setVisible (false);
}

void TooltipWindow::timerCallback()
{
const unsigned int now = Time::getApproximateMillisecondCounter();
Component* const newComp = Component::getComponentUnderMouse();
const String newTip (getTipFor (newComp));

const bool tipChanged = (newTip != lastTipUnderMouse || newComp != lastComponentUnderMouse);
lastComponentUnderMouse = newComp;
lastTipUnderMouse = newTip;

const int clickCount = Desktop::getInstance().getMouseButtonClickCounter();
const bool mouseWasClicked = clickCount > mouseClicks;
mouseClicks = clickCount;

int mx, my;
Desktop::getMousePosition (mx, my);
const bool mouseMovedQuickly = (abs (mx - mouseX) + abs (my - mouseY) > 12);
mouseX = mx;
mouseY = my;

const unsigned int now = Time::getApproximateMillisecondCounter();
Component* const underMouse = Component::getComponentUnderMouse();
const bool changedComp = (underMouse != lastComponentUnderMouse);
lastComponentUnderMouse = underMouse;
if (tipChanged || mouseWasClicked || mouseMovedQuickly)
lastCompChangeTime = now;

if (changedComp
|| abs (mx - mouseX) > 4
|| abs (my - mouseY) > 4
|| Desktop::getInstance().getMouseButtonClickCounter() > mouseClicks)
if (isVisible() || now < lastHideTime + 500)
{
lastMouseMoveTime = now;
if (isVisible())
// if a tip is currently visible (or has just disappeared), update to a new one
// immediately if needed..
if (newComp == 0 || mouseWasClicked || newTip.isEmpty())
{
lastHideTime = now;
hide();
if (isVisible())
{
lastHideTime = now;
hide();
}
}
else if (tipChanged)
{
showFor (newComp, newTip);
}

changedCompsSinceShown = changedCompsSinceShown || changedComp;

tip = String::empty;

mouseX = mx;
mouseY = my;
}

if (changedCompsSinceShown)
else
{
if ((now > lastMouseMoveTime + millisecondsBeforeTipAppears
|| now < lastHideTime + 500)
&& ! isVisible())
// if there isn't currently a tip, but one is needed, only let it
// appear after a timeout..
if (newTip.isNotEmpty()
&& newTip != tipShowing
&& now > lastCompChangeTime + millisecondsBeforeTipAppears)
{
if (underMouse->isValidComponent())
showFor (underMouse);

changedCompsSinceShown = false;
showFor (newComp, newTip);
}
}

mouseClicks = Desktop::getInstance().getMouseButtonClickCounter();
}

END_JUCE_NAMESPACE
@@ -270323,12 +270353,15 @@ static JuceAppDelegate* juceAppDelegate = 0;

void MessageManager::runDispatchLoop()
{
const ScopedAutoReleasePool pool;
if (! quitMessagePosted) // check that the quit message wasn't already posted..
{
const ScopedAutoReleasePool pool;

// must only be called by the message thread!
jassert (isThisTheMessageThread());
// must only be called by the message thread!
jassert (isThisTheMessageThread());

[NSApp run];
[NSApp run];
}
}

void MessageManager::stopDispatchLoop()


+ 10
- 3
juce_amalgamated.h View File

@@ -29942,16 +29942,17 @@ private:

const int millisecondsBeforeTipAppears;
int mouseX, mouseY, mouseClicks;
unsigned int lastMouseMoveTime, lastHideTime;
unsigned int lastCompChangeTime, lastHideTime;
Component* lastComponentUnderMouse;
bool changedCompsSinceShown;
String tip;
String tipShowing, lastTipUnderMouse;

void paint (Graphics& g);
void mouseEnter (const MouseEvent& e);
void timerCallback();

void showFor (Component* const c);
static const String getTipFor (Component* const c);
void showFor (Component* const c, const String& tip);
void hide();

TooltipWindow (const TooltipWindow&);
@@ -43355,6 +43356,11 @@ public:
*/
virtual void itemSelectionChanged (bool isNowSelected);

/** The item can return a tool tip string here if it wants to.
@see TooltipClient
*/
virtual const String getTooltip();

/** To allow items from your treeview to be dragged-and-dropped, implement this method.

If this returns a non-empty name then when the user drags an item, the treeview will
@@ -45947,6 +45953,7 @@ private:
double currentValue;
bool displayPercentage;
String displayedMessage, currentMessage;
uint32 lastCallbackTime;

void timerCallback();



+ 1
- 1
src/juce_appframework/events/juce_MessageManager.cpp View File

@@ -278,7 +278,7 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
{
if (MessageManager::instance->currentThreadHasLockedMessageManager())
{
locked = true; // either we're on the message thread, or this it's a re-entrant call.
locked = true; // either we're on the message thread, or this is a re-entrant call.
}
else
{


+ 0
- 1
src/juce_appframework/events/juce_Timer.cpp View File

@@ -247,7 +247,6 @@ public:
addTimer (t);
const ScopedUnlock ul (lock);
callbackNeeded = false;
JUCE_TRY
{


+ 9
- 3
src/juce_appframework/gui/components/controls/juce_ProgressBar.cpp View File

@@ -40,7 +40,8 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
ProgressBar::ProgressBar (double& progress_)
: progress (progress_),
displayPercentage (true)
displayPercentage (true),
lastCallbackTime (0)
{
currentValue = jlimit (0.0, 1.0, progress);
}
@@ -109,9 +110,14 @@ void ProgressBar::timerCallback()
{
if (currentValue < newProgress
&& newProgress >= 0 && newProgress < 1.0
&& currentValue >= 0 && newProgress < 1.0)
&& currentValue >= 0 && currentValue < 1.0)
{
newProgress = jmin (currentValue + 0.02, newProgress);
const uint32 now = Time::getMillisecondCounter();
const int timeSinceLastCallback = (int) (now - lastCallbackTime);
lastCallbackTime = now;
newProgress = jmin (currentValue + 0.00018 * timeSinceLastCallback,
newProgress);
}
currentValue = newProgress;


+ 1
- 0
src/juce_appframework/gui/components/controls/juce_ProgressBar.h View File

@@ -119,6 +119,7 @@ private:
double currentValue;
bool displayPercentage;
String displayedMessage, currentMessage;
uint32 lastCallbackTime;
void timerCallback();


+ 21
- 1
src/juce_appframework/gui/components/controls/juce_TreeView.cpp View File

@@ -41,7 +41,8 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
class TreeViewContentComponent : public Component
class TreeViewContentComponent : public Component,
public TooltipClient
{
public:
TreeViewContentComponent (TreeView* const owner_)
@@ -303,6 +304,20 @@ public:
owner->itemsChanged();
}
const String getTooltip()
{
int x, y;
getMouseXYRelative (x, y);
Rectangle pos;
TreeViewItem* const item = findItemAt (y, pos);
if (item != 0)
return item->getTooltip();
return owner->getTooltip();
}
//==============================================================================
juce_UseDebuggingNewOperator
@@ -980,6 +995,11 @@ void TreeViewItem::itemSelectionChanged (bool)
{
}
const String TreeViewItem::getTooltip()
{
return String::empty;
}
const String TreeViewItem::getDragSourceDescription()
{
return String::empty;


+ 5
- 0
src/juce_appframework/gui/components/controls/juce_TreeView.h View File

@@ -337,6 +337,11 @@ public:
*/
virtual void itemSelectionChanged (bool isNowSelected);
/** The item can return a tool tip string here if it wants to.
@see TooltipClient
*/
virtual const String getTooltip();
/** To allow items from your treeview to be dragged-and-dropped, implement this method.
If this returns a non-empty name then when the user drags an item, the treeview will


+ 6
- 6
src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp View File

@@ -495,10 +495,8 @@ AlertWindow* LookAndFeel::createAlertWindow (const String& title,
aw->addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut);
aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut);
}
else
else if (numButtons == 3)
{
jassert (numButtons == 3);
aw->addButton (button1, 1, button1ShortCut);
aw->addButton (button2, 2, button2ShortCut);
aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0));
@@ -1591,7 +1589,7 @@ ImageEffectFilter* LookAndFeel::getSliderEffect()
//==============================================================================
static const TextLayout layoutTooltipText (const String& text) throw()
{
const float tooltipFontSize = 15.0f;
const float tooltipFontSize = 12.0f;
const int maxToolTipWidth = 400;
const Font f (tooltipFontSize, Font::bold);
@@ -1606,7 +1604,7 @@ void LookAndFeel::getTooltipSize (const String& tipText, int& width, int& height
const TextLayout tl (layoutTooltipText (tipText));
width = tl.getWidth() + 14;
height = tl.getHeight() + 10;
height = tl.getHeight() + 6;
}
void LookAndFeel::drawTooltip (Graphics& g, const String& text, int width, int height)
@@ -1615,8 +1613,10 @@ void LookAndFeel::drawTooltip (Graphics& g, const String& text, int width, int h
const Colour textCol (findColour (TooltipWindow::textColourId));
#if ! JUCE_MAC // The mac windows already have a non-optional 1 pix outline, so don't double it here..
g.setColour (findColour (TooltipWindow::outlineColourId));
g.drawRect (0, 0, width, height);
g.drawRect (0, 0, width, height, 1);
#endif
const TextLayout tl (layoutTooltipText (text));


+ 4
- 5
src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp View File

@@ -461,13 +461,12 @@ bool ComponentPeer::handleKeyPress (const int keyCode,
if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0)
{
Component::getCurrentlyFocusedComponent()
->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown());
keyWasUsed = true;
Component* const currentlyFocused = Component::getCurrentlyFocusedComponent();
currentlyFocused->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown());
keyWasUsed = (currentlyFocused != Component::getCurrentlyFocusedComponent());
break;
}
target = target->parentComponent_;
}


+ 6
- 8
src/juce_appframework/gui/components/windows/juce_ThreadWithProgressWindow.cpp View File

@@ -50,14 +50,12 @@ ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title,
timeOutMsWhenCancelling (timeOutMsWhenCancelling_)
{
alertWindow = LookAndFeel::getDefaultLookAndFeel()
.createAlertWindow (title, String::empty, cancelButtonText, String::empty, String::empty,
AlertWindow::NoIcon, 1, 0);
.createAlertWindow (title, String::empty, cancelButtonText,
String::empty, String::empty,
AlertWindow::NoIcon, hasCancelButton ? 1 : 0, 0);
if (hasProgressBar)
alertWindow->addProgressBarComponent (progress);
if (hasCancelButton)
alertWindow->addButton (cancelButtonText, 1);
}
ThreadWithProgressWindow::~ThreadWithProgressWindow()
@@ -76,13 +74,13 @@ bool ThreadWithProgressWindow::runThread (const int priority)
alertWindow->setMessage (message);
}
const bool wasCancelled = alertWindow->runModalLoop() != 0;
const bool finishedNaturally = alertWindow->runModalLoop() != 0;
stopThread (timeOutMsWhenCancelling);
alertWindow->setVisible (false);
return ! wasCancelled;
return finishedNaturally;
}
void ThreadWithProgressWindow::setProgress (const double newProgress)
@@ -101,7 +99,7 @@ void ThreadWithProgressWindow::timerCallback()
if (! isThreadRunning())
{
// thread has finished normally..
alertWindow->exitModalState (0);
alertWindow->exitModalState (1);
alertWindow->setVisible (false);
}
else


+ 77
- 68
src/juce_appframework/gui/components/windows/juce_TooltipWindow.cpp View File

@@ -36,6 +36,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_TooltipWindow.h"
#include "../../../../juce_core/basics/juce_Time.h"
#include "../../../../juce_core/threads/juce_Process.h"
#include "../lookandfeel/juce_LookAndFeel.h"
#include "../juce_Desktop.h"
@@ -47,7 +48,6 @@ TooltipWindow::TooltipWindow (Component* const parentComponent,
millisecondsBeforeTipAppears (millisecondsBeforeTipAppears_),
mouseX (0),
mouseY (0),
lastMouseMoveTime (0),
lastHideTime (0),
lastComponentUnderMouse (0),
changedCompsSinceShown (true)
@@ -68,7 +68,7 @@ TooltipWindow::~TooltipWindow()
void TooltipWindow::paint (Graphics& g)
{
getLookAndFeel().drawTooltip (g, tip, getWidth(), getHeight());
getLookAndFeel().drawTooltip (g, tipShowing, getWidth(), getHeight());
}
void TooltipWindow::mouseEnter (const MouseEvent&)
@@ -76,104 +76,113 @@ void TooltipWindow::mouseEnter (const MouseEvent&)
hide();
}
void TooltipWindow::showFor (Component* const c)
void TooltipWindow::showFor (Component* const c, const String& tip)
{
TooltipClient* const ttc = dynamic_cast <TooltipClient*> (c);
jassert (tip.isNotEmpty());
tipShowing = tip;
int mx, my;
Desktop::getMousePosition (mx, my);
if (ttc != 0 && ! c->isCurrentlyBlockedByAnotherModalComponent())
tip = ttc->getTooltip();
else
tip = String::empty;
if (getParentComponent() != 0)
getParentComponent()->globalPositionToRelative (mx, my);
if (tip.isEmpty())
{
hide();
}
else
{
int mx, my;
Desktop::getMousePosition (mx, my);
int x, y, w, h;
getLookAndFeel().getTooltipSize (tip, w, h);
if (getParentComponent() != 0)
getParentComponent()->globalPositionToRelative (mx, my);
if (mx > getParentWidth() / 2)
x = mx - (w + 12);
else
x = mx + 24;
int x, y, w, h;
getLookAndFeel().getTooltipSize (tip, w, h);
if (my > getParentHeight() / 2)
y = my - (h + 6);
else
y = my + 6;
if (mx > getParentWidth() / 2)
x = mx - (w + 12);
else
x = mx + 24;
setBounds (x, y, w, h);
setVisible (true);
if (my > getParentHeight() / 2)
y = my - (h + 6);
else
y = my + 6;
if (getParentComponent() == 0)
{
addToDesktop (ComponentPeer::windowHasDropShadow
| ComponentPeer::windowIsTemporary);
}
setBounds (x, y, w, h);
setVisible (true);
toFront (false);
}
if (getParentComponent() == 0)
{
addToDesktop (ComponentPeer::windowHasDropShadow
| ComponentPeer::windowIsTemporary);
}
const String TooltipWindow::getTipFor (Component* const c)
{
if (c->isValidComponent() && Process::isForegroundProcess())
{
TooltipClient* const ttc = dynamic_cast <TooltipClient*> (c);
toFront (false);
if (ttc != 0 && ! c->isCurrentlyBlockedByAnotherModalComponent())
return ttc->getTooltip();
}
return String::empty;
}
void TooltipWindow::hide()
{
tipShowing = String::empty;
removeFromDesktop();
setVisible (false);
}
void TooltipWindow::timerCallback()
{
const unsigned int now = Time::getApproximateMillisecondCounter();
Component* const newComp = Component::getComponentUnderMouse();
const String newTip (getTipFor (newComp));
const bool tipChanged = (newTip != lastTipUnderMouse || newComp != lastComponentUnderMouse);
lastComponentUnderMouse = newComp;
lastTipUnderMouse = newTip;
const int clickCount = Desktop::getInstance().getMouseButtonClickCounter();
const bool mouseWasClicked = clickCount > mouseClicks;
mouseClicks = clickCount;
int mx, my;
Desktop::getMousePosition (mx, my);
const bool mouseMovedQuickly = (abs (mx - mouseX) + abs (my - mouseY) > 12);
mouseX = mx;
mouseY = my;
const unsigned int now = Time::getApproximateMillisecondCounter();
Component* const underMouse = Component::getComponentUnderMouse();
const bool changedComp = (underMouse != lastComponentUnderMouse);
lastComponentUnderMouse = underMouse;
if (changedComp
|| abs (mx - mouseX) > 4
|| abs (my - mouseY) > 4
|| Desktop::getInstance().getMouseButtonClickCounter() > mouseClicks)
{
lastMouseMoveTime = now;
if (tipChanged || mouseWasClicked || mouseMovedQuickly)
lastCompChangeTime = now;
if (isVisible())
if (isVisible() || now < lastHideTime + 500)
{
// if a tip is currently visible (or has just disappeared), update to a new one
// immediately if needed..
if (newComp == 0 || mouseWasClicked || newTip.isEmpty())
{
lastHideTime = now;
hide();
if (isVisible())
{
lastHideTime = now;
hide();
}
}
else if (tipChanged)
{
showFor (newComp, newTip);
}
changedCompsSinceShown = changedCompsSinceShown || changedComp;
tip = String::empty;
mouseX = mx;
mouseY = my;
}
if (changedCompsSinceShown)
else
{
if ((now > lastMouseMoveTime + millisecondsBeforeTipAppears
|| now < lastHideTime + 500)
&& ! isVisible())
// if there isn't currently a tip, but one is needed, only let it
// appear after a timeout..
if (newTip.isNotEmpty()
&& newTip != tipShowing
&& now > lastCompChangeTime + millisecondsBeforeTipAppears)
{
if (underMouse->isValidComponent())
showFor (underMouse);
changedCompsSinceShown = false;
showFor (newComp, newTip);
}
}
mouseClicks = Desktop::getInstance().getMouseButtonClickCounter();
}
END_JUCE_NAMESPACE

+ 4
- 3
src/juce_appframework/gui/components/windows/juce_TooltipWindow.h View File

@@ -101,16 +101,17 @@ private:
//==============================================================================
const int millisecondsBeforeTipAppears;
int mouseX, mouseY, mouseClicks;
unsigned int lastMouseMoveTime, lastHideTime;
unsigned int lastCompChangeTime, lastHideTime;
Component* lastComponentUnderMouse;
bool changedCompsSinceShown;
String tip;
String tipShowing, lastTipUnderMouse;
void paint (Graphics& g);
void mouseEnter (const MouseEvent& e);
void timerCallback();
void showFor (Component* const c);
static const String getTipFor (Component* const c);
void showFor (Component* const c, const String& tip);
void hide();
TooltipWindow (const TooltipWindow&);


+ 1
- 1
src/juce_core/misc/juce_ZipFile.cpp View File

@@ -137,7 +137,7 @@ public:
bool isExhausted() throw()
{
return pos >= zipEntryInfo.compressedSize;
return headerSize <= 0 || pos >= zipEntryInfo.compressedSize;
}
int64 getPosition() throw()


Loading…
Cancel
Save