adium 5155:3b5586d8d518: Rewrote the Source/Destination bar to b...

commits at adium.im commits at adium.im
Sun Oct 21 13:47:56 UTC 2012


details:	http://hg.adium.im/adium/rev/3b5586d8d518
revision:	5155:3b5586d8d518
branch:		adium-1.6
author:		Thijs Alkemade <thijsalkemade at gmail.com>
date:		Sun Oct 21 15:45:39 2012 +0200

Rewrote the Source/Destination bar to be more flexible.

Now a message window can have an arbitrary number of bars at the top of the window, with nice animations.

diffs (truncated from 2623 to 1000 lines):

diff -r 162d0f9e351f -r 3b5586d8d518 Adium.xcodeproj/project.pbxproj
--- a/Adium.xcodeproj/project.pbxproj	Sat Oct 20 21:16:28 2012 +0200
+++ b/Adium.xcodeproj/project.pbxproj	Sun Oct 21 15:45:39 2012 +0200
@@ -1366,6 +1366,9 @@
 		76731DE315F90538007728C3 /* libgpgerror.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76731DE115F90538007728C3 /* libgpgerror.framework */; };
 		76731DE415F9057F007728C3 /* libgcrypt.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 76731DE015F90538007728C3 /* libgcrypt.framework */; };
 		76731DE515F90582007728C3 /* libgpgerror.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 76731DE115F90538007728C3 /* libgpgerror.framework */; };
+		767870CE16334AA700BD0E4D /* AIAccountSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 767870CD16334AA600BD0E4D /* AIAccountSelectionViewController.m */; };
+		767870E41634045D00BD0E4D /* AIMessageViewTopBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 767870E31634045C00BD0E4D /* AIMessageViewTopBarController.m */; };
+		767870E51634139600BD0E4D /* AIAccountSelectionTopBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 767870E71634139600BD0E4D /* AIAccountSelectionTopBar.xib */; };
 		76889DEB12D3CA17007AEF00 /* get-info.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 76889DEA12D3CA17007AEF00 /* get-info.tiff */; };
 		76889DEF12D3CA40007AEF00 /* Profile.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 76889DEE12D3CA40007AEF00 /* Profile.tiff */; };
 		76C1AF9C125A906A00D269A9 /* AIAdiumURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C1AF9B125A906A00D269A9 /* AIAdiumURLProtocol.m */; };
@@ -4392,6 +4395,11 @@
 		766ABAB51306D1020049FFB7 /* AIUnreadMessagesTooltip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIUnreadMessagesTooltip.m; path = Source/AIUnreadMessagesTooltip.m; sourceTree = "<group>"; };
 		76731DE015F90538007728C3 /* libgcrypt.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libgcrypt.framework; path = Frameworks/libgcrypt.framework; sourceTree = "<group>"; };
 		76731DE115F90538007728C3 /* libgpgerror.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libgpgerror.framework; path = Frameworks/libgpgerror.framework; sourceTree = "<group>"; };
+		767870CC16334AA600BD0E4D /* AIAccountSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIAccountSelectionViewController.h; path = Source/AIAccountSelectionViewController.h; sourceTree = "<group>"; };
+		767870CD16334AA600BD0E4D /* AIAccountSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIAccountSelectionViewController.m; path = Source/AIAccountSelectionViewController.m; sourceTree = "<group>"; };
+		767870E21634045C00BD0E4D /* AIMessageViewTopBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIMessageViewTopBarController.h; path = Source/AIMessageViewTopBarController.h; sourceTree = "<group>"; };
+		767870E31634045C00BD0E4D /* AIMessageViewTopBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIMessageViewTopBarController.m; path = Source/AIMessageViewTopBarController.m; sourceTree = "<group>"; };
+		767870E61634139600BD0E4D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/AIAccountSelectionTopBar.xib; sourceTree = "<group>"; };
 		76889DEA12D3CA17007AEF00 /* get-info.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = "get-info.tiff"; path = "Resources/get-info.tiff"; sourceTree = "<group>"; };
 		76889DEE12D3CA40007AEF00 /* Profile.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = Profile.tiff; path = Resources/Profile.tiff; sourceTree = "<group>"; };
 		76C1AF9A125A906A00D269A9 /* AIAdiumURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIAdiumURLProtocol.h; path = "Plugins/WebKit Message View/AIAdiumURLProtocol.h"; sourceTree = "<group>"; };
@@ -7065,6 +7073,9 @@
 			children = (
 				4B25494603F6A32700A8010A /* AIAccountSelectionView.h */,
 				4B25494703F6A32700A8010A /* AIAccountSelectionView.m */,
+				767870E71634139600BD0E4D /* AIAccountSelectionTopBar.xib */,
+				767870CC16334AA600BD0E4D /* AIAccountSelectionViewController.h */,
+				767870CD16334AA600BD0E4D /* AIAccountSelectionViewController.m */,
 			);
 			name = Other;
 			sourceTree = "<group>";
@@ -8664,6 +8675,8 @@
 				348C47150D3B20BE00FB6E7A /* AIMessageWindowOutgoingScrollView.h */,
 				348C47160D3B20BE00FB6E7A /* AIMessageWindowOutgoingScrollView.m */,
 				5A1FEA601334549300C14951 /* MessageView.xib */,
+				767870E21634045C00BD0E4D /* AIMessageViewTopBarController.h */,
+				767870E31634045C00BD0E4D /* AIMessageViewTopBarController.m */,
 			);
 			name = Messages;
 			sourceTree = "<group>";
@@ -9775,6 +9788,7 @@
 				C6B545AA15D3390F0005F1F8 /* ABSearch at 2x.png in Resources */,
 				C61AFA9A15DD43C80001EDEF /* AboutDialog_bg at 2x.png in Resources */,
 				C6BC7F9B15DD666600C5FF52 /* events-notification.tiff in Resources */,
+				767870E51634139600BD0E4D /* AIAccountSelectionTopBar.xib in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -10424,6 +10438,8 @@
 				5A4BD52513F8653D00A4D3F7 /* ESContactListAdvancedPreferences.m in Sources */,
 				5A4BD55413F86A6200A4D3F7 /* AIMessagePreferences.m in Sources */,
 				5A5EC831154649140043FFAA /* AIPreferenceCollectionItem.m in Sources */,
+				767870CE16334AA700BD0E4D /* AIAccountSelectionViewController.m in Sources */,
+				767870E41634045D00BD0E4D /* AIMessageViewTopBarController.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -12175,6 +12191,15 @@
 			name = Localizable.strings;
 			sourceTree = "<group>";
 		};
+		767870E71634139600BD0E4D /* AIAccountSelectionTopBar.xib */ = {
+			isa = PBXVariantGroup;
+			children = (
+				767870E61634139600BD0E4D /* en */,
+			);
+			name = AIAccountSelectionTopBar.xib;
+			path = Resources;
+			sourceTree = "<group>";
+		};
 /* End PBXVariantGroup section */
 
 /* Begin XCBuildConfiguration section */
diff -r 162d0f9e351f -r 3b5586d8d518 Plugins/Dual Window Interface/AIAccountSelectionView.h
--- a/Plugins/Dual Window Interface/AIAccountSelectionView.h	Sat Oct 20 21:16:28 2012 +0200
+++ b/Plugins/Dual Window Interface/AIAccountSelectionView.h	Sun Oct 21 15:45:39 2012 +0200
@@ -19,32 +19,8 @@
 
 @class AIChat;
 
-#define AIViewFrameDidChangeNotification	@"AIViewFrameDidChangeNotification"
+ at interface AIAccountSelectionView : NSView {
 
-/*!	@brief	View for selecting the account and contact of a chat.
- *
- *	@par	This view contains two pop-up menus: One for accounts, and the other for contacts. It appears at the top of the chat window when the user double-clicks on a contact row in the contact list, and when the chat receives content from a different contact in the same metacontact as the existing current contact.
- */
-
- at interface AIAccountSelectionView : NSView <AIAccountMenuDelegate, AIContactMenuDelegate> {
-	NSPopUpButton		*popUp_accounts;
-	NSView				*box_accounts;
-
-	NSPopUpButton   	*popUp_contacts;
-	NSView				*box_contacts;
-	
-	AIAccountMenu		*accountMenu;	
-	AIContactMenu		*contactMenu;	
-	AIChat				*chat;
-	
-	NSColor *leftColor;
-	NSColor *rightColor;
 }
 
-- (id)initWithCoder:(NSCoder *)aDecoder;
-- (id)initWithFrame:(NSRect)frameRect;
-- (void)setChat:(AIChat *)inChat;
-
-- (void)setLeftColor:(NSColor *)inLeftColor rightColor:(NSColor *)inRightColor;
-
 @end
diff -r 162d0f9e351f -r 3b5586d8d518 Plugins/Dual Window Interface/AIAccountSelectionView.m
--- a/Plugins/Dual Window Interface/AIAccountSelectionView.m	Sat Oct 20 21:16:28 2012 +0200
+++ b/Plugins/Dual Window Interface/AIAccountSelectionView.m	Sun Oct 21 15:45:39 2012 +0200
@@ -14,493 +14,21 @@
  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#import <Adium/AIAccountControllerProtocol.h>
+#import <PSMTabBarControl/NSBezierPath_AMShading.h>
 #import "AIAccountSelectionView.h"
-#import <Adium/AIContactControllerProtocol.h>
-#import <Adium/AIContentControllerProtocol.h>
-#import <Adium/AIChatControllerProtocol.h>
-#import <AIUtilities/AIPopUpButtonAdditions.h>
-#import <Adium/AIAccount.h>
-#import <Adium/AIContentMessage.h>
-#import <Adium/AIListContact.h>
-#import <Adium/AIMetaContact.h>
-#import <Adium/AIService.h>
-#import <Adium/AIChat.h>
-#import <PSMTabBarControl/NSBezierPath_AMShading.h>
 
-#define BOX_RECT	NSMakeRect(0, 0, 300, 28)
-#define LABEL_RECT	NSMakeRect(17, 7, 56, 17)
-#define POPUP_RECT	NSMakeRect(75, 1, 212, 26)
-
- at interface AIAccountSelectionView ()
-- (id)_init;
-- (void)configureForCurrentChat;
-- (void)chatDestinationChanged:(NSNotification *)notification;
-- (void)chatSourceChanged:(NSNotification *)notification;
-- (BOOL)_accountIsAvailable:(AIAccount *)inAccount;
-- (void)configureAccountMenu;
-- (void)_createContactMenu;
-- (void)_destroyAccountMenu;
-- (void)_destroyContactMenu;
-- (BOOL)choicesAvailableForAccount;
-- (BOOL)choicesAvailableForContact;
-- (NSTextField *)_textFieldLabelWithValue:(NSString *)inValue frame:(NSRect)inFrame;
-- (NSPopUpButton *)_popUpButtonWithFrame:(NSRect)inFrame;
-- (NSView *)_boxWithFrame:(NSRect)inFrame;
-- (void)_repositionMenusAndResize;
- at end
-
-/*!
- * @class AIAccountSelectionView
- * @brief A view for picking the destination (contact) and source (account) for a chat.
- *
- * This view manages data, as well, MVC be damned.
- *
- * The To: field, display first, is the indepdenent variable.  It shows all contacts within the selected metacontact, or shows nothing
- * if a normal contact is the chat's destination.
- *
- * The From: field is the dependent variable. It shows all accounts which could message the selected contact.
- */
 @implementation AIAccountSelectionView
 
-/*!
- * @brief InitWithCoder
- */
-- (id)initWithCoder:(NSCoder *)aDecoder
+-(void)drawRect:(NSRect)aRect
 {
-	if((self = [super initWithCoder:aDecoder])) {
-		[self _init];
-	}
-	return self;
-}
-
-/*!
- * @brief InitWithFrame
- */
-- (id)initWithFrame:(NSRect)frameRect
-{
-	if((self = [super initWithFrame:frameRect])) {
-		[self _init];
-	}
-	return self;
-}
-
-/*!
- * @brief Common init
- */
-- (id)_init
-{
-	return self;
-}
-
-- (void)dealloc
-{
-	[self setChat:nil];
-
-	[leftColor release];
-	[rightColor release];
-	[super dealloc];
-}
-
-- (void)setLeftColor:(NSColor *)inLeftColor rightColor:(NSColor *)inRightColor
-{
-	if (leftColor != inLeftColor) {
-		[leftColor release];
-		leftColor = [inLeftColor retain];
-	}
-	
-	if (rightColor != inRightColor) {
-		[rightColor release];
-		rightColor = [inRightColor retain];
-	}
-	
-	[self setNeedsDisplay:YES];
-}
-
--(void)drawRect:(NSRect)aRect
-{	
-	if (rightColor && leftColor) {
-		NSBezierPath *path = [NSBezierPath bezierPathWithRect:[self bounds]];
-		[path linearVerticalGradientFillWithStartColor:leftColor 
-											  endColor:rightColor];
-	}
-}
-
-#pragma mark Chat
-/*!
- * @brief Set the chat associated with this selection view
- *
- * @param inChat AIChat instance this view representents
- */
-- (void)setChat:(AIChat *)inChat
-{
-	if(chat != inChat){
-		if(chat){
-			//Stop observing the existing chat
-			[[NSNotificationCenter defaultCenter] removeObserver:self name:Chat_SourceChanged object:chat];
-			[[NSNotificationCenter defaultCenter] removeObserver:self name:Chat_DestinationChanged object:chat];
-
-			//Remove our menus
-			[self _destroyAccountMenu];
-			[self _destroyContactMenu];
-			
-			//Release it
-			[chat release]; chat = nil;
-		}
-
-		if(inChat){
-			//Retain the new chat
-			chat = [inChat retain];
-			
-			//Observe changes to this chat's source and destination
-			[[NSNotificationCenter defaultCenter] addObserver:self
-										   selector:@selector(chatSourceChanged:)
-											   name:Chat_SourceChanged
-											 object:chat];
-			[[NSNotificationCenter defaultCenter] addObserver:self
-										   selector:@selector(chatDestinationChanged:)
-											   name:Chat_DestinationChanged
-											 object:chat];
-			
-			//Update source and destination menus
-			[self configureForCurrentChat];
-		}			
-	} else {
-		[self configureForCurrentChat];
-	}
-}
-
-/*!
- * @brief Build and configure all menus for the current chat
- */
-- (void)configureForCurrentChat
-{
-	AILogWithSignature(@"");
-
-	//Rebuild 'To' contact menu
-	if ([self choicesAvailableForContact]) {
-		[self _createContactMenu];
-	} else {
-		[self _destroyContactMenu];
-	}
-
-	//Update our 'From' account menu
-	[self chatDestinationChanged:nil];
-}
-
-/*!
- * @brief Update our menus when the destination contact changes
- */
-- (void)chatDestinationChanged:(NSNotification *)notification
-{
-	AILogWithSignature(@"popUp_contacts selecting %@ (%@)", chat.listObject, [notification object]);
-
-	//Update selection in contact menu
-	[popUp_contacts selectItemWithRepresentedObjectUsingCompare:chat.listObject];
-
-	//Rebuild 'From' account menu
-	if ([self choicesAvailableForAccount]){
-		[self configureAccountMenu];
-	} else {
-		[self _destroyAccountMenu];	
-	}
-
-	//Reposition our menus and resize as necessary
-	[self _repositionMenusAndResize];
-
-	//Update selection in account menu
-	[self chatSourceChanged:nil];
-}
-
-/*!
- * @brief Update our menus when the source account changes
- */
-- (void)chatSourceChanged:(NSNotification *)notification
-{
-	//Update selection in account menu
-	AILogWithSignature(@"popUp_accounts selecting %@ (%@)", chat.account,  [notification object]);
-	[popUp_accounts selectItemWithRepresentedObject:chat.account];
-}
-
-/*!
- * @brief Reposition our menus and resize the account selection view as necessary
- *
- * Invoke this method after the visibility of either menu has changed.
- */
-- (void)_repositionMenusAndResize
-{
-	NSInteger		newHeight = 0;
-	NSRect	oldFrame = [self frame];
-	
-	//Account menu is always at the bottom
-	if(box_accounts){
-		[box_accounts setFrameOrigin:NSMakePoint(0, 0)];
-		newHeight += [box_accounts frame].size.height;
-	}
-
-	//Contact menu is at the bottom, unless the account menu is present in which case it moves up
-	if(box_contacts){
-		[box_contacts setFrameOrigin:NSMakePoint(0, (box_accounts ? [box_accounts frame].size.height : 0))];
-		newHeight += [box_contacts frame].size.height;
-	}
-
-	//Resize our view to fit whichever menus are visible
-	[self setFrameSize:NSMakeSize([self frame].size.width, newHeight)];
-	[[self superview] setNeedsDisplayInRect:NSUnionRect(oldFrame,[self frame])];
-	
-	[[NSNotificationCenter defaultCenter] postNotificationName:AIViewFrameDidChangeNotification object:self];
-}
-
-
-//Account Menu ---------------------------------------------------------------------------------------------------------
-#pragma mark Account Menu
-/*!
- * @brief Returns YES if a choice of source account is available
- */
-- (BOOL)choicesAvailableForAccount
-{
-	NSInteger		choices = 0;
-
-	for (AIAccount *account in adium.accountController.accounts) {
-		if ([self _accountIsAvailable:account]) {
-			if (++choices > 1) return YES;
-		}
-	}
-	
-	return NO;
-}
-
-- (void)rebuildAccountMenuFromMenuItems:(NSArray *)menuItems
-{
-	NSMenuItem	 *menuItem;
-	NSMutableArray *menuItemsForAccountsWhichKnow = [NSMutableArray array];
-	NSMutableArray *menuItemsForAccountsWhichDoNotKnow = [NSMutableArray array];
-	
-	for (menuItem in menuItems) {
-		AIAccount *account = [menuItem representedObject];
-		AIListContact *listContact = [adium.contactController existingContactWithService:chat.listObject.service
-																				 account:account
-																					 UID:chat.listObject.UID];
-
-		if (!listContact || listContact.isStranger)
-			[menuItemsForAccountsWhichDoNotKnow addObject:menuItem];
-		else
-			[menuItemsForAccountsWhichKnow addObject:menuItem];
-	}
-	
-	NSMenu *menu = [[NSMenu alloc] init];
-
-	//First, add items for accounts which have the current contact on their contact lists
-	for (menuItem in menuItemsForAccountsWhichKnow) {
-		[menu addItem:menuItem];
-	}
-	
-	//If we added any items and will be adding more, put in a separator
-	if ([menu numberOfItems] && [menuItemsForAccountsWhichDoNotKnow count]) [menu addItem:[NSMenuItem separatorItem]];
-
-	//Finally, add items for accounts which are on the right service but don't know about this contact
-	for (menuItem in menuItemsForAccountsWhichDoNotKnow) {
-		[menu addItem:menuItem];
-	}
-
-	[popUp_accounts setMenu:menu];
-	[menu release];
-}
-
-/*!
- * @brief Account Menu Delegate
- */
-- (void)accountMenu:(AIAccountMenu *)inAccountMenu didRebuildMenuItems:(NSArray *)menuItems {
-	[self rebuildAccountMenuFromMenuItems:menuItems];
-}
-- (void)accountMenu:(AIAccountMenu *)inAccountMenu didSelectAccount:(AIAccount *)inAccount {
-	[adium.chatController switchChat:chat toAccount:inAccount];
-}
-- (BOOL)accountMenu:(AIAccountMenu *)inAccountMenu shouldIncludeAccount:(AIAccount *)inAccount {
-	return [self _accountIsAvailable:inAccount];
-}
-- (NSControlSize)controlSizeForAccountMenu:(AIAccountMenu *)inAccountMenu;
-{
-	return NSRegularControlSize;
-}
-
-/*!
- * @brief Check if an account is available for sending content
- *
- * An account is considered available if it's of the right service class and is currently online.
- * @param inAccount AIAccount instance to check
- * @return YES if the account is available
- */
-- (BOOL)_accountIsAvailable:(AIAccount *)inAccount
-{
-	return [chat.listObject.service.serviceClass isEqualToString:inAccount.service.serviceClass] && inAccount.online;
-}
-
-/*!
- * @brief Create the account menu and add it to our view
- */
-- (void)configureAccountMenu
-{
-	[box_accounts removeFromSuperview]; [box_accounts release];
-	box_accounts = [[self _boxWithFrame:BOX_RECT] retain];
-	
-	[popUp_accounts release];
-	popUp_accounts = [[self _popUpButtonWithFrame:POPUP_RECT] retain];
-	[box_accounts addSubview:popUp_accounts];
-	
-	NSTextField *label_accounts = [self _textFieldLabelWithValue:AILocalizedString(@"From:", "Label in front of the dropdown of accounts from which to send a message")
-														   frame:LABEL_RECT];
-	[box_accounts addSubview:label_accounts];
-
-	//Resize the contact box to fit our view and insert it
-	[box_accounts setFrameSize:NSMakeSize(NSWidth([self frame]), NSHeight(BOX_RECT))];
-	[self addSubview:box_accounts];
-
-	//Configure the contact menu
-	if (accountMenu)
-		[accountMenu rebuildMenu];
-	else
-		accountMenu = [[AIAccountMenu accountMenuWithDelegate:self submenuType:AIAccountNoSubmenu showTitleVerbs:NO] retain];
-}
-
-/*!
- * @brief Destroy the account menu, removing it from our view
- */
-- (void)_destroyAccountMenu
-{
-	if (popUp_accounts) {
-		[box_accounts removeFromSuperview];
-		[popUp_accounts release]; popUp_accounts = nil;
-		[box_accounts release]; box_accounts = nil;
-		[accountMenu release]; accountMenu = nil;
-	}
-}
-
-
-//Contact Menu ---------------------------------------------------------------------------------------------------------
-#pragma mark Contact Menu
-/*!
- * @brief Returns YES if a choice of destination contact is available
- */
-- (BOOL)choicesAvailableForContact {
-	if (chat.listObject.metaContact)
-		return chat.listObject.metaContact.uniqueContainedObjects.count > 1;
-	
-	return NO;
-}
-
-/*!
- * @brief Contact menu delegate
- */
-- (void)contactMenuDidRebuild:(AIContactMenu *)inContactMenu {
-	AILogWithSignature(@"");
-	[popUp_contacts setMenu:[inContactMenu menu]];
-	[self chatDestinationChanged:nil];
-}
-- (void)contactMenu:(AIContactMenu *)inContactMenu didSelectContact:(AIListContact *)inContact {
-	[adium.chatController switchChat:chat toListContact:inContact usingContactAccount:YES];
-}
-- (AIListContact *)contactMenu:(AIContactMenu *)inContactMenu validateContact:(AIListContact *)inContact {
-	AIListContact *preferredContact = [adium.contactController preferredContactForContentType:CONTENT_MESSAGE_TYPE
-																				 forListContact:inContact];
-	return (preferredContact ? preferredContact : inContact);
-}
-/*!
- * @brief Create the contact menu and add it to our view
- */
-- (void)_createContactMenu
-{
-	[box_contacts removeFromSuperview]; [box_contacts release];
-	box_contacts = [[self _boxWithFrame:BOX_RECT] retain];
-
-	[popUp_contacts release];
-	popUp_contacts = [[self _popUpButtonWithFrame:POPUP_RECT] retain];
-	[box_contacts addSubview:popUp_contacts];
-		
-	NSTextField *label_contacts = [self _textFieldLabelWithValue:AILocalizedString(@"To:", "Label in front of the dropdown for picking which contact to send a message to in the message window") frame:LABEL_RECT];
-	[box_contacts addSubview:label_contacts];
-
-	//Resize the contact box to fit our view and insert it
-	[box_contacts setFrameSize:NSMakeSize(NSWidth([self frame]), NSHeight(BOX_RECT))];
-	[self addSubview:box_contacts];
-
-	//Configure the contact menu
-	if (contactMenu)
-		[contactMenu rebuildMenu];
-	else
-		contactMenu = [[AIContactMenu contactMenuWithDelegate:self forContactsInObject:chat.listObject.parentContact] retain];
-}
-
-/*!
- * @brief Destroy the contact menu, remove it from our view
- */
-- (void)_destroyContactMenu
-{
-	if(popUp_contacts){
-		[box_contacts removeFromSuperview];
-		[box_contacts release]; box_contacts = nil;
-		[popUp_contacts release]; popUp_contacts = nil;
-		[contactMenu release]; contactMenu = nil;
-	}
-}
-
-
-//Misc -----------------------------------------------------------------------------------------------------------------
-#pragma mark Misc
-/*!
- * @brief
- */
-- (NSTextField *)_textFieldLabelWithValue:(NSString *)inValue frame:(NSRect)inFrame
-{
-	NSTextField *label = [[NSTextField alloc] initWithFrame:inFrame];
-
-	[label setStringValue:inValue];
-	[label setEditable:NO];
-	[label setSelectable:NO];
-	[label setBordered:NO];
-	[label setDrawsBackground:NO];
-	[label setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
-	[label setAlignment:NSRightTextAlignment];
-
-	return [label autorelease];
-}
-
-/*!
- * @brief
- */
-- (NSPopUpButton *)_popUpButtonWithFrame:(NSRect)inFrame
-{
-	NSPopUpButton *popUp = [[NSPopUpButton alloc] initWithFrame:inFrame];
-
-	[popUp setAutoresizingMask:(NSViewWidthSizable)];
-
-	/* If we don't explicitly set the font of the pop-up button
-	 * menu items without a font of their own get displayed at 14 pt (as of Mac OS X 10.4.10)
-	 * which is too big the text gets clipped.
-	 *
-	 * If you uncomment this line, you can notice this problem in descenders
-	 * (such as that of the letter 'g') in the recipient pop-up.
-	 */
-	[popUp setFont:[NSFont systemFontOfSize:0.0f]];
-	
-	return [popUp autorelease];
-}
-
-/*!
- * @brief
- */
-- (NSView *)_boxWithFrame:(NSRect)inFrame
-{
-	NSView	*box = [[NSView alloc] initWithFrame:inFrame];
-
-	[box setAutoresizingMask:(NSViewWidthSizable)];
-	
-	return [box autorelease];
-}
-
-- (NSString *)description
-{
-	return [NSString stringWithFormat:@"%@{%@}",[super description], chat];
+    NSBezierPath *path = [NSBezierPath bezierPathWithRect:self.bounds];
+    [path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.80f alpha:1.0f]
+                                  endColor:[NSColor colorWithCalibratedWhite:0.95f alpha:1.0f]];
+    path = [NSBezierPath bezierPath];
+    [path moveToPoint:NSMakePoint(NSMinX(self.bounds), NSMinY(self.bounds))];
+    [path lineToPoint:NSMakePoint(NSMaxX(self.bounds), NSMinY(self.bounds))];
+    [[NSColor blackColor] setStroke];
+    [path stroke];
 }
 
 @end
diff -r 162d0f9e351f -r 3b5586d8d518 Plugins/Dual Window Interface/AIDualWindowInterfacePlugin.m
--- a/Plugins/Dual Window Interface/AIDualWindowInterfacePlugin.m	Sat Oct 20 21:16:28 2012 +0200
+++ b/Plugins/Dual Window Interface/AIDualWindowInterfacePlugin.m	Sun Oct 21 15:45:39 2012 +0200
@@ -95,10 +95,10 @@
 				notify:NotifyNever];
 		[container addTabViewItem:messageTab atIndex:idx silent:NO];
 	}
-
-    //Display the account selector if necessary
-	[[messageTab messageViewController] setAccountSelectionMenuVisibleIfNeeded:YES];
 	
+    [[NSNotificationCenter defaultCenter] postNotificationName:Chat_DestinationChanged object:chat];
+    [[NSNotificationCenter defaultCenter] postNotificationName:Chat_SourceChanged object:chat];
+    
 	//Open the container window.  We wait until after the chat has been added to the container
 	//before making it visible so window opening looks cleaner.
 	if (container && !applicationIsHidden && ![[container window] isMiniaturized] && ![[container window] isVisible]) {
diff -r 162d0f9e351f -r 3b5586d8d518 Plugins/Dual Window Interface/AIMessageViewController.h
--- a/Plugins/Dual Window Interface/AIMessageViewController.h	Sat Oct 20 21:16:28 2012 +0200
+++ b/Plugins/Dual Window Interface/AIMessageViewController.h	Sun Oct 21 15:45:39 2012 +0200
@@ -15,6 +15,7 @@
  */
 
 #import "ESChatUserListController.h"
+#import "AIMessageViewTopBarController.h"
 #import <Adium/AIInterfaceControllerProtocol.h>
 #import <Adium/AIMessageEntryTextView.h>
 
@@ -48,14 +49,16 @@
 
 	//
     NSObject<AIMessageDisplayController>	*messageDisplayController;
-	IBOutlet	AIAccountSelectionView		*view_accountSelection;
+	
+    IBOutlet	NSView                  *view_topBars;
+    NSMutableArray                      *topBarControllers;
+    
 	AIMessageWindowController				*messageWindowController;
 	
 	//menuitem
 	NSMenuItem				*showHide;
 
     AIChat					*chat;
-	BOOL					accountSelectionVisible;
 	BOOL					suppressSendLaterPrompt;
 	CGFloat					entryMinHeight;
 	
@@ -89,10 +92,6 @@
 //User List
 - (IBAction)showActionMenu:(id)sender;
 
-//Account Selection
-- (void)redisplaySourceAndDestinationSelector:(NSNotification *)notification;
-- (void)setAccountSelectionMenuVisibleIfNeeded:(BOOL)makeVisible;
-
 //Text Entry
 - (AIMessageEntryTextView *)textEntryView;
 - (void)makeTextEntryViewFirstResponder;
@@ -104,5 +103,11 @@
 - (void)didSelect;
 - (void)willDeselect;
 
+- (void)addTopBarController:(AIMessageViewTopBarController *)newController;
+- (void)removeTopBarController:(AIMessageViewTopBarController *)controller;
+- (void)hideTopBarController:(AIMessageViewTopBarController *)controller;
+- (void)unhideTopBarController:(AIMessageViewTopBarController *)controller;
+- (void)didResizeTopbarController:(AIMessageViewTopBarController *)controller;
+
 @end
 
diff -r 162d0f9e351f -r 3b5586d8d518 Plugins/Dual Window Interface/AIMessageViewController.m
--- a/Plugins/Dual Window Interface/AIMessageViewController.m	Sat Oct 20 21:16:28 2012 +0200
+++ b/Plugins/Dual Window Interface/AIMessageViewController.m	Sun Oct 21 15:45:39 2012 +0200
@@ -21,6 +21,7 @@
 #import "AIDualWindowInterfacePlugin.h"
 #import "AIMessageWindowOutgoingScrollView.h"
 #import "AIGradientView.h"
+#import "AIAccountSelectionViewController.h"
 
 #import <Adium/AIChatControllerProtocol.h>
 #import <Adium/AIContactAlertsControllerProtocol.h>
@@ -32,6 +33,7 @@
 
 #import <AIUtilities/AIAttributedStringAdditions.h>
 #import <AIUtilities/AIDictionaryAdditions.h>
+#import <AIUtilities/AIBundleAdditions.h>
 #import <AIUtilities/AIOSCompatibility.h>
 
 #import <PSMTabBarControl/NSBezierPath_AMShading.h>
@@ -53,11 +55,8 @@
 
 @interface AIMessageViewController ()
 - (id)initForChat:(AIChat *)inChat;
-- (void)chatStatusChanged:(NSNotification *)notification;
 - (void)chatParticipatingListObjectsChanged:(NSNotification *)notification;
 - (void)_configureMessageDisplay;
-- (void)_createAccountSelectionView;
-- (void)_destroyAccountSelectionView;
 - (void)_configureTextEntryView;
 - (void)_updateTextEntryViewHeight;
 - (CGFloat)_textEntryViewProperHeightIgnoringUserMininum:(BOOL)ignoreUserMinimum;
@@ -65,7 +64,6 @@
 - (void)_hideUserListView;
 - (void)_configureUserList;
 - (CGFloat)_userListViewDividerPositionIgnoringUserMinimum:(BOOL)ignoreUserMinimum;
-- (void)updateFramesForAccountSelectionView;
 - (void)saveUserListMinimumSize;
 - (BOOL)userListInitiallyVisible;
 - (void)setUserListVisible:(BOOL)inVisible;
@@ -99,9 +97,9 @@
 		//Init
 		chat = [inChat retain];
 		contact = chat.listObject;
-		accountSelectionVisible = NO;
 		userListController = nil;
 		suppressSendLaterPrompt = NO;
+        topBarControllers = [[NSMutableArray alloc] initWithCapacity:0];
 		
 		//Load the view containing our controls
 		[NSBundle loadNibNamed:MESSAGE_VIEW_NIB owner:self];
@@ -115,22 +113,10 @@
 									   selector:@selector(didSendMessage:)
 										   name:Interface_DidSendEnteredMessage 
 										 object:chat];
-		[[NSNotificationCenter defaultCenter] addObserver:self
-									   selector:@selector(chatStatusChanged:) 
-										   name:Chat_StatusChanged
-										 object:chat];
 		[[NSNotificationCenter defaultCenter] addObserver:self 
 									   selector:@selector(chatParticipatingListObjectsChanged:)
 										   name:Chat_ParticipatingListObjectsChanged
 										 object:chat];
-		[[NSNotificationCenter defaultCenter] addObserver:self
-									   selector:@selector(redisplaySourceAndDestinationSelector:) 
-										   name:Chat_SourceChanged
-										 object:chat];
-		[[NSNotificationCenter defaultCenter] addObserver:self
-									   selector:@selector(redisplaySourceAndDestinationSelector:) 
-										   name:Chat_DestinationChanged
-										 object:chat];
 
 		//Observe general preferences for sending keys
 		[adium.preferenceController registerPreferenceObserver:self forGroup:PREF_GROUP_GENERAL];
@@ -142,7 +128,6 @@
 		[self setUserListVisible:(chat.isGroupChat && [self userListInitiallyVisible])];
 		
 		[self chatParticipatingListObjectsChanged:nil];
-		[self chatStatusChanged:nil];
 		
 		//Configure our views
 		[self _configureMessageDisplay];
@@ -158,8 +143,23 @@
 			initialBaseWritingDirection = [contact baseWritingDirection];
 			[textView_outgoing setBaseWritingDirection:initialBaseWritingDirection];
 		}
+        
+        [view_topBars setFrameSize:NSMakeSize(view_topBars.frame.size.width, 0.0f)];
+        NSRect verticalFrame = splitView_verticalSplit.frame;
+        verticalFrame.size.height = NSHeight(view_contents.frame) - NSMinY(verticalFrame) - 2;
+        verticalFrame.size.width = NSWidth(view_contents.frame);
+        [splitView_verticalSplit setFrame:verticalFrame];
+        
+        AIAccountSelectionViewController *sourceDestination = [[AIAccountSelectionViewController alloc] init];
+        
+        [self addTopBarController:sourceDestination];
+        [sourceDestination setChat:chat];
+        
+        [sourceDestination release];
+        
+        [self _updateTextEntryViewHeight];
 	}
-
+    
 	return self;
 }
 
@@ -191,9 +191,6 @@
 	//remove observers
 	[[NSNotificationCenter defaultCenter] removeObserver:self];
 	
-    //Account selection view
-	[self _destroyAccountSelectionView];
-	
 	[messageDisplayController messageViewIsClosing];
     [messageDisplayController release];
 	[userListController release];
@@ -203,6 +200,8 @@
 	[view_contents release]; view_contents = nil;
 	[undoManager release]; undoManager = nil;
 
+    [topBarControllers release]; topBarControllers = nil;
+    
     [super dealloc];
 }
 
@@ -219,28 +218,6 @@
 										  group:PREF_GROUP_DUAL_WINDOW_INTERFACE];
 }
 
-- (void)updateGradientColors
-{
-	NSColor *darkerColor = [NSColor colorWithCalibratedWhite:0.90f alpha:1.0f];
-	NSColor *lighterColor = [NSColor colorWithCalibratedWhite:0.92f alpha:1.0f];
-	NSColor *leftColor = nil, *rightColor = nil;
-
-	switch ([messageWindowController tabPosition]) {
-		case AdiumTabPositionBottom:
-		case AdiumTabPositionTop:
-		case AdiumTabPositionLeft:
-			leftColor = lighterColor;
-			rightColor = darkerColor;
-			break;
-		case AdiumTabPositionRight:
-			leftColor = darkerColor;
-			rightColor = lighterColor;
-			break;
-	}
-
-	[view_accountSelection setLeftColor:leftColor rightColor:rightColor];
-}
-
 /*!
  * @brief Invoked before the message view closes
  *
@@ -265,8 +242,6 @@
 	if (inWindowController != messageWindowController) {
 		[messageWindowController release];
 		messageWindowController = [inWindowController retain];
-		
-		[self updateGradientColors];
 	}
 }
 
@@ -306,21 +281,6 @@
 	return nil;
 }
 
-/*!
- * @brief Invoked when the status of our chat changes
- *
- * The only chat status change we're interested in is one to the disallow account switching flag.  When this flag 
- * changes we update the visibility of our account status menus accordingly.
- */
-- (void)chatStatusChanged:(NSNotification *)notification
-{
-    NSArray	*modifiedKeys = [[notification userInfo] objectForKey:@"Keys"];
-	
-    if (notification == nil || [modifiedKeys containsObject:@"DisallowAccountSwitching"]) {
-		[self setAccountSelectionMenuVisibleIfNeeded:YES];
-    }
-}
-
 
 //Message Display ------------------------------------------------------------------------------------------------------
 #pragma mark Message Display
@@ -558,7 +518,6 @@
  */
 - (IBAction)didSendMessage:(id)sender
 {
-    [self setAccountSelectionMenuVisibleIfNeeded:NO];
     [self clearTextEntryView];
 }
 
@@ -625,104 +584,6 @@
 	[listContact release];
 }
 
-//Account Selection ----------------------------------------------------------------------------------------------------
-#pragma mark Account Selection
-/*!
- * @brief
- */
-- (void)accountSelectionViewFrameDidChange:(NSNotification *)notification
-{
-	[self updateFramesForAccountSelectionView];
-}
-
-/*!
- * @brief Redisplay the source/destination account selector
- */
-- (void)redisplaySourceAndDestinationSelector:(NSNotification *)notification
-{
-	// Update the textView's chat source, in case any attributes it monitors changed.
-	[textView_outgoing setChat:chat];
-	[self setAccountSelectionMenuVisibleIfNeeded:YES];
-}
-
-/*!
- * @brief Toggle visibility of the account selection menus
- *
- * Invoking this method with NO will hide the account selection menus.  Invoking it with YES will show the account
- * selection menus if they are needed.
- */
-- (void)setAccountSelectionMenuVisibleIfNeeded:(BOOL)makeVisible
-{
-	//Hide or show the account selection view as requested
-	if (makeVisible) {
-		[self _createAccountSelectionView];
-	} else {
-		[self _destroyAccountSelectionView];
-	}
-}
-
-/*!
- * @brief Show the account selection view
- */
-- (void)_createAccountSelectionView
-{
-	if (!accountSelectionVisible) {
-		//Setup the account selection view
-		[view_accountSelection setChat:chat];
-		[self updateGradientColors];
-		
-		//Insert the account selection view at the top of our view
-		accountSelectionVisible = YES;
-
-		[[NSNotificationCenter defaultCenter] addObserver:self
-												 selector:@selector(accountSelectionViewFrameDidChange:)
-													 name:AIViewFrameDidChangeNotification
-												   object:view_accountSelection];
-		
-		[self updateFramesForAccountSelectionView];
-	} else {
-		[view_accountSelection setChat:chat];
-	}
-}
-
-/*!
- * @brief Hide the account selection view
- */
-- (void)_destroyAccountSelectionView
-{
-	if (accountSelectionVisible) {
-		//Remove the observer
-		[[NSNotificationCenter defaultCenter] removeObserver:self
-														name:AIViewFrameDidChangeNotification
-													  object:view_accountSelection];
-
-		accountSelectionVisible = NO;
-
-		//Redisplay everything
-		[self updateFramesForAccountSelectionView];
-	}
-}
-
-/*!
- * @brief Position the account selection view, if it is present, and the messages/text entry splitview appropriately
- */
-- (void)updateFramesForAccountSelectionView
-{
-	CGFloat accountSelectionHeight = (accountSelectionVisible ? NSHeight(view_accountSelection.frame) : 0.0f);
-	
-	NSRect verticalFrame = splitView_verticalSplit.frame;
-	verticalFrame.size.height = NSHeight(view_contents.frame) - accountSelectionHeight - NSMinY(verticalFrame) - 2;
-	verticalFrame.size.width = NSWidth(view_contents.frame);
-	[splitView_verticalSplit setFrame:verticalFrame];
-	
-	[view_accountSelection setFrameOrigin:NSMakePoint(NSMinX(splitView_verticalSplit.frame), NSMaxY(splitView_verticalSplit.frame))];
-	
-	[view_accountSelection setHidden:!accountSelectionVisible];
-	
-	[self _updateTextEntryViewHeight];
-}	
-
-
 //Text Entry -----------------------------------------------------------------------------------------------------------
 #pragma mark Text Entry
 /*!
@@ -1478,5 +1339,81 @@
 	return undoManager;
 }
 
+#pragma mark Top bar
+
+- (void)addTopBarController:(AIMessageViewTopBarController *)newController
+{
+    [topBarControllers addObject:newController];
+    [view_topBars addSubview:newController.view];
+    




More information about the commits mailing list