- updated
git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@117 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -102,7 +102,7 @@ public:
|
||||
|
||||
private:
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// Note that this method has been removed - instead, see LookAndFeel::getTextButtonWidthToFitText()
|
||||
// Note that this method has been removed - instead, see LookAndFeel::getTextButtonFont()
|
||||
virtual int getFont() { return 0; }
|
||||
#endif
|
||||
|
||||
|
||||
@@ -784,6 +784,7 @@ public:
|
||||
validArea.clear();
|
||||
}
|
||||
|
||||
if (! validArea.containsRectangle (compBounds))
|
||||
{
|
||||
Graphics imG (image);
|
||||
LowLevelGraphicsContext& lg = imG.getInternalContext();
|
||||
@@ -791,18 +792,15 @@ public:
|
||||
for (const Rectangle<int>* i = validArea.begin(), * const e = validArea.end(); i != e; ++i)
|
||||
lg.excludeClipRectangle (*i);
|
||||
|
||||
if (! lg.isClipEmpty())
|
||||
if (! owner.isOpaque())
|
||||
{
|
||||
if (! owner.isOpaque())
|
||||
{
|
||||
lg.setFill (Colours::transparentBlack);
|
||||
lg.fillRect (imageBounds, true);
|
||||
lg.setFill (Colours::black);
|
||||
}
|
||||
|
||||
lg.addTransform (AffineTransform::scale (scale));
|
||||
owner.paintEntireComponent (imG, true);
|
||||
lg.setFill (Colours::transparentBlack);
|
||||
lg.fillRect (imageBounds, true);
|
||||
lg.setFill (Colours::black);
|
||||
}
|
||||
|
||||
lg.addTransform (AffineTransform::scale (scale));
|
||||
owner.paintEntireComponent (imG, true);
|
||||
}
|
||||
|
||||
validArea = imageBounds;
|
||||
|
||||
@@ -89,7 +89,7 @@ ModalComponentManager::~ModalComponentManager()
|
||||
clearSingletonInstance();
|
||||
}
|
||||
|
||||
juce_ImplementSingleton_SingleThreaded (ModalComponentManager);
|
||||
juce_ImplementSingleton_SingleThreaded (ModalComponentManager)
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (ModalComponentManager);
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (ModalComponentManager)
|
||||
|
||||
protected:
|
||||
/** Creates a ModalComponentManager.
|
||||
|
||||
@@ -37,6 +37,7 @@ DrawableImage::DrawableImage (const DrawableImage& other)
|
||||
overlayColour (other.overlayColour),
|
||||
bounds (other.bounds)
|
||||
{
|
||||
setBounds (other.getBounds());
|
||||
}
|
||||
|
||||
DrawableImage::~DrawableImage()
|
||||
|
||||
@@ -1157,9 +1157,9 @@ private:
|
||||
|
||||
tokens.removeEmptyStrings (true);
|
||||
|
||||
float numbers [6];
|
||||
float numbers[6];
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
for (int i = 0; i < numElementsInArray (numbers); ++i)
|
||||
numbers[i] = tokens[i].getFloatValue();
|
||||
|
||||
AffineTransform trans;
|
||||
@@ -1171,33 +1171,23 @@ private:
|
||||
}
|
||||
else if (t.startsWithIgnoreCase ("translate"))
|
||||
{
|
||||
jassert (tokens.size() == 2);
|
||||
trans = AffineTransform::translation (numbers[0], numbers[1]);
|
||||
}
|
||||
else if (t.startsWithIgnoreCase ("scale"))
|
||||
{
|
||||
if (tokens.size() == 1)
|
||||
trans = AffineTransform::scale (numbers[0]);
|
||||
else
|
||||
trans = AffineTransform::scale (numbers[0], numbers[1]);
|
||||
trans = AffineTransform::scale (numbers[0], numbers[tokens.size() > 1 ? 1 : 0]);
|
||||
}
|
||||
else if (t.startsWithIgnoreCase ("rotate"))
|
||||
{
|
||||
if (tokens.size() != 3)
|
||||
trans = AffineTransform::rotation (numbers[0] / (180.0f / float_Pi));
|
||||
else
|
||||
trans = AffineTransform::rotation (numbers[0] / (180.0f / float_Pi),
|
||||
numbers[1], numbers[2]);
|
||||
trans = AffineTransform::rotation (numbers[0] / (180.0f / float_Pi), numbers[1], numbers[2]);
|
||||
}
|
||||
else if (t.startsWithIgnoreCase ("skewX"))
|
||||
{
|
||||
trans = AffineTransform (1.0f, std::tan (numbers[0] * (float_Pi / 180.0f)), 0.0f,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
trans = AffineTransform::shear (std::tan (numbers[0] * (float_Pi / 180.0f)), 0.0f);
|
||||
}
|
||||
else if (t.startsWithIgnoreCase ("skewY"))
|
||||
{
|
||||
trans = AffineTransform (1.0f, 0.0f, 0.0f,
|
||||
std::tan (numbers[0] * (float_Pi / 180.0f)), 1.0f, 0.0f);
|
||||
trans = AffineTransform::shear (0.0f, std::tan (numbers[0] * (float_Pi / 180.0f)));
|
||||
}
|
||||
|
||||
result = trans.followedBy (result);
|
||||
@@ -1218,8 +1208,8 @@ private:
|
||||
const double midX = (x1 - x2) * 0.5;
|
||||
const double midY = (y1 - y2) * 0.5;
|
||||
|
||||
const double cosAngle = cos (angle);
|
||||
const double sinAngle = sin (angle);
|
||||
const double cosAngle = std::cos (angle);
|
||||
const double sinAngle = std::sin (angle);
|
||||
const double xp = cosAngle * midX + sinAngle * midY;
|
||||
const double yp = cosAngle * midY - sinAngle * midX;
|
||||
const double xp2 = xp * xp;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "juce_gui_basics",
|
||||
"name": "JUCE GUI core classes",
|
||||
"version": "3.0.8",
|
||||
"version": "3.1.1",
|
||||
"description": "Basic user-interface components and related classes.",
|
||||
"website": "http://www.juce.com/juce",
|
||||
"license": "GPL/Commercial",
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
*/
|
||||
void endDrag()
|
||||
{
|
||||
startTimer (1000 / 60);
|
||||
startTimerHz (60);
|
||||
}
|
||||
|
||||
/** Called outside of a drag operation to cause a nudge in the specified direction.
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
*/
|
||||
void nudge (double deltaFromCurrentPosition)
|
||||
{
|
||||
startTimer (100);
|
||||
startTimerHz (10);
|
||||
moveTo (position + deltaFromCurrentPosition);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ private:
|
||||
if (behaviour.isStopped (newPos))
|
||||
stopTimer();
|
||||
else
|
||||
startTimer (1000 / 60);
|
||||
startTimerHz (60);
|
||||
|
||||
setPositionAndSendChange (newPos);
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@
|
||||
class ComponentAnimator::AnimationTask
|
||||
{
|
||||
public:
|
||||
AnimationTask (Component* const comp) noexcept : component (comp)
|
||||
{
|
||||
}
|
||||
AnimationTask (Component* c) noexcept : component (c) {}
|
||||
|
||||
void reset (const Rectangle<int>& finalBounds,
|
||||
float finalAlpha,
|
||||
@@ -65,8 +63,8 @@ public:
|
||||
|
||||
bool useTimeslice (const int elapsed)
|
||||
{
|
||||
if (Component* const c = proxy != nullptr ? static_cast <Component*> (proxy)
|
||||
: static_cast <Component*> (component))
|
||||
if (Component* const c = proxy != nullptr ? static_cast<Component*> (proxy)
|
||||
: static_cast<Component*> (component))
|
||||
{
|
||||
msElapsed += elapsed;
|
||||
double newProgress = msElapsed / (double) msTotal;
|
||||
@@ -149,7 +147,10 @@ public:
|
||||
else
|
||||
jassertfalse; // seem to be trying to animate a component that's not visible..
|
||||
|
||||
image = c.createComponentSnapshot (c.getLocalBounds(), false, getDesktopScaleFactor());
|
||||
const float scale = (float) Desktop::getInstance().getDisplays()
|
||||
.getDisplayContaining (getScreenBounds().getCentre()).scale;
|
||||
|
||||
image = c.createComponentSnapshot (c.getLocalBounds(), false, scale);
|
||||
|
||||
setVisible (true);
|
||||
toBehind (&c);
|
||||
@@ -189,14 +190,8 @@ private:
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
ComponentAnimator::ComponentAnimator()
|
||||
: lastTime (0)
|
||||
{
|
||||
}
|
||||
|
||||
ComponentAnimator::~ComponentAnimator()
|
||||
{
|
||||
}
|
||||
ComponentAnimator::ComponentAnimator() : lastTime (0) {}
|
||||
ComponentAnimator::~ComponentAnimator() {}
|
||||
|
||||
//==============================================================================
|
||||
ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* const component) const noexcept
|
||||
@@ -236,7 +231,7 @@ void ComponentAnimator::animateComponent (Component* const component,
|
||||
if (! isTimerRunning())
|
||||
{
|
||||
lastTime = Time::getMillisecondCounter();
|
||||
startTimer (1000 / 50);
|
||||
startTimerHz (50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ Viewport::Viewport (const String& name)
|
||||
Viewport::~Viewport()
|
||||
{
|
||||
deleteContentComp();
|
||||
mouseWheelTimer = nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -357,6 +358,30 @@ static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexce
|
||||
: jmax (distance, 1.0f));
|
||||
}
|
||||
|
||||
// This puts a temporary component overlay over the content component, to prevent
|
||||
// wheel events from reaching components inside it, so that while spinning a wheel
|
||||
// with momentum, it won't accidentally scroll any subcomponents of the viewport.
|
||||
struct Viewport::MouseWheelTimer : public Timer
|
||||
{
|
||||
MouseWheelTimer (Viewport& v) : viewport (v)
|
||||
{
|
||||
viewport.contentHolder.addAndMakeVisible (dummyOverlay);
|
||||
dummyOverlay.setAlwaysOnTop (true);
|
||||
dummyOverlay.setPaintingIsUnclipped (true);
|
||||
dummyOverlay.setBounds (viewport.contentHolder.getLocalBounds());
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
viewport.mouseWheelTimer = nullptr;
|
||||
}
|
||||
|
||||
Component dummyOverlay;
|
||||
Viewport& viewport;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MouseWheelTimer)
|
||||
};
|
||||
|
||||
bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel)
|
||||
{
|
||||
if (! (e.mods.isAltDown() || e.mods.isCtrlDown() || e.mods.isCommandDown()))
|
||||
@@ -387,6 +412,11 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelD
|
||||
|
||||
if (pos != getViewPosition())
|
||||
{
|
||||
if (mouseWheelTimer == nullptr)
|
||||
mouseWheelTimer = new MouseWheelTimer (*this);
|
||||
|
||||
mouseWheelTimer->startTimer (300);
|
||||
|
||||
setViewPosition (pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -267,6 +267,9 @@ private:
|
||||
bool allowScrollingWithoutScrollbarV, allowScrollingWithoutScrollbarH;
|
||||
Component contentHolder;
|
||||
ScrollBar verticalScrollBar, horizontalScrollBar;
|
||||
struct MouseWheelTimer;
|
||||
ScopedPointer<Timer> mouseWheelTimer;
|
||||
|
||||
Point<int> viewportPosToCompPos (Point<int>) const;
|
||||
|
||||
void updateVisibleArea();
|
||||
|
||||
@@ -1397,7 +1397,6 @@ void LookAndFeel_V2::drawRotarySlider (Graphics& g, int x, int y, int width, int
|
||||
g.fillPath (filledArc);
|
||||
}
|
||||
|
||||
if (thickness > 0)
|
||||
{
|
||||
const float innerRadius = radius * 0.2f;
|
||||
Path p;
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
|
||||
To be informed when items are selected/deselected, register a ChangeListener with
|
||||
this object.
|
||||
|
||||
@see SelectableObject
|
||||
*/
|
||||
template <class SelectableItemType>
|
||||
class SelectedItemSet : public ChangeBroadcaster
|
||||
|
||||
@@ -111,7 +111,8 @@ public:
|
||||
// NB: must not put this in the initialiser list, as it invokes a callback,
|
||||
// which will fail if the peer is only half-constructed.
|
||||
view = GlobalRef (android.activity.callObjectMethod (JuceAppActivity.createNewView,
|
||||
component.isOpaque(), (jlong) this));
|
||||
(jboolean) component.isOpaque(),
|
||||
(jlong) this));
|
||||
|
||||
if (isFocused())
|
||||
handleFocusGain();
|
||||
@@ -584,7 +585,7 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void*)
|
||||
|
||||
jobject createOpenGLView (ComponentPeer* peer)
|
||||
{
|
||||
jobject parentView = static_cast <jobject> (peer->getNativeHandle());
|
||||
jobject parentView = static_cast<jobject> (peer->getNativeHandle());
|
||||
return getEnv()->CallObjectMethod (parentView, ComponentPeerView.createGLView);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,10 +172,10 @@ void FileChooser::showPlatformDialog (Array<File>& results,
|
||||
[panel setDirectoryURL: [NSURL fileURLWithPath: juceStringToNS (directory)]];
|
||||
[panel setNameFieldStringValue: juceStringToNS (filename)];
|
||||
|
||||
if ([panel runModal] == NSOKButton)
|
||||
if ([panel runModal] == 1 /*NSModalResponseOK*/)
|
||||
#else
|
||||
if ([panel runModalForDirectory: juceStringToNS (directory)
|
||||
file: juceStringToNS (filename)] == NSOKButton)
|
||||
file: juceStringToNS (filename)] == 1 /*NSModalResponseOK*/)
|
||||
#endif
|
||||
{
|
||||
if (isSaveDialogue)
|
||||
|
||||
@@ -411,9 +411,9 @@ public:
|
||||
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 windowPoint = [view convertPoint: NSMakePoint (localPos.x, viewFrame.size.height - localPos.y) toView: nil];
|
||||
const NSPoint screenPoint = NSMakePoint (windowFrame.origin.x + windowPoint.x,
|
||||
windowFrame.origin.y + windowFrame.size.height - windowPoint.y);
|
||||
windowFrame.origin.y + windowPoint.y);
|
||||
|
||||
if (! isWindowAtPoint (viewWindow, screenPoint))
|
||||
return false;
|
||||
@@ -574,7 +574,15 @@ public:
|
||||
{
|
||||
currentModifiers = currentModifiers.withoutMouseButtons();
|
||||
|
||||
if (isWindowAtPoint ([ev window], [[ev window] convertBaseToScreen: [ev locationInWindow]]))
|
||||
NSPoint windowPos = [ev locationInWindow];
|
||||
|
||||
#if defined (MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
|
||||
NSPoint screenPos = [[ev window] convertRectToScreen: NSMakeRect (windowPos.x, windowPos.y, 1.0f, 1.0f)].origin;
|
||||
#else
|
||||
NSPoint screenPos = [[ev window] convertBaseToScreen: windowPos];
|
||||
#endif
|
||||
|
||||
if (isWindowAtPoint ([ev window], screenPos))
|
||||
sendMouseEvent (ev);
|
||||
else
|
||||
// moved into another window which overlaps this one, so trigger an exit
|
||||
@@ -1786,7 +1794,9 @@ private:
|
||||
|
||||
static void windowDidExitFullScreen (id, SEL, NSNotification*)
|
||||
{
|
||||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
[NSApp setPresentationOptions: NSApplicationPresentationDefault];
|
||||
#endif
|
||||
}
|
||||
|
||||
static void zoom (id self, SEL, id sender)
|
||||
|
||||
@@ -164,37 +164,29 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi
|
||||
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
NSView* view = (NSView*) sourceComp->getWindowHandle();
|
||||
if (NSView* view = (NSView*) sourceComp->getWindowHandle())
|
||||
{
|
||||
if (NSEvent* event = [[view window] currentEvent])
|
||||
{
|
||||
NSPoint eventPos = [event locationInWindow];
|
||||
NSRect dragRect = [view convertRect: NSMakeRect (eventPos.x - 16.0f, eventPos.y - 16.0f, 32.0f, 32.0f)
|
||||
fromView: nil];
|
||||
|
||||
if (view == nil)
|
||||
return false;
|
||||
for (int i = 0; i < files.size(); ++i)
|
||||
{
|
||||
if (! [view dragFile: juceStringToNS (files[i])
|
||||
fromRect: dragRect
|
||||
slideBack: YES
|
||||
event: event])
|
||||
return false;
|
||||
}
|
||||
|
||||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName: NSDragPboard];
|
||||
[pboard declareTypes: [NSArray arrayWithObject: NSFilenamesPboardType]
|
||||
owner: nil];
|
||||
|
||||
NSMutableArray* filesArray = [NSMutableArray arrayWithCapacity: 4];
|
||||
for (int i = 0; i < files.size(); ++i)
|
||||
[filesArray addObject: juceStringToNS (files[i])];
|
||||
|
||||
[pboard setPropertyList: filesArray
|
||||
forType: NSFilenamesPboardType];
|
||||
|
||||
NSPoint dragPosition = [view convertPoint: [[[view window] currentEvent] locationInWindow]
|
||||
fromView: nil];
|
||||
dragPosition.x -= 16;
|
||||
dragPosition.y -= 16;
|
||||
|
||||
[view dragImage: [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (files[0])]
|
||||
at: dragPosition
|
||||
offset: NSMakeSize (0, 0)
|
||||
event: [[view window] currentEvent]
|
||||
pasteboard: pboard
|
||||
source: view
|
||||
slideBack: YES];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DragAndDropContainer::performExternalDragDropOfText (const String& /*text*/)
|
||||
@@ -340,13 +332,13 @@ public:
|
||||
const_cast <Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh();
|
||||
}
|
||||
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback);
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback)
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DisplaySettingsChangeCallback)
|
||||
};
|
||||
|
||||
juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback);
|
||||
juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback)
|
||||
|
||||
static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom)
|
||||
{
|
||||
|
||||
@@ -1226,7 +1226,7 @@ private:
|
||||
|
||||
LPCTSTR getWindowClassName() const noexcept { return (LPCTSTR) MAKELONG (atom, 0); }
|
||||
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (WindowClassHolder);
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (WindowClassHolder)
|
||||
|
||||
private:
|
||||
ATOM atom;
|
||||
@@ -1749,10 +1749,13 @@ private:
|
||||
|
||||
doMouseMove (position);
|
||||
|
||||
updateModifiersFromWParam (wParam);
|
||||
isDragging = true;
|
||||
if (isValidPeer (this))
|
||||
{
|
||||
updateModifiersFromWParam (wParam);
|
||||
isDragging = true;
|
||||
|
||||
doMouseEvent (position);
|
||||
doMouseEvent (position);
|
||||
}
|
||||
}
|
||||
|
||||
void doMouseUp (Point<float> position, const WPARAM wParam)
|
||||
@@ -2936,7 +2939,7 @@ ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component& component, voi
|
||||
}
|
||||
|
||||
|
||||
juce_ImplementSingleton_SingleThreaded (HWNDComponentPeer::WindowClassHolder);
|
||||
juce_ImplementSingleton_SingleThreaded (HWNDComponentPeer::WindowClassHolder)
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
@@ -208,7 +208,7 @@ public:
|
||||
|
||||
void applyToComponentBounds()
|
||||
{
|
||||
for (int i = 4; --i >= 0;)
|
||||
for (int i = 32; --i >= 0;)
|
||||
{
|
||||
ComponentScope scope (getComponent());
|
||||
const Rectangle<int> newBounds (rectangle.resolve (&scope).getSmallestIntegerContainer());
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An rectangle stored as a set of RelativeCoordinate values.
|
||||
A rectangle stored as a set of RelativeCoordinate values.
|
||||
|
||||
The rectangle's top, left, bottom and right edge positions are each stored as a RelativeCoordinate.
|
||||
|
||||
|
||||
@@ -473,7 +473,7 @@ bool ComboBox::keyPressed (const KeyPress& key)
|
||||
|
||||
if (key == KeyPress::returnKey)
|
||||
{
|
||||
showPopup();
|
||||
showPopupIfNotActive();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -512,42 +512,51 @@ void ComboBox::popupMenuFinishedCallback (int result, ComboBox* box)
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::showPopup()
|
||||
void ComboBox::showPopupIfNotActive()
|
||||
{
|
||||
if (! menuActive)
|
||||
{
|
||||
const int selectedId = getSelectedId();
|
||||
|
||||
PopupMenu menu;
|
||||
menu.setLookAndFeel (&getLookAndFeel());
|
||||
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
{
|
||||
const ItemInfo* const item = items.getUnchecked(i);
|
||||
|
||||
if (item->isSeparator())
|
||||
menu.addSeparator();
|
||||
else if (item->isHeading)
|
||||
menu.addSectionHeader (item->name);
|
||||
else
|
||||
menu.addItem (item->itemId, item->name,
|
||||
item->isEnabled, item->itemId == selectedId);
|
||||
}
|
||||
|
||||
if (items.size() == 0)
|
||||
menu.addItem (1, noChoicesMessage, false);
|
||||
|
||||
menuActive = true;
|
||||
|
||||
menu.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
|
||||
.withItemThatMustBeVisible (selectedId)
|
||||
.withMinimumWidth (getWidth())
|
||||
.withMaximumNumColumns (1)
|
||||
.withStandardItemHeight (jlimit (12, 24, getHeight())),
|
||||
ModalCallbackFunction::forComponent (popupMenuFinishedCallback, this));
|
||||
showPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::showPopup()
|
||||
{
|
||||
PopupMenu menu;
|
||||
menu.setLookAndFeel (&getLookAndFeel());
|
||||
addItemsToMenu (menu);
|
||||
|
||||
menu.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
|
||||
.withItemThatMustBeVisible (getSelectedId())
|
||||
.withMinimumWidth (getWidth())
|
||||
.withMaximumNumColumns (1)
|
||||
.withStandardItemHeight (label->getHeight()),
|
||||
ModalCallbackFunction::forComponent (popupMenuFinishedCallback, this));
|
||||
}
|
||||
|
||||
void ComboBox::addItemsToMenu (PopupMenu& menu) const
|
||||
{
|
||||
const int selectedId = getSelectedId();
|
||||
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
{
|
||||
const ItemInfo* const item = items.getUnchecked(i);
|
||||
jassert (item != nullptr);
|
||||
|
||||
if (item->isSeparator())
|
||||
menu.addSeparator();
|
||||
else if (item->isHeading)
|
||||
menu.addSectionHeader (item->name);
|
||||
else
|
||||
menu.addItem (item->itemId, item->name,
|
||||
item->isEnabled, item->itemId == selectedId);
|
||||
}
|
||||
|
||||
if (items.size() == 0)
|
||||
menu.addItem (1, noChoicesMessage, false);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ComboBox::mouseDown (const MouseEvent& e)
|
||||
{
|
||||
@@ -556,7 +565,7 @@ void ComboBox::mouseDown (const MouseEvent& e)
|
||||
isButtonDown = isEnabled() && ! e.mods.isPopupMenu();
|
||||
|
||||
if (isButtonDown && (e.eventComponent == this || ! label->isEditable()))
|
||||
showPopup();
|
||||
showPopupIfNotActive();
|
||||
}
|
||||
|
||||
void ComboBox::mouseDrag (const MouseEvent& e)
|
||||
@@ -564,7 +573,7 @@ void ComboBox::mouseDrag (const MouseEvent& e)
|
||||
beginDragAutoRepeat (50);
|
||||
|
||||
if (isButtonDown && ! e.mouseWasClicked())
|
||||
showPopup();
|
||||
showPopupIfNotActive();
|
||||
}
|
||||
|
||||
void ComboBox::mouseUp (const MouseEvent& e2)
|
||||
@@ -579,7 +588,7 @@ void ComboBox::mouseUp (const MouseEvent& e2)
|
||||
if (reallyContains (e.getPosition(), true)
|
||||
&& (e2.eventComponent == this || ! label->isEditable()))
|
||||
{
|
||||
showPopup();
|
||||
showPopupIfNotActive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +263,9 @@ public:
|
||||
*/
|
||||
virtual void showPopup();
|
||||
|
||||
/** Adds the items in this ComboBox to the given menu. */
|
||||
virtual void addItemsToMenu (PopupMenu&) const;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class for receiving events from a ComboBox.
|
||||
@@ -432,6 +435,7 @@ private:
|
||||
bool selectIfEnabled (int index);
|
||||
bool nudgeSelectedItem (int delta);
|
||||
void sendChange (NotificationType);
|
||||
void showPopupIfNotActive();
|
||||
static void popupMenuFinishedCallback (int, ComboBox*);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBox)
|
||||
|
||||
@@ -174,7 +174,7 @@ public:
|
||||
|
||||
int getRowNumberOfComponent (Component* const rowComponent) const noexcept
|
||||
{
|
||||
const int index = getIndexOfChildComponent (rowComponent);
|
||||
const int index = getViewedComponent()->getIndexOfChildComponent (rowComponent);
|
||||
const int num = rows.size();
|
||||
|
||||
for (int i = num; --i >= 0;)
|
||||
@@ -196,15 +196,16 @@ public:
|
||||
{
|
||||
hasUpdated = false;
|
||||
|
||||
const int newX = getViewedComponent()->getX();
|
||||
int newY = getViewedComponent()->getY();
|
||||
Component& content = *getViewedComponent();
|
||||
const int newX = content.getX();
|
||||
int newY = content.getY();
|
||||
const int newW = jmax (owner.minimumRowWidth, getMaximumVisibleWidth());
|
||||
const int newH = owner.totalItems * owner.getRowHeight();
|
||||
|
||||
if (newY + newH < getMaximumVisibleHeight() && newH > getMaximumVisibleHeight())
|
||||
newY = getMaximumVisibleHeight() - newH;
|
||||
|
||||
getViewedComponent()->setBounds (newX, newY, newW, newH);
|
||||
content.setBounds (newX, newY, newW, newH);
|
||||
|
||||
if (makeSureItUpdatesContent && ! hasUpdated)
|
||||
updateContents();
|
||||
@@ -214,11 +215,12 @@ public:
|
||||
{
|
||||
hasUpdated = true;
|
||||
const int rowH = owner.getRowHeight();
|
||||
Component& content = *getViewedComponent();
|
||||
|
||||
if (rowH > 0)
|
||||
{
|
||||
const int y = getViewPositionY();
|
||||
const int w = getViewedComponent()->getWidth();
|
||||
const int w = content.getWidth();
|
||||
|
||||
const int numNeeded = 2 + getMaximumVisibleHeight() / rowH;
|
||||
rows.removeRange (numNeeded, rows.size());
|
||||
@@ -227,7 +229,7 @@ public:
|
||||
{
|
||||
RowComponent* newRow = new RowComponent (owner);
|
||||
rows.add (newRow);
|
||||
getViewedComponent()->addAndMakeVisible (newRow);
|
||||
content.addAndMakeVisible (newRow);
|
||||
}
|
||||
|
||||
firstIndex = y / rowH;
|
||||
@@ -247,10 +249,10 @@ public:
|
||||
}
|
||||
|
||||
if (owner.headerComponent != nullptr)
|
||||
owner.headerComponent->setBounds (owner.outlineThickness + getViewedComponent()->getX(),
|
||||
owner.headerComponent->setBounds (owner.outlineThickness + content.getX(),
|
||||
owner.outlineThickness,
|
||||
jmax (owner.getWidth() - owner.outlineThickness * 2,
|
||||
getViewedComponent()->getWidth()),
|
||||
content.getWidth()),
|
||||
owner.headerComponent->getHeight());
|
||||
}
|
||||
|
||||
|
||||
@@ -248,9 +248,7 @@ public:
|
||||
void setSkewFactorFromMidPoint (double sliderValueToShowAtMidPoint);
|
||||
|
||||
/** Returns the current skew factor.
|
||||
|
||||
See setSkewFactor for more info.
|
||||
|
||||
@see setSkewFactor, setSkewFactorFromMidPoint
|
||||
*/
|
||||
double getSkewFactor() const noexcept;
|
||||
@@ -682,6 +680,13 @@ public:
|
||||
/** Returns the suffix that was set by setTextValueSuffix(). */
|
||||
String getTextValueSuffix() const;
|
||||
|
||||
/** Returns the best number of decimal places to use when displaying this
|
||||
slider's value.
|
||||
It calculates the fewest decimal places needed to represent numbers with
|
||||
the slider's interval setting.
|
||||
*/
|
||||
int getNumDecimalPlacesToDisplay() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Allows a user-defined mapping of distance along the slider to its value.
|
||||
|
||||
@@ -831,7 +836,6 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
@@ -858,11 +862,6 @@ protected:
|
||||
/** @internal */
|
||||
void colourChanged() override;
|
||||
|
||||
/** Returns the best number of decimal places to use when displaying numbers.
|
||||
This is calculated from the slider's interval setting.
|
||||
*/
|
||||
int getNumDecimalPlacesToDisplay() const noexcept;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_PUBLIC_IN_DLL_BUILD (class Pimpl)
|
||||
|
||||
@@ -558,6 +558,10 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s)
|
||||
}
|
||||
|
||||
updateLastPosIfNotFullScreen();
|
||||
|
||||
if (fs)
|
||||
setBoundsConstrained (newPos);
|
||||
|
||||
setFullScreen (fs);
|
||||
|
||||
if (! fs)
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
TooltipWindow::TooltipWindow (Component* const parentComp, const int delayMs)
|
||||
: Component ("tooltip"),
|
||||
lastComponentUnderMouse (nullptr),
|
||||
millisecondsBeforeTipAppears (delayMs),
|
||||
mouseClicks (0),
|
||||
mouseWheelMoves (0),
|
||||
lastHideTime (0),
|
||||
lastComponentUnderMouse (nullptr)
|
||||
mouseClicks (0), mouseWheelMoves (0),
|
||||
lastCompChangeTime (0), lastHideTime (0),
|
||||
reentrant (false)
|
||||
{
|
||||
if (Desktop::getInstance().getMainMouseSource().canHover())
|
||||
startTimer (123);
|
||||
@@ -76,27 +76,34 @@ void TooltipWindow::updatePosition (const String& tip, Point<int> pos, const Rec
|
||||
void TooltipWindow::displayTip (Point<int> screenPos, const String& tip)
|
||||
{
|
||||
jassert (tip.isNotEmpty());
|
||||
if (tipShowing != tip)
|
||||
repaint();
|
||||
|
||||
tipShowing = tip;
|
||||
|
||||
if (Component* const parent = getParentComponent())
|
||||
if (! reentrant)
|
||||
{
|
||||
updatePosition (tip, parent->getLocalPoint (nullptr, screenPos),
|
||||
parent->getLocalBounds());
|
||||
}
|
||||
else
|
||||
{
|
||||
updatePosition (tip, screenPos, Desktop::getInstance().getDisplays()
|
||||
.getDisplayContaining (screenPos).userArea);
|
||||
ScopedValueSetter<bool> setter (reentrant, true, false);
|
||||
|
||||
addToDesktop (ComponentPeer::windowHasDropShadow
|
||||
| ComponentPeer::windowIsTemporary
|
||||
| ComponentPeer::windowIgnoresKeyPresses);
|
||||
}
|
||||
if (tipShowing != tip)
|
||||
{
|
||||
tipShowing = tip;
|
||||
repaint();
|
||||
}
|
||||
|
||||
toFront (false);
|
||||
if (Component* const parent = getParentComponent())
|
||||
{
|
||||
updatePosition (tip, parent->getLocalPoint (nullptr, screenPos),
|
||||
parent->getLocalBounds());
|
||||
}
|
||||
else
|
||||
{
|
||||
updatePosition (tip, screenPos, Desktop::getInstance().getDisplays()
|
||||
.getDisplayContaining (screenPos).userArea);
|
||||
|
||||
addToDesktop (ComponentPeer::windowHasDropShadow
|
||||
| ComponentPeer::windowIsTemporary
|
||||
| ComponentPeer::windowIgnoresKeyPresses);
|
||||
}
|
||||
|
||||
toFront (false);
|
||||
}
|
||||
}
|
||||
|
||||
String TooltipWindow::getTipFor (Component* const c)
|
||||
@@ -110,14 +117,17 @@ String TooltipWindow::getTipFor (Component* const c)
|
||||
return ttc->getTooltip();
|
||||
}
|
||||
|
||||
return String::empty;
|
||||
return String();
|
||||
}
|
||||
|
||||
void TooltipWindow::hideTip()
|
||||
{
|
||||
tipShowing.clear();
|
||||
removeFromDesktop();
|
||||
setVisible (false);
|
||||
if (! reentrant)
|
||||
{
|
||||
tipShowing.clear();
|
||||
removeFromDesktop();
|
||||
setVisible (false);
|
||||
}
|
||||
}
|
||||
|
||||
void TooltipWindow::timerCallback()
|
||||
|
||||
@@ -110,12 +110,13 @@ public:
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
int millisecondsBeforeTipAppears;
|
||||
Point<float> lastMousePos;
|
||||
int mouseClicks, mouseWheelMoves;
|
||||
unsigned int lastCompChangeTime, lastHideTime;
|
||||
Component* lastComponentUnderMouse;
|
||||
String tipShowing, lastTipUnderMouse;
|
||||
int millisecondsBeforeTipAppears;
|
||||
int mouseClicks, mouseWheelMoves;
|
||||
unsigned int lastCompChangeTime, lastHideTime;
|
||||
bool reentrant;
|
||||
|
||||
void paint (Graphics&) override;
|
||||
void mouseEnter (const MouseEvent&) override;
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
clearSingletonInstance();
|
||||
}
|
||||
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager);
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager)
|
||||
|
||||
void checkFocusAsync()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user