Enable the header control when there's a topic or a header and "Use regular chat style settings" is enabled. Fixes #13791
(transplanted from d7fe2ee7d9b1a0d3e83ed73053e8866c9cc958a2)
2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
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.
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.
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.
17 #import "ESWebKitMessageViewPreferences.h"
18 #import "AIWebKitMessageViewPlugin.h"
19 #import "AIWebkitMessageViewStyle.h"
20 #import "AIWebKitPreviewMessageViewController.h"
21 #import "AIPreviewChat.h"
23 #import <Adium/AIAccountControllerProtocol.h>
24 #import <Adium/AIContactControllerProtocol.h>
25 #import <Adium/AIContentControllerProtocol.h>
26 #import <Adium/AIInterfaceControllerProtocol.h>
27 #import <Adium/AIAccount.h>
28 #import <Adium/AIChat.h>
29 #import <Adium/AIContentMessage.h>
30 #import <Adium/AIContentObject.h>
31 #import <Adium/AIContentEvent.h>
32 #import <Adium/AIListContact.h>
33 #import <Adium/AIHTMLDecoder.h>
34 #import <Adium/AIService.h>
35 #import <Adium/JVFontPreviewField.h>
36 #import <AIUtilities/AIAttributedStringAdditions.h>
37 #import <AIUtilities/AIColorAdditions.h>
38 #import <AIUtilities/AIFontAdditions.h>
39 #import <AIUtilities/AIMenuAdditions.h>
40 #import <AIUtilities/AIPopUpButtonAdditions.h>
41 #import <AIUtilities/AIBundleAdditions.h>
42 #import <AIUtilities/AIDateFormatterAdditions.h>
43 #import <AIUtilities/AIImageAdditions.h>
44 #import <AIUtilities/AIImageViewWithImagePicker.h>
46 #import "AIPreviewContentMessage.h"
48 #define WEBKIT_PREVIEW_CONVERSATION_FILE @"Preview"
49 #define PREF_GROUP_DISPLAYFORMAT @"Display Format" //To watch when the contact name display format changes
51 @interface ESWebKitMessageViewPreferences ()
52 - (void)configurePreferencesForTab;
53 - (void)_setBackgroundImage:(NSImage *)image;
54 - (NSMenu *)_stylesMenu;
55 - (NSMenu *)_variantsMenu;
56 - (NSMenu *)_backgroundImageTypeMenu;
57 - (void)_addBackgroundImageTypeChoice:(NSInteger)tag toMenu:(NSMenu *)menu withTitle:(NSString *)title;
58 - (void)_configureChatPreview;
59 - (AIChat *)previewChatWithDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary **)outListObjects;
60 - (void)_fillContentOfChat:(AIChat *)inChat withDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary *)listObjects;
61 - (NSMutableDictionary *)_addParticipants:(NSDictionary *)participants toChat:(AIChat *)inChat fromPath:(NSString *)previewPath;
62 - (void)_applySettings:(NSDictionary *)chatDict toChat:(AIPreviewChat *)inChat withParticipants:(NSDictionary *)participants;
63 - (void)_addContent:(NSArray *)chatArray toChat:(AIChat *)inChat withParticipants:(NSDictionary *)participants;
64 - (void)_setDisplayFontFace:(NSString *)face size:(NSNumber *)size;
69 @implementation ESWebKitMessageViewPreferences
71 - (NSString *)paneIdentifier
75 - (NSString *)paneName{
76 return AILocalizedString(@"Messages", "Title of the messages preferences");
78 - (NSString *)nibName{
79 return @"WebKitPreferencesView";
83 return [NSImage imageNamed:@"pref-messages"];
87 * @brief Configure the preference view
92 previewListObjectsDict = nil;
95 [popUp_backgroundImageType setMenu:[self _backgroundImageTypeMenu]];
96 [popUp_styles setMenu:[self _stylesMenu]];
99 [fontPreviewField_currentFont setShowFontFace:YES];
100 [fontPreviewField_currentFont setShowPointSize:YES];
102 //We want to be able to obtain bigger images than the image picker will feed us
103 [imageView_backgroundImage setUsePictureTaker:NO];
105 //Configure the chat preview
106 [self _configureChatPreview];
108 [tabView_messageType selectTabViewItem:tabViewItem_regularChat];
110 [self configurePreferencesForTab];
114 * @brief Close the preference view
116 - (void)viewWillClose
118 //Hide the alpha component
119 [[NSColorPanel sharedColorPanel] setShowsAlpha:NO];
121 [[NSNotificationCenter defaultCenter] removeObserver:self];
122 [previewListObjectsDict release]; previewListObjectsDict = nil;
124 [previewController release]; previewController = nil;
125 [view_previewLocation setFrame:[preview frame]];
126 [[preview superview] replaceSubview:preview with:view_previewLocation];
127 [preview release]; preview = nil;
128 //Matches the retain performed in -[ESWebKitMessageViewPreferences _configureChatPreview]
129 [view_previewLocation release];
134 - (void)messageStyleXtrasDidChange
137 NSDictionary *prefDict = [adium.preferenceController preferencesForGroup:self.preferenceGroupForCurrentTab];
139 [popUp_styles setMenu:[self _stylesMenu]];
140 [popUp_styles selectItemWithRepresentedObject:[prefDict objectForKey:KEY_WEBKIT_STYLE]];
144 //Preferences ----------------------------------------------------------------------------------------------------------
145 #pragma mark Preferences
146 - (AIWebkitStyleType)currentTab
148 if (tabView_messageType.selectedTabViewItem == tabViewItem_regularChat) {
149 return AIWebkitRegularChat;
151 return AIWebkitGroupChat;
155 - (NSString *)preferenceGroupForCurrentTab
157 NSString *prefGroup = nil;
159 switch(self.currentTab) {
160 case AIWebkitRegularChat:
161 prefGroup = PREF_GROUP_WEBKIT_REGULAR_MESSAGE_DISPLAY;
164 case AIWebkitGroupChat:
165 prefGroup = PREF_GROUP_WEBKIT_GROUP_MESSAGE_DISPLAY;
172 - (void)configurePreferencesForTab
174 //Configure our controls to represent the global preferences
176 NSDictionary *prefDict = [adium.preferenceController preferencesForGroup:self.preferenceGroupForCurrentTab];
178 [checkBox_showUserIcons setState:([[previewController messageStyle] allowsUserIcons] ?
179 [[prefDict objectForKey:KEY_WEBKIT_SHOW_USER_ICONS] boolValue] :
181 [checkBox_showHeader setState:[[prefDict objectForKey:KEY_WEBKIT_SHOW_HEADER] boolValue]];
182 [checkBox_showMessageColors setState:([[previewController messageStyle] allowsColors] ?
183 [[prefDict objectForKey:KEY_WEBKIT_SHOW_MESSAGE_COLORS] boolValue] :
185 [checkBox_showMessageFonts setState:[[prefDict objectForKey:KEY_WEBKIT_SHOW_MESSAGE_FONTS] boolValue]];
187 [checkBox_useRegularChatForGroup setState:[[adium.preferenceController preferenceForKey:KEY_WEBKIT_USE_REGULAR_PREFERENCES
188 group:self.preferenceGroupForCurrentTab] boolValue]];
190 //Allow the alpha component to be set for our background color
191 [[NSColorPanel sharedColorPanel] setShowsAlpha:YES];
193 [previewController setIsGroupChat:(self.currentTab == AIWebkitGroupChat)];
195 // The preview controller will send us a preferences changed message also.
196 [previewController preferencesChangedForGroup:self.preferenceGroupForCurrentTab
199 preferenceDict:[adium.preferenceController preferencesForGroup:self.preferenceGroupForCurrentTab]
203 - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
205 [self configurePreferencesForTab];
209 * @brief Update our preference view to reflect changed preferences
211 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key object:(AIListObject *)object
212 preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
214 if (!viewIsOpen) return;
216 if ([group isEqualToString:self.preferenceGroupForCurrentTab]) {
220 //Ensure our style/variant menus are showing the correct selection
221 style = [prefDict objectForKey:KEY_WEBKIT_STYLE];
222 if (!style || ![popUp_styles selectItemWithRepresentedObject:style]) {
223 style = [[plugin messageStyleBundleWithIdentifier:style] bundleIdentifier];
224 [popUp_styles selectItemWithRepresentedObject:style];
227 //When the active style changes, rebuild our variant menu for the new style
228 if (!key || [key isEqualToString:KEY_WEBKIT_STYLE]) {
229 [popUp_variants setMenu:[self _variantsMenu]];
232 variant = [prefDict objectForKey:[plugin styleSpecificKey:@"Variant" forStyle:style]];
233 if (!variant || ![popUp_variants selectItemWithRepresentedObject:variant]) {
234 variant = [AIWebkitMessageViewStyle defaultVariantForBundle:[plugin messageStyleBundleWithIdentifier:style]];
235 [popUp_variants selectItemWithRepresentedObject:variant];
238 [popUp_variants synchronizeTitleAndSelectedItem];
240 //Configure our style-specific controls to represent the current style
241 NSString *fontFamily = [prefDict objectForKey:[plugin styleSpecificKey:@"FontFamily" forStyle:style]];
242 if (!fontFamily) fontFamily = [[plugin messageStyleBundleWithIdentifier:style] objectForInfoDictionaryKey:KEY_WEBKIT_DEFAULT_FONT_FAMILY];
243 if (!fontFamily) fontFamily = [[NSFont systemFontOfSize:0] familyName];
245 NSNumber *fontSize = [prefDict objectForKey:[plugin styleSpecificKey:@"FontSize" forStyle:style]];
246 if (!fontSize) fontSize = [[plugin messageStyleBundleWithIdentifier:style] objectForInfoDictionaryKey:KEY_WEBKIT_DEFAULT_FONT_SIZE];
247 if (!fontSize) fontSize = [NSNumber numberWithInteger:[[NSFont systemFontOfSize:0] pointSize]];
249 NSFont *defaultFont = [NSFont cachedFontWithName:fontFamily size:[fontSize integerValue]];
250 [fontPreviewField_currentFont setFont:defaultFont];
252 //Style-specific background prefs
253 NSData *backgroundImage = [adium.preferenceController preferenceForKey:[plugin styleSpecificKey:@"Background" forStyle:style]
254 group:PREF_GROUP_WEBKIT_BACKGROUND_IMAGES];
255 if (backgroundImage) {
256 [imageView_backgroundImage setImage:[[[NSImage alloc] initWithData:backgroundImage] autorelease]];
258 [imageView_backgroundImage setImage:nil];
261 NSColor *backgroundColor = [[prefDict objectForKey:[plugin styleSpecificKey:@"BackgroundColor" forStyle:style]] representedColor];
262 [colorWell_customBackgroundColor setColor:(backgroundColor ? backgroundColor : [NSColor whiteColor])] ;
264 [checkBox_useCustomBackground setState:[[prefDict objectForKey:[plugin styleSpecificKey:@"UseCustomBackground" forStyle:style]] boolValue]];
265 [popUp_backgroundImageType selectItemWithTag:[[prefDict objectForKey:[plugin styleSpecificKey:@"BackgroundType" forStyle:style]] integerValue]];
267 [self configureControlDimming];
272 * @brief Save changed preferences
274 - (IBAction)changePreference:(id)sender
277 if (sender == checkBox_showUserIcons) {
278 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
279 forKey:KEY_WEBKIT_SHOW_USER_ICONS
280 group:self.preferenceGroupForCurrentTab];
282 } else if (sender == checkBox_showHeader) {
283 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
284 forKey:KEY_WEBKIT_SHOW_HEADER
285 group:self.preferenceGroupForCurrentTab];
287 } else if (sender == checkBox_showMessageColors) {
288 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
289 forKey:KEY_WEBKIT_SHOW_MESSAGE_COLORS
290 group:self.preferenceGroupForCurrentTab];
292 } else if (sender == checkBox_showMessageFonts) {
293 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
294 forKey:KEY_WEBKIT_SHOW_MESSAGE_FONTS
295 group:self.preferenceGroupForCurrentTab];
296 } else if (sender == checkBox_useCustomBackground) {
297 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
298 forKey:[plugin styleSpecificKey:@"UseCustomBackground"
299 forStyle:[[popUp_styles selectedItem] representedObject]]
300 group:self.preferenceGroupForCurrentTab];
301 } else if (sender == checkBox_useRegularChatForGroup) {
302 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
303 forKey:KEY_WEBKIT_USE_REGULAR_PREFERENCES
304 group:self.preferenceGroupForCurrentTab];
306 [self configurePreferencesForTab];
307 } else if (sender == colorWell_customBackgroundColor) {
308 [adium.preferenceController setPreference:[[colorWell_customBackgroundColor color] stringRepresentation]
309 forKey:[plugin styleSpecificKey:@"BackgroundColor"
310 forStyle:[[popUp_styles selectedItem] representedObject]]
311 group:self.preferenceGroupForCurrentTab];
313 } else if (sender == popUp_backgroundImageType) {
314 [adium.preferenceController setPreference:[NSNumber numberWithInteger:[[popUp_backgroundImageType selectedItem] tag]]
315 forKey:[plugin styleSpecificKey:@"BackgroundType"
316 forStyle:[[popUp_styles selectedItem] representedObject]]
317 group:self.preferenceGroupForCurrentTab];
319 } else if (sender == popUp_styles) {
320 [adium.preferenceController setPreference:[[sender selectedItem] representedObject]
321 forKey:KEY_WEBKIT_STYLE
322 group:self.preferenceGroupForCurrentTab];
324 } else if (sender == popUp_variants) {
325 NSString *activeStyle = [adium.preferenceController preferenceForKey:KEY_WEBKIT_STYLE
326 group:self.preferenceGroupForCurrentTab];
328 [adium.preferenceController setPreference:[[sender selectedItem] representedObject]
329 forKey:[plugin styleSpecificKey:@"Variant" forStyle:activeStyle]
330 group:self.preferenceGroupForCurrentTab];
333 [self configureControlDimming];
337 - (void)configureControlDimming
339 // Controls are enabled if we're the regular chat tab, or we're not using regular preferences.
340 BOOL useRegularPreferences = [[adium.preferenceController preferenceForKey:KEY_WEBKIT_USE_REGULAR_PREFERENCES
341 group:PREF_GROUP_WEBKIT_GROUP_MESSAGE_DISPLAY] boolValue];
342 BOOL anyControlsEnabled = (self.currentTab == AIWebkitRegularChat || !useRegularPreferences);
344 // General controls with no other qualifiers.
345 [popUp_styles setEnabled:anyControlsEnabled];
346 [fontPreviewField_currentFont setEnabled:anyControlsEnabled];
347 [checkBox_showMessageFonts setEnabled:anyControlsEnabled];
348 [checkBox_showMessageColors setEnabled:anyControlsEnabled];
349 [button_setFont setEnabled:anyControlsEnabled];
350 [button_defaultFont setEnabled:anyControlsEnabled];
352 //Only enable if there are multiple variant choices
353 [popUp_variants setEnabled:[popUp_variants numberOfItems] > 0 && anyControlsEnabled];
355 //Disable the custom background controls if the style doesn't support them
356 AIWebkitMessageViewStyle *messageStyle = [previewController messageStyle];
357 BOOL allowCustomBackground = [messageStyle allowsCustomBackground] && anyControlsEnabled;
358 [checkBox_useCustomBackground setEnabled:allowCustomBackground];
360 allowCustomBackground = allowCustomBackground && checkBox_useCustomBackground.state;
362 [colorWell_customBackgroundColor setEnabled:allowCustomBackground];
363 [popUp_backgroundImageType setEnabled:allowCustomBackground];
364 [imageView_backgroundImage setEnabled:allowCustomBackground];
366 //Disable the header control if this style doesn't have a header or topic
367 if (self.currentTab == AIWebkitGroupChat)
368 [checkBox_showHeader setEnabled:[messageStyle hasTopic] && anyControlsEnabled];
370 [checkBox_showHeader setEnabled:[messageStyle hasHeader] || ([messageStyle hasTopic] && useRegularPreferences)];
372 //Disable user icon toggling if the style doesn't support them
373 [checkBox_showUserIcons setEnabled:[messageStyle allowsUserIcons] && anyControlsEnabled];
375 [checkBox_showMessageColors setEnabled:[messageStyle allowsColors] && anyControlsEnabled];
379 * @brief Save changes to the font field
381 - (void)fontPreviewField:(JVFontPreviewField *)field didChangeToFont:(NSFont *)font
383 [self _setDisplayFontFace:[font fontName] size:[NSNumber numberWithInteger:[font pointSize]]];
386 - (IBAction)resetDisplayFontToDefault:(id)sender
388 [self _setDisplayFontFace:nil size:0];
392 * @brief Set the display font of the active style.
394 * @param face New font face, nil to remove custom font
395 * @param size New font size, nil to remove custom size
397 - (void)_setDisplayFontFace:(NSString *)face size:(NSNumber *)size
399 NSString *activeStyle = [adium.preferenceController preferenceForKey:KEY_WEBKIT_STYLE
400 group:self.preferenceGroupForCurrentTab];
402 [adium.preferenceController setPreference:face
403 forKey:[plugin styleSpecificKey:@"FontFamily" forStyle:activeStyle]
404 group:self.preferenceGroupForCurrentTab];
405 [adium.preferenceController setPreference:size
406 forKey:[plugin styleSpecificKey:@"FontSize" forStyle:activeStyle]
407 group:self.preferenceGroupForCurrentTab];
412 * @brief Save changes to the background image
414 - (void)imageViewWithImagePicker:(AIImageViewWithImagePicker *)picker didChangeToImage:(NSImage *)image
416 [self _setBackgroundImage:image];
420 * @brief Remove the background image
422 - (void)deleteInImageViewWithImagePicker:(AIImageViewWithImagePicker *)picker
424 [self _setBackgroundImage:nil];
428 * @brief Set the background image of the active style.
430 * @param image New background image, nil to remove background image
432 - (void)_setBackgroundImage:(NSImage *)image
434 NSString *style = [[popUp_styles selectedItem] representedObject];
436 /* Save the new image. We store the images in a separate preference group since they may get big.
437 * This will let loading other groups not be affected by its presence.
439 [adium.preferenceController setPreference:[image PNGRepresentation]
440 forKey:[plugin styleSpecificKey:@"Background" forStyle:style]
441 group:PREF_GROUP_WEBKIT_BACKGROUND_IMAGES];
445 * @brief Builds and returns a menu of available styles
447 - (NSMenu *)_stylesMenu
449 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@""];
450 NSMutableArray *menuItemArray = [NSMutableArray array];
451 NSArray *availableStyles = [[plugin availableMessageStyles] allValues];
452 NSMenuItem *menuItem;
454 for (NSBundle *style in availableStyles) {
455 menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[style name]
459 [menuItem setRepresentedObject:[style bundleIdentifier]];
460 [menuItemArray addObject:menuItem];
464 [menuItemArray sortUsingSelector:@selector(titleCompare:)];
466 for (menuItem in menuItemArray) {
467 [menu addItem:menuItem];
470 return [menu autorelease];
474 * @brief Build & return a menu of variants for the passed style
476 - (NSMenu *)_variantsMenu
478 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@""];
480 //Add a menu item for each variant
481 for (NSString *variant in previewController.messageStyle.availableVariants) {
482 [menu addItemWithTitle:variant
486 representedObject:variant];
489 return [menu autorelease];
493 * @brief Build & return a menu of choices for background display
495 - (NSMenu *)_backgroundImageTypeMenu
497 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
499 [self _addBackgroundImageTypeChoice:BackgroundNormal toMenu:menu withTitle:AILocalizedString(@"Normal","Background image display preference: The image will be displayed normally")];
500 [self _addBackgroundImageTypeChoice:BackgroundCenter toMenu:menu withTitle:AILocalizedString(@"Centered","Background image display preference: The image will be centered in the window")];
501 [self _addBackgroundImageTypeChoice:BackgroundTile toMenu:menu withTitle:AILocalizedString(@"Tiled","Background image display preference: The image will be tiled (repeated) in the window to fill available space")];
502 [self _addBackgroundImageTypeChoice:BackgroundTileCenter toMenu:menu withTitle:AILocalizedString(@"Tiled (Centered)","Background image display preference: The image will be tiled and centered in the window")];
503 [self _addBackgroundImageTypeChoice:BackgroundScale toMenu:menu withTitle:AILocalizedString(@"Scaled", "Background image display preference: The image will be increased or decreased in size to fit the window")];
505 return [menu autorelease];
507 - (void)_addBackgroundImageTypeChoice:(NSInteger)tag toMenu:(NSMenu *)menu withTitle:(NSString *)title
509 NSMenuItem *menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:title
512 [menuItem setTag:tag];
513 [menu addItem:menuItem];
518 //Chat Preview ---------------------------------------------------------------------------------------------------------
519 #pragma mark Chat Preview
521 * @brief Configure our chat preview
523 - (void)_configureChatPreview
525 NSDictionary *previewDict;
526 NSString *previewFilePath;
527 NSString *previewPath;
530 //Create our fake chat and message controller for the live preview
531 previewFilePath = [[NSBundle bundleForClass:[self class]] pathForResource:WEBKIT_PREVIEW_CONVERSATION_FILE ofType:@"plist"];
532 previewDict = [[NSDictionary alloc] initWithContentsOfFile:previewFilePath];
533 previewPath = [previewFilePath stringByDeletingLastPathComponent];
535 NSDictionary *listObjects;
536 previewChat = [self previewChatWithDictionary:previewDict fromPath:previewPath listObjects:&listObjects];
537 previewController = [[AIWebKitPreviewMessageViewController messageDisplayControllerForChat:previewChat
538 withPlugin:plugin] retain];
540 //Enable live refreshing of our preview
541 [previewController setShouldReflectPreferenceChanges:YES];
542 [previewController setPreferencesChangedDelegate:self];
544 //Add fake users and content to our chat
545 [self _fillContentOfChat:previewChat withDictionary:previewDict fromPath:previewPath listObjects:listObjects];
546 [previewDict release];
548 //Place the preview chat in our view
549 preview = [[previewController messageView] retain];
550 [preview setFrame:[view_previewLocation frame]];
551 //Will be released in viewWillClose
552 [view_previewLocation retain];
553 [[view_previewLocation superview] replaceSubview:view_previewLocation with:preview];
555 //Disable drag and drop onto the preview chat - Jeff doesn't need your porn :)
556 if ([preview respondsToSelector:@selector(setAllowsDragAndDrop:)]) {
557 [(ESWebView *)preview setAllowsDragAndDrop:NO];
560 //Disable forwarding of events so the preferences responder chain works properly
561 if ([preview respondsToSelector:@selector(setShouldForwardEvents:)]) {
562 [(ESWebView *)preview setShouldForwardEvents:NO];
566 - (AIChat *)previewChatWithDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary **)outListObjects
568 AIPreviewChat *previewChat = [AIPreviewChat previewChat];
569 [previewChat setDisplayName:AILocalizedString(@"Sample Conversation", "Title for the sample conversation")];
571 //Process and create all participants
572 *outListObjects = [self _addParticipants:[previewDict objectForKey:@"Participants"]
573 toChat:previewChat fromPath:previewPath];
575 //Setup the chat, and its source/destination
576 [self _applySettings:[previewDict objectForKey:@"Chat"]
577 toChat:previewChat withParticipants:*outListObjects];
583 * @brief Fill the content of the specified chat using content archived in the dictionary
585 - (void)_fillContentOfChat:(AIChat *)inChat withDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary *)listObjects
587 //Add the archived chat content
588 [self _addContent:[previewDict objectForKey:@"Preview Messages"]
589 toChat:inChat withParticipants:listObjects];
593 * @brief Add participants
595 - (NSMutableDictionary *)_addParticipants:(NSDictionary *)participants toChat:(AIChat *)inChat fromPath:(NSString *)previewPath
597 NSMutableDictionary *listObjectDict = [NSMutableDictionary dictionary];
598 AIService *aimService = [adium.accountController firstServiceWithServiceID:@"AIM"];
600 for (NSDictionary *participant in participants) {
601 NSString *UID, *alias, *userIconName;
602 AIListContact *listContact;
605 UID = [participant objectForKey:@"UID"];
606 listContact = [[AIListContact alloc] initWithUID:UID service:aimService];
609 if ((alias = [participant objectForKey:@"Display Name"])) {
610 [[NSNotificationCenter defaultCenter] postNotificationName:Contact_ApplyDisplayName
612 userInfo:[NSDictionary dictionaryWithObject:alias forKey:@"Alias"]];
616 if ((userIconName = [participant objectForKey:@"UserIcon Name"])) {
617 [listContact setValue:[previewPath stringByAppendingPathComponent:userIconName]
618 forProperty:@"UserIconPath"
622 [listObjectDict setObject:listContact forKey:UID];
623 [listContact release];
626 return listObjectDict;
630 * @brief Chat settings
632 - (void)_applySettings:(NSDictionary *)chatDict toChat:(AIPreviewChat *)inChat withParticipants:(NSDictionary *)participants
634 NSString *dateOpened, *type, *name, *UID;
637 if ((dateOpened = [chatDict objectForKey:@"Date Opened"])) {
638 [inChat setDateOpened:[NSDate dateWithNaturalLanguageString:dateOpened]];
642 type = [chatDict objectForKey:@"Type"];
643 if ([type isEqualToString:@"IM"]) {
644 if ((UID = [chatDict objectForKey:@"Destination UID"])) {
645 [inChat addParticipatingListObject:[participants objectForKey:UID] notify:YES];
647 if ((UID = [chatDict objectForKey:@"Source UID"])) {
648 [inChat setAccount:(AIAccount *)[participants objectForKey:UID]];
651 if ((name = [chatDict objectForKey:@"Name"])) {
652 [inChat setName:name];
656 //We don't want the interface controller to try to open this fake chat
657 [inChat setIsOpen:YES];
661 * @brief Chat content
663 - (void)_addContent:(NSArray *)chatArray toChat:(AIChat *)inChat withParticipants:(NSDictionary *)participants
665 NSDictionary *messageDict;
667 for (messageDict in chatArray) {
668 AIContentObject *content = nil;
669 AIListObject *source;
670 NSString *from, *msgType;
671 NSAttributedString *message;
673 msgType = [messageDict objectForKey:@"Type"];
674 from = [messageDict objectForKey:@"From"];
676 source = (from ? [participants objectForKey:from] : nil);
678 if ([msgType isEqualToString:CONTENT_MESSAGE_TYPE]) {
679 //Create message content object
684 message = [AIHTMLDecoder decodeHTML:[messageDict objectForKey:@"Message"]];
685 to = [messageDict objectForKey:@"To"];
686 outgoing = [[messageDict objectForKey:@"Outgoing"] boolValue];
688 //The other person is always the one we're chatting with right now
689 dest = [participants objectForKey:to];
690 content = [AIPreviewContentMessage messageInChat:inChat
693 date:[NSDate dateWithNaturalLanguageString:[messageDict objectForKey:@"Date"]]
695 autoreply:[[messageDict objectForKey:@"Autoreply"] boolValue]];
697 //AIContentMessage won't know whether the message is outgoing unless we tell it since neither our source
698 //nor our destination are AIAccount objects.
699 [(AIPreviewContentMessage *)content setIsOutgoing:outgoing];
701 } else if ([msgType isEqualToString:CONTENT_STATUS_TYPE]) {
702 //Create status content object
703 NSString *statusMessageType;
705 message = [AIHTMLDecoder decodeHTML:[messageDict objectForKey:@"Message"]];
706 statusMessageType = [messageDict objectForKey:@"Status Message Type"];
708 //Create our content object
709 content = [AIContentEvent eventInChat:inChat
712 date:[NSDate dateWithNaturalLanguageString:[messageDict objectForKey:@"Date"]]
714 withType:statusMessageType];
718 [content setTrackContent:NO];
719 [content setPostProcessContent:NO];
720 [content setDisplayContentImmediately:NO];
722 [adium.contentController displayContentObject:content
723 usingContentFilters:YES
728 //We finished adding untracked content
729 [[NSNotificationCenter defaultCenter] postNotificationName:Content_ChatDidFinishAddingUntrackedContent