- Library code update
- project update (added Eigen) git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@94 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -53,24 +53,24 @@
|
||||
MyJUCEApp() {}
|
||||
~MyJUCEApp() {}
|
||||
|
||||
void initialise (const String& commandLine)
|
||||
void initialise (const String& commandLine) override
|
||||
{
|
||||
myMainWindow = new MyApplicationWindow();
|
||||
myMainWindow->setBounds (100, 100, 400, 500);
|
||||
myMainWindow->setVisible (true);
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
void shutdown() override
|
||||
{
|
||||
myMainWindow = nullptr;
|
||||
}
|
||||
|
||||
const String getApplicationName()
|
||||
const String getApplicationName() override
|
||||
{
|
||||
return "Super JUCE-o-matic";
|
||||
}
|
||||
|
||||
const String getApplicationVersion()
|
||||
const String getApplicationVersion() override
|
||||
{
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
@@ -125,11 +125,12 @@ void Button::setTooltip (const String& newTooltip)
|
||||
generateTooltip = false;
|
||||
}
|
||||
|
||||
String Button::getTooltip()
|
||||
void Button::updateAutomaticTooltip (const ApplicationCommandInfo& info)
|
||||
{
|
||||
if (generateTooltip && commandManagerToUse != nullptr && commandID != 0)
|
||||
if (generateTooltip && commandManagerToUse != nullptr)
|
||||
{
|
||||
String tt (commandManagerToUse->getDescriptionOfCommand (commandID));
|
||||
String tt (info.description.isNotEmpty() ? info.description
|
||||
: info.shortName);
|
||||
|
||||
Array<KeyPress> keyPresses (commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID));
|
||||
|
||||
@@ -145,10 +146,8 @@ String Button::getTooltip()
|
||||
tt << key << ']';
|
||||
}
|
||||
|
||||
return tt;
|
||||
SettableTooltipClient::setTooltip (tt);
|
||||
}
|
||||
|
||||
return SettableTooltipClient::getTooltip();
|
||||
}
|
||||
|
||||
void Button::setConnectedEdges (const int newFlags)
|
||||
@@ -542,6 +541,7 @@ void Button::applicationCommandListChangeCallback()
|
||||
|
||||
if (commandManagerToUse->getTargetForCommand (commandID, info) != nullptr)
|
||||
{
|
||||
updateAutomaticTooltip (info);
|
||||
setEnabled ((info.flags & ApplicationCommandInfo::isDisabled) == 0);
|
||||
setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, dontSendNotification);
|
||||
}
|
||||
|
||||
@@ -277,12 +277,6 @@ public:
|
||||
*/
|
||||
void setTooltip (const String& newTooltip) override;
|
||||
|
||||
/** Returns the tooltip set by setTooltip(), or the description corresponding to
|
||||
the currently mapped command if one is enabled (see setCommandToTrigger).
|
||||
*/
|
||||
String getTooltip() override;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** A combination of these flags are used by setConnectedEdges(). */
|
||||
enum ConnectedEdgeFlags
|
||||
@@ -349,6 +343,9 @@ public:
|
||||
*/
|
||||
void setState (ButtonState newState);
|
||||
|
||||
/** Returns the button's current over/down/up state. */
|
||||
ButtonState getState() const noexcept { return buttonState; }
|
||||
|
||||
// This method's parameters have changed - see the new version.
|
||||
JUCE_DEPRECATED (void setToggleState (bool, bool));
|
||||
|
||||
@@ -363,9 +360,8 @@ public:
|
||||
virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
|
||||
bool isMouseOverButton, bool isButtonDown) = 0;
|
||||
|
||||
virtual Font getTextButtonFont (TextButton&) = 0;
|
||||
|
||||
virtual void changeTextButtonWidthToFitText (TextButton&, int newHeight) = 0;
|
||||
virtual Font getTextButtonFont (TextButton&, int buttonHeight) = 0;
|
||||
virtual int getTextButtonWidthToFitText (TextButton&, int buttonHeight) = 0;
|
||||
|
||||
/** Draws the text for a TextButton. */
|
||||
virtual void drawButtonText (Graphics&, TextButton&, bool isMouseOverButton, bool isButtonDown) = 0;
|
||||
@@ -379,6 +375,13 @@ public:
|
||||
bool ticked, bool isEnabled, bool isMouseOverButton, bool isButtonDown) = 0;
|
||||
|
||||
virtual void drawDrawableButton (Graphics&, DrawableButton&, bool isMouseOverButton, bool isButtonDown) = 0;
|
||||
|
||||
private:
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// These method have been deprecated: see their replacements above.
|
||||
virtual int getTextButtonFont (TextButton&) { return 0; }
|
||||
virtual int changeTextButtonWidthToFitText (TextButton&, int) { return 0; }
|
||||
#endif
|
||||
};
|
||||
|
||||
protected:
|
||||
@@ -489,6 +492,7 @@ private:
|
||||
void repeatTimerCallback();
|
||||
bool keyStateChangedCallback();
|
||||
void applicationCommandListChangeCallback();
|
||||
void updateAutomaticTooltip (const ApplicationCommandInfo&);
|
||||
|
||||
ButtonState updateState();
|
||||
ButtonState updateState (bool isOver, bool isDown);
|
||||
|
||||
@@ -80,6 +80,31 @@ void DrawableButton::setEdgeIndent (const int numPixelsIndent)
|
||||
resized();
|
||||
}
|
||||
|
||||
Rectangle<float> DrawableButton::getImageBounds() const
|
||||
{
|
||||
Rectangle<int> r (getLocalBounds());
|
||||
|
||||
if (style != ImageStretched)
|
||||
{
|
||||
int indentX = jmin (edgeIndent, proportionOfWidth (0.3f));
|
||||
int indentY = jmin (edgeIndent, proportionOfHeight (0.3f));
|
||||
|
||||
if (style == ImageOnButtonBackground)
|
||||
{
|
||||
indentX = jmax (getWidth() / 4, indentX);
|
||||
indentY = jmax (getHeight() / 4, indentY);
|
||||
}
|
||||
else if (style == ImageAboveTextLabel)
|
||||
{
|
||||
r = r.withTrimmedBottom (jmin (16, proportionOfHeight (0.25f)));
|
||||
}
|
||||
|
||||
r = r.reduced (indentX, indentY);
|
||||
}
|
||||
|
||||
return r.toFloat();
|
||||
}
|
||||
|
||||
void DrawableButton::resized()
|
||||
{
|
||||
Button::resized();
|
||||
@@ -87,36 +112,11 @@ void DrawableButton::resized()
|
||||
if (currentImage != nullptr)
|
||||
{
|
||||
if (style == ImageRaw)
|
||||
{
|
||||
currentImage->setOriginWithOriginalSize (Point<float>());
|
||||
}
|
||||
else if (style == ImageStretched)
|
||||
{
|
||||
currentImage->setTransformToFit (getLocalBounds().toFloat(), RectanglePlacement::stretchToFit);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle<int> imageSpace;
|
||||
|
||||
const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f));
|
||||
const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f));
|
||||
|
||||
if (style == ImageOnButtonBackground)
|
||||
{
|
||||
imageSpace = getLocalBounds().reduced (jmax (getWidth() / 4, indentX),
|
||||
jmax (getHeight() / 4, indentY));
|
||||
}
|
||||
else
|
||||
{
|
||||
const int textH = (style == ImageAboveTextLabel) ? jmin (16, proportionOfHeight (0.25f)) : 0;
|
||||
|
||||
imageSpace.setBounds (indentX, indentY,
|
||||
getWidth() - indentX * 2,
|
||||
getHeight() - indentY * 2 - textH);
|
||||
}
|
||||
|
||||
currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred);
|
||||
}
|
||||
currentImage->setTransformToFit (getImageBounds(),
|
||||
style == ImageStretched ? RectanglePlacement::stretchToFit
|
||||
: RectanglePlacement::centred);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ void DrawableButton::buttonStateChanged()
|
||||
{
|
||||
currentImage->setInterceptsMouseClicks (false, false);
|
||||
addAndMakeVisible (currentImage);
|
||||
DrawableButton::resized();
|
||||
resized();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,9 @@ public:
|
||||
/** Returns the image that the button will use when the mouse is held down on it. */
|
||||
Drawable* getDownImage() const noexcept;
|
||||
|
||||
/** Can be overridden to specify a custom position for the image within the button. */
|
||||
virtual Rectangle<float> getImageBounds() const;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the link.
|
||||
|
||||
@@ -173,8 +176,8 @@ public:
|
||||
private:
|
||||
//==============================================================================
|
||||
ButtonStyle style;
|
||||
ScopedPointer <Drawable> normalImage, overImage, downImage, disabledImage,
|
||||
normalImageOn, overImageOn, downImageOn, disabledImageOn;
|
||||
ScopedPointer<Drawable> normalImage, overImage, downImage, disabledImage,
|
||||
normalImageOn, overImageOn, downImageOn, disabledImageOn;
|
||||
Drawable* currentImage;
|
||||
int edgeIndent;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
@@ -26,8 +25,11 @@ TextButton::TextButton() : Button (String())
|
||||
{
|
||||
}
|
||||
|
||||
TextButton::TextButton (const String& name, const String& toolTip)
|
||||
: Button (name)
|
||||
TextButton::TextButton (const String& name) : Button (name)
|
||||
{
|
||||
}
|
||||
|
||||
TextButton::TextButton (const String& name, const String& toolTip) : Button (name)
|
||||
{
|
||||
setTooltip (toolTip);
|
||||
}
|
||||
@@ -52,12 +54,17 @@ void TextButton::colourChanged()
|
||||
repaint();
|
||||
}
|
||||
|
||||
Font TextButton::getFont()
|
||||
void TextButton::changeWidthToFitText()
|
||||
{
|
||||
return Font (jmin (15.0f, getHeight() * 0.6f));
|
||||
changeWidthToFitText (getHeight());
|
||||
}
|
||||
|
||||
void TextButton::changeWidthToFitText (const int newHeight)
|
||||
{
|
||||
getLookAndFeel().changeTextButtonWidthToFitText (*this, newHeight);
|
||||
setSize (getBestWidthForHeight (newHeight), newHeight);
|
||||
}
|
||||
|
||||
int TextButton::getBestWidthForHeight (int buttonHeight)
|
||||
{
|
||||
return getLookAndFeel().getTextButtonWidthToFitText (*this, buttonHeight);
|
||||
}
|
||||
|
||||
@@ -44,11 +44,16 @@ public:
|
||||
@param buttonName the text to put in the button (the component's name is also
|
||||
initially set to this string, but these can be changed later
|
||||
using the setName() and setButtonText() methods)
|
||||
@param toolTip an optional string to use as a toolip
|
||||
@see Button
|
||||
*/
|
||||
explicit TextButton (const String& buttonName,
|
||||
const String& toolTip = String::empty);
|
||||
explicit TextButton (const String& buttonName);
|
||||
|
||||
/** Creates a TextButton.
|
||||
@param buttonName the text to put in the button (the component's name is also
|
||||
initially set to this string, but these can be changed later
|
||||
using the setName() and setButtonText() methods)
|
||||
@param toolTip an optional string to use as a toolip
|
||||
*/
|
||||
TextButton (const String& buttonName, const String& toolTip);
|
||||
|
||||
/** Destructor. */
|
||||
~TextButton();
|
||||
@@ -74,17 +79,20 @@ public:
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Resizes the button to fit neatly around its current text.
|
||||
If newHeight is >= 0, the button's height will be changed to this
|
||||
value. If it's less than zero, its height will be unaffected.
|
||||
/** Changes this button's width to fit neatly around its current text, without
|
||||
changing its height.
|
||||
*/
|
||||
void changeWidthToFitText (int newHeight = -1);
|
||||
void changeWidthToFitText();
|
||||
|
||||
/** This can be overridden to use different fonts than the default one.
|
||||
Note that you'll need to set the font's size appropriately, too.
|
||||
/** Resizes the button's width to fit neatly around its current text, and gives it
|
||||
the specified height.
|
||||
*/
|
||||
virtual Font getFont();
|
||||
void changeWidthToFitText (int newHeight);
|
||||
|
||||
/** Returns the width that the LookAndFeel suggests would be best for this button if it
|
||||
had the given height.
|
||||
*/
|
||||
int getBestWidthForHeight (int buttonHeight);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
@@ -93,6 +101,11 @@ public:
|
||||
void colourChanged() override;
|
||||
|
||||
private:
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// Note that this method has been removed - instead, see LookAndFeel::getTextButtonWidthToFitText()
|
||||
virtual int getFont() { return 0; }
|
||||
#endif
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextButton)
|
||||
};
|
||||
|
||||
|
||||
+25
-14
@@ -51,7 +51,20 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n
|
||||
// the name isn't optional!
|
||||
jassert (newCommand.shortName.isNotEmpty());
|
||||
|
||||
if (getCommandForID (newCommand.commandID) == 0)
|
||||
if (ApplicationCommandInfo* command = getMutableCommandForID (newCommand.commandID))
|
||||
{
|
||||
// Trying to re-register the same command ID with different parameters can often indicate a typo.
|
||||
// This assertion is here because I've found it useful catching some mistakes, but it may also cause
|
||||
// false alarms if you're deliberately updating some flags for a command.
|
||||
jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName
|
||||
&& newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName
|
||||
&& newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses
|
||||
&& (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))
|
||||
== (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)));
|
||||
|
||||
*command = newCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationCommandInfo* const newInfo = new ApplicationCommandInfo (newCommand);
|
||||
newInfo->flags &= ~ApplicationCommandInfo::isTicked;
|
||||
@@ -61,16 +74,6 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n
|
||||
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// trying to re-register the same command ID with different parameters?
|
||||
jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName
|
||||
&& (newCommand.description == getCommandForID (newCommand.commandID)->description || newCommand.description.isEmpty())
|
||||
&& newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName
|
||||
&& newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses
|
||||
&& (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))
|
||||
== (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)));
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationCommandManager::registerAllCommandsForTarget (ApplicationCommandTarget* target)
|
||||
@@ -113,7 +116,7 @@ void ApplicationCommandManager::commandStatusChanged()
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept
|
||||
ApplicationCommandInfo* ApplicationCommandManager::getMutableCommandForID (CommandID commandID) const noexcept
|
||||
{
|
||||
for (int i = commands.size(); --i >= 0;)
|
||||
if (commands.getUnchecked(i)->commandID == commandID)
|
||||
@@ -122,6 +125,11 @@ const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept
|
||||
{
|
||||
return getMutableCommandForID (commandID);
|
||||
}
|
||||
|
||||
String ApplicationCommandManager::getNameOfCommand (const CommandID commandID) const noexcept
|
||||
{
|
||||
if (const ApplicationCommandInfo* const ci = getCommandForID (commandID))
|
||||
@@ -215,7 +223,10 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const
|
||||
target = target->getTargetForCommand (commandID);
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
upToDateInfo.commandID = commandID;
|
||||
target->getCommandInfo (commandID, upToDateInfo);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -223,7 +234,7 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const
|
||||
//==============================================================================
|
||||
ApplicationCommandTarget* ApplicationCommandManager::findTargetForComponent (Component* c)
|
||||
{
|
||||
ApplicationCommandTarget* target = dynamic_cast <ApplicationCommandTarget*> (c);
|
||||
ApplicationCommandTarget* target = dynamic_cast<ApplicationCommandTarget*> (c);
|
||||
|
||||
if (target == nullptr && c != nullptr)
|
||||
target = c->findParentComponentOfClass<ApplicationCommandTarget>();
|
||||
@@ -263,7 +274,7 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget(
|
||||
// component that really should get the event. And if not, the event will
|
||||
// still be passed up to the top level window anyway, so let's send it to the
|
||||
// content comp.
|
||||
if (ResizableWindow* const resizableWindow = dynamic_cast <ResizableWindow*> (c))
|
||||
if (ResizableWindow* const resizableWindow = dynamic_cast<ResizableWindow*> (c))
|
||||
if (Component* const content = resizableWindow->getContentComponent())
|
||||
c = content;
|
||||
|
||||
|
||||
@@ -308,6 +308,7 @@ private:
|
||||
void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo&);
|
||||
void handleAsyncUpdate() override;
|
||||
void globalFocusChanged (Component*) override;
|
||||
ApplicationCommandInfo* getMutableCommandForID (CommandID) const noexcept;
|
||||
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// This is just here to cause a compile error in old code that hasn't been changed to use the new
|
||||
|
||||
@@ -91,7 +91,7 @@ ApplicationCommandTarget* ApplicationCommandTarget::getTargetForCommand (const C
|
||||
|
||||
while (target != nullptr)
|
||||
{
|
||||
Array <CommandID> commandIDs;
|
||||
Array<CommandID> commandIDs;
|
||||
target->getAllCommands (commandIDs);
|
||||
|
||||
if (commandIDs.contains (commandID))
|
||||
@@ -113,7 +113,7 @@ ApplicationCommandTarget* ApplicationCommandTarget::getTargetForCommand (const C
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
Array <CommandID> commandIDs;
|
||||
Array<CommandID> commandIDs;
|
||||
target->getAllCommands (commandIDs);
|
||||
|
||||
if (commandIDs.contains (commandID))
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
Your target should add all the command IDs that it handles to the array that is
|
||||
passed-in.
|
||||
*/
|
||||
virtual void getAllCommands (Array <CommandID>& commands) = 0;
|
||||
virtual void getAllCommands (Array<CommandID>& commands) = 0;
|
||||
|
||||
/** This must provide details about one of the commands that this target can perform.
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ bool KeyPressMappingSet::restoreFromXml (const XmlElement& xmlVersion)
|
||||
|
||||
XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefaultSet) const
|
||||
{
|
||||
ScopedPointer <KeyPressMappingSet> defaultSet;
|
||||
ScopedPointer<KeyPressMappingSet> defaultSet;
|
||||
|
||||
if (saveDifferencesFromDefaultSet)
|
||||
{
|
||||
|
||||
@@ -22,12 +22,6 @@
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define CHECK_MESSAGE_MANAGER_IS_LOCKED \
|
||||
jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager());
|
||||
|
||||
#define CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN \
|
||||
jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager() || getPeer() == nullptr);
|
||||
|
||||
Component* Component::currentlyFocusedComponent = nullptr;
|
||||
|
||||
|
||||
@@ -147,7 +141,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Array <MouseListener*> listeners;
|
||||
Array<MouseListener*> listeners;
|
||||
int numDeepMouseListeners;
|
||||
|
||||
class BailOutChecker2
|
||||
@@ -245,6 +239,15 @@ struct ScalingHelpers
|
||||
{
|
||||
return scaledScreenPosToUnscaled (comp.getDesktopScaleFactor(), pos);
|
||||
}
|
||||
|
||||
static Point<int> addPosition (Point<int> p, const Component& c) noexcept { return p + c.getPosition(); }
|
||||
static Rectangle<int> addPosition (Rectangle<int> p, const Component& c) noexcept { return p + c.getPosition(); }
|
||||
static Point<float> addPosition (Point<float> p, const Component& c) noexcept { return p + c.getPosition().toFloat(); }
|
||||
static Rectangle<float> addPosition (Rectangle<float> p, const Component& c) noexcept { return p + c.getPosition().toFloat(); }
|
||||
static Point<int> subtractPosition (Point<int> p, const Component& c) noexcept { return p - c.getPosition(); }
|
||||
static Rectangle<int> subtractPosition (Rectangle<int> p, const Component& c) noexcept { return p - c.getPosition(); }
|
||||
static Point<float> subtractPosition (Point<float> p, const Component& c) noexcept { return p - c.getPosition().toFloat(); }
|
||||
static Rectangle<float> subtractPosition (Rectangle<float> p, const Component& c) noexcept { return p - c.getPosition().toFloat(); }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
@@ -253,7 +256,7 @@ struct Component::ComponentHelpers
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
static void* runModalLoopCallback (void* userData)
|
||||
{
|
||||
return (void*) (pointer_sized_int) static_cast <Component*> (userData)->runModalLoop();
|
||||
return (void*) (pointer_sized_int) static_cast<Component*> (userData)->runModalLoop();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -327,7 +330,7 @@ struct Component::ComponentHelpers
|
||||
}
|
||||
else
|
||||
{
|
||||
pointInParentSpace -= comp.getPosition();
|
||||
pointInParentSpace = ScalingHelpers::subtractPosition (pointInParentSpace, comp);
|
||||
}
|
||||
|
||||
return pointInParentSpace;
|
||||
@@ -346,7 +349,7 @@ struct Component::ComponentHelpers
|
||||
}
|
||||
else
|
||||
{
|
||||
pointInLocalSpace += comp.getPosition();
|
||||
pointInLocalSpace = ScalingHelpers::addPosition (pointInLocalSpace, comp);
|
||||
}
|
||||
|
||||
if (comp.affineTransform != nullptr)
|
||||
@@ -396,16 +399,6 @@ struct Component::ComponentHelpers
|
||||
return convertFromDistantParentSpace (topLevelComp, *target, p);
|
||||
}
|
||||
|
||||
static Rectangle<int> getUnclippedArea (const Component& comp)
|
||||
{
|
||||
Rectangle<int> r (comp.getLocalBounds());
|
||||
|
||||
if (Component* const p = comp.getParentComponent())
|
||||
r = r.getIntersection (convertFromParentSpace (comp, getUnclippedArea (*p)));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool clipObscuredRegions (const Component& comp, Graphics& g, const Rectangle<int>& clipRect, Point<int> delta)
|
||||
{
|
||||
bool nothingChanged = true;
|
||||
@@ -438,35 +431,6 @@ struct Component::ComponentHelpers
|
||||
return nothingChanged;
|
||||
}
|
||||
|
||||
static void subtractObscuredRegions (const Component& comp, RectangleList<int>& result,
|
||||
Point<int> delta, const Rectangle<int>& clipRect,
|
||||
const Component* const compToAvoid)
|
||||
{
|
||||
for (int i = comp.childComponentList.size(); --i >= 0;)
|
||||
{
|
||||
const Component* const c = comp.childComponentList.getUnchecked(i);
|
||||
|
||||
if (c != compToAvoid && c->isVisible())
|
||||
{
|
||||
if (c->isOpaque() && c->componentTransparency == 0)
|
||||
{
|
||||
Rectangle<int> childBounds (c->bounds.getIntersection (clipRect));
|
||||
childBounds.translate (delta.x, delta.y);
|
||||
|
||||
result.subtract (childBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle<int> newClip (clipRect.getIntersection (c->bounds));
|
||||
newClip.translate (-c->getX(), -c->getY());
|
||||
|
||||
subtractObscuredRegions (*c, result, c->getPosition() + delta,
|
||||
newClip, compToAvoid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Rectangle<int> getParentOrMainMonitorBounds (const Component& comp)
|
||||
{
|
||||
if (Component* p = comp.getParentComponent())
|
||||
@@ -477,7 +441,7 @@ struct Component::ComponentHelpers
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
Component::Component()
|
||||
Component::Component() noexcept
|
||||
: parentComponent (nullptr),
|
||||
lookAndFeel (nullptr),
|
||||
effect (nullptr),
|
||||
@@ -486,7 +450,7 @@ Component::Component()
|
||||
{
|
||||
}
|
||||
|
||||
Component::Component (const String& name)
|
||||
Component::Component (const String& name) noexcept
|
||||
: componentName (name),
|
||||
parentComponent (nullptr),
|
||||
lookAndFeel (nullptr),
|
||||
@@ -524,7 +488,7 @@ void Component::setName (const String& name)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
if (componentName != name)
|
||||
{
|
||||
@@ -550,7 +514,7 @@ void Component::setVisible (bool shouldBeVisible)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
const WeakReference<Component> safePointer (this);
|
||||
flags.visibleFlag = shouldBeVisible;
|
||||
@@ -617,7 +581,6 @@ bool Component::isShowing() const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void* Component::getWindowHandle() const
|
||||
{
|
||||
@@ -632,7 +595,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
if (isOpaque())
|
||||
styleWanted &= ~ComponentPeer::windowIsSemiTransparent;
|
||||
@@ -659,7 +622,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo)
|
||||
|
||||
bool wasFullscreen = false;
|
||||
bool wasMinimised = false;
|
||||
ComponentBoundsConstrainer* currentConstainer = nullptr;
|
||||
ComponentBoundsConstrainer* currentConstrainer = nullptr;
|
||||
Rectangle<int> oldNonFullScreenBounds;
|
||||
int oldRenderingEngine = -1;
|
||||
|
||||
@@ -669,7 +632,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo)
|
||||
|
||||
wasFullscreen = peer->isFullScreen();
|
||||
wasMinimised = peer->isMinimised();
|
||||
currentConstainer = peer->getConstrainer();
|
||||
currentConstrainer = peer->getConstrainer();
|
||||
oldNonFullScreenBounds = peer->getNonFullScreenBounds();
|
||||
oldRenderingEngine = peer->getCurrentRenderingEngine();
|
||||
|
||||
@@ -720,7 +683,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo)
|
||||
peer->setAlwaysOnTop (true);
|
||||
#endif
|
||||
|
||||
peer->setConstrainer (currentConstainer);
|
||||
peer->setConstrainer (currentConstrainer);
|
||||
|
||||
repaint();
|
||||
internalHierarchyChanged();
|
||||
@@ -732,7 +695,7 @@ void Component::removeFromDesktop()
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
if (flags.hasHeavyweightPeerFlag)
|
||||
{
|
||||
@@ -877,7 +840,7 @@ void Component::setBufferedToImage (const bool shouldBeBuffered)
|
||||
// so by calling setBufferedToImage, you'll be deleting the custom one - this is almost certainly
|
||||
// not what you wanted to happen... If you really do know what you're doing here, and want to
|
||||
// avoid this assertion, just call setCachedComponentImage (nullptr) before setBufferedToImage().
|
||||
jassert (cachedImage == nullptr || dynamic_cast <StandardCachedComponentImage*> (cachedImage.get()) != nullptr);
|
||||
jassert (cachedImage == nullptr || dynamic_cast<StandardCachedComponentImage*> (cachedImage.get()) != nullptr);
|
||||
|
||||
if (shouldBeBuffered)
|
||||
{
|
||||
@@ -910,7 +873,7 @@ void Component::toFront (const bool setAsForeground)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
if (flags.hasHeavyweightPeerFlag)
|
||||
{
|
||||
@@ -1092,6 +1055,11 @@ Point<int> Component::getLocalPoint (const Component* source, Point<int> point)
|
||||
return ComponentHelpers::convertCoordinate (this, source, point);
|
||||
}
|
||||
|
||||
Point<float> Component::getLocalPoint (const Component* source, Point<float> point) const
|
||||
{
|
||||
return ComponentHelpers::convertCoordinate (this, source, point);
|
||||
}
|
||||
|
||||
Rectangle<int> Component::getLocalArea (const Component* source, const Rectangle<int>& area) const
|
||||
{
|
||||
return ComponentHelpers::convertCoordinate (this, source, area);
|
||||
@@ -1102,6 +1070,11 @@ Point<int> Component::localPointToGlobal (Point<int> point) const
|
||||
return ComponentHelpers::convertCoordinate (nullptr, this, point);
|
||||
}
|
||||
|
||||
Point<float> Component::localPointToGlobal (Point<float> point) const
|
||||
{
|
||||
return ComponentHelpers::convertCoordinate (nullptr, this, point);
|
||||
}
|
||||
|
||||
Rectangle<int> Component::localAreaToGlobal (const Rectangle<int>& area) const
|
||||
{
|
||||
return ComponentHelpers::convertCoordinate (nullptr, this, area);
|
||||
@@ -1130,7 +1103,7 @@ void Component::setBounds (const int x, const int y, int w, int h)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
if (w < 0) w = 0;
|
||||
if (h < 0) h = 0;
|
||||
@@ -1169,11 +1142,25 @@ void Component::setBounds (const int x, const int y, int w, int h)
|
||||
cachedImage->invalidateAll();
|
||||
}
|
||||
|
||||
flags.isMoveCallbackPending = wasMoved;
|
||||
flags.isResizeCallbackPending = wasResized;
|
||||
|
||||
if (flags.hasHeavyweightPeerFlag)
|
||||
if (ComponentPeer* const peer = getPeer())
|
||||
peer->updateBounds();
|
||||
|
||||
sendMovedResizedMessages (wasMoved, wasResized);
|
||||
sendMovedResizedMessagesIfPending();
|
||||
}
|
||||
}
|
||||
|
||||
void Component::sendMovedResizedMessagesIfPending()
|
||||
{
|
||||
if (flags.isMoveCallbackPending || flags.isResizeCallbackPending)
|
||||
{
|
||||
sendMovedResizedMessages (flags.isMoveCallbackPending, flags.isResizeCallbackPending);
|
||||
|
||||
flags.isMoveCallbackPending = false;
|
||||
flags.isResizeCallbackPending = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1463,7 +1450,7 @@ void Component::addChildComponent (Component& child, int zOrder)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
if (child.parentComponent != this)
|
||||
{
|
||||
@@ -1539,7 +1526,7 @@ Component* Component::removeChildComponent (const int index, bool sendParentEven
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN
|
||||
|
||||
Component* const child = childComponentList [index];
|
||||
|
||||
@@ -1616,7 +1603,7 @@ Component* Component::getChildComponent (const int index) const noexcept
|
||||
|
||||
int Component::getIndexOfChildComponent (const Component* const child) const noexcept
|
||||
{
|
||||
return childComponentList.indexOf (const_cast <Component*> (child));
|
||||
return childComponentList.indexOf (const_cast<Component*> (child));
|
||||
}
|
||||
|
||||
Component* Component::findChildWithID (StringRef targetID) const noexcept
|
||||
@@ -1638,7 +1625,7 @@ Component* Component::getTopLevelComponent() const noexcept
|
||||
while (comp->parentComponent != nullptr)
|
||||
comp = comp->parentComponent;
|
||||
|
||||
return const_cast <Component*> (comp);
|
||||
return const_cast<Component*> (comp);
|
||||
}
|
||||
|
||||
bool Component::isParentOf (const Component* possibleChild) const noexcept
|
||||
@@ -1730,7 +1717,7 @@ void Component::enterModalState (const bool shouldTakeKeyboardFocus,
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
// Check for an attempt to make a component modal when it already is!
|
||||
// This can cause nasty problems..
|
||||
@@ -1917,7 +1904,7 @@ void Component::internalRepaintUnchecked (const Rectangle<int>& area, const bool
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
if (ComponentPeer* const peer = getPeer())
|
||||
{
|
||||
@@ -2034,6 +2021,14 @@ void Component::paintComponentAndChildren (Graphics& g)
|
||||
|
||||
void Component::paintEntireComponent (Graphics& g, const bool ignoreAlphaLevel)
|
||||
{
|
||||
// If sizing a top-level-window and the OS paint message is delivered synchronously
|
||||
// before resized() is called, then we'll invoke the callback here, to make sure
|
||||
// the components inside have had a chance to sort their sizes out..
|
||||
#if JUCE_DEBUG
|
||||
if (! flags.isInsidePaintCall) // (avoids an assertion in plugins hosted in WaveLab)
|
||||
#endif
|
||||
sendMovedResizedMessagesIfPending();
|
||||
|
||||
#if JUCE_DEBUG
|
||||
flags.isInsidePaintCall = true;
|
||||
#endif
|
||||
@@ -2170,7 +2165,7 @@ void Component::sendLookAndFeelChange()
|
||||
Colour Component::findColour (const int colourId, const bool inheritFromParent) const
|
||||
{
|
||||
if (const var* const v = properties.getVarPointer (ComponentHelpers::getColourPropertyId (colourId)))
|
||||
return Colour ((uint32) static_cast <int> (*v));
|
||||
return Colour ((uint32) static_cast<int> (*v));
|
||||
|
||||
if (inheritFromParent && parentComponent != nullptr
|
||||
&& (lookAndFeel == nullptr || ! lookAndFeel->isColourSpecified (colourId)))
|
||||
@@ -2249,28 +2244,6 @@ Rectangle<int> Component::getBoundsInParent() const noexcept
|
||||
: bounds.transformedBy (*affineTransform);
|
||||
}
|
||||
|
||||
void Component::getVisibleArea (RectangleList<int>& result, const bool includeSiblings) const
|
||||
{
|
||||
result.clear();
|
||||
const Rectangle<int> unclipped (ComponentHelpers::getUnclippedArea (*this));
|
||||
|
||||
if (! unclipped.isEmpty())
|
||||
{
|
||||
result.add (unclipped);
|
||||
|
||||
if (includeSiblings)
|
||||
{
|
||||
const Component* const c = getTopLevelComponent();
|
||||
|
||||
ComponentHelpers::subtractObscuredRegions (*c, result, getLocalPoint (c, Point<int>()),
|
||||
c->getLocalBounds(), this);
|
||||
}
|
||||
|
||||
ComponentHelpers::subtractObscuredRegions (*this, result, Point<int>(), unclipped, nullptr);
|
||||
result.consolidate();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Component::mouseEnter (const MouseEvent&) {}
|
||||
void Component::mouseExit (const MouseEvent&) {}
|
||||
@@ -2306,7 +2279,7 @@ void Component::addComponentListener (ComponentListener* const newListener)
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
#if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
|
||||
if (getParentComponent() != nullptr)
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED;
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED;
|
||||
#endif
|
||||
|
||||
componentListeners.add (newListener);
|
||||
@@ -2369,7 +2342,7 @@ void Component::addMouseListener (MouseListener* const newListener,
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
// If you register a component as a mouselistener for itself, it'll receive all the events
|
||||
// twice - once via the direct callback that all components get anyway, and then again as a listener!
|
||||
@@ -2385,14 +2358,14 @@ void Component::removeMouseListener (MouseListener* const listenerToRemove)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
if (mouseListeners != nullptr)
|
||||
mouseListeners->removeListener (listenerToRemove);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Component::internalMouseEnter (MouseInputSource source, Point<int> relativePos, Time time)
|
||||
void Component::internalMouseEnter (MouseInputSource source, Point<float> relativePos, Time time)
|
||||
{
|
||||
if (isCurrentlyBlockedByAnotherModalComponent())
|
||||
{
|
||||
@@ -2418,7 +2391,7 @@ void Component::internalMouseEnter (MouseInputSource source, Point<int> relative
|
||||
MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseEnter, me);
|
||||
}
|
||||
|
||||
void Component::internalMouseExit (MouseInputSource source, Point<int> relativePos, Time time)
|
||||
void Component::internalMouseExit (MouseInputSource source, Point<float> relativePos, Time time)
|
||||
{
|
||||
if (flags.repaintOnMouseActivityFlag)
|
||||
repaint();
|
||||
@@ -2438,7 +2411,7 @@ void Component::internalMouseExit (MouseInputSource source, Point<int> relativeP
|
||||
MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseExit, me);
|
||||
}
|
||||
|
||||
void Component::internalMouseDown (MouseInputSource source, Point<int> relativePos, Time time)
|
||||
void Component::internalMouseDown (MouseInputSource source, Point<float> relativePos, Time time)
|
||||
{
|
||||
Desktop& desktop = Desktop::getInstance();
|
||||
BailOutChecker checker (this);
|
||||
@@ -2502,7 +2475,7 @@ void Component::internalMouseDown (MouseInputSource source, Point<int> relativeP
|
||||
MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseDown, me);
|
||||
}
|
||||
|
||||
void Component::internalMouseUp (MouseInputSource source, Point<int> relativePos,
|
||||
void Component::internalMouseUp (MouseInputSource source, Point<float> relativePos,
|
||||
Time time, const ModifierKeys oldModifiers)
|
||||
{
|
||||
if (flags.mouseDownWasBlocked && isCurrentlyBlockedByAnotherModalComponent())
|
||||
@@ -2545,7 +2518,7 @@ void Component::internalMouseUp (MouseInputSource source, Point<int> relativePos
|
||||
}
|
||||
}
|
||||
|
||||
void Component::internalMouseDrag (MouseInputSource source, Point<int> relativePos, Time time)
|
||||
void Component::internalMouseDrag (MouseInputSource source, Point<float> relativePos, Time time)
|
||||
{
|
||||
if (! isCurrentlyBlockedByAnotherModalComponent())
|
||||
{
|
||||
@@ -2568,7 +2541,7 @@ void Component::internalMouseDrag (MouseInputSource source, Point<int> relativeP
|
||||
}
|
||||
}
|
||||
|
||||
void Component::internalMouseMove (MouseInputSource source, Point<int> relativePos, Time time)
|
||||
void Component::internalMouseMove (MouseInputSource source, Point<float> relativePos, Time time)
|
||||
{
|
||||
Desktop& desktop = Desktop::getInstance();
|
||||
|
||||
@@ -2594,7 +2567,7 @@ void Component::internalMouseMove (MouseInputSource source, Point<int> relativeP
|
||||
}
|
||||
}
|
||||
|
||||
void Component::internalMouseWheel (MouseInputSource source, Point<int> relativePos,
|
||||
void Component::internalMouseWheel (MouseInputSource source, Point<float> relativePos,
|
||||
Time time, const MouseWheelDetails& wheel)
|
||||
{
|
||||
Desktop& desktop = Desktop::getInstance();
|
||||
@@ -2622,7 +2595,7 @@ void Component::internalMouseWheel (MouseInputSource source, Point<int> relative
|
||||
}
|
||||
}
|
||||
|
||||
void Component::internalMagnifyGesture (MouseInputSource source, Point<int> relativePos,
|
||||
void Component::internalMagnifyGesture (MouseInputSource source, Point<float> relativePos,
|
||||
Time time, float amount)
|
||||
{
|
||||
if (! isCurrentlyBlockedByAnotherModalComponent())
|
||||
@@ -2821,7 +2794,7 @@ void Component::grabFocusInternal (const FocusChangeType cause, const bool canTr
|
||||
else
|
||||
{
|
||||
// find the default child component..
|
||||
ScopedPointer <KeyboardFocusTraverser> traverser (createFocusTraverser());
|
||||
ScopedPointer<KeyboardFocusTraverser> traverser (createFocusTraverser());
|
||||
|
||||
if (traverser != nullptr)
|
||||
{
|
||||
@@ -2850,7 +2823,7 @@ void Component::grabKeyboardFocus()
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
grabFocusInternal (focusChangedDirectly, true);
|
||||
}
|
||||
@@ -2859,11 +2832,11 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
CHECK_MESSAGE_MANAGER_IS_LOCKED
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
if (parentComponent != nullptr)
|
||||
{
|
||||
ScopedPointer <KeyboardFocusTraverser> traverser (createFocusTraverser());
|
||||
ScopedPointer<KeyboardFocusTraverser> traverser (createFocusTraverser());
|
||||
|
||||
if (traverser != nullptr)
|
||||
{
|
||||
@@ -2972,7 +2945,7 @@ bool Component::isMouseOver (const bool includeChildren) const
|
||||
Component* const c = mi->getComponentUnderMouse();
|
||||
|
||||
if ((c == this || (includeChildren && isParentOf (c)))
|
||||
&& c->reallyContains (c->getLocalPoint (nullptr, mi->getScreenPosition()), false)
|
||||
&& c->reallyContains (c->getLocalPoint (nullptr, mi->getScreenPosition()).roundToInt(), false)
|
||||
&& (mi->isMouse() || mi->isDragging()))
|
||||
return true;
|
||||
}
|
||||
@@ -3017,7 +2990,7 @@ Point<int> Component::getMouseXYRelative() const
|
||||
void Component::addKeyListener (KeyListener* const newListener)
|
||||
{
|
||||
if (keyListeners == nullptr)
|
||||
keyListeners = new Array <KeyListener*>();
|
||||
keyListeners = new Array<KeyListener*>();
|
||||
|
||||
keyListeners->addIfNotAlreadyThere (newListener);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
subclass of Component or use one of the other types of component from
|
||||
the library.
|
||||
*/
|
||||
Component();
|
||||
Component() noexcept;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
/** Creates a component, setting its name at the same time.
|
||||
@see getName, setName
|
||||
*/
|
||||
explicit Component (const String& componentName);
|
||||
explicit Component (const String& componentName) noexcept;
|
||||
|
||||
/** Returns the name of this component.
|
||||
@see setName
|
||||
@@ -315,16 +315,6 @@ public:
|
||||
*/
|
||||
Rectangle<int> getBoundsInParent() const noexcept;
|
||||
|
||||
/** Returns the region of this component that's not obscured by other, opaque components.
|
||||
|
||||
The RectangleList that is returned represents the area of this component
|
||||
which isn't covered by opaque child components.
|
||||
|
||||
If includeSiblings is true, it will also take into account any siblings
|
||||
that may be overlapping the component.
|
||||
*/
|
||||
void getVisibleArea (RectangleList<int>& result, bool includeSiblings) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns this component's x coordinate relative the screen's top-left origin.
|
||||
@see getX, localPointToGlobal
|
||||
@@ -355,6 +345,15 @@ public:
|
||||
Point<int> getLocalPoint (const Component* sourceComponent,
|
||||
Point<int> pointRelativeToSourceComponent) const;
|
||||
|
||||
/** Converts a point to be relative to this component's coordinate space.
|
||||
|
||||
This takes a point relative to a different component, and returns its position relative to this
|
||||
component. If the sourceComponent parameter is null, the source point is assumed to be a global
|
||||
screen coordinate.
|
||||
*/
|
||||
Point<float> getLocalPoint (const Component* sourceComponent,
|
||||
Point<float> pointRelativeToSourceComponent) const;
|
||||
|
||||
/** Converts a rectangle to be relative to this component's coordinate space.
|
||||
|
||||
This takes a rectangle that is relative to a different component, and returns its position relative
|
||||
@@ -373,6 +372,11 @@ public:
|
||||
*/
|
||||
Point<int> localPointToGlobal (Point<int> localPoint) const;
|
||||
|
||||
/** Converts a point relative to this component's top-left into a screen coordinate.
|
||||
@see getLocalPoint, localAreaToGlobal
|
||||
*/
|
||||
Point<float> localPointToGlobal (Point<float> localPoint) const;
|
||||
|
||||
/** Converts a rectangle from this component's coordinate space to a screen coordinate.
|
||||
|
||||
If you've used setTransform() to apply one or more transforms to components, then the source rectangle
|
||||
@@ -793,7 +797,7 @@ public:
|
||||
TargetClass* findParentComponentOfClass() const
|
||||
{
|
||||
for (Component* p = parentComponent; p != nullptr; p = p->parentComponent)
|
||||
if (TargetClass* const target = dynamic_cast <TargetClass*> (p))
|
||||
if (TargetClass* const target = dynamic_cast<TargetClass*> (p))
|
||||
return target;
|
||||
|
||||
return nullptr;
|
||||
@@ -1152,7 +1156,7 @@ public:
|
||||
By default, components are considered transparent, unless this is used to
|
||||
make it otherwise.
|
||||
|
||||
@see isOpaque, getVisibleArea
|
||||
@see isOpaque
|
||||
*/
|
||||
void setOpaque (bool shouldBeOpaque);
|
||||
|
||||
@@ -1743,11 +1747,14 @@ public:
|
||||
*/
|
||||
virtual void focusLost (FocusChangeType cause);
|
||||
|
||||
/** Called to indicate that one of this component's children has been focused or unfocused.
|
||||
/** Called to indicate a change in whether or not this component is the parent of the
|
||||
currently-focused component.
|
||||
|
||||
Essentially this means that the return value of a call to hasKeyboardFocus (true) has
|
||||
Essentially this is called when the return value of a call to hasKeyboardFocus (true) has
|
||||
changed. It happens when focus moves from one of this component's children (at any depth)
|
||||
to a component that isn't contained in this one, (or vice-versa).
|
||||
Note that this method does NOT get called to when focus simply moves from one of its
|
||||
child components to another.
|
||||
|
||||
@see focusGained, setWantsKeyboardFocus, getCurrentlyFocusedComponent, hasKeyboardFocus
|
||||
*/
|
||||
@@ -1782,9 +1789,7 @@ public:
|
||||
bool isMouseButtonDown() const;
|
||||
|
||||
/** True if the mouse is over this component, or if it's being dragged in this component.
|
||||
|
||||
This is a handy equivalent to (isMouseOver() || isMouseButtonDown()).
|
||||
|
||||
@see isMouseOver, isMouseButtonDown, isMouseButtonDownAnywhere
|
||||
*/
|
||||
bool isMouseOverOrDragging() const;
|
||||
@@ -2122,31 +2127,31 @@ public:
|
||||
SafePointer() noexcept {}
|
||||
|
||||
/** Creates a SafePointer that points at the given component. */
|
||||
SafePointer (ComponentType* const component) : weakRef (component) {}
|
||||
SafePointer (ComponentType* component) : weakRef (component) {}
|
||||
|
||||
/** Creates a copy of another SafePointer. */
|
||||
SafePointer (const SafePointer& other) noexcept : weakRef (other.weakRef) {}
|
||||
SafePointer (const SafePointer& other) noexcept : weakRef (other.weakRef) {}
|
||||
|
||||
/** Copies another pointer to this one. */
|
||||
SafePointer& operator= (const SafePointer& other) { weakRef = other.weakRef; return *this; }
|
||||
SafePointer& operator= (const SafePointer& other) { weakRef = other.weakRef; return *this; }
|
||||
|
||||
/** Copies another pointer to this one. */
|
||||
SafePointer& operator= (ComponentType* const newComponent) { weakRef = newComponent; return *this; }
|
||||
SafePointer& operator= (ComponentType* newComponent) { weakRef = newComponent; return *this; }
|
||||
|
||||
/** Returns the component that this pointer refers to, or null if the component no longer exists. */
|
||||
ComponentType* getComponent() const noexcept { return dynamic_cast <ComponentType*> (weakRef.get()); }
|
||||
ComponentType* getComponent() const noexcept { return dynamic_cast<ComponentType*> (weakRef.get()); }
|
||||
|
||||
/** Returns the component that this pointer refers to, or null if the component no longer exists. */
|
||||
operator ComponentType*() const noexcept { return getComponent(); }
|
||||
operator ComponentType*() const noexcept { return getComponent(); }
|
||||
|
||||
/** Returns the component that this pointer refers to, or null if the component no longer exists. */
|
||||
ComponentType* operator->() noexcept { return getComponent(); }
|
||||
ComponentType* operator->() noexcept { return getComponent(); }
|
||||
|
||||
/** Returns the component that this pointer refers to, or null if the component no longer exists. */
|
||||
const ComponentType* operator->() const noexcept { return getComponent(); }
|
||||
const ComponentType* operator->() const noexcept { return getComponent(); }
|
||||
|
||||
/** If the component is valid, this deletes it and sets this pointer to null. */
|
||||
void deleteAndZero() { delete getComponent(); }
|
||||
void deleteAndZero() { delete getComponent(); }
|
||||
|
||||
bool operator== (ComponentType* component) const noexcept { return weakRef == component; }
|
||||
bool operator!= (ComponentType* component) const noexcept { return weakRef != component; }
|
||||
@@ -2254,20 +2259,20 @@ private:
|
||||
String componentName, componentID;
|
||||
Component* parentComponent;
|
||||
Rectangle<int> bounds;
|
||||
ScopedPointer <Positioner> positioner;
|
||||
ScopedPointer <AffineTransform> affineTransform;
|
||||
Array <Component*> childComponentList;
|
||||
ScopedPointer<Positioner> positioner;
|
||||
ScopedPointer<AffineTransform> affineTransform;
|
||||
Array<Component*> childComponentList;
|
||||
LookAndFeel* lookAndFeel;
|
||||
MouseCursor cursor;
|
||||
ImageEffectFilter* effect;
|
||||
ScopedPointer <CachedComponentImage> cachedImage;
|
||||
ScopedPointer<CachedComponentImage> cachedImage;
|
||||
|
||||
class MouseListenerList;
|
||||
friend class MouseListenerList;
|
||||
friend struct ContainerDeletePolicy<MouseListenerList>;
|
||||
ScopedPointer <MouseListenerList> mouseListeners;
|
||||
ScopedPointer <Array <KeyListener*> > keyListeners;
|
||||
ListenerList <ComponentListener> componentListeners;
|
||||
ScopedPointer<MouseListenerList> mouseListeners;
|
||||
ScopedPointer<Array<KeyListener*> > keyListeners;
|
||||
ListenerList<ComponentListener> componentListeners;
|
||||
NamedValueSet properties;
|
||||
|
||||
friend class WeakReference<Component>;
|
||||
@@ -2292,9 +2297,11 @@ private:
|
||||
bool childCompFocusedFlag : 1;
|
||||
bool dontClipGraphicsFlag : 1;
|
||||
bool mouseDownWasBlocked : 1;
|
||||
#if JUCE_DEBUG
|
||||
bool isMoveCallbackPending : 1;
|
||||
bool isResizeCallbackPending : 1;
|
||||
#if JUCE_DEBUG
|
||||
bool isInsidePaintCall : 1;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
union
|
||||
@@ -2306,18 +2313,18 @@ private:
|
||||
uint8 componentTransparency;
|
||||
|
||||
//==============================================================================
|
||||
void internalMouseEnter (MouseInputSource, Point<int>, Time);
|
||||
void internalMouseExit (MouseInputSource, Point<int>, Time);
|
||||
void internalMouseDown (MouseInputSource, Point<int>, Time);
|
||||
void internalMouseUp (MouseInputSource, Point<int>, Time, const ModifierKeys oldModifiers);
|
||||
void internalMouseDrag (MouseInputSource, Point<int>, Time);
|
||||
void internalMouseMove (MouseInputSource, Point<int>, Time);
|
||||
void internalMouseWheel (MouseInputSource, Point<int>, Time, const MouseWheelDetails&);
|
||||
void internalMagnifyGesture (MouseInputSource, Point<int>, Time, float);
|
||||
void internalMouseEnter (MouseInputSource, Point<float>, Time);
|
||||
void internalMouseExit (MouseInputSource, Point<float>, Time);
|
||||
void internalMouseDown (MouseInputSource, Point<float>, Time);
|
||||
void internalMouseUp (MouseInputSource, Point<float>, Time, const ModifierKeys oldModifiers);
|
||||
void internalMouseDrag (MouseInputSource, Point<float>, Time);
|
||||
void internalMouseMove (MouseInputSource, Point<float>, Time);
|
||||
void internalMouseWheel (MouseInputSource, Point<float>, Time, const MouseWheelDetails&);
|
||||
void internalMagnifyGesture (MouseInputSource, Point<float>, Time, float);
|
||||
void internalBroughtToFront();
|
||||
void internalFocusGain (const FocusChangeType, const WeakReference<Component>&);
|
||||
void internalFocusGain (const FocusChangeType);
|
||||
void internalFocusLoss (const FocusChangeType);
|
||||
void internalFocusGain (FocusChangeType, const WeakReference<Component>&);
|
||||
void internalFocusGain (FocusChangeType);
|
||||
void internalFocusLoss (FocusChangeType);
|
||||
void internalChildFocusChange (FocusChangeType, const WeakReference<Component>&);
|
||||
void internalModalInputAttempt();
|
||||
void internalModifierKeysChanged();
|
||||
@@ -2330,6 +2337,7 @@ private:
|
||||
void paintComponentAndChildren (Graphics&);
|
||||
void paintWithinParentContext (Graphics&);
|
||||
void sendMovedResizedMessages (bool wasMoved, bool wasResized);
|
||||
void sendMovedResizedMessagesIfPending();
|
||||
void repaintParent();
|
||||
void sendFakeMouseMove() const;
|
||||
void takeKeyboardFocus (const FocusChangeType);
|
||||
|
||||
@@ -68,6 +68,8 @@ Component* Desktop::getComponent (const int index) const noexcept
|
||||
|
||||
Component* Desktop::findComponentAt (Point<int> screenPosition) const
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
for (int i = desktopComponents.size(); --i >= 0;)
|
||||
{
|
||||
Component* const c = desktopComponents.getUnchecked(i);
|
||||
@@ -100,6 +102,7 @@ LookAndFeel& Desktop::getDefaultLookAndFeel() noexcept
|
||||
|
||||
void Desktop::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel)
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
currentLookAndFeel = newDefaultLookAndFeel;
|
||||
|
||||
for (int i = getNumComponents(); --i >= 0;)
|
||||
@@ -145,18 +148,23 @@ void Desktop::componentBroughtToFront (Component* const c)
|
||||
|
||||
//==============================================================================
|
||||
Point<int> Desktop::getMousePosition()
|
||||
{
|
||||
return getMousePositionFloat().roundToInt();
|
||||
}
|
||||
|
||||
Point<float> Desktop::getMousePositionFloat()
|
||||
{
|
||||
return getInstance().getMainMouseSource().getScreenPosition();
|
||||
}
|
||||
|
||||
void Desktop::setMousePosition (Point<int> newPosition)
|
||||
{
|
||||
getInstance().getMainMouseSource().setScreenPosition (newPosition);
|
||||
getInstance().getMainMouseSource().setScreenPosition (newPosition.toFloat());
|
||||
}
|
||||
|
||||
Point<int> Desktop::getLastMouseDownPosition()
|
||||
{
|
||||
return getInstance().getMainMouseSource().getLastMouseDownPosition();
|
||||
return getInstance().getMainMouseSource().getLastMouseDownPosition().roundToInt();
|
||||
}
|
||||
|
||||
int Desktop::getMouseButtonClickCounter() const noexcept { return mouseClickCounter; }
|
||||
@@ -194,10 +202,10 @@ void Desktop::resetTimer()
|
||||
else
|
||||
startTimer (100);
|
||||
|
||||
lastFakeMouseMove = getMousePosition();
|
||||
lastFakeMouseMove = getMousePositionFloat();
|
||||
}
|
||||
|
||||
ListenerList <MouseListener>& Desktop::getMouseListeners()
|
||||
ListenerList<MouseListener>& Desktop::getMouseListeners()
|
||||
{
|
||||
resetTimer();
|
||||
return mouseListeners;
|
||||
@@ -205,19 +213,21 @@ ListenerList <MouseListener>& Desktop::getMouseListeners()
|
||||
|
||||
void Desktop::addGlobalMouseListener (MouseListener* const listener)
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
mouseListeners.add (listener);
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
void Desktop::removeGlobalMouseListener (MouseListener* const listener)
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
mouseListeners.remove (listener);
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
void Desktop::timerCallback()
|
||||
{
|
||||
if (lastFakeMouseMove != getMousePosition())
|
||||
if (lastFakeMouseMove != getMousePositionFloat())
|
||||
sendMouseMove();
|
||||
}
|
||||
|
||||
@@ -227,12 +237,12 @@ void Desktop::sendMouseMove()
|
||||
{
|
||||
startTimer (20);
|
||||
|
||||
lastFakeMouseMove = getMousePosition();
|
||||
lastFakeMouseMove = getMousePositionFloat();
|
||||
|
||||
if (Component* const target = findComponentAt (lastFakeMouseMove))
|
||||
if (Component* const target = findComponentAt (lastFakeMouseMove.roundToInt()))
|
||||
{
|
||||
Component::BailOutChecker checker (target);
|
||||
const Point<int> pos (target->getLocalPoint (nullptr, lastFakeMouseMove));
|
||||
const Point<float> pos (target->getLocalPoint (nullptr, lastFakeMouseMove));
|
||||
const Time now (Time::getCurrentTime());
|
||||
|
||||
const MouseEvent me (getMainMouseSource(), pos, ModifierKeys::getCurrentModifiers(),
|
||||
@@ -253,12 +263,14 @@ Desktop::Displays::~Displays() {}
|
||||
|
||||
const Desktop::Displays::Display& Desktop::Displays::getMainDisplay() const noexcept
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
jassert (displays.getReference(0).isMain);
|
||||
return displays.getReference(0);
|
||||
}
|
||||
|
||||
const Desktop::Displays::Display& Desktop::Displays::getDisplayContaining (Point<int> position) const noexcept
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
const Display* best = &displays.getReference(0);
|
||||
double bestDistance = 1.0e10;
|
||||
|
||||
@@ -286,6 +298,7 @@ const Desktop::Displays::Display& Desktop::Displays::getDisplayContaining (Point
|
||||
|
||||
RectangleList<int> Desktop::Displays::getRectangleList (bool userAreasOnly) const
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
RectangleList<int> rl;
|
||||
|
||||
for (int i = 0; i < displays.size(); ++i)
|
||||
@@ -329,6 +342,7 @@ void Desktop::Displays::refresh()
|
||||
oldDisplays.swapWith (displays);
|
||||
|
||||
init (Desktop::getInstance());
|
||||
jassert (displays.size() > 0);
|
||||
|
||||
if (oldDisplays != displays)
|
||||
{
|
||||
@@ -391,6 +405,8 @@ bool Desktop::isOrientationEnabled (const DisplayOrientation orientation) const
|
||||
|
||||
void Desktop::setGlobalScaleFactor (float newScaleFactor) noexcept
|
||||
{
|
||||
ASSERT_MESSAGE_MANAGER_IS_LOCKED
|
||||
|
||||
if (masterScaleFactor != newScaleFactor)
|
||||
{
|
||||
masterScaleFactor = newScaleFactor;
|
||||
|
||||
@@ -414,7 +414,7 @@ private:
|
||||
|
||||
ScopedPointer<Displays> displays;
|
||||
|
||||
Point<int> lastFakeMouseMove;
|
||||
Point<float> lastFakeMouseMove;
|
||||
void sendMouseMove();
|
||||
|
||||
int mouseClickCounter, mouseWheelCounter;
|
||||
@@ -441,11 +441,13 @@ private:
|
||||
void removeDesktopComponent (Component*);
|
||||
void componentBroughtToFront (Component*);
|
||||
|
||||
void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars);
|
||||
void setKioskComponent (Component*, bool shouldBeEnabled, bool allowMenusAndBars);
|
||||
|
||||
void triggerFocusCallback();
|
||||
void handleAsyncUpdate() override;
|
||||
|
||||
static Point<float> getMousePositionFloat();
|
||||
|
||||
static double getDefaultMasterScale();
|
||||
|
||||
Desktop();
|
||||
|
||||
@@ -234,6 +234,17 @@ void ModalComponentManager::bringModalComponentsToFront (bool topOneShouldGrabFo
|
||||
}
|
||||
}
|
||||
|
||||
bool ModalComponentManager::cancelAllModalComponents()
|
||||
{
|
||||
const int numModal = getNumModalComponents();
|
||||
|
||||
for (int i = numModal; --i >= 0;)
|
||||
if (Component* const c = getModalComponent(i))
|
||||
c->exitModalState (0);
|
||||
|
||||
return numModal > 0;
|
||||
}
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
class ModalComponentManager::ReturnValueRetriever : public ModalComponentManager::Callback
|
||||
{
|
||||
|
||||
@@ -107,6 +107,11 @@ public:
|
||||
/** Brings any modal components to the front. */
|
||||
void bringModalComponentsToFront (bool topOneShouldGrabFocus = true);
|
||||
|
||||
/** Calls exitModalState (0) on any components that are currently modal.
|
||||
@returns true if any components were modal; false if nothing needed cancelling
|
||||
*/
|
||||
bool cancelAllModalComponents();
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
/** Runs the event loop until the currently topmost modal component is dismissed, and
|
||||
returns the exit code for that component.
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
|
||||
DrawableComposite* const drawable = new DrawableComposite();
|
||||
|
||||
drawable->setName (xml->getStringAttribute ("id"));
|
||||
setDrawableID (*drawable, xml);
|
||||
|
||||
SVGState newState (*this);
|
||||
|
||||
@@ -85,31 +85,13 @@ public:
|
||||
newState.viewBoxW = vwh.x;
|
||||
newState.viewBoxH = vwh.y;
|
||||
|
||||
int placementFlags = 0;
|
||||
const int placementFlags = parsePlacementFlags (xml->getStringAttribute ("preserveAspectRatio").trim());
|
||||
|
||||
const String aspect (xml->getStringAttribute ("preserveAspectRatio"));
|
||||
|
||||
if (aspect.containsIgnoreCase ("none"))
|
||||
{
|
||||
placementFlags = RectanglePlacement::stretchToFit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aspect.containsIgnoreCase ("slice")) placementFlags |= RectanglePlacement::fillDestination;
|
||||
|
||||
if (aspect.containsIgnoreCase ("xMin")) placementFlags |= RectanglePlacement::xLeft;
|
||||
else if (aspect.containsIgnoreCase ("xMax")) placementFlags |= RectanglePlacement::xRight;
|
||||
else placementFlags |= RectanglePlacement::xMid;
|
||||
|
||||
if (aspect.containsIgnoreCase ("yMin")) placementFlags |= RectanglePlacement::yTop;
|
||||
else if (aspect.containsIgnoreCase ("yMax")) placementFlags |= RectanglePlacement::yBottom;
|
||||
else placementFlags |= RectanglePlacement::yMid;
|
||||
}
|
||||
|
||||
newState.transform = RectanglePlacement (placementFlags)
|
||||
.getTransformToFit (Rectangle<float> (viewboxXY.x, viewboxXY.y, vwh.x, vwh.y),
|
||||
Rectangle<float> (newState.width, newState.height))
|
||||
.followedBy (newState.transform);
|
||||
if (placementFlags != 0)
|
||||
newState.transform = RectanglePlacement (placementFlags)
|
||||
.getTransformToFit (Rectangle<float> (viewboxXY.x, viewboxXY.y, vwh.x, vwh.y),
|
||||
Rectangle<float> (newState.width, newState.height))
|
||||
.followedBy (newState.transform);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -349,6 +331,11 @@ public:
|
||||
if (! carryOn)
|
||||
break;
|
||||
}
|
||||
|
||||
// paths that finish back at their start position often seem to be
|
||||
// left without a 'z', so need to be closed explicitly..
|
||||
if (path.getCurrentPosition() == subpathStart)
|
||||
path.closeSubPath();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -358,6 +345,13 @@ private:
|
||||
AffineTransform transform;
|
||||
String cssStyleText;
|
||||
|
||||
static void setDrawableID (Drawable& d, const XmlPath& xml)
|
||||
{
|
||||
String compID (xml->getStringAttribute ("id"));
|
||||
d.setName (compID);
|
||||
d.setComponentID (compID);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void parseSubElements (const XmlPath& xml, DrawableComposite& parentDrawable)
|
||||
{
|
||||
@@ -397,7 +391,7 @@ private:
|
||||
{
|
||||
DrawableComposite* const drawable = new DrawableComposite();
|
||||
|
||||
drawable->setName (xml->getStringAttribute ("id"));
|
||||
setDrawableID (*drawable, xml);
|
||||
|
||||
if (xml->hasAttribute ("transform"))
|
||||
{
|
||||
@@ -542,30 +536,18 @@ private:
|
||||
}
|
||||
|
||||
DrawablePath* dp = new DrawablePath();
|
||||
dp->setName (xml->getStringAttribute ("id"));
|
||||
setDrawableID (*dp, xml);
|
||||
dp->setFill (Colours::transparentBlack);
|
||||
|
||||
path.applyTransform (transform);
|
||||
dp->setPath (path);
|
||||
|
||||
Path::Iterator iter (path);
|
||||
|
||||
bool containsClosedSubPath = false;
|
||||
while (iter.next())
|
||||
{
|
||||
if (iter.elementType == Path::Iterator::closePath)
|
||||
{
|
||||
containsClosedSubPath = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dp->setFill (getPathFillType (path,
|
||||
getStyleAttribute (xml, "fill"),
|
||||
getStyleAttribute (xml, "fill-opacity"),
|
||||
getStyleAttribute (xml, "opacity"),
|
||||
containsClosedSubPath ? Colours::black
|
||||
: Colours::transparentBlack));
|
||||
pathContainsClosedSubPath (path) ? Colours::black
|
||||
: Colours::transparentBlack));
|
||||
|
||||
const String strokeType (getStyleAttribute (xml, "stroke"));
|
||||
|
||||
@@ -582,6 +564,15 @@ private:
|
||||
return dp;
|
||||
}
|
||||
|
||||
static bool pathContainsClosedSubPath (const Path& path) noexcept
|
||||
{
|
||||
for (Path::Iterator iter (path); iter.next();)
|
||||
if (iter.elementType == Path::Iterator::closePath)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct SetGradientStopsOp
|
||||
{
|
||||
const SVGState* state;
|
||||
@@ -784,44 +775,41 @@ private:
|
||||
return parseColour (fill, i, defaultColour).withMultipliedAlpha (opacity);
|
||||
}
|
||||
|
||||
static PathStrokeType::JointStyle getJointStyle (const String& join) noexcept
|
||||
{
|
||||
if (join.equalsIgnoreCase ("round")) return PathStrokeType::curved;
|
||||
if (join.equalsIgnoreCase ("bevel")) return PathStrokeType::beveled;
|
||||
|
||||
return PathStrokeType::mitered;
|
||||
}
|
||||
|
||||
static PathStrokeType::EndCapStyle getEndCapStyle (const String& cap) noexcept
|
||||
{
|
||||
if (cap.equalsIgnoreCase ("round")) return PathStrokeType::rounded;
|
||||
if (cap.equalsIgnoreCase ("square")) return PathStrokeType::square;
|
||||
|
||||
return PathStrokeType::butt;
|
||||
}
|
||||
|
||||
float getStrokeWidth (const String& strokeWidth) const noexcept
|
||||
{
|
||||
return transform.getScaleFactor() * getCoordLength (strokeWidth, viewBoxW);
|
||||
}
|
||||
|
||||
PathStrokeType getStrokeFor (const XmlPath& xml) const
|
||||
{
|
||||
const String strokeWidth (getStyleAttribute (xml, "stroke-width"));
|
||||
const String cap (getStyleAttribute (xml, "stroke-linecap"));
|
||||
const String join (getStyleAttribute (xml, "stroke-linejoin"));
|
||||
|
||||
//const String mitreLimit (getStyleAttribute (xml, "stroke-miterlimit"));
|
||||
//const String dashArray (getStyleAttribute (xml, "stroke-dasharray"));
|
||||
//const String dashOffset (getStyleAttribute (xml, "stroke-dashoffset"));
|
||||
|
||||
PathStrokeType::JointStyle joinStyle = PathStrokeType::mitered;
|
||||
PathStrokeType::EndCapStyle capStyle = PathStrokeType::butt;
|
||||
|
||||
if (join.equalsIgnoreCase ("round"))
|
||||
joinStyle = PathStrokeType::curved;
|
||||
else if (join.equalsIgnoreCase ("bevel"))
|
||||
joinStyle = PathStrokeType::beveled;
|
||||
|
||||
if (cap.equalsIgnoreCase ("round"))
|
||||
capStyle = PathStrokeType::rounded;
|
||||
else if (cap.equalsIgnoreCase ("square"))
|
||||
capStyle = PathStrokeType::square;
|
||||
|
||||
float ox = 0.0f, oy = 0.0f;
|
||||
float x = getCoordLength (strokeWidth, viewBoxW), y = 0.0f;
|
||||
transform.transformPoints (ox, oy, x, y);
|
||||
|
||||
return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypot (x - ox, y - oy) : 1.0f,
|
||||
joinStyle, capStyle);
|
||||
return PathStrokeType (getStrokeWidth (getStyleAttribute (xml, "stroke-width", "1")),
|
||||
getJointStyle (getStyleAttribute (xml, "stroke-linejoin")),
|
||||
getEndCapStyle (getStyleAttribute (xml, "stroke-linecap")));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Drawable* parseText (const XmlPath& xml)
|
||||
{
|
||||
Array <float> xCoords, yCoords, dxCoords, dyCoords;
|
||||
Array<float> xCoords, yCoords, dxCoords, dyCoords;
|
||||
|
||||
getCoordList (xCoords, getInheritedAttribute (xml, "x"), true, true);
|
||||
getCoordList (yCoords, getInheritedAttribute (xml, "y"), true, false);
|
||||
getCoordList (xCoords, getInheritedAttribute (xml, "x"), true, true);
|
||||
getCoordList (yCoords, getInheritedAttribute (xml, "y"), true, false);
|
||||
getCoordList (dxCoords, getInheritedAttribute (xml, "dx"), true, true);
|
||||
getCoordList (dyCoords, getInheritedAttribute (xml, "dy"), true, false);
|
||||
|
||||
@@ -886,7 +874,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
float getCoordLength (const String& s, const float sizeForProportions) const
|
||||
float getCoordLength (const String& s, const float sizeForProportions) const noexcept
|
||||
{
|
||||
float n = s.getFloatValue();
|
||||
const int len = s.length();
|
||||
@@ -908,13 +896,12 @@ private:
|
||||
return n;
|
||||
}
|
||||
|
||||
float getCoordLength (const XmlPath& xml, const char* attName, const float sizeForProportions) const
|
||||
float getCoordLength (const XmlPath& xml, const char* attName, const float sizeForProportions) const noexcept
|
||||
{
|
||||
return getCoordLength (xml->getStringAttribute (attName), sizeForProportions);
|
||||
}
|
||||
|
||||
void getCoordList (Array <float>& coords, const String& list,
|
||||
const bool allowUnits, const bool isX) const
|
||||
void getCoordList (Array<float>& coords, const String& list, bool allowUnits, const bool isX) const
|
||||
{
|
||||
String::CharPointerType text (list.getCharPointer());
|
||||
float value;
|
||||
@@ -948,7 +935,7 @@ private:
|
||||
return source;
|
||||
}
|
||||
|
||||
String getStyleAttribute (const XmlPath& xml, const String& attributeName,
|
||||
String getStyleAttribute (const XmlPath& xml, StringRef attributeName,
|
||||
const String& defaultValue = String()) const
|
||||
{
|
||||
if (xml->hasAttribute (attributeName))
|
||||
@@ -988,7 +975,7 @@ private:
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
String getInheritedAttribute (const XmlPath& xml, const String& attributeName) const
|
||||
String getInheritedAttribute (const XmlPath& xml, StringRef attributeName) const
|
||||
{
|
||||
if (xml->hasAttribute (attributeName))
|
||||
return xml->getStringAttribute (attributeName);
|
||||
@@ -999,13 +986,30 @@ private:
|
||||
return String();
|
||||
}
|
||||
|
||||
static int parsePlacementFlags (const String& align) noexcept
|
||||
{
|
||||
if (align.isEmpty())
|
||||
return 0;
|
||||
|
||||
if (align.containsIgnoreCase ("none"))
|
||||
return RectanglePlacement::stretchToFit;
|
||||
|
||||
return (align.containsIgnoreCase ("slice") ? RectanglePlacement::fillDestination : 0)
|
||||
| (align.containsIgnoreCase ("xMin") ? RectanglePlacement::xLeft
|
||||
: (align.containsIgnoreCase ("xMax") ? RectanglePlacement::xRight
|
||||
: RectanglePlacement::xMid))
|
||||
| (align.containsIgnoreCase ("yMin") ? RectanglePlacement::yTop
|
||||
: (align.containsIgnoreCase ("yMax") ? RectanglePlacement::yBottom
|
||||
: RectanglePlacement::yMid));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool isIdentifierChar (const juce_wchar c)
|
||||
{
|
||||
return CharacterFunctions::isLetter (c) || c == '-';
|
||||
}
|
||||
|
||||
static String getAttributeFromStyleList (const String& list, const String& attributeName, const String& defaultValue)
|
||||
static String getAttributeFromStyleList (const String& list, StringRef attributeName, const String& defaultValue)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -1209,7 +1213,7 @@ private:
|
||||
const bool largeArc, const bool sweep,
|
||||
double& rx, double& ry,
|
||||
double& centreX, double& centreY,
|
||||
double& startAngle, double& deltaAngle)
|
||||
double& startAngle, double& deltaAngle) noexcept
|
||||
{
|
||||
const double midX = (x1 - x2) * 0.5;
|
||||
const double midY = (y1 - y2) * 0.5;
|
||||
|
||||
@@ -115,8 +115,7 @@ void DirectoryContentsList::setFileFilter (const FileFilter* newFileFilter)
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool DirectoryContentsList::getFileInfo (const int index,
|
||||
FileInfo& result) const
|
||||
bool DirectoryContentsList::getFileInfo (const int index, FileInfo& result) const
|
||||
{
|
||||
const ScopedLock sl (fileListLock);
|
||||
|
||||
@@ -222,7 +221,7 @@ struct FileInfoComparator
|
||||
return first->isDirectory ? -1 : 1;
|
||||
#endif
|
||||
|
||||
return first->filename.compareIgnoreCase (second->filename);
|
||||
return first->filename.compareNatural (second->filename);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ void FileChooserDialogBox::okButtonPressed()
|
||||
{
|
||||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
|
||||
TRANS("File already exists"),
|
||||
TRANS("There's already a file called: FLMN")
|
||||
TRANS("There's already a file called: FLNM")
|
||||
.replace ("FLNM", content->chooserComponent.getSelectedFile(0).getFullPathName())
|
||||
+ "\n\n"
|
||||
+ TRANS("Are you sure you want to overwrite it?"),
|
||||
|
||||
@@ -68,6 +68,13 @@ void FilenameComponent::resized()
|
||||
getLookAndFeel().layoutFilenameComponent (*this, &filenameBox, browseButton);
|
||||
}
|
||||
|
||||
KeyboardFocusTraverser* FilenameComponent::createFocusTraverser()
|
||||
{
|
||||
// This prevents the sub-components from grabbing focus if the
|
||||
// FilenameComponent has been set to refuse focus.
|
||||
return getWantsKeyboardFocus() ? Component::createFocusTraverser() : nullptr;
|
||||
}
|
||||
|
||||
void FilenameComponent::setBrowseButtonText (const String& newBrowseButtonText)
|
||||
{
|
||||
browseButtonText = newBrowseButtonText;
|
||||
@@ -155,9 +162,14 @@ void FilenameComponent::fileDragExit (const StringArray&)
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
String FilenameComponent::getCurrentFileText() const
|
||||
{
|
||||
return filenameBox.getText();
|
||||
}
|
||||
|
||||
File FilenameComponent::getCurrentFile() const
|
||||
{
|
||||
File f (File::getCurrentWorkingDirectory().getChildFile (filenameBox.getText()));
|
||||
File f (File::getCurrentWorkingDirectory().getChildFile (getCurrentFileText()));
|
||||
|
||||
if (enforcedSuffix.isNotEmpty())
|
||||
f = f.withFileExtension (enforcedSuffix);
|
||||
|
||||
@@ -103,6 +103,9 @@ public:
|
||||
/** Returns the currently displayed filename. */
|
||||
File getCurrentFile() const;
|
||||
|
||||
/** Returns the raw text that the user has entered. */
|
||||
String getCurrentFileText() const;
|
||||
|
||||
/** Changes the current filename.
|
||||
|
||||
@param newFile the new filename to use
|
||||
@@ -205,6 +208,8 @@ public:
|
||||
void fileDragEnter (const StringArray&, int, int) override;
|
||||
/** @internal */
|
||||
void fileDragExit (const StringArray&) override;
|
||||
/** @internal */
|
||||
KeyboardFocusTraverser* createFocusTraverser() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#import <WebKit/WebKit.h>
|
||||
#import <IOKit/pwr_mgt/IOPMLib.h>
|
||||
|
||||
#if JUCE_SUPPORT_CARBON
|
||||
#if JUCE_SUPPORT_CARBON && ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)
|
||||
#define Point CarbonDummyPointName
|
||||
#define Component CarbonDummyCompName
|
||||
#import <Carbon/Carbon.h> // still needed for SetSystemUIMode()
|
||||
@@ -135,6 +135,12 @@
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#define ASSERT_MESSAGE_MANAGER_IS_LOCKED \
|
||||
jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager());
|
||||
|
||||
#define ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN \
|
||||
jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager() || getPeer() == nullptr);
|
||||
|
||||
extern bool juce_areThereAnyAlwaysOnTopWindows();
|
||||
|
||||
#include "components/juce_Component.cpp"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "juce_gui_basics",
|
||||
"name": "JUCE GUI core classes",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.8",
|
||||
"description": "Basic user-interface components and related classes.",
|
||||
"website": "http://www.juce.com/juce",
|
||||
"license": "GPL/Commercial",
|
||||
|
||||
@@ -71,6 +71,23 @@ public:
|
||||
|
||||
/** Returns the position of the caret, relative to the component's origin. */
|
||||
virtual Rectangle<int> getCaretRectangle() = 0;
|
||||
|
||||
/** A set of possible on-screen keyboard types, for use in the
|
||||
getKeyboardType() method.
|
||||
*/
|
||||
enum VirtualKeyboardType
|
||||
{
|
||||
textKeyboard = 0,
|
||||
numericKeyboard,
|
||||
urlKeyboard,
|
||||
emailAddressKeyboard,
|
||||
phoneNumberKeyboard
|
||||
};
|
||||
|
||||
/** Returns the target's preference for the type of keyboard that would be most appropriate.
|
||||
This may be ignored, depending on the capabilities of the OS.
|
||||
*/
|
||||
virtual VirtualKeyboardType getKeyboardType() { return textKeyboard; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
class ComponentAnimator::AnimationTask
|
||||
{
|
||||
public:
|
||||
AnimationTask (Component* const comp)
|
||||
: component (comp)
|
||||
AnimationTask (Component* const comp) noexcept : component (comp)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,7 +33,7 @@ public:
|
||||
float finalAlpha,
|
||||
int millisecondsToSpendMoving,
|
||||
bool useProxyComponent,
|
||||
double startSpeed_, double endSpeed_)
|
||||
double startSpd, double endSpd)
|
||||
{
|
||||
msElapsed = 0;
|
||||
msTotal = jmax (1, millisecondsToSpendMoving);
|
||||
@@ -51,10 +50,10 @@ public:
|
||||
bottom = component->getBottom();
|
||||
alpha = component->getAlpha();
|
||||
|
||||
const double invTotalDistance = 4.0 / (startSpeed_ + endSpeed_ + 2.0);
|
||||
startSpeed = jmax (0.0, startSpeed_ * invTotalDistance);
|
||||
const double invTotalDistance = 4.0 / (startSpd + endSpd + 2.0);
|
||||
startSpeed = jmax (0.0, startSpd * invTotalDistance);
|
||||
midSpeed = invTotalDistance;
|
||||
endSpeed = jmax (0.0, endSpeed_ * invTotalDistance);
|
||||
endSpeed = jmax (0.0, endSpd * invTotalDistance);
|
||||
|
||||
if (useProxyComponent)
|
||||
proxy = new ProxyComponent (*component);
|
||||
@@ -218,7 +217,7 @@ void ComponentAnimator::animateComponent (Component* const component,
|
||||
const double endSpeed)
|
||||
{
|
||||
// the speeds must be 0 or greater!
|
||||
jassert (startSpeed >= 0 && endSpeed >= 0)
|
||||
jassert (startSpeed >= 0 && endSpeed >= 0);
|
||||
|
||||
if (component != nullptr)
|
||||
{
|
||||
|
||||
@@ -148,10 +148,10 @@ public:
|
||||
private:
|
||||
//==============================================================================
|
||||
class AnimationTask;
|
||||
OwnedArray <AnimationTask> tasks;
|
||||
OwnedArray<AnimationTask> tasks;
|
||||
uint32 lastTime;
|
||||
|
||||
AnimationTask* findTaskFor (Component* component) const noexcept;
|
||||
AnimationTask* findTaskFor (Component*) const noexcept;
|
||||
void timerCallback();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentAnimator)
|
||||
|
||||
@@ -238,7 +238,7 @@ void ComponentBuilder::updateChildComponents (Component& parent, const ValueTree
|
||||
|
||||
const int numExistingChildComps = parent.getNumChildComponents();
|
||||
|
||||
Array <Component*> componentsInOrder;
|
||||
Array<Component*> componentsInOrder;
|
||||
componentsInOrder.ensureStorageAllocated (numExistingChildComps);
|
||||
|
||||
{
|
||||
|
||||
@@ -226,7 +226,7 @@ public:
|
||||
|
||||
private:
|
||||
//=============================================================================
|
||||
OwnedArray <TypeHandler> types;
|
||||
OwnedArray<TypeHandler> types;
|
||||
ScopedPointer<Component> component;
|
||||
ImageProvider* imageProvider;
|
||||
#if JUCE_DEBUG
|
||||
|
||||
@@ -287,7 +287,7 @@ void TabbedButtonBar::setTabName (const int tabIndex, const String& newName)
|
||||
}
|
||||
}
|
||||
|
||||
void TabbedButtonBar::removeTab (const int tabIndex)
|
||||
void TabbedButtonBar::removeTab (const int tabIndex, const bool animate)
|
||||
{
|
||||
const int oldIndex = currentTabIndex;
|
||||
if (tabIndex == currentTabIndex)
|
||||
@@ -296,7 +296,7 @@ void TabbedButtonBar::removeTab (const int tabIndex)
|
||||
tabs.remove (tabIndex);
|
||||
|
||||
setCurrentTabIndex (oldIndex);
|
||||
resized();
|
||||
updateTabPositions (animate);
|
||||
}
|
||||
|
||||
void TabbedButtonBar::moveTab (const int currentIndex, const int newIndex, const bool animate)
|
||||
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
void setTabName (int tabIndex, const String& newName);
|
||||
|
||||
/** Gets rid of one of the tabs. */
|
||||
void removeTab (int tabIndex);
|
||||
void removeTab (int tabIndex, bool animate = false);
|
||||
|
||||
/** Moves a tab to a new index in the list.
|
||||
Pass -1 as the index to move it to the end of the list.
|
||||
|
||||
@@ -346,15 +346,15 @@ void Viewport::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& whe
|
||||
Component::mouseWheelMove (e, wheel);
|
||||
}
|
||||
|
||||
static float rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept
|
||||
static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept
|
||||
{
|
||||
if (distance == 0)
|
||||
return 0;
|
||||
|
||||
distance *= 14.0f * singleStepSize;
|
||||
|
||||
return distance < 0 ? jmin (distance, -1.0f)
|
||||
: jmax (distance, 1.0f);
|
||||
return roundToInt (distance < 0 ? jmin (distance, -1.0f)
|
||||
: jmax (distance, 1.0f));
|
||||
}
|
||||
|
||||
bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel)
|
||||
@@ -366,26 +366,23 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelD
|
||||
|
||||
if (canScrollHorz || canScrollVert)
|
||||
{
|
||||
float wheelIncrementX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX);
|
||||
float wheelIncrementY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY);
|
||||
const int deltaX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX);
|
||||
const int deltaY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY);
|
||||
|
||||
Point<int> pos (getViewPosition());
|
||||
|
||||
if (wheelIncrementX != 0 && wheelIncrementY != 0 && canScrollHorz && canScrollVert)
|
||||
if (deltaX != 0 && deltaY != 0 && canScrollHorz && canScrollVert)
|
||||
{
|
||||
pos.setX (pos.x - roundToInt (wheelIncrementX));
|
||||
pos.setY (pos.y - roundToInt (wheelIncrementY));
|
||||
pos.x -= deltaX;
|
||||
pos.y -= deltaY;
|
||||
}
|
||||
else if (canScrollHorz && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! canScrollVert))
|
||||
else if (canScrollHorz && (deltaX != 0 || e.mods.isShiftDown() || ! canScrollVert))
|
||||
{
|
||||
if (wheelIncrementX == 0 && ! canScrollVert)
|
||||
wheelIncrementX = wheelIncrementY;
|
||||
|
||||
pos.setX (pos.x - roundToInt (wheelIncrementX));
|
||||
pos.x -= deltaX != 0 ? deltaX : deltaY;
|
||||
}
|
||||
else if (canScrollVert && wheelIncrementY != 0)
|
||||
else if (canScrollVert && deltaY != 0)
|
||||
{
|
||||
pos.setY (pos.y - roundToInt (wheelIncrementY));
|
||||
pos.y -= deltaY;
|
||||
}
|
||||
|
||||
if (pos != getViewPosition())
|
||||
|
||||
@@ -111,6 +111,9 @@ LookAndFeel_V2::LookAndFeel_V2()
|
||||
TextPropertyComponent::textColourId, 0xff000000,
|
||||
TextPropertyComponent::outlineColourId, standardOutlineColour,
|
||||
|
||||
BooleanPropertyComponent::backgroundColourId, 0xffffffff,
|
||||
BooleanPropertyComponent::outlineColourId, standardOutlineColour,
|
||||
|
||||
ListBox::backgroundColourId, 0xffffffff,
|
||||
ListBox::outlineColourId, standardOutlineColour,
|
||||
ListBox::textColourId, 0xff000000,
|
||||
@@ -238,24 +241,19 @@ void LookAndFeel_V2::drawButtonBackground (Graphics& g,
|
||||
button.isConnectedOnBottom());
|
||||
}
|
||||
|
||||
Font LookAndFeel_V2::getTextButtonFont (TextButton& button)
|
||||
Font LookAndFeel_V2::getTextButtonFont (TextButton&, int buttonHeight)
|
||||
{
|
||||
return button.getFont();
|
||||
return Font (jmin (15.0f, buttonHeight * 0.6f));
|
||||
}
|
||||
|
||||
void LookAndFeel_V2::changeTextButtonWidthToFitText (TextButton& b, int newHeight)
|
||||
int LookAndFeel_V2::getTextButtonWidthToFitText (TextButton& b, int buttonHeight)
|
||||
{
|
||||
if (newHeight >= 0)
|
||||
b.setSize (jmax (1, b.getWidth()), newHeight);
|
||||
else
|
||||
newHeight = b.getHeight();
|
||||
|
||||
b.setSize (getTextButtonFont (b).getStringWidth (b.getButtonText()) + newHeight, newHeight);
|
||||
return getTextButtonFont (b, buttonHeight).getStringWidth (b.getButtonText()) + buttonHeight;
|
||||
}
|
||||
|
||||
void LookAndFeel_V2::drawButtonText (Graphics& g, TextButton& button, bool /*isMouseOverButton*/, bool /*isButtonDown*/)
|
||||
{
|
||||
Font font (getTextButtonFont (button));
|
||||
Font font (getTextButtonFont (button, button.getHeight()));
|
||||
g.setFont (font);
|
||||
g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId
|
||||
: TextButton::textColourOffId)
|
||||
@@ -452,8 +450,7 @@ void LookAndFeel_V2::drawAlertBox (Graphics& g, AlertWindow& alert,
|
||||
colour = alert.getAlertType() == AlertWindow::InfoIcon ? (uint32) 0x605555ff : (uint32) 0x40b69900;
|
||||
character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?';
|
||||
|
||||
icon.addEllipse ((float) iconRect.getX(), (float) iconRect.getY(),
|
||||
(float) iconRect.getWidth(), (float) iconRect.getHeight());
|
||||
icon.addEllipse (iconRect.toFloat());
|
||||
}
|
||||
|
||||
GlyphArrangement ga;
|
||||
@@ -1007,6 +1004,16 @@ void LookAndFeel_V2::drawPopupMenuItem (Graphics& g, const Rectangle<int>& area,
|
||||
}
|
||||
}
|
||||
|
||||
void LookAndFeel_V2::drawPopupMenuSectionHeader (Graphics& g, const Rectangle<int>& area, const String& sectionName)
|
||||
{
|
||||
g.setFont (getPopupMenuFont().boldened());
|
||||
g.setColour (findColour (PopupMenu::headerTextColourId));
|
||||
|
||||
g.drawFittedText (sectionName,
|
||||
area.getX() + 12, area.getY(), area.getWidth() - 16, (int) (area.getHeight() * 0.8f),
|
||||
Justification::bottomLeft, 1);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int LookAndFeel_V2::getMenuWindowFlags()
|
||||
{
|
||||
@@ -1183,13 +1190,11 @@ void LookAndFeel_V2::drawLabel (Graphics& g, Label& label)
|
||||
|
||||
g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
|
||||
g.setFont (font);
|
||||
g.drawFittedText (label.getText(),
|
||||
label.getHorizontalBorderSize(),
|
||||
label.getVerticalBorderSize(),
|
||||
label.getWidth() - 2 * label.getHorizontalBorderSize(),
|
||||
label.getHeight() - 2 * label.getVerticalBorderSize(),
|
||||
label.getJustificationType(),
|
||||
jmax (1, (int) (label.getHeight() / font.getHeight())),
|
||||
|
||||
Rectangle<int> textArea (label.getBorderSize().subtractedFrom (label.getLocalBounds()));
|
||||
|
||||
g.drawFittedText (label.getText(), textArea, label.getJustificationType(),
|
||||
jmax (1, (int) (textArea.getHeight() / font.getHeight())),
|
||||
label.getMinimumHorizontalScale());
|
||||
|
||||
g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha));
|
||||
@@ -2365,6 +2370,10 @@ void LookAndFeel_V2::drawCallOutBoxBackground (CallOutBox& box, Graphics& g,
|
||||
g.strokePath (path, PathStrokeType (2.0f));
|
||||
}
|
||||
|
||||
int LookAndFeel_V2::getCallOutBoxBorderSize (const CallOutBox&)
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AttributedString LookAndFeel_V2::createFileChooserHeaderText (const String& title,
|
||||
|
||||
@@ -39,16 +39,14 @@ public:
|
||||
~LookAndFeel_V2();
|
||||
|
||||
//==============================================================================
|
||||
void drawButtonBackground (Graphics&, Button& button, const Colour& backgroundColour,
|
||||
void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
|
||||
bool isMouseOverButton, bool isButtonDown) override;
|
||||
Font getTextButtonFont (TextButton&, int buttonHeight) override;
|
||||
|
||||
Font getTextButtonFont (TextButton&) override;
|
||||
void drawButtonText (Graphics&, TextButton&, bool isMouseOverButton, bool isButtonDown) override;
|
||||
int getTextButtonWidthToFitText (TextButton&, int buttonHeight) override;
|
||||
|
||||
void drawButtonText (Graphics&, TextButton& button,
|
||||
bool isMouseOverButton, bool isButtonDown) override;
|
||||
void changeTextButtonWidthToFitText (TextButton&, int newHeight) override;
|
||||
|
||||
void drawToggleButton (Graphics&, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) override;
|
||||
void drawToggleButton (Graphics&, ToggleButton&, bool isMouseOverButton, bool isButtonDown) override;
|
||||
|
||||
void changeToggleButtonWidthToFitText (ToggleButton&) override;
|
||||
|
||||
@@ -78,17 +76,17 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
bool areScrollbarButtonsVisible() override;
|
||||
void drawScrollbarButton (Graphics& g, ScrollBar&, int width, int height, int buttonDirection,
|
||||
void drawScrollbarButton (Graphics&, ScrollBar&, int width, int height, int buttonDirection,
|
||||
bool isScrollbarVertical, bool isMouseOverButton, bool isButtonDown) override;
|
||||
|
||||
void drawScrollbar (Graphics& g, ScrollBar&, int x, int y, int width, int height,
|
||||
void drawScrollbar (Graphics&, ScrollBar&, int x, int y, int width, int height,
|
||||
bool isScrollbarVertical, int thumbStartPosition, int thumbSize,
|
||||
bool isMouseOver, bool isMouseDown) override;
|
||||
|
||||
ImageEffectFilter* getScrollbarEffect() override;
|
||||
int getMinimumScrollbarThumbSize (ScrollBar&) override;
|
||||
int getDefaultScrollbarWidth() override;
|
||||
int getScrollbarButtonSize (ScrollBar& scrollbar) override;
|
||||
int getScrollbarButtonSize (ScrollBar&) override;
|
||||
|
||||
//==============================================================================
|
||||
Path getTickShape (float height) override;
|
||||
@@ -139,6 +137,9 @@ public:
|
||||
const String& text, const String& shortcutKeyText,
|
||||
const Drawable* icon, const Colour* textColour) override;
|
||||
|
||||
void drawPopupMenuSectionHeader (Graphics&, const Rectangle<int>& area,
|
||||
const String& sectionName) override;
|
||||
|
||||
Font getPopupMenuFont() override;
|
||||
|
||||
void drawPopupMenuUpDownArrow (Graphics&, int width, int height, bool isScrollUpArrow) override;
|
||||
@@ -199,7 +200,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
Button* createFilenameComponentBrowseButton (const String& text) override;
|
||||
void layoutFilenameComponent (FilenameComponent& filenameComp, ComboBox* filenameBox, Button* browseButton) override;
|
||||
void layoutFilenameComponent (FilenameComponent&, ComboBox* filenameBox, Button* browseButton) override;
|
||||
|
||||
//==============================================================================
|
||||
void drawConcertinaPanelHeader (Graphics&, const Rectangle<int>& area,
|
||||
@@ -250,8 +251,8 @@ public:
|
||||
void drawTabbedButtonBarBackground (TabbedButtonBar&, Graphics&) override;
|
||||
void drawTabAreaBehindFrontButton (TabbedButtonBar&, Graphics&, int w, int h) override;
|
||||
|
||||
void createTabButtonShape (TabBarButton&, Path& path, bool isMouseOver, bool isMouseDown) override;
|
||||
void fillTabButtonShape (TabBarButton&, Graphics&, const Path& path, bool isMouseOver, bool isMouseDown) override;
|
||||
void createTabButtonShape (TabBarButton&, Path&, bool isMouseOver, bool isMouseDown) override;
|
||||
void fillTabButtonShape (TabBarButton&, Graphics&, const Path&, bool isMouseOver, bool isMouseDown) override;
|
||||
|
||||
Button* createTabBarExtrasButton() override;
|
||||
|
||||
@@ -287,11 +288,12 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path& path, Image& cachedImage) override;
|
||||
int getCallOutBoxBorderSize (const CallOutBox&) override;
|
||||
|
||||
//==============================================================================
|
||||
void drawLevelMeter (Graphics&, int width, int height, float level) override;
|
||||
|
||||
void drawKeymapChangeButton (Graphics&, int width, int height, Button& button, const String& keyDescription) override;
|
||||
void drawKeymapChangeButton (Graphics&, int width, int height, Button&, const String& keyDescription) override;
|
||||
|
||||
//==============================================================================
|
||||
/** Draws a 3D raised (or indented) bevel using two colours.
|
||||
@@ -318,15 +320,15 @@ public:
|
||||
|
||||
/** Utility function to draw a shiny, glassy circle (for round LED-type buttons). */
|
||||
static void drawGlassSphere (Graphics&, float x, float y, float diameter,
|
||||
const Colour& colour, float outlineThickness) noexcept;
|
||||
const Colour&, float outlineThickness) noexcept;
|
||||
|
||||
static void drawGlassPointer (Graphics&, float x, float y, float diameter,
|
||||
const Colour& colour, float outlineThickness, int direction) noexcept;
|
||||
const Colour&, float outlineThickness, int direction) noexcept;
|
||||
|
||||
/** Utility function to draw a shiny, glassy oblong (for text buttons). */
|
||||
static void drawGlassLozenge (Graphics&,
|
||||
float x, float y, float width, float height,
|
||||
const Colour& colour, float outlineThickness, float cornerSize,
|
||||
const Colour&, float outlineThickness, float cornerSize,
|
||||
bool flatOnLeft, bool flatOnRight, bool flatOnTop, bool flatOnBottom) noexcept;
|
||||
|
||||
private:
|
||||
@@ -335,7 +337,7 @@ private:
|
||||
|
||||
void drawShinyButtonShape (Graphics&,
|
||||
float x, float y, float w, float h, float maxCornerSize,
|
||||
const Colour& baseColour, float strokeWidth,
|
||||
const Colour&, float strokeWidth,
|
||||
bool flatOnLeft, bool flatOnRight, bool flatOnTop, bool flatOnBottom) noexcept;
|
||||
|
||||
class GlassWindowButton;
|
||||
|
||||
@@ -30,8 +30,8 @@ LookAndFeel_V3::LookAndFeel_V3()
|
||||
setColour (TextButton::buttonColourId, textButtonColour);
|
||||
setColour (ComboBox::buttonColourId, textButtonColour);
|
||||
setColour (TextEditor::outlineColourId, Colours::transparentBlack);
|
||||
setColour (TabbedButtonBar::tabOutlineColourId, Colour (0xff999999));
|
||||
setColour (TabbedComponent::outlineColourId, Colour (0xff999999));
|
||||
setColour (TabbedButtonBar::tabOutlineColourId, Colour (0x66000000));
|
||||
setColour (TabbedComponent::outlineColourId, Colour (0x66000000));
|
||||
setColour (Slider::trackColourId, Colour (0xbbffffff));
|
||||
setColour (Slider::thumbColourId, Colour (0xffddddff));
|
||||
setColour (BubbleComponent::backgroundColourId, Colour (0xeeeeeedd));
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
MenuBarComponent::MenuBarComponent (MenuBarModel* model_)
|
||||
MenuBarComponent::MenuBarComponent (MenuBarModel* m)
|
||||
: model (nullptr),
|
||||
itemUnderMouse (-1),
|
||||
currentPopupIndex (-1),
|
||||
@@ -32,7 +32,7 @@ MenuBarComponent::MenuBarComponent (MenuBarModel* model_)
|
||||
setWantsKeyboardFocus (false);
|
||||
setMouseClickGrabsKeyboardFocus (false);
|
||||
|
||||
setModel (model_);
|
||||
setModel (m);
|
||||
}
|
||||
|
||||
MenuBarComponent::~MenuBarComponent()
|
||||
@@ -284,22 +284,26 @@ void MenuBarComponent::mouseMove (const MouseEvent& e)
|
||||
|
||||
bool MenuBarComponent::keyPressed (const KeyPress& key)
|
||||
{
|
||||
bool used = false;
|
||||
const int numMenus = menuNames.size();
|
||||
const int currentIndex = jlimit (0, menuNames.size() - 1, currentPopupIndex);
|
||||
|
||||
if (key.isKeyCode (KeyPress::leftKey))
|
||||
if (numMenus > 0)
|
||||
{
|
||||
showMenu ((currentIndex + numMenus - 1) % numMenus);
|
||||
used = true;
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::rightKey))
|
||||
{
|
||||
showMenu ((currentIndex + 1) % numMenus);
|
||||
used = true;
|
||||
const int currentIndex = jlimit (0, numMenus - 1, currentPopupIndex);
|
||||
|
||||
if (key.isKeyCode (KeyPress::leftKey))
|
||||
{
|
||||
showMenu ((currentIndex + numMenus - 1) % numMenus);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.isKeyCode (KeyPress::rightKey))
|
||||
{
|
||||
showMenu ((currentIndex + 1) % numMenus);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return used;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuBarItemsChanged (MenuBarModel* /*menuBarModel*/)
|
||||
|
||||
@@ -40,9 +40,9 @@ public:
|
||||
//==============================================================================
|
||||
/** Creates a menu bar.
|
||||
|
||||
@param model the model object to use to control this bar. You can
|
||||
pass 0 into this if you like, and set the model later
|
||||
using the setModel() method
|
||||
@param model the model object to use to control this bar. You can
|
||||
pass nullptr into this if you like, and set the model
|
||||
later using the setModel() method
|
||||
*/
|
||||
MenuBarComponent (MenuBarModel* model);
|
||||
|
||||
@@ -57,8 +57,7 @@ public:
|
||||
*/
|
||||
void setModel (MenuBarModel* newModel);
|
||||
|
||||
/** Returns the current menu bar model being used.
|
||||
*/
|
||||
/** Returns the current menu bar model being used. */
|
||||
MenuBarModel* getModel() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
|
||||
@@ -80,8 +80,7 @@ public:
|
||||
virtual ~Listener() {}
|
||||
|
||||
//==============================================================================
|
||||
/** This callback is made when items are changed in the menu bar model.
|
||||
*/
|
||||
/** This callback is made when items are changed in the menu bar model. */
|
||||
virtual void menuBarItemsChanged (MenuBarModel* menuBarModel) = 0;
|
||||
|
||||
/** This callback is made when an application command is invoked that
|
||||
@@ -101,7 +100,6 @@ public:
|
||||
void addListener (Listener* listenerToAdd) noexcept;
|
||||
|
||||
/** Removes a listener.
|
||||
|
||||
@see addListener
|
||||
*/
|
||||
void removeListener (Listener* listenerToRemove) noexcept;
|
||||
@@ -130,7 +128,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC || DOXYGEN
|
||||
/** MAC ONLY - Sets the model that is currently being shown as the main
|
||||
/** OSX ONLY - Sets the model that is currently being shown as the main
|
||||
menu bar at the top of the screen on the Mac.
|
||||
|
||||
You can pass 0 to stop the current model being displayed. Be careful
|
||||
@@ -151,12 +149,12 @@ public:
|
||||
const PopupMenu* extraAppleMenuItems = nullptr,
|
||||
const String& recentItemsMenuName = String::empty);
|
||||
|
||||
/** MAC ONLY - Returns the menu model that is currently being shown as
|
||||
/** OSX ONLY - Returns the menu model that is currently being shown as
|
||||
the main menu bar.
|
||||
*/
|
||||
static MenuBarModel* getMacMainMenu();
|
||||
|
||||
/** MAC ONLY - Returns the menu that was last passed as the extraAppleMenuItems
|
||||
/** OSX ONLY - Returns the menu that was last passed as the extraAppleMenuItems
|
||||
argument to setMacMainMenu(), or nullptr if none was specified.
|
||||
*/
|
||||
static const PopupMenu* getMacExtraAppleItemsMenu();
|
||||
@@ -164,7 +162,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) override;
|
||||
void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&) override;
|
||||
/** @internal */
|
||||
void applicationCommandListChanged() override;
|
||||
/** @internal */
|
||||
@@ -172,7 +170,7 @@ public:
|
||||
|
||||
private:
|
||||
ApplicationCommandManager* manager;
|
||||
ListenerList <Listener> listeners;
|
||||
ListenerList<Listener> listeners;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarModel)
|
||||
};
|
||||
|
||||
@@ -740,7 +740,7 @@ public:
|
||||
|
||||
void ensureItemIsVisible (const int itemID, int wantedY)
|
||||
{
|
||||
jassert (itemID != 0)
|
||||
jassert (itemID != 0);
|
||||
|
||||
for (int i = items.size(); --i >= 0;)
|
||||
{
|
||||
@@ -980,12 +980,12 @@ public:
|
||||
void timerCallback() override
|
||||
{
|
||||
if (window.windowIsStillValid())
|
||||
handleMousePosition (source.getScreenPosition());
|
||||
handleMousePosition (source.getScreenPosition().roundToInt());
|
||||
}
|
||||
|
||||
bool isOver() const
|
||||
{
|
||||
return window.reallyContains (window.getLocalPoint (nullptr, source.getScreenPosition()), true);
|
||||
return window.reallyContains (window.getLocalPoint (nullptr, source.getScreenPosition()).roundToInt(), true);
|
||||
}
|
||||
|
||||
MenuWindow& window;
|
||||
@@ -1216,12 +1216,7 @@ public:
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.setFont (getLookAndFeel().getPopupMenuFont().boldened());
|
||||
g.setColour (findColour (PopupMenu::headerTextColourId));
|
||||
|
||||
g.drawFittedText (getName(),
|
||||
12, 0, getWidth() - 16, proportionOfHeight (0.8f),
|
||||
Justification::bottomLeft, 1);
|
||||
getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());
|
||||
}
|
||||
|
||||
void getIdealSize (int& idealWidth, int& idealHeight)
|
||||
|
||||
@@ -562,6 +562,9 @@ public:
|
||||
const Drawable* icon,
|
||||
const Colour* textColour) = 0;
|
||||
|
||||
virtual void drawPopupMenuSectionHeader (Graphics&, const Rectangle<int>& area,
|
||||
const String& sectionName) = 0;
|
||||
|
||||
/** Returns the size and style of font to use in popup menus. */
|
||||
virtual Font getPopupMenuFont() = 0;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ void ComponentDragger::dragComponent (Component* const componentToDrag, const Mo
|
||||
// so their coordinates become wrong after the first one moves the window, so in that case, we'll use
|
||||
// the current mouse position instead of the one that the event contains...
|
||||
if (componentToDrag->isOnDesktop())
|
||||
bounds += componentToDrag->getLocalPoint (nullptr, e.source.getScreenPosition()) - mouseDownWithinTarget;
|
||||
bounds += componentToDrag->getLocalPoint (nullptr, e.source.getScreenPosition()).roundToInt() - mouseDownWithinTarget;
|
||||
else
|
||||
bounds += e.getEventRelativeTo (componentToDrag).getPosition() - mouseDownWithinTarget;
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ public:
|
||||
if (current->isInterestedInDragSource (sourceDetails))
|
||||
current->itemDragExit (sourceDetails);
|
||||
}
|
||||
|
||||
owner.dragOperationEnded();
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
@@ -164,14 +166,14 @@ public:
|
||||
|
||||
if (sourceDetails.sourceComponent == nullptr)
|
||||
{
|
||||
delete this;
|
||||
deleteSelf();
|
||||
}
|
||||
else if (! isMouseButtonDownAnywhere())
|
||||
{
|
||||
if (mouseDragSource != nullptr)
|
||||
mouseDragSource->removeMouseListener (this);
|
||||
|
||||
delete this;
|
||||
deleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +182,7 @@ public:
|
||||
if (key == KeyPress::escapeKey)
|
||||
{
|
||||
dismissWithAnimation (true);
|
||||
delete this;
|
||||
deleteSelf();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -212,7 +214,22 @@ private:
|
||||
|
||||
DragAndDropTarget* getCurrentlyOver() const noexcept
|
||||
{
|
||||
return dynamic_cast <DragAndDropTarget*> (currentlyOverComp.get());
|
||||
return dynamic_cast<DragAndDropTarget*> (currentlyOverComp.get());
|
||||
}
|
||||
|
||||
static Component* findDesktopComponentBelow (Point<int> screenPos)
|
||||
{
|
||||
Desktop& desktop = Desktop::getInstance();
|
||||
|
||||
for (int i = desktop.getNumComponents(); --i >= 0;)
|
||||
{
|
||||
Component* c = desktop.getComponent(i);
|
||||
|
||||
if (Component* hit = c->getComponentAt (c->getLocalPoint (nullptr, screenPos)))
|
||||
return hit;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DragAndDropTarget* findTarget (Point<int> screenPos, Point<int>& relativePos,
|
||||
@@ -221,7 +238,7 @@ private:
|
||||
Component* hit = getParentComponent();
|
||||
|
||||
if (hit == nullptr)
|
||||
hit = Desktop::getInstance().findComponentAt (screenPos);
|
||||
hit = findDesktopComponentBelow (screenPos);
|
||||
else
|
||||
hit = hit->getComponentAt (hit->getLocalPoint (nullptr, screenPos));
|
||||
|
||||
@@ -231,7 +248,7 @@ private:
|
||||
|
||||
while (hit != nullptr)
|
||||
{
|
||||
if (DragAndDropTarget* const ddt = dynamic_cast <DragAndDropTarget*> (hit))
|
||||
if (DragAndDropTarget* const ddt = dynamic_cast<DragAndDropTarget*> (hit))
|
||||
{
|
||||
if (ddt->isInterestedInDragSource (details))
|
||||
{
|
||||
@@ -296,12 +313,17 @@ private:
|
||||
&& ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown())
|
||||
{
|
||||
(new ExternalDragAndDropMessage (files, canMoveFiles))->post();
|
||||
delete this;
|
||||
deleteSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteSelf()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void dismissWithAnimation (const bool shouldSnapBack)
|
||||
{
|
||||
setVisible (true);
|
||||
@@ -353,7 +375,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
|
||||
return;
|
||||
}
|
||||
|
||||
const Point<int> lastMouseDown (draggingSource->getLastMouseDownPosition());
|
||||
const Point<int> lastMouseDown (draggingSource->getLastMouseDownPosition().roundToInt());
|
||||
Point<int> imageOffset;
|
||||
|
||||
if (dragImage.isNull())
|
||||
@@ -383,7 +405,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
|
||||
{
|
||||
const float alpha = (distance > hi) ? 0
|
||||
: (hi - distance) / (float) (hi - lo)
|
||||
+ random.nextFloat() * 0.008f;
|
||||
+ random.nextFloat() * 0.008f;
|
||||
|
||||
dragImage.multiplyAlphaAt (x, y, alpha);
|
||||
}
|
||||
@@ -414,7 +436,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Component* const thisComp = dynamic_cast <Component*> (this))
|
||||
if (Component* const thisComp = dynamic_cast<Component*> (this))
|
||||
{
|
||||
thisComp->addChildComponent (dragImageComponent);
|
||||
}
|
||||
@@ -425,8 +447,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
|
||||
}
|
||||
}
|
||||
|
||||
static_cast <DragImageComponent*> (dragImageComponent.get())->updateLocation (false, lastMouseDown);
|
||||
dragImageComponent->setVisible (true);
|
||||
static_cast<DragImageComponent*> (dragImageComponent.get())->updateLocation (false, lastMouseDown);
|
||||
dragImageComponent->enterModalState();
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
@@ -435,6 +456,8 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
|
||||
if (ComponentPeer* const peer = dragImageComponent->getPeer())
|
||||
peer->performAnyPendingRepaintsNow();
|
||||
#endif
|
||||
|
||||
dragOperationStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,6 +482,9 @@ bool DragAndDropContainer::shouldDropFilesWhenDraggedExternally (const DragAndDr
|
||||
return false;
|
||||
}
|
||||
|
||||
void DragAndDropContainer::dragOperationStarted() {}
|
||||
void DragAndDropContainer::dragOperationEnded() {}
|
||||
|
||||
//==============================================================================
|
||||
DragAndDropTarget::SourceDetails::SourceDetails (const var& desc, Component* comp, Point<int> pos) noexcept
|
||||
: description (desc),
|
||||
|
||||
@@ -165,6 +165,12 @@ protected:
|
||||
virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
|
||||
StringArray& files, bool& canMoveFiles);
|
||||
|
||||
/** Subclasses can override this to be told when a drag starts. */
|
||||
virtual void dragOperationStarted();
|
||||
|
||||
/** Subclasses can override this to be told when a drag finishes. */
|
||||
virtual void dragOperationEnded();
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class DragImageComponent;
|
||||
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
SpinLock MouseCursor::SharedCursorHandle::lock;
|
||||
|
||||
//==============================================================================
|
||||
MouseCursor::MouseCursor()
|
||||
MouseCursor::MouseCursor() noexcept
|
||||
: cursorHandle (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -72,10 +72,10 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
/** Creates the standard arrow cursor. */
|
||||
MouseCursor();
|
||||
MouseCursor() noexcept;
|
||||
|
||||
/** Creates one of the standard mouse cursor */
|
||||
MouseCursor (StandardCursorType type);
|
||||
MouseCursor (StandardCursorType);
|
||||
|
||||
/** Creates a custom cursor from an image.
|
||||
|
||||
|
||||
@@ -23,17 +23,18 @@
|
||||
*/
|
||||
|
||||
MouseEvent::MouseEvent (MouseInputSource inputSource,
|
||||
Point<int> position,
|
||||
Point<float> pos,
|
||||
ModifierKeys modKeys,
|
||||
Component* const eventComp,
|
||||
Component* const originator,
|
||||
Time time,
|
||||
Point<int> downPos,
|
||||
Point<float> downPos,
|
||||
Time downTime,
|
||||
const int numClicks,
|
||||
const bool mouseWasDragged) noexcept
|
||||
: x (position.x),
|
||||
y (position.y),
|
||||
: position (pos),
|
||||
x (roundToInt (pos.x)),
|
||||
y (roundToInt (pos.y)),
|
||||
mods (modKeys),
|
||||
eventComponent (eventComp),
|
||||
originalComponent (originator),
|
||||
@@ -55,19 +56,26 @@ MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent) cons
|
||||
{
|
||||
jassert (otherComponent != nullptr);
|
||||
|
||||
return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, getPosition()),
|
||||
return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, position),
|
||||
mods, otherComponent, originalComponent, eventTime,
|
||||
otherComponent->getLocalPoint (eventComponent, mouseDownPos),
|
||||
mouseDownTime, numberOfClicks, wasMovedSinceMouseDown != 0);
|
||||
}
|
||||
|
||||
MouseEvent MouseEvent::withNewPosition (Point<int> newPosition) const noexcept
|
||||
MouseEvent MouseEvent::withNewPosition (Point<float> newPosition) const noexcept
|
||||
{
|
||||
return MouseEvent (source, newPosition, mods, eventComponent, originalComponent,
|
||||
eventTime, mouseDownPos, mouseDownTime,
|
||||
numberOfClicks, wasMovedSinceMouseDown != 0);
|
||||
}
|
||||
|
||||
MouseEvent MouseEvent::withNewPosition (Point<int> newPosition) const noexcept
|
||||
{
|
||||
return MouseEvent (source, newPosition.toFloat(), mods, eventComponent, originalComponent,
|
||||
eventTime, mouseDownPos, mouseDownTime,
|
||||
numberOfClicks, wasMovedSinceMouseDown != 0);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool MouseEvent::mouseWasClicked() const noexcept
|
||||
{
|
||||
@@ -86,17 +94,17 @@ int MouseEvent::getLengthOfMousePress() const noexcept
|
||||
Point<int> MouseEvent::getPosition() const noexcept { return Point<int> (x, y); }
|
||||
Point<int> MouseEvent::getScreenPosition() const { return eventComponent->localPointToGlobal (getPosition()); }
|
||||
|
||||
Point<int> MouseEvent::getMouseDownPosition() const noexcept { return mouseDownPos; }
|
||||
Point<int> MouseEvent::getMouseDownScreenPosition() const { return eventComponent->localPointToGlobal (mouseDownPos); }
|
||||
Point<int> MouseEvent::getMouseDownPosition() const noexcept { return mouseDownPos.roundToInt(); }
|
||||
Point<int> MouseEvent::getMouseDownScreenPosition() const { return eventComponent->localPointToGlobal (mouseDownPos).roundToInt(); }
|
||||
|
||||
Point<int> MouseEvent::getOffsetFromDragStart() const noexcept { return getPosition() - mouseDownPos; }
|
||||
int MouseEvent::getDistanceFromDragStart() const noexcept { return mouseDownPos.getDistanceFrom (getPosition()); }
|
||||
Point<int> MouseEvent::getOffsetFromDragStart() const noexcept { return (position - mouseDownPos).roundToInt(); }
|
||||
int MouseEvent::getDistanceFromDragStart() const noexcept { return roundToInt (mouseDownPos.getDistanceFrom (position)); }
|
||||
|
||||
int MouseEvent::getMouseDownX() const noexcept { return mouseDownPos.x; }
|
||||
int MouseEvent::getMouseDownY() const noexcept { return mouseDownPos.y; }
|
||||
int MouseEvent::getMouseDownX() const noexcept { return roundToInt (mouseDownPos.x); }
|
||||
int MouseEvent::getMouseDownY() const noexcept { return roundToInt (mouseDownPos.y); }
|
||||
|
||||
int MouseEvent::getDistanceFromDragStartX() const noexcept { return x - mouseDownPos.x; }
|
||||
int MouseEvent::getDistanceFromDragStartY() const noexcept { return y - mouseDownPos.y; }
|
||||
int MouseEvent::getDistanceFromDragStartX() const noexcept { return getOffsetFromDragStart().x; }
|
||||
int MouseEvent::getDistanceFromDragStartY() const noexcept { return getOffsetFromDragStart().y; }
|
||||
|
||||
int MouseEvent::getScreenX() const { return getScreenPosition().x; }
|
||||
int MouseEvent::getScreenY() const { return getScreenPosition().y; }
|
||||
|
||||
@@ -57,12 +57,12 @@ public:
|
||||
@param mouseWasDragged whether the mouse has been dragged significantly since the previous mouse-down
|
||||
*/
|
||||
MouseEvent (MouseInputSource source,
|
||||
Point<int> position,
|
||||
Point<float> position,
|
||||
ModifierKeys modifiers,
|
||||
Component* eventComponent,
|
||||
Component* originator,
|
||||
Time eventTime,
|
||||
Point<int> mouseDownPos,
|
||||
Point<float> mouseDownPos,
|
||||
Time mouseDownTime,
|
||||
int numberOfClicks,
|
||||
bool mouseWasDragged) noexcept;
|
||||
@@ -71,10 +71,22 @@ public:
|
||||
~MouseEvent() noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** The position of the mouse when the event occurred.
|
||||
|
||||
This value is relative to the top-left of the component to which the
|
||||
event applies (as indicated by the MouseEvent::eventComponent field).
|
||||
|
||||
This is a more accurate floating-point version of the position returned by
|
||||
getPosition() and the integer x and y member variables.
|
||||
*/
|
||||
const Point<float> position;
|
||||
|
||||
/** The x-position of the mouse when the event occurred.
|
||||
|
||||
This value is relative to the top-left of the component to which the
|
||||
event applies (as indicated by the MouseEvent::eventComponent field).
|
||||
|
||||
For a floating-point coordinate, see MouseEvent::position
|
||||
*/
|
||||
const int x;
|
||||
|
||||
@@ -82,6 +94,8 @@ public:
|
||||
|
||||
This value is relative to the top-left of the component to which the
|
||||
event applies (as indicated by the MouseEvent::eventComponent field).
|
||||
|
||||
For a floating-point coordinate, see MouseEvent::position
|
||||
*/
|
||||
const int y;
|
||||
|
||||
@@ -130,25 +144,19 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the x coordinate of the last place that a mouse was pressed.
|
||||
|
||||
The coordinate is relative to the component specified in MouseEvent::component.
|
||||
|
||||
@see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked
|
||||
*/
|
||||
int getMouseDownX() const noexcept;
|
||||
|
||||
/** Returns the y coordinate of the last place that a mouse was pressed.
|
||||
|
||||
The coordinate is relative to the component specified in MouseEvent::component.
|
||||
|
||||
@see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked
|
||||
*/
|
||||
int getMouseDownY() const noexcept;
|
||||
|
||||
/** Returns the coordinates of the last place that a mouse was pressed.
|
||||
|
||||
The coordinates are relative to the component specified in MouseEvent::component.
|
||||
|
||||
@see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked
|
||||
*/
|
||||
Point<int> getMouseDownPosition() const noexcept;
|
||||
@@ -221,6 +229,8 @@ public:
|
||||
|
||||
This position is relative to the top-left of the component to which the
|
||||
event applies (as indicated by the MouseEvent::eventComponent field).
|
||||
|
||||
For a floating-point position, see MouseEvent::position
|
||||
*/
|
||||
Point<int> getPosition() const noexcept;
|
||||
|
||||
@@ -269,6 +279,12 @@ public:
|
||||
*/
|
||||
MouseEvent getEventRelativeTo (Component* newComponent) const noexcept;
|
||||
|
||||
/** Creates a copy of this event with a different position.
|
||||
All other members of the event object are the same, but the x and y are
|
||||
replaced with these new values.
|
||||
*/
|
||||
MouseEvent withNewPosition (Point<float> newPosition) const noexcept;
|
||||
|
||||
/** Creates a copy of this event with a different position.
|
||||
All other members of the event object are the same, but the x and y are
|
||||
replaced with these new values.
|
||||
@@ -297,7 +313,7 @@ public:
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const Point<int> mouseDownPos;
|
||||
const Point<float> mouseDownPos;
|
||||
const uint8 numberOfClicks, wasMovedSinceMouseDown;
|
||||
|
||||
MouseEvent& operator= (const MouseEvent&);
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
return lastPeer;
|
||||
}
|
||||
|
||||
static Point<int> screenPosToLocalPos (Component& comp, Point<int> pos)
|
||||
static Point<float> screenPosToLocalPos (Component& comp, Point<float> pos)
|
||||
{
|
||||
if (ComponentPeer* const peer = comp.getPeer())
|
||||
{
|
||||
@@ -70,23 +70,25 @@ public:
|
||||
return comp.getLocalPoint (nullptr, ScalingHelpers::unscaledScreenPosToScaled (comp, pos));
|
||||
}
|
||||
|
||||
Component* findComponentAt (Point<int> screenPos)
|
||||
Component* findComponentAt (Point<float> screenPos)
|
||||
{
|
||||
if (ComponentPeer* const peer = getPeer())
|
||||
{
|
||||
Point<int> relativePos (ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(),
|
||||
peer->globalToLocal (screenPos)));
|
||||
Point<float> relativePos (ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(),
|
||||
peer->globalToLocal (screenPos)));
|
||||
Component& comp = peer->getComponent();
|
||||
|
||||
const Point<int> pos (relativePos.roundToInt());
|
||||
|
||||
// (the contains() call is needed to test for overlapping desktop windows)
|
||||
if (comp.contains (relativePos))
|
||||
return comp.getComponentAt (relativePos);
|
||||
if (comp.contains (pos))
|
||||
return comp.getComponentAt (pos);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Point<int> getScreenPosition() const
|
||||
Point<float> getScreenPosition() const
|
||||
{
|
||||
// This needs to return the live position if possible, but it mustn't update the lastScreenPos
|
||||
// value, because that can cause continuity problems.
|
||||
@@ -95,63 +97,63 @@ public:
|
||||
: lastScreenPos));
|
||||
}
|
||||
|
||||
void setScreenPosition (Point<int> p)
|
||||
void setScreenPosition (Point<float> p)
|
||||
{
|
||||
MouseInputSource::setRawMousePosition (ScalingHelpers::scaledScreenPosToUnscaled (p));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_DUMP_MOUSE_EVENTS
|
||||
#define JUCE_MOUSE_EVENT_DBG(desc) DBG ("Mouse " desc << " #" << source.getIndex() \
|
||||
#define JUCE_MOUSE_EVENT_DBG(desc) DBG ("Mouse " << desc << " #" << index \
|
||||
<< ": " << screenPosToLocalPos (comp, screenPos).toString() \
|
||||
<< " - Comp: " << String::toHexString ((int) &comp));
|
||||
<< " - Comp: " << String::toHexString ((pointer_sized_int) &comp));
|
||||
#else
|
||||
#define JUCE_MOUSE_EVENT_DBG(desc)
|
||||
#endif
|
||||
|
||||
void sendMouseEnter (Component& comp, Point<int> screenPos, Time time)
|
||||
void sendMouseEnter (Component& comp, Point<float> screenPos, Time time)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("enter")
|
||||
comp.internalMouseEnter (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time);
|
||||
}
|
||||
|
||||
void sendMouseExit (Component& comp, Point<int> screenPos, Time time)
|
||||
void sendMouseExit (Component& comp, Point<float> screenPos, Time time)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("exit")
|
||||
comp.internalMouseExit (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time);
|
||||
}
|
||||
|
||||
void sendMouseMove (Component& comp, Point<int> screenPos, Time time)
|
||||
void sendMouseMove (Component& comp, Point<float> screenPos, Time time)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("move")
|
||||
comp.internalMouseMove (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time);
|
||||
}
|
||||
|
||||
void sendMouseDown (Component& comp, Point<int> screenPos, Time time)
|
||||
void sendMouseDown (Component& comp, Point<float> screenPos, Time time)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("down")
|
||||
comp.internalMouseDown (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time);
|
||||
}
|
||||
|
||||
void sendMouseDrag (Component& comp, Point<int> screenPos, Time time)
|
||||
void sendMouseDrag (Component& comp, Point<float> screenPos, Time time)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("drag")
|
||||
comp.internalMouseDrag (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time);
|
||||
}
|
||||
|
||||
void sendMouseUp (Component& comp, Point<int> screenPos, Time time, const ModifierKeys oldMods)
|
||||
void sendMouseUp (Component& comp, Point<float> screenPos, Time time, const ModifierKeys oldMods)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("up")
|
||||
comp.internalMouseUp (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, oldMods);
|
||||
}
|
||||
|
||||
void sendMouseWheel (Component& comp, Point<int> screenPos, Time time, const MouseWheelDetails& wheel)
|
||||
void sendMouseWheel (Component& comp, Point<float> screenPos, Time time, const MouseWheelDetails& wheel)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("wheel")
|
||||
comp.internalMouseWheel (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, wheel);
|
||||
}
|
||||
|
||||
void sendMagnifyGesture (Component& comp, Point<int> screenPos, Time time, const float amount)
|
||||
void sendMagnifyGesture (Component& comp, Point<float> screenPos, Time time, const float amount)
|
||||
{
|
||||
JUCE_MOUSE_EVENT_DBG ("magnify")
|
||||
comp.internalMagnifyGesture (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, amount);
|
||||
@@ -159,7 +161,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
// (returns true if the button change caused a modal event loop)
|
||||
bool setButtons (Point<int> screenPos, Time time, const ModifierKeys newButtonState)
|
||||
bool setButtons (Point<float> screenPos, Time time, const ModifierKeys newButtonState)
|
||||
{
|
||||
if (buttonState == newButtonState)
|
||||
return false;
|
||||
@@ -209,7 +211,7 @@ public:
|
||||
return lastCounter != mouseEventCounter;
|
||||
}
|
||||
|
||||
void setComponentUnderMouse (Component* const newComponent, Point<int> screenPos, Time time)
|
||||
void setComponentUnderMouse (Component* const newComponent, Point<float> screenPos, Time time)
|
||||
{
|
||||
Component* current = getComponentUnderMouse();
|
||||
|
||||
@@ -242,7 +244,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setPeer (ComponentPeer& newPeer, Point<int> screenPos, Time time)
|
||||
void setPeer (ComponentPeer& newPeer, Point<float> screenPos, Time time)
|
||||
{
|
||||
ModifierKeys::updateCurrentModifiers();
|
||||
|
||||
@@ -254,7 +256,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setScreenPos (Point<int> newScreenPos, Time time, const bool forceUpdate)
|
||||
void setScreenPos (Point<float> newScreenPos, Time time, const bool forceUpdate)
|
||||
{
|
||||
if (! isDragging())
|
||||
setComponentUnderMouse (findComponentAt (newScreenPos), newScreenPos, time);
|
||||
@@ -272,7 +274,7 @@ public:
|
||||
sendMouseDrag (*current, newScreenPos + unboundedMouseOffset, time);
|
||||
|
||||
if (isUnboundedMouseModeOn)
|
||||
handleUnboundedDrag (current);
|
||||
handleUnboundedDrag (*current);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -285,11 +287,11 @@ public:
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void handleEvent (ComponentPeer& newPeer, Point<int> positionWithinPeer, Time time, const ModifierKeys newMods)
|
||||
void handleEvent (ComponentPeer& newPeer, Point<float> positionWithinPeer, Time time, const ModifierKeys newMods)
|
||||
{
|
||||
lastTime = time;
|
||||
++mouseEventCounter;
|
||||
const Point<int> screenPos (newPeer.localToGlobal (positionWithinPeer));
|
||||
const Point<float> screenPos (newPeer.localToGlobal (positionWithinPeer));
|
||||
|
||||
if (isDragging() && newMods.isAnyMouseButtonDown())
|
||||
{
|
||||
@@ -311,8 +313,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Component* getTargetForGesture (ComponentPeer& peer, Point<int> positionWithinPeer,
|
||||
Time time, Point<int>& screenPos)
|
||||
Component* getTargetForGesture (ComponentPeer& peer, Point<float> positionWithinPeer,
|
||||
Time time, Point<float>& screenPos)
|
||||
{
|
||||
lastTime = time;
|
||||
++mouseEventCounter;
|
||||
@@ -325,27 +327,27 @@ public:
|
||||
return isDragging() ? nullptr : getComponentUnderMouse();
|
||||
}
|
||||
|
||||
void handleWheel (ComponentPeer& peer, Point<int> positionWithinPeer,
|
||||
void handleWheel (ComponentPeer& peer, Point<float> positionWithinPeer,
|
||||
Time time, const MouseWheelDetails& wheel)
|
||||
{
|
||||
Desktop::getInstance().incrementMouseWheelCounter();
|
||||
|
||||
Point<int> screenPos;
|
||||
Point<float> screenPos;
|
||||
if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos))
|
||||
sendMouseWheel (*current, screenPos, time, wheel);
|
||||
}
|
||||
|
||||
void handleMagnifyGesture (ComponentPeer& peer, Point<int> positionWithinPeer,
|
||||
void handleMagnifyGesture (ComponentPeer& peer, Point<float> positionWithinPeer,
|
||||
Time time, const float scaleFactor)
|
||||
{
|
||||
Point<int> screenPos;
|
||||
Point<float> screenPos;
|
||||
if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos))
|
||||
sendMagnifyGesture (*current, screenPos, time, scaleFactor);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Time getLastMouseDownTime() const noexcept { return mouseDowns[0].time; }
|
||||
Point<int> getLastMouseDownPosition() const noexcept { return ScalingHelpers::unscaledScreenPosToScaled (mouseDowns[0].position); }
|
||||
Point<float> getLastMouseDownPosition() const noexcept { return ScalingHelpers::unscaledScreenPosToScaled (mouseDowns[0].position); }
|
||||
|
||||
int getNumberOfMultipleClicks() const noexcept
|
||||
{
|
||||
@@ -397,33 +399,34 @@ public:
|
||||
{
|
||||
// when released, return the mouse to within the component's bounds
|
||||
if (Component* current = getComponentUnderMouse())
|
||||
Desktop::setMousePosition (current->getScreenBounds()
|
||||
.getConstrainedPoint (lastScreenPos));
|
||||
setScreenPosition (current->getScreenBounds().toFloat()
|
||||
.getConstrainedPoint (ScalingHelpers::unscaledScreenPosToScaled (lastScreenPos)));
|
||||
}
|
||||
|
||||
isUnboundedMouseModeOn = enable;
|
||||
unboundedMouseOffset = Point<int>();
|
||||
unboundedMouseOffset = Point<float>();
|
||||
|
||||
revealCursor (true);
|
||||
}
|
||||
}
|
||||
|
||||
void handleUnboundedDrag (Component* current)
|
||||
void handleUnboundedDrag (Component& current)
|
||||
{
|
||||
const Rectangle<int> screenArea (current->getParentMonitorArea().expanded (-2, -2));
|
||||
const Rectangle<float> componentScreenBounds
|
||||
= ScalingHelpers::scaledScreenPosToUnscaled (current.getParentMonitorArea().reduced (2, 2).toFloat());
|
||||
|
||||
if (! screenArea.contains (lastScreenPos))
|
||||
if (! componentScreenBounds.contains (lastScreenPos))
|
||||
{
|
||||
const Point<int> componentCentre (current->getScreenBounds().getCentre());
|
||||
unboundedMouseOffset += (lastScreenPos - componentCentre);
|
||||
Desktop::setMousePosition (componentCentre);
|
||||
const Point<float> componentCentre (current.getScreenBounds().toFloat().getCentre());
|
||||
unboundedMouseOffset += (lastScreenPos - ScalingHelpers::scaledScreenPosToUnscaled (componentCentre));
|
||||
setScreenPosition (componentCentre);
|
||||
}
|
||||
else if (isCursorVisibleUntilOffscreen
|
||||
&& (! unboundedMouseOffset.isOrigin())
|
||||
&& screenArea.contains (lastScreenPos + unboundedMouseOffset))
|
||||
&& componentScreenBounds.contains (lastScreenPos + unboundedMouseOffset))
|
||||
{
|
||||
Desktop::setMousePosition (lastScreenPos + unboundedMouseOffset);
|
||||
unboundedMouseOffset = Point<int>();
|
||||
MouseInputSource::setRawMousePosition (lastScreenPos + unboundedMouseOffset);
|
||||
unboundedMouseOffset = Point<float>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,10 +464,9 @@ public:
|
||||
//==============================================================================
|
||||
const int index;
|
||||
const bool isMouseDevice;
|
||||
Point<int> lastScreenPos;
|
||||
Point<float> lastScreenPos, unboundedMouseOffset; // NB: these are unscaled coords
|
||||
ModifierKeys buttonState;
|
||||
|
||||
Point<int> unboundedMouseOffset;
|
||||
bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen;
|
||||
|
||||
private:
|
||||
@@ -478,7 +480,7 @@ private:
|
||||
{
|
||||
RecentMouseDown() noexcept : peerID (0) {}
|
||||
|
||||
Point<int> position;
|
||||
Point<float> position;
|
||||
Time time;
|
||||
ModifierKeys buttons;
|
||||
uint32 peerID;
|
||||
@@ -486,8 +488,8 @@ private:
|
||||
bool canBePartOfMultipleClickWith (const RecentMouseDown& other, const int maxTimeBetweenMs) const
|
||||
{
|
||||
return time - other.time < RelativeTime::milliseconds (maxTimeBetweenMs)
|
||||
&& abs (position.x - other.position.x) < 8
|
||||
&& abs (position.y - other.position.y) < 8
|
||||
&& std::abs (position.x - other.position.x) < 8
|
||||
&& std::abs (position.y - other.position.y) < 8
|
||||
&& buttons == other.buttons
|
||||
&& peerID == other.peerID;
|
||||
}
|
||||
@@ -497,7 +499,7 @@ private:
|
||||
Time lastTime;
|
||||
bool mouseMovedSignificantlySincePressed;
|
||||
|
||||
void registerMouseDown (Point<int> screenPos, Time time,
|
||||
void registerMouseDown (Point<float> screenPos, Time time,
|
||||
Component& component, const ModifierKeys modifiers) noexcept
|
||||
{
|
||||
for (int i = numElementsInArray (mouseDowns); --i > 0;)
|
||||
@@ -515,7 +517,7 @@ private:
|
||||
mouseMovedSignificantlySincePressed = false;
|
||||
}
|
||||
|
||||
void registerMouseDrag (Point<int> screenPos) noexcept
|
||||
void registerMouseDrag (Point<float> screenPos) noexcept
|
||||
{
|
||||
mouseMovedSignificantlySincePressed = mouseMovedSignificantlySincePressed
|
||||
|| mouseDowns[0].position.getDistanceFrom (screenPos) >= 4;
|
||||
@@ -535,47 +537,44 @@ MouseInputSource& MouseInputSource::operator= (const MouseInputSource& other) no
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool MouseInputSource::isMouse() const { return pimpl->isMouseDevice; }
|
||||
bool MouseInputSource::isTouch() const { return ! isMouse(); }
|
||||
bool MouseInputSource::canHover() const { return isMouse(); }
|
||||
bool MouseInputSource::hasMouseWheel() const { return isMouse(); }
|
||||
int MouseInputSource::getIndex() const { return pimpl->index; }
|
||||
bool MouseInputSource::isDragging() const { return pimpl->isDragging(); }
|
||||
Point<int> MouseInputSource::getScreenPosition() const { return pimpl->getScreenPosition(); }
|
||||
ModifierKeys MouseInputSource::getCurrentModifiers() const { return pimpl->getCurrentModifiers(); }
|
||||
Component* MouseInputSource::getComponentUnderMouse() const { return pimpl->getComponentUnderMouse(); }
|
||||
void MouseInputSource::triggerFakeMove() const { pimpl->triggerFakeMove(); }
|
||||
int MouseInputSource::getNumberOfMultipleClicks() const noexcept { return pimpl->getNumberOfMultipleClicks(); }
|
||||
Time MouseInputSource::getLastMouseDownTime() const noexcept { return pimpl->getLastMouseDownTime(); }
|
||||
Point<int> MouseInputSource::getLastMouseDownPosition() const noexcept { return pimpl->getLastMouseDownPosition(); }
|
||||
bool MouseInputSource::isMouse() const { return pimpl->isMouseDevice; }
|
||||
bool MouseInputSource::isTouch() const { return ! isMouse(); }
|
||||
bool MouseInputSource::canHover() const { return isMouse(); }
|
||||
bool MouseInputSource::hasMouseWheel() const { return isMouse(); }
|
||||
int MouseInputSource::getIndex() const { return pimpl->index; }
|
||||
bool MouseInputSource::isDragging() const { return pimpl->isDragging(); }
|
||||
Point<float> MouseInputSource::getScreenPosition() const { return pimpl->getScreenPosition(); }
|
||||
ModifierKeys MouseInputSource::getCurrentModifiers() const { return pimpl->getCurrentModifiers(); }
|
||||
Component* MouseInputSource::getComponentUnderMouse() const { return pimpl->getComponentUnderMouse(); }
|
||||
void MouseInputSource::triggerFakeMove() const { pimpl->triggerFakeMove(); }
|
||||
int MouseInputSource::getNumberOfMultipleClicks() const noexcept { return pimpl->getNumberOfMultipleClicks(); }
|
||||
Time MouseInputSource::getLastMouseDownTime() const noexcept { return pimpl->getLastMouseDownTime(); }
|
||||
Point<float> MouseInputSource::getLastMouseDownPosition() const noexcept { return pimpl->getLastMouseDownPosition(); }
|
||||
bool MouseInputSource::hasMouseMovedSignificantlySincePressed() const noexcept { return pimpl->hasMouseMovedSignificantlySincePressed(); }
|
||||
bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); }
|
||||
bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); }
|
||||
void MouseInputSource::enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen) const
|
||||
{ pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); }
|
||||
bool MouseInputSource::isUnboundedMouseMovementEnabled() const { return pimpl->isUnboundedMouseModeOn; }
|
||||
bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); }
|
||||
void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); }
|
||||
void MouseInputSource::hideCursor() { pimpl->hideCursor(); }
|
||||
void MouseInputSource::revealCursor() { pimpl->revealCursor (false); }
|
||||
void MouseInputSource::forceMouseCursorUpdate() { pimpl->revealCursor (true); }
|
||||
void MouseInputSource::setScreenPosition (Point<int> p) { pimpl->setScreenPosition (p); }
|
||||
{ pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); }
|
||||
bool MouseInputSource::isUnboundedMouseMovementEnabled() const { return pimpl->isUnboundedMouseModeOn; }
|
||||
bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); }
|
||||
void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); }
|
||||
void MouseInputSource::hideCursor() { pimpl->hideCursor(); }
|
||||
void MouseInputSource::revealCursor() { pimpl->revealCursor (false); }
|
||||
void MouseInputSource::forceMouseCursorUpdate() { pimpl->revealCursor (true); }
|
||||
void MouseInputSource::setScreenPosition (Point<float> p) { pimpl->setScreenPosition (p); }
|
||||
|
||||
void MouseInputSource::handleEvent (ComponentPeer& peer, Point<int> positionWithinPeer,
|
||||
const int64 time, const ModifierKeys mods)
|
||||
void MouseInputSource::handleEvent (ComponentPeer& peer, Point<float> pos, int64 time, ModifierKeys mods)
|
||||
{
|
||||
pimpl->handleEvent (peer, positionWithinPeer, Time (time), mods.withOnlyMouseButtons());
|
||||
pimpl->handleEvent (peer, pos, Time (time), mods.withOnlyMouseButtons());
|
||||
}
|
||||
|
||||
void MouseInputSource::handleWheel (ComponentPeer& peer, Point<int> positionWithinPeer,
|
||||
const int64 time, const MouseWheelDetails& wheel)
|
||||
void MouseInputSource::handleWheel (ComponentPeer& peer, Point<float> pos, int64 time, const MouseWheelDetails& wheel)
|
||||
{
|
||||
pimpl->handleWheel (peer, positionWithinPeer, Time (time), wheel);
|
||||
pimpl->handleWheel (peer, pos, Time (time), wheel);
|
||||
}
|
||||
|
||||
void MouseInputSource::handleMagnifyGesture (ComponentPeer& peer, Point<int> positionWithinPeer,
|
||||
const int64 time, const float scaleFactor)
|
||||
void MouseInputSource::handleMagnifyGesture (ComponentPeer& peer, Point<float> pos, int64 time, float scaleFactor)
|
||||
{
|
||||
pimpl->handleMagnifyGesture (peer, positionWithinPeer, Time (time), scaleFactor);
|
||||
pimpl->handleMagnifyGesture (peer, pos, Time (time), scaleFactor);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
bool isDragging() const;
|
||||
|
||||
/** Returns the last-known screen position of this source. */
|
||||
Point<int> getScreenPosition() const;
|
||||
Point<float> getScreenPosition() const;
|
||||
|
||||
/** Returns a set of modifiers that indicate which buttons are currently
|
||||
held down on this device.
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
Time getLastMouseDownTime() const noexcept;
|
||||
|
||||
/** Returns the screen position at which the last mouse-down occurred. */
|
||||
Point<int> getLastMouseDownPosition() const noexcept;
|
||||
Point<float> getLastMouseDownPosition() const noexcept;
|
||||
|
||||
/** Returns true if this mouse is currently down, and if it has been dragged more
|
||||
than a couple of pixels from the place it was pressed.
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
bool isUnboundedMouseMovementEnabled() const;
|
||||
|
||||
/** Attempts to set this mouse pointer's screen position. */
|
||||
void setScreenPosition (Point<int> newPosition);
|
||||
void setScreenPosition (Point<float> newPosition);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
@@ -174,12 +174,12 @@ private:
|
||||
struct SourceList;
|
||||
|
||||
explicit MouseInputSource (MouseInputSourceInternal*) noexcept;
|
||||
void handleEvent (ComponentPeer&, Point<int>, int64 time, const ModifierKeys);
|
||||
void handleWheel (ComponentPeer&, Point<int>, int64 time, const MouseWheelDetails&);
|
||||
void handleMagnifyGesture (ComponentPeer&, Point<int>, int64 time, float scaleFactor);
|
||||
void handleEvent (ComponentPeer&, Point<float>, int64 time, ModifierKeys);
|
||||
void handleWheel (ComponentPeer&, Point<float>, int64 time, const MouseWheelDetails&);
|
||||
void handleMagnifyGesture (ComponentPeer&, Point<float>, int64 time, float scaleFactor);
|
||||
|
||||
static Point<int> getCurrentRawMousePosition();
|
||||
static void setRawMousePosition (Point<int>);
|
||||
static Point<float> getCurrentRawMousePosition();
|
||||
static void setRawMousePosition (Point<float>);
|
||||
|
||||
JUCE_LEAK_DETECTOR (MouseInputSource)
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* en
|
||||
|
||||
JUCEApplicationBase* app = JUCEApplicationBase::createInstance();
|
||||
if (! app->initialiseApp())
|
||||
exit (0);
|
||||
exit (app->getApplicationReturnValue());
|
||||
|
||||
jassert (MessageManager::getInstance()->isThisTheMessageThread());
|
||||
}
|
||||
@@ -91,7 +91,7 @@ DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas");
|
||||
METHOD (hasFocus, "hasFocus", "()Z") \
|
||||
METHOD (invalidate, "invalidate", "(IIII)V") \
|
||||
METHOD (containsPoint, "containsPoint", "(II)Z") \
|
||||
METHOD (showKeyboard, "showKeyboard", "(Z)V") \
|
||||
METHOD (showKeyboard, "showKeyboard", "(Ljava/lang/String;)V") \
|
||||
METHOD (createGLView, "createGLView", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;") \
|
||||
|
||||
DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView");
|
||||
@@ -234,14 +234,14 @@ public:
|
||||
view.callIntMethod (ComponentPeerView.getTop));
|
||||
}
|
||||
|
||||
Point<int> localToGlobal (Point<int> relativePosition) override
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override
|
||||
{
|
||||
return relativePosition + getScreenPosition();
|
||||
return relativePosition + getScreenPosition().toFloat();
|
||||
}
|
||||
|
||||
Point<int> globalToLocal (Point<int> screenPosition) override
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override
|
||||
{
|
||||
return screenPosition - getScreenPosition();
|
||||
return screenPosition - getScreenPosition().toFloat();
|
||||
}
|
||||
|
||||
void setMinimised (bool shouldBeMinimised) override
|
||||
@@ -320,7 +320,7 @@ public:
|
||||
lastMousePos = pos;
|
||||
|
||||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before.
|
||||
handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time);
|
||||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time);
|
||||
|
||||
if (isValidPeer (this))
|
||||
handleMouseDragCallback (index, pos, time);
|
||||
@@ -333,8 +333,8 @@ public:
|
||||
jassert (index < 64);
|
||||
touchesDown = (touchesDown | (1 << (index & 63)));
|
||||
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier);
|
||||
handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons()
|
||||
.withFlags (ModifierKeys::leftButtonModifier), time);
|
||||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons()
|
||||
.withFlags (ModifierKeys::leftButtonModifier), time);
|
||||
}
|
||||
|
||||
void handleMouseUpCallback (int index, Point<float> pos, int64 time)
|
||||
@@ -347,7 +347,7 @@ public:
|
||||
if (touchesDown == 0)
|
||||
currentModifiers = currentModifiers.withoutMouseButtons();
|
||||
|
||||
handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time);
|
||||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time);
|
||||
}
|
||||
|
||||
void handleKeyDownCallback (int k, int kc)
|
||||
@@ -378,14 +378,30 @@ public:
|
||||
handleFocusLoss();
|
||||
}
|
||||
|
||||
void textInputRequired (const Point<int>&) override
|
||||
static const char* getVirtualKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept
|
||||
{
|
||||
view.callVoidMethod (ComponentPeerView.showKeyboard, true);
|
||||
switch (type)
|
||||
{
|
||||
case TextInputTarget::textKeyboard: return "text";
|
||||
case TextInputTarget::numericKeyboard: return "number";
|
||||
case TextInputTarget::urlKeyboard: return "textUri";
|
||||
case TextInputTarget::emailAddressKeyboard: return "textEmailAddress";
|
||||
case TextInputTarget::phoneNumberKeyboard: return "phone";
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return "text";
|
||||
}
|
||||
|
||||
void textInputRequired (Point<int>, TextInputTarget& target) override
|
||||
{
|
||||
view.callVoidMethod (ComponentPeerView.showKeyboard,
|
||||
javaString (getVirtualKeyboardType (target.getKeyboardType())).get());
|
||||
}
|
||||
|
||||
void dismissPendingTextInput() override
|
||||
{
|
||||
view.callVoidMethod (ComponentPeerView.showKeyboard, false);
|
||||
view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -595,12 +611,12 @@ bool MouseInputSource::SourceList::addSource()
|
||||
return true;
|
||||
}
|
||||
|
||||
Point<int> MouseInputSource::getCurrentRawMousePosition()
|
||||
Point<float> MouseInputSource::getCurrentRawMousePosition()
|
||||
{
|
||||
return AndroidComponentPeer::lastMousePos.toInt();
|
||||
return AndroidComponentPeer::lastMousePos;
|
||||
}
|
||||
|
||||
void MouseInputSource::setRawMousePosition (Point<int>)
|
||||
void MouseInputSource::setRawMousePosition (Point<float>)
|
||||
{
|
||||
// not needed
|
||||
}
|
||||
|
||||
@@ -24,6 +24,14 @@
|
||||
|
||||
class UIViewComponentPeer;
|
||||
|
||||
// The way rotation works changed in iOS8..
|
||||
static bool isUsingOldRotationMethod() noexcept
|
||||
{
|
||||
static bool isPreV8 = ([[[UIDevice currentDevice] systemVersion] compare: @"8.0"
|
||||
options: NSNumericSearch] == NSOrderedAscending);
|
||||
return isPreV8;
|
||||
}
|
||||
|
||||
namespace Orientations
|
||||
{
|
||||
static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation)
|
||||
@@ -42,12 +50,15 @@ namespace Orientations
|
||||
|
||||
static CGAffineTransform getCGTransformFor (const Desktop::DisplayOrientation orientation) noexcept
|
||||
{
|
||||
switch (orientation)
|
||||
if (isUsingOldRotationMethod())
|
||||
{
|
||||
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
|
||||
case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0);
|
||||
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0);
|
||||
default: break;
|
||||
switch (orientation)
|
||||
{
|
||||
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
|
||||
case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0);
|
||||
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return CGAffineTransformIdentity;
|
||||
@@ -85,10 +96,10 @@ using namespace juce;
|
||||
|
||||
- (void) drawRect: (CGRect) r;
|
||||
|
||||
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
|
||||
|
||||
- (BOOL) becomeFirstResponder;
|
||||
- (BOOL) resignFirstResponder;
|
||||
@@ -106,6 +117,7 @@ using namespace juce;
|
||||
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation;
|
||||
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration;
|
||||
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation;
|
||||
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator;
|
||||
|
||||
- (void) viewDidLoad;
|
||||
- (void) viewWillAppear: (BOOL) animated;
|
||||
@@ -145,8 +157,8 @@ public:
|
||||
|
||||
Rectangle<int> getBounds() const override { return getBounds (! isSharedWindow); }
|
||||
Rectangle<int> getBounds (bool global) const;
|
||||
Point<int> localToGlobal (Point<int> relativePosition) override;
|
||||
Point<int> globalToLocal (Point<int> screenPosition) override;
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override;
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override;
|
||||
void setAlpha (float newAlpha) override;
|
||||
void setMinimised (bool) override {}
|
||||
bool isMinimised() const override { return false; }
|
||||
@@ -168,7 +180,7 @@ public:
|
||||
void viewFocusLoss();
|
||||
bool isFocused() const override;
|
||||
void grabFocus() override;
|
||||
void textInputRequired (const Point<int>&) override;
|
||||
void textInputRequired (Point<int>, TextInputTarget&) override;
|
||||
|
||||
BOOL textViewReplaceCharacters (Range<int>, const String&);
|
||||
void updateHiddenTextContent (TextInputTarget*);
|
||||
@@ -189,7 +201,7 @@ public:
|
||||
bool isSharedWindow, fullScreen, insideDrawRect;
|
||||
static ModifierKeys currentModifiers;
|
||||
|
||||
static int64 getMouseTime (UIEvent* e)
|
||||
static int64 getMouseTime (UIEvent* e) noexcept
|
||||
{
|
||||
return (Time::currentTimeMillis() - Time::getMillisecondCounter())
|
||||
+ (int64) ([e timestamp] * 1000.0);
|
||||
@@ -197,26 +209,29 @@ public:
|
||||
|
||||
static Rectangle<int> rotatedScreenPosToReal (const Rectangle<int>& r)
|
||||
{
|
||||
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
|
||||
|
||||
switch ([[UIApplication sharedApplication] statusBarOrientation])
|
||||
if (isUsingOldRotationMethod())
|
||||
{
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return r;
|
||||
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
|
||||
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
|
||||
r.getWidth(), r.getHeight());
|
||||
switch ([[UIApplication sharedApplication] statusBarOrientation])
|
||||
{
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return r;
|
||||
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
|
||||
r.getHeight(), r.getWidth());
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
|
||||
r.getWidth(), r.getHeight());
|
||||
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
|
||||
r.getHeight(), r.getWidth());
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
|
||||
r.getHeight(), r.getWidth());
|
||||
|
||||
default: jassertfalse; // unknown orientation!
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
|
||||
r.getHeight(), r.getWidth());
|
||||
|
||||
default: jassertfalse; // unknown orientation!
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -224,26 +239,29 @@ public:
|
||||
|
||||
static Rectangle<int> realScreenPosToRotated (const Rectangle<int>& r)
|
||||
{
|
||||
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
|
||||
|
||||
switch ([[UIApplication sharedApplication] statusBarOrientation])
|
||||
if (isUsingOldRotationMethod())
|
||||
{
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return r;
|
||||
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
|
||||
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
|
||||
r.getWidth(), r.getHeight());
|
||||
switch ([[UIApplication sharedApplication] statusBarOrientation])
|
||||
{
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return r;
|
||||
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
|
||||
r.getHeight(), r.getWidth());
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
|
||||
r.getWidth(), r.getHeight());
|
||||
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
|
||||
r.getHeight(), r.getWidth());
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
|
||||
r.getHeight(), r.getWidth());
|
||||
|
||||
default: jassertfalse; // unknown orientation!
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
|
||||
r.getHeight(), r.getWidth());
|
||||
|
||||
default: jassertfalse; // unknown orientation!
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -273,6 +291,13 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
static void sendScreenBoundsUpdate (JuceUIViewController* c)
|
||||
{
|
||||
JuceUIView* juceView = (JuceUIView*) [c view];
|
||||
jassert (juceView != nil && juceView->owner != nullptr);
|
||||
juceView->owner->updateTransformAndScreenBounds();
|
||||
}
|
||||
|
||||
} // (juce namespace)
|
||||
|
||||
//==============================================================================
|
||||
@@ -301,19 +326,23 @@ private:
|
||||
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation
|
||||
{
|
||||
(void) fromInterfaceOrientation;
|
||||
|
||||
JuceUIView* juceView = (JuceUIView*) [self view];
|
||||
jassert (juceView != nil && juceView->owner != nullptr);
|
||||
juceView->owner->updateTransformAndScreenBounds();
|
||||
|
||||
sendScreenBoundsUpdate (self);
|
||||
[UIView setAnimationsEnabled: YES];
|
||||
}
|
||||
|
||||
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator
|
||||
{
|
||||
[super viewWillTransitionToSize: size withTransitionCoordinator: coordinator];
|
||||
sendScreenBoundsUpdate (self);
|
||||
|
||||
// On some devices the screen-size isn't yet updated at this point, so also trigger another
|
||||
// async update to double-check..
|
||||
MessageManager::callAsync ([=]() { sendScreenBoundsUpdate (self); });
|
||||
}
|
||||
|
||||
- (void) viewDidLoad
|
||||
{
|
||||
JuceUIView* juceView = (JuceUIView*) [self view];
|
||||
jassert (juceView != nil && juceView->owner != nullptr);
|
||||
juceView->owner->updateTransformAndScreenBounds();
|
||||
sendScreenBoundsUpdate (self);
|
||||
}
|
||||
|
||||
- (void) viewWillAppear: (BOOL) animated
|
||||
@@ -477,7 +506,7 @@ void ModifierKeys::updateCurrentModifiers() noexcept
|
||||
currentModifiers = UIViewComponentPeer::currentModifiers;
|
||||
}
|
||||
|
||||
Point<int> juce_lastMousePos;
|
||||
Point<float> juce_lastMousePos;
|
||||
|
||||
//==============================================================================
|
||||
UIViewComponentPeer::UIViewComponentPeer (Component& comp, const int windowStyleFlags, UIView* viewToAttachTo)
|
||||
@@ -603,14 +632,14 @@ Rectangle<int> UIViewComponentPeer::getBounds (const bool global) const
|
||||
return convertToRectInt (r);
|
||||
}
|
||||
|
||||
Point<int> UIViewComponentPeer::localToGlobal (Point<int> relativePosition)
|
||||
Point<float> UIViewComponentPeer::localToGlobal (Point<float> relativePosition)
|
||||
{
|
||||
return relativePosition + getBounds (true).getPosition();
|
||||
return relativePosition + getBounds (true).getPosition().toFloat();
|
||||
}
|
||||
|
||||
Point<int> UIViewComponentPeer::globalToLocal (Point<int> screenPosition)
|
||||
Point<float> UIViewComponentPeer::globalToLocal (Point<float> screenPosition)
|
||||
{
|
||||
return screenPosition - getBounds (true).getPosition();
|
||||
return screenPosition - getBounds (true).getPosition().toFloat();
|
||||
}
|
||||
|
||||
void UIViewComponentPeer::setAlpha (float newAlpha)
|
||||
@@ -702,10 +731,7 @@ void UIViewComponentPeer::toFront (bool makeActiveWindow)
|
||||
|
||||
void UIViewComponentPeer::toBehind (ComponentPeer* other)
|
||||
{
|
||||
UIViewComponentPeer* const otherPeer = dynamic_cast <UIViewComponentPeer*> (other);
|
||||
jassert (otherPeer != nullptr); // wrong type of window?
|
||||
|
||||
if (otherPeer != nullptr)
|
||||
if (UIViewComponentPeer* const otherPeer = dynamic_cast<UIViewComponentPeer*> (other))
|
||||
{
|
||||
if (isSharedWindow)
|
||||
{
|
||||
@@ -716,6 +742,10 @@ void UIViewComponentPeer::toBehind (ComponentPeer* other)
|
||||
// don't know how to do this
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // wrong type of window?
|
||||
}
|
||||
}
|
||||
|
||||
void UIViewComponentPeer::setIcon (const Image& /*newIcon*/)
|
||||
@@ -736,8 +766,8 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons
|
||||
continue;
|
||||
|
||||
CGPoint p = [touch locationInView: view];
|
||||
const Point<int> pos ((int) p.x, (int) p.y);
|
||||
juce_lastMousePos = pos + getBounds (true).getPosition();
|
||||
const Point<float> pos (p.x, p.y);
|
||||
juce_lastMousePos = pos + getBounds (true).getPosition().toFloat();
|
||||
|
||||
const int64 time = getMouseTime (event);
|
||||
const int touchIndex = currentTouches.getIndexOfTouch (touch);
|
||||
@@ -781,7 +811,7 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons
|
||||
|
||||
if (isUp || isCancel)
|
||||
{
|
||||
handleMouseEvent (touchIndex, Point<int> (-1, -1), modsToSend, time);
|
||||
handleMouseEvent (touchIndex, Point<float> (-1.0f, -1.0f), modsToSend, time);
|
||||
if (! isValidPeer (this))
|
||||
return;
|
||||
}
|
||||
@@ -828,12 +858,28 @@ void UIViewComponentPeer::grabFocus()
|
||||
}
|
||||
}
|
||||
|
||||
void UIViewComponentPeer::textInputRequired (const Point<int>&)
|
||||
void UIViewComponentPeer::textInputRequired (Point<int>, TextInputTarget&)
|
||||
{
|
||||
}
|
||||
|
||||
static UIKeyboardType getUIKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TextInputTarget::textKeyboard: return UIKeyboardTypeAlphabet;
|
||||
case TextInputTarget::numericKeyboard: return UIKeyboardTypeNumbersAndPunctuation;
|
||||
case TextInputTarget::urlKeyboard: return UIKeyboardTypeURL;
|
||||
case TextInputTarget::emailAddressKeyboard: return UIKeyboardTypeEmailAddress;
|
||||
case TextInputTarget::phoneNumberKeyboard: return UIKeyboardTypePhonePad;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return UIKeyboardTypeDefault;
|
||||
}
|
||||
|
||||
void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target)
|
||||
{
|
||||
view->hiddenTextView.keyboardType = getUIKeyboardType (target->getKeyboardType());
|
||||
view->hiddenTextView.text = juceStringToNS (target->getTextInRange (Range<int> (0, target->getHighlightedRegion().getStart())));
|
||||
view->hiddenTextView.selectedRange = NSMakeRange (target->getHighlightedRegion().getStart(), 0);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ private:
|
||||
|
||||
- (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
|
||||
{
|
||||
owner->buttonClicked (buttonIndex);
|
||||
owner->buttonClicked ((int) buttonIndex);
|
||||
alertView.hidden = true;
|
||||
}
|
||||
|
||||
@@ -312,12 +312,12 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
|
||||
return true;
|
||||
}
|
||||
|
||||
Point<int> MouseInputSource::getCurrentRawMousePosition()
|
||||
Point<float> MouseInputSource::getCurrentRawMousePosition()
|
||||
{
|
||||
return juce_lastMousePos;
|
||||
}
|
||||
|
||||
void MouseInputSource::setRawMousePosition (Point<int>)
|
||||
void MouseInputSource::setRawMousePosition (Point<float>)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -42,99 +42,134 @@ bool FileChooser::isPlatformDialogAvailable()
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileChooser::showPlatformDialog (Array<File>& results,
|
||||
const String& title,
|
||||
const File& file,
|
||||
const String& filters,
|
||||
bool isDirectory,
|
||||
bool /* selectsFiles */,
|
||||
bool isSave,
|
||||
bool /* warnAboutOverwritingExistingFiles */,
|
||||
bool selectMultipleFiles,
|
||||
FilePreviewComponent* /* previewComponent */)
|
||||
static uint64 getTopWindowID() noexcept
|
||||
{
|
||||
String separator;
|
||||
StringArray args;
|
||||
if (TopLevelWindow* top = TopLevelWindow::getActiveTopLevelWindow())
|
||||
return (uint64) (pointer_sized_uint) top->getWindowHandle();
|
||||
|
||||
const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
|
||||
const bool isKdeFullSession = SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String::empty)
|
||||
.equalsIgnoreCase ("true");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (exeIsAvailable ("kdialog") && (isKdeFullSession || ! exeIsAvailable ("zenity")))
|
||||
static bool isKdeFullSession()
|
||||
{
|
||||
return SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String())
|
||||
.equalsIgnoreCase ("true");
|
||||
}
|
||||
|
||||
static void addKDialogArgs (StringArray& args, String& separator,
|
||||
const String& title, const File& file, const String& filters,
|
||||
bool isDirectory, bool isSave, bool selectMultipleFiles)
|
||||
{
|
||||
args.add ("kdialog");
|
||||
|
||||
if (title.isNotEmpty())
|
||||
args.add ("--title=" + title);
|
||||
|
||||
if (uint64 topWindowID = getTopWindowID())
|
||||
{
|
||||
// use kdialog for KDE sessions or if zenity is missing
|
||||
args.add ("kdialog");
|
||||
args.add ("--attach");
|
||||
args.add (String (topWindowID));
|
||||
}
|
||||
|
||||
if (title.isNotEmpty())
|
||||
args.add ("--title=" + title);
|
||||
|
||||
if (selectMultipleFiles)
|
||||
{
|
||||
separator = "\n";
|
||||
args.add ("--multiple");
|
||||
args.add ("--separate-output");
|
||||
args.add ("--getopenfilename");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isSave) args.add ("--getsavefilename");
|
||||
else if (isDirectory) args.add ("--getexistingdirectory");
|
||||
else args.add ("--getopenfilename");
|
||||
}
|
||||
|
||||
String startPath;
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
startPath = file.getFullPathName();
|
||||
}
|
||||
else if (file.getParentDirectory().exists())
|
||||
{
|
||||
startPath = file.getParentDirectory().getFullPathName();
|
||||
}
|
||||
else
|
||||
{
|
||||
startPath = File::getSpecialLocation (File::userHomeDirectory).getFullPathName();
|
||||
|
||||
if (isSave)
|
||||
startPath += "/" + file.getFileName();
|
||||
}
|
||||
|
||||
args.add (startPath);
|
||||
args.add (filters.replaceCharacter (';', ' '));
|
||||
if (selectMultipleFiles)
|
||||
{
|
||||
separator = "\n";
|
||||
args.add ("--multiple");
|
||||
args.add ("--separate-output");
|
||||
args.add ("--getopenfilename");
|
||||
}
|
||||
else
|
||||
{
|
||||
// zenity
|
||||
args.add ("zenity");
|
||||
args.add ("--file-selection");
|
||||
|
||||
if (title.isNotEmpty())
|
||||
args.add ("--title=" + title);
|
||||
|
||||
if (selectMultipleFiles)
|
||||
{
|
||||
separator = ":";
|
||||
args.add ("--multiple");
|
||||
args.add ("--separator=" + separator);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDirectory) args.add ("--directory");
|
||||
if (isSave) args.add ("--save");
|
||||
}
|
||||
|
||||
if (file.isDirectory())
|
||||
file.setAsCurrentWorkingDirectory();
|
||||
else if (file.getParentDirectory().exists())
|
||||
file.getParentDirectory().setAsCurrentWorkingDirectory();
|
||||
else
|
||||
File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory();
|
||||
|
||||
if (! file.getFileName().isEmpty())
|
||||
args.add ("--filename=" + file.getFileName());
|
||||
if (isSave) args.add ("--getsavefilename");
|
||||
else if (isDirectory) args.add ("--getexistingdirectory");
|
||||
else args.add ("--getopenfilename");
|
||||
}
|
||||
|
||||
File startPath;
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
startPath = file;
|
||||
}
|
||||
else if (file.getParentDirectory().exists())
|
||||
{
|
||||
startPath = file.getParentDirectory();
|
||||
}
|
||||
else
|
||||
{
|
||||
startPath = File::getSpecialLocation (File::userHomeDirectory);
|
||||
|
||||
if (isSave)
|
||||
startPath = startPath.getChildFile (file.getFileName());
|
||||
}
|
||||
|
||||
args.add (startPath.getFullPathName());
|
||||
args.add (filters.replaceCharacter (';', ' '));
|
||||
}
|
||||
|
||||
static void addZenityArgs (StringArray& args, String& separator,
|
||||
const String& title, const File& file, const String& filters,
|
||||
bool isDirectory, bool isSave, bool selectMultipleFiles)
|
||||
{
|
||||
args.add ("zenity");
|
||||
args.add ("--file-selection");
|
||||
|
||||
if (title.isNotEmpty())
|
||||
args.add ("--title=" + title);
|
||||
|
||||
if (selectMultipleFiles)
|
||||
{
|
||||
separator = ":";
|
||||
args.add ("--multiple");
|
||||
args.add ("--separator=" + separator);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDirectory) args.add ("--directory");
|
||||
if (isSave) args.add ("--save");
|
||||
}
|
||||
|
||||
if (filters.isNotEmpty() && filters != "*" && filters != "*.*")
|
||||
{
|
||||
args.add ("--file-filter");
|
||||
args.add (filters.replaceCharacter (';', ' '));
|
||||
|
||||
args.add ("--file-filter");
|
||||
args.add ("All files | *");
|
||||
}
|
||||
|
||||
if (file.isDirectory())
|
||||
file.setAsCurrentWorkingDirectory();
|
||||
else if (file.getParentDirectory().exists())
|
||||
file.getParentDirectory().setAsCurrentWorkingDirectory();
|
||||
else
|
||||
File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory();
|
||||
|
||||
if (! file.getFileName().isEmpty())
|
||||
args.add ("--filename=" + file.getFileName());
|
||||
|
||||
// supplying the window ID of the topmost window makes sure that Zenity pops up..
|
||||
if (uint64 topWindowID = getTopWindowID())
|
||||
setenv ("WINDOWID", String (topWindowID).toRawUTF8(), true);
|
||||
}
|
||||
|
||||
void FileChooser::showPlatformDialog (Array<File>& results,
|
||||
const String& title, const File& file, const String& filters,
|
||||
bool isDirectory, bool /* selectsFiles */,
|
||||
bool isSave, bool /* warnAboutOverwritingExistingFiles */,
|
||||
bool selectMultipleFiles, FilePreviewComponent*)
|
||||
{
|
||||
const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
|
||||
|
||||
StringArray args;
|
||||
String separator;
|
||||
|
||||
// use kdialog for KDE sessions or if zenity is missing
|
||||
if (exeIsAvailable ("kdialog") && (isKdeFullSession() || ! exeIsAvailable ("zenity")))
|
||||
addKDialogArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles);
|
||||
else
|
||||
addZenityArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles);
|
||||
|
||||
args.add ("2>/dev/null"); // (to avoid logging info ending up in the results)
|
||||
|
||||
ChildProcess child;
|
||||
|
||||
@@ -33,17 +33,18 @@ struct Atoms
|
||||
{
|
||||
Atoms()
|
||||
{
|
||||
Protocols = getIfExists ("WM_PROTOCOLS");
|
||||
ProtocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS");
|
||||
ProtocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW");
|
||||
ProtocolList [PING] = getIfExists ("_NET_WM_PING");
|
||||
ChangeState = getIfExists ("WM_CHANGE_STATE");
|
||||
State = getIfExists ("WM_STATE");
|
||||
UserTime = getCreating ("_NET_WM_USER_TIME");
|
||||
ActiveWin = getCreating ("_NET_ACTIVE_WINDOW");
|
||||
Pid = getCreating ("_NET_WM_PID");
|
||||
WindowType = getIfExists ("_NET_WM_WINDOW_TYPE");
|
||||
WindowState = getIfExists ("_NET_WM_STATE");
|
||||
protocols = getIfExists ("WM_PROTOCOLS");
|
||||
protocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS");
|
||||
protocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW");
|
||||
protocolList [PING] = getIfExists ("_NET_WM_PING");
|
||||
changeState = getIfExists ("WM_CHANGE_STATE");
|
||||
state = getIfExists ("WM_STATE");
|
||||
userTime = getCreating ("_NET_WM_USER_TIME");
|
||||
activeWin = getCreating ("_NET_ACTIVE_WINDOW");
|
||||
pid = getCreating ("_NET_WM_PID");
|
||||
windowType = getIfExists ("_NET_WM_WINDOW_TYPE");
|
||||
windowState = getIfExists ("_NET_WM_STATE");
|
||||
compositingManager = getCreating ("_NET_WM_CM_S0");
|
||||
|
||||
XdndAware = getCreating ("XdndAware");
|
||||
XdndEnter = getCreating ("XdndEnter");
|
||||
@@ -88,8 +89,8 @@ struct Atoms
|
||||
PING = 2
|
||||
};
|
||||
|
||||
Atom Protocols, ProtocolList[3], ChangeState, State, UserTime,
|
||||
ActiveWin, Pid, WindowType, WindowState,
|
||||
Atom protocols, protocolList[3], changeState, state, userTime,
|
||||
activeWin, pid, windowType, windowState, compositingManager,
|
||||
XdndAware, XdndEnter, XdndLeave, XdndPosition, XdndStatus,
|
||||
XdndDrop, XdndFinished, XdndSelection, XdndTypeList, XdndActionList,
|
||||
XdndActionDescription, XdndActionCopy, XdndActionPrivate,
|
||||
@@ -314,6 +315,11 @@ namespace XRender
|
||||
return xRenderQueryVersion != nullptr;
|
||||
}
|
||||
|
||||
static bool hasCompositingWindowManager()
|
||||
{
|
||||
return XGetSelectionOwner (display, Atoms::get().compositingManager) != 0;
|
||||
}
|
||||
|
||||
static XRenderPictFormat* findPictureFormat()
|
||||
{
|
||||
ScopedXLock xlock;
|
||||
@@ -915,7 +921,7 @@ public:
|
||||
clientMsg.window = windowH;
|
||||
clientMsg.type = ClientMessage;
|
||||
clientMsg.format = 32;
|
||||
clientMsg.message_type = Atoms::get().WindowState;
|
||||
clientMsg.message_type = Atoms::get().windowState;
|
||||
clientMsg.data.l[0] = 0; // Remove
|
||||
clientMsg.data.l[1] = fs;
|
||||
clientMsg.data.l[2] = 0;
|
||||
@@ -971,14 +977,14 @@ public:
|
||||
|
||||
Rectangle<int> getBounds() const override { return bounds; }
|
||||
|
||||
Point<int> localToGlobal (Point<int> relativePosition) override
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override
|
||||
{
|
||||
return relativePosition + bounds.getPosition();
|
||||
return relativePosition + bounds.getPosition().toFloat();
|
||||
}
|
||||
|
||||
Point<int> globalToLocal (Point<int> screenPosition) override
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override
|
||||
{
|
||||
return screenPosition - bounds.getPosition();
|
||||
return screenPosition - bounds.getPosition().toFloat();
|
||||
}
|
||||
|
||||
void setAlpha (float /* newAlpha */) override
|
||||
@@ -1002,7 +1008,7 @@ public:
|
||||
clientMsg.window = windowH;
|
||||
clientMsg.type = ClientMessage;
|
||||
clientMsg.format = 32;
|
||||
clientMsg.message_type = Atoms::get().ChangeState;
|
||||
clientMsg.message_type = Atoms::get().changeState;
|
||||
clientMsg.data.l[0] = IconicState;
|
||||
|
||||
ScopedXLock xlock;
|
||||
@@ -1018,10 +1024,10 @@ public:
|
||||
{
|
||||
ScopedXLock xlock;
|
||||
const Atoms& atoms = Atoms::get();
|
||||
GetXProperty prop (windowH, atoms.State, 0, 64, false, atoms.State);
|
||||
GetXProperty prop (windowH, atoms.state, 0, 64, false, atoms.state);
|
||||
|
||||
return prop.success
|
||||
&& prop.actualType == atoms.State
|
||||
&& prop.actualType == atoms.state
|
||||
&& prop.actualFormat == 32
|
||||
&& prop.numItems > 0
|
||||
&& ((unsigned long*) prop.data)[0] == IconicState;
|
||||
@@ -1039,7 +1045,7 @@ public:
|
||||
r = Desktop::getInstance().getDisplays().getMainDisplay().userArea;
|
||||
|
||||
if (! r.isEmpty())
|
||||
setBounds (r, shouldBeFullScreen);
|
||||
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen);
|
||||
|
||||
component.repaint();
|
||||
}
|
||||
@@ -1081,9 +1087,7 @@ public:
|
||||
{
|
||||
for (int i = windowListSize; --i >= 0;)
|
||||
{
|
||||
LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]);
|
||||
|
||||
if (peer != 0)
|
||||
if (LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]))
|
||||
{
|
||||
result = (peer == this);
|
||||
break;
|
||||
@@ -1109,9 +1113,9 @@ public:
|
||||
if (c == &component)
|
||||
break;
|
||||
|
||||
// TODO: needs scaling correctly
|
||||
if (c->contains (localPos + bounds.getPosition() - c->getScreenPosition()))
|
||||
return false;
|
||||
if (ComponentPeer* peer = c->getPeer())
|
||||
if (peer->contains (localPos + bounds.getPosition() - peer->getBounds().getPosition(), true))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trueIfInAChildWindow)
|
||||
@@ -1152,7 +1156,7 @@ public:
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.serial = 0;
|
||||
ev.xclient.send_event = True;
|
||||
ev.xclient.message_type = Atoms::get().ActiveWin;
|
||||
ev.xclient.message_type = Atoms::get().activeWin;
|
||||
ev.xclient.window = windowH;
|
||||
ev.xclient.format = 32;
|
||||
ev.xclient.data.l[0] = 2;
|
||||
@@ -1178,10 +1182,7 @@ public:
|
||||
|
||||
void toBehind (ComponentPeer* other) override
|
||||
{
|
||||
LinuxComponentPeer* const otherPeer = dynamic_cast <LinuxComponentPeer*> (other);
|
||||
jassert (otherPeer != nullptr); // wrong type of window?
|
||||
|
||||
if (otherPeer != nullptr)
|
||||
if (LinuxComponentPeer* const otherPeer = dynamic_cast<LinuxComponentPeer*> (other))
|
||||
{
|
||||
setMinimised (false);
|
||||
|
||||
@@ -1190,6 +1191,8 @@ public:
|
||||
ScopedXLock xlock;
|
||||
XRestackWindows (display, newStack, 2);
|
||||
}
|
||||
else
|
||||
jassertfalse; // wrong type of window?
|
||||
}
|
||||
|
||||
bool isFocused() const override
|
||||
@@ -1217,11 +1220,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void textInputRequired (const Point<int>&) override {}
|
||||
void textInputRequired (Point<int>, TextInputTarget&) override {}
|
||||
|
||||
void repaint (const Rectangle<int>& area) override
|
||||
{
|
||||
repainter->repaint (area.getIntersection (component.getLocalBounds()));
|
||||
repainter->repaint (area.getIntersection (bounds.withZeroOrigin()));
|
||||
}
|
||||
|
||||
void performAnyPendingRepaintsNow() override
|
||||
@@ -1327,6 +1330,7 @@ public:
|
||||
|
||||
default:
|
||||
#if JUCE_USE_XSHM
|
||||
if (XSHMHelpers::isShmAvailable())
|
||||
{
|
||||
ScopedXLock xlock;
|
||||
if (event.xany.type == XShmGetEventBase (display))
|
||||
@@ -1368,7 +1372,7 @@ public:
|
||||
const ModifierKeys oldMods (currentModifiers);
|
||||
bool keyPressed = false;
|
||||
|
||||
if ((sym & 0xff00) == 0xff00 || sym == XK_ISO_Left_Tab)
|
||||
if ((sym & 0xff00) == 0xff00 || keyCode == XK_ISO_Left_Tab)
|
||||
{
|
||||
switch (sym) // Translate keypad
|
||||
{
|
||||
@@ -1427,6 +1431,11 @@ public:
|
||||
keyCode &= 0xff;
|
||||
break;
|
||||
|
||||
case XK_ISO_Left_Tab:
|
||||
keyPressed = true;
|
||||
keyCode = XK_Tab & 0xff;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (sym >= XK_F1 && sym <= XK_F16)
|
||||
{
|
||||
@@ -1490,9 +1499,9 @@ public:
|
||||
}
|
||||
|
||||
template <typename EventType>
|
||||
static Point<int> getMousePos (const EventType& e) noexcept
|
||||
static Point<float> getMousePos (const EventType& e) noexcept
|
||||
{
|
||||
return Point<int> (e.x, e.y);
|
||||
return Point<float> ((float) e.x, (float) e.y);
|
||||
}
|
||||
|
||||
void handleWheelEvent (const XButtonPressedEvent& buttonPressEvent, const float amount)
|
||||
@@ -1698,11 +1707,11 @@ public:
|
||||
{
|
||||
const Atoms& atoms = Atoms::get();
|
||||
|
||||
if (clientMsg.message_type == atoms.Protocols && clientMsg.format == 32)
|
||||
if (clientMsg.message_type == atoms.protocols && clientMsg.format == 32)
|
||||
{
|
||||
const Atom atom = (Atom) clientMsg.data.l[0];
|
||||
|
||||
if (atom == atoms.ProtocolList [Atoms::PING])
|
||||
if (atom == atoms.protocolList [Atoms::PING])
|
||||
{
|
||||
Window root = RootWindow (display, DefaultScreen (display));
|
||||
|
||||
@@ -1711,7 +1720,7 @@ public:
|
||||
XSendEvent (display, root, False, NoEventMask, &event);
|
||||
XFlush (display);
|
||||
}
|
||||
else if (atom == atoms.ProtocolList [Atoms::TAKE_FOCUS])
|
||||
else if (atom == atoms.protocolList [Atoms::TAKE_FOCUS])
|
||||
{
|
||||
if ((getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0)
|
||||
{
|
||||
@@ -1726,7 +1735,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (atom == atoms.ProtocolList [Atoms::DELETE_WINDOW])
|
||||
else if (atom == atoms.protocolList [Atoms::DELETE_WINDOW])
|
||||
{
|
||||
handleUserClosingWindow();
|
||||
}
|
||||
@@ -1902,7 +1911,8 @@ private:
|
||||
for (const Rectangle<int>* i = originalRepaintRegion.begin(), * const e = originalRepaintRegion.end(); i != e; ++i)
|
||||
{
|
||||
#if JUCE_USE_XSHM
|
||||
++shmPaintsPending;
|
||||
if (XSHMHelpers::isShmAvailable())
|
||||
++shmPaintsPending;
|
||||
#endif
|
||||
|
||||
static_cast<XBitmapImage*> (image.getPixelData())
|
||||
@@ -2166,7 +2176,7 @@ private:
|
||||
|
||||
netHints[1] = Atoms::getIfExists ("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
|
||||
|
||||
xchangeProperty (windowH, Atoms::get().WindowType, XA_ATOM, 32, &netHints, 2);
|
||||
xchangeProperty (windowH, Atoms::get().windowType, XA_ATOM, 32, &netHints, 2);
|
||||
|
||||
int numHints = 0;
|
||||
|
||||
@@ -2177,7 +2187,7 @@ private:
|
||||
netHints [numHints++] = Atoms::getIfExists ("_NET_WM_STATE_ABOVE");
|
||||
|
||||
if (numHints > 0)
|
||||
xchangeProperty (windowH, Atoms::get().WindowState, XA_ATOM, 32, &netHints, numHints);
|
||||
xchangeProperty (windowH, Atoms::get().windowState, XA_ATOM, 32, &netHints, numHints);
|
||||
}
|
||||
|
||||
void createWindow (Window parentToAddTo)
|
||||
@@ -2254,10 +2264,10 @@ private:
|
||||
|
||||
// Associate the PID, allowing to be shut down when something goes wrong
|
||||
unsigned long pid = getpid();
|
||||
xchangeProperty (windowH, atoms.Pid, XA_CARDINAL, 32, &pid, 1);
|
||||
xchangeProperty (windowH, atoms.pid, XA_CARDINAL, 32, &pid, 1);
|
||||
|
||||
// Set window manager protocols
|
||||
xchangeProperty (windowH, atoms.Protocols, XA_ATOM, 32, atoms.ProtocolList, 2);
|
||||
xchangeProperty (windowH, atoms.protocols, XA_ATOM, 32, atoms.protocolList, 2);
|
||||
|
||||
// Set drag and drop flags
|
||||
xchangeProperty (windowH, atoms.XdndTypeList, XA_ATOM, 32, atoms.allowedMimeTypes, numElementsInArray (atoms.allowedMimeTypes));
|
||||
@@ -2314,7 +2324,7 @@ private:
|
||||
|
||||
long getUserTime() const
|
||||
{
|
||||
GetXProperty prop (windowH, Atoms::get().UserTime, 0, 65536, false, XA_CARDINAL);
|
||||
GetXProperty prop (windowH, Atoms::get().userTime, 0, 65536, false, XA_CARDINAL);
|
||||
return prop.success ? *(long*) prop.data : 0;
|
||||
}
|
||||
|
||||
@@ -3042,10 +3052,10 @@ void Desktop::Displays::findDisplays (float masterScale)
|
||||
d.userArea = d.totalArea = Rectangle<int> (screens[j].x_org,
|
||||
screens[j].y_org,
|
||||
screens[j].width,
|
||||
screens[j].height) * masterScale;
|
||||
screens[j].height) / masterScale;
|
||||
d.isMain = (index == 0);
|
||||
d.scale = masterScale;
|
||||
d.dpi = getDisplayDPI (index);
|
||||
d.dpi = getDisplayDPI (0); // (all screens share the same DPI)
|
||||
|
||||
displays.add (d);
|
||||
}
|
||||
@@ -3114,14 +3124,20 @@ bool MouseInputSource::SourceList::addSource()
|
||||
|
||||
bool Desktop::canUseSemiTransparentWindows() noexcept
|
||||
{
|
||||
int matchedDepth = 0;
|
||||
const int desiredDepth = 32;
|
||||
#if JUCE_USE_XRENDER
|
||||
if (XRender::hasCompositingWindowManager())
|
||||
{
|
||||
int matchedDepth = 0, desiredDepth = 32;
|
||||
|
||||
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0
|
||||
&& (matchedDepth == desiredDepth);
|
||||
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0
|
||||
&& matchedDepth == desiredDepth;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Point<int> MouseInputSource::getCurrentRawMousePosition()
|
||||
Point<float> MouseInputSource::getCurrentRawMousePosition()
|
||||
{
|
||||
Window root, child;
|
||||
int x, y, winx, winy;
|
||||
@@ -3138,14 +3154,14 @@ Point<int> MouseInputSource::getCurrentRawMousePosition()
|
||||
x = y = -1;
|
||||
}
|
||||
|
||||
return Point<int> (x, y);
|
||||
return Point<float> ((float) x, (float) y);
|
||||
}
|
||||
|
||||
void MouseInputSource::setRawMousePosition (Point<int> newPosition)
|
||||
void MouseInputSource::setRawMousePosition (Point<float> newPosition)
|
||||
{
|
||||
ScopedXLock xlock;
|
||||
Window root = RootWindow (display, DefaultScreen (display));
|
||||
XWarpPointer (display, None, root, 0, 0, 0, 0, newPosition.getX(), newPosition.getY());
|
||||
XWarpPointer (display, None, root, 0, 0, 0, 0, roundToInt (newPosition.getX()), roundToInt (newPosition.getY()));
|
||||
}
|
||||
|
||||
double Desktop::getDefaultMasterScale()
|
||||
@@ -3364,7 +3380,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty
|
||||
|
||||
void MouseCursor::showInWindow (ComponentPeer* peer) const
|
||||
{
|
||||
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (peer))
|
||||
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (peer))
|
||||
lp->showMouseCursor ((Cursor) getHandle());
|
||||
}
|
||||
|
||||
@@ -3388,7 +3404,7 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi
|
||||
|
||||
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
|
||||
if (Component* sourceComp = draggingSource->getComponentUnderMouse())
|
||||
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer()))
|
||||
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer()))
|
||||
return lp->externalDragFileInit (files, canMoveFiles);
|
||||
|
||||
// This method must be called in response to a component's mouseDown or mouseDrag event!
|
||||
@@ -3403,7 +3419,7 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
|
||||
|
||||
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
|
||||
if (Component* sourceComp = draggingSource->getComponentUnderMouse())
|
||||
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer()))
|
||||
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer()))
|
||||
return lp->externalDragTextInit (text);
|
||||
|
||||
// This method must be called in response to a component's mouseDown or mouseDrag event!
|
||||
|
||||
@@ -295,14 +295,14 @@ public:
|
||||
return getBounds (! isSharedWindow);
|
||||
}
|
||||
|
||||
Point<int> localToGlobal (Point<int> relativePosition) override
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override
|
||||
{
|
||||
return relativePosition + getBounds (true).getPosition();
|
||||
return relativePosition + getBounds (true).getPosition().toFloat();
|
||||
}
|
||||
|
||||
Point<int> globalToLocal (Point<int> screenPosition) override
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override
|
||||
{
|
||||
return screenPosition - getBounds (true).getPosition();
|
||||
return screenPosition - getBounds (true).getPosition().toFloat();
|
||||
}
|
||||
|
||||
void setAlpha (float newAlpha) override
|
||||
@@ -369,7 +369,7 @@ public:
|
||||
|
||||
// (can't call the component's setBounds method because that'll reset our fullscreen flag)
|
||||
if (r != component.getBounds() && ! r.isEmpty())
|
||||
setBounds (r, shouldBeFullScreen);
|
||||
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -390,16 +390,37 @@ public:
|
||||
return ComponentPeer::isKioskMode();
|
||||
}
|
||||
|
||||
static bool isWindowAtPoint (NSWindow* w, NSPoint screenPoint)
|
||||
{
|
||||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)])
|
||||
return [NSWindow windowNumberAtPoint: screenPoint belowWindowWithWindowNumber: 0] == [w windowNumber];
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override
|
||||
{
|
||||
NSRect frameRect = [view frame];
|
||||
NSRect viewFrame = [view frame];
|
||||
|
||||
if (! (isPositiveAndBelow (localPos.getX(), (int) frameRect.size.width)
|
||||
&& isPositiveAndBelow (localPos.getY(), (int) frameRect.size.height)))
|
||||
if (! (isPositiveAndBelow (localPos.getX(), (int) viewFrame.size.width)
|
||||
&& isPositiveAndBelow (localPos.getY(), (int) viewFrame.size.height)))
|
||||
return false;
|
||||
|
||||
NSView* v = [view hitTest: NSMakePoint (frameRect.origin.x + localPos.getX(),
|
||||
frameRect.origin.y + frameRect.size.height - localPos.getY())];
|
||||
if (NSWindow* const viewWindow = [view window])
|
||||
{
|
||||
const NSRect windowFrame = [viewWindow frame];
|
||||
const NSPoint windowPoint = [view convertPoint: NSMakePoint (localPos.x, localPos.y) toView: nil];
|
||||
const NSPoint screenPoint = NSMakePoint (windowFrame.origin.x + windowPoint.x,
|
||||
windowFrame.origin.y + windowFrame.size.height - windowPoint.y);
|
||||
|
||||
if (! isWindowAtPoint (viewWindow, screenPoint))
|
||||
return false;
|
||||
}
|
||||
|
||||
NSView* v = [view hitTest: NSMakePoint (viewFrame.origin.x + localPos.getX(),
|
||||
viewFrame.origin.y + viewFrame.size.height - localPos.getY())];
|
||||
|
||||
return trueIfInAChildWindow ? (v != nil)
|
||||
: (v == view);
|
||||
@@ -553,19 +574,11 @@ public:
|
||||
{
|
||||
currentModifiers = currentModifiers.withoutMouseButtons();
|
||||
|
||||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)]
|
||||
&& [NSWindow windowNumberAtPoint: [[ev window] convertBaseToScreen: [ev locationInWindow]]
|
||||
belowWindowWithWindowNumber: 0] != [window windowNumber])
|
||||
{
|
||||
// moved into another window which overlaps this one, so trigger an exit
|
||||
handleMouseEvent (0, Point<int> (-1, -1), currentModifiers, getMouseTime (ev));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (isWindowAtPoint ([ev window], [[ev window] convertBaseToScreen: [ev locationInWindow]]))
|
||||
sendMouseEvent (ev);
|
||||
}
|
||||
else
|
||||
// moved into another window which overlaps this one, so trigger an exit
|
||||
handleMouseEvent (0, Point<float> (-1.0f, -1.0f), currentModifiers, getMouseTime (ev));
|
||||
|
||||
showArrowCursorIfNeeded();
|
||||
}
|
||||
@@ -936,7 +949,7 @@ public:
|
||||
MouseInputSource mouse = desktop.getMainMouseSource();
|
||||
|
||||
if (mouse.getComponentUnderMouse() == nullptr
|
||||
&& desktop.findComponentAt (mouse.getScreenPosition()) == nullptr)
|
||||
&& desktop.findComponentAt (mouse.getScreenPosition().roundToInt()) == nullptr)
|
||||
{
|
||||
[[NSCursor arrowCursor] set];
|
||||
}
|
||||
@@ -1010,10 +1023,10 @@ public:
|
||||
+ (int64) ([e timestamp] * 1000.0);
|
||||
}
|
||||
|
||||
static Point<int> getMousePos (NSEvent* e, NSView* view)
|
||||
static Point<float> getMousePos (NSEvent* e, NSView* view)
|
||||
{
|
||||
NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil];
|
||||
return Point<int> ((int) p.x, (int) ([view frame].size.height - p.y));
|
||||
return Point<float> ((float) p.x, (float) ([view frame].size.height - p.y));
|
||||
}
|
||||
|
||||
static int getModifierForButtonNumber (const NSInteger num)
|
||||
@@ -1136,8 +1149,9 @@ public:
|
||||
|
||||
bool isFocused() const override
|
||||
{
|
||||
return isSharedWindow ? this == currentlyFocusedPeer
|
||||
: [window isKeyWindow];
|
||||
return (isSharedWindow || ! JUCEApplication::isStandaloneApp())
|
||||
? this == currentlyFocusedPeer
|
||||
: [window isKeyWindow];
|
||||
}
|
||||
|
||||
void grabFocus() override
|
||||
@@ -1151,7 +1165,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void textInputRequired (const Point<int>&) override {}
|
||||
void textInputRequired (Point<int>, TextInputTarget&) override {}
|
||||
|
||||
//==============================================================================
|
||||
void repaint (const Rectangle<int>& area) override
|
||||
@@ -1221,6 +1235,8 @@ private:
|
||||
const Rectangle<int> clipBounds (clipW, clipH);
|
||||
const CGFloat viewH = [view frame].size.height;
|
||||
|
||||
clip.ensureStorageAllocated ((int) numRects);
|
||||
|
||||
for (int i = 0; i < numRects; ++i)
|
||||
clip.addWithoutMerging (clipBounds.getIntersection (Rectangle<int> (roundToInt (rects[i].origin.x) + offset.x,
|
||||
roundToInt (viewH - (rects[i].origin.y + rects[i].size.height)) + offset.y,
|
||||
@@ -1687,21 +1703,22 @@ private:
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct JuceNSWindowClass : public ObjCClass <NSWindow>
|
||||
struct JuceNSWindowClass : public ObjCClass<NSWindow>
|
||||
{
|
||||
JuceNSWindowClass() : ObjCClass <NSWindow> ("JUCEWindow_")
|
||||
JuceNSWindowClass() : ObjCClass<NSWindow> ("JUCEWindow_")
|
||||
{
|
||||
addIvar<NSViewComponentPeer*> ("owner");
|
||||
|
||||
addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:");
|
||||
addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:");
|
||||
addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@");
|
||||
addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@");
|
||||
addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize));
|
||||
addMethod (@selector (zoom:), zoom, "v@:@");
|
||||
addMethod (@selector (windowWillMove:), windowWillMove, "v@:@");
|
||||
addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:");
|
||||
addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:");
|
||||
addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@");
|
||||
addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@");
|
||||
addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize));
|
||||
addMethod (@selector (windowDidExitFullScreen:), windowDidExitFullScreen, "v@:@");
|
||||
addMethod (@selector (zoom:), zoom, "v@:@");
|
||||
addMethod (@selector (windowWillMove:), windowWillMove, "v@:@");
|
||||
addMethod (@selector (windowWillStartLiveResize:), windowWillStartLiveResize, "v@:@");
|
||||
addMethod (@selector (windowDidEndLiveResize:), windowDidEndLiveResize, "v@:@");
|
||||
addMethod (@selector (windowDidEndLiveResize:), windowDidEndLiveResize, "v@:@");
|
||||
|
||||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
addProtocol (@protocol (NSWindowDelegate));
|
||||
@@ -1767,6 +1784,11 @@ private:
|
||||
return frameRect.size;
|
||||
}
|
||||
|
||||
static void windowDidExitFullScreen (id, SEL, NSNotification*)
|
||||
{
|
||||
[NSApp setPresentationOptions: NSApplicationPresentationDefault];
|
||||
}
|
||||
|
||||
static void zoom (id self, SEL, id sender)
|
||||
{
|
||||
if (NSViewComponentPeer* const owner = getOwner (self))
|
||||
@@ -1865,7 +1887,7 @@ bool MouseInputSource::SourceList::addSource()
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, bool allowMenusAndBars)
|
||||
void Desktop::setKioskComponent (Component* kioskComp, bool shouldBeEnabled, bool allowMenusAndBars)
|
||||
{
|
||||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
|
||||
|
||||
@@ -1876,13 +1898,15 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo
|
||||
if (peer->hasNativeTitleBar()
|
||||
&& [peer->window respondsToSelector: @selector (toggleFullScreen:)])
|
||||
{
|
||||
[peer->window performSelector: @selector (toggleFullScreen:)
|
||||
withObject: [NSNumber numberWithBool: (BOOL) enableOrDisable]];
|
||||
if (shouldBeEnabled && ! allowMenusAndBars)
|
||||
[NSApp setPresentationOptions: NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar];
|
||||
|
||||
[peer->window performSelector: @selector (toggleFullScreen:) withObject: nil];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (enableOrDisable)
|
||||
if (shouldBeEnabled)
|
||||
{
|
||||
if (peer->hasNativeTitleBar())
|
||||
[peer->window setStyleMask: NSBorderlessWindowMask];
|
||||
@@ -1904,9 +1928,7 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo
|
||||
}
|
||||
}
|
||||
#elif JUCE_SUPPORT_CARBON
|
||||
(void) kioskComp; (void) enableOrDisable; (void) allowMenusAndBars;
|
||||
|
||||
if (enableOrDisable)
|
||||
if (shouldBeEnabled)
|
||||
{
|
||||
SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0);
|
||||
kioskComp->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea);
|
||||
@@ -1916,7 +1938,7 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo
|
||||
SetSystemUIMode (kUIModeNormal, 0);
|
||||
}
|
||||
#else
|
||||
(void) kioskComp; (void) enableOrDisable; (void) allowMenusAndBars;
|
||||
(void) kioskComp; (void) shouldBeEnabled; (void) allowMenusAndBars;
|
||||
|
||||
// If you're targeting OSes earlier than 10.6 and want to use this feature,
|
||||
// you'll need to enable JUCE_SUPPORT_CARBON.
|
||||
|
||||
@@ -209,16 +209,16 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
|
||||
return true;
|
||||
}
|
||||
|
||||
Point<int> MouseInputSource::getCurrentRawMousePosition()
|
||||
Point<float> MouseInputSource::getCurrentRawMousePosition()
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
const NSPoint p ([NSEvent mouseLocation]);
|
||||
return Point<int> (roundToInt (p.x), roundToInt (getMainScreenHeight() - p.y));
|
||||
return Point<float> ((float) p.x, (float) (getMainScreenHeight() - p.y));
|
||||
}
|
||||
}
|
||||
|
||||
void MouseInputSource::setRawMousePosition (Point<int> newPosition)
|
||||
void MouseInputSource::setRawMousePosition (Point<float> newPosition)
|
||||
{
|
||||
// this rubbish needs to be done around the warp call, to avoid causing a
|
||||
// bizarre glitch..
|
||||
@@ -354,6 +354,30 @@ static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom)
|
||||
return convertToRectInt (r);
|
||||
}
|
||||
|
||||
static Desktop::Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenBottom, const float masterScale)
|
||||
{
|
||||
Desktop::Displays::Display d;
|
||||
|
||||
d.isMain = (mainScreenBottom == 0);
|
||||
|
||||
if (d.isMain)
|
||||
mainScreenBottom = [s frame].size.height;
|
||||
|
||||
d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale;
|
||||
d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale;
|
||||
d.scale = masterScale;
|
||||
|
||||
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
|
||||
if ([s respondsToSelector: @selector (backingScaleFactor)])
|
||||
d.scale *= s.backingScaleFactor;
|
||||
#endif
|
||||
|
||||
NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue];
|
||||
d.dpi = (dpi.width + dpi.height) / 2.0;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void Desktop::Displays::findDisplays (const float masterScale)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
@@ -363,30 +387,7 @@ void Desktop::Displays::findDisplays (const float masterScale)
|
||||
CGFloat mainScreenBottom = 0;
|
||||
|
||||
for (NSScreen* s in [NSScreen screens])
|
||||
{
|
||||
Display d;
|
||||
d.isMain = false;
|
||||
|
||||
if (mainScreenBottom == 0)
|
||||
{
|
||||
mainScreenBottom = [s frame].size.height;
|
||||
d.isMain = true;
|
||||
}
|
||||
|
||||
d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale;
|
||||
d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale;
|
||||
d.scale = masterScale;
|
||||
|
||||
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
|
||||
if ([s respondsToSelector: @selector (backingScaleFactor)])
|
||||
d.scale *= s.backingScaleFactor;
|
||||
#endif
|
||||
|
||||
NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue];
|
||||
d.dpi = (dpi.width + dpi.height) / 2.0;
|
||||
|
||||
displays.add (d);
|
||||
}
|
||||
displays.add (getDisplayFromScreen (s, mainScreenBottom, masterScale));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@ static void setWindowZOrder (HWND hwnd, HWND insertAfter)
|
||||
//==============================================================================
|
||||
static void setDPIAwareness()
|
||||
{
|
||||
#if ! JUCE_DISABLE_WIN32_DPI_AWARENESS
|
||||
if (JUCEApplicationBase::isStandaloneApp())
|
||||
{
|
||||
if (setProcessDPIAwareness == nullptr)
|
||||
@@ -203,6 +204,7 @@ static void setDPIAwareness()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static double getGlobalDPI()
|
||||
@@ -704,8 +706,8 @@ public:
|
||||
r.top + windowBorder.getTop());
|
||||
}
|
||||
|
||||
Point<int> localToGlobal (Point<int> relativePosition) override { return relativePosition + getScreenPosition(); }
|
||||
Point<int> globalToLocal (Point<int> screenPosition) override { return screenPosition - getScreenPosition(); }
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override { return relativePosition + getScreenPosition().toFloat(); }
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override { return screenPosition - getScreenPosition().toFloat(); }
|
||||
|
||||
void setAlpha (float newAlpha) override
|
||||
{
|
||||
@@ -763,7 +765,7 @@ public:
|
||||
ShowWindow (hwnd, SW_SHOWNORMAL);
|
||||
|
||||
if (! boundsCopy.isEmpty())
|
||||
setBounds (boundsCopy, false);
|
||||
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, boundsCopy), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -845,7 +847,7 @@ public:
|
||||
|
||||
void toBehind (ComponentPeer* other) override
|
||||
{
|
||||
if (HWNDComponentPeer* const otherPeer = dynamic_cast <HWNDComponentPeer*> (other))
|
||||
if (HWNDComponentPeer* const otherPeer = dynamic_cast<HWNDComponentPeer*> (other))
|
||||
{
|
||||
setMinimised (false);
|
||||
|
||||
@@ -877,7 +879,7 @@ public:
|
||||
shouldDeactivateTitleBar = oldDeactivate;
|
||||
}
|
||||
|
||||
void textInputRequired (const Point<int>&) override
|
||||
void textInputRequired (Point<int>, TextInputTarget&) override
|
||||
{
|
||||
if (! hasCreatedCaret)
|
||||
{
|
||||
@@ -902,10 +904,15 @@ public:
|
||||
|
||||
void performAnyPendingRepaintsNow() override
|
||||
{
|
||||
MSG m;
|
||||
if (component.isVisible()
|
||||
&& (PeekMessage (&m, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE) || isUsingUpdateLayeredWindow()))
|
||||
handlePaintMessage();
|
||||
if (component.isVisible())
|
||||
{
|
||||
WeakReference<Component> localRef (&component);
|
||||
MSG m;
|
||||
|
||||
if (isUsingUpdateLayeredWindow() || PeekMessage (&m, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE))
|
||||
if (localRef != nullptr) // (the PeekMessage call can dispatch messages, which may delete this comp)
|
||||
handlePaintMessage();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -955,7 +962,7 @@ public:
|
||||
static ModifierKeys modifiersAtLastCallback;
|
||||
|
||||
//==============================================================================
|
||||
class JuceDropTarget : public ComBaseClassHelper <IDropTarget>
|
||||
class JuceDropTarget : public ComBaseClassHelper<IDropTarget>
|
||||
{
|
||||
public:
|
||||
JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {}
|
||||
@@ -988,7 +995,7 @@ public:
|
||||
if (ownerInfo == nullptr)
|
||||
return S_FALSE;
|
||||
|
||||
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos);
|
||||
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt();
|
||||
const bool wasWanted = ownerInfo->owner.handleDragMove (ownerInfo->dragInfo);
|
||||
*pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE;
|
||||
return S_OK;
|
||||
@@ -999,7 +1006,7 @@ public:
|
||||
HRESULT hr = updateFileList (pDataObject);
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos);
|
||||
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt();
|
||||
const bool wasWanted = ownerInfo->owner.handleDragDrop (ownerInfo->dragInfo);
|
||||
*pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE;
|
||||
hr = S_OK;
|
||||
@@ -1013,9 +1020,10 @@ public:
|
||||
{
|
||||
OwnerInfo (HWNDComponentPeer& p) : owner (p) {}
|
||||
|
||||
Point<int> getMousePos (const POINTL& mousePos) const
|
||||
Point<float> getMousePos (const POINTL& mousePos) const
|
||||
{
|
||||
return owner.globalToLocal (Point<int> (mousePos.x, mousePos.y));
|
||||
return owner.globalToLocal (Point<float> (static_cast<float> (mousePos.x),
|
||||
static_cast<float> (mousePos.y)));
|
||||
}
|
||||
|
||||
template <typename CharType>
|
||||
@@ -1093,13 +1101,13 @@ public:
|
||||
|
||||
if (SUCCEEDED (fileData.error))
|
||||
{
|
||||
const LPDROPFILES dropFiles = static_cast <const LPDROPFILES> (fileData.data);
|
||||
const LPDROPFILES dropFiles = static_cast<const LPDROPFILES> (fileData.data);
|
||||
const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES));
|
||||
|
||||
if (dropFiles->fWide)
|
||||
ownerInfo->parseFileList (static_cast <const WCHAR*> (names), fileData.dataSize);
|
||||
ownerInfo->parseFileList (static_cast<const WCHAR*> (names), fileData.dataSize);
|
||||
else
|
||||
ownerInfo->parseFileList (static_cast <const char*> (names), fileData.dataSize);
|
||||
ownerInfo->parseFileList (static_cast<const char*> (names), fileData.dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1294,7 +1302,7 @@ private:
|
||||
//==============================================================================
|
||||
static void* createWindowCallback (void* userData)
|
||||
{
|
||||
static_cast <HWNDComponentPeer*> (userData)->createWindow();
|
||||
static_cast<HWNDComponentPeer*> (userData)->createWindow();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1522,10 +1530,14 @@ private:
|
||||
// if something in a paint handler calls, e.g. a message box, this can become reentrant and
|
||||
// corrupt the image it's using to paint into, so do a check here.
|
||||
static bool reentrant = false;
|
||||
if (! (reentrant || dontRepaint))
|
||||
if (! reentrant)
|
||||
{
|
||||
const ScopedValueSetter<bool> setter (reentrant, true, false);
|
||||
performPaint (dc, rgn, regionType, paintStruct);
|
||||
|
||||
if (dontRepaint)
|
||||
component.handleCommandMessage (0); // (this triggers a repaint in the openGL context)
|
||||
else
|
||||
performPaint (dc, rgn, regionType, paintStruct);
|
||||
}
|
||||
|
||||
DeleteObject (rgn);
|
||||
@@ -1633,7 +1645,7 @@ private:
|
||||
handlePaint (*context);
|
||||
}
|
||||
|
||||
static_cast <WindowsBitmapImage*> (offscreenImage.getPixelData())
|
||||
static_cast<WindowsBitmapImage*> (offscreenImage.getPixelData())
|
||||
->blitToWindow (hwnd, dc, transparent, x, y, updateLayeredWindowAlpha);
|
||||
}
|
||||
|
||||
@@ -1643,7 +1655,7 @@ private:
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void doMouseEvent (Point<int> position)
|
||||
void doMouseEvent (Point<float> position)
|
||||
{
|
||||
handleMouseEvent (0, position, currentModifiers, getMouseEventTime());
|
||||
}
|
||||
@@ -1694,7 +1706,7 @@ private:
|
||||
return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP..
|
||||
}
|
||||
|
||||
void doMouseMove (Point<int> position)
|
||||
void doMouseMove (Point<float> position)
|
||||
{
|
||||
if (! isMouseOver)
|
||||
{
|
||||
@@ -1715,7 +1727,7 @@ private:
|
||||
}
|
||||
else if (! isDragging)
|
||||
{
|
||||
if (! contains (position, false))
|
||||
if (! contains (position.roundToInt(), false))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1730,7 +1742,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void doMouseDown (Point<int> position, const WPARAM wParam)
|
||||
void doMouseDown (Point<float> position, const WPARAM wParam)
|
||||
{
|
||||
if (GetCapture() != hwnd)
|
||||
SetCapture (hwnd);
|
||||
@@ -1743,7 +1755,7 @@ private:
|
||||
doMouseEvent (position);
|
||||
}
|
||||
|
||||
void doMouseUp (Point<int> position, const WPARAM wParam)
|
||||
void doMouseUp (Point<float> position, const WPARAM wParam)
|
||||
{
|
||||
updateModifiersFromWParam (wParam);
|
||||
const bool wasDragging = isDragging;
|
||||
@@ -1779,9 +1791,9 @@ private:
|
||||
doMouseEvent (getCurrentMousePos());
|
||||
}
|
||||
|
||||
ComponentPeer* findPeerUnderMouse (Point<int>& localPos)
|
||||
ComponentPeer* findPeerUnderMouse (Point<float>& localPos)
|
||||
{
|
||||
const Point<int> globalPos (getCurrentMousePosGlobal());
|
||||
const Point<int> globalPos (getCurrentMousePosGlobal().roundToInt());
|
||||
|
||||
// Because Windows stupidly sends all wheel events to the window with the keyboard
|
||||
// focus, we have to redirect them here according to the mouse pos..
|
||||
@@ -1791,7 +1803,7 @@ private:
|
||||
if (peer == nullptr)
|
||||
peer = this;
|
||||
|
||||
localPos = peer->globalToLocal (globalPos);
|
||||
localPos = peer->globalToLocal (globalPos.toFloat());
|
||||
return peer;
|
||||
}
|
||||
|
||||
@@ -1806,7 +1818,7 @@ private:
|
||||
wheel.isReversed = false;
|
||||
wheel.isSmooth = false;
|
||||
|
||||
Point<int> localPos;
|
||||
Point<float> localPos;
|
||||
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))
|
||||
peer->handleMouseWheel (0, localPos, getMouseEventTime(), wheel);
|
||||
}
|
||||
@@ -1820,7 +1832,7 @@ private:
|
||||
if (getGestureInfo != nullptr && getGestureInfo ((HGESTUREINFO) lParam, &gi))
|
||||
{
|
||||
updateKeyModifiers();
|
||||
Point<int> localPos;
|
||||
Point<float> localPos;
|
||||
|
||||
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))
|
||||
{
|
||||
@@ -1878,8 +1890,8 @@ private:
|
||||
bool isCancel = false;
|
||||
const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID);
|
||||
const int64 time = getMouseEventTime();
|
||||
const Point<int> pos (globalToLocal (Point<int> ((int) TOUCH_COORD_TO_PIXEL (touch.x),
|
||||
(int) TOUCH_COORD_TO_PIXEL (touch.y))));
|
||||
const Point<float> pos (globalToLocal (Point<float> (static_cast<float> (TOUCH_COORD_TO_PIXEL (touch.x)),
|
||||
static_cast<float> (TOUCH_COORD_TO_PIXEL (touch.y)))));
|
||||
ModifierKeys modsToSend (currentModifiers);
|
||||
|
||||
if (isDown)
|
||||
@@ -1890,7 +1902,7 @@ private:
|
||||
if (! isPrimary)
|
||||
{
|
||||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before.
|
||||
handleMouseEvent (touchIndex, pos, modsToSend.withoutMouseButtons(), time);
|
||||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend.withoutMouseButtons(), time);
|
||||
if (! isValidPeer (this)) // (in case this component was deleted by the event)
|
||||
return false;
|
||||
}
|
||||
@@ -1916,14 +1928,14 @@ private:
|
||||
|
||||
if (! isPrimary)
|
||||
{
|
||||
handleMouseEvent (touchIndex, pos, modsToSend, time);
|
||||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, time);
|
||||
if (! isValidPeer (this)) // (in case this component was deleted by the event)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((isUp || isCancel) && ! isPrimary)
|
||||
{
|
||||
handleMouseEvent (touchIndex, Point<int> (-10, -10), currentModifiers, time);
|
||||
handleMouseEvent (touchIndex, Point<float> (-10.0f, -10.0f), currentModifiers, time);
|
||||
if (! isValidPeer (this))
|
||||
return false;
|
||||
}
|
||||
@@ -2203,6 +2215,22 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool handlePositionChanged()
|
||||
{
|
||||
const Point<float> pos (getCurrentMousePos());
|
||||
|
||||
if (contains (pos.roundToInt(), false))
|
||||
{
|
||||
doMouseEvent (pos);
|
||||
|
||||
if (! isValidPeer (this))
|
||||
return true;
|
||||
}
|
||||
|
||||
handleMovedOrResized();
|
||||
return ! dontRepaint; // to allow non-accelerated openGL windows to draw themselves correctly..
|
||||
}
|
||||
|
||||
void handleAppActivation (const WPARAM wParam)
|
||||
{
|
||||
modifiersAtLastCallback = -1;
|
||||
@@ -2213,7 +2241,7 @@ private:
|
||||
component.repaint();
|
||||
handleMovedOrResized();
|
||||
|
||||
if (! ComponentPeer::isValidPeer (this))
|
||||
if (! isValidPeer (this))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2235,6 +2263,24 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void handlePowerBroadcast (WPARAM wParam)
|
||||
{
|
||||
if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case PBT_APMSUSPEND: app->suspended(); break;
|
||||
|
||||
case PBT_APMQUERYSUSPENDFAILED:
|
||||
case PBT_APMRESUMECRITICAL:
|
||||
case PBT_APMRESUMESUSPEND:
|
||||
case PBT_APMRESUMEAUTOMATIC: app->resumed(); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleLeftClickInNCArea (WPARAM wParam)
|
||||
{
|
||||
if (! sendInputAttemptWhenModalMessage())
|
||||
@@ -2283,7 +2329,7 @@ private:
|
||||
{
|
||||
Desktop& desktop = Desktop::getInstance();
|
||||
|
||||
const_cast <Desktop::Displays&> (desktop.getDisplays()).refresh();
|
||||
const_cast<Desktop::Displays&> (desktop.getDisplays()).refresh();
|
||||
|
||||
if (fullScreen && ! isMinimised())
|
||||
{
|
||||
@@ -2321,17 +2367,18 @@ private:
|
||||
return MessageManager::getInstance()->callFunctionOnMessageThread (callback, userData);
|
||||
}
|
||||
|
||||
static Point<int> getPointFromLParam (LPARAM lParam) noexcept
|
||||
static Point<float> getPointFromLParam (LPARAM lParam) noexcept
|
||||
{
|
||||
return Point<int> (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam));
|
||||
return Point<float> (static_cast<float> (GET_X_LPARAM (lParam)),
|
||||
static_cast<float> (GET_Y_LPARAM (lParam)));
|
||||
}
|
||||
|
||||
static Point<int> getCurrentMousePosGlobal() noexcept
|
||||
static Point<float> getCurrentMousePosGlobal() noexcept
|
||||
{
|
||||
return getPointFromLParam (GetMessagePos());
|
||||
}
|
||||
|
||||
Point<int> getCurrentMousePos() noexcept
|
||||
Point<float> getCurrentMousePos() noexcept
|
||||
{
|
||||
return globalToLocal (getCurrentMousePosGlobal());
|
||||
}
|
||||
@@ -2411,18 +2458,10 @@ private:
|
||||
case WM_WINDOWPOSCHANGING: return handlePositionChanging (*(WINDOWPOS*) lParam);
|
||||
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
const Point<int> pos (getCurrentMousePos());
|
||||
if (contains (pos, false))
|
||||
doMouseEvent (pos);
|
||||
}
|
||||
if (handlePositionChanged())
|
||||
return 0;
|
||||
|
||||
handleMovedOrResized();
|
||||
|
||||
if (dontRepaint)
|
||||
break; // needed for non-accelerated openGL windows to draw themselves correctly..
|
||||
|
||||
return 0;
|
||||
break;
|
||||
|
||||
//==============================================================================
|
||||
case WM_KEYDOWN:
|
||||
@@ -2531,6 +2570,10 @@ private:
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case WM_POWERBROADCAST:
|
||||
handlePowerBroadcast (wParam);
|
||||
break;
|
||||
|
||||
case WM_SYNCPAINT:
|
||||
return 0;
|
||||
|
||||
@@ -2860,7 +2903,7 @@ private:
|
||||
|
||||
void moveCandidateWindowToLeftAlignWithSelection (HIMC hImc, ComponentPeer& peer, TextInputTarget* target) const
|
||||
{
|
||||
if (Component* const targetComp = dynamic_cast <Component*> (target))
|
||||
if (Component* const targetComp = dynamic_cast<Component*> (target))
|
||||
{
|
||||
const Rectangle<int> area (peer.getComponent().getLocalArea (targetComp, target->getCaretRectangle()));
|
||||
|
||||
@@ -2881,18 +2924,15 @@ private:
|
||||
ModifierKeys HWNDComponentPeer::currentModifiers;
|
||||
ModifierKeys HWNDComponentPeer::modifiersAtLastCallback;
|
||||
|
||||
ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAttachTo)
|
||||
ComponentPeer* Component::createNewPeer (int styleFlags, void* parentHWND)
|
||||
{
|
||||
return new HWNDComponentPeer (*this, styleFlags,
|
||||
(HWND) nativeWindowToAttachTo, false);
|
||||
return new HWNDComponentPeer (*this, styleFlags, (HWND) parentHWND, false);
|
||||
}
|
||||
|
||||
ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component* component, void* parent)
|
||||
ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component& component, void* parentHWND)
|
||||
{
|
||||
jassert (component != nullptr);
|
||||
|
||||
return new HWNDComponentPeer (*component, ComponentPeer::windowIgnoresMouseClicks,
|
||||
(HWND) parent, true);
|
||||
return new HWNDComponentPeer (component, ComponentPeer::windowIgnoresMouseClicks,
|
||||
(HWND) parentHWND, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -2965,7 +3005,7 @@ bool JUCE_CALLTYPE Process::isForegroundProcess()
|
||||
fg = GetAncestor (fg, GA_ROOT);
|
||||
|
||||
for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
|
||||
if (HWNDComponentPeer* const wp = dynamic_cast <HWNDComponentPeer*> (ComponentPeer::getPeer (i)))
|
||||
if (HWNDComponentPeer* const wp = dynamic_cast<HWNDComponentPeer*> (ComponentPeer::getPeer (i)))
|
||||
if (wp->isInside (fg))
|
||||
return true;
|
||||
|
||||
@@ -2991,7 +3031,7 @@ static BOOL CALLBACK enumAlwaysOnTopWindows (HWND hwnd, LPARAM lParam)
|
||||
if (GetWindowInfo (hwnd, &info)
|
||||
&& (info.dwExStyle & WS_EX_TOPMOST) != 0)
|
||||
{
|
||||
*reinterpret_cast <bool*> (lParam) = true;
|
||||
*reinterpret_cast<bool*> (lParam) = true;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -3126,16 +3166,17 @@ bool MouseInputSource::SourceList::addSource()
|
||||
return false;
|
||||
}
|
||||
|
||||
Point<int> MouseInputSource::getCurrentRawMousePosition()
|
||||
Point<float> MouseInputSource::getCurrentRawMousePosition()
|
||||
{
|
||||
POINT mousePos;
|
||||
GetCursorPos (&mousePos);
|
||||
return Point<int> (mousePos.x, mousePos.y);
|
||||
return Point<float> ((float) mousePos.x, (float) mousePos.y);
|
||||
}
|
||||
|
||||
void MouseInputSource::setRawMousePosition (Point<int> newPosition)
|
||||
void MouseInputSource::setRawMousePosition (Point<float> newPosition)
|
||||
{
|
||||
SetCursorPos (newPosition.x, newPosition.y);
|
||||
SetCursorPos (roundToInt (newPosition.x),
|
||||
roundToInt (newPosition.y));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -3195,7 +3236,7 @@ void SystemClipboard::copyTextToClipboard (const String& text)
|
||||
{
|
||||
if (HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bytesNeeded + sizeof (WCHAR)))
|
||||
{
|
||||
if (WCHAR* const data = static_cast <WCHAR*> (GlobalLock (bufH)))
|
||||
if (WCHAR* const data = static_cast<WCHAR*> (GlobalLock (bufH)))
|
||||
{
|
||||
text.copyToUTF16 (data, bytesNeeded);
|
||||
GlobalUnlock (bufH);
|
||||
|
||||
@@ -81,8 +81,9 @@ public:
|
||||
bool isDynamic() const;
|
||||
|
||||
/** Returns a string which represents this point.
|
||||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of
|
||||
the string syntax used by the coordinates, see the RelativeCoordinate constructor notes.
|
||||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom.
|
||||
If you're using this to position a Component, then see the notes for
|
||||
Component::setBounds (const RelativeRectangle&) for details of the syntax used.
|
||||
The string that is returned can be passed to the RelativeRectangle constructor to recreate the rectangle.
|
||||
*/
|
||||
String toString() const;
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ void BooleanPropertyComponent::paint (Graphics& g)
|
||||
{
|
||||
PropertyComponent::paint (g);
|
||||
|
||||
g.setColour (Colours::white);
|
||||
g.setColour (findColour (backgroundColourId));
|
||||
g.fillRect (button.getBounds());
|
||||
|
||||
g.setColour (findColour (ComboBox::outlineColourId));
|
||||
|
||||
@@ -56,6 +56,10 @@ protected:
|
||||
public:
|
||||
/** Creates a button component.
|
||||
|
||||
Note that if you call this constructor then you must use the Value to interact with the
|
||||
button state, and you can't override the class with your own setState or getState methods.
|
||||
If you want to use getState and setState, call the other constructor instead.
|
||||
|
||||
@param valueToControl a Value object that this property should refer to.
|
||||
@param propertyName the property name to be passed to the PropertyComponent
|
||||
@param buttonText the text shown in the ToggleButton component
|
||||
@@ -74,6 +78,20 @@ public:
|
||||
/** Must return the current value of the property. */
|
||||
virtual bool getState() const;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the component.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
backgroundColourId = 0x100e801, /**< The colour to fill the background of the button area. */
|
||||
outlineColourId = 0x100e803, /**< The colour to use to draw an outline around the text area. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
|
||||
@@ -74,7 +74,7 @@ ChoicePropertyComponent::ChoicePropertyComponent (const String& name)
|
||||
ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl,
|
||||
const String& name,
|
||||
const StringArray& choiceList,
|
||||
const Array <var>& correspondingValues)
|
||||
const Array<var>& correspondingValues)
|
||||
: PropertyComponent (name),
|
||||
choices (choiceList),
|
||||
isCustomClass (false)
|
||||
|
||||
@@ -50,15 +50,17 @@ class JUCE_API ChoicePropertyComponent : public PropertyComponent,
|
||||
{
|
||||
protected:
|
||||
/** Creates the component.
|
||||
|
||||
Your subclass's constructor must add a list of options to the choices
|
||||
member variable.
|
||||
Your subclass's constructor must add a list of options to the choices member variable.
|
||||
*/
|
||||
ChoicePropertyComponent (const String& propertyName);
|
||||
|
||||
public:
|
||||
/** Creates the component.
|
||||
|
||||
Note that if you call this constructor then you must use the Value to interact with the
|
||||
index, and you can't override the class with your own setIndex or getIndex methods.
|
||||
If you want to use those methods, call the other constructor instead.
|
||||
|
||||
@param valueToControl the value that the combo box will read and control
|
||||
@param propertyName the name of the property
|
||||
@param choices the list of possible values that the drop-down list will contain
|
||||
@@ -70,7 +72,7 @@ public:
|
||||
ChoicePropertyComponent (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
const StringArray& choices,
|
||||
const Array <var>& correspondingValues);
|
||||
const Array<var>& correspondingValues);
|
||||
|
||||
/** Destructor. */
|
||||
~ChoicePropertyComponent();
|
||||
|
||||
@@ -58,6 +58,10 @@ public:
|
||||
|
||||
If you need to customise the slider in other ways, your constructor can
|
||||
access the slider member variable and change it directly.
|
||||
|
||||
Note that if you call this constructor then you must use the Value to interact with
|
||||
the value, and you can't override the class with your own setValue or getValue methods.
|
||||
If you want to use those methods, call the other constructor instead.
|
||||
*/
|
||||
SliderPropertyComponent (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
|
||||
@@ -49,7 +49,7 @@ ComboBox::ComboBox (const String& name)
|
||||
noChoicesMessage (TRANS("(no choices)"))
|
||||
{
|
||||
setRepaintsOnMouseActivity (true);
|
||||
ComboBox::lookAndFeelChanged();
|
||||
lookAndFeelChanged();
|
||||
currentId.addListener (this);
|
||||
}
|
||||
|
||||
@@ -410,12 +410,22 @@ void ComboBox::enablementChanged()
|
||||
repaint();
|
||||
}
|
||||
|
||||
void ComboBox::colourChanged()
|
||||
{
|
||||
lookAndFeelChanged();
|
||||
}
|
||||
|
||||
void ComboBox::parentHierarchyChanged()
|
||||
{
|
||||
lookAndFeelChanged();
|
||||
}
|
||||
|
||||
void ComboBox::lookAndFeelChanged()
|
||||
{
|
||||
repaint();
|
||||
|
||||
{
|
||||
ScopedPointer <Label> newLabel (getLookAndFeel().createComboBoxTextBox (*this));
|
||||
ScopedPointer<Label> newLabel (getLookAndFeel().createComboBoxTextBox (*this));
|
||||
jassert (newLabel != nullptr);
|
||||
|
||||
if (label != nullptr)
|
||||
@@ -446,11 +456,6 @@ void ComboBox::lookAndFeelChanged()
|
||||
resized();
|
||||
}
|
||||
|
||||
void ComboBox::colourChanged()
|
||||
{
|
||||
lookAndFeelChanged();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool ComboBox::keyPressed (const KeyPress& key)
|
||||
{
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
@param newItemId an associated ID number that can be set or retrieved - see
|
||||
getSelectedId() and setSelectedId(). Note that this value can not
|
||||
be 0!
|
||||
@see setItemEnabled, addSeparator, addSectionHeading, removeItem, getNumItems, getItemText, getItemId
|
||||
@see setItemEnabled, addSeparator, addSectionHeading, getNumItems, getItemText, getItemId
|
||||
*/
|
||||
void addItem (const String& newItemText, int newItemId);
|
||||
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
If this call causes the content to be cleared, and a change-message
|
||||
will be broadcast according to the notification parameter.
|
||||
|
||||
@see addItem, removeItem, getNumItems
|
||||
@see addItem, getNumItems
|
||||
*/
|
||||
void clear (NotificationType notification = sendNotificationAsync);
|
||||
|
||||
@@ -257,8 +257,11 @@ public:
|
||||
*/
|
||||
void showEditor();
|
||||
|
||||
/** Pops up the combo box's list. */
|
||||
void showPopup();
|
||||
/** Pops up the combo box's list.
|
||||
This is virtual so that you can override it with your own custom popup
|
||||
mechanism if you need some really unusual behaviour.
|
||||
*/
|
||||
virtual void showPopup();
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
@@ -393,6 +396,8 @@ public:
|
||||
bool keyPressed (const KeyPress&) override;
|
||||
/** @internal */
|
||||
void valueChanged (Value&) override;
|
||||
/** @internal */
|
||||
void parentHierarchyChanged() override;
|
||||
|
||||
// These methods' bool parameters have changed: see their new method signatures.
|
||||
JUCE_DEPRECATED (void clear (bool));
|
||||
@@ -413,7 +418,7 @@ private:
|
||||
bool isEnabled : 1, isHeading : 1;
|
||||
};
|
||||
|
||||
OwnedArray <ItemInfo> items;
|
||||
OwnedArray<ItemInfo> items;
|
||||
Value currentId;
|
||||
int lastCurrentId;
|
||||
bool isButtonDown, separatorPending, menuActive, scrollWheelEnabled;
|
||||
|
||||
@@ -28,8 +28,7 @@ Label::Label (const String& name, const String& labelText)
|
||||
lastTextValue (labelText),
|
||||
font (15.0f),
|
||||
justification (Justification::centredLeft),
|
||||
horizontalBorderSize (5),
|
||||
verticalBorderSize (1),
|
||||
border (1, 5, 1, 5),
|
||||
minimumHorizontalScale (0.7f),
|
||||
editSingleClick (false),
|
||||
editDoubleClick (false),
|
||||
@@ -123,12 +122,11 @@ void Label::setJustificationType (Justification newJustification)
|
||||
}
|
||||
}
|
||||
|
||||
void Label::setBorderSize (int h, int v)
|
||||
void Label::setBorderSize (BorderSize<int> newBorder)
|
||||
{
|
||||
if (horizontalBorderSize != h || verticalBorderSize != v)
|
||||
if (border != newBorder)
|
||||
{
|
||||
horizontalBorderSize = h;
|
||||
verticalBorderSize = v;
|
||||
border = newBorder;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
@@ -191,7 +189,12 @@ void Label::componentVisibilityChanged (Component& component)
|
||||
//==============================================================================
|
||||
void Label::textWasEdited() {}
|
||||
void Label::textWasChanged() {}
|
||||
void Label::editorShown (TextEditor*) {}
|
||||
|
||||
void Label::editorShown (TextEditor* textEditor)
|
||||
{
|
||||
Component::BailOutChecker checker (this);
|
||||
listeners.callChecked (checker, &LabelListener::editorShown, this, *textEditor);
|
||||
}
|
||||
|
||||
void Label::editorAboutToBeHidden (TextEditor*)
|
||||
{
|
||||
@@ -286,11 +289,22 @@ bool Label::isBeingEdited() const noexcept
|
||||
return editor != nullptr;
|
||||
}
|
||||
|
||||
static void copyColourIfSpecified (Label& l, TextEditor& ed, int colourID, int targetColourID)
|
||||
{
|
||||
if (l.isColourSpecified (colourID) || l.getLookAndFeel().isColourSpecified (colourID))
|
||||
ed.setColour (targetColourID, l.findColour (colourID));
|
||||
}
|
||||
|
||||
TextEditor* Label::createEditorComponent()
|
||||
{
|
||||
TextEditor* const ed = new TextEditor (getName());
|
||||
ed->applyFontToAllText (getLookAndFeel().getLabelFont (*this));
|
||||
copyAllExplicitColoursTo (*ed);
|
||||
|
||||
copyColourIfSpecified (*this, *ed, textWhenEditingColourId, TextEditor::textColourId);
|
||||
copyColourIfSpecified (*this, *ed, backgroundWhenEditingColourId, TextEditor::backgroundColourId);
|
||||
copyColourIfSpecified (*this, *ed, outlineWhenEditingColourId, TextEditor::outlineColourId);
|
||||
|
||||
return ed;
|
||||
}
|
||||
|
||||
@@ -325,7 +339,7 @@ void Label::mouseDoubleClick (const MouseEvent& e)
|
||||
void Label::resized()
|
||||
{
|
||||
if (editor != nullptr)
|
||||
editor->setBoundsInset (BorderSize<int> (0));
|
||||
editor->setBounds (getLocalBounds());
|
||||
}
|
||||
|
||||
void Label::focusGained (FocusChangeType cause)
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
You can call Value::referTo() on this object to make the label read and control
|
||||
a Value object that you supply.
|
||||
*/
|
||||
Value& getTextValue() { return textValue; }
|
||||
Value& getTextValue() noexcept { return textValue; }
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the font to use to draw the text.
|
||||
@@ -101,33 +101,32 @@ public:
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */
|
||||
textColourId = 0x1000281, /**< The colour for the text. */
|
||||
outlineColourId = 0x1000282 /**< An optional colour to use to draw a border around the label.
|
||||
Leave this transparent to not have an outline. */
|
||||
backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */
|
||||
textColourId = 0x1000281, /**< The colour for the text. */
|
||||
outlineColourId = 0x1000282, /**< An optional colour to use to draw a border around the label.
|
||||
Leave this transparent to not have an outline. */
|
||||
backgroundWhenEditingColourId = 0x1000283, /**< The background colour when the label is being edited. */
|
||||
textWhenEditingColourId = 0x1000284, /**< The colour for the text when the label is being edited. */
|
||||
outlineWhenEditingColourId = 0x1000285 /**< An optional border colour when the label is being edited. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the style of justification to be used for positioning the text.
|
||||
|
||||
(The default is Justification::centredLeft)
|
||||
*/
|
||||
void setJustificationType (Justification justification);
|
||||
|
||||
/** Returns the type of justification, as set in setJustificationType(). */
|
||||
Justification getJustificationType() const noexcept { return justification; }
|
||||
Justification getJustificationType() const noexcept { return justification; }
|
||||
|
||||
/** Changes the gap that is left between the edge of the component and the text.
|
||||
/** Changes the border that is left between the edge of the component and the text.
|
||||
By default there's a small gap left at the sides of the component to allow for
|
||||
the drawing of the border, but you can change this if necessary.
|
||||
*/
|
||||
void setBorderSize (int horizontalBorder, int verticalBorder);
|
||||
void setBorderSize (BorderSize<int> newBorderSize);
|
||||
|
||||
/** Returns the size of the horizontal gap being left around the text. */
|
||||
int getHorizontalBorderSize() const noexcept { return horizontalBorderSize; }
|
||||
|
||||
/** Returns the size of the vertical gap being left around the text. */
|
||||
int getVerticalBorderSize() const noexcept { return verticalBorderSize; }
|
||||
/** Returns the size of the border to be left around the text. */
|
||||
BorderSize<int> getBorderSize() const noexcept { return border; }
|
||||
|
||||
/** Makes this label "stick to" another component.
|
||||
|
||||
@@ -152,16 +151,17 @@ public:
|
||||
Returns false if the label is above the other component. This is only relevent if
|
||||
attachToComponent() has been called.
|
||||
*/
|
||||
bool isAttachedOnLeft() const noexcept { return leftOfOwnerComp; }
|
||||
bool isAttachedOnLeft() const noexcept { return leftOfOwnerComp; }
|
||||
|
||||
/** Specifies the minimum amount that the font can be squashed horizantally before it starts
|
||||
/** Specifies the minimum amount that the font can be squashed horizontally before it starts
|
||||
using ellipsis.
|
||||
|
||||
@see Graphics::drawFittedText
|
||||
*/
|
||||
void setMinimumHorizontalScale (float newScale);
|
||||
|
||||
float getMinimumHorizontalScale() const noexcept { return minimumHorizontalScale; }
|
||||
/** Specifies the amount that the font can be squashed horizontally. */
|
||||
float getMinimumHorizontalScale() const noexcept { return minimumHorizontalScale; }
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
@@ -182,6 +182,9 @@ public:
|
||||
|
||||
/** Called when a Label's text has changed. */
|
||||
virtual void labelTextChanged (Label* labelThatHasChanged) = 0;
|
||||
|
||||
/** Called when a Label goes into editing mode and displays a TextEditor. */
|
||||
virtual void editorShown (Label*, TextEditor&) {}
|
||||
};
|
||||
|
||||
/** Registers a listener that will be called when the label's text changes. */
|
||||
@@ -228,7 +231,6 @@ public:
|
||||
bool isEditable() const noexcept { return editSingleClick || editDoubleClick; }
|
||||
|
||||
/** Makes the editor appear as if the label had been clicked by the user.
|
||||
|
||||
@see textWasEdited, setEditable
|
||||
*/
|
||||
void showEditor();
|
||||
@@ -327,7 +329,7 @@ private:
|
||||
ScopedPointer<TextEditor> editor;
|
||||
ListenerList<Listener> listeners;
|
||||
WeakReference<Component> ownerComponent;
|
||||
int horizontalBorderSize, verticalBorderSize;
|
||||
BorderSize<int> border;
|
||||
float minimumHorizontalScale;
|
||||
bool editSingleClick;
|
||||
bool editDoubleClick;
|
||||
|
||||
@@ -367,6 +367,7 @@ ListBox::ListBox (const String& name, ListBoxModel* const m)
|
||||
outlineThickness (0),
|
||||
lastRowSelected (-1),
|
||||
multipleSelection (false),
|
||||
alwaysFlipSelection (false),
|
||||
hasDoneInitialUpdate (false)
|
||||
{
|
||||
addAndMakeVisible (viewport = new ListViewport (*this));
|
||||
@@ -391,11 +392,16 @@ void ListBox::setModel (ListBoxModel* const newModel)
|
||||
}
|
||||
}
|
||||
|
||||
void ListBox::setMultipleSelectionEnabled (bool b)
|
||||
void ListBox::setMultipleSelectionEnabled (bool b) noexcept
|
||||
{
|
||||
multipleSelection = b;
|
||||
}
|
||||
|
||||
void ListBox::setClickingTogglesRowSelection (bool b) noexcept
|
||||
{
|
||||
alwaysFlipSelection = b;
|
||||
}
|
||||
|
||||
void ListBox::setMouseMoveSelectsRows (bool b)
|
||||
{
|
||||
if (b)
|
||||
@@ -457,7 +463,7 @@ void ListBox::updateContent()
|
||||
|
||||
if (selected.size() > 0 && selected [selected.size() - 1] >= totalItems)
|
||||
{
|
||||
selected.removeRange (Range <int> (totalItems, std::numeric_limits<int>::max()));
|
||||
selected.removeRange (Range<int> (totalItems, std::numeric_limits<int>::max()));
|
||||
lastRowSelected = getSelectedRow (0);
|
||||
selectionChanged = true;
|
||||
}
|
||||
@@ -470,9 +476,7 @@ void ListBox::updateContent()
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ListBox::selectRow (const int row,
|
||||
bool dontScroll,
|
||||
bool deselectOthersFirst)
|
||||
void ListBox::selectRow (int row, bool dontScroll, bool deselectOthersFirst)
|
||||
{
|
||||
selectRowInternal (row, dontScroll, deselectOthersFirst, false);
|
||||
}
|
||||
@@ -516,7 +520,7 @@ void ListBox::deselectRow (const int row)
|
||||
{
|
||||
if (selected.contains (row))
|
||||
{
|
||||
selected.removeRange (Range <int> (row, row + 1));
|
||||
selected.removeRange (Range<int> (row, row + 1));
|
||||
|
||||
if (row == lastRowSelected)
|
||||
lastRowSelected = getSelectedRow (0);
|
||||
@@ -530,7 +534,7 @@ void ListBox::setSelectedRows (const SparseSet<int>& setOfRowsToBeSelected,
|
||||
const NotificationType sendNotificationEventToModel)
|
||||
{
|
||||
selected = setOfRowsToBeSelected;
|
||||
selected.removeRange (Range <int> (totalItems, std::numeric_limits<int>::max()));
|
||||
selected.removeRange (Range<int> (totalItems, std::numeric_limits<int>::max()));
|
||||
|
||||
if (! isRowSelected (lastRowSelected))
|
||||
lastRowSelected = getSelectedRow (0);
|
||||
@@ -554,10 +558,10 @@ void ListBox::selectRangeOfRows (int firstRow, int lastRow)
|
||||
firstRow = jlimit (0, jmax (0, numRows), firstRow);
|
||||
lastRow = jlimit (0, jmax (0, numRows), lastRow);
|
||||
|
||||
selected.addRange (Range <int> (jmin (firstRow, lastRow),
|
||||
jmax (firstRow, lastRow) + 1));
|
||||
selected.addRange (Range<int> (jmin (firstRow, lastRow),
|
||||
jmax (firstRow, lastRow) + 1));
|
||||
|
||||
selected.removeRange (Range <int> (lastRow, lastRow + 1));
|
||||
selected.removeRange (Range<int> (lastRow, lastRow + 1));
|
||||
}
|
||||
|
||||
selectRowInternal (lastRow, false, false, true);
|
||||
@@ -589,7 +593,7 @@ void ListBox::selectRowsBasedOnModifierKeys (const int row,
|
||||
ModifierKeys mods,
|
||||
const bool isMouseUpEvent)
|
||||
{
|
||||
if (multipleSelection && mods.isCommandDown())
|
||||
if (multipleSelection && (mods.isCommandDown() || alwaysFlipSelection))
|
||||
{
|
||||
flipRowSelection (row);
|
||||
}
|
||||
@@ -652,7 +656,7 @@ int ListBox::getInsertionIndexForPosition (const int x, const int y) const noexc
|
||||
Component* ListBox::getComponentForRowNumber (const int row) const noexcept
|
||||
{
|
||||
if (RowComponent* const listRowComp = viewport->getComponentForRowIfOnscreen (row))
|
||||
return static_cast <Component*> (listRowComp->customComponent);
|
||||
return static_cast<Component*> (listRowComp->customComponent);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -809,7 +813,7 @@ void ListBox::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& whee
|
||||
void ListBox::mouseUp (const MouseEvent& e)
|
||||
{
|
||||
if (e.mouseWasClicked() && model != nullptr)
|
||||
model->backgroundClicked();
|
||||
model->backgroundClicked (e);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -853,6 +857,11 @@ void ListBox::colourChanged()
|
||||
repaint();
|
||||
}
|
||||
|
||||
void ListBox::parentHierarchyChanged()
|
||||
{
|
||||
colourChanged();
|
||||
}
|
||||
|
||||
void ListBox::setOutlineThickness (const int newThickness)
|
||||
{
|
||||
outlineThickness = newThickness;
|
||||
@@ -878,7 +887,7 @@ void ListBox::repaintRow (const int rowNumber) noexcept
|
||||
Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY)
|
||||
{
|
||||
Rectangle<int> imageArea;
|
||||
const int firstRow = getRowContainingPosition (0, 0);
|
||||
const int firstRow = getRowContainingPosition (0, viewport->getY());
|
||||
|
||||
for (int i = getNumRowsOnScreen() + 2; --i >= 0;)
|
||||
{
|
||||
@@ -947,7 +956,7 @@ Component* ListBoxModel::refreshComponentForRow (int, bool, Component* existingC
|
||||
|
||||
void ListBoxModel::listBoxItemClicked (int, const MouseEvent&) {}
|
||||
void ListBoxModel::listBoxItemDoubleClicked (int, const MouseEvent&) {}
|
||||
void ListBoxModel::backgroundClicked() {}
|
||||
void ListBoxModel::backgroundClicked (const MouseEvent&) {}
|
||||
void ListBoxModel::selectedRowsChanged (int) {}
|
||||
void ListBoxModel::deleteKeyPressed (int) {}
|
||||
void ListBoxModel::returnKeyPressed (int) {}
|
||||
|
||||
@@ -45,7 +45,10 @@ public:
|
||||
*/
|
||||
virtual int getNumRows() = 0;
|
||||
|
||||
/** This method must be implemented to draw a row of the list. */
|
||||
/** This method must be implemented to draw a row of the list.
|
||||
Note that the rowNumber value may be greater than the number of rows in your
|
||||
list, so be careful that you don't assume it's less than getNumRows().
|
||||
*/
|
||||
virtual void paintListBoxItem (int rowNumber,
|
||||
Graphics& g,
|
||||
int width, int height,
|
||||
@@ -84,18 +87,18 @@ public:
|
||||
/** This can be overridden to react to the user clicking on a row.
|
||||
@see listBoxItemDoubleClicked
|
||||
*/
|
||||
virtual void listBoxItemClicked (int row, const MouseEvent& e);
|
||||
virtual void listBoxItemClicked (int row, const MouseEvent&);
|
||||
|
||||
/** This can be overridden to react to the user double-clicking on a row.
|
||||
@see listBoxItemClicked
|
||||
*/
|
||||
virtual void listBoxItemDoubleClicked (int row, const MouseEvent& e);
|
||||
virtual void listBoxItemDoubleClicked (int row, const MouseEvent&);
|
||||
|
||||
/** This can be overridden to react to the user clicking on a part of the list where
|
||||
there are no rows.
|
||||
@see listBoxItemClicked
|
||||
*/
|
||||
virtual void backgroundClicked();
|
||||
virtual void backgroundClicked (const MouseEvent&);
|
||||
|
||||
/** Override this to be informed when rows are selected or deselected.
|
||||
|
||||
@@ -152,6 +155,12 @@ public:
|
||||
|
||||
/** You can override this to return a custom mouse cursor for each row. */
|
||||
virtual MouseCursor getMouseCursorForRow (int row);
|
||||
|
||||
private:
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// This method's signature has changed to take a MouseEvent parameter - please update your code!
|
||||
JUCE_DEPRECATED_WITH_BODY (virtual int backgroundClicked(), { return 0; })
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -210,7 +219,16 @@ public:
|
||||
clicked and to get it to do the appropriate selection based on whether
|
||||
the ctrl/shift keys are held down.
|
||||
*/
|
||||
void setMultipleSelectionEnabled (bool shouldBeEnabled);
|
||||
void setMultipleSelectionEnabled (bool shouldBeEnabled) noexcept;
|
||||
|
||||
/** If enabled, this makes the listbox flip the selection status of
|
||||
each row that the user clicks, without affecting other selected rows.
|
||||
|
||||
(This only has an effect if multiple selection is also enabled).
|
||||
If not enabled, you can still get the same row-flipping behaviour by holding
|
||||
down CMD or CTRL when clicking.
|
||||
*/
|
||||
void setClickingTogglesRowSelection (bool flipRowSelection) noexcept;
|
||||
|
||||
/** Makes the list react to mouse moves by selecting the row that the mouse if over.
|
||||
|
||||
@@ -534,6 +552,8 @@ public:
|
||||
/** @internal */
|
||||
void colourChanged() override;
|
||||
/** @internal */
|
||||
void parentHierarchyChanged() override;
|
||||
/** @internal */
|
||||
void startDragAndDrop (const MouseEvent&, const var& dragDescription, bool allowDraggingToOtherWindows);
|
||||
|
||||
private:
|
||||
@@ -549,7 +569,7 @@ private:
|
||||
int totalItems, rowHeight, minimumRowWidth;
|
||||
int outlineThickness;
|
||||
int lastRowSelected;
|
||||
bool multipleSelection, hasDoneInitialUpdate;
|
||||
bool multipleSelection, alwaysFlipSelection, hasDoneInitialUpdate;
|
||||
SparseSet<int> selected;
|
||||
|
||||
void selectRowInternal (int rowNumber, bool dontScrollToShowThisRow,
|
||||
|
||||
@@ -320,12 +320,12 @@ public:
|
||||
{
|
||||
if (notification != dontSendNotification)
|
||||
{
|
||||
owner.valueChanged();
|
||||
|
||||
if (notification == sendNotificationSync)
|
||||
handleAsyncUpdate();
|
||||
else
|
||||
triggerAsyncUpdate();
|
||||
|
||||
owner.valueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,9 +464,9 @@ public:
|
||||
const bool stopAtEnd)
|
||||
{
|
||||
// make sure the values are sensible..
|
||||
jassert (rotaryStart >= 0 && rotaryEnd >= 0);
|
||||
jassert (rotaryStart < float_Pi * 4.0f && rotaryEnd < float_Pi * 4.0f);
|
||||
jassert (rotaryStart < rotaryEnd);
|
||||
jassert (startAngleRadians >= 0 && endAngleRadians >= 0);
|
||||
jassert (startAngleRadians < float_Pi * 4.0f && endAngleRadians < float_Pi * 4.0f);
|
||||
jassert (startAngleRadians < endAngleRadians);
|
||||
|
||||
rotaryStart = startAngleRadians;
|
||||
rotaryEnd = endAngleRadians;
|
||||
@@ -566,6 +566,7 @@ public:
|
||||
|
||||
valueBox->setWantsKeyboardFocus (false);
|
||||
valueBox->setText (previousTextBoxContent, dontSendNotification);
|
||||
valueBox->setTooltip (owner.getTooltip());
|
||||
|
||||
if (valueBox->isEditable() != editableText) // (avoid overriding the single/double click flags unless we have to)
|
||||
valueBox->setEditable (editableText && owner.isEnabled());
|
||||
@@ -577,10 +578,6 @@ public:
|
||||
valueBox->addMouseListener (&owner, false);
|
||||
valueBox->setMouseCursor (MouseCursor::ParentCursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
valueBox->setTooltip (owner.getTooltip());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -667,7 +664,7 @@ public:
|
||||
|
||||
if (isTwoValue || isThreeValue)
|
||||
{
|
||||
const float mousePos = (float) (isVertical() ? e.y : e.x);
|
||||
const float mousePos = isVertical() ? e.position.y : e.position.x;
|
||||
|
||||
const float normalPosDistance = std::abs (getLinearSliderPos (currentValue.getValue()) - mousePos);
|
||||
const float minPosDistance = std::abs (getLinearSliderPos (valueMin.getValue()) - 0.1f - mousePos);
|
||||
@@ -689,10 +686,10 @@ public:
|
||||
//==============================================================================
|
||||
void handleRotaryDrag (const MouseEvent& e)
|
||||
{
|
||||
const int dx = e.x - sliderRect.getCentreX();
|
||||
const int dy = e.y - sliderRect.getCentreY();
|
||||
const float dx = e.position.x - sliderRect.getCentreX();
|
||||
const float dy = e.position.y - sliderRect.getCentreY();
|
||||
|
||||
if (dx * dx + dy * dy > 25)
|
||||
if (dx * dx + dy * dy > 25.0f)
|
||||
{
|
||||
double angle = std::atan2 ((double) dx, (double) -dy);
|
||||
while (angle < 0.0)
|
||||
@@ -736,7 +733,7 @@ public:
|
||||
|
||||
void handleAbsoluteDrag (const MouseEvent& e)
|
||||
{
|
||||
const int mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.x : e.y;
|
||||
const float mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.position.x : e.position.y;
|
||||
double newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize;
|
||||
|
||||
if (style == RotaryHorizontalDrag
|
||||
@@ -745,12 +742,12 @@ public:
|
||||
|| ((style == LinearHorizontal || style == LinearVertical || style == LinearBar || style == LinearBarVertical)
|
||||
&& ! snapsToMousePos))
|
||||
{
|
||||
const int mouseDiff = (style == RotaryHorizontalDrag
|
||||
|| style == LinearHorizontal
|
||||
|| style == LinearBar
|
||||
|| (style == IncDecButtons && incDecDragDirectionIsHorizontal()))
|
||||
? e.x - mouseDragStartPos.x
|
||||
: mouseDragStartPos.y - e.y;
|
||||
const float mouseDiff = (style == RotaryHorizontalDrag
|
||||
|| style == LinearHorizontal
|
||||
|| style == LinearBar
|
||||
|| (style == IncDecButtons && incDecDragDirectionIsHorizontal()))
|
||||
? e.position.x - mouseDragStartPos.x
|
||||
: mouseDragStartPos.y - e.position.y;
|
||||
|
||||
newPos = owner.valueToProportionOfLength (valueOnMouseDown)
|
||||
+ mouseDiff * (1.0 / pixelsForFullDragExtent);
|
||||
@@ -763,7 +760,8 @@ public:
|
||||
}
|
||||
else if (style == RotaryHorizontalVerticalDrag)
|
||||
{
|
||||
const int mouseDiff = (e.x - mouseDragStartPos.x) + (mouseDragStartPos.y - e.y);
|
||||
const float mouseDiff = (e.position.x - mouseDragStartPos.x)
|
||||
+ (mouseDragStartPos.y - e.position.y);
|
||||
|
||||
newPos = owner.valueToProportionOfLength (valueOnMouseDown)
|
||||
+ mouseDiff * (1.0 / pixelsForFullDragExtent);
|
||||
@@ -779,16 +777,16 @@ public:
|
||||
|
||||
void handleVelocityDrag (const MouseEvent& e)
|
||||
{
|
||||
const int mouseDiff = style == RotaryHorizontalVerticalDrag
|
||||
? (e.x - mousePosWhenLastDragged.x) + (mousePosWhenLastDragged.y - e.y)
|
||||
: (isHorizontal()
|
||||
|| style == RotaryHorizontalDrag
|
||||
|| (style == IncDecButtons && incDecDragDirectionIsHorizontal()))
|
||||
? e.x - mousePosWhenLastDragged.x
|
||||
: e.y - mousePosWhenLastDragged.y;
|
||||
const float mouseDiff = style == RotaryHorizontalVerticalDrag
|
||||
? (e.position.x - mousePosWhenLastDragged.x) + (mousePosWhenLastDragged.y - e.position.y)
|
||||
: (isHorizontal()
|
||||
|| style == RotaryHorizontalDrag
|
||||
|| (style == IncDecButtons && incDecDragDirectionIsHorizontal()))
|
||||
? e.position.x - mousePosWhenLastDragged.x
|
||||
: e.position.y - mousePosWhenLastDragged.y;
|
||||
|
||||
const double maxSpeed = jmax (200, sliderRegionSize);
|
||||
double speed = jlimit (0.0, maxSpeed, (double) abs (mouseDiff));
|
||||
double speed = jlimit (0.0, maxSpeed, (double) std::abs (mouseDiff));
|
||||
|
||||
if (speed != 0)
|
||||
{
|
||||
@@ -816,7 +814,7 @@ public:
|
||||
{
|
||||
incDecDragged = false;
|
||||
useDragEvents = false;
|
||||
mouseDragStartPos = mousePosWhenLastDragged = e.getPosition();
|
||||
mouseDragStartPos = mousePosWhenLastDragged = e.position;
|
||||
currentDrag = nullptr;
|
||||
|
||||
if (owner.isEnabled())
|
||||
@@ -887,7 +885,7 @@ public:
|
||||
return;
|
||||
|
||||
incDecDragged = true;
|
||||
mouseDragStartPos = e.getPosition();
|
||||
mouseDragStartPos = e.position;
|
||||
}
|
||||
|
||||
if (isAbsoluteDragMode (e.mods) || (maximum - minimum) / sliderRegionSize < interval)
|
||||
@@ -930,7 +928,7 @@ public:
|
||||
minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue();
|
||||
}
|
||||
|
||||
mousePosWhenLastDragged = e.getPosition();
|
||||
mousePosWhenLastDragged = e.position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,29 +978,45 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
double getMouseWheelDelta (double value, double wheelAmount)
|
||||
{
|
||||
if (style == IncDecButtons)
|
||||
return interval * wheelAmount;
|
||||
|
||||
const double proportionDelta = wheelAmount * 0.15f;
|
||||
const double currentPos = owner.valueToProportionOfLength (value);
|
||||
return owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)) - value;
|
||||
}
|
||||
|
||||
bool mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel)
|
||||
{
|
||||
if (scrollWheelEnabled
|
||||
&& style != TwoValueHorizontal
|
||||
&& style != TwoValueVertical)
|
||||
{
|
||||
if (maximum > minimum && ! e.mods.isAnyMouseButtonDown())
|
||||
// sometimes duplicate wheel events seem to be sent, so since we're going to
|
||||
// bump the value by a minimum of the interval, avoid doing this twice..
|
||||
if (e.eventTime != lastMouseWheelTime)
|
||||
{
|
||||
if (valueBox != nullptr)
|
||||
valueBox->hideEditor (false);
|
||||
lastMouseWheelTime = e.eventTime;
|
||||
|
||||
const double value = (double) currentValue.getValue();
|
||||
const double proportionDelta = (wheel.deltaX != 0 ? -wheel.deltaX : wheel.deltaY)
|
||||
* (wheel.isReversed ? -0.15f : 0.15f);
|
||||
const double currentPos = owner.valueToProportionOfLength (value);
|
||||
const double newValue = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta));
|
||||
if (maximum > minimum && ! e.mods.isAnyMouseButtonDown())
|
||||
{
|
||||
if (valueBox != nullptr)
|
||||
valueBox->hideEditor (false);
|
||||
|
||||
double delta = (newValue != value) ? jmax (std::abs (newValue - value), interval) : 0;
|
||||
if (value > newValue)
|
||||
delta = -delta;
|
||||
const double value = (double) currentValue.getValue();
|
||||
const double delta = getMouseWheelDelta (value, (std::abs (wheel.deltaX) > std::abs (wheel.deltaY)
|
||||
? -wheel.deltaX : wheel.deltaY)
|
||||
* (wheel.isReversed ? -1.0f : 1.0f));
|
||||
if (delta != 0)
|
||||
{
|
||||
const double newValue = value + jmax (interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0);
|
||||
|
||||
DragInProgress drag (*this);
|
||||
setValue (owner.snapValue (value + delta, notDragging), sendNotificationSync);
|
||||
DragInProgress drag (*this);
|
||||
setValue (owner.snapValue (newValue, notDragging), sendNotificationSync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1036,29 +1050,29 @@ public:
|
||||
const double pos = sliderBeingDragged == 2 ? getMaxValue()
|
||||
: (sliderBeingDragged == 1 ? getMinValue()
|
||||
: (double) currentValue.getValue());
|
||||
Point<int> mousePos;
|
||||
Point<float> mousePos;
|
||||
|
||||
if (isRotary())
|
||||
{
|
||||
mousePos = mi->getLastMouseDownPosition();
|
||||
|
||||
const int delta = roundToInt (pixelsForFullDragExtent * (owner.valueToProportionOfLength (valueOnMouseDown)
|
||||
- owner.valueToProportionOfLength (pos)));
|
||||
const float delta = (float) (pixelsForFullDragExtent * (owner.valueToProportionOfLength (valueOnMouseDown)
|
||||
- owner.valueToProportionOfLength (pos)));
|
||||
|
||||
if (style == RotaryHorizontalDrag) mousePos += Point<int> (-delta, 0);
|
||||
else if (style == RotaryVerticalDrag) mousePos += Point<int> (0, delta);
|
||||
else mousePos += Point<int> (delta / -2, delta / 2);
|
||||
if (style == RotaryHorizontalDrag) mousePos += Point<float> (-delta, 0.0f);
|
||||
else if (style == RotaryVerticalDrag) mousePos += Point<float> (0.0f, delta);
|
||||
else mousePos += Point<float> (delta / -2.0f, delta / 2.0f);
|
||||
|
||||
mousePos = owner.getScreenBounds().reduced (4).getConstrainedPoint (mousePos);
|
||||
mousePos = owner.getScreenBounds().reduced (4).toFloat().getConstrainedPoint (mousePos);
|
||||
mouseDragStartPos = mousePosWhenLastDragged = owner.getLocalPoint (nullptr, mousePos);
|
||||
valueOnMouseDown = valueWhenLastDragged;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int pixelPos = (int) getLinearSliderPos (pos);
|
||||
const float pixelPos = (float) getLinearSliderPos (pos);
|
||||
|
||||
mousePos = owner.localPointToGlobal (Point<int> (isHorizontal() ? pixelPos : (owner.getWidth() / 2),
|
||||
isVertical() ? pixelPos : (owner.getHeight() / 2)));
|
||||
mousePos = owner.localPointToGlobal (Point<float> (isHorizontal() ? pixelPos : (owner.getWidth() / 2.0f),
|
||||
isVertical() ? pixelPos : (owner.getHeight() / 2.0f)));
|
||||
}
|
||||
|
||||
mi->setScreenPosition (mousePos);
|
||||
@@ -1231,10 +1245,11 @@ public:
|
||||
double velocityModeSensitivity, velocityModeOffset, minMaxDiff;
|
||||
int velocityModeThreshold;
|
||||
float rotaryStart, rotaryEnd;
|
||||
Point<int> mouseDragStartPos, mousePosWhenLastDragged;
|
||||
Point<float> mouseDragStartPos, mousePosWhenLastDragged;
|
||||
int sliderRegionStart, sliderRegionSize;
|
||||
int sliderBeingDragged;
|
||||
int pixelsForFullDragExtent;
|
||||
Time lastMouseWheelTime;
|
||||
Rectangle<int> sliderRect;
|
||||
ScopedPointer<DragInProgress> currentDrag;
|
||||
|
||||
@@ -1272,6 +1287,7 @@ public:
|
||||
{
|
||||
setAlwaysOnTop (true);
|
||||
setAllowedPlacement (owner.getLookAndFeel().getSliderPopupPlacement (s));
|
||||
setLookAndFeel (&s.getLookAndFeel());
|
||||
}
|
||||
|
||||
void paintContent (Graphics& g, int w, int h)
|
||||
|
||||
@@ -623,7 +623,7 @@ void TableHeaderComponent::mouseDrag (const MouseEvent& e)
|
||||
minWidthOnRight += columns.getUnchecked (i)->minimumWidth;
|
||||
|
||||
const Rectangle<int> currentPos (getColumnPosition (getIndexOfColumnId (columnIdBeingResized, true)));
|
||||
w = jmax (ci->minimumWidth, jmin (w, getWidth() - minWidthOnRight - currentPos.getX()));
|
||||
w = jmax (ci->minimumWidth, jmin (w, lastDeliberateWidth - minWidthOnRight - currentPos.getX()));
|
||||
}
|
||||
|
||||
setColumnWidth (columnIdBeingResized, w);
|
||||
|
||||
@@ -26,7 +26,7 @@ class TableListBox::RowComp : public Component,
|
||||
public TooltipClient
|
||||
{
|
||||
public:
|
||||
RowComp (TableListBox& tlb) : owner (tlb), row (-1), isSelected (false)
|
||||
RowComp (TableListBox& tlb) noexcept : owner (tlb), row (-1), isSelected (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
if (TableListBoxModel* m = owner.getModel())
|
||||
return m->getCellTooltip (row, columnId);
|
||||
|
||||
return String::empty;
|
||||
return String();
|
||||
}
|
||||
|
||||
Component* findChildComponentForColumn (const int columnId) const
|
||||
@@ -275,7 +275,7 @@ void TableListBox::setHeader (TableHeaderComponent* newHeader)
|
||||
{
|
||||
jassert (newHeader != nullptr); // you need to supply a real header for a table!
|
||||
|
||||
Rectangle<int> newBounds (0, 0, 100, 28);
|
||||
Rectangle<int> newBounds (100, 28);
|
||||
if (header != nullptr)
|
||||
newBounds = header->getBounds();
|
||||
|
||||
@@ -287,7 +287,7 @@ void TableListBox::setHeader (TableHeaderComponent* newHeader)
|
||||
header->addListener (this);
|
||||
}
|
||||
|
||||
int TableListBox::getHeaderHeight() const
|
||||
int TableListBox::getHeaderHeight() const noexcept
|
||||
{
|
||||
return header->getHeight();
|
||||
}
|
||||
@@ -312,16 +312,11 @@ void TableListBox::autoSizeAllColumns()
|
||||
autoSizeColumn (header->getColumnIdOfIndex (i, true));
|
||||
}
|
||||
|
||||
void TableListBox::setAutoSizeMenuOptionShown (const bool shouldBeShown)
|
||||
void TableListBox::setAutoSizeMenuOptionShown (const bool shouldBeShown) noexcept
|
||||
{
|
||||
autoSizeOptionsShown = shouldBeShown;
|
||||
}
|
||||
|
||||
bool TableListBox::isAutoSizeMenuOptionShown() const
|
||||
{
|
||||
return autoSizeOptionsShown;
|
||||
}
|
||||
|
||||
Rectangle<int> TableListBox::getCellPosition (const int columnId, const int rowNumber,
|
||||
const bool relativeToComponentTopLeft) const
|
||||
{
|
||||
@@ -337,7 +332,7 @@ Rectangle<int> TableListBox::getCellPosition (const int columnId, const int rowN
|
||||
|
||||
Component* TableListBox::getCellComponent (int columnId, int rowNumber) const
|
||||
{
|
||||
if (RowComp* const rowComp = dynamic_cast <RowComp*> (getComponentForRowNumber (rowNumber)))
|
||||
if (RowComp* const rowComp = dynamic_cast<RowComp*> (getComponentForRowNumber (rowNumber)))
|
||||
return rowComp->findChildComponentForColumn (columnId);
|
||||
|
||||
return nullptr;
|
||||
@@ -370,12 +365,12 @@ void TableListBox::paintListBoxItem (int, Graphics&, int, int, bool)
|
||||
{
|
||||
}
|
||||
|
||||
Component* TableListBox::refreshComponentForRow (int rowNumber, bool isRowSelected_, Component* existingComponentToUpdate)
|
||||
Component* TableListBox::refreshComponentForRow (int rowNumber, bool rowSelected, Component* existingComponentToUpdate)
|
||||
{
|
||||
if (existingComponentToUpdate == nullptr)
|
||||
existingComponentToUpdate = new RowComp (*this);
|
||||
|
||||
static_cast <RowComp*> (existingComponentToUpdate)->update (rowNumber, isRowSelected_);
|
||||
static_cast<RowComp*> (existingComponentToUpdate)->update (rowNumber, rowSelected);
|
||||
|
||||
return existingComponentToUpdate;
|
||||
}
|
||||
@@ -398,10 +393,10 @@ void TableListBox::returnKeyPressed (int row)
|
||||
model->returnKeyPressed (row);
|
||||
}
|
||||
|
||||
void TableListBox::backgroundClicked()
|
||||
void TableListBox::backgroundClicked (const MouseEvent& e)
|
||||
{
|
||||
if (model != nullptr)
|
||||
model->backgroundClicked();
|
||||
model->backgroundClicked (e);
|
||||
}
|
||||
|
||||
void TableListBox::listWasScrolled()
|
||||
@@ -450,14 +445,14 @@ void TableListBox::updateColumnComponents() const
|
||||
const int firstRow = getRowContainingPosition (0, 0);
|
||||
|
||||
for (int i = firstRow + getNumRowsOnScreen() + 2; --i >= firstRow;)
|
||||
if (RowComp* const rowComp = dynamic_cast <RowComp*> (getComponentForRowNumber (i)))
|
||||
if (RowComp* const rowComp = dynamic_cast<RowComp*> (getComponentForRowNumber (i)))
|
||||
rowComp->resized();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void TableListBoxModel::cellClicked (int, int, const MouseEvent&) {}
|
||||
void TableListBoxModel::cellDoubleClicked (int, int, const MouseEvent&) {}
|
||||
void TableListBoxModel::backgroundClicked() {}
|
||||
void TableListBoxModel::backgroundClicked (const MouseEvent&) {}
|
||||
void TableListBoxModel::sortOrderChanged (int, const bool) {}
|
||||
int TableListBoxModel::getColumnAutoSizeWidth (int) { return 0; }
|
||||
void TableListBoxModel::selectedRowsChanged (int) {}
|
||||
@@ -465,7 +460,7 @@ void TableListBoxModel::deleteKeyPressed (int) {}
|
||||
void TableListBoxModel::returnKeyPressed (int) {}
|
||||
void TableListBoxModel::listWasScrolled() {}
|
||||
|
||||
String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/) { return String::empty; }
|
||||
String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/) { return String(); }
|
||||
var TableListBoxModel::getDragSourceDescription (const SparseSet<int>&) { return var(); }
|
||||
|
||||
Component* TableListBoxModel::refreshComponentForCell (int, int, bool, Component* existingComponentToUpdate)
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
The graphics context has its origin at the row's top-left, and your method
|
||||
should fill the area specified by the width and height parameters.
|
||||
*/
|
||||
virtual void paintRowBackground (Graphics& g,
|
||||
virtual void paintRowBackground (Graphics&,
|
||||
int rowNumber,
|
||||
int width, int height,
|
||||
bool rowIsSelected) = 0;
|
||||
@@ -66,8 +66,11 @@ public:
|
||||
|
||||
The graphics context's origin will already be set to the top-left of the cell,
|
||||
whose size is specified by (width, height).
|
||||
|
||||
Note that the rowNumber value may be greater than the number of rows in your
|
||||
list, so be careful that you don't assume it's less than getNumRows().
|
||||
*/
|
||||
virtual void paintCell (Graphics& g,
|
||||
virtual void paintCell (Graphics&,
|
||||
int rowNumber,
|
||||
int columnId,
|
||||
int width, int height,
|
||||
@@ -103,21 +106,21 @@ public:
|
||||
The mouse event's coordinates will be relative to the entire table row.
|
||||
@see cellDoubleClicked, backgroundClicked
|
||||
*/
|
||||
virtual void cellClicked (int rowNumber, int columnId, const MouseEvent& e);
|
||||
virtual void cellClicked (int rowNumber, int columnId, const MouseEvent&);
|
||||
|
||||
/** This callback is made when the user clicks on one of the cells in the table.
|
||||
|
||||
The mouse event's coordinates will be relative to the entire table row.
|
||||
@see cellClicked, backgroundClicked
|
||||
*/
|
||||
virtual void cellDoubleClicked (int rowNumber, int columnId, const MouseEvent& e);
|
||||
virtual void cellDoubleClicked (int rowNumber, int columnId, const MouseEvent&);
|
||||
|
||||
/** This can be overridden to react to the user double-clicking on a part of the list where
|
||||
there are no rows.
|
||||
|
||||
@see cellClicked
|
||||
*/
|
||||
virtual void backgroundClicked();
|
||||
virtual void backgroundClicked (const MouseEvent&);
|
||||
|
||||
//==============================================================================
|
||||
/** This callback is made when the table's sort order is changed.
|
||||
@@ -142,25 +145,21 @@ public:
|
||||
*/
|
||||
virtual int getColumnAutoSizeWidth (int columnId);
|
||||
|
||||
/** Returns a tooltip for a particular cell in the table.
|
||||
*/
|
||||
/** Returns a tooltip for a particular cell in the table. */
|
||||
virtual String getCellTooltip (int rowNumber, int columnId);
|
||||
|
||||
//==============================================================================
|
||||
/** Override this to be informed when rows are selected or deselected.
|
||||
|
||||
@see ListBox::selectedRowsChanged()
|
||||
*/
|
||||
virtual void selectedRowsChanged (int lastRowSelected);
|
||||
|
||||
/** Override this to be informed when the delete key is pressed.
|
||||
|
||||
@see ListBox::deleteKeyPressed()
|
||||
*/
|
||||
virtual void deleteKeyPressed (int lastRowSelected);
|
||||
|
||||
/** Override this to be informed when the return key is pressed.
|
||||
|
||||
@see ListBox::returnKeyPressed()
|
||||
*/
|
||||
virtual void returnKeyPressed (int lastRowSelected);
|
||||
@@ -182,6 +181,12 @@ public:
|
||||
@see getDragSourceCustomData, DragAndDropContainer::startDragging
|
||||
*/
|
||||
virtual var getDragSourceDescription (const SparseSet<int>& currentlySelectedRows);
|
||||
|
||||
private:
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// This method's signature has changed to take a MouseEvent parameter - please update your code!
|
||||
JUCE_DEPRECATED_WITH_BODY (virtual int backgroundClicked(), { return 0; })
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -204,29 +209,34 @@ public:
|
||||
/** Creates a TableListBox.
|
||||
|
||||
The model pointer passed-in can be null, in which case you can set it later
|
||||
with setModel().
|
||||
with setModel(). The TableListBox does not take ownership of the model - it's
|
||||
the caller's responsibility to manage its lifetime and make sure it
|
||||
doesn't get deleted while still being used.
|
||||
*/
|
||||
TableListBox (const String& componentName = String::empty,
|
||||
TableListBoxModel* model = 0);
|
||||
TableListBox (const String& componentName = String(),
|
||||
TableListBoxModel* model = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~TableListBox();
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the TableListBoxModel that is being used for this table.
|
||||
The TableListBox does not take ownership of the model - it's the caller's responsibility
|
||||
to manage its lifetime and make sure it doesn't get deleted while still being used.
|
||||
*/
|
||||
void setModel (TableListBoxModel* newModel);
|
||||
|
||||
/** Returns the model currently in use. */
|
||||
TableListBoxModel* getModel() const { return model; }
|
||||
TableListBoxModel* getModel() const noexcept { return model; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the header component being used in this table. */
|
||||
TableHeaderComponent& getHeader() const { return *header; }
|
||||
TableHeaderComponent& getHeader() const noexcept { return *header; }
|
||||
|
||||
/** Sets the header component to use for the table.
|
||||
The table will take ownership of the component that you pass in, and will delete it
|
||||
when it's no longer needed.
|
||||
The pointer passed in may not be null.
|
||||
*/
|
||||
void setHeader (TableHeaderComponent* newHeader);
|
||||
|
||||
@@ -238,7 +248,7 @@ public:
|
||||
/** Returns the height of the table header.
|
||||
@see setHeaderHeight
|
||||
*/
|
||||
int getHeaderHeight() const;
|
||||
int getHeaderHeight() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Resizes a column to fit its contents.
|
||||
@@ -254,15 +264,14 @@ public:
|
||||
void autoSizeAllColumns();
|
||||
|
||||
/** Enables or disables the auto size options on the popup menu.
|
||||
|
||||
By default, these are enabled.
|
||||
*/
|
||||
void setAutoSizeMenuOptionShown (bool shouldBeShown);
|
||||
void setAutoSizeMenuOptionShown (bool shouldBeShown) noexcept;
|
||||
|
||||
/** True if the auto-size options should be shown on the menu.
|
||||
@see setAutoSizeMenuOptionsShown
|
||||
@see setAutoSizeMenuOptionShown
|
||||
*/
|
||||
bool isAutoSizeMenuOptionShown() const;
|
||||
bool isAutoSizeMenuOptionShown() const noexcept { return autoSizeOptionsShown; }
|
||||
|
||||
/** Returns the position of one of the cells in the table.
|
||||
|
||||
@@ -303,7 +312,7 @@ public:
|
||||
/** @internal */
|
||||
void returnKeyPressed (int currentSelectedRow) override;
|
||||
/** @internal */
|
||||
void backgroundClicked() override;
|
||||
void backgroundClicked (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void listWasScrolled() override;
|
||||
/** @internal */
|
||||
|
||||
@@ -1931,7 +1931,7 @@ bool TextEditor::deleteBackwards (bool moveInWholeWordSteps)
|
||||
if (moveInWholeWordSteps)
|
||||
moveCaretTo (findWordBreakBefore (getCaretPosition()), true);
|
||||
else if (selection.isEmpty() && selection.getStart() > 0)
|
||||
selection.setStart (selection.getEnd() - 1);
|
||||
selection = Range<int> (selection.getEnd() - 1, selection.getEnd());
|
||||
|
||||
cut();
|
||||
return true;
|
||||
@@ -1940,7 +1940,7 @@ bool TextEditor::deleteBackwards (bool moveInWholeWordSteps)
|
||||
bool TextEditor::deleteForwards (bool /*moveInWholeWordSteps*/)
|
||||
{
|
||||
if (selection.isEmpty() && selection.getStart() < getTotalNumChars())
|
||||
selection.setEnd (selection.getStart() + 1);
|
||||
selection = Range<int> (selection.getStart(), selection.getStart() + 1);
|
||||
|
||||
cut();
|
||||
return true;
|
||||
@@ -2059,7 +2059,7 @@ void TextEditor::focusGained (FocusChangeType)
|
||||
|
||||
if (ComponentPeer* const peer = getPeer())
|
||||
if (! isReadOnly())
|
||||
peer->textInputRequired (peer->globalToLocal (getScreenPosition()));
|
||||
peer->textInputRequired (peer->globalToLocal (getScreenPosition()), *this);
|
||||
}
|
||||
|
||||
void TextEditor::focusLost (FocusChangeType)
|
||||
|
||||
@@ -568,6 +568,9 @@ public:
|
||||
*/
|
||||
void setInputFilter (InputFilter* newFilter, bool takeOwnership);
|
||||
|
||||
/** Returns the current InputFilter, as set by setInputFilter(). */
|
||||
InputFilter* getInputFilter() const noexcept { return inputFilter; }
|
||||
|
||||
/** Sets limits on the characters that can be entered.
|
||||
This is just a shortcut that passes an instance of the LengthAndCharacterRestriction
|
||||
class to setInputFilter().
|
||||
|
||||
@@ -591,8 +591,8 @@ void Toolbar::itemDragMove (const SourceDetails& dragSourceDetails)
|
||||
{
|
||||
const Rectangle<int> previousPos (animator.getComponentDestination (prev));
|
||||
|
||||
if (abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX())
|
||||
< abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight()))))
|
||||
if (std::abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()))
|
||||
< std::abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))
|
||||
{
|
||||
newIndex = getIndexOfChildComponent (prev);
|
||||
}
|
||||
@@ -602,8 +602,8 @@ void Toolbar::itemDragMove (const SourceDetails& dragSourceDetails)
|
||||
{
|
||||
const Rectangle<int> nextPos (animator.getComponentDestination (next));
|
||||
|
||||
if (abs (dragObjectLeft - (vertical ? current.getY() : current.getX())
|
||||
> abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight()))))
|
||||
if (std::abs (dragObjectLeft - (vertical ? current.getY() : current.getX()))
|
||||
> std::abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))
|
||||
{
|
||||
newIndex = getIndexOfChildComponent (next) + 1;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
selectBasedOnModifiers (item, e.mods);
|
||||
|
||||
if (e.x >= pos.getX())
|
||||
item->itemClicked (e.withNewPosition (e.getPosition() - pos.getPosition()));
|
||||
item->itemClicked (e.withNewPosition (e.position - pos.getPosition().toFloat()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
Rectangle<int> pos;
|
||||
if (TreeViewItem* const item = findItemAt (e.y, pos))
|
||||
if (e.x >= pos.getX() || ! owner.openCloseButtonsVisible)
|
||||
item->itemDoubleClicked (e.withNewPosition (e.getPosition() - pos.getPosition()));
|
||||
item->itemDoubleClicked (e.withNewPosition (e.position - pos.getPosition().toFloat()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1773,6 +1773,11 @@ TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const noexce
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static String escapeSlashesInTreeViewItemName (const String& s)
|
||||
{
|
||||
return s.replaceCharacter ('/', '\\');
|
||||
}
|
||||
|
||||
String TreeViewItem::getItemIdentifierString() const
|
||||
{
|
||||
String s;
|
||||
@@ -1780,12 +1785,12 @@ String TreeViewItem::getItemIdentifierString() const
|
||||
if (parentItem != nullptr)
|
||||
s = parentItem->getItemIdentifierString();
|
||||
|
||||
return s + "/" + getUniqueName().replaceCharacter ('/', '\\');
|
||||
return s + "/" + escapeSlashesInTreeViewItemName (getUniqueName());
|
||||
}
|
||||
|
||||
TreeViewItem* TreeViewItem::findItemFromIdentifierString (const String& identifierString)
|
||||
{
|
||||
const String thisId ("/" + getUniqueName());
|
||||
const String thisId ("/" + escapeSlashesInTreeViewItemName (getUniqueName()));
|
||||
|
||||
if (thisId == identifierString)
|
||||
return this;
|
||||
|
||||
@@ -744,7 +744,7 @@ public:
|
||||
void setIndentSize (int newIndentSize);
|
||||
|
||||
/** Searches the tree for an item with the specified identifier.
|
||||
The identifer string must have been created by calling TreeViewItem::getItemIdentifierString().
|
||||
The identifier string must have been created by calling TreeViewItem::getItemIdentifierString().
|
||||
If no such item exists, this will return false. If the item is found, all of its items
|
||||
will be automatically opened.
|
||||
*/
|
||||
|
||||
@@ -404,7 +404,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
|
||||
|
||||
for (int i = textBlocks.size(); --i >= 0;)
|
||||
{
|
||||
const AlertTextComp* const ac = static_cast <const AlertTextComp*> (textBlocks.getUnchecked(i));
|
||||
const AlertTextComp* const ac = static_cast<const AlertTextComp*> (textBlocks.getUnchecked(i));
|
||||
w = jmax (w, ac->getPreferredWidth());
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
|
||||
|
||||
for (int i = textBlocks.size(); --i >= 0;)
|
||||
{
|
||||
AlertTextComp* const ac = static_cast <AlertTextComp*> (textBlocks.getUnchecked(i));
|
||||
AlertTextComp* const ac = static_cast<AlertTextComp*> (textBlocks.getUnchecked(i));
|
||||
ac->updateLayout ((int) (w * 0.8f));
|
||||
h += ac->getHeight() + 10;
|
||||
}
|
||||
@@ -470,11 +470,11 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
|
||||
Component* const c = allComps.getUnchecked(i);
|
||||
h = 22;
|
||||
|
||||
const int comboIndex = comboBoxes.indexOf (dynamic_cast <ComboBox*> (c));
|
||||
const int comboIndex = comboBoxes.indexOf (dynamic_cast<ComboBox*> (c));
|
||||
if (comboIndex >= 0 && comboBoxNames [comboIndex].isNotEmpty())
|
||||
y += labelHeight;
|
||||
|
||||
const int tbIndex = textBoxes.indexOf (dynamic_cast <TextEditor*> (c));
|
||||
const int tbIndex = textBoxes.indexOf (dynamic_cast<TextEditor*> (c));
|
||||
if (tbIndex >= 0 && textboxNames[tbIndex].isNotEmpty())
|
||||
y += labelHeight;
|
||||
|
||||
@@ -536,7 +536,8 @@ bool AlertWindow::keyPressed (const KeyPress& key)
|
||||
exitModalState (0);
|
||||
return true;
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1)
|
||||
|
||||
if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1)
|
||||
{
|
||||
buttons.getUnchecked(0)->triggerClick();
|
||||
return true;
|
||||
@@ -592,8 +593,8 @@ private:
|
||||
LookAndFeel& lf = associatedComponent != nullptr ? associatedComponent->getLookAndFeel()
|
||||
: LookAndFeel::getDefaultLookAndFeel();
|
||||
|
||||
ScopedPointer <Component> alertBox (lf.createAlertWindow (title, message, button1, button2, button3,
|
||||
iconType, numButtons, associatedComponent));
|
||||
ScopedPointer<Component> alertBox (lf.createAlertWindow (title, message, button1, button2, button3,
|
||||
iconType, numButtons, associatedComponent));
|
||||
|
||||
jassert (alertBox != nullptr); // you have to return one of these!
|
||||
|
||||
@@ -614,7 +615,7 @@ private:
|
||||
|
||||
static void* showCallback (void* userData)
|
||||
{
|
||||
static_cast <AlertWindowInfo*> (userData)->show();
|
||||
static_cast<AlertWindowInfo*> (userData)->show();
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
CallOutBox::CallOutBox (Component& c, const Rectangle<int>& area, Component* const parent)
|
||||
: arrowSize (16.0f), content (c)
|
||||
: arrowSize (16.0f), content (c), dismissalMouseClicksAreAlwaysConsumed (false)
|
||||
{
|
||||
addAndMakeVisible (content);
|
||||
|
||||
@@ -91,7 +91,7 @@ void CallOutBox::setArrowSize (const float newSize)
|
||||
|
||||
int CallOutBox::getBorderSize() const noexcept
|
||||
{
|
||||
return jmax (20, (int) arrowSize);
|
||||
return jmax (getLookAndFeel().getCallOutBoxBorderSize (*this), (int) arrowSize);
|
||||
}
|
||||
|
||||
void CallOutBox::paint (Graphics& g)
|
||||
@@ -123,9 +123,8 @@ bool CallOutBox::hitTest (int x, int y)
|
||||
|
||||
void CallOutBox::inputAttemptWhenModal()
|
||||
{
|
||||
const Point<int> mousePos (getMouseXYRelative() + getBounds().getPosition());
|
||||
|
||||
if (targetArea.contains (mousePos))
|
||||
if (dismissalMouseClicksAreAlwaysConsumed
|
||||
|| targetArea.contains (getMouseXYRelative() + getBounds().getPosition()))
|
||||
{
|
||||
// if you click on the area that originally popped-up the callout, you expect it
|
||||
// to get rid of the box, but deleting the box here allows the click to pass through and
|
||||
@@ -139,6 +138,11 @@ void CallOutBox::inputAttemptWhenModal()
|
||||
}
|
||||
}
|
||||
|
||||
void CallOutBox::setDismissalMouseClicksAreAlwaysConsumed (bool b) noexcept
|
||||
{
|
||||
dismissalMouseClicksAreAlwaysConsumed = b;
|
||||
}
|
||||
|
||||
enum { callOutBoxDismissCommandId = 0x4f83a04b };
|
||||
|
||||
void CallOutBox::handleCommandMessage (int commandId)
|
||||
|
||||
@@ -123,6 +123,16 @@ public:
|
||||
*/
|
||||
void dismiss();
|
||||
|
||||
/** Determines whether the mouse events for clicks outside the calloutbox are
|
||||
consumed, or allowed to arrive at the other component that they were aimed at.
|
||||
|
||||
By default this is false, so that when you click on something outside the calloutbox,
|
||||
that event will also be sent to the component that was clicked on. If you set it to
|
||||
true, then the first click will always just dismiss the box and not be sent to
|
||||
anything else.
|
||||
*/
|
||||
void setDismissalMouseClicksAreAlwaysConsumed (bool shouldAlwaysBeConsumed) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** This abstract base class is implemented by LookAndFeel classes. */
|
||||
struct JUCE_API LookAndFeelMethods
|
||||
@@ -130,6 +140,7 @@ public:
|
||||
virtual ~LookAndFeelMethods() {}
|
||||
|
||||
virtual void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path&, Image& cachedImage) = 0;
|
||||
virtual int getCallOutBoxBorderSize (const CallOutBox&) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
@@ -160,6 +171,7 @@ private:
|
||||
Point<float> targetPoint;
|
||||
Rectangle<int> availableArea, targetArea;
|
||||
Image background;
|
||||
bool dismissalMouseClicksAreAlwaysConsumed;
|
||||
|
||||
void refreshPath();
|
||||
|
||||
|
||||
@@ -85,25 +85,22 @@ bool ComponentPeer::isKioskMode() const
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ComponentPeer::handleMouseEvent (const int touchIndex, const Point<int> positionWithinPeer,
|
||||
const ModifierKeys newMods, const int64 time)
|
||||
void ComponentPeer::handleMouseEvent (int touchIndex, Point<float> pos, ModifierKeys newMods, int64 time)
|
||||
{
|
||||
if (MouseInputSource* mouse = Desktop::getInstance().mouseSources->getOrCreateMouseInputSource (touchIndex))
|
||||
MouseInputSource (*mouse).handleEvent (*this, positionWithinPeer, time, newMods);
|
||||
MouseInputSource (*mouse).handleEvent (*this, pos, time, newMods);
|
||||
}
|
||||
|
||||
void ComponentPeer::handleMouseWheel (const int touchIndex, const Point<int> positionWithinPeer,
|
||||
const int64 time, const MouseWheelDetails& wheel)
|
||||
void ComponentPeer::handleMouseWheel (int touchIndex, Point<float> pos, int64 time, const MouseWheelDetails& wheel)
|
||||
{
|
||||
if (MouseInputSource* mouse = Desktop::getInstance().mouseSources->getOrCreateMouseInputSource (touchIndex))
|
||||
MouseInputSource (*mouse).handleWheel (*this, positionWithinPeer, time, wheel);
|
||||
MouseInputSource (*mouse).handleWheel (*this, pos, time, wheel);
|
||||
}
|
||||
|
||||
void ComponentPeer::handleMagnifyGesture (const int touchIndex, const Point<int> positionWithinPeer,
|
||||
const int64 time, const float scaleFactor)
|
||||
void ComponentPeer::handleMagnifyGesture (int touchIndex, Point<float> pos, int64 time, float scaleFactor)
|
||||
{
|
||||
if (MouseInputSource* mouse = Desktop::getInstance().mouseSources->getOrCreateMouseInputSource (touchIndex))
|
||||
MouseInputSource (*mouse).handleMagnifyGesture (*this, positionWithinPeer, time, scaleFactor);
|
||||
MouseInputSource (*mouse).handleMagnifyGesture (*this, pos, time, scaleFactor);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -402,6 +399,9 @@ const Rectangle<int>& ComponentPeer::getNonFullScreenBounds() const noexcept
|
||||
return lastNonFullscreenBounds;
|
||||
}
|
||||
|
||||
Point<int> ComponentPeer::localToGlobal (Point<int> p) { return localToGlobal (p.toFloat()).roundToInt(); }
|
||||
Point<int> ComponentPeer::globalToLocal (Point<int> p) { return globalToLocal (p.toFloat()).roundToInt(); }
|
||||
|
||||
Rectangle<int> ComponentPeer::localToGlobal (const Rectangle<int>& relativePosition)
|
||||
{
|
||||
return relativePosition.withPosition (localToGlobal (relativePosition.getPosition()));
|
||||
|
||||
@@ -148,14 +148,20 @@ public:
|
||||
virtual Rectangle<int> getBounds() const = 0;
|
||||
|
||||
/** Converts a position relative to the top-left of this component to screen coordinates. */
|
||||
virtual Point<int> localToGlobal (Point<int> relativePosition) = 0;
|
||||
virtual Point<float> localToGlobal (Point<float> relativePosition) = 0;
|
||||
|
||||
/** Converts a screen coordinate to a position relative to the top-left of this component. */
|
||||
virtual Point<float> globalToLocal (Point<float> screenPosition) = 0;
|
||||
|
||||
/** Converts a position relative to the top-left of this component to screen coordinates. */
|
||||
Point<int> localToGlobal (Point<int> relativePosition);
|
||||
|
||||
/** Converts a screen coordinate to a position relative to the top-left of this component. */
|
||||
Point<int> globalToLocal (Point<int> screenPosition);
|
||||
|
||||
/** Converts a rectangle relative to the top-left of this component to screen coordinates. */
|
||||
virtual Rectangle<int> localToGlobal (const Rectangle<int>& relativePosition);
|
||||
|
||||
/** Converts a screen coordinate to a position relative to the top-left of this component. */
|
||||
virtual Point<int> globalToLocal (Point<int> screenPosition) = 0;
|
||||
|
||||
/** Converts a screen area to a position relative to the top-left of this component. */
|
||||
virtual Rectangle<int> globalToLocal (const Rectangle<int>& screenPosition);
|
||||
|
||||
@@ -276,7 +282,7 @@ public:
|
||||
This may cause things like a virtual on-screen keyboard to appear, depending
|
||||
on the OS.
|
||||
*/
|
||||
virtual void textInputRequired (const Point<int>& position) = 0;
|
||||
virtual void textInputRequired (Point<int> position, TextInputTarget&) = 0;
|
||||
|
||||
/** If there's some kind of OS input-method in progress, this should dismiss it. */
|
||||
virtual void dismissPendingTextInput();
|
||||
@@ -300,9 +306,9 @@ public:
|
||||
virtual void setAlpha (float newAlpha) = 0;
|
||||
|
||||
//==============================================================================
|
||||
void handleMouseEvent (int touchIndex, const Point<int> positionWithinPeer, const ModifierKeys newMods, int64 time);
|
||||
void handleMouseWheel (int touchIndex, const Point<int> positionWithinPeer, int64 time, const MouseWheelDetails&);
|
||||
void handleMagnifyGesture (int touchIndex, const Point<int> positionWithinPeer, int64 time, float scaleFactor);
|
||||
void handleMouseEvent (int touchIndex, Point<float> positionWithinPeer, ModifierKeys newMods, int64 time);
|
||||
void handleMouseWheel (int touchIndex, Point<float> positionWithinPeer, int64 time, const MouseWheelDetails&);
|
||||
void handleMagnifyGesture (int touchIndex, Point<float> positionWithinPeer, int64 time, float scaleFactor);
|
||||
|
||||
void handleUserClosingWindow();
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
initialise its fields with the appropriate details, and then call its launchAsync()
|
||||
method to launch the dialog.
|
||||
*/
|
||||
struct LaunchOptions
|
||||
struct JUCE_API LaunchOptions
|
||||
{
|
||||
LaunchOptions() noexcept;
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ void TooltipWindow::timerCallback()
|
||||
mouseClicks = clickCount;
|
||||
mouseWheelMoves = wheelCount;
|
||||
|
||||
const Point<int> mousePos (mouseSource.getScreenPosition());
|
||||
const Point<float> mousePos (mouseSource.getScreenPosition());
|
||||
const bool mouseMovedQuickly = mousePos.getDistanceFrom (lastMousePos) > 12;
|
||||
lastMousePos = mousePos;
|
||||
|
||||
@@ -159,7 +159,7 @@ void TooltipWindow::timerCallback()
|
||||
}
|
||||
else if (tipChanged)
|
||||
{
|
||||
displayTip (mousePos, newTip);
|
||||
displayTip (mousePos.roundToInt(), newTip);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -170,7 +170,7 @@ void TooltipWindow::timerCallback()
|
||||
&& newTip != tipShowing
|
||||
&& now > lastCompChangeTime + (unsigned int) millisecondsBeforeTipAppears)
|
||||
{
|
||||
displayTip (mousePos, newTip);
|
||||
displayTip (mousePos.roundToInt(), newTip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
private:
|
||||
//==============================================================================
|
||||
int millisecondsBeforeTipAppears;
|
||||
Point<int> lastMousePos;
|
||||
Point<float> lastMousePos;
|
||||
int mouseClicks, mouseWheelMoves;
|
||||
unsigned int lastCompChangeTime, lastHideTime;
|
||||
Component* lastComponentUnderMouse;
|
||||
|
||||
@@ -27,7 +27,6 @@ class TopLevelWindowManager : private Timer,
|
||||
private DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
TopLevelWindowManager() : currentActive (nullptr)
|
||||
{
|
||||
}
|
||||
@@ -48,33 +47,15 @@ public:
|
||||
{
|
||||
startTimer (jmin (1731, getTimerInterval() * 2));
|
||||
|
||||
TopLevelWindow* active = nullptr;
|
||||
TopLevelWindow* newActive = findCurrentlyActiveWindow();
|
||||
|
||||
if (Process::isForegroundProcess())
|
||||
if (newActive != currentActive)
|
||||
{
|
||||
active = currentActive;
|
||||
|
||||
Component* const c = Component::getCurrentlyFocusedComponent();
|
||||
TopLevelWindow* tlw = dynamic_cast <TopLevelWindow*> (c);
|
||||
|
||||
if (tlw == nullptr && c != nullptr)
|
||||
tlw = c->findParentComponentOfClass<TopLevelWindow>();
|
||||
|
||||
if (tlw != nullptr)
|
||||
active = tlw;
|
||||
}
|
||||
|
||||
if (active != currentActive)
|
||||
{
|
||||
currentActive = active;
|
||||
currentActive = newActive;
|
||||
|
||||
for (int i = windows.size(); --i >= 0;)
|
||||
{
|
||||
TopLevelWindow* const tlw = windows.getUnchecked (i);
|
||||
tlw->setWindowActive (isWindowActive (tlw));
|
||||
|
||||
i = jmin (i, windows.size() - 1);
|
||||
}
|
||||
if (TopLevelWindow* tlw = windows[i])
|
||||
tlw->setWindowActive (isWindowActive (tlw));
|
||||
|
||||
Desktop::getInstance().triggerFocusCallback();
|
||||
}
|
||||
@@ -101,7 +82,7 @@ public:
|
||||
deleteInstance();
|
||||
}
|
||||
|
||||
Array <TopLevelWindow*> windows;
|
||||
Array<TopLevelWindow*> windows;
|
||||
|
||||
private:
|
||||
TopLevelWindow* currentActive;
|
||||
@@ -119,6 +100,26 @@ private:
|
||||
&& tlw->isShowing();
|
||||
}
|
||||
|
||||
TopLevelWindow* findCurrentlyActiveWindow() const
|
||||
{
|
||||
if (Process::isForegroundProcess())
|
||||
{
|
||||
Component* const focusedComp = Component::getCurrentlyFocusedComponent();
|
||||
TopLevelWindow* w = dynamic_cast<TopLevelWindow*> (focusedComp);
|
||||
|
||||
if (w == nullptr && focusedComp != nullptr)
|
||||
w = focusedComp->findParentComponentOfClass<TopLevelWindow>();
|
||||
|
||||
if (w == nullptr)
|
||||
w = currentActive;
|
||||
|
||||
if (w != nullptr && w->isShowing())
|
||||
return w;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (TopLevelWindowManager)
|
||||
};
|
||||
|
||||
@@ -187,12 +188,11 @@ bool TopLevelWindow::isUsingNativeTitleBar() const noexcept
|
||||
|
||||
void TopLevelWindow::visibilityChanged()
|
||||
{
|
||||
if (isShowing()
|
||||
&& (getPeer()->getStyleFlags() & (ComponentPeer::windowIsTemporary
|
||||
| ComponentPeer::windowIgnoresKeyPresses)) == 0)
|
||||
{
|
||||
toFront (true);
|
||||
}
|
||||
if (isShowing())
|
||||
if (ComponentPeer* p = getPeer())
|
||||
if ((p->getStyleFlags() & (ComponentPeer::windowIsTemporary
|
||||
| ComponentPeer::windowIgnoresKeyPresses)) == 0)
|
||||
toFront (true);
|
||||
}
|
||||
|
||||
void TopLevelWindow::parentHierarchyChanged()
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
virtual void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = nullptr) override;
|
||||
void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = nullptr) override;
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
@@ -155,7 +155,7 @@ private:
|
||||
bool useDropShadow, useNativeTitleBar, isCurrentlyActive;
|
||||
ScopedPointer<DropShadower> shadower;
|
||||
|
||||
void setWindowActive (bool isNowActive);
|
||||
void setWindowActive (bool);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TopLevelWindow)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user