From 5435bfcb2641ca371d9ea1c411042f799b2c1e5e Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 7 Nov 2011 17:24:22 +0000 Subject: [PATCH] win32 revealToUser improvement. TextEditor fix. Supprt for cut/copy/paste shortcuts when OSX file browsers are visible. iOS embedded window positioning fix. --- .../native/juce_BasicNativeHeaders.h | 2 +- modules/juce_core/native/juce_win32_Files.cpp | 24 +++++---- .../juce_core/system/juce_StandardHeader.h | 1 + .../components/juce_Component.cpp | 6 +-- .../components/juce_Component.h | 2 +- .../native/juce_ios_UIViewComponentPeer.mm | 44 ++++++++-------- .../native/juce_mac_FileChooser.mm | 51 ++++++++++++++++--- .../widgets/juce_TextEditor.cpp | 10 ++-- 8 files changed, 93 insertions(+), 47 deletions(-) diff --git a/modules/juce_core/native/juce_BasicNativeHeaders.h b/modules/juce_core/native/juce_BasicNativeHeaders.h index 5d9a9dadea..70a5de7607 100644 --- a/modules/juce_core/native/juce_BasicNativeHeaders.h +++ b/modules/juce_core/native/juce_BasicNativeHeaders.h @@ -80,7 +80,7 @@ #define STRICT 1 #define WIN32_LEAN_AND_MEAN 1 - #define _WIN32_WINNT 0x0500 + #define _WIN32_WINNT 0x0600 #define _UNICODE 1 #define UNICODE 1 #ifndef _WIN32_IE diff --git a/modules/juce_core/native/juce_win32_Files.cpp b/modules/juce_core/native/juce_win32_Files.cpp index 27c6139c34..f9b30bab98 100644 --- a/modules/juce_core/native/juce_win32_Files.cpp +++ b/modules/juce_core/native/juce_win32_Files.cpp @@ -168,14 +168,13 @@ bool File::moveToTrash() const if (! exists()) return true; - SHFILEOPSTRUCT fos = { 0 }; - // The string we pass in must be double null terminated.. const int numBytes = CharPointer_UTF16::getBytesRequiredFor (fullPath.getCharPointer()) + 8; HeapBlock doubleNullTermPath; doubleNullTermPath.calloc (numBytes, 1); fullPath.copyToUTF16 (doubleNullTermPath, numBytes); + SHFILEOPSTRUCT fos = { 0 }; fos.wFunc = FO_DELETE; fos.pFrom = doubleNullTermPath; fos.fFlags = FOF_ALLOWUNDO | FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION @@ -645,12 +644,12 @@ public: filenameFound = findData.cFileName; - if (isDir != nullptr) *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); - if (isHidden != nullptr) *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0); - if (fileSize != nullptr) *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32); - if (modTime != nullptr) *modTime = Time (fileTimeToTime (&findData.ftLastWriteTime)); + if (isDir != nullptr) *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + if (isHidden != nullptr) *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0); + if (isReadOnly != nullptr) *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); + if (fileSize != nullptr) *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32); + if (modTime != nullptr) *modTime = Time (fileTimeToTime (&findData.ftLastWriteTime)); if (creationTime != nullptr) *creationTime = Time (fileTimeToTime (&findData.ftCreationTime)); - if (isReadOnly != nullptr) *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); return true; } @@ -695,10 +694,13 @@ bool Process::openDocument (const String& fileName, const String& parameters) void File::revealToUser() const { - if (isDirectory()) - startAsProcess(); - else if (getParentDirectory().exists()) - getParentDirectory().startAsProcess(); + ITEMIDLIST* const itemIDList = ILCreateFromPath (fullPath.toWideCharPointer()); + + if (itemIDList != nullptr) + { + SHOpenFolderAndSelectItems (itemIDList, 0, nullptr, 0); + ILFree (itemIDList); + } } //============================================================================== diff --git a/modules/juce_core/system/juce_StandardHeader.h b/modules/juce_core/system/juce_StandardHeader.h index 328819743a..e4d4291bfd 100644 --- a/modules/juce_core/system/juce_StandardHeader.h +++ b/modules/juce_core/system/juce_StandardHeader.h @@ -68,6 +68,7 @@ template Type abs (Type a) { if (a < 0) return -a; return a; } template Type tan (Type a) { return static_cast (::tan (static_cast (a))); } template Type sin (Type a) { return static_cast (::sin (static_cast (a))); } + template Type asin (Type a) { return static_cast (::asin (static_cast (a))); } template Type cos (Type a) { return static_cast (::cos (static_cast (a))); } template Type sqrt (Type a) { return static_cast (::sqrt (static_cast (a))); } template Type floor (Type a) { return static_cast (::floor (static_cast (a))); } diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index ecca9377a6..f6f8609c6a 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -2383,7 +2383,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r if (! flags.dontFocusOnMouseClickFlag) { - grabFocusInternal (focusChangedByMouseClick); + grabFocusInternal (focusChangedByMouseClick, true); if (checker.shouldBailOut()) return; @@ -2804,7 +2804,7 @@ void Component::grabKeyboardFocus() // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. CHECK_MESSAGE_MANAGER_IS_LOCKED - grabFocusInternal (focusChangedDirectly); + grabFocusInternal (focusChangedDirectly, true); } void Component::moveKeyboardFocusToSibling (const bool moveToNext) @@ -2834,7 +2834,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) return; } - nextComp->grabFocusInternal (focusChangedByTabKey); + nextComp->grabFocusInternal (focusChangedByTabKey, true); return; } } diff --git a/modules/juce_gui_basics/components/juce_Component.h b/modules/juce_gui_basics/components/juce_Component.h index d4b58d296c..90d54b7028 100644 --- a/modules/juce_gui_basics/components/juce_Component.h +++ b/modules/juce_gui_basics/components/juce_Component.h @@ -2324,7 +2324,7 @@ private: void repaintParent(); void sendFakeMouseMove() const; void takeKeyboardFocus (const FocusChangeType); - void grabFocusInternal (const FocusChangeType, bool canTryParent = true); + void grabFocusInternal (const FocusChangeType, bool canTryParent); static void giveAwayFocus (bool sendFocusLossEvent); void sendEnablementChangeMessage(); void sendVisibilityChangeMessage(); diff --git a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm index 89125b40ac..b8418af2d0 100644 --- a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm @@ -160,7 +160,7 @@ public: static Rectangle rotatedScreenPosToReal (const Rectangle& r) { - const Rectangle screen (convertToRectInt ([[UIScreen mainScreen] bounds])); + const Rectangle screen (convertToRectInt ([UIScreen mainScreen].bounds)); switch ([[UIApplication sharedApplication] statusBarOrientation]) { @@ -187,7 +187,7 @@ public: static Rectangle realScreenPosToRotated (const Rectangle& r) { - const Rectangle screen (convertToRectInt ([[UIScreen mainScreen] bounds])); + const Rectangle screen (convertToRectInt ([UIScreen mainScreen].bounds)); switch ([[UIApplication sharedApplication] statusBarOrientation]) { @@ -404,7 +404,7 @@ UIViewComponentPeer::UIViewComponentPeer (Component* const component, controller.view = view; r = convertToCGRect (rotatedScreenPosToReal (component->getBounds())); - r.origin.y = [[UIScreen mainScreen] bounds].size.height - (r.origin.y + r.size.height); + r.origin.y = [UIScreen mainScreen].bounds.size.height - (r.origin.y + r.size.height); window = [[JuceUIWindow alloc] init]; window.frame = r; @@ -480,10 +480,10 @@ void UIViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNo if (isSharedWindow) { - CGRect r = CGRectMake ((float) x, (float) y, (float) w, (float) h); + CGRect r = CGRectMake ((CGFloat) x, (CGFloat) y, (CGFloat) w, (CGFloat) h); - if ([view frame].size.width != r.size.width - || [view frame].size.height != r.size.height) + if (view.frame.size.width != r.size.width + || view.frame.size.height != r.size.height) [view setNeedsDisplay]; view.frame = r; @@ -492,7 +492,7 @@ void UIViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNo { const Rectangle bounds (rotatedScreenPosToReal (Rectangle (x, y, w, h))); window.frame = convertToCGRect (bounds); - view.frame = CGRectMake (0, 0, (float) bounds.getWidth(), (float) bounds.getHeight()); + view.frame = CGRectMake (0, 0, (CGFloat) bounds.getWidth(), (CGFloat) bounds.getHeight()); handleMovedOrResized(); } @@ -500,17 +500,17 @@ void UIViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNo const Rectangle UIViewComponentPeer::getBounds (const bool global) const { - CGRect r = [view frame]; + CGRect r = view.frame; - if (global && [view window] != nil) + if (global && view.window != nil) { r = [view convertRect: r toView: nil]; - CGRect wr = [[view window] frame]; + CGRect wr = view.window.frame; const Rectangle windowBounds (realScreenPosToRotated (convertToRectInt (wr))); - r.origin.x = windowBounds.getX(); - r.origin.y = windowBounds.getY(); + r.origin.x += windowBounds.getX(); + r.origin.y += windowBounds.getY(); } return convertToRectInt (r); @@ -540,10 +540,12 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r) { if (constrainer != nullptr) { - CGRect current = [window frame]; - current.origin.y = [[UIScreen mainScreen] bounds].size.height - current.origin.y - current.size.height; + CGRect mainScreen = [UIScreen mainScreen].bounds; - r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.origin.y - r.size.height; + CGRect current = window.frame; + current.origin.y = mainScreen.size.height - current.origin.y - current.size.height; + + r.origin.y = mainScreen.size.height - r.origin.y - r.size.height; Rectangle pos (convertToRectInt (r)); Rectangle original (convertToRectInt (current)); @@ -551,12 +553,12 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r) constrainer->checkBounds (pos, original, Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), - pos.getX() != original.getX() && pos.getRight() == original.getRight(), + pos.getX() != original.getX() && pos.getRight() == original.getRight(), pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), - pos.getX() == original.getX() && pos.getRight() != original.getRight()); + pos.getX() == original.getX() && pos.getRight() != original.getRight()); r.origin.x = pos.getX(); - r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.size.height - pos.getY(); + r.origin.y = mainScreen.size.height - r.size.height - pos.getY(); r.size.width = pos.getWidth(); r.size.height = pos.getHeight(); } @@ -566,7 +568,7 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r) void UIViewComponentPeer::setAlpha (float newAlpha) { - [[view window] setAlpha: (CGFloat) newAlpha]; + [view.window setAlpha: (CGFloat) newAlpha]; } void UIViewComponentPeer::setMinimised (bool shouldBeMinimised) @@ -634,7 +636,7 @@ void UIViewComponentPeer::displayRotated() fullScreen = false; setFullScreen (true); } - else + else if (! isSharedWindow) { const float l = oldArea.getX() / (float) oldDesktop.getWidth(); const float r = oldArea.getRight() / (float) oldDesktop.getWidth(); @@ -657,7 +659,7 @@ bool UIViewComponentPeer::contains (const Point& position, bool trueIfInACh && isPositiveAndBelow (position.getY(), component->getHeight()))) return false; - UIView* v = [view hitTest: CGPointMake ((float) position.getX(), (float) position.getY()) + UIView* v = [view hitTest: CGPointMake ((CGFloat) position.getX(), (CGFloat) position.getY()) withEvent: nil]; if (trueIfInAChildWindow) diff --git a/modules/juce_gui_basics/native/juce_mac_FileChooser.mm b/modules/juce_gui_basics/native/juce_mac_FileChooser.mm index c7efc0370c..375dbdef2b 100644 --- a/modules/juce_gui_basics/native/juce_mac_FileChooser.mm +++ b/modules/juce_gui_basics/native/juce_mac_FileChooser.mm @@ -98,6 +98,47 @@ bool FileChooser::isPlatformDialogAvailable() return true; } +class TemporaryMainMenuWithStandardCommands +{ +public: + TemporaryMainMenuWithStandardCommands() + : oldMenu (MenuBarModel::getMacMainMenu()) + { + MenuBarModel::setMacMainMenu (nullptr); + + NSMenu* menu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Edit")]; + NSMenuItem* item; + + item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Cut"), nil) + action: @selector (cut:) keyEquivalent: nsStringLiteral ("x")]; + [menu addItem: item]; + [item release]; + + item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Copy"), nil) + action: @selector (copy:) keyEquivalent: nsStringLiteral ("c")]; + [menu addItem: item]; + [item release]; + + item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Paste"), nil) + action: @selector (paste:) keyEquivalent: nsStringLiteral ("v")]; + [menu addItem: item]; + [item release]; + + item = [[NSApp mainMenu] addItemWithTitle: NSLocalizedString (nsStringLiteral ("Edit"), nil) + action: nil keyEquivalent: nsEmptyString()]; + [[NSApp mainMenu] setSubmenu: menu forItem: item]; + [menu release]; + } + + ~TemporaryMainMenuWithStandardCommands() + { + MenuBarModel::setMacMainMenu (oldMenu); + } + +private: + MenuBarModel* oldMenu; +}; + void FileChooser::showPlatformDialog (Array& results, const String& title, const File& currentFileOrDirectory, @@ -111,6 +152,8 @@ void FileChooser::showPlatformDialog (Array& results, { JUCE_AUTORELEASEPOOL + const TemporaryMainMenuWithStandardCommands tempMenu; + StringArray* filters = new StringArray(); filters->addTokens (filter.replaceCharacters (",:", ";;"), ";", String::empty); filters->trim(); @@ -151,8 +194,7 @@ void FileChooser::showPlatformDialog (Array& results, } if ([panel runModalForDirectory: juceStringToNS (directory) - file: juceStringToNS (filename)] - == NSOKButton) + file: juceStringToNS (filename)] == NSOKButton) { if (isSaveDialogue) { @@ -164,10 +206,7 @@ void FileChooser::showPlatformDialog (Array& results, NSArray* urls = [openPanel filenames]; for (unsigned int i = 0; i < [urls count]; ++i) - { - NSString* f = [urls objectAtIndex: i]; - results.add (File (nsStringToJuce (f))); - } + results.add (File (nsStringToJuce ([urls objectAtIndex: i]))); } } diff --git a/modules/juce_gui_basics/widgets/juce_TextEditor.cpp b/modules/juce_gui_basics/widgets/juce_TextEditor.cpp index b6d462624c..9d5932ffea 100644 --- a/modules/juce_gui_basics/widgets/juce_TextEditor.cpp +++ b/modules/juce_gui_basics/widgets/juce_TextEditor.cpp @@ -1229,7 +1229,9 @@ void TextEditor::setText (const String& newText, if (newLength != getTotalNumChars() || getText() != newText) { - const int oldCursorPos = caretPosition; + textValue = newText; + + int oldCursorPos = caretPosition; const bool cursorWasAtEnd = oldCursorPos >= getTotalNumChars(); clearInternal (0); @@ -1240,9 +1242,9 @@ void TextEditor::setText (const String& newText, jassert (multiline || ! newText.containsAnyOf ("\r\n")); if (cursorWasAtEnd && ! isMultiLine()) - moveCaretTo (getTotalNumChars(), false); - else - moveCaretTo (oldCursorPos, false); + oldCursorPos = getTotalNumChars(); + + moveCaretTo (oldCursorPos, false); if (sendTextChangeMessage) textChanged();