From 49320b25d2d3dcb705de513d8f2f29dcade63eed Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 22 Mar 2010 17:25:45 +0000 Subject: [PATCH] iPhone on-screen keyboard support, when a TextEditor or CodeEditor is focused. --- .../components/jucer_TabbedComponentHandler.h | 2 +- .../model/components/jucer_ViewportHandler.h | 2 +- .../paintelements/jucer_ColouredElement.cpp | 4 +- .../paintelements/jucer_PaintElementImage.h | 2 +- .../jucer_PaintElementRoundedRectangle.h | 2 +- juce_amalgamated.cpp | 201 ++++++++++++++---- juce_amalgamated.h | 36 +++- .../juce_FlacAudioFormat.cpp | 38 ++-- .../juce_OggVorbisAudioFormat.cpp | 8 +- src/containers/juce_Variant.h | 14 +- src/core/juce_Atomic.h | 5 + src/core/juce_ByteOrder.h | 5 + src/core/juce_PlatformUtilities.h | 5 + src/core/juce_SystemStats.h | 5 + .../components/controls/juce_TextEditor.cpp | 12 +- .../components/windows/juce_TooltipWindow.cpp | 3 +- .../image_file_formats/juce_JPEGLoader.cpp | 3 + .../image_file_formats/juce_PNGLoader.cpp | 26 +-- .../mac/juce_iphone_UIViewComponentPeer.mm | 114 +++++++++- src/text/juce_StringArray.h | 2 +- 20 files changed, 375 insertions(+), 114 deletions(-) diff --git a/extras/the jucer/src/model/components/jucer_TabbedComponentHandler.h b/extras/the jucer/src/model/components/jucer_TabbedComponentHandler.h index 9d10ae27cb..cbadc76069 100644 --- a/extras/the jucer/src/model/components/jucer_TabbedComponentHandler.h +++ b/extras/the jucer/src/model/components/jucer_TabbedComponentHandler.h @@ -597,7 +597,7 @@ private: T("Change TabComponent tab depth")); } - const double getValue() const + double getValue() const { return component->getTabBarDepth(); } diff --git a/extras/the jucer/src/model/components/jucer_ViewportHandler.h b/extras/the jucer/src/model/components/jucer_ViewportHandler.h index 1ab77751aa..34551eb488 100644 --- a/extras/the jucer/src/model/components/jucer_ViewportHandler.h +++ b/extras/the jucer/src/model/components/jucer_ViewportHandler.h @@ -396,7 +396,7 @@ private: T("Change Viewport scrollbar size")); } - const double getValue() const + double getValue() const { return component->getScrollBarThickness(); } diff --git a/extras/the jucer/src/model/paintelements/jucer_ColouredElement.cpp b/extras/the jucer/src/model/paintelements/jucer_ColouredElement.cpp index 70bd41d1d0..792ea5b085 100644 --- a/extras/the jucer/src/model/paintelements/jucer_ColouredElement.cpp +++ b/extras/the jucer/src/model/paintelements/jucer_ColouredElement.cpp @@ -330,7 +330,7 @@ public: true); } - const double getValue() const { return owner->getStrokeType().stroke.getStrokeThickness(); } + double getValue() const { return owner->getStrokeType().stroke.getStrokeThickness(); } void changeListenerCallback (void*) { refresh(); } @@ -586,7 +586,7 @@ public: } } - const double getValue() const + double getValue() const { if (isForStroke) return element->getStrokeType().fill.imageOpacity; diff --git a/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h b/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h index ed015a507e..85c96142bb 100644 --- a/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h +++ b/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h @@ -449,7 +449,7 @@ private: element->setOpacity (newValue, true); } - const double getValue() const + double getValue() const { return element->getOpacity(); } diff --git a/extras/the jucer/src/model/paintelements/jucer_PaintElementRoundedRectangle.h b/extras/the jucer/src/model/paintelements/jucer_PaintElementRoundedRectangle.h index d2db43d7e3..690285beb3 100644 --- a/extras/the jucer/src/model/paintelements/jucer_PaintElementRoundedRectangle.h +++ b/extras/the jucer/src/model/paintelements/jucer_PaintElementRoundedRectangle.h @@ -227,7 +227,7 @@ private: owner->setCornerSize (newValue, true); } - const double getValue() const { return owner->getCornerSize(); } + double getValue() const { return owner->getCornerSize(); } void changeListenerCallback (void*) { refresh(); } diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 26f23438c2..7d5addbdb4 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -52245,6 +52245,12 @@ void TextEditor::insertTextAtCaret (const String& newText_) if (allowedCharacters.isNotEmpty()) newText = newText.retainCharacters (allowedCharacters); + if ((! returnKeyStartsNewLine) && newText == T("\n")) + { + returnPressed(); + return; + } + if (! isMultiLine()) newText = newText.replaceCharacters (T("\r\n"), T(" ")); else @@ -52658,11 +52664,7 @@ bool TextEditor::keyPressed (const KeyPress& key) else if (key == KeyPress::returnKey) { newTransaction(); - - if (returnKeyStartsNewLine) - insertTextAtCaret (T("\n")); - else - returnPressed(); + insertTextAtCaret (T("\n")); } else if (key.isKeyCode (KeyPress::escapeKey)) { @@ -77406,7 +77408,8 @@ TooltipWindow::TooltipWindow (Component* const parentComponent, lastComponentUnderMouse (0), changedCompsSinceShown (true) { - startTimer (123); + if (Desktop::getInstance().getMainMouseSource().canHover()) + startTimer (123); setAlwaysOnTop (true); setOpaque (true); @@ -114411,6 +114414,9 @@ void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L) #endif } +#undef max +#undef min + #ifdef _MSC_VER #pragma warning (pop) #endif @@ -114418,7 +114424,7 @@ void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L) BEGIN_JUCE_NAMESPACE static const char* const flacFormatName = "FLAC file"; -static const tchar* const flacExtensions[] = { T(".flac"), 0 }; +static const juce_wchar* const flacExtensions[] = { T(".flac"), 0 }; class FlacReader : public AudioFormatReader { @@ -114580,34 +114586,34 @@ public: static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[], size_t* bytes, void* client_data) { using namespace FlacNamespace; - *bytes = (unsigned int) ((const FlacReader*) client_data)->input->read (buffer, (int) *bytes); + *bytes = (size_t) static_cast (client_data)->input->read (buffer, (int) *bytes); return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset, void* client_data) { using namespace FlacNamespace; - ((const FlacReader*) client_data)->input->setPosition ((int) absolute_byte_offset); + static_cast (client_data)->input->setPosition ((int) absolute_byte_offset); return FLAC__STREAM_DECODER_SEEK_STATUS_OK; } static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data) { using namespace FlacNamespace; - *absolute_byte_offset = ((const FlacReader*) client_data)->input->getPosition(); + *absolute_byte_offset = static_cast (client_data)->input->getPosition(); return FLAC__STREAM_DECODER_TELL_STATUS_OK; } static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length, void* client_data) { using namespace FlacNamespace; - *stream_length = ((const FlacReader*) client_data)->input->getTotalLength(); + *stream_length = static_cast (client_data)->input->getTotalLength(); return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; } static FlacNamespace::FLAC__bool eofCallback_ (const FlacNamespace::FLAC__StreamDecoder*, void* client_data) { - return ((const FlacReader*) client_data)->input->isExhausted(); + return static_cast (client_data)->input->isExhausted(); } static FlacNamespace::FLAC__StreamDecoderWriteStatus writeCallback_ (const FlacNamespace::FLAC__StreamDecoder*, @@ -114616,7 +114622,7 @@ public: void* client_data) { using namespace FlacNamespace; - ((FlacReader*) client_data)->useSamples (buffer, frame->header.blocksize); + static_cast (client_data)->useSamples (buffer, frame->header.blocksize); return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } @@ -114624,7 +114630,7 @@ public: const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data) { - ((FlacReader*) client_data)->useMetadata (metadata->data.stream_info); + static_cast (client_data)->useMetadata (metadata->data.stream_info); } static void errorCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__StreamDecoderErrorStatus, void*) @@ -114780,7 +114786,7 @@ public: void* client_data) { using namespace FlacNamespace; - return ((FlacWriter*) client_data)->writeData (buffer, (int) bytes) + return static_cast (client_data)->writeData (buffer, (int) bytes) ? FLAC__STREAM_ENCODER_WRITE_STATUS_OK : FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; } @@ -114797,15 +114803,13 @@ public: if (client_data == 0) return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; - *absolute_byte_offset = (FLAC__uint64) ((FlacWriter*) client_data)->output->getPosition(); + *absolute_byte_offset = (FLAC__uint64) static_cast (client_data)->output->getPosition(); return FLAC__STREAM_ENCODER_TELL_STATUS_OK; } - static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, - const FlacNamespace::FLAC__StreamMetadata* metadata, - void* client_data) + static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data) { - ((FlacWriter*) client_data)->writeMetaData (metadata); + static_cast (client_data)->writeMetaData (metadata); } juce_UseDebuggingNewOperator @@ -114821,7 +114825,7 @@ private: }; FlacAudioFormat::FlacAudioFormat() - : AudioFormat (TRANS (flacFormatName), (const tchar**) flacExtensions) + : AudioFormat (TRANS (flacFormatName), (const juce_wchar**) flacExtensions) { } @@ -114859,7 +114863,7 @@ bool FlacAudioFormat::isCompressed() AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails) { - ScopedPointer r (new FlacReader (in)); + ScopedPointer r (new FlacReader (in)); if (r->sampleRate != 0) return r.release(); @@ -114879,10 +114883,7 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out, { if (getPossibleBitDepths().contains (bitsPerSample)) { - ScopedPointer w (new FlacWriter (out, - sampleRate, - numberOfChannels, - bitsPerSample)); + ScopedPointer w (new FlacWriter (out, sampleRate, numberOfChannels, bitsPerSample)); if (w->ok) return w.release(); @@ -171166,10 +171167,13 @@ void _vorbis_apply_window(float *d,int *winno,long *blocksizes, #endif } +#undef max +#undef min + BEGIN_JUCE_NAMESPACE static const char* const oggFormatName = "Ogg-Vorbis file"; -static const tchar* const oggExtensions[] = { T(".ogg"), 0 }; +static const juce_wchar* const oggExtensions[] = { T(".ogg"), 0 }; class OggReader : public AudioFormatReader { @@ -171471,7 +171475,7 @@ public: }; OggVorbisAudioFormat::OggVorbisAudioFormat() - : AudioFormat (TRANS (oggFormatName), (const tchar**) oggExtensions) + : AudioFormat (TRANS (oggFormatName), (const juce_wchar**) oggExtensions) { } @@ -188337,6 +188341,9 @@ jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, #endif } +#undef max +#undef min + #if JUCE_MSVC #pragma warning (pop) #endif @@ -210929,6 +210936,9 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) #endif } +#undef max +#undef min + #ifdef _MSC_VER #pragma warning (pop) #endif @@ -210943,11 +210953,14 @@ namespace PNGHelpers { using namespace pnglibNamespace; - static void readCallback (png_structp pngReadStruct, png_bytep data, png_size_t length) + static void readCallback (png_structp png, png_bytep data, png_size_t length) { - using namespace pnglibNamespace; - InputStream* const in = (InputStream*) png_get_io_ptr (pngReadStruct); - in->read (data, (int) length); + static_cast (png->io_ptr)->read (data, (int) length); + } + + static void writeDataCallback (png_structp png, png_bytep data, png_size_t length) + { + static_cast (png->io_ptr)->write (data, (int) length); } struct PNGErrorStruct {}; @@ -210956,17 +210969,6 @@ namespace PNGHelpers { throw PNGErrorStruct(); } - - static void writeDataCallback (png_structp png_ptr, png_bytep data, png_size_t length) - { - OutputStream* const out = (OutputStream*) png_ptr->io_ptr; - - const bool ok = out->write (data, (int) length); - - (void) ok; - jassert (ok); - } - } Image* juce_loadPNGImageFromStream (InputStream& in) @@ -240405,10 +240407,11 @@ END_JUCE_NAMESPACE #define JuceUIView MakeObjCClassName(JuceUIView) -@interface JuceUIView : UIView +@interface JuceUIView : UIView { @public UIViewComponentPeer* owner; + UITextField *hiddenTextField; } - (JuceUIView*) initWithOwner: (UIViewComponentPeer*) owner withFrame: (CGRect) frame; @@ -240427,6 +240430,9 @@ END_JUCE_NAMESPACE - (void) asyncRepaint: (id) rect; +- (BOOL) textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString*) string; +- (BOOL) textFieldShouldClear: (UITextField*) textField; +- (BOOL) textFieldShouldReturn: (UITextField*) textField; @end #define JuceUIWindow MakeObjCClassName(JuceUIWindow) @@ -240444,7 +240450,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -class UIViewComponentPeer : public ComponentPeer +class UIViewComponentPeer : public ComponentPeer, + public FocusChangeListener { public: UIViewComponentPeer (Component* const component, @@ -240490,6 +240497,12 @@ public: void grabFocus(); void textInputRequired (const Point& position); + virtual BOOL textFieldReplaceCharacters (const Range& range, const String& text); + virtual BOOL textFieldShouldClear(); + virtual BOOL textFieldShouldReturn(); + void updateHiddenTextContent (TextInputTarget* target); + void globalFocusChanged (Component*); + void handleTouches (UIEvent* e, bool isDown, bool isUp, bool isCancel); void repaint (int x, int y, int w, int h); @@ -240521,11 +240534,18 @@ END_JUCE_NAMESPACE [super initWithFrame: frame]; owner = owner_; + hiddenTextField = [[UITextField alloc] initWithFrame: CGRectMake (0, 0, 0, 0)]; + [self addSubview: hiddenTextField]; + hiddenTextField.delegate = self; + return self; } - (void) dealloc { + [hiddenTextField removeFromSuperview]; + [hiddenTextField release]; + [super dealloc]; } @@ -240607,6 +240627,22 @@ JUCE_NAMESPACE::Point juce_lastMousePos; [self setNeedsDisplayInRect: *r]; } +- (BOOL) textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString*) text +{ + return owner->textFieldReplaceCharacters (Range (range.location, range.location + range.length), + nsStringToJuce (text)); +} + +- (BOOL) textFieldShouldClear: (UITextField*) textField +{ + return owner->textFieldShouldClear(); +} + +- (BOOL) textFieldShouldReturn: (UITextField*) textField +{ + return owner->textFieldShouldReturn(); +} + @end @implementation JuceUIWindow @@ -240679,10 +240715,14 @@ UIViewComponentPeer::UIViewComponentPeer (Component* const component, } setTitle (component->getName()); + + Desktop::getInstance().addFocusChangeListener (this); } UIViewComponentPeer::~UIViewComponentPeer() { + Desktop::getInstance().removeFocusChangeListener (this); + view->owner = 0; [view removeFromSuperview]; [view release]; @@ -241029,6 +241069,77 @@ void UIViewComponentPeer::textInputRequired (const Point&) { } +void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target) +{ + view->hiddenTextField.text = juceStringToNS (target->getTextInRange (Range (0, target->getHighlightedRegion().getStart()))); +} + +BOOL UIViewComponentPeer::textFieldReplaceCharacters (const Range& range, const String& text) +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + const Range currentSelection (target->getHighlightedRegion()); + + if (range.getLength() == 1 && text.isEmpty()) // (detect backspace) + if (currentSelection.isEmpty()) + target->setHighlightedRegion (currentSelection.withStart (currentSelection.getStart() - 1)); + + target->insertTextAtCaret (text); + updateHiddenTextContent (target); + } + + return NO; +} + +BOOL UIViewComponentPeer::textFieldShouldClear() +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + target->setHighlightedRegion (Range (0, std::numeric_limits::max())); + target->insertTextAtCaret (String::empty); + updateHiddenTextContent (target); + } + + return YES; +} + +BOOL UIViewComponentPeer::textFieldShouldReturn() +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + target->insertTextAtCaret (T("\n")); + updateHiddenTextContent (target); + } + + return YES; +} + +void UIViewComponentPeer::globalFocusChanged (Component*) +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + Component* comp = dynamic_cast (target); + + Point pos (comp->relativePositionToOtherComponent (component, Point())); + view->hiddenTextField.frame = CGRectMake (pos.getX(), pos.getY(), 0, 0); + + updateHiddenTextContent (target); + [view->hiddenTextField becomeFirstResponder]; + } + else + { + [view->hiddenTextField resignFirstResponder]; + } +} + void UIViewComponentPeer::drawRect (CGRect r) { if (r.size.width < 1.0f || r.size.height < 1.0f) diff --git a/juce_amalgamated.h b/juce_amalgamated.h index c73b34aeb1..27707a430c 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -875,6 +875,11 @@ public: static void bigEndian24BitToChars (int value, char* destBytes); static bool isBigEndian(); + +private: + ByteOrder(); + ByteOrder (const ByteOrder&); + ByteOrder& operator= (const ByteOrder&); }; #if JUCE_USE_INTRINSICS @@ -2891,13 +2896,13 @@ public: static const var null; var (const var& valueToCopy); - var (const int value) throw(); - var (const bool value) throw(); - var (const double value) throw(); - var (const char* const value); - var (const juce_wchar* const value); + var (int value) throw(); + var (bool value) throw(); + var (double value) throw(); + var (const char* value); + var (const juce_wchar* value); var (const String& value); - var (DynamicObject* const object); + var (DynamicObject* object); var (MethodFunction method) throw(); var& operator= (const var& valueToCopy); @@ -2937,7 +2942,7 @@ public: public: identifier() throw(); - identifier (const char* const name); + identifier (const char* name); identifier (const String& name); @@ -3075,6 +3080,11 @@ public: static int32 compareAndExchange (int32& destination, int32 newValue, int32 requiredCurrentValue); static void* swapPointers (void* volatile* value1, void* value2); + +private: + Atomic(); + Atomic (const Atomic&); + Atomic& operator= (const Atomic&); }; #if (JUCE_MAC || JUCE_IPHONE) // Mac and iPhone... @@ -3891,7 +3901,7 @@ public: inline int size() const throw() { return strings.size(); }; - const String& operator[] (const int index) const throw(); + const String& operator[] (int index) const throw(); bool contains (const String& stringToLookFor, bool ignoreCase = false) const; @@ -6967,6 +6977,11 @@ public: #if JUCE_LINUX || DOXYGEN #endif + +private: + PlatformUtilities(); + PlatformUtilities (const PlatformUtilities&); + PlatformUtilities& operator= (const PlatformUtilities&); }; #if JUCE_MAC || JUCE_IPHONE @@ -7342,6 +7357,11 @@ public: // not-for-public-use platform-specific method gets called at startup to initialise things. static void initialiseStats() throw(); + +private: + SystemStats(); + SystemStats (const SystemStats&); + SystemStats& operator= (const SystemStats&); }; #endif // __JUCE_SYSTEMSTATS_JUCEHEADER__ diff --git a/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp b/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp index e515d11b58..39a392b208 100644 --- a/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp @@ -70,6 +70,9 @@ namespace FlacNamespace #endif } +#undef max +#undef min + #ifdef _MSC_VER #pragma warning (pop) #endif @@ -83,7 +86,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== static const char* const flacFormatName = "FLAC file"; -static const tchar* const flacExtensions[] = { T(".flac"), 0 }; +static const juce_wchar* const flacExtensions[] = { T(".flac"), 0 }; //============================================================================== @@ -248,34 +251,34 @@ public: static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[], size_t* bytes, void* client_data) { using namespace FlacNamespace; - *bytes = (unsigned int) ((const FlacReader*) client_data)->input->read (buffer, (int) *bytes); + *bytes = (size_t) static_cast (client_data)->input->read (buffer, (int) *bytes); return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset, void* client_data) { using namespace FlacNamespace; - ((const FlacReader*) client_data)->input->setPosition ((int) absolute_byte_offset); + static_cast (client_data)->input->setPosition ((int) absolute_byte_offset); return FLAC__STREAM_DECODER_SEEK_STATUS_OK; } static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data) { using namespace FlacNamespace; - *absolute_byte_offset = ((const FlacReader*) client_data)->input->getPosition(); + *absolute_byte_offset = static_cast (client_data)->input->getPosition(); return FLAC__STREAM_DECODER_TELL_STATUS_OK; } static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length, void* client_data) { using namespace FlacNamespace; - *stream_length = ((const FlacReader*) client_data)->input->getTotalLength(); + *stream_length = static_cast (client_data)->input->getTotalLength(); return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; } static FlacNamespace::FLAC__bool eofCallback_ (const FlacNamespace::FLAC__StreamDecoder*, void* client_data) { - return ((const FlacReader*) client_data)->input->isExhausted(); + return static_cast (client_data)->input->isExhausted(); } static FlacNamespace::FLAC__StreamDecoderWriteStatus writeCallback_ (const FlacNamespace::FLAC__StreamDecoder*, @@ -284,7 +287,7 @@ public: void* client_data) { using namespace FlacNamespace; - ((FlacReader*) client_data)->useSamples (buffer, frame->header.blocksize); + static_cast (client_data)->useSamples (buffer, frame->header.blocksize); return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } @@ -292,7 +295,7 @@ public: const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data) { - ((FlacReader*) client_data)->useMetadata (metadata->data.stream_info); + static_cast (client_data)->useMetadata (metadata->data.stream_info); } static void errorCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__StreamDecoderErrorStatus, void*) @@ -452,7 +455,7 @@ public: void* client_data) { using namespace FlacNamespace; - return ((FlacWriter*) client_data)->writeData (buffer, (int) bytes) + return static_cast (client_data)->writeData (buffer, (int) bytes) ? FLAC__STREAM_ENCODER_WRITE_STATUS_OK : FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; } @@ -469,15 +472,13 @@ public: if (client_data == 0) return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; - *absolute_byte_offset = (FLAC__uint64) ((FlacWriter*) client_data)->output->getPosition(); + *absolute_byte_offset = (FLAC__uint64) static_cast (client_data)->output->getPosition(); return FLAC__STREAM_ENCODER_TELL_STATUS_OK; } - static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, - const FlacNamespace::FLAC__StreamMetadata* metadata, - void* client_data) + static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data) { - ((FlacWriter*) client_data)->writeMetaData (metadata); + static_cast (client_data)->writeMetaData (metadata); } juce_UseDebuggingNewOperator @@ -495,7 +496,7 @@ private: //============================================================================== FlacAudioFormat::FlacAudioFormat() - : AudioFormat (TRANS (flacFormatName), (const tchar**) flacExtensions) + : AudioFormat (TRANS (flacFormatName), (const juce_wchar**) flacExtensions) { } @@ -533,7 +534,7 @@ bool FlacAudioFormat::isCompressed() AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails) { - ScopedPointer r (new FlacReader (in)); + ScopedPointer r (new FlacReader (in)); if (r->sampleRate != 0) return r.release(); @@ -553,10 +554,7 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out, { if (getPossibleBitDepths().contains (bitsPerSample)) { - ScopedPointer w (new FlacWriter (out, - sampleRate, - numberOfChannels, - bitsPerSample)); + ScopedPointer w (new FlacWriter (out, sampleRate, numberOfChannels, bitsPerSample)); if (w->ok) return w.release(); diff --git a/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp b/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp index d92cd90b49..ffddd026d2 100644 --- a/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp @@ -72,6 +72,9 @@ namespace OggVorbisNamespace #endif } +#undef max +#undef min + BEGIN_JUCE_NAMESPACE #include "juce_OggVorbisAudioFormat.h" @@ -80,10 +83,9 @@ BEGIN_JUCE_NAMESPACE #include "../../io/files/juce_FileInputStream.h" #include "../../text/juce_LocalisedStrings.h" - //============================================================================== static const char* const oggFormatName = "Ogg-Vorbis file"; -static const tchar* const oggExtensions[] = { T(".ogg"), 0 }; +static const juce_wchar* const oggExtensions[] = { T(".ogg"), 0 }; //============================================================================== class OggReader : public AudioFormatReader @@ -393,7 +395,7 @@ public: //============================================================================== OggVorbisAudioFormat::OggVorbisAudioFormat() - : AudioFormat (TRANS (oggFormatName), (const tchar**) oggExtensions) + : AudioFormat (TRANS (oggFormatName), (const juce_wchar**) oggExtensions) { } diff --git a/src/containers/juce_Variant.h b/src/containers/juce_Variant.h index 1d21041194..8143a68776 100644 --- a/src/containers/juce_Variant.h +++ b/src/containers/juce_Variant.h @@ -59,13 +59,13 @@ public: static const var null; var (const var& valueToCopy); - var (const int value) throw(); - var (const bool value) throw(); - var (const double value) throw(); - var (const char* const value); - var (const juce_wchar* const value); + var (int value) throw(); + var (bool value) throw(); + var (double value) throw(); + var (const char* value); + var (const juce_wchar* value); var (const String& value); - var (DynamicObject* const object); + var (DynamicObject* object); var (MethodFunction method) throw(); var& operator= (const var& valueToCopy); @@ -119,7 +119,7 @@ public: Because this name may need to be used in contexts such as script variables or XML tags, it must only contain ascii letters and digits, or the underscore character. */ - identifier (const char* const name); + identifier (const char* name); /** Creates an identifier with a specified name. Because this name may need to be used in contexts such as script variables or XML diff --git a/src/core/juce_Atomic.h b/src/core/juce_Atomic.h index 9eb1557015..5a1e41e410 100644 --- a/src/core/juce_Atomic.h +++ b/src/core/juce_Atomic.h @@ -53,6 +53,11 @@ public: /** This atomically sets *value1 to be value2, and returns the previous value of *value1. */ static void* swapPointers (void* volatile* value1, void* value2); + +private: + Atomic(); + Atomic (const Atomic&); + Atomic& operator= (const Atomic&); }; diff --git a/src/core/juce_ByteOrder.h b/src/core/juce_ByteOrder.h index 424dd432b8..81663a6762 100644 --- a/src/core/juce_ByteOrder.h +++ b/src/core/juce_ByteOrder.h @@ -92,6 +92,11 @@ public: //============================================================================== /** Returns true if the current CPU is big-endian. */ static bool isBigEndian(); + +private: + ByteOrder(); + ByteOrder (const ByteOrder&); + ByteOrder& operator= (const ByteOrder&); }; diff --git a/src/core/juce_PlatformUtilities.h b/src/core/juce_PlatformUtilities.h index 6674d5f5e3..10f3fac91d 100644 --- a/src/core/juce_PlatformUtilities.h +++ b/src/core/juce_PlatformUtilities.h @@ -194,6 +194,11 @@ public: //============================================================================== #endif + +private: + PlatformUtilities(); + PlatformUtilities (const PlatformUtilities&); + PlatformUtilities& operator= (const PlatformUtilities&); }; diff --git a/src/core/juce_SystemStats.h b/src/core/juce_SystemStats.h index 8d9e10ba9c..c5e4efca33 100644 --- a/src/core/juce_SystemStats.h +++ b/src/core/juce_SystemStats.h @@ -189,6 +189,11 @@ public: //============================================================================== // not-for-public-use platform-specific method gets called at startup to initialise things. static void initialiseStats() throw(); + +private: + SystemStats(); + SystemStats (const SystemStats&); + SystemStats& operator= (const SystemStats&); }; diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index cfe1f6657c..52e058cdae 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -1585,6 +1585,12 @@ void TextEditor::insertTextAtCaret (const String& newText_) if (allowedCharacters.isNotEmpty()) newText = newText.retainCharacters (allowedCharacters); + if ((! returnKeyStartsNewLine) && newText == T("\n")) + { + returnPressed(); + return; + } + if (! isMultiLine()) newText = newText.replaceCharacters (T("\r\n"), T(" ")); else @@ -2002,11 +2008,7 @@ bool TextEditor::keyPressed (const KeyPress& key) else if (key == KeyPress::returnKey) { newTransaction(); - - if (returnKeyStartsNewLine) - insertTextAtCaret (T("\n")); - else - returnPressed(); + insertTextAtCaret (T("\n")); } else if (key.isKeyCode (KeyPress::escapeKey)) { diff --git a/src/gui/components/windows/juce_TooltipWindow.cpp b/src/gui/components/windows/juce_TooltipWindow.cpp index 3a388c83b9..5e83fa9c0b 100644 --- a/src/gui/components/windows/juce_TooltipWindow.cpp +++ b/src/gui/components/windows/juce_TooltipWindow.cpp @@ -46,7 +46,8 @@ TooltipWindow::TooltipWindow (Component* const parentComponent, lastComponentUnderMouse (0), changedCompsSinceShown (true) { - startTimer (123); + if (Desktop::getInstance().getMainMouseSource().canHover()) + startTimer (123); setAlwaysOnTop (true); setOpaque (true); diff --git a/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp b/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp index 01be8d64fc..9876d8626f 100644 --- a/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp +++ b/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp @@ -117,6 +117,9 @@ namespace jpeglibNamespace #endif } +#undef max +#undef min + #if JUCE_MSVC #pragma warning (pop) #endif diff --git a/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp b/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp index a857b4940d..890ec6af0c 100644 --- a/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp +++ b/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp @@ -90,13 +90,15 @@ namespace pnglibNamespace #endif } +#undef max +#undef min + #ifdef _MSC_VER #pragma warning (pop) #endif BEGIN_JUCE_NAMESPACE - #include "../juce_Image.h" #include "../../../../io/streams/juce_InputStream.h" #include "../../../../io/streams/juce_OutputStream.h" @@ -111,11 +113,14 @@ namespace PNGHelpers { using namespace pnglibNamespace; - static void readCallback (png_structp pngReadStruct, png_bytep data, png_size_t length) + static void readCallback (png_structp png, png_bytep data, png_size_t length) + { + static_cast (png->io_ptr)->read (data, (int) length); + } + + static void writeDataCallback (png_structp png, png_bytep data, png_size_t length) { - using namespace pnglibNamespace; - InputStream* const in = (InputStream*) png_get_io_ptr (pngReadStruct); - in->read (data, (int) length); + static_cast (png->io_ptr)->write (data, (int) length); } struct PNGErrorStruct {}; @@ -124,17 +129,6 @@ namespace PNGHelpers { throw PNGErrorStruct(); } - - static void writeDataCallback (png_structp png_ptr, png_bytep data, png_size_t length) - { - OutputStream* const out = (OutputStream*) png_ptr->io_ptr; - - const bool ok = out->write (data, (int) length); - - (void) ok; - jassert (ok); - } - } //============================================================================== diff --git a/src/native/mac/juce_iphone_UIViewComponentPeer.mm b/src/native/mac/juce_iphone_UIViewComponentPeer.mm index 5950c0020c..3474f6f153 100644 --- a/src/native/mac/juce_iphone_UIViewComponentPeer.mm +++ b/src/native/mac/juce_iphone_UIViewComponentPeer.mm @@ -34,10 +34,11 @@ END_JUCE_NAMESPACE #define JuceUIView MakeObjCClassName(JuceUIView) -@interface JuceUIView : UIView +@interface JuceUIView : UIView { @public UIViewComponentPeer* owner; + UITextField *hiddenTextField; } - (JuceUIView*) initWithOwner: (UIViewComponentPeer*) owner withFrame: (CGRect) frame; @@ -56,8 +57,12 @@ END_JUCE_NAMESPACE - (void) asyncRepaint: (id) rect; +- (BOOL) textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString*) string; +- (BOOL) textFieldShouldClear: (UITextField*) textField; +- (BOOL) textFieldShouldReturn: (UITextField*) textField; @end + //============================================================================== #define JuceUIWindow MakeObjCClassName(JuceUIWindow) @@ -75,7 +80,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE //============================================================================== -class UIViewComponentPeer : public ComponentPeer +class UIViewComponentPeer : public ComponentPeer, + public FocusChangeListener { public: UIViewComponentPeer (Component* const component, @@ -123,6 +129,12 @@ public: void grabFocus(); void textInputRequired (const Point& position); + virtual BOOL textFieldReplaceCharacters (const Range& range, const String& text); + virtual BOOL textFieldShouldClear(); + virtual BOOL textFieldShouldReturn(); + void updateHiddenTextContent (TextInputTarget* target); + void globalFocusChanged (Component*); + void handleTouches (UIEvent* e, bool isDown, bool isUp, bool isCancel); //============================================================================== @@ -157,11 +169,18 @@ END_JUCE_NAMESPACE [super initWithFrame: frame]; owner = owner_; + hiddenTextField = [[UITextField alloc] initWithFrame: CGRectMake (0, 0, 0, 0)]; + [self addSubview: hiddenTextField]; + hiddenTextField.delegate = self; + return self; } - (void) dealloc { + [hiddenTextField removeFromSuperview]; + [hiddenTextField release]; + [super dealloc]; } @@ -247,6 +266,22 @@ JUCE_NAMESPACE::Point juce_lastMousePos; [self setNeedsDisplayInRect: *r]; } +- (BOOL) textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString*) text +{ + return owner->textFieldReplaceCharacters (Range (range.location, range.location + range.length), + nsStringToJuce (text)); +} + +- (BOOL) textFieldShouldClear: (UITextField*) textField +{ + return owner->textFieldShouldClear(); +} + +- (BOOL) textFieldShouldReturn: (UITextField*) textField +{ + return owner->textFieldShouldReturn(); +} + @end //============================================================================== @@ -323,10 +358,14 @@ UIViewComponentPeer::UIViewComponentPeer (Component* const component, } setTitle (component->getName()); + + Desktop::getInstance().addFocusChangeListener (this); } UIViewComponentPeer::~UIViewComponentPeer() { + Desktop::getInstance().removeFocusChangeListener (this); + view->owner = 0; [view removeFromSuperview]; [view release]; @@ -676,6 +715,77 @@ void UIViewComponentPeer::textInputRequired (const Point&) { } +void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target) +{ + view->hiddenTextField.text = juceStringToNS (target->getTextInRange (Range (0, target->getHighlightedRegion().getStart()))); +} + +BOOL UIViewComponentPeer::textFieldReplaceCharacters (const Range& range, const String& text) +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + const Range currentSelection (target->getHighlightedRegion()); + + if (range.getLength() == 1 && text.isEmpty()) // (detect backspace) + if (currentSelection.isEmpty()) + target->setHighlightedRegion (currentSelection.withStart (currentSelection.getStart() - 1)); + + target->insertTextAtCaret (text); + updateHiddenTextContent (target); + } + + return NO; +} + +BOOL UIViewComponentPeer::textFieldShouldClear() +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + target->setHighlightedRegion (Range (0, std::numeric_limits::max())); + target->insertTextAtCaret (String::empty); + updateHiddenTextContent (target); + } + + return YES; +} + +BOOL UIViewComponentPeer::textFieldShouldReturn() +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + target->insertTextAtCaret (T("\n")); + updateHiddenTextContent (target); + } + + return YES; +} + +void UIViewComponentPeer::globalFocusChanged (Component*) +{ + TextInputTarget* const target = findCurrentTextInputTarget(); + + if (target != 0) + { + Component* comp = dynamic_cast (target); + + Point pos (comp->relativePositionToOtherComponent (component, Point())); + view->hiddenTextField.frame = CGRectMake (pos.getX(), pos.getY(), 0, 0); + + updateHiddenTextContent (target); + [view->hiddenTextField becomeFirstResponder]; + } + else + { + [view->hiddenTextField resignFirstResponder]; + } +} + //============================================================================== void UIViewComponentPeer::drawRect (CGRect r) diff --git a/src/text/juce_StringArray.h b/src/text/juce_StringArray.h index c44e117a1e..24b4328384 100644 --- a/src/text/juce_StringArray.h +++ b/src/text/juce_StringArray.h @@ -110,7 +110,7 @@ public: Obviously the reference returned shouldn't be stored for later use, as the string it refers to may disappear when the array changes. */ - const String& operator[] (const int index) const throw(); + const String& operator[] (int index) const throw(); /** Searches for a string in the array.