From e1e5018a91c76577763825f588c614acdf720c33 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Fri, 18 Mar 2011 11:37:04 +0000 Subject: [PATCH] New class: CaretComponent, which is created by the LookAndFeel. Fix for VST build on VC2005. --- Builds/Linux/Makefile | 6 + Builds/MacOSX/Juce.xcodeproj/project.pbxproj | 6 + Builds/VisualStudio2005/Juce.vcproj | 2 + Builds/VisualStudio2008/Juce.vcproj | 2 + Builds/VisualStudio2008_DLL/Juce.vcproj | 2 + Builds/VisualStudio2010/Juce.vcxproj | 2 + Builds/VisualStudio2010/Juce.vcxproj.filters | 6 + Builds/iOS/Juce.xcodeproj/project.pbxproj | 6 + Juce.jucer | 4 + amalgamation/juce_amalgamated_template.cpp | 1 + .../wrapper/VST/juce_VST_Wrapper.cpp | 17 + .../components/jucer_TextEditorHandler.h | 2 +- juce_amalgamated.cpp | 569 +++++++----------- juce_amalgamated.h | 78 ++- src/core/juce_StandardHeader.h | 2 +- .../code_editor/juce_CodeEditorComponent.cpp | 59 +- .../code_editor/juce_CodeEditorComponent.h | 5 +- src/gui/components/controls/juce_Label.cpp | 5 +- .../components/controls/juce_TextEditor.cpp | 153 ++--- src/gui/components/controls/juce_TextEditor.h | 12 +- .../keyboard/juce_CaretComponent.cpp | 69 +++ .../components/keyboard/juce_CaretComponent.h | 84 +++ .../lookandfeel/juce_LookAndFeel.cpp | 10 +- .../components/lookandfeel/juce_LookAndFeel.h | 3 + src/juce_app_includes.h | 3 + 25 files changed, 586 insertions(+), 522 deletions(-) create mode 100644 src/gui/components/keyboard/juce_CaretComponent.cpp create mode 100644 src/gui/components/keyboard/juce_CaretComponent.h diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index ec16d4193b..31585aeaee 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -163,6 +163,7 @@ OBJECTS := \ $(OBJDIR)/juce_FileTreeComponent_8cb2d3a3.o \ $(OBJDIR)/juce_ImagePreviewComponent_a108ea50.o \ $(OBJDIR)/juce_WildcardFileFilter_9337b18.o \ + $(OBJDIR)/juce_CaretComponent_26bf4433.o \ $(OBJDIR)/juce_KeyboardFocusTraverser_6325fc08.o \ $(OBJDIR)/juce_KeyListener_631ada24.o \ $(OBJDIR)/juce_KeyMappingEditorComponent_a0183a92.o \ @@ -1002,6 +1003,11 @@ $(OBJDIR)/juce_WildcardFileFilter_9337b18.o: ../../src/gui/components/filebrowse @echo "Compiling juce_WildcardFileFilter.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/juce_CaretComponent_26bf4433.o: ../../src/gui/components/keyboard/juce_CaretComponent.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling juce_CaretComponent.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/juce_KeyboardFocusTraverser_6325fc08.o: ../../src/gui/components/keyboard/juce_KeyboardFocusTraverser.cpp -@mkdir -p $(OBJDIR) @echo "Compiling juce_KeyboardFocusTraverser.cpp" diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index 767a7c7bfb..8e7f31d6ee 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -132,6 +132,7 @@ 0D91D36C2195315FE534F304 = { isa = PBXBuildFile; fileRef = A418FC3BDDBF1CE9F2903490; }; A1E82F70796B8611D7323247 = { isa = PBXBuildFile; fileRef = 949854EDE6B5B16CEFB6108F; }; BC1856E0B20406DDCE5EBF94 = { isa = PBXBuildFile; fileRef = 8A67B45A2BA1D19D1AC43315; }; + FF3A28F88174E10CB478931E = { isa = PBXBuildFile; fileRef = 912C419859C9C56BC96AA6FB; }; C39AE37828718E9A45589A24 = { isa = PBXBuildFile; fileRef = 5ABC6616473BA4791AA8101E; }; 4400B0595B35F919291C1A01 = { isa = PBXBuildFile; fileRef = 29A79478AE8567250972ED43; }; BB1DAC0CA8D7B3DEEDEE76C6 = { isa = PBXBuildFile; fileRef = 7F5A271EAB78C7CF8B2341DE; }; @@ -664,6 +665,8 @@ F39059E72B927A700010851B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ImagePreviewComponent.h; path = ../../src/gui/components/filebrowser/juce_ImagePreviewComponent.h; sourceTree = SOURCE_ROOT; }; 8A67B45A2BA1D19D1AC43315 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_WildcardFileFilter.cpp; path = ../../src/gui/components/filebrowser/juce_WildcardFileFilter.cpp; sourceTree = SOURCE_ROOT; }; ECDD0F8397F3EE4E7FA7ACCC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_WildcardFileFilter.h; path = ../../src/gui/components/filebrowser/juce_WildcardFileFilter.h; sourceTree = SOURCE_ROOT; }; + 912C419859C9C56BC96AA6FB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_CaretComponent.cpp; path = ../../src/gui/components/keyboard/juce_CaretComponent.cpp; sourceTree = SOURCE_ROOT; }; + 717295136FD426125079F78C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CaretComponent.h; path = ../../src/gui/components/keyboard/juce_CaretComponent.h; sourceTree = SOURCE_ROOT; }; 5ABC6616473BA4791AA8101E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_KeyboardFocusTraverser.cpp; path = ../../src/gui/components/keyboard/juce_KeyboardFocusTraverser.cpp; sourceTree = SOURCE_ROOT; }; F61C34EE417006881D0869F4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_KeyboardFocusTraverser.h; path = ../../src/gui/components/keyboard/juce_KeyboardFocusTraverser.h; sourceTree = SOURCE_ROOT; }; 29A79478AE8567250972ED43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_KeyListener.cpp; path = ../../src/gui/components/keyboard/juce_KeyListener.cpp; sourceTree = SOURCE_ROOT; }; @@ -1424,6 +1427,8 @@ 8A67B45A2BA1D19D1AC43315, ECDD0F8397F3EE4E7FA7ACCC ); name = filebrowser; sourceTree = ""; }; 558A664D5D1ECEC607F4775D = { isa = PBXGroup; children = ( + 912C419859C9C56BC96AA6FB, + 717295136FD426125079F78C, 5ABC6616473BA4791AA8101E, F61C34EE417006881D0869F4, 29A79478AE8567250972ED43, @@ -2149,6 +2154,7 @@ 0D91D36C2195315FE534F304, A1E82F70796B8611D7323247, BC1856E0B20406DDCE5EBF94, + FF3A28F88174E10CB478931E, C39AE37828718E9A45589A24, 4400B0595B35F919291C1A01, BB1DAC0CA8D7B3DEEDEE76C6, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index 718236acc0..60d72cbba9 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -525,6 +525,8 @@ + + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index fb049700b8..3d5b0f1950 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -525,6 +525,8 @@ + + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 5a932605aa..1d73cd4d26 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -527,6 +527,8 @@ + + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index ef5c42f028..d6f2eac146 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -246,6 +246,7 @@ + @@ -616,6 +617,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index e83bf457fd..edb03db9e5 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -598,6 +598,9 @@ Juce\Source\gui\components\filebrowser + + Juce\Source\gui\components\keyboard + Juce\Source\gui\components\keyboard @@ -1782,6 +1785,9 @@ Juce\Source\gui\components\filebrowser + + Juce\Source\gui\components\keyboard + Juce\Source\gui\components\keyboard diff --git a/Builds/iOS/Juce.xcodeproj/project.pbxproj b/Builds/iOS/Juce.xcodeproj/project.pbxproj index 6545f2ed28..b1c910ebc2 100644 --- a/Builds/iOS/Juce.xcodeproj/project.pbxproj +++ b/Builds/iOS/Juce.xcodeproj/project.pbxproj @@ -132,6 +132,7 @@ 0D91D36C2195315FE534F304 = { isa = PBXBuildFile; fileRef = A418FC3BDDBF1CE9F2903490; }; A1E82F70796B8611D7323247 = { isa = PBXBuildFile; fileRef = 949854EDE6B5B16CEFB6108F; }; BC1856E0B20406DDCE5EBF94 = { isa = PBXBuildFile; fileRef = 8A67B45A2BA1D19D1AC43315; }; + FF3A28F88174E10CB478931E = { isa = PBXBuildFile; fileRef = 912C419859C9C56BC96AA6FB; }; C39AE37828718E9A45589A24 = { isa = PBXBuildFile; fileRef = 5ABC6616473BA4791AA8101E; }; 4400B0595B35F919291C1A01 = { isa = PBXBuildFile; fileRef = 29A79478AE8567250972ED43; }; BB1DAC0CA8D7B3DEEDEE76C6 = { isa = PBXBuildFile; fileRef = 7F5A271EAB78C7CF8B2341DE; }; @@ -664,6 +665,8 @@ F39059E72B927A700010851B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ImagePreviewComponent.h; path = ../../src/gui/components/filebrowser/juce_ImagePreviewComponent.h; sourceTree = SOURCE_ROOT; }; 8A67B45A2BA1D19D1AC43315 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_WildcardFileFilter.cpp; path = ../../src/gui/components/filebrowser/juce_WildcardFileFilter.cpp; sourceTree = SOURCE_ROOT; }; ECDD0F8397F3EE4E7FA7ACCC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_WildcardFileFilter.h; path = ../../src/gui/components/filebrowser/juce_WildcardFileFilter.h; sourceTree = SOURCE_ROOT; }; + 912C419859C9C56BC96AA6FB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_CaretComponent.cpp; path = ../../src/gui/components/keyboard/juce_CaretComponent.cpp; sourceTree = SOURCE_ROOT; }; + 717295136FD426125079F78C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CaretComponent.h; path = ../../src/gui/components/keyboard/juce_CaretComponent.h; sourceTree = SOURCE_ROOT; }; 5ABC6616473BA4791AA8101E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_KeyboardFocusTraverser.cpp; path = ../../src/gui/components/keyboard/juce_KeyboardFocusTraverser.cpp; sourceTree = SOURCE_ROOT; }; F61C34EE417006881D0869F4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_KeyboardFocusTraverser.h; path = ../../src/gui/components/keyboard/juce_KeyboardFocusTraverser.h; sourceTree = SOURCE_ROOT; }; 29A79478AE8567250972ED43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_KeyListener.cpp; path = ../../src/gui/components/keyboard/juce_KeyListener.cpp; sourceTree = SOURCE_ROOT; }; @@ -1424,6 +1427,8 @@ 8A67B45A2BA1D19D1AC43315, ECDD0F8397F3EE4E7FA7ACCC ); name = filebrowser; sourceTree = ""; }; 558A664D5D1ECEC607F4775D = { isa = PBXGroup; children = ( + 912C419859C9C56BC96AA6FB, + 717295136FD426125079F78C, 5ABC6616473BA4791AA8101E, F61C34EE417006881D0869F4, 29A79478AE8567250972ED43, @@ -2153,6 +2158,7 @@ 0D91D36C2195315FE534F304, A1E82F70796B8611D7323247, BC1856E0B20406DDCE5EBF94, + FF3A28F88174E10CB478931E, C39AE37828718E9A45589A24, 4400B0595B35F919291C1A01, BB1DAC0CA8D7B3DEEDEE76C6, diff --git a/Juce.jucer b/Juce.jucer index a72368e3a6..ba30de1431 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -683,6 +683,10 @@ file="src/gui/components/filebrowser/juce_WildcardFileFilter.h"/> + + = 0 && wParam == WM_MOUSEWHEEL) { const MSLLHOOKSTRUCT& hs = *(MSLLHOOKSTRUCT*) lParam; @@ -226,6 +239,10 @@ namespace void registerMouseWheelHook() { + #ifndef WH_MOUSE_LL + #define WH_MOUSE_LL 14 + #endif + if (mouseHookUsers++ == 0) mouseWheelHook = SetWindowsHookEx (WH_MOUSE_LL, mouseWheelHookCallback, (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), 0); diff --git a/extras/the jucer/src/model/components/jucer_TextEditorHandler.h b/extras/the jucer/src/model/components/jucer_TextEditorHandler.h index 7dd6ed66a7..949f9b13f9 100644 --- a/extras/the jucer/src/model/components/jucer_TextEditorHandler.h +++ b/extras/the jucer/src/model/components/jucer_TextEditorHandler.h @@ -42,7 +42,7 @@ public: registerColour (TextEditor::highlightColourId, "highlight", "hilitecol"); registerColour (TextEditor::outlineColourId, "outline", "outlinecol"); registerColour (TextEditor::shadowColourId, "shadow", "shadowcol"); - registerColour (TextEditor::caretColourId, "caret", "caretcol"); + registerColour (CaretComponent::caretColourId, "caret", "caretcol"); } //============================================================================== diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 6add57b217..bf52f1459b 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -1754,7 +1754,7 @@ namespace TimeHelpers if (now >= 0 && now <= 0x793406fff) localtime_s (&result, &now); else - zeromem (&result, sizeof (result)); + zerostruct (result); #else result = *localtime (&now); #endif @@ -8999,8 +8999,7 @@ namespace SocketHelpers if (handle <= 0 || port <= 0) return false; - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); + struct sockaddr_in servTmpAddr = { 0 }; servTmpAddr.sin_family = PF_INET; servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); servTmpAddr.sin_port = htons ((uint16) port); @@ -9126,8 +9125,7 @@ namespace SocketHelpers const int portNumber, const int timeOutMillisecs) throw() { - struct addrinfo hints; - zerostruct (hints); + struct addrinfo hints = { 0 }; hints.ai_family = AF_UNSPEC; hints.ai_socktype = isDatagram ? SOCK_DGRAM : SOCK_STREAM; hints.ai_flags = AI_NUMERICSERV; @@ -9314,8 +9312,7 @@ bool StreamingSocket::createListener (const int newPortNumber, const String& loc portNumber = newPortNumber; isListener = true; - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); + struct sockaddr_in servTmpAddr = { 0 }; servTmpAddr.sin_family = PF_INET; servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); @@ -26609,7 +26606,7 @@ public: conv = new AudioData::ConverterInstance , AudioData::Pointer >(); if (! inPlace) - zerostruct (reversed); + zeromem (reversed, sizeof (reversed)); conv->convertSamples (reversed, inPlace ? reversed : converted, numSamples); @@ -31615,8 +31612,7 @@ void AudioUnitPluginInstance::setPluginCallbacks() if (audioUnit != 0) { { - AURenderCallbackStruct info; - zerostruct (info); + AURenderCallbackStruct info = { 0 }; info.inputProcRefCon = this; info.inputProc = renderGetInputCallback; @@ -31625,8 +31621,7 @@ void AudioUnitPluginInstance::setPluginCallbacks() } { - HostCallbackInfo info; - zerostruct (info); + HostCallbackInfo info = { 0 }; info.hostUserData = this; info.beatAndTempoProc = getBeatAndTempoCallback; info.musicalTimeLocationProc = getMusicalTimeLocationCallback; @@ -31673,8 +31668,7 @@ void AudioUnitPluginInstance::prepareToPlay (double sampleRate_, AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); { - AudioStreamBasicDescription stream; - zerostruct (stream); + AudioStreamBasicDescription stream = { 0 }; stream.mSampleRate = sampleRate_; stream.mFormatID = kAudioFormatLinearPCM; stream.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; @@ -32261,8 +32255,7 @@ void AudioUnitPluginInstance::setParameter (int index, float newValue) const String AudioUnitPluginInstance::getParameterName (int index) { - AudioUnitParameterInfo info; - zerostruct (info); + AudioUnitParameterInfo info = { 0 }; UInt32 sz = sizeof (info); String name; @@ -32528,12 +32521,10 @@ const StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearch { StringArray result; ComponentRecord* comp = 0; - ComponentDescription desc; - zerostruct (desc); for (;;) { - zerostruct (desc); + ComponentDescription desc = { 0 }; comp = FindNextComponent (comp, &desc); if (comp == 0) @@ -33961,8 +33952,7 @@ public: { const Rectangle clip (g.getClipBounds()); - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xexpose.type = Expose; ev.xexpose.display = display; ev.xexpose.window = pluginWindow; @@ -34017,8 +34007,7 @@ public: toFront (true); - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xbutton.display = display; ev.xbutton.type = ButtonPress; ev.xbutton.window = pluginWindow; @@ -34333,8 +34322,7 @@ private: { if (pluginWindow != 0) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xcrossing.display = display; ev.xcrossing.type = EnterNotify; ev.xcrossing.window = pluginWindow; @@ -34357,8 +34345,7 @@ private: { if (pluginWindow != 0) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xcrossing.display = display; ev.xcrossing.type = LeaveNotify; ev.xcrossing.window = pluginWindow; @@ -34382,8 +34369,7 @@ private: { if (pluginWindow != 0) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xmotion.display = display; ev.xmotion.type = MotionNotify; ev.xmotion.window = pluginWindow; @@ -34403,8 +34389,7 @@ private: { if (pluginWindow != 0) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xmotion.display = display; ev.xmotion.type = MotionNotify; ev.xmotion.window = pluginWindow; @@ -34425,8 +34410,7 @@ private: { if (pluginWindow != 0) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xbutton.display = display; ev.xbutton.type = ButtonRelease; ev.xbutton.window = pluginWindow; @@ -34448,8 +34432,7 @@ private: { if (pluginWindow != 0) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xbutton.display = display; ev.xbutton.type = ButtonPress; ev.xbutton.window = pluginWindow; @@ -45518,43 +45501,6 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_CodeEditorComponent.cpp ***/ BEGIN_JUCE_NAMESPACE -class CodeEditorComponent::CaretComponent : public Component, - public Timer -{ -public: - CaretComponent (CodeEditorComponent& owner_) - : owner (owner_) - { - setAlwaysOnTop (true); - setInterceptsMouseClicks (false, false); - } - - void paint (Graphics& g) - { - g.fillAll (findColour (CodeEditorComponent::caretColourId)); - } - - void timerCallback() - { - setVisible (shouldBeShown() && ! isVisible()); - } - - void updatePosition() - { - startTimer (400); - setVisible (shouldBeShown()); - - setBounds (owner.getCharacterBounds (owner.getCaretPos()).withWidth (2)); - } - -private: - CodeEditorComponent& owner; - - bool shouldBeShown() const { return owner.hasKeyboardFocus (true); } - - JUCE_DECLARE_NON_COPYABLE (CaretComponent); -}; - class CodeEditorComponent::CodeEditorLine { public: @@ -45794,7 +45740,7 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& document_, addAndMakeVisible (&horizontalScrollBar); horizontalScrollBar.setSingleStepSize (1.0); - addAndMakeVisible (caret = new CaretComponent (*this)); + addAndMakeVisible (caret = getLookAndFeel().createCaretComponent (this)); Font f (12.0f); f.setTypefaceName (Font::getDefaultMonospacedFontName()); @@ -45836,7 +45782,7 @@ void CodeEditorComponent::codeDocumentChanged (const CodeDocument::Position& aff triggerAsyncUpdate(); - caret->updatePosition(); + updateCaretPosition(); columnToTryToMaintain = -1; if (affectedTextEnd.getPosition() >= selectionStart.getPosition() @@ -45856,7 +45802,7 @@ void CodeEditorComponent::resized() columnsOnScreen = (int) ((getWidth() - scrollbarThickness) / charWidth); lines.clear(); rebuildLineTokens(); - caret->updatePosition(); + updateCaretPosition(); verticalScrollBar.setBounds (getWidth() - scrollbarThickness, 0, scrollbarThickness, getHeight() - scrollbarThickness); horizontalScrollBar.setBounds (gutter, getHeight() - scrollbarThickness, getWidth() - scrollbarThickness - gutter, scrollbarThickness); @@ -45948,6 +45894,11 @@ void CodeEditorComponent::rebuildLineTokens() } } +void CodeEditorComponent::updateCaretPosition() +{ + caret->setCaretPosition (getCharacterBounds (getCaretPos())); +} + void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, const bool highlighting) { caretPos = newPos; @@ -45998,7 +45949,7 @@ void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, con deselectAll(); } - caret->updatePosition(); + updateCaretPosition(); scrollToKeepCaretOnScreen(); updateScrollBars(); } @@ -46029,7 +45980,7 @@ void CodeEditorComponent::scrollToLineInternal (int newFirstLineOnScreen) if (newFirstLineOnScreen != firstLineOnScreen) { firstLineOnScreen = newFirstLineOnScreen; - caret->updatePosition(); + updateCaretPosition(); updateCachedIterators (firstLineOnScreen); triggerAsyncUpdate(); @@ -46043,7 +45994,7 @@ void CodeEditorComponent::scrollToColumnInternal (double column) if (xOffset != newOffset) { xOffset = newOffset; - caret->updatePosition(); + updateCaretPosition(); repaint(); } } @@ -46580,12 +46531,12 @@ void CodeEditorComponent::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, doub void CodeEditorComponent::focusGained (FocusChangeType) { - caret->updatePosition(); + updateCaretPosition(); } void CodeEditorComponent::focusLost (FocusChangeType) { - caret->updatePosition(); + updateCaretPosition(); } void CodeEditorComponent::setTabSize (const int numSpaces, const bool insertSpaces) @@ -48187,10 +48138,10 @@ TextEditor* Label::createEditorComponent() TextEditor::textColourId, TextEditor::highlightColourId, TextEditor::highlightedTextColourId, - TextEditor::caretColourId, TextEditor::outlineColourId, TextEditor::focusedOutlineColourId, - TextEditor::shadowColourId }; + TextEditor::shadowColourId, + CaretComponent::caretColourId }; for (int i = 0; i < numElementsInArray (cols); ++i) ed->setColour (cols[i], findColour (cols[i])); @@ -52960,6 +52911,11 @@ public: owner.drawContent (g); } + void restartTimer() + { + startTimer (350); + } + void timerCallback() { owner.timerCallbackInt(); @@ -53017,8 +52973,6 @@ private: namespace TextEditorDefs { - const int flashSpeedIntervalMs = 380; - const int textChangeMessageId = 0x10003001; const int returnKeyMessageId = 0x10003002; const int escapeKeyMessageId = 0x10003003; @@ -53041,19 +52995,14 @@ TextEditor::TextEditor (const String& name, multiline (false), wordWrap (false), returnKeyStartsNewLine (false), - caretVisible (true), popupMenuEnabled (true), selectAllTextWhenFocused (false), scrollbarVisible (true), wasFocused (false), - caretFlashState (true), keepCursorOnScreen (true), tabKeyUsed (false), menuActive (false), valueTextNeedsUpdating (false), - cursorX (0), - cursorY (0), - cursorHeight (0), maxTextLength (0), leftIndent (4), topIndent (4), @@ -53071,8 +53020,8 @@ TextEditor::TextEditor (const String& name, viewport->setWantsKeyboardFocus (false); viewport->setScrollBarsShown (false, false); - setMouseCursor (MouseCursor::IBeamCursor); setWantsKeyboardFocus (true); + setCaretVisible (true); } TextEditor::~TextEditor() @@ -53212,15 +53161,26 @@ void TextEditor::colourChanged() void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) { - caretVisible = shouldCaretBeVisible; - - if (shouldCaretBeVisible) - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + if (shouldCaretBeVisible && ! isReadOnly()) + { + if (caret == 0) + textHolder->addChildComponent (caret = getLookAndFeel().createCaretComponent (this)); + } + else + { + caret = 0; + } setMouseCursor (shouldCaretBeVisible ? MouseCursor::IBeamCursor : MouseCursor::NormalCursor); } +void TextEditor::updateCaretPosition() +{ + if (caret != 0) + caret->setCaretPosition (getCaretRectangle().translated (leftIndent, topIndent)); +} + void TextEditor::setInputRestrictions (const int maxLen, const String& chars) { @@ -53345,22 +53305,8 @@ void TextEditor::removeListener (TextEditorListener* const listenerToRemove) void TextEditor::timerCallbackInt() { - const bool newState = (! caretFlashState) && ! isCurrentlyBlockedByAnotherModalComponent(); - - if (caretFlashState != newState) - { - caretFlashState = newState; - - if (caretFlashState) - wasFocused = true; - - if (caretVisible - && hasKeyboardFocus (false) - && ! isReadOnly()) - { - repaintCaret(); - } - } + if (hasKeyboardFocus (false) && ! isCurrentlyBlockedByAnotherModalComponent()) + wasFocused = true; const unsigned int now = Time::getApproximateMillisecondCounter(); @@ -53368,15 +53314,6 @@ void TextEditor::timerCallbackInt() newTransaction(); } -void TextEditor::repaintCaret() -{ - if (! findColour (caretColourId).isTransparent()) - repaint (borderSize.getLeft() + textHolder->getX() + leftIndent + roundToInt (cursorX) - 1, - borderSize.getTop() + textHolder->getY() + topIndent + roundToInt (cursorY) - 1, - 4, - roundToInt (cursorHeight) + 2); -} - void TextEditor::repaintText (const Range& range) { if (! range.isEmpty()) @@ -53418,12 +53355,10 @@ void TextEditor::moveCaret (int newCaretPos) if (newCaretPos != getCaretPosition()) { - repaintCaret(); - caretFlashState = true; caretPosition = newCaretPos; - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + textHolder->restartTimer(); scrollToMakeSureCursorIsVisible(); - repaintCaret(); + updateCaretPosition(); } } @@ -53443,17 +53378,15 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, { updateCaretPosition(); - int vx = roundToInt (cursorX) - desiredCaretX; - int vy = roundToInt (cursorY) - desiredCaretY; + const Rectangle caretPos (getCaretRectangle()); + + int vx = caretPos.getX() - desiredCaretX; + int vy = caretPos.getY() - desiredCaretY; if (desiredCaretX < jmax (1, proportionOfWidth (0.05f))) - { vx += desiredCaretX - proportionOfWidth (0.2f); - } else if (desiredCaretX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10))) - { vx += desiredCaretX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth(); - } vx = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), vx); @@ -53465,16 +53398,10 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, { vy = jlimit (0, jmax (0, textHolder->getHeight() - viewport->getMaximumVisibleHeight()), vy); - const int curH = roundToInt (cursorHeight); - if (desiredCaretY < 0) - { vy = jmax (0, desiredCaretY + vy); - } - else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) - { - vy += desiredCaretY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); - } + else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - caretPos.getHeight())) + vy += desiredCaretY + 2 + caretPos.getHeight() + topIndent - viewport->getMaximumVisibleHeight(); } viewport->setViewPosition (vx, vy); @@ -53482,17 +53409,17 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, const Rectangle TextEditor::getCaretRectangle() { - updateCaretPosition(); + float cursorX, cursorY; + float cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) + getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); - return Rectangle (roundToInt (cursorX) - viewport->getX(), - roundToInt (cursorY) - viewport->getY(), - 1, roundToInt (cursorHeight)); + return Rectangle (roundToInt (cursorX), roundToInt (cursorY), 2, roundToInt (cursorHeight)); } float TextEditor::getWordWrapWidth() const { - return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) - : 1.0e10f; + return wordWrap ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) + : std::numeric_limits::max(); } void TextEditor::updateTextHolderSize() @@ -53512,7 +53439,7 @@ void TextEditor::updateTextHolderSize() const int h = topIndent + roundToInt (jmax (i.lineY + i.lineHeight, currentFont.getHeight())); - textHolder->setSize (w + 1, h + 1); + textHolder->setSize (w + 2, h + 1); } } @@ -53549,12 +53476,6 @@ void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) keepCursorOnScreen = shouldScrollToShowCursor; } -void TextEditor::updateCaretPosition() -{ - cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) - getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); -} - void TextEditor::scrollToMakeSureCursorIsVisible() { updateCaretPosition(); @@ -53564,8 +53485,10 @@ void TextEditor::scrollToMakeSureCursorIsVisible() int x = viewport->getViewPositionX(); int y = viewport->getViewPositionY(); - const int relativeCursorX = roundToInt (cursorX) - x; - const int relativeCursorY = roundToInt (cursorY) - y; + const Rectangle caretPos (getCaretRectangle()); + + const int relativeCursorX = caretPos.getX() - x; + const int relativeCursorY = caretPos.getY() - y; if (relativeCursorX < jmax (1, proportionOfWidth (0.05f))) { @@ -53584,15 +53507,13 @@ void TextEditor::scrollToMakeSureCursorIsVisible() } else { - const int curH = roundToInt (cursorHeight); - if (relativeCursorY < 0) { y = jmax (0, relativeCursorY + y); } - else if (relativeCursorY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) + else if (relativeCursorY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - caretPos.getHeight())) { - y += relativeCursorY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); + y += relativeCursorY + 2 + caretPos.getHeight() + topIndent - viewport->getMaximumVisibleHeight(); } } @@ -53782,18 +53703,6 @@ void TextEditor::paint (Graphics& g) void TextEditor::paintOverChildren (Graphics& g) { - if (caretFlashState - && hasKeyboardFocus (false) - && caretVisible - && ! isReadOnly()) - { - g.setColour (findColour (caretColourId)); - - g.fillRect (borderSize.getLeft() + textHolder->getX() + leftIndent + cursorX, - borderSize.getTop() + textHolder->getY() + topIndent + cursorY, - 2.0f, cursorHeight); - } - if (textToShowWhenEmpty.isNotEmpty() && (! hasKeyboardFocus (false)) && getTotalNumChars() == 0) @@ -53864,7 +53773,7 @@ void TextEditor::mouseDrag (const MouseEvent& e) void TextEditor::mouseUp (const MouseEvent& e) { newTransaction(); - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + textHolder->restartTimer(); if (wasFocused || ! selectAllTextWhenFocused) { @@ -53952,6 +53861,7 @@ bool TextEditor::keyPressed (const KeyPress& key) return false; const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); + const Rectangle caretPos (getCaretRectangle().toFloat()); if (key.isKeyCode (KeyPress::leftKey) || key.isKeyCode (KeyPress::upKey)) @@ -53961,7 +53871,7 @@ bool TextEditor::keyPressed (const KeyPress& key) int newPos; if (isMultiLine() && key.isKeyCode (KeyPress::upKey)) - newPos = indexAtPosition (cursorX, cursorY - 1); + newPos = indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f); else if (moveInWholeWordSteps) newPos = findWordBreakBefore (getCaretPosition()); else @@ -53977,7 +53887,7 @@ bool TextEditor::keyPressed (const KeyPress& key) int newPos; if (isMultiLine() && key.isKeyCode (KeyPress::downKey)) - newPos = indexAtPosition (cursorX, cursorY + cursorHeight + 1); + newPos = indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f); else if (moveInWholeWordSteps) newPos = findWordBreakAfter (getCaretPosition()); else @@ -53989,14 +53899,14 @@ bool TextEditor::keyPressed (const KeyPress& key) { newTransaction(); - moveCursorTo (indexAtPosition (cursorX, cursorY + cursorHeight + viewport->getViewHeight()), + moveCursorTo (indexAtPosition (caretPos.getX(), caretPos.getBottom() + viewport->getViewHeight()), key.getModifiers().isShiftDown()); } else if (key.isKeyCode (KeyPress::pageUpKey) && isMultiLine()) { newTransaction(); - moveCursorTo (indexAtPosition (cursorX, cursorY - viewport->getViewHeight()), + moveCursorTo (indexAtPosition (caretPos.getX(), caretPos.getY() - viewport->getViewHeight()), key.getModifiers().isShiftDown()); } else if (key.isKeyCode (KeyPress::homeKey)) @@ -54004,7 +53914,7 @@ bool TextEditor::keyPressed (const KeyPress& key) newTransaction(); if (isMultiLine() && ! moveInWholeWordSteps) - moveCursorTo (indexAtPosition (0.0f, cursorY), + moveCursorTo (indexAtPosition (0.0f, caretPos.getY()), key.getModifiers().isShiftDown()); else moveCursorTo (0, key.getModifiers().isShiftDown()); @@ -54014,7 +53924,7 @@ bool TextEditor::keyPressed (const KeyPress& key) newTransaction(); if (isMultiLine() && ! moveInWholeWordSteps) - moveCursorTo (indexAtPosition ((float) textHolder->getWidth(), cursorY), + moveCursorTo (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()), key.getModifiers().isShiftDown()); else moveCursorTo (getTotalNumChars(), key.getModifiers().isShiftDown()); @@ -54189,8 +54099,6 @@ void TextEditor::focusGained (FocusChangeType) { newTransaction(); - caretFlashState = true; - if (selectAllTextWhenFocused) { moveCursorTo (0, false); @@ -54198,9 +54106,7 @@ void TextEditor::focusGained (FocusChangeType) } repaint(); - - if (caretVisible) - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + updateCaretPosition(); ComponentPeer* const peer = getPeer(); if (peer != 0 && ! isReadOnly()) @@ -54213,7 +54119,7 @@ void TextEditor::focusLost (FocusChangeType) wasFocused = false; textHolder->stopTimer(); - caretFlashState = false; + updateCaretPosition(); postCommandMessage (TextEditorDefs::focusLossMessageId); repaint(); @@ -61152,6 +61058,47 @@ END_JUCE_NAMESPACE /*** End of inlined file: juce_ModifierKeys.cpp ***/ +/*** Start of inlined file: juce_CaretComponent.cpp ***/ +BEGIN_JUCE_NAMESPACE + +CaretComponent::CaretComponent (Component* const keyFocusOwner) + : owner (keyFocusOwner) +{ + setAlwaysOnTop (true); + setInterceptsMouseClicks (false, false); +} + +CaretComponent::~CaretComponent() +{ +} + +void CaretComponent::paint (Graphics& g) +{ + g.fillAll (findColour (caretColourId)); +} + +void CaretComponent::timerCallback() +{ + setVisible (shouldBeShown() && ! isVisible()); +} + +void CaretComponent::setCaretPosition (const Rectangle& characterArea) +{ + startTimer (380); + setVisible (shouldBeShown()); + setBounds (characterArea.withWidth (2)); +} + +bool CaretComponent::shouldBeShown() const +{ + return owner == 0 || (owner->hasKeyboardFocus (true) + && ! owner->isCurrentlyBlockedByAnotherModalComponent()); +} + +END_JUCE_NAMESPACE +/*** End of inlined file: juce_CaretComponent.cpp ***/ + + /*** Start of inlined file: juce_ComponentAnimator.cpp ***/ BEGIN_JUCE_NAMESPACE @@ -65239,11 +65186,12 @@ LookAndFeel::LookAndFeel() TextEditor::textColourId, 0xff000000, TextEditor::highlightColourId, textHighlightColour, TextEditor::highlightedTextColourId, 0xff000000, - TextEditor::caretColourId, 0xff000000, TextEditor::outlineColourId, 0x00000000, TextEditor::focusedOutlineColourId, textButtonColour, TextEditor::shadowColourId, 0x38000000, + CaretComponent::caretColourId, 0xff000000, + Label::backgroundColourId, 0x00000000, Label::textColourId, 0xff000000, Label::outlineColourId, 0x00000000, @@ -65326,7 +65274,6 @@ LookAndFeel::LookAndFeel() MidiKeyboardComponent::upDownButtonArrowColourId, 0xff000000, CodeEditorComponent::backgroundColourId, 0xffffffff, - CodeEditorComponent::caretColourId, 0xff000000, CodeEditorComponent::highlightColourId, textHighlightColour, CodeEditorComponent::defaultTextColourId, 0xff000000, @@ -66358,6 +66305,11 @@ void LookAndFeel::drawTextEditorOutline (Graphics& g, int width, int height, Tex } } +CaretComponent* LookAndFeel::createCaretComponent (Component* keyFocusOwner) +{ + return new CaretComponent (keyFocusOwner); +} + void LookAndFeel::drawComboBox (Graphics& g, int width, int height, const bool isButtonDown, int buttonX, int buttonY, @@ -242963,8 +242915,7 @@ bool File::moveToTrash() const if (! exists()) return true; - SHFILEOPSTRUCT fos; - zerostruct (fos); + SHFILEOPSTRUCT fos = { 0 }; // The string we pass in must be double null terminated.. String doubleNullTermPath (getFullPathName() + " "); @@ -243458,8 +243409,7 @@ public: if (! connected) { - OVERLAPPED over; - zerostruct (over); + OVERLAPPED over = { 0 }; over.hEvent = CreateEvent (0, TRUE, FALSE, 0); @@ -243546,8 +243496,7 @@ int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMillisecon if (maxBytesToRead <= 0) return 0; - OVERLAPPED over; - zerostruct (over); + OVERLAPPED over = { 0 }; over.hEvent = CreateEvent (0, TRUE, FALSE, 0); unsigned long numRead; @@ -243601,9 +243550,7 @@ int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOut if (numBytesToWrite <= 0) return 0; - OVERLAPPED over; - zerostruct (over); - + OVERLAPPED over = { 0 }; over.hEvent = CreateEvent (0, TRUE, FALSE, 0); unsigned long numWritten; @@ -243853,8 +243800,7 @@ private: // break up the url.. TCHAR file[1024], server[1024]; - URL_COMPONENTS uc; - zerostruct (uc); + URL_COMPONENTS uc = { 0 }; uc.dwStructSize = sizeof (uc); uc.dwUrlPathLength = sizeof (file); uc.dwHostNameLength = sizeof (server); @@ -243918,8 +243864,7 @@ private: if (request != 0) { - INTERNET_BUFFERS buffers; - zerostruct (buffers); + INTERNET_BUFFERS buffers = { 0 }; buffers.dwStructSize = sizeof (INTERNET_BUFFERS); buffers.lpcszHeader = headers.toWideCharPointer(); buffers.dwHeadersLength = headers.length(); @@ -244016,39 +243961,36 @@ namespace MACAddressHelpers if (NetbiosCall != 0) { - NCB ncb; - zerostruct (ncb); + LANA_ENUM enums = { 0 }; - struct ASTAT { - ADAPTER_STATUS adapt; - NAME_BUFFER NameBuff [30]; - }; - - ASTAT astat; - zeromem (&astat, sizeof (astat)); // (can't use zerostruct here in VC6) - - LANA_ENUM enums; - zerostruct (enums); - - ncb.ncb_command = NCBENUM; - ncb.ncb_buffer = (unsigned char*) &enums; - ncb.ncb_length = sizeof (LANA_ENUM); - NetbiosCall (&ncb); + NCB ncb = { 0 }; + ncb.ncb_command = NCBENUM; + ncb.ncb_buffer = (unsigned char*) &enums; + ncb.ncb_length = sizeof (LANA_ENUM); + NetbiosCall (&ncb); + } for (int i = 0; i < enums.length; ++i) { - zerostruct (ncb); - ncb.ncb_command = NCBRESET; - ncb.ncb_lana_num = enums.lana[i]; + NCB ncb2 = { 0 }; + ncb2.ncb_command = NCBRESET; + ncb2.ncb_lana_num = enums.lana[i]; - if (NetbiosCall (&ncb) == 0) + if (NetbiosCall (&ncb2) == 0) { - zerostruct (ncb); + NCB ncb = { 0 }; memcpy (ncb.ncb_callname, "* ", NCBNAMSZ); ncb.ncb_command = NCBASTAT; ncb.ncb_lana_num = enums.lana[i]; + struct ASTAT + { + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff [30]; + }; + + ASTAT astat = { 0 }; ncb.ncb_buffer = (unsigned char*) &astat; ncb.ncb_length = sizeof (ASTAT); @@ -244080,13 +244022,11 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd if (mapiSendMail != 0) { - MapiMessage message; - zerostruct (message); + MapiMessage message = { 0 }; message.lpszSubject = (LPSTR) emailSubject.toUTF8().getAddress(); message.lpszNoteText = (LPSTR) bodyText.toUTF8().getAddress(); - MapiRecipDesc recip; - zerostruct (recip); + MapiRecipDesc recip = { 0 }; recip.ulRecipClass = MAPI_TO; String targetEmailAddress_ (targetEmailAddress); if (targetEmailAddress_.isEmpty()) @@ -244563,8 +244503,7 @@ void MessageManager::doPlatformSpecificInitialisation() HMODULE moduleHandle = (HMODULE) PlatformUtilities::getCurrentModuleInstanceHandle(); - WNDCLASSEX wc; - zerostruct (wc); + WNDCLASSEX wc = { 0 }; wc.cbSize = sizeof (wc); wc.lpfnWndProc = (WNDPROC) juce_MessageWndProc; wc.cbWndExtra = 4; @@ -244618,9 +244557,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, { if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) { - LOGFONTW lf; - zerostruct (lf); - + LOGFONTW lf = { 0 }; lf.lfWeight = FW_DONTCARE; lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfQuality = DEFAULT_QUALITY; @@ -244647,9 +244584,7 @@ const StringArray Font::findAllTypefaceNames() HDC dc = CreateCompatibleDC (0); { - LOGFONTW lf; - zerostruct (lf); - + LOGFONTW lf = { 0 }; lf.lfWeight = FW_DONTCARE; lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfQuality = DEFAULT_QUALITY; @@ -244722,9 +244657,7 @@ public: SetMapperFlags (dc, 0); SetMapMode (dc, MM_TEXT); - LOGFONTW lfw; - zerostruct (lfw); - + LOGFONTW lfw = { 0 }; lfw.lfCharSet = DEFAULT_CHARSET; lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS; lfw.lfOutPrecision = OUT_OUTLINE_PRECIS; @@ -246847,8 +246780,7 @@ private: GetModuleFileName (moduleHandle, moduleFile, 1024); WORD iconNum = 0; - WNDCLASSEX wcex; - zerostruct (wcex); + WNDCLASSEX wcex = { 0 }; wcex.cbSize = sizeof (wcex); wcex.style = CS_OWNDC; wcex.lpfnWndProc = (WNDPROC) windowProc; @@ -248899,9 +248831,7 @@ void FileChooser::showPlatformDialog (Array& results, const String& title_ if (selectsDirectory) { - BROWSEINFO bi; - zerostruct (bi); - + BROWSEINFO bi = { 0 }; bi.hwndOwner = (HWND) parentWindow.getWindowHandle(); bi.pszDisplayName = files; bi.lpszTitle = title.toWideCharPointer(); @@ -248956,16 +248886,14 @@ void FileChooser::showPlatformDialog (Array& results, const String& title_ filter.copyToUTF16 (filters + (bytesWritten / sizeof (WCHAR)) + 1, (filterSpaceNumChars - 1) * sizeof (WCHAR) - bytesWritten); - OPENFILENAMEW of; - zerostruct (of); - + OPENFILENAMEW of = { 0 }; String localPath (info.initialPath); - #ifdef OPENFILENAME_SIZE_VERSION_400W + #ifdef OPENFILENAME_SIZE_VERSION_400W of.lStructSize = OPENFILENAME_SIZE_VERSION_400W; - #else + #else of.lStructSize = sizeof (of); - #endif + #endif of.hwndOwner = (HWND) parentWindow.getWindowHandle(); of.lpstrFilter = filters.getData(); of.nFilterIndex = 1; @@ -249805,8 +249733,7 @@ bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle dataHandle = 0; bool ok = false; - QTNewMoviePropertyElement props[5]; - zeromem (props, sizeof (props)); + QTNewMoviePropertyElement props[5] = { 0 }; int prop = 0; DataReferenceRecord dr; @@ -250269,8 +250196,7 @@ public: createNativeWindow(); // Use a default pixel format that should be supported everywhere - PIXELFORMATDESCRIPTOR pfd; - zerostruct (pfd); + PIXELFORMATDESCRIPTOR pfd = { 0 }; pfd.nSize = sizeof (pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; @@ -250347,8 +250273,7 @@ public: { makeActive(); - PIXELFORMATDESCRIPTOR pfd; - zerostruct (pfd); + PIXELFORMATDESCRIPTOR pfd = { 0 }; pfd.nSize = sizeof (pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; @@ -251004,8 +250929,7 @@ void findCDDevices (Array& list) { char buffer[100] = { 0 }; - SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p; - zerostruct (p); + SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p = { 0 }; p.spt.Length = sizeof (SCSI_PASS_THROUGH); p.spt.CdbLength = 6; p.spt.SenseInfoLength = 24; @@ -251027,8 +250951,7 @@ void findCDDevices (Array& list) dev.scsiDriveLetter = driveLetter; dev.createDescription (buffer); - SCSI_ADDRESS scsiAddr; - zerostruct (scsiAddr); + SCSI_ADDRESS scsiAddr = { 0 }; scsiAddr.Length = sizeof (scsiAddr); if (DeviceIoControl (h, IOCTL_SCSI_GET_ADDRESS, @@ -251051,9 +250974,7 @@ void findCDDevices (Array& list) DWORD performScsiPassThroughCommand (SRB_ExecSCSICmd* const srb, const char driveLetter, HANDLE& deviceHandle, const bool retryOnFailure) { - SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER s; - zerostruct (s); - + SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER s = { 0 }; s.spt.Length = sizeof (SCSI_PASS_THROUGH); s.spt.CdbLength = srb->SRB_CDBLen; @@ -251472,8 +251393,7 @@ int CDController::getLastIndex() bool CDDeviceHandle::readTOC (TOC* lpToc) { - SRB_ExecSCSICmd s; - zerostruct (s); + SRB_ExecSCSICmd s = { 0 }; s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.SRB_HaID = info.ha; s.SRB_Target = info.tgt; @@ -251547,8 +251467,7 @@ void CDDeviceHandle::openDrawer (bool shouldBeOpen) } } - SRB_ExecSCSICmd s; - zerostruct (s); + SRB_ExecSCSICmd s = { 0 }; s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.SRB_HaID = info.ha; s.SRB_Target = info.tgt; @@ -251801,9 +251720,7 @@ bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int sta bool AudioCDReader::isCDStillPresent() const { using namespace CDReaderHelpers; - TOC toc; - zerostruct (toc); - + TOC toc = { 0 }; return static_cast (handle)->deviceHandle.readTOC (&toc); } @@ -251813,8 +251730,7 @@ void AudioCDReader::refreshTrackLengths() trackStartSamples.clear(); zeromem (audioTracks, sizeof (audioTracks)); - TOC toc; - zerostruct (toc); + TOC toc = { 0 }; if (static_cast (handle)->deviceHandle.readTOC (&toc)) { @@ -252586,8 +252502,7 @@ const StringArray MidiInput::getDevices() for (int i = 0; i < num; ++i) { - MIDIINCAPS mc; - zerostruct (mc); + MIDIINCAPS mc = { 0 }; if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) s.add (String (mc.szPname, sizeof (mc.szPname))); @@ -252614,8 +252529,7 @@ MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const call for (int i = 0; i < num; ++i) { - MIDIINCAPS mc; - zerostruct (mc); + MIDIINCAPS mc = { 0 }; if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) { @@ -252691,8 +252605,7 @@ const StringArray MidiOutput::getDevices() for (int i = 0; i < num; ++i) { - MIDIOUTCAPS mc; - zerostruct (mc); + MIDIOUTCAPS mc = { 0 }; if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) s.add (String (mc.szPname, sizeof (mc.szPname))); @@ -252708,8 +252621,7 @@ int MidiOutput::getDefaultDeviceIndex() for (int i = 0; i < num; ++i) { - MIDIOUTCAPS mc; - zerostruct (mc); + MIDIOUTCAPS mc = { 0 }; if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) { @@ -252731,8 +252643,7 @@ MidiOutput* MidiOutput::openDevice (int index) for (i = 0; i < num; ++i) { - MIDIOUTCAPS mc; - zerostruct (mc); + MIDIOUTCAPS mc = { 0 }; if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) { @@ -252852,8 +252763,7 @@ void MidiOutput::sendMessageNow (const MidiMessage& message) if (message.getRawDataSize() > 3 || message.isSysEx()) { - MIDIHDR h; - zerostruct (h); + MIDIHDR h = { 0 }; h.lpData = (char*) message.getRawData(); h.dwBufferLength = message.getRawDataSize(); @@ -253305,9 +253215,7 @@ public: { inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n); - ASIOChannelInfo channelInfo; - zerostruct (channelInfo); - + ASIOChannelInfo channelInfo = { 0 }; channelInfo.channel = i; channelInfo.isInput = 1; asioObject->getChannelInfo (&channelInfo); @@ -253334,9 +253242,7 @@ public: { outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n)); - ASIOChannelInfo channelInfo; - zerostruct (channelInfo); - + ASIOChannelInfo channelInfo = { 0 }; channelInfo.channel = i; channelInfo.isInput = 0; asioObject->getChannelInfo (&channelInfo); @@ -253904,12 +253810,9 @@ private: updateSampleRates(); - ASIOChannelInfo channelInfo; - channelInfo.type = 0; - for (i = 0; i < totalNumInputChans; ++i) { - zerostruct (channelInfo); + ASIOChannelInfo channelInfo = { 0 }; channelInfo.channel = i; channelInfo.isInput = 1; asioObject->getChannelInfo (&channelInfo); @@ -253919,7 +253822,7 @@ private: for (i = 0; i < totalNumOutputChans; ++i) { - zerostruct (channelInfo); + ASIOChannelInfo channelInfo = { 0 }; channelInfo.channel = i; channelInfo.isInput = 0; asioObject->getChannelInfo (&channelInfo); @@ -254977,9 +254880,7 @@ public: { IDirectSoundBuffer* pPrimaryBuffer; - DSBUFFERDESC primaryDesc; - zerostruct (primaryDesc); - + DSBUFFERDESC primaryDesc = { 0 }; primaryDesc.dwSize = sizeof (DSBUFFERDESC); primaryDesc.dwFlags = 1 /* DSBCAPS_PRIMARYBUFFER */; primaryDesc.dwBufferBytes = 0; @@ -255005,9 +254906,7 @@ public: if (hr == S_OK) { - DSBUFFERDESC secondaryDesc; - zerostruct (secondaryDesc); - + DSBUFFERDESC secondaryDesc = { 0 }; secondaryDesc.dwSize = sizeof (DSBUFFERDESC); secondaryDesc.dwFlags = 0x8000 /* DSBCAPS_GLOBALFOCUS */ | 0x10000 /* DSBCAPS_GETCURRENTPOSITION2 */; @@ -255304,9 +255203,7 @@ public: wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; wfFormat.cbSize = 0; - DSCBUFFERDESC captureDesc; - zerostruct (captureDesc); - + DSCBUFFERDESC captureDesc = { 0 }; captureDesc.dwSize = sizeof (DSCBUFFERDESC); captureDesc.dwFlags = 0; captureDesc.dwBufferBytes = totalBytesPerBuffer; @@ -256373,8 +256270,7 @@ private: bool tryInitialisingWithFormat (const bool useFloat, const int bytesPerSampleToTry) { - WAVEFORMATEXTENSIBLE format; - zerostruct (format); + WAVEFORMATEXTENSIBLE format = { 0 }; if (numChannels <= 2 && bytesPerSampleToTry <= 2) { @@ -257249,12 +257145,13 @@ public: if (FAILED (hr)) return; - AM_MEDIA_TYPE mt; - zerostruct (mt); - mt.majortype = MEDIATYPE_Video; - mt.subtype = MEDIASUBTYPE_RGB24; - mt.formattype = FORMAT_VideoInfo; - sampleGrabber->SetMediaType (&mt); + { + AM_MEDIA_TYPE mt = { 0 }; + mt.majortype = MEDIATYPE_Video; + mt.subtype = MEDIASUBTYPE_RGB24; + mt.formattype = FORMAT_VideoInfo; + sampleGrabber->SetMediaType (&mt); + } callback = new GrabberCallback (*this); hr = sampleGrabber->SetCallback (callback, 1); @@ -257273,7 +257170,7 @@ public: if (FAILED (hr)) return; - zerostruct (mt); + AM_MEDIA_TYPE mt = { 0 }; hr = sampleGrabber->GetConnectedMediaType (&mt); VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*) (mt.pbFormat); width = pVih->bmiHeader.biWidth; @@ -257747,8 +257644,7 @@ private: if (wantedDirection == dir) { - PIN_INFO info; - zerostruct (info); + PIN_INFO info = { 0 }; pin->QueryPinInfo (&info); if (pinName == 0 || String (pinName).equalsIgnoreCase (String (info.achName))) @@ -258582,8 +258478,7 @@ const String File::getVolumeLabel() const char mountPointSpace [MAXPATHLEN]; } attrBuf; - struct attrlist attrList; - zerostruct (attrList); + struct attrlist attrList = { 0 }; attrList.bitmapcount = ATTR_BIT_MAP_COUNT; attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; @@ -258664,8 +258559,7 @@ public: if (handle != 0) { - struct flock fl; - zerostruct (fl); + struct flock fl = { 0 }; fl.l_whence = SEEK_SET; fl.l_type = F_WRLCK; @@ -258701,8 +258595,7 @@ public: { if (handle != 0) { - struct flock fl; - zerostruct (fl); + struct flock fl = { 0 }; fl.l_whence = SEEK_SET; fl.l_type = F_UNLCK; @@ -259577,8 +259470,7 @@ private: port = hostPort; } - struct addrinfo hints; - zerostruct (hints); + struct addrinfo hints = { 0 }; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICSERV; @@ -261423,8 +261315,7 @@ namespace XSHMHelpers trappedErrorCode = 0; XErrorHandler oldHandler = XSetErrorHandler (errorTrapHandler); - XShmSegmentInfo segmentInfo; - zerostruct (segmentInfo); + XShmSegmentInfo segmentInfo = { 0 }; XImage* xImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), 24, ZPixmap, 0, &segmentInfo, 50, 50); @@ -262919,8 +262810,7 @@ public: if (managerWin != None) { - XEvent ev; - zerostruct (ev); + XEvent ev = { 0 }; ev.xclient.type = ClientMessage; ev.xclient.window = managerWin; ev.xclient.message_type = XInternAtom (display, "_NET_SYSTEM_TRAY_OPCODE", False); @@ -263233,8 +263123,7 @@ private: if (hints != None) { - MotifWmHints motifHints; - zerostruct (motifHints); + MotifWmHints motifHints = { 0 }; motifHints.flags = 2; /* MWM_HINTS_DECORATIONS */ motifHints.decorations = 0; @@ -263273,9 +263162,7 @@ private: if (hints != None) { - MotifWmHints motifHints; - zerostruct (motifHints); - + MotifWmHints motifHints = { 0 }; motifHints.flags = 1 | 2; /* MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS */ motifHints.decorations = 2 /* MWM_DECOR_BORDER */ | 8 /* MWM_DECOR_TITLE */ | 16; /* MWM_DECOR_MENU */ @@ -263600,8 +263487,7 @@ private: void sendDragAndDropStatus (const bool acceptDrop, Atom dropAction) { - XClientMessageEvent msg; - zerostruct (msg); + XClientMessageEvent msg = { 0 }; msg.message_type = Atoms::XdndStatus; msg.data.l[1] = (acceptDrop ? 1 : 0) | 2; // 2 indicates that we want to receive position messages msg.data.l[4] = dropAction; @@ -263611,16 +263497,14 @@ private: void sendDragAndDropLeave() { - XClientMessageEvent msg; - zerostruct (msg); + XClientMessageEvent msg = { 0 }; msg.message_type = Atoms::XdndLeave; sendDragAndDropMessage (msg); } void sendDragAndDropFinish() { - XClientMessageEvent msg; - zerostruct (msg); + XClientMessageEvent msg = { 0 }; msg.message_type = Atoms::XdndFinished; sendDragAndDropMessage (msg); } @@ -266902,8 +266786,7 @@ public: runLoop = CFRunLoopGetCurrent(); #endif - CFRunLoopSourceContext sourceContext; - zerostruct (sourceContext); + CFRunLoopSourceContext sourceContext = { 0 }; sourceContext.info = this; sourceContext.perform = runLoopSourceCallback; runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext); @@ -268476,8 +268359,7 @@ const String File::getVolumeLabel() const char mountPointSpace [MAXPATHLEN]; } attrBuf; - struct attrlist attrList; - zerostruct (attrList); + struct attrlist attrList = { 0 }; attrList.bitmapcount = ATTR_BIT_MAP_COUNT; attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; @@ -268558,8 +268440,7 @@ public: if (handle != 0) { - struct flock fl; - zerostruct (fl); + struct flock fl = { 0 }; fl.l_whence = SEEK_SET; fl.l_type = F_WRLCK; @@ -268595,8 +268476,7 @@ public: { if (handle != 0) { - struct flock fl; - zerostruct (fl); + struct flock fl = { 0 }; fl.l_whence = SEEK_SET; fl.l_type = F_UNLCK; @@ -284696,8 +284576,7 @@ const String File::getVolumeLabel() const char mountPointSpace [MAXPATHLEN]; } attrBuf; - struct attrlist attrList; - zerostruct (attrList); + struct attrlist attrList = { 0 }; attrList.bitmapcount = ATTR_BIT_MAP_COUNT; attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; @@ -284778,8 +284657,7 @@ public: if (handle != 0) { - struct flock fl; - zerostruct (fl); + struct flock fl = { 0 }; fl.l_whence = SEEK_SET; fl.l_type = F_WRLCK; @@ -284815,8 +284693,7 @@ public: { if (handle != 0) { - struct flock fl; - zerostruct (fl); + struct flock fl = { 0 }; fl.l_whence = SEEK_SET; fl.l_type = F_UNLCK; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 64793f4f21..cd0f67d0ec 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 55 +#define JUCE_BUILDNUMBER 56 /** Current Juce version number. @@ -41819,6 +41819,61 @@ public: #endif // __JUCE_TEXTINPUTTARGET_JUCEHEADER__ /*** End of inlined file: juce_TextInputTarget.h ***/ + +/*** Start of inlined file: juce_CaretComponent.h ***/ +#ifndef __JUCE_CARETCOMPONENT_JUCEHEADER__ +#define __JUCE_CARETCOMPONENT_JUCEHEADER__ + +/** +*/ +class JUCE_API CaretComponent : public Component, + public Timer +{ +public: + + /** Creates the caret component. + The keyFocusOwner is an optional component which the caret will check, making + itself visible only when the keyFocusOwner has keyboard focus. + */ + CaretComponent (Component* keyFocusOwner); + + /** Destructor. */ + ~CaretComponent(); + + /** Sets the caret's position to place it next to the given character. + The area is the rectangle containing the entire character that the caret is + positioned on, so by default a vertical-line caret may choose to just show itself + at the left of this area. You can override this method to customise its size. + This method will also force the caret to reset its timer and become visible (if + appropriate), so that as it moves, you can see where it is. + */ + virtual void setCaretPosition (const Rectangle& characterArea); + + /** A set of colour IDs to use to change the colour of various aspects of the caret. + These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() + methods. + @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour + */ + enum ColourIds + { + caretColourId = 0x1000204, /**< The colour with which to draw the caret. */ + }; + + /** @internal */ + void paint (Graphics& g); + /** @internal */ + void timerCallback(); + +private: + Component* owner; + bool shouldBeShown() const; + + JUCE_DECLARE_NON_COPYABLE (CaretComponent); +}; + +#endif // __JUCE_CARETCOMPONENT_JUCEHEADER__ +/*** End of inlined file: juce_CaretComponent.h ***/ + /** A component containing text that can be edited. @@ -41910,9 +41965,7 @@ public: bool isReadOnly() const; /** Makes the caret visible or invisible. - By default the caret is visible. - @see setCaretColour, setCaretPosition */ void setCaretVisible (bool shouldBeVisible); @@ -41920,7 +41973,7 @@ public: /** Returns true if the caret is enabled. @see setCaretVisible */ - bool isCaretVisible() const { return caretVisible; } + bool isCaretVisible() const { return caret != 0; } /** Enables/disables a vertical scrollbar. @@ -41994,8 +42047,6 @@ public: highlightedTextColourId = 0x1000203, /**< The colour with which to draw the text in highlighted sections. */ - caretColourId = 0x1000204, /**< The colour with which to draw the caret. */ - outlineColourId = 0x1000205, /**< If this is non-transparent, it will be used to draw a box around the edge of the component. */ @@ -42385,19 +42436,17 @@ private: bool multiline : 1; bool wordWrap : 1; bool returnKeyStartsNewLine : 1; - bool caretVisible : 1; bool popupMenuEnabled : 1; bool selectAllTextWhenFocused : 1; bool scrollbarVisible : 1; bool wasFocused : 1; - bool caretFlashState : 1; bool keepCursorOnScreen : 1; bool tabKeyUsed : 1; bool menuActive : 1; bool valueTextNeedsUpdating : 1; UndoManager undoManager; - float cursorX, cursorY, cursorHeight; + ScopedPointer caret; int maxTextLength; Range selection; int leftIndent, topIndent; @@ -42441,7 +42490,6 @@ private: void updateTextHolderSize(); float getWordWrapWidth() const; void timerCallbackInt(); - void repaintCaret(); void repaintText (const Range& range); UndoManager* getUndoManager() throw(); @@ -51637,7 +51685,6 @@ public: enum ColourIds { backgroundColourId = 0x1004500, /**< A colour to use to fill the editor's background. */ - caretColourId = 0x1004501, /**< The colour to draw the caret. */ highlightColourId = 0x1004502, /**< The colour to use for the highlighted background under selected text. */ defaultTextColourId = 0x1004503 /**< The colour to use for text when no syntax colouring is @@ -51697,8 +51744,6 @@ private: CodeDocument::Position caretPos; CodeDocument::Position selectionStart, selectionEnd; - class CaretComponent; - friend class ScopedPointer ; ScopedPointer caret; ScrollBar verticalScrollBar, horizontalScrollBar; @@ -51724,6 +51769,7 @@ private: void getIteratorForPosition (int position, CodeDocument::Iterator& result); void moveLineDelta (int delta, bool selecting); + void updateCaretPosition(); void updateScrollBars(); void scrollToLineInternal (int line); void scrollToColumnInternal (double column); @@ -57710,6 +57756,9 @@ private: #endif #ifndef __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__ +#endif +#ifndef __JUCE_CARETCOMPONENT_JUCEHEADER__ + #endif #ifndef __JUCE_KEYBOARDFOCUSTRAVERSER_JUCEHEADER__ @@ -59878,6 +59927,7 @@ class FilePreviewComponent; class ImageButton; class CallOutBox; class Drawable; +class CaretComponent; /** LookAndFeel objects define the appearance of all the JUCE widgets, and subclasses @@ -60099,6 +60149,8 @@ public: virtual void fillTextEditorBackground (Graphics& g, int width, int height, TextEditor& textEditor); virtual void drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor); + virtual CaretComponent* createCaretComponent (Component* keyFocusOwner); + // These return a pointer to an internally cached drawable - make sure you don't keep // a copy of this pointer anywhere, as it may become invalid in the future. virtual const Drawable* getDefaultFolderImage(); diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index c8a4ec58de..8dc15cabab 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 55 +#define JUCE_BUILDNUMBER 56 /** Current Juce version number. diff --git a/src/gui/components/code_editor/juce_CodeEditorComponent.cpp b/src/gui/components/code_editor/juce_CodeEditorComponent.cpp index 3f5d5ed9ee..a5ab6c14c0 100644 --- a/src/gui/components/code_editor/juce_CodeEditorComponent.cpp +++ b/src/gui/components/code_editor/juce_CodeEditorComponent.cpp @@ -32,44 +32,6 @@ BEGIN_JUCE_NAMESPACE #include "../../../utilities/juce_SystemClipboard.h" -//============================================================================== -class CodeEditorComponent::CaretComponent : public Component, - public Timer -{ -public: - CaretComponent (CodeEditorComponent& owner_) - : owner (owner_) - { - setAlwaysOnTop (true); - setInterceptsMouseClicks (false, false); - } - - void paint (Graphics& g) - { - g.fillAll (findColour (CodeEditorComponent::caretColourId)); - } - - void timerCallback() - { - setVisible (shouldBeShown() && ! isVisible()); - } - - void updatePosition() - { - startTimer (400); - setVisible (shouldBeShown()); - - setBounds (owner.getCharacterBounds (owner.getCaretPos()).withWidth (2)); - } - -private: - CodeEditorComponent& owner; - - bool shouldBeShown() const { return owner.hasKeyboardFocus (true); } - - JUCE_DECLARE_NON_COPYABLE (CaretComponent); -}; - //============================================================================== class CodeEditorComponent::CodeEditorLine { @@ -311,7 +273,7 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& document_, addAndMakeVisible (&horizontalScrollBar); horizontalScrollBar.setSingleStepSize (1.0); - addAndMakeVisible (caret = new CaretComponent (*this)); + addAndMakeVisible (caret = getLookAndFeel().createCaretComponent (this)); Font f (12.0f); f.setTypefaceName (Font::getDefaultMonospacedFontName()); @@ -354,7 +316,7 @@ void CodeEditorComponent::codeDocumentChanged (const CodeDocument::Position& aff triggerAsyncUpdate(); - caret->updatePosition(); + updateCaretPosition(); columnToTryToMaintain = -1; if (affectedTextEnd.getPosition() >= selectionStart.getPosition() @@ -374,7 +336,7 @@ void CodeEditorComponent::resized() columnsOnScreen = (int) ((getWidth() - scrollbarThickness) / charWidth); lines.clear(); rebuildLineTokens(); - caret->updatePosition(); + updateCaretPosition(); verticalScrollBar.setBounds (getWidth() - scrollbarThickness, 0, scrollbarThickness, getHeight() - scrollbarThickness); horizontalScrollBar.setBounds (gutter, getHeight() - scrollbarThickness, getWidth() - scrollbarThickness - gutter, scrollbarThickness); @@ -467,6 +429,11 @@ void CodeEditorComponent::rebuildLineTokens() } //============================================================================== +void CodeEditorComponent::updateCaretPosition() +{ + caret->setCaretPosition (getCharacterBounds (getCaretPos())); +} + void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, const bool highlighting) { caretPos = newPos; @@ -517,7 +484,7 @@ void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, con deselectAll(); } - caret->updatePosition(); + updateCaretPosition(); scrollToKeepCaretOnScreen(); updateScrollBars(); } @@ -548,7 +515,7 @@ void CodeEditorComponent::scrollToLineInternal (int newFirstLineOnScreen) if (newFirstLineOnScreen != firstLineOnScreen) { firstLineOnScreen = newFirstLineOnScreen; - caret->updatePosition(); + updateCaretPosition(); updateCachedIterators (firstLineOnScreen); triggerAsyncUpdate(); @@ -562,7 +529,7 @@ void CodeEditorComponent::scrollToColumnInternal (double column) if (xOffset != newOffset) { xOffset = newOffset; - caret->updatePosition(); + updateCaretPosition(); repaint(); } } @@ -1104,12 +1071,12 @@ void CodeEditorComponent::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, doub //============================================================================== void CodeEditorComponent::focusGained (FocusChangeType) { - caret->updatePosition(); + updateCaretPosition(); } void CodeEditorComponent::focusLost (FocusChangeType) { - caret->updatePosition(); + updateCaretPosition(); } //============================================================================== diff --git a/src/gui/components/code_editor/juce_CodeEditorComponent.h b/src/gui/components/code_editor/juce_CodeEditorComponent.h index d1fd9ee080..3b1d97dae1 100644 --- a/src/gui/components/code_editor/juce_CodeEditorComponent.h +++ b/src/gui/components/code_editor/juce_CodeEditorComponent.h @@ -29,6 +29,7 @@ #include "../juce_Component.h" #include "../layout/juce_ScrollBar.h" #include "../keyboard/juce_TextInputTarget.h" +#include "../keyboard/juce_CaretComponent.h" #include "juce_CodeDocument.h" #include "juce_CodeTokeniser.h" @@ -208,7 +209,6 @@ public: enum ColourIds { backgroundColourId = 0x1004500, /**< A colour to use to fill the editor's background. */ - caretColourId = 0x1004501, /**< The colour to draw the caret. */ highlightColourId = 0x1004502, /**< The colour to use for the highlighted background under selected text. */ defaultTextColourId = 0x1004503 /**< The colour to use for text when no syntax colouring is @@ -270,8 +270,6 @@ private: CodeDocument::Position caretPos; CodeDocument::Position selectionStart, selectionEnd; - class CaretComponent; - friend class ScopedPointer ; ScopedPointer caret; ScrollBar verticalScrollBar, horizontalScrollBar; @@ -299,6 +297,7 @@ private: void moveLineDelta (int delta, bool selecting); //============================================================================== + void updateCaretPosition(); void updateScrollBars(); void scrollToLineInternal (int line); void scrollToColumnInternal (double column); diff --git a/src/gui/components/controls/juce_Label.cpp b/src/gui/components/controls/juce_Label.cpp index cfaab29646..bd6ba5deb1 100644 --- a/src/gui/components/controls/juce_Label.cpp +++ b/src/gui/components/controls/juce_Label.cpp @@ -30,6 +30,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_Label.h" #include "../lookandfeel/juce_LookAndFeel.h" #include "../windows/juce_ComponentPeer.h" +#include "../keyboard/juce_CaretComponent.h" //============================================================================== @@ -311,10 +312,10 @@ TextEditor* Label::createEditorComponent() TextEditor::textColourId, TextEditor::highlightColourId, TextEditor::highlightedTextColourId, - TextEditor::caretColourId, TextEditor::outlineColourId, TextEditor::focusedOutlineColourId, - TextEditor::shadowColourId }; + TextEditor::shadowColourId, + CaretComponent::caretColourId }; for (int i = 0; i < numElementsInArray (cols); ++i) ed->setColour (cols[i], findColour (cols[i])); diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index bd9ca6b7eb..10637c6a32 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -884,6 +884,11 @@ public: owner.drawContent (g); } + void restartTimer() + { + startTimer (350); + } + void timerCallback() { owner.timerCallbackInt(); @@ -943,8 +948,6 @@ private: //============================================================================== namespace TextEditorDefs { - const int flashSpeedIntervalMs = 380; - const int textChangeMessageId = 0x10003001; const int returnKeyMessageId = 0x10003002; const int escapeKeyMessageId = 0x10003003; @@ -968,19 +971,14 @@ TextEditor::TextEditor (const String& name, multiline (false), wordWrap (false), returnKeyStartsNewLine (false), - caretVisible (true), popupMenuEnabled (true), selectAllTextWhenFocused (false), scrollbarVisible (true), wasFocused (false), - caretFlashState (true), keepCursorOnScreen (true), tabKeyUsed (false), menuActive (false), valueTextNeedsUpdating (false), - cursorX (0), - cursorY (0), - cursorHeight (0), maxTextLength (0), leftIndent (4), topIndent (4), @@ -998,8 +996,8 @@ TextEditor::TextEditor (const String& name, viewport->setWantsKeyboardFocus (false); viewport->setScrollBarsShown (false, false); - setMouseCursor (MouseCursor::IBeamCursor); setWantsKeyboardFocus (true); + setCaretVisible (true); } TextEditor::~TextEditor() @@ -1142,15 +1140,26 @@ void TextEditor::colourChanged() void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) { - caretVisible = shouldCaretBeVisible; - - if (shouldCaretBeVisible) - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + if (shouldCaretBeVisible && ! isReadOnly()) + { + if (caret == 0) + textHolder->addChildComponent (caret = getLookAndFeel().createCaretComponent (this)); + } + else + { + caret = 0; + } setMouseCursor (shouldCaretBeVisible ? MouseCursor::IBeamCursor : MouseCursor::NormalCursor); } +void TextEditor::updateCaretPosition() +{ + if (caret != 0) + caret->setCaretPosition (getCaretRectangle().translated (leftIndent, topIndent)); +} + void TextEditor::setInputRestrictions (const int maxLen, const String& chars) { @@ -1279,22 +1288,8 @@ void TextEditor::removeListener (TextEditorListener* const listenerToRemove) //============================================================================== void TextEditor::timerCallbackInt() { - const bool newState = (! caretFlashState) && ! isCurrentlyBlockedByAnotherModalComponent(); - - if (caretFlashState != newState) - { - caretFlashState = newState; - - if (caretFlashState) - wasFocused = true; - - if (caretVisible - && hasKeyboardFocus (false) - && ! isReadOnly()) - { - repaintCaret(); - } - } + if (hasKeyboardFocus (false) && ! isCurrentlyBlockedByAnotherModalComponent()) + wasFocused = true; const unsigned int now = Time::getApproximateMillisecondCounter(); @@ -1302,15 +1297,6 @@ void TextEditor::timerCallbackInt() newTransaction(); } -void TextEditor::repaintCaret() -{ - if (! findColour (caretColourId).isTransparent()) - repaint (borderSize.getLeft() + textHolder->getX() + leftIndent + roundToInt (cursorX) - 1, - borderSize.getTop() + textHolder->getY() + topIndent + roundToInt (cursorY) - 1, - 4, - roundToInt (cursorHeight) + 2); -} - void TextEditor::repaintText (const Range& range) { if (! range.isEmpty()) @@ -1353,12 +1339,10 @@ void TextEditor::moveCaret (int newCaretPos) if (newCaretPos != getCaretPosition()) { - repaintCaret(); - caretFlashState = true; caretPosition = newCaretPos; - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + textHolder->restartTimer(); scrollToMakeSureCursorIsVisible(); - repaintCaret(); + updateCaretPosition(); } } @@ -1378,17 +1362,15 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, { updateCaretPosition(); - int vx = roundToInt (cursorX) - desiredCaretX; - int vy = roundToInt (cursorY) - desiredCaretY; + const Rectangle caretPos (getCaretRectangle()); + + int vx = caretPos.getX() - desiredCaretX; + int vy = caretPos.getY() - desiredCaretY; if (desiredCaretX < jmax (1, proportionOfWidth (0.05f))) - { vx += desiredCaretX - proportionOfWidth (0.2f); - } else if (desiredCaretX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10))) - { vx += desiredCaretX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth(); - } vx = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), vx); @@ -1400,16 +1382,10 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, { vy = jlimit (0, jmax (0, textHolder->getHeight() - viewport->getMaximumVisibleHeight()), vy); - const int curH = roundToInt (cursorHeight); - if (desiredCaretY < 0) - { vy = jmax (0, desiredCaretY + vy); - } - else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) - { - vy += desiredCaretY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); - } + else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - caretPos.getHeight())) + vy += desiredCaretY + 2 + caretPos.getHeight() + topIndent - viewport->getMaximumVisibleHeight(); } viewport->setViewPosition (vx, vy); @@ -1417,18 +1393,18 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, const Rectangle TextEditor::getCaretRectangle() { - updateCaretPosition(); + float cursorX, cursorY; + float cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) + getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); - return Rectangle (roundToInt (cursorX) - viewport->getX(), - roundToInt (cursorY) - viewport->getY(), - 1, roundToInt (cursorHeight)); + return Rectangle (roundToInt (cursorX), roundToInt (cursorY), 2, roundToInt (cursorHeight)); } //============================================================================== float TextEditor::getWordWrapWidth() const { - return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) - : 1.0e10f; + return wordWrap ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) + : std::numeric_limits::max(); } void TextEditor::updateTextHolderSize() @@ -1448,7 +1424,7 @@ void TextEditor::updateTextHolderSize() const int h = topIndent + roundToInt (jmax (i.lineY + i.lineHeight, currentFont.getHeight())); - textHolder->setSize (w + 1, h + 1); + textHolder->setSize (w + 2, h + 1); // (the +2 allows a bit of space for the cursor to be at the right-hand-edge) } } @@ -1485,12 +1461,6 @@ void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) keepCursorOnScreen = shouldScrollToShowCursor; } -void TextEditor::updateCaretPosition() -{ - cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) - getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); -} - void TextEditor::scrollToMakeSureCursorIsVisible() { updateCaretPosition(); @@ -1500,8 +1470,10 @@ void TextEditor::scrollToMakeSureCursorIsVisible() int x = viewport->getViewPositionX(); int y = viewport->getViewPositionY(); - const int relativeCursorX = roundToInt (cursorX) - x; - const int relativeCursorY = roundToInt (cursorY) - y; + const Rectangle caretPos (getCaretRectangle()); + + const int relativeCursorX = caretPos.getX() - x; + const int relativeCursorY = caretPos.getY() - y; if (relativeCursorX < jmax (1, proportionOfWidth (0.05f))) { @@ -1520,15 +1492,13 @@ void TextEditor::scrollToMakeSureCursorIsVisible() } else { - const int curH = roundToInt (cursorHeight); - if (relativeCursorY < 0) { y = jmax (0, relativeCursorY + y); } - else if (relativeCursorY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) + else if (relativeCursorY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - caretPos.getHeight())) { - y += relativeCursorY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); + y += relativeCursorY + 2 + caretPos.getHeight() + topIndent - viewport->getMaximumVisibleHeight(); } } @@ -1720,18 +1690,6 @@ void TextEditor::paint (Graphics& g) void TextEditor::paintOverChildren (Graphics& g) { - if (caretFlashState - && hasKeyboardFocus (false) - && caretVisible - && ! isReadOnly()) - { - g.setColour (findColour (caretColourId)); - - g.fillRect (borderSize.getLeft() + textHolder->getX() + leftIndent + cursorX, - borderSize.getTop() + textHolder->getY() + topIndent + cursorY, - 2.0f, cursorHeight); - } - if (textToShowWhenEmpty.isNotEmpty() && (! hasKeyboardFocus (false)) && getTotalNumChars() == 0) @@ -1803,7 +1761,7 @@ void TextEditor::mouseDrag (const MouseEvent& e) void TextEditor::mouseUp (const MouseEvent& e) { newTransaction(); - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + textHolder->restartTimer(); if (wasFocused || ! selectAllTextWhenFocused) { @@ -1892,6 +1850,7 @@ bool TextEditor::keyPressed (const KeyPress& key) return false; const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); + const Rectangle caretPos (getCaretRectangle().toFloat()); if (key.isKeyCode (KeyPress::leftKey) || key.isKeyCode (KeyPress::upKey)) @@ -1901,7 +1860,7 @@ bool TextEditor::keyPressed (const KeyPress& key) int newPos; if (isMultiLine() && key.isKeyCode (KeyPress::upKey)) - newPos = indexAtPosition (cursorX, cursorY - 1); + newPos = indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f); else if (moveInWholeWordSteps) newPos = findWordBreakBefore (getCaretPosition()); else @@ -1917,7 +1876,7 @@ bool TextEditor::keyPressed (const KeyPress& key) int newPos; if (isMultiLine() && key.isKeyCode (KeyPress::downKey)) - newPos = indexAtPosition (cursorX, cursorY + cursorHeight + 1); + newPos = indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f); else if (moveInWholeWordSteps) newPos = findWordBreakAfter (getCaretPosition()); else @@ -1929,14 +1888,14 @@ bool TextEditor::keyPressed (const KeyPress& key) { newTransaction(); - moveCursorTo (indexAtPosition (cursorX, cursorY + cursorHeight + viewport->getViewHeight()), + moveCursorTo (indexAtPosition (caretPos.getX(), caretPos.getBottom() + viewport->getViewHeight()), key.getModifiers().isShiftDown()); } else if (key.isKeyCode (KeyPress::pageUpKey) && isMultiLine()) { newTransaction(); - moveCursorTo (indexAtPosition (cursorX, cursorY - viewport->getViewHeight()), + moveCursorTo (indexAtPosition (caretPos.getX(), caretPos.getY() - viewport->getViewHeight()), key.getModifiers().isShiftDown()); } else if (key.isKeyCode (KeyPress::homeKey)) @@ -1944,7 +1903,7 @@ bool TextEditor::keyPressed (const KeyPress& key) newTransaction(); if (isMultiLine() && ! moveInWholeWordSteps) - moveCursorTo (indexAtPosition (0.0f, cursorY), + moveCursorTo (indexAtPosition (0.0f, caretPos.getY()), key.getModifiers().isShiftDown()); else moveCursorTo (0, key.getModifiers().isShiftDown()); @@ -1954,7 +1913,7 @@ bool TextEditor::keyPressed (const KeyPress& key) newTransaction(); if (isMultiLine() && ! moveInWholeWordSteps) - moveCursorTo (indexAtPosition ((float) textHolder->getWidth(), cursorY), + moveCursorTo (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()), key.getModifiers().isShiftDown()); else moveCursorTo (getTotalNumChars(), key.getModifiers().isShiftDown()); @@ -2131,8 +2090,6 @@ void TextEditor::focusGained (FocusChangeType) { newTransaction(); - caretFlashState = true; - if (selectAllTextWhenFocused) { moveCursorTo (0, false); @@ -2140,9 +2097,7 @@ void TextEditor::focusGained (FocusChangeType) } repaint(); - - if (caretVisible) - textHolder->startTimer (TextEditorDefs::flashSpeedIntervalMs); + updateCaretPosition(); ComponentPeer* const peer = getPeer(); if (peer != 0 && ! isReadOnly()) @@ -2155,7 +2110,7 @@ void TextEditor::focusLost (FocusChangeType) wasFocused = false; textHolder->stopTimer(); - caretFlashState = false; + updateCaretPosition(); postCommandMessage (TextEditorDefs::focusLossMessageId); repaint(); diff --git a/src/gui/components/controls/juce_TextEditor.h b/src/gui/components/controls/juce_TextEditor.h index d02c69f8bc..268c20cf3c 100644 --- a/src/gui/components/controls/juce_TextEditor.h +++ b/src/gui/components/controls/juce_TextEditor.h @@ -34,6 +34,7 @@ #include "../menus/juce_PopupMenu.h" #include "../../../containers/juce_Value.h" #include "../keyboard/juce_TextInputTarget.h" +#include "../keyboard/juce_CaretComponent.h" //============================================================================== @@ -133,9 +134,7 @@ public: //============================================================================== /** Makes the caret visible or invisible. - By default the caret is visible. - @see setCaretColour, setCaretPosition */ void setCaretVisible (bool shouldBeVisible); @@ -143,7 +142,7 @@ public: /** Returns true if the caret is enabled. @see setCaretVisible */ - bool isCaretVisible() const { return caretVisible; } + bool isCaretVisible() const { return caret != 0; } //============================================================================== /** Enables/disables a vertical scrollbar. @@ -222,8 +221,6 @@ public: highlightedTextColourId = 0x1000203, /**< The colour with which to draw the text in highlighted sections. */ - caretColourId = 0x1000204, /**< The colour with which to draw the caret. */ - outlineColourId = 0x1000205, /**< If this is non-transparent, it will be used to draw a box around the edge of the component. */ @@ -622,19 +619,17 @@ private: bool multiline : 1; bool wordWrap : 1; bool returnKeyStartsNewLine : 1; - bool caretVisible : 1; bool popupMenuEnabled : 1; bool selectAllTextWhenFocused : 1; bool scrollbarVisible : 1; bool wasFocused : 1; - bool caretFlashState : 1; bool keepCursorOnScreen : 1; bool tabKeyUsed : 1; bool menuActive : 1; bool valueTextNeedsUpdating : 1; UndoManager undoManager; - float cursorX, cursorY, cursorHeight; + ScopedPointer caret; int maxTextLength; Range selection; int leftIndent, topIndent; @@ -678,7 +673,6 @@ private: void updateTextHolderSize(); float getWordWrapWidth() const; void timerCallbackInt(); - void repaintCaret(); void repaintText (const Range& range); UndoManager* getUndoManager() throw(); diff --git a/src/gui/components/keyboard/juce_CaretComponent.cpp b/src/gui/components/keyboard/juce_CaretComponent.cpp new file mode 100644 index 0000000000..289e99354b --- /dev/null +++ b/src/gui/components/keyboard/juce_CaretComponent.cpp @@ -0,0 +1,69 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#include "../../../core/juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_CaretComponent.h" + + +//============================================================================== +CaretComponent::CaretComponent (Component* const keyFocusOwner) + : owner (keyFocusOwner) +{ + setAlwaysOnTop (true); + setInterceptsMouseClicks (false, false); +} + +CaretComponent::~CaretComponent() +{ +} + +void CaretComponent::paint (Graphics& g) +{ + g.fillAll (findColour (caretColourId)); +} + +void CaretComponent::timerCallback() +{ + setVisible (shouldBeShown() && ! isVisible()); +} + +void CaretComponent::setCaretPosition (const Rectangle& characterArea) +{ + startTimer (380); + setVisible (shouldBeShown()); + setBounds (characterArea.withWidth (2)); +} + +bool CaretComponent::shouldBeShown() const +{ + return owner == 0 || (owner->hasKeyboardFocus (true) + && ! owner->isCurrentlyBlockedByAnotherModalComponent()); +} + + +END_JUCE_NAMESPACE diff --git a/src/gui/components/keyboard/juce_CaretComponent.h b/src/gui/components/keyboard/juce_CaretComponent.h new file mode 100644 index 0000000000..7ecef28e35 --- /dev/null +++ b/src/gui/components/keyboard/juce_CaretComponent.h @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_CARETCOMPONENT_JUCEHEADER__ +#define __JUCE_CARETCOMPONENT_JUCEHEADER__ + +#include "../juce_Component.h" +#include "../../../events/juce_Timer.h" + + +//============================================================================== +/** +*/ +class JUCE_API CaretComponent : public Component, + public Timer +{ +public: + //============================================================================== + /** Creates the caret component. + The keyFocusOwner is an optional component which the caret will check, making + itself visible only when the keyFocusOwner has keyboard focus. + */ + CaretComponent (Component* keyFocusOwner); + + /** Destructor. */ + ~CaretComponent(); + + //============================================================================== + /** Sets the caret's position to place it next to the given character. + The area is the rectangle containing the entire character that the caret is + positioned on, so by default a vertical-line caret may choose to just show itself + at the left of this area. You can override this method to customise its size. + This method will also force the caret to reset its timer and become visible (if + appropriate), so that as it moves, you can see where it is. + */ + virtual void setCaretPosition (const Rectangle& characterArea); + + /** A set of colour IDs to use to change the colour of various aspects of the caret. + These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() + methods. + @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour + */ + enum ColourIds + { + caretColourId = 0x1000204, /**< The colour with which to draw the caret. */ + }; + + //============================================================================== + /** @internal */ + void paint (Graphics& g); + /** @internal */ + void timerCallback(); + +private: + Component* owner; + bool shouldBeShown() const; + + JUCE_DECLARE_NON_COPYABLE (CaretComponent); +}; + + +#endif // __JUCE_CARETCOMPONENT_JUCEHEADER__ diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index 083510c582..f08583751f 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -52,6 +52,7 @@ BEGIN_JUCE_NAMESPACE #include "../controls/juce_ProgressBar.h" #include "../controls/juce_TreeView.h" #include "../keyboard/juce_KeyMappingEditorComponent.h" +#include "../keyboard/juce_CaretComponent.h" #include "../code_editor/juce_CodeEditorComponent.h" #include "../filebrowser/juce_FilenameComponent.h" #include "../filebrowser/juce_DirectoryContentsDisplayComponent.h" @@ -191,11 +192,12 @@ LookAndFeel::LookAndFeel() TextEditor::textColourId, 0xff000000, TextEditor::highlightColourId, textHighlightColour, TextEditor::highlightedTextColourId, 0xff000000, - TextEditor::caretColourId, 0xff000000, TextEditor::outlineColourId, 0x00000000, TextEditor::focusedOutlineColourId, textButtonColour, TextEditor::shadowColourId, 0x38000000, + CaretComponent::caretColourId, 0xff000000, + Label::backgroundColourId, 0x00000000, Label::textColourId, 0xff000000, Label::outlineColourId, 0x00000000, @@ -278,7 +280,6 @@ LookAndFeel::LookAndFeel() MidiKeyboardComponent::upDownButtonArrowColourId, 0xff000000, CodeEditorComponent::backgroundColourId, 0xffffffff, - CodeEditorComponent::caretColourId, 0xff000000, CodeEditorComponent::highlightColourId, textHighlightColour, CodeEditorComponent::defaultTextColourId, 0xff000000, @@ -1325,6 +1326,11 @@ void LookAndFeel::drawTextEditorOutline (Graphics& g, int width, int height, Tex } } +CaretComponent* LookAndFeel::createCaretComponent (Component* keyFocusOwner) +{ + return new CaretComponent (keyFocusOwner); +} + //============================================================================== void LookAndFeel::drawComboBox (Graphics& g, int width, int height, const bool isButtonDown, diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.h b/src/gui/components/lookandfeel/juce_LookAndFeel.h index 94e70c3e99..0e6270b544 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.h +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.h @@ -59,6 +59,7 @@ class FilePreviewComponent; class ImageButton; class CallOutBox; class Drawable; +class CaretComponent; //============================================================================== /** @@ -294,6 +295,8 @@ public: virtual void fillTextEditorBackground (Graphics& g, int width, int height, TextEditor& textEditor); virtual void drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor); + virtual CaretComponent* createCaretComponent (Component* keyFocusOwner); + //============================================================================== // These return a pointer to an internally cached drawable - make sure you don't keep // a copy of this pointer anywhere, as it may become invalid in the future. diff --git a/src/juce_app_includes.h b/src/juce_app_includes.h index 18a2d53a49..547280f0d3 100644 --- a/src/juce_app_includes.h +++ b/src/juce_app_includes.h @@ -401,6 +401,9 @@ #ifndef __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__ #include "gui/components/juce_ModalComponentManager.h" #endif +#ifndef __JUCE_CARETCOMPONENT_JUCEHEADER__ + #include "gui/components/keyboard/juce_CaretComponent.h" +#endif #ifndef __JUCE_KEYBOARDFOCUSTRAVERSER_JUCEHEADER__ #include "gui/components/keyboard/juce_KeyboardFocusTraverser.h" #endif