@@ -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() | |||
@@ -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() | |||
@@ -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(); | |||
@@ -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 | |||
{ | |||
@@ -247,7 +247,6 @@ public: | |||
addTimer (t); | |||
const ScopedUnlock ul (lock); | |||
callbackNeeded = false; | |||
JUCE_TRY | |||
{ | |||
@@ -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; | |||
@@ -119,6 +119,7 @@ private: | |||
double currentValue; | |||
bool displayPercentage; | |||
String displayedMessage, currentMessage; | |||
uint32 lastCallbackTime; | |||
void timerCallback(); | |||
@@ -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; | |||
@@ -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 | |||
@@ -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)); | |||
@@ -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_; | |||
} | |||
@@ -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 | |||
@@ -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 |
@@ -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&); | |||
@@ -137,7 +137,7 @@ public: | |||
bool isExhausted() throw() | |||
{ | |||
return pos >= zipEntryInfo.compressedSize; | |||
return headerSize <= 0 || pos >= zipEntryInfo.compressedSize; | |||
} | |||
int64 getPosition() throw() | |||