void TabbedButtonBar::addTab (const String& tabName,
                              const Colour& tabBackgroundColour,
                              int insertIndex)
{
    jassert (tabName.isNotEmpty()); // you have to give them all a name..

    if (tabName.isNotEmpty())
    {
        if (! isPositiveAndBelow (insertIndex, tabs.size()))
            insertIndex = tabs.size();

        TabInfo* const currentTab = tabs [currentTabIndex];

        TabInfo* newTab = new TabInfo();
        newTab->name = tabName;
        newTab->colour = tabBackgroundColour;
        newTab->button = createTabButton (tabName, insertIndex);
        jassert (newTab->button != nullptr);

        tabs.insert (insertIndex, newTab);
        currentTabIndex = tabs.indexOf (currentTab);
        addAndMakeVisible (newTab->button, insertIndex);

        resized();

        if (currentTabIndex < 0)
            setCurrentTabIndex (0);
    }
}
void TabbedButtonBar::addTab (const String& tabName,
                              const Colour& tabBackgroundColour,
                              int insertIndex)
{
    jassert (tabName.isNotEmpty()); // you have to give them all a name..

    if (tabName.isNotEmpty())
    {
        if (((unsigned int) insertIndex) > (unsigned int) tabs.size())
            insertIndex = tabs.size();

        for (int i = tabs.size(); --i >= insertIndex;)
        {
            TabBarButton* const tb = getTabButton (i);

            if (tb != 0)
                tb->tabIndex++;
        }

        tabs.insert (insertIndex, tabName);
        tabColours.insert (insertIndex, tabBackgroundColour);

        TabBarButton* const tb = createTabButton (tabName, insertIndex);
        jassert (tb != 0); // your createTabButton() mustn't return zero!

        addAndMakeVisible (tb, insertIndex);

        resized();

        if (currentTabIndex < 0)
            setCurrentTabIndex (0);
    }
}
Example #3
0
void LibraryModule::getLocalCompiledFiles (const File& localModuleFolder, Array<File>& result) const
{
    const var compileArray (moduleInfo.moduleInfo ["compile"]); // careful to keep this alive while the array is in use!

    if (const Array<var>* const files = compileArray.getArray())
    {
        for (int i = 0; i < files->size(); ++i)
        {
            const var& file = files->getReference(i);
            const String filename (file ["file"].toString());

            if (filename.isNotEmpty()
                  #if JUCE_MAC
                   && exporterTargetMatches ("xcode", file ["target"].toString())
                  #elif JUCE_WINDOWS
                   && exporterTargetMatches ("msvc",  file ["target"].toString())
                  #elif JUCE_LINUX
                   && exporterTargetMatches ("linux", file ["target"].toString())
                  #endif
                )
            {
                result.add (localModuleFolder.getChildFile (filename));
            }
        }
    }
}
//==============================================================================
void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
{
    if (defaultMidiOutputName != deviceName)
    {
        Array<AudioIODeviceCallback*> oldCallbacks;

        {
            const ScopedLock sl (audioCallbackLock);
            oldCallbacks.swapWith (callbacks);
        }

        if (currentAudioDevice != nullptr)
            for (int i = oldCallbacks.size(); --i >= 0;)
                oldCallbacks.getUnchecked(i)->audioDeviceStopped();

        defaultMidiOutput = nullptr;
        defaultMidiOutputName = deviceName;

        if (deviceName.isNotEmpty())
            defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));

        if (currentAudioDevice != nullptr)
            for (int i = oldCallbacks.size(); --i >= 0;)
                oldCallbacks.getUnchecked(i)->audioDeviceAboutToStart (currentAudioDevice);

        {
            const ScopedLock sl (audioCallbackLock);
            oldCallbacks.swapWith (callbacks);
        }

        updateXml();
        sendChangeMessage();
    }
}
	var getResult(const Scope& s) const override
	{
		var result = object->getResult(s);

		if (VariantBuffer *b = result.getBuffer())
		{
			const int i = index->getResult(s);
			return (*b)[i];
		}
		else if (AssignableObject * instance = dynamic_cast<AssignableObject*>(result.getObject()))
		{
			cacheIndex(instance, s);

			return instance->getAssignedValue(cachedIndex);
		}
		else if (const Array<var>* array = result.getArray())
			return (*array)[static_cast<int> (index->getResult(s))];

        else if (const DynamicObject* obj = result.getDynamicObject())
        {
            const String name = index->getResult(s).toString();
            
            if(name.isNotEmpty())
            {
                return obj->getProperty(Identifier(name));
            }
            
            
        }
        
		return var::undefined();
	}
void UnitTestRunner::addFail (const String& failureMessage)
{
    {
        const ScopedLock sl (results.getLock());

        TestResult* const r = results.getLast();
        jassert (r != nullptr); // You need to call UnitTest::beginTest() before performing any tests!

        r->failures++;

        String message ("!!! Test ");
        message << (r->failures + r->passes) << " failed";

        if (failureMessage.isNotEmpty())
            message << ": " << failureMessage;

        r->messages.add (message);

        logMessage (message);
    }

    resultsUpdated();

    if (assertOnFailure) { jassertfalse; }
}
Example #7
0
    void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
    {
        if (rowIsSelected)
            g.fillAll (Colours::deepskyblue);

        if (JuceDemoTypeBase* type = JuceDemoTypeBase::getDemoTypeList() [rowNumber])
        {
            String name (type->name.trimCharactersAtStart ("0123456789").trimStart());

            AttributedString a;
            a.setJustification (Justification::centredLeft);

            String category;

            if (name.containsChar (':'))
            {
                category = name.upToFirstOccurrenceOf (":", true, false);
                name = name.fromFirstOccurrenceOf (":", false, false).trim();

                if (height > 20)
                    category << "\n";
                else
                    category << " ";
            }

            if (category.isNotEmpty())
                a.append (category, Font (10.0f), Colour::greyLevel (0.5f));

            a.append (name, Font (13.0f), Colours::white.withAlpha (0.9f));

            a.draw (g, Rectangle<int> (width + 10, height).reduced (6, 0).toFloat());
        }
    }
Example #8
0
void LibraryModule::findAndAddCompiledCode (ProjectExporter& exporter, ProjectSaver& projectSaver,
                                            const File& localModuleFolder, Array<File>& result) const
{
    const var compileArray (moduleInfo.moduleInfo ["compile"]); // careful to keep this alive while the array is in use!

    if (const Array<var>* const files = compileArray.getArray())
    {
        for (int i = 0; i < files->size(); ++i)
        {
            const var& file = files->getReference(i);
            const String filename (file ["file"].toString());

            if (filename.isNotEmpty()
                 && fileTargetMatches (exporter, file ["target"].toString()))
            {
                const File compiledFile (localModuleFolder.getChildFile (filename));
                result.add (compiledFile);

                Project::Item item (projectSaver.addFileToGeneratedGroup (compiledFile));

                if (file ["warnings"].toString().equalsIgnoreCase ("disabled"))
                    item.getShouldInhibitWarningsValue() = true;

                if (file ["stdcall"])
                    item.getShouldUseStdCallValue() = true;
            }
        }
    }
}
Example #9
0
void ProjectExporter::addVST3FolderToPath()
{
    const String vst3Folder (getVST3PathValue().toString());

    if (vst3Folder.isNotEmpty())
        addToExtraSearchPaths (RelativePath (vst3Folder, RelativePath::projectFolder), 0);
}
Example #10
0
void ComboBox::addSectionHeading (const String& headingName)
{
    // you can't add empty strings to the list..
    jassert (headingName.isNotEmpty());

    if (headingName.isNotEmpty())
    {
        if (separatorPending)
        {
            separatorPending = false;
            items.add (new ItemInfo (String::empty, 0, false, false));
        }

        items.add (new ItemInfo (headingName, 0, true, true));
    }
}
Example #11
0
void TestComponent::setFilename (const String& newName)
{
    File newFile;

    if (newName.isNotEmpty())
    {
        if (ownerDocument != nullptr)
            newFile = ownerDocument->getCppFile().getSiblingFile (newName);
        else
            newFile = File::getCurrentWorkingDirectory().getChildFile (newName);
    }

    if (! recursiveFiles.contains (newFile.getFullPathName()))
    {
        recursiveFiles.add (newFile.getFullPathName());

        loadedDocument = nullptr;

        filename = newName;
        lastModificationTime = findFile().getLastModificationTime();

        loadedDocument = JucerDocument::createForCppFile (nullptr, findFile());

        updateContents();
        repaint();

        recursiveFiles.remove (recursiveFiles.size() - 1);
    }
}
Example #12
0
    bool getIndentForCurrentBlock (CodeDocument::Position pos, const String& tab,
                                   String& blockIndent, String& lastLineIndent)
    {
        int braceCount = 0;
        bool indentFound = false;

        while (pos.getLineNumber() > 0)
        {
            pos = pos.movedByLines (-1);

            const String line (pos.getLineText());
            const String trimmedLine (line.trimStart());

            braceCount += getBraceCount (trimmedLine.getCharPointer());

            if (braceCount > 0)
            {
                blockIndent = getLeadingWhitespace (line);
                if (! indentFound)
                    lastLineIndent = blockIndent + tab;

                return true;
            }

            if ((! indentFound) && trimmedLine.isNotEmpty())
            {
                indentFound = true;
                lastLineIndent = getLeadingWhitespace (line);
            }
        }

        return false;
    }
Example #13
0
//==============================================================================
void LibraryModule::prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const
{
    Project& project = exporter.getProject();

    exporter.addToExtraSearchPaths (exporter.getModuleFolderRelativeToProject (getID(), projectSaver).getParentDirectory());

    const String extraDefs (moduleInfo.getPreprocessorDefs().trim());

    if (extraDefs.isNotEmpty())
        exporter.getExporterPreprocessorDefs() = exporter.getExporterPreprocessorDefsString() + "\n" + extraDefs;

    {
        Array<File> compiled;

        const File localModuleFolder = project.getModules().shouldCopyModuleFilesLocally (getID()).getValue()
                                          ? projectSaver.getLocalModuleFolder (getID())
                                          : moduleInfo.getFolder();

        findAndAddCompiledCode (exporter, projectSaver, localModuleFolder, compiled);

        if (project.getModules().shouldShowAllModuleFilesInProject (getID()).getValue())
            addBrowsableCode (exporter, projectSaver, compiled, moduleInfo.getFolder());
    }

    if (isVSTPluginHost (project))
        VSTHelpers::addVSTFolderToPath (exporter, exporter.extraSearchPaths);

    if (exporter.isXcode())
    {
        if (isAUPluginHost (project))
            exporter.xcodeFrameworks.addTokens ("AudioUnit CoreAudioKit", false);

        const String frameworks (moduleInfo.moduleInfo [exporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString());
        exporter.xcodeFrameworks.addTokens (frameworks, ", ", String::empty);
    }
    else if (exporter.isLinux())
    {
        const String libs (moduleInfo.moduleInfo ["LinuxLibs"].toString());
        exporter.linuxLibs.addTokens (libs, ", ", String::empty);
        exporter.linuxLibs.trim();
        exporter.linuxLibs.sort (false);
        exporter.linuxLibs.removeDuplicates (false);
    }
    else if (exporter.isCodeBlocks())
    {
        const String libs (moduleInfo.moduleInfo ["mingwLibs"].toString());
        exporter.mingwLibs.addTokens (libs, ", ", String::empty);
        exporter.mingwLibs.trim();
        exporter.mingwLibs.sort (false);
        exporter.mingwLibs.removeDuplicates (false);
    }

    if (moduleInfo.isPluginClient())
    {
        if (shouldBuildVST  (project).getValue())  VSTHelpers::prepareExporter (exporter, projectSaver);
        if (shouldBuildAU   (project).getValue())  AUHelpers::prepareExporter (exporter, projectSaver);
        if (shouldBuildAAX  (project).getValue())  AAXHelpers::prepareExporter (exporter, projectSaver);
        if (shouldBuildRTAS (project).getValue())  RTASHelpers::prepareExporter (exporter, projectSaver);
    }
}
Example #14
0
void CodeDocument::insert (const String& text, const int insertPos, const bool undoable)
{
    if (text.isNotEmpty())
    {
        if (undoable)
        {
            undoManager.perform (new CodeDocumentInsertAction (*this, text, insertPos));
        }
        else
        {
            Position pos (*this, insertPos);
            const int firstAffectedLine = pos.getLineNumber();

            CodeDocumentLine* const firstLine = lines [firstAffectedLine];
            String textInsideOriginalLine (text);

            if (firstLine != nullptr)
            {
                const int index = pos.getIndexInLine();
                textInsideOriginalLine = firstLine->line.substring (0, index)
                                         + textInsideOriginalLine
                                         + firstLine->line.substring (index);
            }

            maximumLineLength = -1;
            Array <CodeDocumentLine*> newLines;
            CodeDocumentLine::createLines (newLines, textInsideOriginalLine);
            jassert (newLines.size() > 0);

            CodeDocumentLine* const newFirstLine = newLines.getUnchecked (0);
            newFirstLine->lineStartInFile = firstLine != nullptr ? firstLine->lineStartInFile : 0;
            lines.set (firstAffectedLine, newFirstLine);

            if (newLines.size() > 1)
                lines.insertArray (firstAffectedLine + 1, newLines.getRawDataPointer() + 1, newLines.size() - 1);

            int lineStart = newFirstLine->lineStartInFile;
            for (int i = firstAffectedLine; i < lines.size(); ++i)
            {
                CodeDocumentLine& l = *lines.getUnchecked (i);
                l.lineStartInFile = lineStart;
                lineStart += l.lineLength;
            }

            checkLastLineStatus();

            const int newTextLength = text.length();
            for (int i = 0; i < positionsToMaintain.size(); ++i)
            {
                CodeDocument::Position& p = *positionsToMaintain.getUnchecked(i);

                if (p.getPosition() >= insertPos)
                    p.setPosition (p.getPosition() + newTextLength);
            }

            listeners.call (&CodeDocument::Listener::codeDocumentTextInserted, text, insertPos);
        }
    }
}
//-----------------------------------------------------------------------------
// Set
//-----------------------------------------------------------------------------
void GFXPrimitiveBufferHandle::set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc)
{
   StrongRefPtr<GFXPrimitiveBuffer>::operator=( theDevice->allocPrimitiveBuffer(indexCount, primitiveCount, bufferType) );

#ifdef TORQUE_DEBUG
   if( desc.isNotEmpty() )
      getPointer()->mDebugCreationPath = desc;
#endif
}
Example #16
0
void Graphics::drawTextAsPath (const String& text, const AffineTransform& transform) const
{
    if (text.isNotEmpty())
    {
        GlyphArrangement arr;
        arr.addLineOfText (context->getFont(), text, 0.0f, 0.0f);
        arr.draw (*this, transform);
    }
}
Example #17
0
//==============================================================================
void Graphics::drawSingleLineText (const String& text, const int startX, const int baselineY) const
{
    if (text.isNotEmpty()
         && startX < context->getClipBounds().getRight())
    {
        GlyphArrangement arr;
        arr.addLineOfText (context->getFont(), text, (float) startX, (float) baselineY);
        arr.draw (*this);
    }
}
Example #18
0
    Typeface::Ptr findTypefaceFor (const Font& font)
    {
        const ScopedReadLock slr (lock);

        const String faceName (font.getTypefaceName());
        const String faceStyle (font.getTypefaceStyle());

        jassert (faceName.isNotEmpty());

        for (int i = faces.size(); --i >= 0;)
        {
            CachedFace& face = faces.getReference(i);

            if (face.typefaceName == faceName
                 && face.typefaceStyle == faceStyle
                 && face.typeface != nullptr
                 && face.typeface->isSuitableForFont (font))
            {
                face.lastUsageCount = ++counter;
                return face.typeface;
            }
        }

        const ScopedWriteLock slw (lock);
        int replaceIndex = 0;
        size_t bestLastUsageCount = std::numeric_limits<size_t>::max();

        for (int i = faces.size(); --i >= 0;)
        {
            const size_t lu = faces.getReference(i).lastUsageCount;

            if (bestLastUsageCount > lu)
            {
                bestLastUsageCount = lu;
                replaceIndex = i;
            }
        }

        CachedFace& face = faces.getReference (replaceIndex);
        face.typefaceName = faceName;
        face.typefaceStyle = faceStyle;
        face.lastUsageCount = ++counter;

        if (juce_getTypefaceForFont == nullptr)
            face.typeface = Font::getDefaultTypefaceForFont (font);
        else
            face.typeface = juce_getTypefaceForFont (font);

        jassert (face.typeface != nullptr); // the look and feel must return a typeface!

        if (defaultFace == nullptr && font == Font())
            defaultFace = face.typeface;

        return face.typeface;
    }
Example #19
0
void LocalisedStrings::loadFromText (const String& fileContents, bool ignoreCase)
{
    translations.setIgnoresCase (ignoreCase);

    StringArray lines;
    lines.addLines (fileContents);

    for (int i = 0; i < lines.size(); ++i)
    {
        String line (lines[i].trim());

        if (line.startsWithChar ('"'))
        {
            int closeQuote = findCloseQuote (line, 1);

            const String originalText (unescapeString (line.substring (1, closeQuote)));

            if (originalText.isNotEmpty())
            {
                const int openingQuote = findCloseQuote (line, closeQuote + 1);
                closeQuote = findCloseQuote (line, openingQuote + 1);

                const String newText (unescapeString (line.substring (openingQuote + 1, closeQuote)));

                if (newText.isNotEmpty())
                    translations.set (originalText, newText);
            }
        }
        else if (line.startsWithIgnoreCase ("language:"))
        {
            languageName = line.substring (9).trim();
        }
        else if (line.startsWithIgnoreCase ("countries:"))
        {
            countryCodes.addTokens (line.substring (10).trim(), true);
            countryCodes.trim();
            countryCodes.removeEmptyStrings();
        }
    }

    translations.minimiseStorageOverheads();
}
//==============================================================================
bool JucerDocument::findTemplateFiles (String& headerContent, String& cppContent) const
{
    if (templateFile.isNotEmpty())
    {
        const File f (getCppFile().getSiblingFile (templateFile));

        const File templateCpp (f.withFileExtension (".cpp"));
        const File templateH (f.withFileExtension (".h"));

        headerContent = templateH.loadFileAsString();
        cppContent = templateCpp.loadFileAsString();

        if (headerContent.isNotEmpty() && cppContent.isNotEmpty())
            return true;
    }

    headerContent = BinaryData::jucer_ComponentTemplate_h;
    cppContent    = BinaryData::jucer_ComponentTemplate_cpp;
    return true;
}
Example #21
0
void ProcessorList::mouseDrag(const MouseEvent& e) 
{

	if (e.getMouseDownX() < getWidth()-getScrollBarWidth() && !(isDragging))
	{

		ProcessorListItem* fli = getListItemForYPos(e.getMouseDownY());

		if (fli != 0)
		{

			if (!fli->hasSubItems())
			{
				isDragging = true;

				String b = fli->getParentName();
				b += "/";
				b += fli->getName();

				const String dragDescription = b;

				//std::cout << dragDescription << std::endl;

				if (dragDescription.isNotEmpty())
				{
					DragAndDropContainer* const dragContainer
						= DragAndDropContainer::findParentDragContainerFor (this);

					if (dragContainer != 0)
					{
						//pos.setSize (pos.getWidth(), 10);

						Image dragImage (Image::ARGB, 100, 15, true);

						Graphics g(dragImage);
						g.setColour (fli->color);
						g.fillAll();
						g.setColour(Colours::white);
						g.setFont(14);
						g.drawSingleLineText(fli->getName(),10,12);//,75,15,Justification::centredRight,true);

						dragImage.multiplyAllAlphas(0.6f);

						Point<int> imageOffset (20,10);
						dragContainer->startDragging(dragDescription, this,
											         dragImage, true, &imageOffset);
					}
				}
			}
		}
	}

	mouseDragInCanvas(e);
}
Example #22
0
void MainWindow::updateTitle (const String& documentName)
{
    String name (JUCEApplication::getInstance()->getApplicationName());

    if (currentProject != nullptr)
        name = currentProject->getDocumentTitle() + " - " + name;

    if (documentName.isNotEmpty())
        name = documentName + " - " + name;

    setName (name);
}
Example #23
0
void Graphics::drawMultiLineText (const String& text, const int startX, const int baselineY, const int maximumLineWidth) const
{
    if (text.isNotEmpty()
         && startX < context->getClipBounds().getRight())
    {
        GlyphArrangement arr;
        arr.addJustifiedText (context->getFont(), text,
                              (float) startX, (float) baselineY, (float) maximumLineWidth,
                              Justification::left);
        arr.draw (*this);
    }
}
Example #24
0
void Font::setTypefaceName (const String& faceName)
{
    if (faceName != font->typefaceName)
    {
        jassert (faceName.isNotEmpty());

        dupeInternalIfShared();
        font->typefaceName = faceName;
        font->typeface = nullptr;
        font->ascent = 0;
    }
}
Example #25
0
//==============================================================================
bool UndoManager::perform (UndoableAction* newAction, const String& actionName)
{
    if (perform (newAction))
    {
        if (actionName.isNotEmpty())
            setCurrentTransactionName (actionName);

        return true;
    }

    return false;
}
Example #26
0
void MainWindow::updateTitle (const String& documentName)
{
    String name (IntrojucerApp::getApp().getApplicationName());

    if (currentProject != nullptr)
        name << " - " << currentProject->getDocumentTitle();

    if (documentName.isNotEmpty())
        name << " - " << documentName;

    setName (name);
}
Example #27
0
static Array<File> getAllPossibleModulePaths (Project& project)
{
    StringArray paths;

    for (Project::ExporterIterator exporter (project); exporter.next();)
    {
        if (exporter->mayCompileOnCurrentOS())
        {
            for (int i = 0; i < project.getModules().getNumModules(); ++i)
            {
                const String path (exporter->getPathForModuleString (project.getModules().getModuleID (i)));

                if (path.isNotEmpty())
                    paths.addIfNotAlreadyThere (path);
            }

            String oldPath (exporter->getLegacyModulePath());

            if (oldPath.isNotEmpty())
                paths.addIfNotAlreadyThere (oldPath);
        }
    }

    Array<File> files;

    for (int i = 0; i < paths.size(); ++i)
    {
        const File f (project.resolveFilename (paths[i]));

        if (f.isDirectory())
        {
            files.add (f);

            if (f.getChildFile ("modules").isDirectory())
                files.addIfNotAlreadyThere (f.getChildFile ("modules"));
        }
    }

    return files;
}
Example #28
0
//==============================================================================
void ComboBox::addItem (const String& newItemText, const int newItemId)
{
    // you can't add empty strings to the list..
    jassert (newItemText.isNotEmpty());

    // IDs must be non-zero, as zero is used to indicate a lack of selecion.
    jassert (newItemId != 0);

    // you shouldn't use duplicate item IDs!
    jassert (getItemForId (newItemId) == nullptr);

    if (newItemText.isNotEmpty() && newItemId != 0)
    {
        if (separatorPending)
        {
            separatorPending = false;
            items.add (new ItemInfo (String::empty, 0, false, false));
        }

        items.add (new ItemInfo (newItemText, newItemId, true, false));
    }
}
Example #29
0
void ProjectExporter::addAAXFoldersToPath()
{
    const String aaxFolder = getAAXPathValue().toString();

    if (aaxFolder.isNotEmpty())
    {
        const RelativePath aaxFolderPath (getAAXPathValue().toString(), RelativePath::projectFolder);

        addToExtraSearchPaths (aaxFolderPath);
        addToExtraSearchPaths (aaxFolderPath.getChildFile ("Interfaces"));
        addToExtraSearchPaths (aaxFolderPath.getChildFile ("Interfaces").getChildFile ("ACF"));
    }
}
void TooltipWindow::showFor (const String& tip)
{
    jassert (tip.isNotEmpty());
    if (tipShowing != tip)
        repaint();

    tipShowing = tip;

    Point<int> mousePos (Desktop::getMousePosition());
    Rectangle<int> parentArea;

    if (getParentComponent() != nullptr)
    {
        mousePos = getParentComponent()->getLocalPoint (nullptr, mousePos);
        parentArea = getParentComponent()->getLocalBounds();
    }
    else
    {
        parentArea = Desktop::getInstance().getMonitorAreaContaining (mousePos);
    }

    int w, h;
    getLookAndFeel().getTooltipSize (tip, w, h);

    int x = mousePos.x;
    if (x > parentArea.getCentreX())
        x -= (w + 12);
    else
        x += 24;

    int y = mousePos.y;
    if (y > parentArea.getCentreY())
        y -= (h + 6);
    else
        y += 6;

    x = jlimit (parentArea.getX(), parentArea.getRight() - w, x);
    y = jlimit (parentArea.getY(), parentArea.getBottom() - h, y);

    setBounds (x, y, w, h);
    setVisible (true);

    if (getParentComponent() == nullptr)
    {
        addToDesktop (ComponentPeer::windowHasDropShadow
                      | ComponentPeer::windowIsTemporary
                      | ComponentPeer::windowIgnoresKeyPresses);
    }

    toFront (false);
}