📄 clusterimcontainercontroller.mm
字号:
/*
* 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 + -