Browse Source

Update juce

tags/1.9.7
falkTX 10 years ago
parent
commit
500dedf3d5
33 changed files with 757 additions and 79 deletions
  1. +4
    -4
      source/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp
  2. +2
    -2
      source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  3. +2
    -1
      source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
  4. +8
    -0
      source/modules/juce_core/AppConfig.h
  5. +2
    -2
      source/modules/juce_core/javascript/juce_Javascript.cpp
  6. +7
    -0
      source/modules/juce_core/juce_core.cpp
  7. +11
    -0
      source/modules/juce_core/juce_core.h
  8. +12
    -4
      source/modules/juce_core/maths/juce_MathsFunctions.h
  9. +18
    -0
      source/modules/juce_core/memory/juce_Memory.h
  10. +7
    -1
      source/modules/juce_core/native/juce_android_JNIHelpers.h
  11. +472
    -0
      source/modules/juce_core/native/juce_curl_Network.cpp
  12. +70
    -12
      source/modules/juce_core/native/juce_linux_Network.cpp
  13. +1
    -1
      source/modules/juce_core/native/juce_posix_SharedCode.h
  14. +16
    -5
      source/modules/juce_core/native/juce_win32_Files.cpp
  15. +1
    -1
      source/modules/juce_core/system/juce_CompilerSupport.h
  16. +2
    -2
      source/modules/juce_core/system/juce_PlatformDefs.h
  17. +2
    -2
      source/modules/juce_core/zip/juce_ZipFile.cpp
  18. +16
    -10
      source/modules/juce_core/zip/juce_ZipFile.h
  19. +5
    -1
      source/modules/juce_graphics/fonts/juce_Font.h
  20. +2
    -0
      source/modules/juce_gui_basics/application/juce_Application.h
  21. +2
    -2
      source/modules/juce_gui_basics/components/juce_Component.h
  22. +0
    -2
      source/modules/juce_gui_basics/components/juce_Desktop.cpp
  23. +4
    -4
      source/modules/juce_gui_basics/drawables/juce_SVGParser.cpp
  24. +7
    -6
      source/modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h
  25. +6
    -0
      source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
  26. +15
    -0
      source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h
  27. +3
    -3
      source/modules/juce_gui_basics/menus/juce_PopupMenu.cpp
  28. +1
    -1
      source/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp
  29. +42
    -0
      source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
  30. +2
    -4
      source/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp
  31. +3
    -0
      source/modules/juce_gui_basics/widgets/juce_TableListBox.h
  32. +11
    -9
      source/modules/juce_gui_basics/windows/juce_AlertWindow.cpp
  33. +1
    -0
      source/modules/juce_gui_basics/windows/juce_AlertWindow.h

+ 4
- 4
source/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp View File

@@ -26,12 +26,12 @@ namespace MidiBufferHelpers
{
inline int getEventTime (const void* const d) noexcept
{
return *static_cast<const int32*> (d);
return readUnaligned<int32> (d);
}
inline uint16 getEventDataSize (const void* const d) noexcept
{
return *reinterpret_cast<const uint16*> (static_cast<const char*> (d) + sizeof (int32));
return readUnaligned<uint16> (static_cast<const char*> (d) + sizeof (int32));
}
inline uint16 getEventTotalSize (const void* const d) noexcept
@@ -124,8 +124,8 @@ void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const
data.insertMultiple (offset, 0, (int) newItemSize);
uint8* const d = data.begin() + offset;
*reinterpret_cast<int32*> (d) = sampleNumber;
*reinterpret_cast<uint16*> (d + 4) = (uint16) numBytes;
writeUnaligned<int32> (d, sampleNumber);
writeUnaligned<uint16> (d + 4, static_cast<uint16> (numBytes));
memcpy (d + 6, newData, (size_t) numBytes);
}
}


+ 2
- 2
source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp View File

@@ -538,10 +538,10 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
jassert (voice->isVoiceActive()); // We wouldn't be here otherwise
if (voice->canPlaySound (soundToPlay))
{
jassert (voice->isVoiceActive()); // We wouldn't be here otherwise
VoiceAgeSorter sorter;
usableVoices.addSorted (sorter, voice);


+ 2
- 1
source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp View File

@@ -977,7 +977,6 @@ bool AudioProcessorGraph::removeNode (const uint32 nodeId)
{
if (nodes.getUnchecked(i)->nodeId == nodeId)
{
nodes.getUnchecked(i)->setParentGraph (nullptr);
nodes.remove (i);
triggerAsyncUpdate();
@@ -1282,6 +1281,8 @@ void AudioProcessorGraph::setPlayHead (AudioPlayHead* audioPlayHead)
{
const ScopedLock sl (getCallbackLock());
AudioProcessor::setPlayHead (audioPlayHead);
for (int i = 0; i < nodes.size(); ++i)
nodes.getUnchecked(i)->getProcessor()->setPlayHead (audioPlayHead);
}


+ 8
- 0
source/modules/juce_core/AppConfig.h View File

@@ -63,6 +63,14 @@
*/
#define JUCE_INCLUDE_ZLIB_CODE 1
/** Config: JUCE_USE_CURL
Enables http/https support via libcurl (Linux only). Enabling this will add an additional
run-time dynmic dependency to libcurl.
If you disable this then https/ssl support will not be available on linux.
*/
#define JUCE_USE_CURL 0
/* Config: JUCE_CATCH_UNHANDLED_EXCEPTIONS
If enabled, this will add some exception-catching code to forward unhandled exceptions
to your JUCEApplicationBase::unhandledException() callback.


+ 2
- 2
source/modules/juce_core/javascript/juce_Javascript.cpp View File

@@ -1584,8 +1584,8 @@ struct JavascriptEngine::RootObject : public DynamicObject
static var Math_range (Args a) { return isInt (a, 0) ? var (jlimit (getInt (a, 1), getInt (a, 2), getInt (a, 0))) : var (jlimit (getDouble (a, 1), getDouble (a, 2), getDouble (a, 0))); }
static var Math_min (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmin (getInt (a, 0), getInt (a, 1))) : var (jmin (getDouble (a, 0), getDouble (a, 1))); }
static var Math_max (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmax (getInt (a, 0), getInt (a, 1))) : var (jmax (getDouble (a, 0), getDouble (a, 1))); }
static var Math_toDegrees (Args a) { return (180.0 / double_Pi) * getDouble (a, 0); }
static var Math_toRadians (Args a) { return (double_Pi / 180.0) * getDouble (a, 0); }
static var Math_toDegrees (Args a) { return radiansToDegrees (getDouble (a, 0)); }
static var Math_toRadians (Args a) { return degreesToRadians (getDouble (a, 0)); }
static var Math_sin (Args a) { return sin (getDouble (a, 0)); }
static var Math_asin (Args a) { return asin (getDouble (a, 0)); }
static var Math_cos (Args a) { return cos (getDouble (a, 0)); }


+ 7
- 0
source/modules/juce_core/juce_core.cpp View File

@@ -82,6 +82,10 @@
#if JUCE_LINUX
#include <langinfo.h>
#include <ifaddrs.h>
#if JUCE_USE_CURL
#include <curl/curl.h>
#endif
#endif
#include <pwd.h>
@@ -210,6 +214,9 @@ namespace juce
#include "native/juce_linux_CommonFile.cpp"
#include "native/juce_linux_Files.cpp"
#include "native/juce_linux_Network.cpp"
#if JUCE_USE_CURL
#include "native/juce_curl_Network.cpp"
#endif
#include "native/juce_linux_SystemStats.cpp"
#include "native/juce_linux_Threads.cpp"


+ 11
- 0
source/modules/juce_core/juce_core.h View File

@@ -126,6 +126,17 @@
#define JUCE_ZLIB_INCLUDE_PATH <zlib.h>
#endif
/** Config: JUCE_USE_CURL
Enables http/https support via libcurl (Linux only). Enabling this will add an additional
run-time dynmic dependency to libcurl.
If you disable this then https/ssl support will not be available on linux.
*/
#ifndef JUCE_USE_CURL
#define JUCE_USE_CURL 0
#endif
/* Config: JUCE_CATCH_UNHANDLED_EXCEPTIONS
If enabled, this will add some exception-catching code to forward unhandled exceptions
to your JUCEApplicationBase::unhandledException() callback.


+ 12
- 4
source/modules/juce_core/maths/juce_MathsFunctions.h View File

@@ -354,6 +354,15 @@ const double double_Pi = 3.1415926535897932384626433832795;
const float float_Pi = 3.14159265358979323846f;
/** Converts an angle in degrees to radians. */
template <typename FloatType>
inline FloatType degreesToRadians (FloatType degrees) noexcept { return degrees * static_cast<FloatType> (double_Pi / 180.0); }
/** Converts an angle in radians to degrees. */
template <typename FloatType>
inline FloatType radiansToDegrees (FloatType radians) noexcept { return radians * static_cast<FloatType> (180.0 / double_Pi); }
//==============================================================================
/** The isfinite() method seems to vary between platforms, so this is a
platform-independent function for it.
@@ -477,16 +486,14 @@ inline int roundFloatToInt (const float value) noexcept
}
//==============================================================================
/** Returns true if the specified integer is a power-of-two.
*/
/** Returns true if the specified integer is a power-of-two. */
template <typename IntegerType>
bool isPowerOfTwo (IntegerType value)
{
return (value & (value - 1)) == 0;
}
/** Returns the smallest power-of-two which is equal to or greater than the given integer.
*/
/** Returns the smallest power-of-two which is equal to or greater than the given integer. */
inline int nextPowerOfTwo (int n) noexcept
{
--n;
@@ -533,6 +540,7 @@ NumericType square (NumericType n) noexcept
return n * n;
}
//==============================================================================
#if JUCE_INTEL || defined (DOXYGEN)
/** This macro can be applied to a float variable to check whether it contains a denormalised


+ 18
- 0
source/modules/juce_core/memory/juce_Memory.h View File

@@ -64,6 +64,24 @@ inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { r
template <class Type>
inline Type* createCopyIfNotNull (const Type* objectToCopy) { return objectToCopy != nullptr ? new Type (*objectToCopy) : nullptr; }
//==============================================================================
/** A handy function to read un-aligned memory without a performance penalty or bus-error. */
template <typename Type>
inline Type readUnaligned (const void* srcPtr) noexcept
{
Type value;
memcpy (&value, srcPtr, sizeof (Type));
return value;
}
/** A handy function to write un-aligned memory without a performance penalty or bus-error. */
template <typename Type>
inline void writeUnaligned (void* dstPtr, Type value) noexcept
{
memcpy (dstPtr, &value, sizeof(Type));
}
//==============================================================================
#if JUCE_MAC || JUCE_IOS || DOXYGEN


+ 7
- 1
source/modules/juce_core/native/juce_android_JNIHelpers.h View File

@@ -227,8 +227,14 @@ private:
//==============================================================================
#if defined (__arm__)
#define JUCE_ARM_SOFT_FLOAT_ABI __attribute__ ((pcs("aapcs")))
#else
#define JUCE_ARM_SOFT_FLOAT_ABI
#endif
#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \
extern "C" __attribute__ ((visibility("default"))) returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params
extern "C" __attribute__ ((visibility("default"))) JUCE_ARM_SOFT_FLOAT_ABI returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params
//==============================================================================
class AndroidSystem


+ 472
- 0
source/modules/juce_core/native/juce_curl_Network.cpp View File

@@ -0,0 +1,472 @@
/*
==============================================================================
This file is part of the juce_core module of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission to use, copy, modify, and/or distribute this software for any purpose with
or without fee is hereby granted, provided that the above copyright notice and this
permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
------------------------------------------------------------------------------
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
using any other modules, be sure to check that you also comply with their license.
For more details, visit www.juce.com
==============================================================================
*/
class WebInputStream : public InputStream
{
public:
WebInputStream (const String& address, bool isPost, const MemoryBlock& postData,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, int timeOutMs, StringPairArray* responseHeaders,
const int maxRedirects)
: multi (nullptr), curl (nullptr), headerList (nullptr), lastError (CURLE_OK),
contentLength (-1), streamPos (0),
finished (false), skipBytes (0),
postBuffer (nullptr), postPosition (0)
{
statusCode = -1;
if (init() && setOptions (address, timeOutMs, (responseHeaders != nullptr),
maxRedirects, headers, isPost, postData.getSize()))
{
connect (responseHeaders, isPost, postData, progressCallback, progressCallbackContext);
}
else
{
cleanup();
}
}
~WebInputStream()
{
cleanup();
}
//==============================================================================
// Input Stream overrides
bool isError() const { return curl == nullptr || lastError != CURLE_OK; }
bool isExhausted() override { return (isError() || finished) && curlBuffer.getSize() == 0; }
int64 getPosition() override { return streamPos; }
int64 getTotalLength() override { return contentLength; }
int read (void* buffer, int bytesToRead) override
{
return readOrSkip (buffer, bytesToRead, false);
}
bool setPosition (int64 wantedPos) override
{
const int amountToSkip = static_cast<int> (wantedPos - getPosition());
if (amountToSkip < 0)
return false;
if (amountToSkip == 0)
return true;
const int actuallySkipped = readOrSkip (nullptr, amountToSkip, true);
return actuallySkipped == amountToSkip;
}
//==============================================================================
int statusCode;
private:
//==============================================================================
bool init()
{
multi = curl_multi_init();
if (multi != nullptr)
{
curl = curl_easy_init();
if (curl != nullptr)
if (curl_multi_add_handle (multi, curl) == CURLM_OK)
return true;
}
cleanup();
return false;
}
void cleanup()
{
if (curl != nullptr)
{
curl_multi_remove_handle (multi, curl);
if (headerList != nullptr)
{
curl_slist_free_all (headerList);
headerList = nullptr;
}
curl_easy_cleanup (curl);
curl = nullptr;
}
if (multi != nullptr)
{
curl_multi_cleanup (multi);
multi = nullptr;
}
}
//==============================================================================
bool setOptions (const String& address, int timeOutMs, bool wantsHeaders,
const int maxRedirects, const String& headers,
bool isPost, size_t postSize)
{
if (curl_easy_setopt (curl, CURLOPT_URL, address.toRawUTF8()) == CURLE_OK
&& curl_easy_setopt (curl, CURLOPT_WRITEDATA, this) == CURLE_OK
&& curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, StaticCurlWrite) == CURLE_OK
&& curl_easy_setopt (curl, CURLOPT_MAXREDIRS, static_cast<long> (maxRedirects)) == CURLE_OK)
{
if (isPost)
{
if (curl_easy_setopt (curl, CURLOPT_READDATA, this) != CURLE_OK
|| curl_easy_setopt (curl, CURLOPT_READFUNCTION, StaticCurlRead) != CURLE_OK)
return false;
if (curl_easy_setopt (curl, CURLOPT_POST, 1) != CURLE_OK
|| curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t> (postSize)) != CURLE_OK)
return false;
}
// do we want to parse the headers
if (wantsHeaders)
{
if (curl_easy_setopt (curl, CURLOPT_HEADERDATA, this) != CURLE_OK
|| curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, StaticCurlHeader) != CURLE_OK)
return false;
}
if (headers.isNotEmpty())
{
const StringArray headerLines = StringArray::fromLines (headers);
// fromLines will always return at least one line if the string is not empty
jassert (headerLines.size() > 0);
headerList = curl_slist_append (headerList, headerLines [0].toRawUTF8());
for (int i = 1; (i < headerLines.size() && headerList != nullptr); ++i)
headerList = curl_slist_append (headerList, headerLines [i].toRawUTF8());
if (headerList == nullptr)
return false;
if (curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headerList) != CURLE_OK)
return false;
}
if (timeOutMs > 0)
{
long timeOutSecs = static_cast<long> (ceil (static_cast<double> (timeOutMs) / 1000.0));
if (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, timeOutSecs) != CURLE_OK)
return false;
}
return true;
}
return false;
}
void connect (StringPairArray* responseHeaders, bool isPost, const MemoryBlock& postData,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
{
if (isPost)
postBuffer = &postData;
size_t lastPos = static_cast<size_t> (-1);
// step until either: 1) there is an error 2) the transaction is complete
// or 3) data is in the in buffer
while ((! finished) && curlBuffer.getSize() == 0 && curl != nullptr)
{
singleStep();
// call callbacks if this is a post request
if (isPost && progressCallback != nullptr && lastPos != postPosition)
{
lastPos = postPosition;
if (! progressCallback (progressCallbackContext,
static_cast<int> (lastPos),
static_cast<int> (postData.getSize())))
{
// user has decided to abort the transaction
cleanup();
return;
}
}
}
long responseCode;
if (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &responseCode) == CURLE_OK)
statusCode = static_cast<int> (responseCode);
// parse headers
if (responseHeaders != nullptr)
parseHttpHeaders (*responseHeaders);
// get content length size
double curlLength;
if (curl_easy_getinfo (curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curlLength) == CURLE_OK)
contentLength = static_cast<int64> (curlLength);
}
void finish()
{
if (curl == nullptr)
return;
for (;;)
{
int cnt = 0;
if (CURLMsg* msg = curl_multi_info_read (multi, &cnt))
{
if (msg->msg == CURLMSG_DONE && msg->easy_handle == curl)
{
lastError = msg->data.result; // this is the error that stopped our process from continuing
break;
}
}
else
{
break;
}
}
finished = true;
}
//==============================================================================
void singleStep()
{
if (curl == nullptr || lastError != CURLE_OK)
return;
fd_set fdread, fdwrite, fdexcep;
int maxfd = -1;
long curl_timeo;
if ((lastError = (int) curl_multi_timeout (multi, &curl_timeo)) != CURLM_OK)
return;
// why 980? see http://curl.haxx.se/libcurl/c/curl_multi_timeout.html
if (curl_timeo < 0)
curl_timeo = 980;
struct timeval tv;
tv.tv_sec = curl_timeo / 1000;
tv.tv_usec = (curl_timeo % 1000) * 1000;
FD_ZERO (&fdread);
FD_ZERO (&fdwrite);
FD_ZERO (&fdexcep);
if ((lastError = (int) curl_multi_fdset (multi, &fdread, &fdwrite, &fdexcep, &maxfd)) != CURLM_OK)
return;
if (maxfd != -1)
{
if (select (maxfd + 1, &fdread, &fdwrite, &fdexcep, &tv) < 0)
{
lastError = -1;
return;
}
}
else
{
// if curl does not return any sockets for to wait on, then the doc says to wait 100 ms
Thread::sleep (100);
}
int still_running = 0;
int curlRet;
while ((curlRet = (int) curl_multi_perform (multi, &still_running)) == CURLM_CALL_MULTI_PERFORM)
{}
if ((lastError = curlRet) != CURLM_OK)
return;
if (still_running <= 0)
finish();
}
int readOrSkip (void* buffer, int bytesToRead, bool skip)
{
if (bytesToRead <= 0)
return 0;
size_t pos = 0;
size_t len = static_cast<size_t> (bytesToRead);
while (len > 0)
{
size_t bufferBytes = curlBuffer.getSize();
bool removeSection = true;
if (bufferBytes == 0)
{
// do not call curl again if we are finished
if (finished || curl == nullptr)
return static_cast<int> (pos);
skipBytes = skip ? len : 0;
singleStep();
// update the amount that was read/skipped from curl
bufferBytes = skip ? len - skipBytes : curlBuffer.getSize();
removeSection = ! skip;
}
// can we copy data from the internal buffer?
if (bufferBytes > 0)
{
size_t max = jmin (len, bufferBytes);
if (! skip)
memcpy (addBytesToPointer (buffer, pos), curlBuffer.getData(), max);
pos += max;
streamPos += static_cast<int64> (max);
len -= max;
if (removeSection)
curlBuffer.removeSection (0, max);
}
}
return static_cast<int> (pos);
}
//==============================================================================
void parseHttpHeaders (StringPairArray& responseHeaders)
{
StringArray headerLines = StringArray::fromLines (curlHeaders);
// ignore the first line as this is the status line
for (int i = 1; i < headerLines.size(); ++i)
{
const String& headersEntry = headerLines[i];
if (headersEntry.isNotEmpty())
{
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
const String previousValue (responseHeaders [key]);
responseHeaders.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
}
}
}
//==============================================================================
// CURL callbacks
size_t curlWriteCallback (char* ptr, size_t size, size_t nmemb)
{
if (curl == nullptr || lastError != CURLE_OK)
return 0;
const size_t len = size * nmemb;
// skip bytes if necessary
size_t max = jmin (skipBytes, len);
skipBytes -= max;
if (len > max)
curlBuffer.append (ptr + max, len - max);
return len;
}
size_t curlReadCallback (char* ptr, size_t size, size_t nmemb)
{
if (curl == nullptr || postBuffer == nullptr || lastError != CURLE_OK)
return 0;
const size_t len = size * nmemb;
size_t max = jmin (postBuffer->getSize() - postPosition, len);
memcpy (ptr, (char*)postBuffer->getData() + postPosition, max);
postPosition += max;
return max;
}
size_t curlHeaderCallback (char* ptr, size_t size, size_t nmemb)
{
if (curl == nullptr || lastError != CURLE_OK)
return 0;
size_t len = size * nmemb;
curlHeaders += String (ptr, len);
return len;
}
//==============================================================================
// Static method wrappers
static size_t StaticCurlWrite (char* ptr, size_t size, size_t nmemb, void* userdata)
{
WebInputStream* wi = reinterpret_cast<WebInputStream*> (userdata);
return wi->curlWriteCallback (ptr, size, nmemb);
}
static size_t StaticCurlRead (char* ptr, size_t size, size_t nmemb, void* userdata)
{
WebInputStream* wi = reinterpret_cast<WebInputStream*> (userdata);
return wi->curlReadCallback (ptr, size, nmemb);
}
static size_t StaticCurlHeader (char* ptr, size_t size, size_t nmemb, void* userdata)
{
WebInputStream* wi = reinterpret_cast<WebInputStream*> (userdata);
return wi->curlHeaderCallback (ptr, size, nmemb);
}
private:
CURLM* multi;
CURL* curl;
struct curl_slist* headerList;
int lastError;
//==============================================================================
// internal buffers and buffer positions
int64 contentLength, streamPos;
MemoryBlock curlBuffer;
String curlHeaders;
bool finished;
size_t skipBytes;
//==============================================================================
// Http POST variables
const MemoryBlock* postBuffer;
size_t postPosition;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};

+ 70
- 12
source/modules/juce_core/native/juce_linux_Network.cpp View File

@@ -67,8 +67,8 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEma
return false;
}
//==============================================================================
#if ! JUCE_USE_CURL
class WebInputStream : public InputStream
{
public:
@@ -77,8 +77,9 @@ public:
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders,
const int maxRedirects)
: statusCode (0), socketHandle (-1), levelsOfRedirection (0),
address (address_), headers (headers_), postData (postData_), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (maxRedirects)
address (address_), headers (headers_), postData (postData_), contentLength (-1), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (maxRedirects),
chunkEnd (0), isChunked (false), readingChunk (false)
{
statusCode = createConnection (progressCallback, progressCallbackContext, numRedirectsToFollow);
@@ -104,18 +105,63 @@ public:
bool isError() const { return socketHandle < 0; }
bool isExhausted() override { return finished; }
int64 getPosition() override { return position; }
int64 getTotalLength() override
{
//xxx to do
return -1;
}
int64 getTotalLength() override { return contentLength; }
int read (void* buffer, int bytesToRead) override
{
if (finished || isError())
return 0;
if (isChunked && ! readingChunk)
{
if (position >= chunkEnd)
{
const ScopedValueSetter<bool> setter (readingChunk, true, false);
MemoryOutputStream chunkLengthBuffer;
char c = 0;
if (chunkEnd > 0)
{
if (read (&c, 1) != 1 || c != '\r'
|| read (&c, 1) != 1 || c != '\n')
{
finished = true;
return 0;
}
}
while (chunkLengthBuffer.getDataSize() < 512 && ! (finished || isError()))
{
if (read (&c, 1) != 1)
{
finished = true;
return 0;
}
if (c == '\r')
continue;
if (c == '\n')
break;
chunkLengthBuffer.writeByte (c);
}
const int64 chunkSize = chunkLengthBuffer.toString().trimStart().getHexValue64();
if (chunkSize == 0)
{
finished = true;
return 0;
}
chunkEnd += chunkSize;
}
if (bytesToRead > chunkEnd - position)
bytesToRead = chunkEnd - position;
}
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
@@ -131,7 +177,9 @@ public:
if (bytesRead == 0)
finished = true;
position += bytesRead;
if (! readingChunk)
position += bytesRead;
return bytesRead;
}
@@ -165,11 +213,13 @@ private:
StringArray headerLines;
String address, headers;
MemoryBlock postData;
int64 position;
int64 contentLength, position;
bool finished;
const bool isPost;
const int timeOutMs;
const int numRedirectsToFollow;
int64 chunkEnd;
bool isChunked, readingChunk;
void closeSocket (bool resetLevelsOfRedirection = true)
{
@@ -298,6 +348,13 @@ private:
return createConnection (progressCallback, progressCallbackContext, numRedirects);
}
String contentLengthString (findHeaderItem (headerLines, "Content-Length:"));
if (contentLengthString.isNotEmpty())
contentLength = contentLengthString.getLargeIntValue();
isChunked = (findHeaderItem (headerLines, "Transfer-Encoding:") == "chunked");
return status;
}
@@ -345,7 +402,7 @@ private:
static void writeHost (MemoryOutputStream& dest, const bool isPost,
const String& path, const String& host, int port)
{
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.1\r\nHost: " << host;
/* HTTP spec 14.23 says that the port number must be included in the header if it is not 80 */
if (port != 80)
@@ -455,3 +512,4 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};
#endif

+ 1
- 1
source/modules/juce_core/native/juce_posix_SharedCode.h View File

@@ -987,7 +987,7 @@ void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMa
if ((affinityMask & (1 << i)) != 0)
CPU_SET (i, &affinity);
#if (! JUCE_LINUX) || ((__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2004)
#if (! JUCE_ANDROID) && ((! JUCE_LINUX) || ((__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2004))
pthread_setaffinity_np (pthread_self(), sizeof (cpu_set_t), &affinity);
#else
// NB: this call isn't really correct because it sets the affinity of the process,


+ 16
- 5
source/modules/juce_core/native/juce_win32_Files.cpp View File

@@ -795,18 +795,19 @@ public:
connected (false), ownsPipe (createPipe), shouldStop (false)
{
if (createPipe)
{
pipeH = CreateNamedPipe (filename.toWideCharPointer(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, 0);
if (GetLastError() == ERROR_ALREADY_EXISTS)
closePipeHandle();
}
}
~Pimpl()
{
disconnectPipe();
if (pipeH != INVALID_HANDLE_VALUE)
CloseHandle (pipeH);
closePipeHandle();
CloseHandle (cancelEvent);
}
@@ -868,6 +869,16 @@ public:
}
}
void closePipeHandle()
{
if (pipeH != INVALID_HANDLE_VALUE)
{
disconnectPipe();
CloseHandle (pipeH);
pipeH = INVALID_HANDLE_VALUE;
}
}
int read (void* destBuffer, const int maxBytesToRead, const int timeOutMilliseconds)
{
while (connect (timeOutMilliseconds))


+ 1
- 1
source/modules/juce_core/system/juce_CompilerSupport.h View File

@@ -113,11 +113,11 @@
#if _MSC_VER >= 1800
#define JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS 1
#define JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES 1
#define JUCE_DELETED_FUNCTION = delete
#endif
#if _MSC_VER >= 1900
#define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1
#define JUCE_DELETED_FUNCTION = delete
#endif
#endif


+ 2
- 2
source/modules/juce_core/system/juce_PlatformDefs.h View File

@@ -63,8 +63,8 @@
//==============================================================================
#if JUCE_IOS || JUCE_LINUX || JUCE_ANDROID || JUCE_PPC
/** This will try to break into the debugger if the app is currently being debugged.
If called by an app that's not being debugged, the behaiour isn't defined - it may crash or not, depending
on the platform.
If called by an app that's not being debugged, the behaviour isn't defined - it may
crash or not, depending on the platform.
@see jassert()
*/
#define juce_breakDebugger { ::kill (0, SIGTRAP); }


+ 2
- 2
source/modules/juce_core/zip/juce_ZipFile.cpp View File

@@ -328,7 +328,7 @@ void ZipFile::sortEntriesByFilename()
//==============================================================================
void ZipFile::init()
{
ScopedPointer <InputStream> toDelete;
ScopedPointer<InputStream> toDelete;
InputStream* in = inputStream;
if (inputSource != nullptr)
@@ -358,7 +358,7 @@ void ZipFile::init()
if (pos + 46 > size)
break;
const char* const buffer = static_cast <const char*> (headerData.getData()) + pos;
const char* const buffer = static_cast<const char*> (headerData.getData()) + pos;
const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28);


+ 16
- 10
source/modules/juce_core/zip/juce_ZipFile.h View File

@@ -40,7 +40,7 @@
class JUCE_API ZipFile
{
public:
/** Creates a ZipFile based for a file. */
/** Creates a ZipFile to read a specific file. */
explicit ZipFile (const File& file);
//==============================================================================
@@ -91,15 +91,12 @@ public:
int getNumEntries() const noexcept;
/** Returns a structure that describes one of the entries in the zip file.
This may return zero if the index is out of range.
@see ZipFile::ZipEntry
*/
const ZipEntry* getEntry (int index) const noexcept;
/** Returns the index of the first entry with a given filename.
This uses a case-sensitive comparison to look for a filename in the
list of entries. It might return -1 if no match is found.
@@ -116,8 +113,7 @@ public:
*/
const ZipEntry* getEntry (const String& fileName) const noexcept;
/** Sorts the list of entries, based on the filename.
*/
/** Sorts the list of entries, based on the filename. */
void sortEntriesByFilename();
//==============================================================================
@@ -128,6 +124,11 @@ public:
The stream must not be used after the ZipFile object that created
has been deleted.
Note that if the ZipFile was created with a user-supplied InputStream object,
then all the streams which are created by this method will by trying to share
the same source stream, so cannot be safely used on multiple threads! (But if
you create the ZipFile from a File or InputSource, then it is safe to do this).
*/
InputStream* createStreamForEntry (int index);
@@ -138,6 +139,11 @@ public:
The stream must not be used after the ZipFile object that created
has been deleted.
Note that if the ZipFile was created with a user-supplied InputStream object,
then all the streams which are created by this method will by trying to share
the same source stream, so cannot be safely used on multiple threads! (But if
you create the ZipFile from a File or InputSource, then it is safe to do this).
*/
InputStream* createStreamForEntry (const ZipEntry& entry);
@@ -194,7 +200,7 @@ public:
will be stored for this file.
*/
void addFile (const File& fileToAdd, int compressionLevel,
const String& storedPathName = String::empty);
const String& storedPathName = String());
/** Adds a file while should be added to the archive.
@@ -233,11 +239,11 @@ private:
friend class ZipInputStream;
friend class ZipEntryHolder;
OwnedArray <ZipEntryHolder> entries;
OwnedArray<ZipEntryHolder> entries;
CriticalSection lock;
InputStream* inputStream;
ScopedPointer <InputStream> streamToDelete;
ScopedPointer <InputSource> inputSource;
ScopedPointer<InputStream> streamToDelete;
ScopedPointer<InputSource> inputSource;
#if JUCE_DEBUG
struct OpenStreamCounter


+ 5
- 1
source/modules/juce_graphics/fonts/juce_Font.h View File

@@ -279,8 +279,12 @@ public:
//==============================================================================
/** Makes the font bold or non-bold. */
void setBold (bool shouldBeBold);
/** Returns a copy of this font with the bold attribute set. */
/** Returns a copy of this font with the bold attribute set.
If the font does not have a bold version, this will return the default font.
*/
Font boldened() const;
/** Returns true if the font is bold. */
bool isBold() const noexcept;


+ 2
- 0
source/modules/juce_gui_basics/application/juce_Application.h View File

@@ -111,11 +111,13 @@ public:
static JUCEApplication* JUCE_CALLTYPE getInstance() noexcept;
//==============================================================================
#if DOXYGEN
/** Returns the application's name. */
virtual const String getApplicationName() = 0;
/** Returns the application's version number. */
virtual const String getApplicationVersion() = 0;
#endif
/** Checks whether multiple instances of the app are allowed.


+ 2
- 2
source/modules/juce_gui_basics/components/juce_Component.h View File

@@ -443,7 +443,7 @@ public:
/** Changes the component's position and size.
The coordinates are relative to the top-left of the component's parent, or relative
to the origin of the screen is the component is on the desktop.
to the origin of the screen if the component is on the desktop.
If this method changes the component's top-left position, it will make a synchronous
call to moved(). If it changes the size, it will also make a call to resized().
@@ -459,7 +459,7 @@ public:
/** Changes the component's position and size.
The coordinates are relative to the top-left of the component's parent, or relative
to the origin of the screen is the component is on the desktop.
to the origin of the screen if the component is on the desktop.
If this method changes the component's top-left position, it will make a synchronous
call to moved(). If it changes the size, it will also make a call to resized().


+ 0
- 2
source/modules/juce_gui_basics/components/juce_Desktop.cpp View File

@@ -333,7 +333,6 @@ bool operator!= (const Desktop::Displays::Display& d1, const Desktop::Displays::
void Desktop::Displays::init (Desktop& desktop)
{
findDisplays (desktop.getGlobalScaleFactor());
jassert (displays.size() > 0);
}
void Desktop::Displays::refresh()
@@ -342,7 +341,6 @@ void Desktop::Displays::refresh()
oldDisplays.swapWith (displays);
init (Desktop::getInstance());
jassert (displays.size() > 0);
if (oldDisplays != displays)
{


+ 4
- 4
source/modules/juce_gui_basics/drawables/juce_SVGParser.cpp View File

@@ -272,7 +272,7 @@ public:
if (parseNextNumber (d, num, false))
{
const float angle = num.getFloatValue() * (180.0f / float_Pi);
const float angle = degreesToRadians (num.getFloatValue());
if (parseNextNumber (d, num, false))
{
@@ -1221,15 +1221,15 @@ private:
}
else if (t.startsWithIgnoreCase ("rotate"))
{
trans = AffineTransform::rotation (numbers[0] / (180.0f / float_Pi), numbers[1], numbers[2]);
trans = AffineTransform::rotation (degreesToRadians (numbers[0]), numbers[1], numbers[2]);
}
else if (t.startsWithIgnoreCase ("skewX"))
{
trans = AffineTransform::shear (std::tan (numbers[0] * (float_Pi / 180.0f)), 0.0f);
trans = AffineTransform::shear (std::tan (degreesToRadians (numbers[0])), 0.0f);
}
else if (t.startsWithIgnoreCase ("skewY"))
{
trans = AffineTransform::shear (0.0f, std::tan (numbers[0] * (float_Pi / 180.0f)));
trans = AffineTransform::shear (0.0f, std::tan (degreesToRadians (numbers[0])));
}
result = trans.followedBy (result);


+ 7
- 6
source/modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h View File

@@ -85,12 +85,6 @@ struct TextEditorKeyMapper
if (key.isKeyCode (KeyPress::pageDownKey)) return target.pageDown (isShiftDown);
}
if (numCtrlAltCommandKeys < 2)
{
if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown);
if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown);
}
if (key == KeyPress ('c', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0))
return target.copyToClipboard();
@@ -103,6 +97,13 @@ struct TextEditorKeyMapper
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
return target.pasteFromClipboard();
// NB: checking for delete must happen after the earlier check for shift + delete
if (numCtrlAltCommandKeys < 2)
{
if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown);
if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown);
}
if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
return target.selectAll();


+ 6
- 0
source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp View File

@@ -490,6 +490,12 @@ int LookAndFeel_V2::getAlertWindowButtonHeight()
return 28;
}
Font LookAndFeel_V2::getAlertWindowTitleFont()
{
Font messageFont = getAlertWindowMessageFont();
return messageFont.withHeight (messageFont.getHeight() * 1.1f).boldened();
}
Font LookAndFeel_V2::getAlertWindowMessageFont()
{
return Font (15.0f);


+ 15
- 0
source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h View File

@@ -67,7 +67,22 @@ public:
void drawAlertBox (Graphics&, AlertWindow&, const Rectangle<int>& textArea, TextLayout&) override;
int getAlertBoxWindowFlags() override;
int getAlertWindowButtonHeight() override;
/** Override this function to supply a custom font for the alert window title.
This default implementation will use a boldened and slightly larger version
of the alert window message font.
@see getAlertWindowMessageFont.
*/
Font getAlertWindowTitleFont() override;
/** Override this function to supply a custom font for the alert window message.
This default implementation will use the default font with height set to 15.0f.
@see getAlertWindowTitleFont
*/
Font getAlertWindowMessageFont() override;
Font getAlertWindowFont() override;
//==============================================================================


+ 3
- 3
source/modules/juce_gui_basics/menus/juce_PopupMenu.cpp View File

@@ -1219,7 +1219,7 @@ public:
getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());
}
void getIdealSize (int& idealWidth, int& idealHeight)
void getIdealSize (int& idealWidth, int& idealHeight) override
{
getLookAndFeel().getIdealPopupMenuItemSize (getName(), false, -1, idealWidth, idealHeight);
idealHeight += idealHeight / 2;
@@ -1698,9 +1698,9 @@ void PopupMenu::CustomComponent::setHighlighted (bool shouldBeHighlighted)
void PopupMenu::CustomComponent::triggerMenuItem()
{
if (HelperClasses::ItemComponent* const mic = dynamic_cast<HelperClasses::ItemComponent*> (getParentComponent()))
if (HelperClasses::ItemComponent* const mic = findParentComponentOfClass<HelperClasses::ItemComponent>())
{
if (HelperClasses::MenuWindow* const pmw = dynamic_cast<HelperClasses::MenuWindow*> (mic->getParentComponent()))
if (HelperClasses::MenuWindow* const pmw = mic->findParentComponentOfClass<HelperClasses::MenuWindow>())
{
pmw->dismissMenu (&mic->itemInfo);
}


+ 1
- 1
source/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp View File

@@ -135,7 +135,7 @@ static void addZenityArgs (StringArray& args, String& separator,
tokens.addTokens (filters, ";,|", "\"");
for (int i = 0; i < tokens.size(); ++i)
args.add ("--file-filter='" + tokens[i] + "'");
args.add ("--file-filter=" + tokens[i]);
}
if (file.isDirectory())


+ 42
- 0
source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp View File

@@ -1881,6 +1881,9 @@ public:
{
if (LinuxComponentPeer* const otherPeer = dynamic_cast<LinuxComponentPeer*> (other))
{
if (otherPeer->styleFlags & windowIsTemporary)
return;
setMinimised (false);
Window newStack[] = { otherPeer->windowH, windowH };
@@ -2320,6 +2323,10 @@ public:
XEvent nextEvent;
ScopedXLock xlock;
// if we have opengl contexts then just repaint them all
// regardless if this is really necessary
repaintOpenGLContexts ();
if (exposeEvent.window != windowH)
{
Window child;
@@ -2509,6 +2516,28 @@ public:
return currentScaleFactor;
}
//===============================================================================
void addOpenGLRepaintListener (Component* dummy)
{
if (dummy != nullptr)
glRepaintListeners.addIfNotAlreadyThere (dummy);
}
void removeOpenGLRepaintListener (Component* dummy)
{
if (dummy != nullptr)
glRepaintListeners.removeAllInstancesOf (dummy);
}
void repaintOpenGLContexts()
{
for (int i = 0; i < glRepaintListeners.size(); ++i)
{
if (Component* c = glRepaintListeners [i])
c->handleCommandMessage (0);
}
}
//==============================================================================
bool dontRepaint;
@@ -2668,6 +2697,7 @@ private:
BorderSize<int> windowBorder;
bool isAlwaysOnTop;
double currentScaleFactor;
Array<Component*> glRepaintListeners;
enum { KeyPressEventType = 2 };
struct MotifWmHints
@@ -4125,6 +4155,18 @@ Rectangle<int> juce_LinuxScaledToPhysicalBounds(ComponentPeer* peer, const Recta
return retval;
}
void juce_LinuxAddRepaintListener (ComponentPeer* peer, Component* dummy)
{
if (LinuxComponentPeer* linuxPeer = dynamic_cast<LinuxComponentPeer*> (peer))
linuxPeer->addOpenGLRepaintListener (dummy);
}
void juce_LinuxRemoveRepaintListener (ComponentPeer* peer, Component* dummy)
{
if (LinuxComponentPeer* linuxPeer = dynamic_cast<LinuxComponentPeer*> (peer))
linuxPeer->removeOpenGLRepaintListener (dummy);
}
//==============================================================================
#if JUCE_MODAL_LOOPS_PERMITTED
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType iconType,


+ 2
- 4
source/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp View File

@@ -218,8 +218,6 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title_
info.customComponent->enterModalState();
}
const StringRef separatorTokens (";,|");
const size_t filterSpaceNumChars = 2048;
HeapBlock<WCHAR> filters;
filters.calloc (filterSpaceNumChars);
@@ -228,7 +226,7 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title_
((filterSpaceNumChars - 1) * sizeof (WCHAR) - bytesWritten));
for (int i = 0; i < filterSpaceNumChars; ++i)
if (separatorTokens.text.indexOf ((juce_wchar) filters[i]) >= 0)
if (filters[i] == '|')
filters[i] = 0;
OPENFILENAMEW of = { 0 };
@@ -255,7 +253,7 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title_
if (isSaveDialogue)
{
StringArray tokens;
tokens.addTokens (filter, separatorTokens, "\"'");
tokens.addTokens (filter, ";,", "\"'");
tokens.trim();
tokens.removeEmptyStrings();


+ 3
- 0
source/modules/juce_gui_basics/widgets/juce_TableListBox.h View File

@@ -56,6 +56,9 @@ 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.
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 paintRowBackground (Graphics&,
int rowNumber,


+ 11
- 9
source/modules/juce_gui_basics/windows/juce_AlertWindow.cpp View File

@@ -343,22 +343,24 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
const int titleH = 24;
const int iconWidth = 80;
const Font font (getLookAndFeel().getAlertWindowMessageFont());
LookAndFeel& lookAndFeel = getLookAndFeel();
const int wid = jmax (font.getStringWidth (text),
font.getStringWidth (getName()));
const Font messageFont (lookAndFeel.getAlertWindowMessageFont());
const int sw = (int) std::sqrt (font.getHeight() * wid);
const int wid = jmax (messageFont.getStringWidth (text),
messageFont.getStringWidth (getName()));
const int sw = (int) std::sqrt (messageFont.getHeight() * wid);
int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f));
const int edgeGap = 10;
const int labelHeight = 18;
int iconSpace = 0;
AttributedString attributedText;
attributedText.append (getName(), font.withHeight (font.getHeight() * 1.1f).boldened());
attributedText.append (getName(), lookAndFeel.getAlertWindowTitleFont());
if (text.isNotEmpty())
attributedText.append ("\n\n" + text, font);
attributedText.append ("\n\n" + text, messageFont);
attributedText.setColour (findColour (textColourId));
@@ -383,18 +385,18 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
int buttonW = 40;
for (int i = 0; i < buttons.size(); ++i)
buttonW += 16 + buttons.getUnchecked(i)->getWidth();
buttonW += 16 + buttons.getUnchecked (i)->getWidth();
w = jmax (buttonW, w);
h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50;
if (buttons.size() > 0)
h += 20 + buttons.getUnchecked(0)->getHeight();
h += 20 + buttons.getUnchecked (0)->getHeight();
for (int i = customComps.size(); --i >= 0;)
{
Component* c = customComps.getUnchecked(i);
Component* c = customComps.getUnchecked (i);
w = jmax (w, (c->getWidth() * 100) / 80);
h += 10 + c->getHeight();


+ 1
- 0
source/modules/juce_gui_basics/windows/juce_AlertWindow.h View File

@@ -437,6 +437,7 @@ public:
virtual int getAlertWindowButtonHeight() = 0;
virtual Font getAlertWindowTitleFont() = 0;
virtual Font getAlertWindowMessageFont() = 0;
virtual Font getAlertWindowFont() = 0;
};


Loading…
Cancel
Save