Subversion Repositories TruePreview

Compare Revisions

Ignore whitespace Rev 16 → Rev 17

/trunk/Source/TruePreviewLibraryMessage.m
31,12 → 31,39
 
#import "TruePreviewLibraryMessage.h"
 
@implementation LibraryMessage (TruePreviewLibraryMessage)
@implementation TruePreviewLibraryMessage
 
#pragma mark Instance methods
#pragma mark Swizzled instance methods
 
- (void)truePreviewMarkAsViewed {
/* nothing */
}
 
#pragma mark Instance methods
 
- (NSMutableDictionary*)truePreviewSettings {
NSMutableDictionary* theSettings = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[[NSUserDefaults standardUserDefaults] objectForKey:@"TruePreviewDelay"], @"delay",
[[NSUserDefaults standardUserDefaults] objectForKey:@"TruePreviewWindow"], @"window",
[[NSUserDefaults standardUserDefaults] objectForKey:@"TruePreviewScroll"], @"scroll",
nil
];
NSMutableDictionary* theAccountSettings = [
[[NSUserDefaults standardUserDefaults] objectForKey:@"TruePreviewAccountSettings"]
objectForKey:[[self account] displayName]
];
if (theAccountSettings != nil) {
for (id theKey in [NSArray arrayWithObjects:@"delay", @"window", @"scroll", nil]) {
id theValue = [theAccountSettings objectForKey:theKey];
if ((theValue != nil) && ([theValue intValue] != TRUEPREVIEW_DELAY_DEFAULT)) {
[theSettings setObject:theValue forKey:theKey];
}
}
}
return theSettings;
}
 
@end
/trunk/Source/TruePreview.h
41,21 → 41,21
 
#import <objc/objc-class.h>
 
#import <Mail/MVMailBundle.h>
#import <Mail/TableViewManager.h>
#import <Message/LibraryMessage.h>
 
#import "TruePreviewLibraryMessage.h"
#import "TruePreviewMessageViewer.h"
#import "TruePreviewPreferences.h"
#import "TruePreviewPreferencesModule.h"
#import "TruePreviewPreferenceValueTransformer.h"
 
/*!
* @class
* The <code>TruePreview</code> class is the subclass of
* <code>MVMailBundle</code> that provide the plugin entrypoint for the
* <code>MVMailBundle</code> that provides the plugin entrypoint for the
* TruePreview plugin.
* @version \@(#) $Id$
* @updated $Date$
*/
@interface TruePreview : MVMailBundle {
@interface TruePreview : NSObject {
}
 
#pragma mark Class initialization
105,6 → 105,15
/*! @group Class methods */
 
/*!
* Adds the methods from this class to the specified class. This is in essence
* adding a category, but we do it through the objective-c runtime, because of
* the "hiding" of classes in >= 10.6.
* @param inClass
* The <code>Class</code> to which this class's methods should be added.
*/
+ (void)truePreviewAddAsCategoryToClass:(Class)inClass;
 
/*!
* Swaps ("swizzles") two methods. Based on
* <a href="http://www.cocoadev.com/index.pl?MethodSwizzling">http://www.cocoadev.com/index.pl?MethodSwizzling</a>.
* @param inOriginalSelector
/trunk/Source/TruePreview_Prefix.pch
30,5 → 30,11
*/
 
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#import <Cocoa/Cocoa.h>
 
#define TRUEPREVIEW_DELAY_MAX 30
#define TRUEPREVIEW_DELAY_IMMEDIATE 0
#define TRUEPREVIEW_DELAY_DEFAULT -1
#define TRUEPREVIEW_DELAY_NEVER -2
 
#endif
/trunk/Source/TruePreviewPreferences.h
38,21 → 38,20
* @updated $Date$
*/
 
#import <AppKit/NSPreferences.h>
 
#import "TruePreview.h"
 
/*!
* @category
* @class
* Adds a method for overriding the preference-loading behavior of
* <code>NSPreferences</code>.
* @version \@(#) $Id$
* @updated $Date$
*/
@interface NSPreferences (TruePreviewPreferences)
@interface TruePreviewPreferences : NSObject {
}
 
#pragma mark Class methods
/*! @group Class methods */
#pragma mark Swizzled class methods
/*! @group Swizzled class methods */
 
/*!
* Adds the TruePreview preferences.
/trunk/Source/TruePreview.m
36,31 → 36,79
#pragma mark Class initialization
 
+ (void)initialize {
[TruePreview registerBundle];
if (self == [TruePreview class]) {
class_setSuperclass(self, NSClassFromString(@"MVMailBundle"));
}
 
[super registerBundle];
// register the preferences value transformers
[NSValueTransformer
setValueTransformer:[[TruePreviewPreferenceValueTransformer alloc] init]
forName:@"TruePreviewPreferenceValueTransformer"
];
[NSValueTransformer
setValueTransformer:[[TruePreviewPreferenceValueTransformerDelay alloc] init]
forName:@"TruePreviewPreferenceValueTransformerDelay"
];
[NSValueTransformer
setValueTransformer:[[TruePreviewPreferenceValueTransformerDelayEditIndicator alloc] init]
forName:@"TruePreviewPreferenceValueTransformerDelayEditIndicator"
];
// add our "categories"
[TruePreviewLibraryMessage truePreviewAddAsCategoryToClass:NSClassFromString(@"LibraryMessage")];
[TruePreviewMessageViewer truePreviewAddAsCategoryToClass:NSClassFromString(@"MessageViewer")];
[TruePreviewPreferences truePreviewAddAsCategoryToClass:NSClassFromString(@"NSPreferences")];
// do our swizzles
[NSPreferences
truePreviewSwizzleMethod:@selector(sharedPreferences)
withMethod:@selector(truePreviewSharedPreferences)
isClassMethod:YES
];
[LibraryMessage
[NSClassFromString(@"LibraryMessage")
truePreviewSwizzleMethod:@selector(markAsViewed)
withMethod:@selector(truePreviewMarkAsViewed)
isClassMethod:NO
];
[TableViewManager
truePreviewSwizzleMethod:@selector(setCurrentDisplayedMessage:)
withMethod:@selector(truePreviewSetCurrentDisplayedMessage:)
[NSClassFromString(@"MessageViewer")
truePreviewSwizzleMethod:@selector(dealloc)
withMethod:@selector(truePreviewDealloc)
isClassMethod:NO
];
[NSClassFromString(@"MessageViewer")
truePreviewSwizzleMethod:@selector(markAsRead:)
withMethod:@selector(truePreviewMarkAsRead:)
isClassMethod:NO
];
[NSClassFromString(@"MessageViewer")
truePreviewSwizzleMethod:@selector(markAsUnread:)
withMethod:@selector(truePreviewMarkAsUnread:)
isClassMethod:NO
];
[NSClassFromString(@"MessageViewer")
truePreviewSwizzleMethod:@selector(messageWasDisplayedInTextView:)
withMethod:@selector(truePreviewMessageWasDisplayedInTextView:)
isClassMethod:NO
];
[NSClassFromString(@"MessageViewer")
truePreviewSwizzleMethod:@selector(messageNoLongerDisplayedInTextView:)
withMethod:@selector(truePreviewMessageNoLongerDisplayedInTextView:)
isClassMethod:NO
];
[NSClassFromString(@"NSPreferences")
truePreviewSwizzleMethod:@selector(sharedPreferences)
withMethod:@selector(truePreviewSharedPreferences)
isClassMethod:YES
];
// set defaults
[[NSUserDefaults standardUserDefaults]
registerDefaults:[NSDictionary
dictionaryWithObject:[NSNumber numberWithInt:0] forKey:@"TruePreviewDelay"
registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:TRUEPREVIEW_DELAY_IMMEDIATE], @"TruePreviewDelay",
[NSNumber numberWithInt:NSOnState], @"TruePreviewWindow",
[NSNumber numberWithInt:NSOffState], @"TruePreviewScroll",
nil
]
];
// we're all set
NSLog(
@"Loaded TruePreview plugin %@",
[[NSBundle bundleForClass:[TruePreview class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]
74,7 → 122,7
}
 
+ (NSString*)preferencesOwnerClassName {
return NSStringFromClass([TruePreviewPreferencesModule class]);
return @"TruePreviewPreferencesModule";
}
 
+ (NSString*)preferencesPanelName {
87,6 → 135,44
 
#pragma mark Class methods
 
+ (void)truePreviewAddAsCategoryToClass:(Class)inClass {
unsigned int theCount = 0;
Method* theMethods = class_copyMethodList(object_getClass([self class]), &theCount);
Class theClass = object_getClass(inClass);
unsigned int i = 0;
while (YES) {
for (i = 0; i < theCount; i++) {
if (
!class_addMethod(
theClass,
method_getName(theMethods[i]),
method_getImplementation(theMethods[i]),
method_getTypeEncoding(theMethods[i])
)
) {
NSLog(
@"truePreviewAddAsCategoryToClass: could not add %@ to %@",
NSStringFromSelector(method_getName(theMethods[i])),
inClass
);
}
}
if (theMethods != nil) {
free(theMethods);
}
if (theClass != inClass) {
theClass = inClass;
theMethods = class_copyMethodList([self class], &theCount);
}
else {
break;
}
}
}
 
+ (void)truePreviewSwizzleMethod:(SEL)inOriginalSelector withMethod:(SEL)inReplacementSelector isClassMethod:(BOOL)inIsClassMethod {
Method theOriginalMethod = (!inIsClassMethod
? class_getInstanceMethod([self class], inOriginalSelector)
97,19 → 183,7
: class_getClassMethod([self class], inReplacementSelector)
);
 
#if __OBJC2__
method_exchangeImplementations(theOriginalMethod, theReplacementMethod);
#else
char* theOriginalTypes = theOriginalMethod->method_types;
 
theOriginalMethod->method_types = theReplacementMethod->method_types;
theReplacementMethod->method_types = theOriginalTypes;
 
IMP theOriginalImp = theOriginalMethod->method_imp;
theOriginalMethod->method_imp = theReplacementMethod->method_imp;
theReplacementMethod->method_imp = theOriginalImp;
#endif
}
 
@end
/trunk/Source/TruePreviewPreferences.m
31,24 → 31,24
 
#import "TruePreviewPreferences.h"
 
@implementation NSPreferences (TruePreviewPreferences)
@implementation TruePreviewPreferences
 
#pragma mark Class methods
#pragma mark Swizzled class methods
 
+ (id)truePreviewSharedPreferences {
static BOOL sAdded = NO;
NSPreferences* thePreferences = [NSPreferences truePreviewSharedPreferences];
id thePreferences = [NSClassFromString(@"NSPreferences") truePreviewSharedPreferences];
if ((thePreferences != nil) && !sAdded) {
sAdded = YES;
[[NSPreferences truePreviewSharedPreferences]
[[NSClassFromString(@"NSPreferences") truePreviewSharedPreferences]
addPreferenceNamed:[TruePreview preferencesPanelName]
owner:[TruePreviewPreferencesModule sharedInstance]
];
}
return [NSPreferences truePreviewSharedPreferences];
return [NSClassFromString(@"NSPreferences") truePreviewSharedPreferences];
}
 
@end
/trunk/Source/TruePreviewPreferencesModule.h
38,12 → 38,8
* @updated $Date$
*/
 
#import <AppKit/NSPreferences.h>
#import <AppKit/NSPreferencesModule.h>
#import <Message/MailAccount.h>
 
#import "TruePreview.h"
 
/*!
* @class
* The <code>TruePreviewPreferencesModule</code> class is the subclass of
/trunk/Source/TruePreviewLibraryMessage.h
38,26 → 38,38
* @updated $Date$
*/
 
#import <Message/LibraryMessage.h>
 
#import "TruePreview.h"
 
/*!
* @category
* @class
* Adds a method for overriding the "mark as viewed" behavior of
* <code>LibraryMessage</code>.
* @version \@(#) $Id$
* @updated $Date$
*/
@interface LibraryMessage (TruePreviewLibraryMessage)
@interface TruePreviewLibraryMessage : NSObject {
}
 
#pragma mark Instance methods
/*! @group Instance methods */
#pragma mark Swizzled instance methods
/*! @group Swizzled instance methods */
 
/*!
* Does nothing. The replacement behavior is handled in
* <code>-[TableViewManager setCurrentDisplayedMessage]</code>.
* <code>TruePreviewMessageViewer</code>.
*/
- (void)truePreviewMarkAsViewed;
 
#pragma mark Instance methods
/*! @group Instance methods */
 
/*!
* Returns the TruePreview settings appropriate for this message.
* @result
* An <code>NSMutableDictionary</code> containing the keys <code>delay</code>,
* <code>window</code>, and <code>scroll</code> and their respective values
* based on the default settings and/or the settings for this message's
* account.
*/
- (NSMutableDictionary*)truePreviewSettings;
 
@end
/trunk/Source/TruePreviewPreferencesModule.m
41,39 → 41,49
 
- (void)willBeDisplayed {
[super willBeDisplayed];
 
// build the list of accounts
NSDictionary* theAccountDict = [[NSUserDefaults standardUserDefaults] objectForKey:@"TruePreviewAccountSettings"];
NSMutableArray* theAccounts = [NSMutableArray array];
NSEnumerator* theEnum = [[[MailAccount remoteAccounts] valueForKey:@"displayName"] objectEnumerator];
NSEnumerator* theEnum = [[[NSClassFromString(@"MailAccount") remoteAccounts] valueForKey:@"displayName"] objectEnumerator];
NSString* theDisplayName = nil;
 
while (theDisplayName = [theEnum nextObject]) {
NSMutableDictionary* theAccount = [[theAccountDict objectForKey:theDisplayName] mutableCopy];
[theAccounts
addObject:((theAccount == nil)
? [NSMutableDictionary dictionaryWithObject:theDisplayName forKey:@"displayName"]
: theAccount
)
NSMutableDictionary* theAccount = [NSMutableDictionary dictionaryWithObjectsAndKeys:
theDisplayName, @"displayName",
[NSNumber numberWithInt:TRUEPREVIEW_DELAY_DEFAULT], @"delay",
[NSNumber numberWithInt:TRUEPREVIEW_DELAY_DEFAULT], @"window",
[NSNumber numberWithInt:TRUEPREVIEW_DELAY_DEFAULT], @"scroll",
nil
];
[theAccount addEntriesFromDictionary:[theAccountDict objectForKey:theDisplayName]];
[theAccounts addObject:theAccount];
}
 
// watch the array for changes to save the user defaults
[theAccounts
addObserver:self
toObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [theAccounts count])]
forKeyPath:@"custom"
forKeyPath:@"delay"
options:0
context:theAccounts
];
[theAccounts
addObserver:self
toObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [theAccounts count])]
forKeyPath:@"delay"
forKeyPath:@"window"
options:0
context:theAccounts
];
[theAccounts
addObserver:self
toObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [theAccounts count])]
forKeyPath:@"scroll"
options:0
context:theAccounts
];
 
[fldAccountArrayController setContent:theAccounts];
}
 
93,6 → 103,7
}
[[NSUserDefaults standardUserDefaults] setObject:theAccountDict forKey:@"TruePreviewAccountSettings"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
 
@end