From 71a12a140e509a02324c725bfbb1a4413acb16d8 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Tue, 8 Dec 2009 11:24:09 +0000 Subject: [PATCH] Improved CoreGraphics clipping. Added a method File::revealToUser(). Added obj-c keywords to the c++ tokeniser. Added a new mode to the file chooser (only implemented on mac so far) --- src/containers/juce_Variant.cpp | 21 ++++++++++++++++ src/containers/juce_Variant.h | 3 +++ .../juce_CPlusPlusCodeTokeniser.cpp | 8 +++--- .../filebrowser/juce_FileChooser.cpp | 24 +++++++++++------- .../components/filebrowser/juce_FileChooser.h | 13 ++++++++-- src/io/files/juce_File.h | 7 ++++++ src/native/linux/juce_linux_AudioCDReader.cpp | 2 +- src/native/linux/juce_linux_FileChooser.cpp | 1 + src/native/linux/juce_linux_Files.cpp | 15 ++++++++--- .../mac/juce_mac_CoreGraphicsContext.mm | 25 +++++++++++++------ src/native/mac/juce_mac_FileChooser.mm | 4 ++- src/native/mac/juce_mac_Files.mm | 10 ++++++++ src/native/windows/juce_win32_FileChooser.cpp | 1 + src/native/windows/juce_win32_Files.cpp | 8 ++++++ src/text/juce_XmlElement.cpp | 2 +- 15 files changed, 115 insertions(+), 29 deletions(-) diff --git a/src/containers/juce_Variant.cpp b/src/containers/juce_Variant.cpp index 08f30d93a6..9802928e44 100644 --- a/src/containers/juce_Variant.cpp +++ b/src/containers/juce_Variant.cpp @@ -279,6 +279,27 @@ DynamicObject* var::getObject() const throw() return type == objectType ? value.objectValue : 0; } +bool var::operator== (const var& other) const throw() +{ + switch (type) + { + case voidType: return other.isVoid(); + case intType: return value.intValue == (int) other; + case boolType: return value.boolValue == (bool) other; + case doubleType: return value.doubleValue == (double) other; + case stringType: return (*(value.stringValue)) == other.toString(); + case objectType: return value.objectValue == other.getObject(); + default: jassertfalse; break; + } + + return false; +} + +bool var::operator!= (const var& other) const throw() +{ + return ! operator== (other); +} + const var var::operator[] (const var::identifier& propertyName) const throw() { if (type == objectType && value.objectValue != 0) diff --git a/src/containers/juce_Variant.h b/src/containers/juce_Variant.h index f6d98bf657..ad0845fded 100644 --- a/src/containers/juce_Variant.h +++ b/src/containers/juce_Variant.h @@ -91,6 +91,9 @@ public: bool isObject() const throw() { return type == objectType; } bool isMethod() const throw() { return type == methodType; } + bool operator== (const var& other) const throw(); + bool operator!= (const var& other) const throw(); + //============================================================================== class JUCE_API identifier { diff --git a/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp b/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp index 5e01ca0330..0c09b1c009 100644 --- a/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp +++ b/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp @@ -46,14 +46,14 @@ namespace CppTokeniser static bool isIdentifierStart (const tchar c) throw() { return CharacterFunctions::isLetter (c) - || c == T('_'); + || c == T('_') || c == T('@'); } static bool isIdentifierBody (const tchar c) throw() { return CharacterFunctions::isLetter (c) || CharacterFunctions::isDigit (c) - || c == T('_'); + || c == T('_') || c == T('@'); } static int parseIdentifier (CodeDocument::Iterator& source) throw() @@ -80,7 +80,9 @@ static int parseIdentifier (CodeDocument::Iterator& source) throw() static const tchar* keywordsOther[] = { T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"), T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"), - T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), 0 }; + T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), + T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"), + T("@private"), T("@property"), T("@protected"), T("@class"), 0 }; int tokenLength = 0; tchar possibleIdentifier [19]; diff --git a/src/gui/components/filebrowser/juce_FileChooser.cpp b/src/gui/components/filebrowser/juce_FileChooser.cpp index 25a70c8693..4ccf9a8e3f 100644 --- a/src/gui/components/filebrowser/juce_FileChooser.cpp +++ b/src/gui/components/filebrowser/juce_FileChooser.cpp @@ -58,22 +58,27 @@ FileChooser::~FileChooser() bool FileChooser::browseForFileToOpen (FilePreviewComponent* previewComponent) { - return showDialog (false, false, false, false, previewComponent); + return showDialog (false, true, false, false, false, previewComponent); } bool FileChooser::browseForMultipleFilesToOpen (FilePreviewComponent* previewComponent) { - return showDialog (false, false, false, true, previewComponent); + return showDialog (false, true, false, false, true, previewComponent); +} + +bool FileChooser::browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent) +{ + return showDialog (true, true, false, false, true, previewComponent); } bool FileChooser::browseForFileToSave (const bool warnAboutOverwritingExistingFiles) { - return showDialog (false, true, warnAboutOverwritingExistingFiles, false, 0); + return showDialog (false, true, true, warnAboutOverwritingExistingFiles, false, 0); } bool FileChooser::browseForDirectory() { - return showDialog (true, false, false, false, 0); + return showDialog (true, false, false, false, false, 0); } const File FileChooser::getResult() const @@ -95,7 +100,8 @@ const OwnedArray & FileChooser::getResults() const return results; } -bool FileChooser::showDialog (const bool isDirectory, +bool FileChooser::showDialog (const bool selectsDirectories, + const bool selectsFiles, const bool isSave, const bool warnAboutOverwritingExistingFiles, const bool selectMultipleFiles, @@ -120,7 +126,7 @@ bool FileChooser::showDialog (const bool isDirectory, #endif { showPlatformDialog (results, title, startingFile, filters, - isDirectory, isSave, + selectsDirectories, selectsFiles, isSave, warnAboutOverwritingExistingFiles, selectMultipleFiles, previewComponent); @@ -131,9 +137,9 @@ bool FileChooser::showDialog (const bool isDirectory, WildcardFileFilter wildcard (filters, String::empty); - FileBrowserComponent browserComponent (isDirectory ? FileBrowserComponent::chooseDirectoryMode - : (isSave ? FileBrowserComponent::saveFileMode - : FileBrowserComponent::loadFileMode), + FileBrowserComponent browserComponent (selectsDirectories ? FileBrowserComponent::chooseDirectoryMode + : (isSave ? FileBrowserComponent::saveFileMode + : FileBrowserComponent::loadFileMode), startingFile, &wildcard, previewComponent); FileChooserDialogBox box (title, String::empty, diff --git a/src/gui/components/filebrowser/juce_FileChooser.h b/src/gui/components/filebrowser/juce_FileChooser.h index a298635105..1fa99874a7 100644 --- a/src/gui/components/filebrowser/juce_FileChooser.h +++ b/src/gui/components/filebrowser/juce_FileChooser.h @@ -136,6 +136,13 @@ public: */ bool browseForDirectory(); + /** Same as browseForFileToOpen, but allows the user to select multiple files and directories. + + The files that are returned can be obtained by calling getResults(). See + browseForFileToOpen() for more info about the behaviour of this method. + */ + bool browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent = 0); + //============================================================================== /** Returns the last file that was chosen by one of the browseFor methods. @@ -171,7 +178,8 @@ private: OwnedArray results; bool useNativeDialogBox; - bool showDialog (const bool isDirectory, + bool showDialog (const bool selectsDirectories, + const bool selectsFiles, const bool isSave, const bool warnAboutOverwritingExistingFiles, const bool selectMultipleFiles, @@ -181,7 +189,8 @@ private: const String& title, const File& file, const String& filters, - bool isDirectory, + bool selectsDirectories, + bool selectsFiles, bool isSave, bool warnAboutOverwritingExistingFiles, bool selectMultipleFiles, diff --git a/src/io/files/juce_File.h b/src/io/files/juce_File.h index 745475b619..48347d8ee9 100644 --- a/src/io/files/juce_File.h +++ b/src/io/files/juce_File.h @@ -729,9 +729,16 @@ public: default viewer application. - if it's a folder, it will be opened in Explorer, Finder, or equivalent. + + @see revealToUser */ bool startAsProcess (const String& parameters = String::empty) const throw(); + /** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location. + @see startAsProcess + */ + void revealToUser() const throw(); + //============================================================================== /** A set of types of location that can be passed to the getSpecialLocation() method. */ diff --git a/src/native/linux/juce_linux_AudioCDReader.cpp b/src/native/linux/juce_linux_AudioCDReader.cpp index 33f7923730..65257511e3 100644 --- a/src/native/linux/juce_linux_AudioCDReader.cpp +++ b/src/native/linux/juce_linux_AudioCDReader.cpp @@ -25,7 +25,7 @@ // (This file gets included by juce_linux_NativeCode.cpp, rather than being // compiled on its own). -#if JUCE_INCLUDED_FILE +#if JUCE_INCLUDED_FILE && JUCE_USE_CDREADER //============================================================================== diff --git a/src/native/linux/juce_linux_FileChooser.cpp b/src/native/linux/juce_linux_FileChooser.cpp index 9a5b921cca..d786fdf23e 100644 --- a/src/native/linux/juce_linux_FileChooser.cpp +++ b/src/native/linux/juce_linux_FileChooser.cpp @@ -33,6 +33,7 @@ void FileChooser::showPlatformDialog (OwnedArray& results, const File& file, const String& filters, bool isDirectory, + bool selectsFiles, bool isSave, bool warnAboutOverwritingExistingFiles, bool selectMultipleFiles, diff --git a/src/native/linux/juce_linux_Files.cpp b/src/native/linux/juce_linux_Files.cpp index d48fe4c39e..c7f16d9ebd 100644 --- a/src/native/linux/juce_linux_Files.cpp +++ b/src/native/linux/juce_linux_Files.cpp @@ -417,10 +417,11 @@ bool juce_launchFile (const String& fileName, cmdString << " " << parameters; if (URL::isProbablyAWebsiteURL (fileName) + || cmdString.startsWithIgnoreCase (T("file:")) || URL::isProbablyAnEmailAddress (fileName)) { // create a command that tries to launch a bunch of likely browsers - const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; + const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; StringArray cmdLines; @@ -430,9 +431,6 @@ bool juce_launchFile (const String& fileName, cmdString = cmdLines.joinIntoString (T(" || ")); } - if (cmdString.startsWithIgnoreCase (T("file:"))) - cmdString = cmdString.substring (5); - const char* const argv[4] = { "/bin/sh", "-c", (const char*) cmdString.toUTF8(), 0 }; const int cpid = fork(); @@ -449,4 +447,13 @@ bool juce_launchFile (const String& fileName, return cpid >= 0; } +void File::revealToUser() const throw() +{ + if (isDirectory()) + startAsProcess(); + else if (getParentDirectory().exists()) + getParentDirectory().startAsProcess(); +} + + #endif diff --git a/src/native/mac/juce_mac_CoreGraphicsContext.mm b/src/native/mac/juce_mac_CoreGraphicsContext.mm index 992a694686..45a6f90615 100644 --- a/src/native/mac/juce_mac_CoreGraphicsContext.mm +++ b/src/native/mac/juce_mac_CoreGraphicsContext.mm @@ -172,18 +172,27 @@ public: bool clipToRectangleList (const RectangleList& clipRegion) { - const int numRects = clipRegion.getNumRectangles(); - CGRect* const rects = new CGRect [numRects]; - for (int i = 0; i < numRects; ++i) + if (clipRegion.isEmpty()) { - const Rectangle& r = clipRegion.getRectangle(i); - rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); + CGContextClipToRect (context, CGRectMake (0, 0, 0, 0)); + return false; } + else + { + const int numRects = clipRegion.getNumRectangles(); - CGContextClipToRects (context, rects, numRects); - delete[] rects; + CGRect* const rects = new CGRect [numRects]; + for (int i = 0; i < numRects; ++i) + { + const Rectangle& r = clipRegion.getRectangle(i); + rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); + } - return ! isClipEmpty(); + CGContextClipToRects (context, rects, numRects); + delete[] rects; + + return ! isClipEmpty(); + } } void excludeClipRectangle (const Rectangle& r) diff --git a/src/native/mac/juce_mac_FileChooser.mm b/src/native/mac/juce_mac_FileChooser.mm index 20d13f8abc..66eaef158a 100644 --- a/src/native/mac/juce_mac_FileChooser.mm +++ b/src/native/mac/juce_mac_FileChooser.mm @@ -84,6 +84,7 @@ void FileChooser::showPlatformDialog (OwnedArray& results, const File& currentFileOrDirectory, const String& filter, bool selectsDirectory, + bool selectsFiles, bool isSaveDialogue, bool warnAboutOverwritingExistingFiles, bool selectMultipleFiles, @@ -108,7 +109,7 @@ void FileChooser::showPlatformDialog (OwnedArray& results, { NSOpenPanel* openPanel = (NSOpenPanel*) panel; [openPanel setCanChooseDirectories: selectsDirectory]; - [openPanel setCanChooseFiles: ! selectsDirectory]; + [openPanel setCanChooseFiles: selectsFiles]; [openPanel setAllowsMultipleSelection: selectMultipleFiles]; } @@ -157,6 +158,7 @@ void FileChooser::showPlatformDialog (OwnedArray& results, const File& currentFileOrDirectory, const String& filter, bool selectsDirectory, + bool selectsFiles, bool isSaveDialogue, bool warnAboutOverwritingExistingFiles, bool selectMultipleFiles, diff --git a/src/native/mac/juce_mac_Files.mm b/src/native/mac/juce_mac_Files.mm index f0d2094cd2..72cedef12f 100644 --- a/src/native/mac/juce_mac_Files.mm +++ b/src/native/mac/juce_mac_Files.mm @@ -497,6 +497,16 @@ bool juce_launchFile (const String& fileName, #endif } +void File::revealToUser() const throw() +{ +#if ! JUCE_IPHONE + if (exists()) + [[NSWorkspace sharedWorkspace] selectFile: juceStringToNS (getFullPathName()) inFileViewerRootedAtPath: @""]; + else if (getParentDirectory().exists()) + getParentDirectory().revealToUser(); +#endif +} + //============================================================================== #if ! JUCE_IPHONE bool PlatformUtilities::makeFSRefFromPath (FSRef* destFSRef, const String& path) diff --git a/src/native/windows/juce_win32_FileChooser.cpp b/src/native/windows/juce_win32_FileChooser.cpp index b2fbb95233..e96338c719 100644 --- a/src/native/windows/juce_win32_FileChooser.cpp +++ b/src/native/windows/juce_win32_FileChooser.cpp @@ -148,6 +148,7 @@ void FileChooser::showPlatformDialog (OwnedArray& results, const File& currentFileOrDirectory, const String& filter, bool selectsDirectory, + bool selectsFiles, bool isSaveDialogue, bool warnAboutOverwritingExistingFiles, bool selectMultipleFiles, diff --git a/src/native/windows/juce_win32_Files.cpp b/src/native/windows/juce_win32_Files.cpp index 1f927c8c05..0644f1a30e 100644 --- a/src/native/windows/juce_win32_Files.cpp +++ b/src/native/windows/juce_win32_Files.cpp @@ -677,6 +677,14 @@ bool juce_launchFile (const String& fileName, return hInstance > (HINSTANCE) 32; } +void File::revealToUser() const throw() +{ + if (isDirectory()) + startAsProcess(); + else if (getParentDirectory().exists()) + getParentDirectory().startAsProcess(); +} + //============================================================================== struct NamedPipeInternal { diff --git a/src/text/juce_XmlElement.cpp b/src/text/juce_XmlElement.cpp index fb780c2181..09d4972a07 100644 --- a/src/text/juce_XmlElement.cpp +++ b/src/text/juce_XmlElement.cpp @@ -1110,7 +1110,7 @@ const String XmlElement::getText() const throw() { jassert (isTextElement()); // you're trying to get the text from an element that // isn't actually a text element.. If this contains text sub-nodes, you - // can use getAllSubText instead to + // probably want to use getAllSubText instead. return getStringAttribute (juce_xmltextContentAttributeName); }