adium/adium
Clone
Summary
Browse
Changes
Graph
Adium 1.5.2 is done!
adium-1.5.2
1.5.2
2012-07-21, Thijs Alkemade
80cc358134ea
Adium 1.5.2 is done!
/*
* Adium is the legal property of its developers, whose names are listed in the copyright file included
* with this source distribution.
*
* 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 02111-1307, USA.
*/
#import "AIEmoticon.h"
#import "AIEmoticonPack.h"
#import "AIEmoticonPackPreviewController.h"
#import "AIEmoticonPackPreviewView.h"
#import "AIEmoticonPreferences.h"
#import "AIEmoticonController.h"
#import <AIUtilities/AITableViewAdditions.h>
#import <AIUtilities/AIGenericViewCell.h>
#import <AIUtilities/AIImageAdditions.h>
#import <AIUtilities/AIArrayAdditions.h>
#import <AIUtilities/AIVerticallyCenteredTextCell.h>
#import <Adium/AIListObject.h>
#define EMOTICON_PACK_DRAG_TYPE @"AIEmoticonPack"
#define EMOTICON_MIN_ROW_HEIGHT 17
#define EMOTICON_MAX_ROW_HEIGHT 64
#define EMOTICON_PACKS_TOOLTIP AILocalizedString(@"Reorder emoticon packs by dragging. Packs are used in the order listed.",nil)
@interface
AIEmoticonPreferences
()
-
(
void
)
_configureEmoticonListForSelection
;
-
(
void
)
moveSelectedPacksToTrash
;
-
(
void
)
configurePreviewControllers
;
-
(
void
)
sheetDidEnd:
(
NSWindow
*
)
sheet
returnCode:
(
NSInteger
)
returnCode
contextInfo:
(
void
*
)
contextInfo
;
-
(
void
)
trashConfirmSheetDidEnd:
(
NSWindow
*
)
sheet
returnCode:
(
NSInteger
)
returnCode
contextInfo:
(
void
*
)
contextInfo
;
@end
@implementation
AIEmoticonPreferences
-
(
id
)
init
{
if
(
self
=
[
super
initWithWindowNibName
:
@"EmoticonPrefs"
])
{
}
return
self
;
}
-
(
void
)
openOnWindow:
(
NSWindow
*
)
parentWindow
{
if
(
parentWindow
)
{
[
NSApp
beginSheet
:
self
.
window
modalForWindow
:
parentWindow
modalDelegate
:
self
didEndSelector
:
@selector
(
sheetDidEnd
:
returnCode
:
contextInfo
:
)
contextInfo
:
nil
];
}
else
{
[
self
showWindow
:
nil
];
[
self
.
window
makeKeyAndOrderFront
:
nil
];
[
NSApp
activateIgnoringOtherApps
:
YES
];
}
}
/*!
* Invoked as the sheet closes, dismiss the sheet
*/
-
(
void
)
sheetDidEnd:
(
NSWindow
*
)
sheet
returnCode:
(
NSInteger
)
returnCode
contextInfo:
(
void
*
)
contextInfo
{
[
sheet
orderOut
:
nil
];
viewIsOpen
=
NO
;
[
adium
.
preferenceController
unregisterPreferenceObserver
:
self
];
[
adium
.
emoticonController
flushEmoticonImageCache
];
[
self
autorelease
];
}
//Configure the preference view
//- (void)viewDidLoad
-
(
void
)
windowDidLoad
{
//Pack table
[
table_emoticonPacks
registerForDraggedTypes
:
[
NSArray
arrayWithObject
:
EMOTICON_PACK_DRAG_TYPE
]];
//Configure the outline view
[[
table_emoticonPacks
tableColumnWithIdentifier
:
@"Emoticons"
]
setDataCell
:
[[[
AIGenericViewCell
alloc
]
init
]
autorelease
]];
[
table_emoticonPacks
selectRowIndexes
:
[
NSIndexSet
indexSetWithIndex
:
0
]
byExtendingSelection
:
NO
];
[
table_emoticonPacks
setToolTip
:
EMOTICON_PACKS_TOOLTIP
];
[
table_emoticonPacks
setDelegate
:
self
];
[
table_emoticonPacks
setDataSource
:
self
];
[
self
configurePreviewControllers
];
//Emoticons table
[
selectedEmoticonPack
release
];
selectedEmoticonPack
=
nil
;
checkCell
=
[[
NSButtonCell
alloc
]
init
];
[
checkCell
setButtonType
:
NSSwitchButton
];
[
checkCell
setControlSize
:
NSSmallControlSize
];
[
checkCell
setTitle
:
@""
];
[
checkCell
setRefusesFirstResponder
:
YES
];
[[
table_emoticons
tableColumnWithIdentifier
:
@"Enabled"
]
setDataCell
:
checkCell
];
NSImageCell
*
imageCell
=
[[
NSImageCell
alloc
]
initImageCell
:
nil
];
if
([
imageCell
respondsToSelector
:
@selector
(
_setAnimates
:
)])
[
imageCell
_setAnimates
:
NO
];
[[
table_emoticons
tableColumnWithIdentifier
:
@"Image"
]
setDataCell
:
imageCell
];
[
imageCell
release
];
AIVerticallyCenteredTextCell
*
textCell
=
[[
AIVerticallyCenteredTextCell
alloc
]
init
];
[
textCell
setLineBreakMode
:
NSLineBreakByTruncatingTail
];
[[
table_emoticons
tableColumnWithIdentifier
:
@"Name"
]
setDataCell
:
textCell
];
[
textCell
release
];
textCell
=
[[
AIVerticallyCenteredTextCell
alloc
]
init
];
[
textCell
setLineBreakMode
:
NSLineBreakByTruncatingTail
];
[[
table_emoticons
tableColumnWithIdentifier
:
@"String"
]
setDataCell
:
textCell
];
[
textCell
release
];
[
table_emoticons
setUsesAlternatingRowBackgroundColors
:
YES
];
//Observe prefs
[
adium
.
preferenceController
registerPreferenceObserver
:
self
forGroup
:
PREF_GROUP_EMOTICONS
];
//Configure the right pane to display the emoticons for the current selection
[
self
_configureEmoticonListForSelection
];
[
button_OK
setLocalizedString
:
AILocalizedStringFromTable
(
@"Close"
,
@"Buttons"
,
nil
)];
//Redisplay the emoticons after an small delay so the sample emoticons line up properly
//since the desired width isn't known by AIEmoticonPackCell until once through the list of packs
[
table_emoticonPacks
performSelector
:
@selector
(
display
)
withObject
:
nil
afterDelay
:
0
];
viewIsOpen
=
YES
;
}
-
(
void
)
windowWillClose:
(
id
)
sender
{
viewIsOpen
=
NO
;
[
super
windowWillClose
:
sender
];
[
adium
.
preferenceController
unregisterPreferenceObserver
:
self
];
[
adium
.
emoticonController
flushEmoticonImageCache
];
[
self
autorelease
];
}
-
(
void
)
dealloc
{
[
checkCell
release
];
checkCell
=
nil
;
[
selectedEmoticonPack
release
];
selectedEmoticonPack
=
nil
;
[
emoticonPackPreviewControllers
release
];
emoticonPackPreviewControllers
=
nil
;
[
emoticonImageCache
release
];
emoticonImageCache
=
nil
;
[
super
dealloc
];
}
-
(
void
)
configurePreviewControllers
{
NSEnumerator
*
enumerator
;
AIEmoticonPack
*
pack
;
NSView
*
view
;
//First, remove any AIEmoticonPackPreviewView instances from the table
enumerator
=
[[[[
table_emoticonPacks
subviews
]
copy
]
autorelease
]
objectEnumerator
];
while
((
view
=
[
enumerator
nextObject
]))
{
if
([
view
isKindOfClass
:
[
AIEmoticonPackPreviewView
class
]])
{
[
view
removeFromSuperviewWithoutNeedingDisplay
];
}
}
//Now [re]create the array of emoticon pack preview controlls
[
emoticonPackPreviewControllers
release
];
emoticonPackPreviewControllers
=
[[
NSMutableArray
alloc
]
init
];
enumerator
=
[[
adium
.
emoticonController
availableEmoticonPacks
]
objectEnumerator
];
while
((
pack
=
[
enumerator
nextObject
]))
{
[
emoticonPackPreviewControllers
addObject
:
[
AIEmoticonPackPreviewController
previewControllerForPack
:
pack
preferences
:
self
]];
}
//Finally, reload
[
table_emoticonPacks
reloadData
];
}
//Configure the emoticon table view for the currently selected pack
-
(
void
)
_configureEmoticonListForSelection
{
NSInteger
rowHeight
=
EMOTICON_MIN_ROW_HEIGHT
;
NSInteger
selectedRow
=
[
table_emoticonPacks
selectedRow
];
NSArray
*
availableEmoticonPacks
=
[
adium
.
emoticonController
availableEmoticonPacks
];
//Remember the selected pack
if
([
table_emoticonPacks
numberOfSelectedRows
]
==
1
&&
((
selectedRow
!=
-1
)
&&
(
selectedRow
<
[
availableEmoticonPacks
count
])))
{
[
selectedEmoticonPack
release
];
selectedEmoticonPack
=
[[
availableEmoticonPacks
objectAtIndex
:
selectedRow
]
retain
];
}
else
{
selectedEmoticonPack
=
nil
;
}
//Set the row height to the average height of the emoticons
if
(
selectedEmoticonPack
)
{
NSEnumerator
*
enumerator
;
AIEmoticon
*
emoticon
;
NSInteger
totalHeight
=
0
;
enumerator
=
[[
selectedEmoticonPack
emoticons
]
objectEnumerator
];
while
((
emoticon
=
[
enumerator
nextObject
]))
{
totalHeight
+=
[[
emoticon
image
]
size
].
height
;
}
rowHeight
=
totalHeight
/
[[
selectedEmoticonPack
emoticons
]
count
];
if
(
rowHeight
<
EMOTICON_MIN_ROW_HEIGHT
)
rowHeight
=
EMOTICON_MIN_ROW_HEIGHT
;
if
(
rowHeight
>
EMOTICON_MAX_ROW_HEIGHT
)
rowHeight
=
EMOTICON_MAX_ROW_HEIGHT
;
}
[
emoticonImageCache
release
];
emoticonImageCache
=
[[
NSMutableDictionary
alloc
]
init
];
//Update the table
[
table_emoticons
reloadData
];
[
table_emoticons
setRowHeight
:
rowHeight
];
//Update header
if
(
selectedEmoticonPack
)
{
//Enable the individual emoticon checks only if the selectedEmoticonPack is enabled
[
checkCell
setEnabled
:
selectedEmoticonPack
.
isEnabled
];
[
textField_packTitle
setStringValue
:
[
NSString
stringWithFormat
:
AILocalizedString
(
@"Emoticons in %@"
,
"Emoticons in <an emoticon pack name>"
),[
selectedEmoticonPack
name
]]];
}
else
{
[
textField_packTitle
setStringValue
:
@""
];
}
}
//Reflect new preferences in view
-
(
void
)
preferencesChangedForGroup:
(
NSString
*
)
group
key:
(
NSString
*
)
key
object
:(
AIListObject
*
)
object
preferenceDict:
(
NSDictionary
*
)
prefDict
firstTime:
(
BOOL
)
firstTime
{
//Refresh our emoticon tables
[
table_emoticonPacks
reloadData
];
[
self
_configureEmoticonListForSelection
];
}
//Returns a dimmed, attributed version of the passed string
-
(
NSAttributedString
*
)
_dimString:
(
NSString
*
)
inString
center:
(
BOOL
)
center
{
NSMutableDictionary
*
attributes
=
[
NSMutableDictionary
dictionaryWithObject
:
[
NSColor
grayColor
]
forKey
:
NSForegroundColorAttributeName
];
if
(
center
)
{
[
attributes
setObject
:
[
NSParagraphStyle
styleWithAlignment
:
NSCenterTextAlignment
]
forKey
:
NSParagraphStyleAttributeName
];
}
return
[[[
NSAttributedString
alloc
]
initWithString
:
inString
attributes
:
attributes
]
autorelease
];
}
#pragma mark Table view data source
//Emoticon table view
-
(
NSInteger
)
numberOfRowsInTableView:
(
NSTableView
*
)
tableView
{
if
(
tableView
==
table_emoticonPacks
)
{
return
[
emoticonPackPreviewControllers
count
];
}
else
{
return
[[
selectedEmoticonPack
emoticons
]
count
];
}
}
-
(
void
)
tableView:
(
NSTableView
*
)
tableView
willDisplayCell:
(
id
)
cell
forTableColumn:
(
NSTableColumn
*
)
tableColumn
row:
(
NSInteger
)
row
{
if
(
tableView
==
table_emoticonPacks
)
{
[
cell
setEmbeddedView
:
[[
emoticonPackPreviewControllers
objectAtIndex
:
row
]
view
]];
}
}
//Emoticon table view delegates
-
(
id
)
tableView:
(
NSTableView
*
)
tableView
objectValueForTableColumn:
(
NSTableColumn
*
)
tableColumn
row:
(
NSInteger
)
row
{
if
(
tableView
==
table_emoticonPacks
)
return
@""
;
NSString
*
identifier
=
[
tableColumn
identifier
];
AIEmoticon
*
emoticon
=
[[
selectedEmoticonPack
emoticons
]
objectAtIndex
:
row
];
if
([
identifier
isEqualToString
:
@"Enabled"
])
return
[
NSNumber
numberWithBool
:
emoticon
.
isEnabled
];
if
([
identifier
isEqualToString
:
@"Image"
])
{
NSNumber
*
key
=
[
NSNumber
numberWithUnsignedInteger
:
[
emoticon
hash
]];
NSImage
*
image
=
[
emoticonImageCache
objectForKey
:
key
];
if
(
!
image
)
{
image
=
[
emoticon
image
];
if
(
image
)
[
emoticonImageCache
setObject
:
image
forKey
:
key
];
}
return
image
;
}
if
([
identifier
isEqualToString
:
@"Name"
])
{
if
(
selectedEmoticonPack
.
isEnabled
&&
emoticon
.
isEnabled
)
return
emoticon
.
name
;
return
[
self
_dimString
:
emoticon
.
name
center
:
NO
];
}
// if ([identifier compare:@"String"] == NSOrderedSame) {
NSArray
*
textEquivalents
=
[
emoticon
textEquivalents
];
if
([
textEquivalents
count
])
{
if
(
selectedEmoticonPack
.
isEnabled
&&
emoticon
.
isEnabled
)
return
[
textEquivalents
objectAtIndex
:
0
];
return
[
self
_dimString
:
[
textEquivalents
objectAtIndex
:
0
]
center
:
YES
];
}
return
@""
;
}
-
(
void
)
tableView:
(
NSTableView
*
)
tableView
setObjectValue:
(
id
)
object
forTableColumn:
(
NSTableColumn
*
)
tableColumn
row:
(
NSInteger
)
row
{
if
(
tableView
==
table_emoticons
&&
[
@"Enabled"
isEqualToString
:
[
tableColumn
identifier
]])
[
adium
.
emoticonController
setEmoticon
:
[[
selectedEmoticonPack
emoticons
]
objectAtIndex
:
row
]
inPack
:
selectedEmoticonPack
enabled
:
[
object
integerValue
]];
}
#pragma mark Drag and Drop
-
(
BOOL
)
tableView:
(
NSTableView
*
)
tableView
writeRows:
(
NSArray
*
)
rows
toPasteboard:
(
NSPasteboard
*
)
pboard
{
if
(
tableView
!=
table_emoticonPacks
)
return
NO
;
dragRows
=
rows
;
[
pboard
declareTypes
:
[
NSArray
arrayWithObject
:
EMOTICON_PACK_DRAG_TYPE
]
owner
:
self
];
[
pboard
setString
:
@"dragPack"
forType
:
EMOTICON_PACK_DRAG_TYPE
];
return
YES
;
}
-
(
NSDragOperation
)
tableView:
(
NSTableView
*
)
tableView
validateDrop:
(
id
<
NSDraggingInfo
>
)
info
proposedRow:
(
NSInteger
)
row
proposedDropOperation:
(
NSTableViewDropOperation
)
op
;
{
if
(
tableView
==
table_emoticonPacks
&&
op
==
NSTableViewDropAbove
&&
row
!=
-1
)
return
NSDragOperationMove
;
return
NSDragOperationNone
;
}
-
(
BOOL
)
tableView
:
(
NSTableView
*
)
tableView
acceptDrop
:
(
id
<
NSDraggingInfo
>
)
info
row
:
(
NSInteger
)
row
dropOperation
:
(
NSTableViewDropOperation
)
op
;
{
if
(
tableView
!=
table_emoticonPacks
)
return
NO
;
NSString
*
availableType
=
[[
info
draggingPasteboard
]
availableTypeFromArray
:
[
NSArray
arrayWithObject
:
EMOTICON_PACK_DRAG_TYPE
]];
if
(
!
[
availableType
isEqualToString
:
EMOTICON_PACK_DRAG_TYPE
])
return
NO
;
//Move
NSMutableArray
*
movedPacks
=
[
NSMutableArray
array
];
//Keep track of the packs we've moved
for
(
NSNumber
*
dragRow
in
dragRows
)
{
[
movedPacks
addObject
:
[[
emoticonPackPreviewControllers
objectAtIndex
:
[
dragRow
integerValue
]]
emoticonPack
]];
}
[
adium
.
emoticonController
moveEmoticonPacks
:
movedPacks
toIndex
:
row
];
[
self
configurePreviewControllers
];
//Select the moved packs
[
tableView
deselectAll
:
nil
];
for
(
AIEmoticonPackPreviewController
*
previewController
in
emoticonPackPreviewControllers
)
{
//If the moved packs contains this preview controller's pack, select it, wherever it may be
AIEmoticonPack
*
emoticonPack
=
[
previewController
emoticonPack
];
if
([
movedPacks
containsObjectIdenticalTo
:
emoticonPack
])
{
[
tableView
selectRowIndexes
:
[
NSIndexSet
indexSetWithIndex
:
[
emoticonPackPreviewControllers
indexOfObject
:
previewController
]]
byExtendingSelection
:
NO
];
}
}
return
YES
;
}
/*
- (void)tableViewSelectionIsChanging:(NSNotification *)notification
{
if ([notification object] == table_emoticonPacks) {
[self _configureEmoticonListForSelection];
} else {
//I don't want the emoticon table to display its selection.
//Returning NO from 'shouldSelectRow' would work, but if we do that
//the checkbox cells stop working. The best solution I've come up with
//so far is to just force a deselect here :( .
[table_emoticons deselectAll:nil];
}
}
*/
#pragma mark Deletion
-
(
void
)
tableViewDeleteSelectedRows
:
(
NSTableView
*
)
tableView
{
//Prevent deleting included packs
NSRange
range
=
[
selectedEmoticonPack
.
path
rangeOfString
:
[[[
NSBundle
mainBundle
]
resourcePath
]
stringByAppendingPathComponent
:
@"Emoticons"
]];
if
(
range
.
length
>
0
)
NSBeep
();
else
[
self
moveSelectedPacksToTrash
];
}
-
(
void
)
moveSelectedPacksToTrash
{
NSString
*
name
=
[[
selectedEmoticonPack
.
name
copy
]
autorelease
];
NSBeginAlertSheet
(
AILocalizedString
(
@"Delete Emoticon Pack"
,
nil
),
AILocalizedString
(
@"Delete"
,
nil
),
AILocalizedString
(
@"Cancel"
,
nil
),
@""
,
[
self
window
],
self
,
@selector
(
trashConfirmSheetDidEnd
:
returnCode
:
contextInfo
:
),
nil
,
nil
,
AILocalizedString
(
@"Are you sure you want to delete the %@ Emoticon Pack? It will be moved to the Trash."
,
nil
),
name
);
}
-
(
void
)
trashConfirmSheetDidEnd
:
(
NSWindow
*
)
sheet
returnCode
:
(
NSInteger
)
returnCode
contextInfo
:
(
void
*
)
contextInfo
{
if
(
returnCode
!=
NSOKButton
)
return
;
for
(
AIEmoticonPackPreviewController
*
previewController
in
[
table_emoticonPacks
selectedItemsFromArray
:
emoticonPackPreviewControllers
])
{
[[
NSFileManager
defaultManager
]
trashFileAtPath
:
previewController
.
emoticonPack
.
path
];
}
[
table_emoticonPacks
deselectAll
:
nil
];
//Note the changed packs
[
adium
.
emoticonController
xtrasChanged
:
nil
];
}
#pragma mark Selection changes
-
(
void
)
tableViewSelectionDidChange
:
(
NSNotification
*
)
notification
{
if
([
notification
object
]
==
table_emoticonPacks
)
{
[
self
_configureEmoticonListForSelection
];
}
else
{
//I don't want the emoticon table to display its selection.
//Returning NO from 'shouldSelectRow' would work, but if we do that
//the checkbox cells stop working. The best solution I've come up with
//so far is to just force a deselect here :( .
[
table_emoticons
deselectAll
:
nil
];
}
}
-
(
void
)
toggledPackController
:
(
id
)
packController
{
[
table_emoticonPacks
selectRowIndexes
:
[
NSIndexSet
indexSetWithIndex
:
[
emoticonPackPreviewControllers
indexOfObject
:
packController
]]
byExtendingSelection
:
NO
];
}
-
(
void
)
emoticonXtrasDidChange
{
if
(
viewIsOpen
)
[
self
configurePreviewControllers
];
}
@end