Frameworks/Adium Framework/Source/AIInterfaceControllerProtocol.h
author Zachary West <zacw@adium.im>
Tue Jun 02 17:22:19 2009 -0400 (2009-06-02)
changeset 2450 08aa9c3a346c
parent 2131 0846c7e2b617
child 2846 28d2f716a225
permissions -rw-r--r--
Create a new advanced preference called "Confirmations". Move Quit Confirmations there.

Adds a new confirmation type for closing message windows with more than 1 tab open. Fixes #12006.

This new preference has two options: always confirm, only confirm when there's unread content. Displays an alert sheet when trying to close the window.
     1 /*
     2  *  AIInterfaceControllerProtocol.h
     3  *  Adium
     4  *
     5  *  Created by Evan Schoenberg on 7/31/06.
     6  *
     7  */
     8 
     9 #import <Adium/AIControllerProtocol.h>
    10 
    11 #define Interface_ContactSelectionChanged				@"Interface_ContactSelectionChanged"
    12 
    13 /*!
    14  * @brief AIContactInfoInspectorDidChangeInspectedObject notification name
    15  *
    16  * userinfo is an NSDictionary with keys KEY_PREVIOUS_INSPECTED_OBJECT and KEY_NEW_INSPECTED_OBJECT and objects of class AIListObject
    17  */
    18 #define AIContactInfoInspectorDidChangeInspectedObject	@"AIContactInfoInspectorWillChangeInspectedObject"
    19 #define KEY_PREVIOUS_INSPECTED_OBJECT	@"PreviousInspectedObject"
    20 #define KEY_NEW_INSPECTED_OBJECT		@"NewInspectedObject"
    21 
    22 #define Interface_SendEnteredMessage				@"Interface_SendEnteredMessage"
    23 #define Interface_WillSendEnteredMessage 			@"Interface_WillSendEnteredMessage"
    24 #define Interface_DidSendEnteredMessage				@"Interface_DidSendEnteredMessage"
    25 #define Interface_ShouldDisplayErrorMessage			@"Interface_ShouldDisplayErrorMessage"
    26 #define Interface_ShouldDisplayQuestion				@"Interface_ShouldDisplayQuestion"
    27 #define Interface_ContactListDidBecomeMain			@"Interface_ContactListDidBecomeMain"
    28 #define Interface_ContactListDidResignMain			@"Interface_contactListDidResignMain"
    29 #define Interface_ContactListDidClose				@"Interface_contactListDidClose"
    30 #define Interface_TabArrangingPreferenceChanged		@"Interface_TabArrangingPreferenceChanged"
    31 #define AIViewDesiredSizeDidChangeNotification		@"AIViewDesiredSizeDidChangeNotification"
    32 
    33 #define PREF_GROUP_INTERFACE			@"Interface"
    34 #define KEY_TABBED_CHATTING				@"Tabbed Chatting"
    35 #define KEY_GROUP_CHATS_BY_GROUP		@"Group Chats By Group"
    36 #define KEY_SAVE_CONTAINERS				@"Save Containers On Quit"
    37 #define KEY_CONTAINERS					@"Containers"
    38 
    39 #define KEY_CL_WINDOW_LEVEL					@"Window Level"
    40 #define KEY_CL_HIDE							@"Hide While in Background"
    41 #define KEY_CL_EDGE_SLIDE					@"Hide On Screen Edges"
    42 #define KEY_CL_FLASH_UNVIEWED_CONTENT		@"Flash Unviewed Content"
    43 #define KEY_CL_ANIMATE_CHANGES				@"Animate Changes"
    44 #define KEY_CL_SHOW_TOOLTIPS				@"Show Tooltips"
    45 #define KEY_CL_SHOW_TOOLTIPS_IN_BACKGROUND	@"Show Tooltips in Background"
    46 #define KEY_CL_WINDOW_HAS_SHADOW			@"Window Has Shadow"
    47 
    48 #define PREF_GROUP_CONFIRMATIONS		@"Confirmations"
    49 #define KEY_CONFIRM_QUIT				@"Confirm Quit"
    50 #define KEY_CONFIRM_QUIT_TYPE			@"Confirm Quit Type"
    51 #define KEY_CONFIRM_QUIT_FT				@"Suppress Quit Confirmation for File Transfers"
    52 #define KEY_CONFIRM_QUIT_OPEN			@"Suppress Quit Confirmation for Open Chats"
    53 #define KEY_CONFIRM_QUIT_UNREAD			@"Suppress Quit Confirmation for Unread Messages"
    54 #define KEY_CONFIRM_MSG_CLOSE			@"Confirm Message Window Close"
    55 #define KEY_CONFIRM_MSG_CLOSE_TYPE		@"Confirm Message Window Close Type"
    56 
    57 typedef enum {
    58 	AINormalWindowLevel = 0,
    59 	AIFloatingWindowLevel = 1,
    60 	AIDesktopWindowLevel = 2
    61 } AIWindowLevel;
    62 
    63 //Identifiers for the various message views
    64 typedef enum {
    65 	DCStandardMessageView = 1,	//webkit is not available
    66 	DCWebkitMessageView			//Preferred message view
    67 } DCMessageViewType;
    68 
    69 @protocol AIInterfaceComponent, AIContactListComponent, AIMessageDisplayController, AIMessageDisplayPlugin;
    70 @protocol AIContactListTooltipEntry, AIFlashObserver;
    71 
    72 @class AIListWindowController, AIMessageWindowController, AIMessageViewController;
    73 
    74 @class AIChat, AIListObject, AIListGroup, AIContactList;
    75 
    76 @protocol AIInterfaceController <AIController>
    77 - (void)registerInterfaceController:(id <AIInterfaceComponent>)inController;
    78 - (void)registerContactListController:(id <AIContactListComponent>)inController;
    79 
    80 /*!	@brief	Implement handling of the reopen Apple Event.
    81  *
    82  *	@par	The reopen handler should respond by making sure that at least one of Adium's windows is visible.
    83  *
    84  *	@par	Adium.app's implementation handles this event this way:
    85  *
    86  *	@li	If there are no chat windows, shows the Contact List.
    87  *	@li	Else, if the foremost chat window and chat tab has unviewed content, make sure it stays foremost (bringing it forward of the Contact List, if necessary).
    88  *	@li	Else, if any chat window has unviewed content, bring foremost the chat window and chat tab with the most recent unviewed content.
    89  *	@li	Else, if all chat windows are minimized, unminimize one of them.
    90  *	@li	If the application is hidden, unhide it.
    91  *
    92  *	@return	A value suitable for returning from the \c NSApplication delegate method <code>applicationShouldHandleReopen:hasVisibleWindows:
    93 </code>. Specifically: \c YES if AppKit should perform its usual response to the event; \c NO if AppKit should do nothing.
    94  */
    95 - (BOOL)handleReopenWithVisibleWindows:(BOOL)visibleWindows;
    96 
    97 //Contact List
    98 /*! @name Contact List */
    99 /* @{ */
   100 /*!
   101  * @brief Brings contact list to the front
   102  */
   103 - (IBAction)showContactList:(id)sender;
   104 /*!
   105  * @brief Close the contact list window
   106  */
   107 - (IBAction)closeContactList:(id)sender;
   108 /*!
   109  * @returns YES if contact list is visible and selected, otherwise NO
   110  */
   111 @property (nonatomic, readonly) BOOL contactListIsVisibleAndMain;
   112 /*!
   113  * @returns YES if contact list is visible, otherwise NO
   114  */
   115 @property (nonatomic, readonly) BOOL contactListIsVisible;
   116 /*! @} */
   117 
   118 #pragma mark Detachable Contact List
   119 /*!
   120  * @brief Create a new AIListWindowController to display a given contact list group in a detached window
   121  *
   122  * @result Created contact list controller for detached contact list
   123  */
   124 - (AIListWindowController *)detachContactList:(AIContactList *)aContactList;
   125 
   126 #pragma mark Messaging
   127 /*!
   128  * @brief Opens tab or window for a chat (following user's preferences)
   129  *
   130  * @param inChat The chat. If already open, the chat will be brought to the front.
   131  */
   132 - (void)openChat:(AIChat *)inChat;
   133 
   134 /*!
   135  * @brief Opens a chat in a given container at a specific index
   136  *
   137  * NOTE: If the chat is already open, this won't move it and instead does nothing. Perhaps it should, though :)
   138  *
   139  * @param inChat The chat.
   140  * @param containerID The name of the container window.
   141  * @param index The index within that containter window.
   142  */
   143 - (id)openChat:(AIChat *)inChat inContainerWithID:(NSString *)containerID atIndex:(NSUInteger)index;
   144 
   145 /*!
   146  * @brief Move a chat to a new window container
   147  *
   148  * NOTE: The chat must already be open. That's a bug.
   149  */
   150 - (void)moveChatToNewContainer:(AIChat *)inChat;
   151 
   152 /*!
   153  * @brief Close the interface for a chat
   154  *
   155  * @param inChat The chat
   156  */
   157 - (void)closeChat:(AIChat *)inChat;
   158 
   159 /*!
   160  * @brief Consolidate all open chats into a single container
   161  */
   162 - (void)consolidateChats;
   163 
   164 /*!
   165  * @brief Active Chat property
   166  *
   167  * Setter brings the tab/window for a chat to the front and sets it as active
   168  * If no chat is active (a non-chat window is focued, or Adium is not focused), getter returns nil.
   169  */
   170 @property (nonatomic, retain) AIChat *activeChat;
   171 
   172 /*!
   173  * @brief Get the chat which was most recently active
   174  *
   175  * If -[self activeChat] is non-nil, this will be the same as activeChat. However, if no chat is active, so long
   176  * as any chat is open, this will return the chat most recently active.  If no chats are open, this will return nil.
   177  */
   178 @property (nonatomic, readonly) AIChat *mostRecentActiveChat;
   179 
   180 /*!
   181  * @brief Get all open chats
   182  *
   183  * @result The open chats. Returns an empty array if no chats are open.
   184  */
   185 @property (nonatomic, readonly) NSArray *openChats;
   186 
   187 /*!
   188  * @brief Get all open chats in a given container.
   189  *
   190  * @result The array of open chats. Returns nil if no container with containerID exists.
   191  */
   192 - (NSArray *)openChatsInContainerWithID:(NSString *)containerID;
   193 
   194 /*!
   195  * @brief Get an array of the containerIDs of all open containers
   196  */
   197 @property (nonatomic, readonly) NSArray *openContainerIDs;
   198 
   199 /*!
   200  * @brief Open a new container with a given ID and name
   201  *
   202  * @param containerID The container's ID. Pass nil to let Adium generate one
   203  * @param containerName THe name of the container. Pass nil to not specify one.
   204  *
   205  * @result The newly created AIMessageWindowController
   206  */
   207 - (AIMessageWindowController *)openContainerWithID:(NSString *)containerID name:(NSString *)containerName;
   208 
   209 /*!
   210  * @brief Cycles to the next open chat, making it active
   211  *
   212  * This crosses container boundaries.
   213  */
   214 - (void)nextChat:(id)sender;
   215 
   216 /*!
   217  * @brief Cycles to the previous open chat, making it active
   218  *
   219  * This crosses container boundaries.
   220  */
   221 - (void)previousChat:(id)sender;
   222 
   223 #pragma mark Interface plugin callbacks
   224 /*!
   225  * @brief A chat window did open: rebuild our window menu to show the new chat
   226  *
   227  * This should be called by the interface plugin (e.g. AIDualWindowInterfacePlugin) after a chat opens
   228  *
   229  * @param inChat Newly created chat 
   230  */
   231 - (void)chatDidOpen:(AIChat *)inChat;
   232 
   233 /*!
   234  * @brief A chat has become active: update our chat closing keys and flag this chat as selected in the window menu
   235  *
   236  * This should be called by the interface plugin (e.g. AIDualWindowInterfacePlugin) 
   237  *
   238  * @param inChat Chat which has become active
   239  */
   240 - (void)chatDidBecomeActive:(AIChat *)inChat;
   241 
   242 /*!
   243  * @brief A chat has become visible: send out a notification for components and plugins to take action
   244  *
   245  * This should be called by the interface plugin (e.g. AIDualWindowInterfacePlugin) 
   246  *
   247  * @param inChat Chat that has become active
   248  * @param inWindow Containing chat window
   249  */
   250 - (void)chatDidBecomeVisible:(AIChat *)inChat inWindow:(NSWindow *)inWindow;
   251 
   252 /*!
   253  * @brief A chat window did close: rebuild our window menu to remove the chat
   254  *
   255  * This should be called by the interface plugin (e.g. AIDualWindowInterfacePlugin) 
   256  * 
   257  * @param inChat Chat that closed
   258  */
   259 - (void)chatDidClose:(AIChat *)inChat;
   260 
   261 /*!
   262  * @brief The order of chats has changed: rebuild our window menu to reflect the new order
   263  *
   264  * This should be called by the interface plugin (e.g. AIDualWindowInterfacePlugin) 
   265  */
   266 - (void)chatOrderDidChange;
   267 
   268 #pragma mark Chat window access
   269 /*!
   270  * @brief Find the window currently displaying a chat
   271  *
   272  * @returns Window for chat otherwise if the chat is not in any window, or is not visible in any window, returns nil
   273  */
   274 - (NSWindow *)windowForChat:(AIChat *)inChat;
   275 
   276 
   277 /*!
   278  * @brief Find the chat active in a window
   279  *
   280  * If the window does not have an active chat, nil is returned
   281  */
   282 - (AIChat *)activeChatInWindow:(NSWindow *)window;
   283 
   284 #pragma mark Interface selection
   285 /*!
   286  * @brief Get the list object currently focused in the interface
   287  *
   288  * We find the first responder that knows about list objects and get its selected object.
   289  * This may be, for example, the contact list or a chat window.
   290  */
   291 @property (readonly, nonatomic) AIListObject *selectedListObject;
   292 
   293 /*!
   294  * @brief Get the list object currently selected in the contact list
   295  *
   296  * If multiple objects are selected, this returns the first one. If possible, use arrayOfSelectedListObjectsInContactList and
   297  * handle multiple selections.
   298  */
   299 @property (readonly, nonatomic) AIListObject *selectedListObjectInContactList;
   300 
   301 /*!
   302  * @brief Get the list objects currently selected in the contact list
   303  *
   304  * @result An NSArray of selected objects
   305  */
   306 @property (readonly, nonatomic) NSArray *arrayOfSelectedListObjectsInContactList;
   307 
   308 /*!
   309  * @brief Get the list objects currently selected in the contact list with their groups
   310  *
   311  * Each entry in the NSArray is an NSDictionary of the following layout:
   312  *
   313  * @"ListObject" => the AIListObject
   314  * @"ContainingObject" => the containing object
   315  *
   316  * @result An NSArray of selected objects
   317  */
   318 @property (readonly, nonatomic) NSArray *arrayOfSelectedListObjectsWithGroupsInContactList;
   319 
   320 #pragma mark Message View
   321 /*!
   322  * @brief Register an object which can handle displaying messages
   323  *
   324  * See @protocol AIMessageDisplayPlugin for details. An example of such an object is the WebKit Message View plugin.
   325  *
   326  * @param inPlugin The object, which must conform to @protocol(AIMessageDisplayPlugin)
   327  */
   328 - (void)registerMessageDisplayPlugin:(id <AIMessageDisplayPlugin>)inPlugin;
   329 
   330 /*!
   331  * @brief Unregister an object previously registered with registerMessageDisplayPlugin.
   332  */
   333 - (void)unregisterMessageDisplayPlugin:(id <AIMessageDisplayPlugin>)inPlugin;
   334 
   335 /*!
   336  * @brief Get the AIMessageDisplayController-conforming object for a chat
   337  *
   338  * Every chat has exactly one. You can get it!
   339  */
   340 - (id <AIMessageDisplayController>)messageDisplayControllerForChat:(AIChat *)inChat;
   341 
   342 #pragma mark Error Display
   343 - (void)handleErrorMessage:(NSString *)inTitle withDescription:(NSString *)inDesc;
   344 - (void)handleMessage:(NSString *)inTitle withDescription:(NSString *)inDesc withWindowTitle:(NSString *)inWindowTitle;
   345 
   346 #pragma mark Question Display
   347 - (void)displayQuestion:(NSString *)inTitle withAttributedDescription:(NSAttributedString *)inDesc withWindowTitle:(NSString *)inWindowTitle
   348 		  defaultButton:(NSString *)inDefaultButton alternateButton:(NSString *)inAlternateButton otherButton:(NSString *)inOtherButton suppression:(NSString *)inSuppression
   349 				 target:(id)inTarget selector:(SEL)inSelector userInfo:(id)inUserInfo;
   350 - (void)displayQuestion:(NSString *)inTitle withDescription:(NSString *)inDesc withWindowTitle:(NSString *)inWindowTitle
   351 		  defaultButton:(NSString *)inDefaultButton alternateButton:(NSString *)inAlternateButton otherButton:(NSString *)inOtherButton suppression:(NSString *)inSuppression
   352 				 target:(id)inTarget selector:(SEL)inSelector userInfo:(id)inUserInfo;
   353 
   354 #pragma mark Synchronized Flashing
   355 - (void)registerFlashObserver:(id <AIFlashObserver>)inObserver;
   356 - (void)unregisterFlashObserver:(id <AIFlashObserver>)inObserver;
   357 - (int)flashState;
   358 
   359 #pragma mark Tooltips
   360 /*!
   361  * @brief Register a tooltip-supplying object
   362  *
   363  * @param inEntry The object which will be queried for information when building a tooltip. Must conform to the AIContactListTooltipEntry protocol.
   364  * @param isSecondary Most tooltips are secondary; this means they are displayed in the bottom half of the tooltip which can expand as needed.
   365  */
   366 - (void)registerContactListTooltipEntry:(id <AIContactListTooltipEntry>)inEntry secondaryEntry:(BOOL)isSecondary;
   367 
   368 /*!
   369  * @brief Unregister a previously reigstered tooltip-supplying object
   370  *
   371  * @param inEntry The object to unregister
   372  * @param isSecondary This should match the value passed to registerContactListTooltipEntry:secondaryEntry:
   373  */
   374 - (void)unregisterContactListTooltipEntry:(id <AIContactListTooltipEntry>)inEntry secondaryEntry:(BOOL)isSecondary;
   375 
   376 /*!
   377  * @brief Get an array of all primary contact list tooltip entries
   378  *
   379  * @result An NSArray of objects conforming to AIContactListTooltipEntry
   380  */
   381 - (NSArray *)contactListTooltipPrimaryEntries;
   382 
   383 /*!
   384  * @brief Get an array of all secondary contact list tooltip entries
   385  *
   386  * @result An NSArray of objects conforming to AIContactListTooltipEntry
   387  */
   388 - (NSArray *)contactListTooltipSecondaryEntries;
   389 
   390 /*!
   391  * @brief Show an object's tooltip at a given point
   392  *
   393  * If object is not nil, the tooltip box will be shown for that object at the given point. It is created if needed;
   394  * if there is an existing object tooltip, that window is moved to the given point and reconfigured for object.
   395  * This is a rich-text, information-rich tooltip, not a simple text tooltip as seen elsewhere in Mac OS X.
   396  *
   397  * @param object The object for which the tooltip should be shown. Pass nil to hide any existing tooltip.
   398  * @param point The point in screen coordinates for the tooltip's origin. If object is nil, this value is ignored.
   399  * @param inWindow The window from which the tooltip is originating. If object is nil, this value is ignored.
   400  */
   401 - (void)showTooltipForListObject:(AIListObject *)object atScreenPoint:(NSPoint)point onWindow:(NSWindow *)inWindow;
   402 
   403 #pragma mark Window level menu
   404 /*!
   405  * @brief Build a menu of possible window levels
   406  *
   407  * Window levels may be, for example, 'Above other windows' or 'Normally'.
   408  *
   409  * @param target The target on which @selector(selectedWindowLevel:) will be called when a menu item is selected
   410  */
   411 - (NSMenu *)menuForWindowLevelsNotifyingTarget:(id)target;
   412 
   413 @end
   414 
   415 //Controls a contact list view
   416 @protocol AIContactListViewController <NSObject>	
   417 - (NSView *)contactListView;
   418 @end
   419 
   420 //Manages contact list view controllers
   421 @protocol AIContactListController <NSObject>	
   422 - (id <AIContactListViewController>)contactListViewController;
   423 @end
   424 
   425 /*!
   426  * @protocol AIMessageDisplayController
   427  * @brief    The message display controller is responsible for, unsurprisingly, the actual display of messages.
   428  *
   429  * The display controller manages a view ("messageView") which will be inserted along with other UI elements such
   430  * as a text entry area into a window.  The Interface Plugin knows nothing about how the AIMessageDisplayController 
   431  * keeps its messageView up to date, nor should it, but knows that the view will show messages.
   432  *
   433  * The AIMessageDisplayController is informed when the message view which is using it is closing.
   434  *
   435  * This is, for example, the AIWebKitMessageViewController.
   436  */
   437 @protocol AIMessageDisplayController <NSObject>
   438 - (void)setChatContentSource:(NSString *)source;
   439 - (NSString *)chatContentSource;
   440 - (NSString *)contentSourceName; // Unique name for this particular style of "content source".
   441 
   442 - (NSView *)messageView;
   443 - (NSView *)messageScrollView;
   444 - (void)messageViewIsClosing;
   445 - (void)clearView;
   446 
   447 - (void)jumpToPreviousMark;
   448 - (BOOL)previousMarkExists;
   449 
   450 - (void)jumpToNextMark;
   451 - (BOOL)nextMarkExists;
   452 
   453 - (void)jumpToFocusMark;
   454 - (BOOL)focusMarkExists;
   455 
   456 - (void)addMark;
   457 - (void)markForFocusChange;
   458 @end
   459 
   460 /*
   461  * @protocol AIMessageDisplayPlugin
   462  * @brief    A AIMessageDisplayPlugin provides AIMessageDisplayController objects on demand.
   463  *
   464  * The WebKit display plugin is one example.
   465  */
   466 @protocol AIMessageDisplayPlugin <NSObject, AIPlugin>	
   467 - (id <AIMessageDisplayController>)messageDisplayControllerForChat:(AIChat *)inChat;
   468 @end
   469 
   470 @protocol AIContactListTooltipEntry <NSObject>
   471 - (NSString *)labelForObject:(AIListObject *)inObject;
   472 - (NSAttributedString *)entryForObject:(AIListObject *)inObject;
   473 - (BOOL)shouldDisplayInContactInspector;
   474 @end
   475 
   476 @protocol AIFlashObserver <NSObject>
   477 - (void)flash:(int)value;
   478 @end
   479 
   480 //Handles any attributed text entry
   481 @protocol AITextEntryView 
   482 - (void)setAttributedString:(NSAttributedString *)inAttributedString;
   483 - (void)setTypingAttributes:(NSDictionary *)attrs;
   484 - (BOOL)availableForSending;
   485 - (AIChat *)chat;
   486 @end
   487 
   488 @protocol AIInterfaceComponent <NSObject>
   489 - (void)openInterface;
   490 - (void)closeInterface;
   491 - (id)openChat:(AIChat *)chat inContainerWithID:(NSString *)containerID withName:(NSString *)containerName atIndex:(NSUInteger)index;
   492 - (void)setActiveChat:(AIChat *)inChat;
   493 - (void)moveChat:(AIChat *)chat toContainerWithID:(NSString *)containerID index:(NSUInteger)index;
   494 - (void)moveChatToNewContainer:(AIChat *)inChat;
   495 - (void)closeChat:(AIChat *)chat;
   496 - (AIMessageWindowController *)openContainerWithID:(NSString *)containerID name:(NSString *)containerName;
   497 /*!
   498  * @brief Return an array of NSDictionary objects for all open containers with associated information
   499  * 
   500  * The returned array has zero or more NSDictionary objects with the following information for each container
   501  *	Key			Value
   502  *	@"ID"		NSString of the containerID
   503  *	@"Frame"	NSString of the window's [NSWindow frame]
   504  *	@"Content"	NSArray of the AIChat objects within that container
   505  *	@"ActiveChat"	AIChat that is currently active
   506  *	@"Name"		NSString of the container's name
   507  */
   508 @property (readonly, nonatomic) NSArray *openContainersAndChats;
   509 @property (readonly, nonatomic) NSArray *openContainerIDs;
   510 @property (readonly, nonatomic) NSArray *openChats;
   511 - (NSArray *)openChatsInContainerWithID:(NSString *)containerID;
   512 - (NSString *)containerIDForChat:(AIChat *)chat;
   513 - (NSWindow *)windowForChat:(AIChat *)chat;
   514 - (AIChat *)activeChatInWindow:(NSWindow *)window;
   515 @end
   516 
   517 /*!
   518  * @protocol AIInterfaceContainer
   519  * @brief This protocol is for a general interface element such as the contact list or the container of a chat
   520  */
   521 @protocol AIInterfaceContainer <NSObject>
   522 - (void)makeActive:(id)sender;	//Make the container active/front
   523 - (void)close:(id)sender;	//Close the container
   524 @end
   525 
   526 /*!
   527  * @protocol AIChatViewController
   528  * @brief A AIChatViewController manages everything pertaining to a chat's view area
   529  *
   530  * It will manage this view, text input, and any associated controls.
   531  */
   532 @protocol AIChatViewController <NSObject>
   533 - (NSView *)view;
   534 - (NSScrollView *)messagesScrollView;
   535 - (AIChat *)chat;
   536 
   537 /*!
   538  * @brief Show/hide the user list for a group chat.
   539  * Does nothing if not in a group chat.
   540  */
   541 - (void)toggleUserList;
   542 
   543 /*!
   544  * @brief Is the user list visible for a group chat?
   545  */
   546 - (BOOL)userListVisible;
   547 
   548 /*!
   549  * @brief Swap the side the user list is on for a group chat.
   550  * Does nothing if not in a group chat.
   551  */
   552 - (void)toggleUserListSide;
   553 @end
   554 
   555 /*!
   556  * @protocol AIChatContainer
   557  * @brief This protocol is for an object which displays a single chat (e.g. a tab in a chat window)
   558  */
   559 @protocol AIChatContainer <AIInterfaceContainer>
   560 /*
   561  * @brief Get the window controller which holds this AIChatContainer
   562  */
   563 @property (readonly, nonatomic, retain) AIMessageWindowController *windowController;
   564 
   565 /*
   566  * @brief Get the view controller for this AIChatContainer
   567  */
   568 @property (readonly, nonatomic) id <AIChatViewController> chatViewController;
   569 
   570 /*!
   571  * @brief Get the message view controller for this AIChatContainer
   572  */
   573 @property (readonly, nonatomic) AIMessageViewController *messageViewController;
   574 @end
   575 
   576 @protocol AIContactListComponent <NSObject>
   577 /*!
   578  * @brief Show the contact list window and bring Adium to the front
   579  */
   580 - (void)showContactListAndBringToFront:(BOOL)bringToFront;
   581 - (BOOL)contactListIsVisibleAndMain;
   582 - (BOOL)contactListIsVisible;
   583 - (void)closeContactList;
   584 @end
   585 
   586 @protocol AIMultiContactListComponent <AIContactListComponent>
   587 - (id)detachContactList:(AIContactList *)contactList;
   588 - (void)nextDetachedContactList;
   589 - (void)previousDetachedContactList;
   590 @end
   591 
   592 //Custom printing informal protocol
   593 @interface NSObject (AdiumPrinting)
   594 - (void)adiumPrint:(id)sender;
   595 - (BOOL)validatePrintMenuItem:(NSMenuItem *)menuItem;
   596 @end
   597 
   598 @interface NSWindowController (AdiumBorderlessWindowClosing)
   599 - (BOOL)windowPermitsClose;
   600 @end