Subversion Repositories TruePreview

[/] [trunk/] [Source/] [TruePreviewMessageViewer.m] - Blame information for rev 14

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jhriggs
/*
2
 * Copyright (c) 2009, Jim Riggs, Christian Serving, L.L.C.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are
7
 * met:
8
 *     * Redistributions of source code must retain the above copyright
9
 *       notice, this list of conditions and the following disclaimer.
10
 *     * Redistributions in binary form must reproduce the above
11
 *       copyright notice, this list of conditions and the following
12
 *       disclaimer in the documentation and/or other materials provided
13
 *       with the distribution.
14
 *     * Neither the name of Christian Serving, L.L.C. nor the names of
15
 *       its contributors may be used to endorse or promote products
16
 *       derived from this software without specific prior written
17
 *       permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 */
31
 
32
#import "TruePreviewMessageViewer.h"
33
 
34
@implementation TruePreviewMessageViewer
35
 
36
#pragma mark Class methods
37
 
38
+ (NSMutableDictionary*)truePreviewTimers {
39
  static NSMutableDictionary* sTimers = nil;
40
 
41
  if (sTimers == nil) {
42
    sTimers = [[NSMutableDictionary alloc] initWithCapacity:1];
43
  }
44
 
45
  return sTimers;
46
}
47
 
48
#pragma mark Swizzled instance methods
49
 
50
- (void)truePreviewDealloc {
51
  [self truePreviewReset];
52
  [[[self class] truePreviewTimers]
53
    removeObjectForKey:[NSNumber numberWithUnsignedLong:(unsigned long)self]
54
  ];
55
  [self truePreviewDealloc];
56
}
57
 
58
- (void)truePreviewMarkAsRead:(id)inSender {
59
  [self truePreviewReset];
60
  [self truePreviewMarkAsRead:inSender];
61
}
62
 
63
- (void)truePreviewMarkAsUnread:(id)inSender {
64
  [self truePreviewReset];
65
  [self truePreviewMarkAsUnread:inSender];
66
}
67
 
68
- (void)truePreviewMessageWasDisplayedInTextView:(NSNotification*)inNotification {
69
  [self truePreviewMessageWasDisplayedInTextView:inNotification];
70
 
71
  id theMessage = [[inNotification userInfo] objectForKey:@"MessageKey"];
72
 
73
  if ([theMessage isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
74
    NSDictionary* theSettings = [theMessage truePreviewSettings];
75
 
76
    if (
77
      ([[theSettings objectForKey:@"delay"] floatValue] == TRUEPREVIEW_DELAY_IMMEDIATE)
78
      || (
79
        [[theSettings objectForKey:@"window"] boolValue]
80
        && [self isKindOfClass:NSClassFromString(@"SingleMessageViewer")]
81
      )        
82
    ) {
83
      [self truePreviewReset];
84
      [theMessage truePreviewMarkAsViewed];
85
 
86
      return;
87
    }
88
 
89
    float theDelay = [[theSettings objectForKey:@"delay"] floatValue];
90
 
91
    if (theDelay > TRUEPREVIEW_DELAY_IMMEDIATE) {
92
      [self truePreviewReset];
93
      [self
94
        truePreviewSetTimer:[NSTimer
95
          scheduledTimerWithTimeInterval:theDelay
96
          target:self
97
          selector:@selector(truePreviewTimerFired:)
98
          userInfo:nil
99
          repeats:NO
100
        ]
101
      ];
102
    }
103
 
104
    if ([[theSettings objectForKey:@"scroll"] boolValue]) {
105
      // listen for bounds change notification on the message's clip view
106
      [[NSNotificationCenter defaultCenter]
107
       addObserver:self
108
       selector:@selector(truePreviewBoundsDidChange:)
109
       name:NSViewBoundsDidChangeNotification
110
       object:[[[[object_getIvar(self, class_getInstanceVariable([self class], "_contentController")) currentDisplay] contentView] enclosingScrollView] contentView]
111
       ];
112
    }    
113
  }
114
}
115
 
116
- (void)truePreviewMessageNoLongerDisplayedInTextView:(NSNotification*)inNotification {
117
  [self truePreviewMessageNoLongerDisplayedInTextView:inNotification];
118
  [self truePreviewReset];
119
}
120
 
121
#pragma mark Accessors
122
 
123
- (NSTimer*)truePreviewTimer {
124
  return [[[self class] truePreviewTimers]
125
    objectForKey:[NSNumber numberWithUnsignedLong:(unsigned long)self]
126
  ];
127
}
128
 
129
- (void)truePreviewSetTimer:(NSTimer*)inTimer {
130
  [[[self class] truePreviewTimers]
131
    setObject:inTimer
132
    forKey:[NSNumber numberWithUnsignedLong:(unsigned long)self]
133
  ];
134
}
135
 
136
#pragma mark Instance methods
137
 
138
- (void)truePreviewReset {
139
  NSTimer* theTimer = [self truePreviewTimer];
140
 
141
  if ((theTimer != nil) && [theTimer isValid]) {
142
    [theTimer invalidate];
143
  }
144
 
145
  // stop observing when changed
146
  [[NSNotificationCenter defaultCenter]
147
    removeObserver:self
148
    name:NSViewBoundsDidChangeNotification
149
    object:[[[[object_getIvar(self, class_getInstanceVariable([self class], "_contentController")) currentDisplay] contentView] enclosingScrollView] contentView]
150
  ];
151
}
152
 
153
- (void)truePreviewTimerFired:(NSTimer*)inTimer {
154
  [self truePreviewReset];
155
 
156
  if ([[self currentDisplayedMessage] isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
157
    [[self currentDisplayedMessage] truePreviewMarkAsViewed];
158
  }
159
}
160
 
161
- (void)truePreviewBoundsDidChange:(NSNotification*)inNotification {
162
  // ignore the first time we get the notification; it may be an initial scroll
163
  // to the origin after changing messages
164
  static BOOL sIsFirstTime = YES;
165
 
166
  if (sIsFirstTime) {
167
    sIsFirstTime = NO;
168
 
169
    return;
170
  }
171
 
172
  sIsFirstTime = YES;
173
 
174
  [self truePreviewReset];
175
 
176
  if ([[self currentDisplayedMessage] isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
177
    [[self currentDisplayedMessage] truePreviewMarkAsViewed];
178
  }
179
}
180
 
181
@end