1 | /* |
---|
2 | * Adium is the legal property of its developers, whose names are listed in the copyright file included |
---|
3 | * with this source distribution. |
---|
4 | * |
---|
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the GNU |
---|
6 | * General Public License as published by the Free Software Foundation; either version 2 of the License, |
---|
7 | * or (at your option) any later version. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
---|
10 | * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
---|
11 | * Public License for more details. |
---|
12 | * |
---|
13 | * You should have received a copy of the GNU General Public License along with this program; if not, |
---|
14 | * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
15 | */ |
---|
16 | |
---|
17 | |
---|
18 | @class AIChat, AIListObject; |
---|
19 | |
---|
20 | /*! @class AIContentObject |
---|
21 | * @brief A complete unit of content. Abstract class. |
---|
22 | * |
---|
23 | * @par âContentâ is a vague word, but this is an abstract class, so vagueness is to be expected. A content object is anything that travels from a source to a destination, relevant to a chat, that may or may not be outgoing, carrying a datestamp and a message. |
---|
24 | * |
---|
25 | * @par The most common kind of content object is a content message, which is what people use to communicate over chats (except on MSN, where some people use their status messages). |
---|
26 | * |
---|
27 | * @par A content object may be incoming or outgoing. AIContentObject's basic rule for determining the direction of the content is to examine the content's source: If the source is an account, then the content is outgoing; if the source is a contact, then the content is incoming. The direction of a content object determines which events are triggered by the content (if that isn't disabled for the content object), and can affect how the content is displayed in the message view. |
---|
28 | * |
---|
29 | * @par Not all content objects have a message. In particular, a typing notification (\c AIContentTyping) does not have a message. |
---|
30 | * |
---|
31 | * @par In addition, AIContentObject includes a number of methods and properties that exist for the convenience of other parts of Adium. These include: |
---|
32 | * @li <code>isSimilarToContent:</code> (used by message view to determine whether styles may want to group two content objects together) |
---|
33 | * @li <code>isFromSameDayAsContent:</code> (used by message view to determine whether to insert a date separator) |
---|
34 | * @li <code>displayClasses</code> (used by message view) |
---|
35 | */ |
---|
36 | |
---|
37 | @interface AIContentObject : NSObject { |
---|
38 | AIChat *chat; |
---|
39 | AIListObject *source; |
---|
40 | AIListObject *destination; |
---|
41 | BOOL outgoing; |
---|
42 | |
---|
43 | NSAttributedString *message; |
---|
44 | NSDate *date; |
---|
45 | |
---|
46 | BOOL filterContent; |
---|
47 | BOOL trackContent; |
---|
48 | BOOL displayContent; |
---|
49 | BOOL displayContentImmediately; |
---|
50 | BOOL sendContent; |
---|
51 | BOOL postProcessContent; |
---|
52 | |
---|
53 | NSDictionary *userInfo; |
---|
54 | |
---|
55 | NSMutableArray *customDisplayClasses; |
---|
56 | } |
---|
57 | |
---|
58 | /*! @brief Create a content object without a message. |
---|
59 | * |
---|
60 | * @par If your subclass represents a type of content that wouldn't have a message associated with it (such as a typing notification), then this is the message you should send to \c super. |
---|
61 | * |
---|
62 | * @param inChat The chat with which this content is associated. The content may be presented in the message view and/or effect a change in the status icon for the tab (as well as the contact's row in the contact list). |
---|
63 | * @param inSource The account or contact from which the content originated. If it's an account, then this is outgoing content. |
---|
64 | * @param inDest The contact to which the content is addressed. |
---|
65 | * @param inDate The date and time at which the content was received or sent. |
---|
66 | * @return A shiny new content object. |
---|
67 | */ |
---|
68 | - (id)initWithChat:(AIChat *)inChat |
---|
69 | source:(AIListObject *)inSource |
---|
70 | destination:(AIListObject *)inDest |
---|
71 | date:(NSDate*)inDate; |
---|
72 | /*! @brief Create a content object with a message. |
---|
73 | * |
---|
74 | * @par Most content objects have a styled-text or plain-text message as their content. If your subclass represents a type of content that may have a message associated with it (such as a chat message), then this is the message you should send to \c super. |
---|
75 | * |
---|
76 | * @param inChat The chat with which this content is associated. The content may be presented in the message view and/or effect a change in the status icon for the tab (as well as the contact's row in the contact list). |
---|
77 | * @param inSource The account or contact from which the content originated. If it's an account, then this is outgoing content. |
---|
78 | * @param inDest The contact to which the content is addressed. |
---|
79 | * @param inDate The date and time at which the content was received or sent. |
---|
80 | * @param inMessage The message that is this object's content. May be \c nil; in that case, this is the same as the init method that doesn't have a message: parameter. |
---|
81 | * @return A shiny new content object. |
---|
82 | */ |
---|
83 | - (id)initWithChat:(AIChat *)inChat |
---|
84 | source:(AIListObject *)inSource |
---|
85 | destination:(AIListObject *)inDest |
---|
86 | date:(NSDate*)inDate |
---|
87 | message:(NSAttributedString *)inMessage; |
---|
88 | |
---|
89 | /*! @brief The type of content. |
---|
90 | * |
---|
91 | * @par There is at least one type defined for every concrete subclass of \c AIContentObject. |
---|
92 | * |
---|
93 | * @par Subclassing note: You must override this method and return a string (not \c nil). This string should probably be constant, so that types can be compared using the <code>==</code> operator rather than string comparison. |
---|
94 | * |
---|
95 | * @return A string representing the type of content that this object bears. |
---|
96 | */ |
---|
97 | - (NSString *)type; |
---|
98 | |
---|
99 | #pragma mark Comparing |
---|
100 | |
---|
101 | /*! @brief Compares the proximity of two content objects. |
---|
102 | * |
---|
103 | * @par The content objects are similar if they are of the same type, are from the same source, and have datestamps within five minutes of each other. |
---|
104 | * |
---|
105 | * @param inContent The content object to compare the receiver to. |
---|
106 | * @return \c YES if the receiver is similar to \a inContent; \c NO if not. |
---|
107 | */ |
---|
108 | - (BOOL)isSimilarToContent:(AIContentObject *)inContent; |
---|
109 | /*! @brief Reports whether two content objects were delivered on the same day. |
---|
110 | * |
---|
111 | * @par The content objects are on the same day if their datestamps have the same year, month, and date. The comparison is performed within the Common Era, i.e., the Gregorian calendar. |
---|
112 | * |
---|
113 | * @param inContent The content object to compare the receiver to. |
---|
114 | * @return \c YES if the receiver is from the same day of the common era as \a inContent; \c NO if not. |
---|
115 | */ |
---|
116 | - (BOOL)isFromSameDayAsContent:(AIContentObject *)inContent; |
---|
117 | |
---|
118 | #pragma mark Content |
---|
119 | |
---|
120 | /*! @brief The list object (usually, account or contact) that originated the content. |
---|
121 | * |
---|
122 | * @par If the source is an account, then the content is outgoing (the user sent it). Otherwise, it's incoming (the user received it). |
---|
123 | * |
---|
124 | * @par Content objects' source should not be not be confused with their chat. See \c chat if that's what you're looking for. |
---|
125 | * |
---|
126 | * @par This is set by the init methods. |
---|
127 | * |
---|
128 | * @return The source of the content. |
---|
129 | */ |
---|
130 | - (AIListObject *)source; |
---|
131 | /*! @brief The list object (usually, contact) that the content is addressed to. |
---|
132 | * |
---|
133 | * @par This is set by the init methods. |
---|
134 | * |
---|
135 | * @return The intended recipient of the content. |
---|
136 | */ |
---|
137 | - (AIListObject *)destination; |
---|
138 | /*! @brief The date and time at which the content was sent. |
---|
139 | * |
---|
140 | * @par This is set by the init methods. |
---|
141 | * |
---|
142 | * @return The datestamp of the content. |
---|
143 | */ |
---|
144 | - (NSDate *)date; |
---|
145 | /*! @brief Returns whether the content is outgoing (the user sent it), rather than incoming (the user received it). |
---|
146 | * |
---|
147 | * @par If the content's source is an account, then the content is outgoing (the user sent it). Otherwise, it's incoming (the user received it). |
---|
148 | * |
---|
149 | * @par Whether a content object is outgoing determines which events are triggered by the content (if that isn't disabled for the content object), and can affect how the content is displayed in the message view. |
---|
150 | * |
---|
151 | * @return \c YES if the content is outgoing; \c NO if it is incoming. |
---|
152 | */ |
---|
153 | - (BOOL)isOutgoing; |
---|
154 | |
---|
155 | /*! @brief The chat with which this content is associated. |
---|
156 | * |
---|
157 | * @par All content is associated with a chat, even if only incidentally. While the content may not be chat-oriented, all content may eventually end up displayed in a chat somewhere, either inline in the message view (status changes and file transfers) or in the tab or title bar (typing notification). |
---|
158 | * |
---|
159 | * @return The chat with which this content is associated. |
---|
160 | */ |
---|
161 | - (AIChat *)chat; |
---|
162 | /*! @brief Associate a different chat with this content. |
---|
163 | * |
---|
164 | * @param inChat The chat you want to portage this content to. |
---|
165 | * |
---|
166 | * @deprecated Deprecated since 1.2, and likely to be pulled even before then. Nothing currently uses <code>setChat:</code>, so unless a reason to have it becomes evident, this will probably fall off, leaving the \c chat property fixed in stone after initialization. |
---|
167 | */ |
---|
168 | - (void)setChat:(AIChat *)inChat; |
---|
169 | |
---|
170 | /*! @brief Change the message of this content. |
---|
171 | * |
---|
172 | * @param inMessage The new message. |
---|
173 | */ |
---|
174 | - (void)setMessage:(NSAttributedString *)inMessage; |
---|
175 | /*! @brief Obtain the current message in the content. |
---|
176 | * |
---|
177 | * @return The current message. |
---|
178 | */ |
---|
179 | - (NSAttributedString *)message; |
---|
180 | |
---|
181 | /*! @brief Get an array of CSS class names with which this content should be displayed. |
---|
182 | * |
---|
183 | * @par You should use these classes whenever inserting the content into an HTML or XHTML document, or anywhere else where CSS would be used with the content. |
---|
184 | * |
---|
185 | * @return An array of strings, each containing a class name. |
---|
186 | */ |
---|
187 | - (NSMutableArray *)displayClasses; |
---|
188 | |
---|
189 | /*! @brief Add a custom display class to this object |
---|
190 | * |
---|
191 | * @par This can be used to tag messages with custom metadata which display engines can use to style them accordingly |
---|
192 | */ |
---|
193 | - (void) addDisplayClass:(NSString *)className; |
---|
194 | |
---|
195 | /*! @brief Obtain an object previously associated with this content object. |
---|
196 | * |
---|
197 | * @par \c AIContentObject does not use this object at all; it simply retains it. This property is entirely for your own use. |
---|
198 | * |
---|
199 | * @return The user info object. |
---|
200 | */ |
---|
201 | - (id)userInfo; |
---|
202 | /*! @brief Associate any object you want with this content object. |
---|
203 | * |
---|
204 | * @par \c AIContentObject does not use this object at all; it simply retains it. This property is entirely for your own use. This sort of property is also called a âreference constantâ, especially by Carbon APIs. |
---|
205 | * |
---|
206 | * @par Beware of setting a mutable object as the user-info object, because the \c AIContentObject will not make a copy; it will only retain it. There's nothing wrong with putting a mutable object here; just make sure that you know you're doing that, that you document that you're willfully setting a mutable object here, and that nothing mutates the object contrarily to your expectations. |
---|
207 | * |
---|
208 | * @par It is safe to set this property to \c nil. |
---|
209 | * |
---|
210 | * @param inUserInfo The new user-info object. |
---|
211 | */ |
---|
212 | - (void)setUserInfo:(id)inUserInfo; |
---|
213 | |
---|
214 | #pragma mark Behavior |
---|
215 | |
---|
216 | /*! @brief Return whether the content passes through content filters. |
---|
217 | * |
---|
218 | * @par Content filtering is performed by the content controller; see \c AIContentControllerProtocol. This property tells the content controller whether to apply its filters to the content object, or leave the content object unfiltered. |
---|
219 | * |
---|
220 | * @return \c YES if the content will be passed through content filters; \c NO if it will not be passed through filters. |
---|
221 | */ |
---|
222 | - (BOOL)filterContent; |
---|
223 | /*! @brief Change whether the content passes through content filters. |
---|
224 | * |
---|
225 | * @par Content filtering is performed by the content controller; see \c AIContentControllerProtocol. This property tells the content controller whether to apply its filters to the content object, or leave the content object unfiltered. |
---|
226 | * |
---|
227 | * @param inFilterContent \c YES if you want the content to be passed through content filters; \c NO if you do not want it passed through filters. |
---|
228 | */ |
---|
229 | - (void)setFilterContent:(BOOL)inFilterContent; |
---|
230 | |
---|
231 | /*! @brief Return whether the content will cause notifications and events. |
---|
232 | * |
---|
233 | * @par If this is \c YES, the content controller will post notifications and generate events so that other objects can monitor the progress of receipt and sending of content. |
---|
234 | * |
---|
235 | * @par See the \c AIContentControllerProtocol documentation for more information on content controller events. |
---|
236 | * |
---|
237 | * @return \c YES if the content controller should generate events and post notifications about this content object; \c NO if it should keep mum. |
---|
238 | */ |
---|
239 | - (BOOL)trackContent; |
---|
240 | /*! @brief Change whether the content will cause notifications and events. |
---|
241 | * |
---|
242 | * @par If \a inTrackContent is \c YES, the content controller will post notifications and generate events (as listed in the Events pane of the Preferences) so that other objects can monitor the progress of receipt and sending of content. |
---|
243 | * |
---|
244 | * @par See the \c AIContentControllerProtocol documentation for more information on content controller events. |
---|
245 | * |
---|
246 | * @par XXX We should list reasons why you would want or not want a content object to be tracked. |
---|
247 | * |
---|
248 | * @return \c YES if the content controller should generate events and post notifications about this content object; \c NO if it should keep mum. |
---|
249 | */ |
---|
250 | - (void)setTrackContent:(BOOL)inTrackContent; |
---|
251 | |
---|
252 | /*! @brief Return whether the content will be displayed to the user. |
---|
253 | * |
---|
254 | * @par Once a content object has completely passed through the content controller's receiving or sending procedure, including all filtering, the content controller then looks to this property to decide whether it should display the content. Some types of content, such as typing notification (\c AIContentTyping), are sent, but not displayed. |
---|
255 | * |
---|
256 | * @par This property also controls whether the content will be entered into its chat's transcript (if the logger knows how to transcribe this content). If it is not displayed, neither will it be logged. See also the \c postProcessContent property, which controls postprocessing (such as logging) independently of whether the content will be displayed. |
---|
257 | * |
---|
258 | * @return \c YES if the content controller will display this content; \c NO otherwise. |
---|
259 | */ |
---|
260 | - (BOOL)displayContent; |
---|
261 | /*! @brief Change whether the content will be displayed to the user. |
---|
262 | * |
---|
263 | * @par Once a content object has completely passed through the content controller's receiving or sending procedure, including all filtering, the content controller then looks to this property to decide whether it should display the content. Some types of content, such as typing notification (\c AIContentTyping), are sent, but not displayed. |
---|
264 | * |
---|
265 | * @par This property also controls whether the content will be entered into its chat's transcript (if the logger knows how to transcribe this content). If it is not displayed, neither will it be logged. See also the \c postProcessContent property, which controls postprocessing (such as logging) independently of whether the content will be displayed. |
---|
266 | * |
---|
267 | * @param inDisplayContent \c YES if the content controller should display this content; \c NO otherwise. |
---|
268 | */ |
---|
269 | - (void)setDisplayContent:(BOOL)inDisplayContent; |
---|
270 | |
---|
271 | /*! @brief Return whether the content will be displayed immediately, or enqueued. |
---|
272 | * |
---|
273 | * @par The message view keeps a queue of messages which it eventually displays all at once rather than one at a time. When this is \c NO, the content is held in this queue until a suitable moment to display all the queued messages. Such a moment generally does arrive very soon; it is unlikely that the content will be held even for a whole second. |
---|
274 | * |
---|
275 | * @par The queue is for the benefit of the message history: it would be distracting if the message view were to scroll as one message after another were introduced into it, so the messages are inserted with <code>displayContentImmediately = YES</code>, so that they bypass the queue and instead all together instantly. |
---|
276 | * |
---|
277 | * @return \c YES if the content object should not be held in the queue; \c NO if it should. |
---|
278 | */ |
---|
279 | - (BOOL)displayContentImmediately; |
---|
280 | /*! @brief Change whether the content will be displayed immediately, or enqueued. |
---|
281 | * |
---|
282 | * @par The message view keeps a queue of messages which it eventually displays all at once rather than one at a time. When this is \c NO, the content is held in this queue until a suitable moment to display all the queued messages. Such a moment generally does arrive very soon; it is unlikely that the content will be held even for a whole second. |
---|
283 | * |
---|
284 | * @par The queue is for the benefit of the message history: it would be distracting if the message view were to scroll as one message after another were introduced into it, so the messages are inserted with <code>displayContentImmediately = YES</code>, so that they bypass the queue and instead all together instantly. |
---|
285 | * |
---|
286 | * @par If this property is \c NO, then in order to have the content displayed, the object that created the content object must, at some point in the future, post a \c Content_ChatDidFinishAddingUntrackedContent notification to \c AIAdium's \c notificationCenter, with the notification's \c object set to the \c chat of this content object. |
---|
287 | * |
---|
288 | * @param inDisplayContentImmediately \c YES if the content object should not held in the queue; \c NO if it should. |
---|
289 | */ |
---|
290 | - (void)setDisplayContentImmediately:(BOOL)inDisplayContentImmediately; |
---|
291 | |
---|
292 | /*! @brief Return whether to allow sending the content. |
---|
293 | * |
---|
294 | * @par The content controller will not send a content object's content if the content object's \c sendContent property is \c NO. |
---|
295 | * |
---|
296 | * @return \c YES if this content is OK for the content controller to send; \c NO if it should not be sent. |
---|
297 | */ |
---|
298 | - (BOOL)sendContent; |
---|
299 | /*! @brief Allow or disallow sending the content. |
---|
300 | * |
---|
301 | * @par The content controller will not send a content object's content if the content object's \c sendContent property is \c NO. |
---|
302 | * |
---|
303 | * @param inSendContent \c YES if this content is OK for the content controller to send; \c NO if it should not be sent. |
---|
304 | */ |
---|
305 | - (void)setSendContent:(BOOL)inSendContent; |
---|
306 | |
---|
307 | /*! @brief Return whether any post-delivery treatment should be applied to the message. |
---|
308 | * |
---|
309 | * @par Logging (aka transcription) is one example of something that is done to messages and other content objects after they have finished being received or sent. |
---|
310 | * |
---|
311 | * @return \c YES if the content should be postprocessed; \c NO if it should not. |
---|
312 | */ |
---|
313 | - (BOOL)postProcessContent; |
---|
314 | /*! @brief Change whether any post-delivery treatment should be applied to the message. |
---|
315 | * |
---|
316 | * @par Logging (aka transcription) is one example of something that is done to messages and other content objects after they have finished being received or sent. |
---|
317 | * |
---|
318 | * @param inPostProcessContent \c YES if the content should be postprocessed; \c NO if it should not. |
---|
319 | */ |
---|
320 | - (void)setPostProcessContent:(BOOL)inPostProcessContent; |
---|
321 | @end |
---|