⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clusterimcontainercontroller.mm

📁 lumaqq
💻 MM
📖 第 1 页 / 共 2 页
字号:
/*
 * LumaQQ - Cross platform QQ client, special edition for Mac
 *
 * Copyright (C) 2007 luma <stubma@163.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 0 2111-1307 USA
 */

#import "ClusterIMContainerController.h"
#import "ClusterCommandPacket.h"
#import "MainWindowController.h"
#import "QQCell.h"
#import "ImageTool.h"
#import "ClusterIM.h"
#import "ClusterSendIMExPacket.h"
#import "TimerTaskManager.h"
#import "ByteTool.h"
#import "NSString-Validate.h"
#import "NSString-Filter.h"
#import "AnimationHelper.h"

// member table menu tag
#define _kMenuItemTagUserInfo 1000
#define _kMenuItemTagAddAsFriend 1001
#define _kMenuItemTagTempSession 1002

@implementation ClusterIMContainerController

#pragma mark -
#pragma mark IMContainer protocol

- (id)initWithObject:(id)obj mainWindow:(MainWindowController*)mainWindowController {
	m_cluster = (Cluster*)obj;
	return [super initWithObject:obj mainWindow:mainWindowController];
}

- (void) dealloc {
	// if we don't do this, it runs into a weird crash, don't know why
	[m_memberTable setDataSource:nil];
	[m_memberTable setDelegate:nil];
	
	[m_memberView release];	
	[super dealloc];
}

- (BOOL)handleQQEvent:(QQNotification*)event {
	BOOL ret = NO;
	
	switch([event eventId]) {
		case kQQEventClusterSendIMOK:
			ret = [self handleClusterSendIMOK:event];
			break;
		case kQQEventClusterSendIMFailed:
			ret = [self handleClusterSendIMFailed:event];
			break;
		case kQQEventClusterGetInfoOK:
			ret = [self handleClusterGetInfoOK:event];
			break;
		case kQQEventClusterGetMemberInfoOK:
			ret = [self handleClusterGetMemberInfoOK:event];
			break;
		case kQQEventClusterGetOnlineMemberOK:
			ret = [self handleClusterGetOnlineMemberOK:event];
			break;
		case kQQEventTempClusterGetInfoOK:
			ret = [self handleTempClusterGetInfoOK:event];
			break;
		case kQQEventTempClusterSendIMOK:
			ret = [self handleTempClusterSendIMOK:event];
			break;
		case kQQEventTempClusterSendIMFailed:
			ret = [self handleTempClusterSendIMFailed:event];
			break;
		case kQQEventTimeoutBasic:
			OutPacket* packet = [event outPacket];
			switch([packet command]) {
				case kQQCommandCluster:
					ClusterCommandPacket* ccp = (ClusterCommandPacket*)packet;
					switch([ccp subCommand]) {
						case kQQSubCommandClusterSendIMEx:
							ret = [self handleClusterSendIMTimeout:event];
							break;
						case kQQSubCommandTempClusterSendIM:
							ret = [self handleTempClusterSendIMTimeout:event];
							break;
					}
					break;
			}
			break;
	}
	
	return ret;
}

- (void)walkMessageQueue:(MessageQueue*)queue {
	if(queue == nil)
		return;
	
	while(InPacket* packet = [queue getClusterMessage:[m_cluster internalId] remove:YES]) {
		[self appendPacket:packet];
	}
	
	// refresh dock icon
	[m_mainWindowController refreshDockIcon];
	
	[m_cluster setMessageCount:0];
}

- (NSString*)owner {
	return [NSString stringWithFormat:@"%u", [m_cluster internalId]];
}

- (NSImage*)ownerImage {
	return [NSImage imageNamed:kImageClusters];
}

- (void)refreshHeadControl:(HeadControl*)headControl {
	[headControl setShowStatus:NO];
	[headControl setHead:kHeadUseImage];
	[headControl setImage:[NSImage imageNamed:kImageClusters]];
}

- (id)windowKey {
	return [NSNumber numberWithUnsignedInt:[m_cluster internalId]];
}

- (NSString*)description {
	if([m_cluster permanent])
		return [NSString stringWithFormat:L(@"LQClusterTitle", @"ClusterIMContainer"), [m_cluster name], [m_cluster externalId]];
	else if([m_cluster isSubject])
		return [NSString stringWithFormat:L(@"LQSubjectTitle", @"ClusterIMContainer"), [m_cluster name]];
	else if([m_cluster isDialog])
		return [NSString stringWithFormat:L(@"LQDialogTitle", @"ClusterIMContainer"), [m_cluster name]];
	else
		return kStringEmpty;
}

- (NSString*)shortDescription {
	return [m_cluster name];
}

- (NSArray*)actionIds {
	if(m_actionIds == nil) {
		m_actionIds = [[NSArray arrayWithObjects:kToolbarItemFont, 
			kToolbarItemColor, 
			kToolbarItemSwitchMemberView,
			NSToolbarSeparatorItemIdentifier,
			kToolbarItemSmiley,
			NSToolbarSeparatorItemIdentifier,
			kToolbarItemSendPicture,
			kToolbarItemScreenscrap,
			nil] retain];
	}
	return m_actionIds;
}

- (NSImage*)actionImage:(NSString*)actionId {
	if([actionId isEqualToString:kToolbarItemSwitchMemberView])
		return [NSImage imageNamed:kImageInformation];
	else
		return [super actionImage:actionId];
}

- (NSString*)actionTooltip:(NSString*)actionId {
	if([actionId isEqualToString:kToolbarItemSwitchMemberView])
		return L(@"LQTooltipSwitchMemberView", @"BaseIMContainer");
	else
		return [super actionTooltip:actionId];
}

- (void)performAction:(NSString*)actionId {
	if([actionId isEqualToString:kToolbarItemSwitchMemberView])
		[self onSwitchMemberView:self];
	else
		[super performAction:actionId];
}

- (void)handleIMContainerAttachedToWindow:(NSNotification*)notification {
	if(m_imView == [notification object]) {
		[m_split setDelegate:self];
		
		// get input box proportion
		float proportion = [m_cluster inputBoxProportion];
		
		// adjust split view
		[self adjustSplitView:m_split belowProportion:proportion];
	}
}

#pragma mark -
#pragma mark PSMTabModel protocol

- (int)objectCount {
	return [m_cluster messageCount];
}

#pragma mark -
#pragma mark helper

- (void)adjustSplitView:(NSSplitView*)split belowProportion:(float)belowProportion {
	// get split view bound
	NSRect bound = [split bounds];
	
	// set input box size
	NSRect frame;
	frame.origin = NSZeroPoint;
	frame.size = bound.size;
	frame.size.height = bound.size.height * (1.0 - belowProportion);
	frame.size.height = MAX(20.0, frame.size.height);
	frame.size.height = MIN(bound.size.height - 20.0, frame.size.height);
	[(NSView*)[[split subviews] objectAtIndex:0] setFrame:frame];
	
	// set output box size
	frame.origin.y = frame.size.height + [split dividerThickness];
	frame.size.height = bound.size.height - frame.origin.y;
	[(NSView*)[[split subviews] objectAtIndex:1] setFrame:frame];
	
	[split adjustSubviews];
}

- (NSString*)getUserDisplayName:(User*)user QQ:(UInt32)QQ {
	// get display string, first we get cluster name card, then nick, then qq number
	NSString* dname = nil;
	if(user) {
		ClusterSpecificInfo* info = [user getClusterSpecificInfo:[m_cluster internalId]];
		if(info) {
			dname = [[info nameCard] name];
			if([dname isEmpty])
				dname = [user nick];
		} else
			dname = [user nick];
	} else
		dname = [NSString stringWithFormat:@"%u", QQ];
	
	// check empty nick
	if([dname isEmpty])
		dname = [NSString stringWithFormat:@"%u", QQ];
	
	return dname;
}

#pragma mark -
#pragma mark split view delegate

- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)offset {
	if(sender == m_split)
		return 20;
	else
		return 0;
}

- (float)splitView:(NSSplitView *)sender constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)offset {
	if(sender == m_split)
		return [sender bounds].size.height - 20 - [sender dividerThickness];
	else
		return [sender bounds].size.height - [sender dividerThickness];
}

- (void)splitViewDidResizeSubviews:(NSNotification *)aNotification {
	if([aNotification object] == m_split) {
		NSView* view = [[m_split subviews] objectAtIndex:1];
		float newProp = ([view bounds].size.height + [m_split dividerThickness]) / [m_split bounds].size.height;
		[m_cluster setInputBoxProportion:newProp];
	}
}

#pragma mark -
#pragma mark override super

- (void)sendCustomFaces:(CustomFaceList*)faceList {
	[[m_mainWindowController client] sendClusterCustomFaces:faceList];
}

- (void)appendPacket:(QQTextView*)textView packet:(InPacket*)inPacket {
	ReceivedIMPacket* packet = (ReceivedIMPacket*)inPacket;
	ClusterIM* im = [packet clusterIM];
	
	// get custom face, client will automatically get them so don't bother here
	CustomFaceList* faceList = [[m_mainWindowController client] removeFaceList:packet];
	if(faceList)
		[[faceList retain] autorelease];
	
	// get display string, first we get cluster name card, then nick, then qq number
	User* user = [[m_mainWindowController groupManager] user:[im sender]];
	NSString* dname = [self getUserDisplayName:user QQ:[im sender]];
	
	// append message
	[self appendMessage:textView
				   nick:dname 
				   data:[im messageData]
				  style:[im fontStyle]
				   date:[NSDate dateWithTimeIntervalSince1970:[im sendTime]]
			customFaces:faceList];
}

- (UInt16)doSend:(NSData*)data style:(FontStyle*)style fragmentCount:(int)fragmentCount fragmentIndex:(int)fragmentIndex {
	if([m_cluster permanent]) {
		return [[m_mainWindowController client] sendClusterIM:[m_cluster internalId]
												  messageData:data
														style:style
												fragmentCount:fragmentCount
												fragmentIndex:fragmentIndex];
	} else {
		return [[m_mainWindowController client] sendTempClusterIM:[m_cluster internalId]
														   parent:[m_cluster parentId] 
													  clusterType:[m_cluster tempType]
													  messageData:data
															style:style
													fragmentCount:fragmentCount
													fragmentIndex:fragmentIndex];
	}
}

- (void)handleHistoryDidSelected:(NSNotification*)notification {
	History* history = [[notification userInfo] objectForKey:kUserInfoHistory];
	if(history == m_history) {
		id object = [notification object];
		if([object isKindOfClass:[SentIM class]]) {
			[self appendMessageHint:m_txtInput
							   nick:[[m_mainWindowController me] nick]
							   date:[NSDate dateWithTimeIntervalSince1970:[(SentIM*)object sendTime]]
						 attributes:m_myHintAttributes];
			[[m_txtInput textStorage] appendAttributedString:[(SentIM*)object message]];
			if(![m_txtInput allowMultiFont])
				[m_txtInput changeAttributesOfAllText:[m_txtInput typingAttributes]];
		} else if([object isKindOfClass:[InPacket class]]) {
			[self appendPacket:m_txtInput packet:(InPacket*)object];
		}
	}
}

#pragma mark -
#pragma mark initialization

- (void)awakeFromNib {
	[super awakeFromNib];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -