Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber
No files matched your search
@@ -76,6 +76,7 @@
|
||||
@import "CPTabView.j"
|
||||
@import "CPTableColumn.j"
|
||||
@import "CPTableView.j"
|
||||
@import "CPText.j"
|
||||
@import "CPTextField.j"
|
||||
@import "CPToolbar.j"
|
||||
@import "CPToolbarItem.j"
|
||||
|
||||
@@ -252,6 +252,9 @@ var CPAlertWarningImage,
|
||||
Buttons will be added starting from the right hand side of the \c CPAlert panel.
|
||||
The first button will have the index 0, the second button 1 and so on.
|
||||
|
||||
The first button will automatically be given a key equivalent of Return,
|
||||
and any button titled "Cancel" will be given a key equivalent of Escape.
|
||||
|
||||
You really shouldn't need more than 3 buttons.
|
||||
*/
|
||||
- (void)addButtonWithTitle:(CPString)title
|
||||
@@ -271,6 +274,8 @@ var CPAlertWarningImage,
|
||||
|
||||
if (_buttonCount == 0)
|
||||
[_alertPanel setDefaultButton:button];
|
||||
else if ([title lowercaseString] === "cancel")
|
||||
[button setKeyEquivalent:CPEscapeFunctionKey];
|
||||
|
||||
_buttonCount++;
|
||||
[_buttons addObject:button];
|
||||
|
||||
@@ -325,7 +325,9 @@ CPRunContinuesResponse = -1002;
|
||||
applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
|
||||
copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
|
||||
|
||||
var aboutPanelController = [[CPWindowController alloc] initWithWindowCibName:@"AboutPanel"],
|
||||
var aboutPanelPath = [[CPBundle bundleForClass:[CPWindowController class]] pathForResource:@"AboutPanel.cib"],
|
||||
aboutPanelController = [CPWindowController alloc],
|
||||
aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController],
|
||||
aboutPanel = [aboutPanelController window],
|
||||
contentView = [aboutPanel contentView],
|
||||
imageView = [contentView viewWithTag:1],
|
||||
@@ -615,7 +617,11 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (CPArray)orderedWindows
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
return CPWindowObjectList();
|
||||
#else
|
||||
return [];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)hide:(id)aSender
|
||||
|
||||
@@ -0,0 +1,538 @@
|
||||
|
||||
/*
|
||||
* CPArrayController.j
|
||||
* AppKit
|
||||
*
|
||||
* Adapted from Cocotron, by Johannes Fortmann
|
||||
*
|
||||
* Created by Ross Boucher.
|
||||
* Copyright 2009, 280 North, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <AppKit/CPObjectController.j>
|
||||
@import <AppKit/CPKeyValueBinding.j>
|
||||
|
||||
|
||||
@implementation CPArrayController : CPObjectController
|
||||
{
|
||||
BOOL _avoidsEmptySelection;
|
||||
BOOL _clearsFilterPredicateOnInsertion;
|
||||
BOOL _filterRestrictsInsertion;
|
||||
BOOL _preservesSelection;
|
||||
BOOL _selectsInsertedObjects;
|
||||
BOOL _alwaysUsesMultipleValuesMarker;
|
||||
|
||||
id _selectionIndexes;
|
||||
id _sortDescriptors;
|
||||
id _filterPredicate;
|
||||
id _arrangedObjects;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self !== [CPArrayController class])
|
||||
return;
|
||||
|
||||
[self exposeBinding:@"contentArray"];
|
||||
[self exposeBinding:@"contentSet"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingContentArray
|
||||
{
|
||||
return [CPSet setWithObjects:"content"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
|
||||
{
|
||||
return [CPSet setWithObjects:"content", "contentArray", "contentSet", "filterPredicate", "sortDescriptors"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingSelection
|
||||
{
|
||||
return [CPSet setWithObjects:"content", "contentArray", "contentSet", "selectionIndexes"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingSelectionIndex
|
||||
{
|
||||
return [CPSet setWithObjects:"content", "contentArray", "contentSet", "selectionIndexes", "selection"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingSelectedObjects
|
||||
{
|
||||
return [CPSet setWithObjects:"content", "contentArray", "contentSet", "selectionIndexes", "selection"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingCanRemove
|
||||
{
|
||||
return [CPSet setWithObjects:"selectionIndexes"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingCanSelectNext
|
||||
{
|
||||
return [CPSet setWithObjects:"selectionIndexes"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingCanSelectPrevious
|
||||
{
|
||||
return [CPSet setWithObjects:"selectionIndexes"];
|
||||
}
|
||||
|
||||
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
|
||||
{
|
||||
if (![super automaticallyNotifiesObserversForKey:aKey])
|
||||
return NO;
|
||||
if (aKey === @"selectionIndexes")
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)prepareContent
|
||||
{
|
||||
[self _setContentArray:[[self newObject]]];
|
||||
}
|
||||
|
||||
- (BOOL)preservesSelection
|
||||
{
|
||||
return _preservesSelection;
|
||||
}
|
||||
|
||||
- (void)setPreservesSelection:(BOOL)value
|
||||
{
|
||||
_preservesSelection = value;
|
||||
}
|
||||
|
||||
- (BOOL)selectsInsertedObjects
|
||||
{
|
||||
return _selectsInsertedObjects;
|
||||
}
|
||||
|
||||
- (void)setSelectsInsertedObjects:(BOOL)value
|
||||
{
|
||||
_selectsInsertedObjects = value;
|
||||
}
|
||||
|
||||
- (BOOL)avoidsEmptySelection
|
||||
{
|
||||
return _avoidsEmptySelection;
|
||||
}
|
||||
|
||||
- (void)setAvoidsEmptySelection:(BOOL)value
|
||||
{
|
||||
_avoidsEmptySelection = value;
|
||||
}
|
||||
|
||||
- (void)setContent:(id)value
|
||||
{
|
||||
if(![value isKindOfClass:[CPArray class]])
|
||||
value = [value];
|
||||
|
||||
var oldSelection = nil,
|
||||
oldSelectionIndexes = [[self selectionIndexes] copy];
|
||||
|
||||
if ([self preservesSelection])
|
||||
oldSelection = [self selectedObjects];
|
||||
|
||||
// Avoid out of bounds selections.
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
//FIXME: copy?
|
||||
[super setContent:value];
|
||||
|
||||
if(_clearsFilterPredicateOnInsertion)
|
||||
[self setFilterPredicate:nil];
|
||||
|
||||
[self rearrangeObjects];
|
||||
|
||||
if (oldSelection)
|
||||
[self setSelectedObjects:oldSelection];
|
||||
else
|
||||
[self setSelectionIndexes:oldSelectionIndexes];
|
||||
}
|
||||
|
||||
- (void)_setContentArray:(id)anArray
|
||||
{
|
||||
[self setContent:anArray];
|
||||
}
|
||||
|
||||
- (void)_setContentSet:(id)aSet
|
||||
{
|
||||
[self setContent:aSet];
|
||||
}
|
||||
|
||||
- (id)contentArray
|
||||
{
|
||||
return [self content];
|
||||
}
|
||||
|
||||
- (id)contentSet
|
||||
{
|
||||
return [self content];
|
||||
}
|
||||
|
||||
- (CPArray)arrangeObjects:(CPArray)objects
|
||||
{
|
||||
var sortedObjects = objects;
|
||||
|
||||
if ([self filterPredicate])
|
||||
sortedObjects = [sortedObjects filteredArrayUsingPredicate:[self filterPredicate]];
|
||||
if ([self sortDescriptors])
|
||||
sortedObjects = [sortedObjects sortedArrayUsingDescriptors:[self sortDescriptors]];
|
||||
|
||||
return sortedObjects;
|
||||
}
|
||||
|
||||
- (void)rearrangeObjects
|
||||
{
|
||||
// Rearranging reapplies the selection criteria and may cause objects to disappear,
|
||||
// so take care of the selection.
|
||||
//
|
||||
// Sometimes rearrangeObjects is called by setContent which may cause two rounds of
|
||||
// selection preservation. This is okay because setContent temporarily clears the
|
||||
// selection and so this code below ends up preserving nothing in that case.
|
||||
var oldSelection = nil,
|
||||
oldSelectionIndexes = [[self selectionIndexes] copy];
|
||||
|
||||
if ([self preservesSelection])
|
||||
oldSelection = [self selectedObjects];
|
||||
|
||||
// Avoid out of bounds selections.
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
|
||||
[self _setArrangedObjects:[self arrangeObjects:[self contentArray]]];
|
||||
|
||||
if (oldSelection)
|
||||
[self setSelectedObjects:oldSelection];
|
||||
else
|
||||
[self setSelectionIndexes:oldSelectionIndexes];
|
||||
}
|
||||
|
||||
- (void)_setArrangedObjects:(id)value
|
||||
{
|
||||
if (_arrangedObjects === value)
|
||||
return;
|
||||
|
||||
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
|
||||
}
|
||||
|
||||
- (id)arrangedObjects
|
||||
{
|
||||
return _arrangedObjects;
|
||||
}
|
||||
|
||||
|
||||
- (CPArray)sortDescriptors
|
||||
{
|
||||
return _sortDescriptors;
|
||||
}
|
||||
|
||||
- (void)setSortDescriptors:(CPArray)value
|
||||
{
|
||||
if (_sortDescriptors === value)
|
||||
return;
|
||||
|
||||
_sortDescriptors = [value copy];
|
||||
[self rearrangeObjects];
|
||||
}
|
||||
|
||||
- (CPPredicate)filterPredicate
|
||||
{
|
||||
return _filterPredicate;
|
||||
}
|
||||
|
||||
- (void)setFilterPredicate:(CPPredicate)value
|
||||
{
|
||||
if (_filterPredicate === value)
|
||||
return;
|
||||
|
||||
_filterPredicate = value;
|
||||
[self rearrangeObjects];
|
||||
}
|
||||
|
||||
- (BOOL)alwaysUsesMultipleValuesMarker
|
||||
{
|
||||
return _alwaysUsesMultipleValuesMarker;
|
||||
}
|
||||
|
||||
//Selection
|
||||
|
||||
- (unsigned)selectionIndex
|
||||
{
|
||||
return [_selectionIndexes firstIndex];
|
||||
}
|
||||
|
||||
- (BOOL)setSelectionIndex:(unsigned)index
|
||||
{
|
||||
return [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
}
|
||||
|
||||
- (CPIndexSet)selectionIndexes
|
||||
{
|
||||
return _selectionIndexes;
|
||||
}
|
||||
|
||||
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
if ([_selectionIndexes isEqualToIndexSet:indexes])
|
||||
return NO;
|
||||
|
||||
if (![indexes count])
|
||||
{
|
||||
if(_avoidsEmptySelection && [[self arrangedObjects] count])
|
||||
indexes = [CPIndexSet indexSetWithIndex:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectsCount = [[self arrangedObjects] count];
|
||||
// Remove out of bounds indexes.
|
||||
[indexes removeIndexesInRange:CPMakeRange(objectsCount, [indexes lastIndex]+1)];
|
||||
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
|
||||
if(![indexes count] && _avoidsEmptySelection && objectsCount)
|
||||
indexes = [CPIndexSet indexSetWithIndex:objectsCount-1];
|
||||
}
|
||||
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
[self _selectionWillChange];
|
||||
|
||||
_selectionIndexes = [indexes copy];
|
||||
|
||||
[self _selectionDidChange];
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
|
||||
// Push back the new selection to the model for selectionIndexes if we have one.
|
||||
// There won't be an infinite loop because of the equality check above.
|
||||
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPArray)selectedObjects
|
||||
{
|
||||
var objects = [[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]];
|
||||
|
||||
return objects || [_CPObservableArray array];
|
||||
}
|
||||
|
||||
- (BOOL)setSelectedObjects:(CPArray)objects
|
||||
{
|
||||
var set = [CPIndexSet indexSet],
|
||||
count = [objects count],
|
||||
arrangedObjects = [self arrangedObjects];
|
||||
|
||||
for (var i=0; i<count; i++)
|
||||
{
|
||||
var index = [arrangedObjects indexOfObject:[objects objectAtIndex:i]];
|
||||
|
||||
if (index !== CPNotFound)
|
||||
[set addIndex:index];
|
||||
}
|
||||
|
||||
[self setSelectionIndexes:set];
|
||||
return YES;
|
||||
}
|
||||
|
||||
//Moving selection
|
||||
|
||||
-(BOOL)canSelectPrevious
|
||||
{
|
||||
return [[self selectionIndexes] firstIndex] > 0
|
||||
}
|
||||
|
||||
-(BOOL)canSelectNext
|
||||
{
|
||||
return [[self selectionIndexes] firstIndex] < [[self arrangedObjects] count] -1;
|
||||
}
|
||||
|
||||
-(void)selectNext:(id)sender
|
||||
{
|
||||
var index = [[self selectionIndexes] firstIndex] + 1 || 0;
|
||||
|
||||
if (index < [[self arrangedObjects] count])
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
}
|
||||
|
||||
-(void)selectPrevious:(id)sender
|
||||
{
|
||||
var index = [[self selectionIndexes] firstIndex] - 1 || [[self arrangedObjects] count] - 1;
|
||||
|
||||
if (index >= 0)
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
}
|
||||
|
||||
//Add/Remove
|
||||
|
||||
- (void)addObject:(id)object
|
||||
{
|
||||
if (![self canAdd])
|
||||
return;
|
||||
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[_contentObject addObject:object];
|
||||
[self didChangeValueForKey:@"content"];
|
||||
|
||||
if (_clearsFilterPredicateOnInsertion)
|
||||
[self setFilterPredicate:nil];
|
||||
|
||||
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
|
||||
{
|
||||
var pos = [_arrangedObjects insertObject:object inArraySortedByDescriptors:_sortDescriptors];
|
||||
|
||||
if (_selectsInsertedObjects)
|
||||
{
|
||||
[self setSelectionIndex:pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
}
|
||||
}
|
||||
else
|
||||
[self rearrangeObjects];
|
||||
}
|
||||
|
||||
- (void)removeObject:(id)object
|
||||
{
|
||||
if (![self canRemove])
|
||||
return;
|
||||
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[_contentObject removeObject:object];
|
||||
[self didChangeValueForKey:@"content"];
|
||||
|
||||
if ([_filterPredicate evaluateWithObject:object])
|
||||
{
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
var pos = [_arrangedObjects indexOfObject:object];
|
||||
|
||||
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)add:(id)sender
|
||||
{
|
||||
if(![self canAdd])
|
||||
return;
|
||||
|
||||
[self insert:sender];
|
||||
}
|
||||
|
||||
- (void)insert:(id)sender
|
||||
{
|
||||
if(![self canInsert])
|
||||
return;
|
||||
|
||||
var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject];
|
||||
|
||||
[self addObject:newObject];
|
||||
}
|
||||
|
||||
- (void)remove:(id)sender
|
||||
{
|
||||
[self removeObjects:[[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]]];
|
||||
}
|
||||
|
||||
- (void)removeObjectsAtArrangedObjectIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self _removeObjects:[[self arrangedObjects] objectsAtIndexes:indexes]];
|
||||
}
|
||||
|
||||
|
||||
- (void)addObjects:(CPArray)objects
|
||||
{
|
||||
if(![self canAdd])
|
||||
return;
|
||||
|
||||
var contentArray = [self contentArray],
|
||||
count = [objects count];
|
||||
|
||||
for (var i=0; i<count; i++)
|
||||
[contentArray addObject:[objects objectAtIndex:i]];
|
||||
|
||||
[self setContent:contentArray];
|
||||
}
|
||||
|
||||
- (void)removeObjects:(CPArray)objects
|
||||
{
|
||||
if(![self canRemove])
|
||||
return;
|
||||
|
||||
[self _removeObjects:objects];
|
||||
}
|
||||
|
||||
- (void)_removeObjects:(CPArray)objects
|
||||
{
|
||||
var contentArray = [self contentArray],
|
||||
count = [objects count];
|
||||
|
||||
for (var i=0; i<count; i++)
|
||||
[contentArray removeObject:[objects objectAtIndex:i]];
|
||||
|
||||
[self setContent:contentArray];
|
||||
}
|
||||
|
||||
- (BOOL)canInsert
|
||||
{
|
||||
return [self isEditable];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPArrayController (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_avoidsEmptySelection = [coder decodeBoolForKey:@"CPArrayControllerAvoidsEmptySelection"];
|
||||
_clearsFilterPredicateOnInsertion = [coder decodeBoolForKey:@"CPClearsFilterPredicateOnInsertion"];
|
||||
_filterRestrictsInsertion = [coder decodeBoolForKey:@"CPArrayControllerFilterRestrictsInsertion"];
|
||||
_preservesSelection = [coder decodeBoolForKey:@"CPArrayControllerPreservesSelection"];
|
||||
_selectsInsertedObjects = [coder decodeBoolForKey:@"CPArrayControllerSelectsInsertedObjects"];
|
||||
_alwaysUsesMultipleValuesMarker = [coder decodeBoolForKey:@"CPArrayControllerAlwaysUsesMultipleValuesMarker"];
|
||||
|
||||
if ([self automaticallyPreparesContent])
|
||||
[self prepareContent];
|
||||
else
|
||||
[self _setContentArray:[]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[self _selectionWillChange];
|
||||
[self _selectionDidChange];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
|
||||
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelected];
|
||||
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelectedDataView];
|
||||
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
|
||||
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
|
||||
@@ -860,7 +860,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
|
||||
[_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
|
||||
return [_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
|
||||
else
|
||||
return CPDragOperationNone;
|
||||
}
|
||||
@@ -923,7 +923,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
||||
positioned:CPWindowAbove
|
||||
relativeToEphemeralSubviewNamed:nil];
|
||||
|
||||
var isHighlighted = [self themeState] & CPThemeStateSelected;
|
||||
var isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
|
||||
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
|
||||
[imageView setImageScaling:CPScaleNone];
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ CPChangeBackgroundCellMask = CPBackgroundButtonMask;
|
||||
|
||||
CPButtonStateMixed = CPThemeState("mixed");
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPButton
|
||||
|
||||
@@ -85,10 +85,10 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
@implementation CPButton : CPControl
|
||||
{
|
||||
BOOL _allowsMixedState;
|
||||
|
||||
|
||||
CPString _title;
|
||||
CPString _alternateTitle;
|
||||
|
||||
|
||||
CPImage _image;
|
||||
CPImage _alternateImage;
|
||||
|
||||
@@ -99,6 +99,9 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
// NS-style Display Properties
|
||||
CPBezelStyle _bezelStyle;
|
||||
CPControlSize _controlSize;
|
||||
|
||||
CPString _keyEquivalent;
|
||||
unsigned _keyEquivalentModifierMask;
|
||||
}
|
||||
|
||||
+ (id)buttonWithTitle:(CPString)aTitle
|
||||
@@ -131,7 +134,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
// Should we instead override the defaults?
|
||||
@@ -139,13 +142,16 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
|
||||
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
||||
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
|
||||
|
||||
|
||||
_controlSize = CPRegularControlSize;
|
||||
|
||||
|
||||
_keyEquivalent = "";
|
||||
_keyEquivalentModifierMask = 0;
|
||||
|
||||
// [self setBezelStyle:CPRoundRectBezelStyle];
|
||||
[self setBordered:YES];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -248,9 +254,9 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
{
|
||||
if (_title === aTitle)
|
||||
return;
|
||||
|
||||
|
||||
_title = aTitle;
|
||||
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
@@ -264,7 +270,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
{
|
||||
if (_alternateTitle === aTitle)
|
||||
return;
|
||||
|
||||
|
||||
_alternateTitle = aTitle;
|
||||
|
||||
[self setNeedsLayout];
|
||||
@@ -280,9 +286,9 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
{
|
||||
if (_image === anImage)
|
||||
return;
|
||||
|
||||
|
||||
_image = anImage;
|
||||
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
@@ -300,9 +306,9 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
{
|
||||
if (_alternateImage === anImage)
|
||||
return;
|
||||
|
||||
|
||||
_alternateImage = anImage;
|
||||
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
@@ -373,13 +379,13 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
[self setShowsStateBy:CPContentsCellMask];
|
||||
break;
|
||||
|
||||
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
|
||||
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
|
||||
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
|
||||
|
||||
case CPRadioButton: [CPException raise:CPInvalidArgumentException
|
||||
case CPRadioButton: [CPException raise:CPInvalidArgumentException
|
||||
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
|
||||
|
||||
default: [CPException raise:CPInvalidArgumentException
|
||||
default: [CPException raise:CPInvalidArgumentException
|
||||
reason:"Unknown button type."];
|
||||
}
|
||||
|
||||
@@ -395,7 +401,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
|
||||
_imageDimsWhenDisabled = imageShouldDimWhenDisabled;
|
||||
|
||||
if (_imageDimsWhenDisabled)
|
||||
if ([self hasThemeState:CPThemeStateDisabled])
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
[self setNeedsLayout];
|
||||
@@ -410,7 +416,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
||||
{
|
||||
[self highlight:YES];
|
||||
|
||||
|
||||
return [super startTrackingAt:aPoint];
|
||||
}
|
||||
|
||||
@@ -435,7 +441,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
bounds.origin.y += contentInset.top;
|
||||
bounds.size.width -= contentInset.left + contentInset.right;
|
||||
bounds.size.height -= contentInset.top + contentInset.bottom;
|
||||
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@@ -483,10 +489,10 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
{
|
||||
if (aName === "bezel-view")
|
||||
return [self bezelRectForBounds:[self bounds]];
|
||||
|
||||
|
||||
else if (aName === "content-view")
|
||||
return [self contentRectForBounds:[self bounds]];
|
||||
|
||||
|
||||
return [super rectForEphemeralSubviewNamed:aName];
|
||||
}
|
||||
|
||||
@@ -497,7 +503,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
|
||||
[view setHitTests:NO];
|
||||
|
||||
|
||||
return view;
|
||||
}
|
||||
else
|
||||
@@ -555,6 +561,54 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
return [self hasThemeState:CPThemeStateBordered];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the keyboard shortcut for this button. For special keys see
|
||||
CPEvent.j CP...FunctionKey and CPText.j CP...Character.
|
||||
|
||||
@param aString the keyboard shortcut as a string
|
||||
*/
|
||||
- (void)setKeyEquivalent:(CPString)aString
|
||||
{
|
||||
_keyEquivalent = aString || @"";
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the keyboard shortcut for this button.
|
||||
*/
|
||||
- (CPString)keyEquivalent
|
||||
{
|
||||
return _keyEquivalent;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the mask used with this button's key equivalent.
|
||||
*/
|
||||
- (void)setKeyEquivalentModifierMask:(unsigned)aMask
|
||||
{
|
||||
_keyEquivalentModifierMask = aMask;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the mask to be used with this button's key equivalent.
|
||||
*/
|
||||
- (unsigned)keyEquivalentModifierMask
|
||||
{
|
||||
return _keyEquivalentModifierMask;
|
||||
}
|
||||
|
||||
/*!
|
||||
Checks the button's key equivalent against that in the event, and if they
|
||||
match simulates a button click.
|
||||
*/
|
||||
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
|
||||
{
|
||||
if (![anEvent _triggersKeyEquivalent:[self keyEquivalent] withModifierMask:[self keyEquivalentModifierMask]])
|
||||
return NO;
|
||||
|
||||
[self performClick:nil];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPButton (NS)
|
||||
@@ -570,11 +624,14 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
@end
|
||||
|
||||
|
||||
var CPButtonImageKey = @"CPButtonImageKey",
|
||||
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
|
||||
CPButtonTitleKey = @"CPButtonTitleKey",
|
||||
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
|
||||
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey";
|
||||
var CPButtonImageKey = @"CPButtonImageKey",
|
||||
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
|
||||
CPButtonTitleKey = @"CPButtonTitleKey",
|
||||
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
|
||||
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey",
|
||||
CPButtonImageDimsWhenDisabledKey = @"CPButtonImageDimsWhenDisabledKey",
|
||||
CPButtonKeyEquivalentKey = @"CPButtonKeyEquivalentKey",
|
||||
CPButtonKeyEquivalentMaskKey = @"CPButtonKeyEquivalentMaskKey";
|
||||
|
||||
@implementation CPButton (CPCoding)
|
||||
|
||||
@@ -585,21 +642,28 @@ var CPButtonImageKey = @"CPButtonImageKey",
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_controlSize = CPRegularControlSize;
|
||||
|
||||
[self setImage:[aCoder decodeObjectForKey:CPButtonImageKey]];
|
||||
[self setAlternateImage:[aCoder decodeObjectForKey:CPButtonAlternateImageKey]];
|
||||
|
||||
|
||||
[self setTitle:[aCoder decodeObjectForKey:CPButtonTitleKey]];
|
||||
[self setAlternateTitle:[aCoder decodeObjectForKey:CPButtonAlternateTitleKey]];
|
||||
|
||||
|
||||
[self setImageDimsWhenDisabled:[aCoder decodeObjectForKey:CPButtonImageDimsWhenDisabledKey]];
|
||||
|
||||
if ([aCoder containsValueForKey:CPButtonKeyEquivalentKey])
|
||||
[self setKeyEquivalent:CFData.decodeBase64ToUtf16String([aCoder decodeObjectForKey:CPButtonKeyEquivalentKey])];
|
||||
|
||||
[self setKeyEquivalentModifierMask:[aCoder decodeObjectForKey:CPButtonKeyEquivalentMaskKey]];
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -616,6 +680,13 @@ var CPButtonImageKey = @"CPButtonImageKey",
|
||||
|
||||
[aCoder encodeObject:_title forKey:CPButtonTitleKey];
|
||||
[aCoder encodeObject:_alternateTitle forKey:CPButtonAlternateTitleKey];
|
||||
|
||||
[aCoder encodeObject:[self imageDimsWhenDisabled] forKey:CPButtonImageDimsWhenDisabledKey];
|
||||
|
||||
if (_keyEquivalent)
|
||||
[aCoder encodeObject:CFData.encodeBase64Utf16String(_keyEquivalent) forKey:CPButtonKeyEquivalentKey];
|
||||
|
||||
[aCoder encodeInt:_keyEquivalentModifierMask forKey:CPButtonKeyEquivalentMaskKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
[_items[index] setSelected:YES];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
|
||||
[_delegate collectionViewDidChangeSelection:self]
|
||||
[_delegate collectionViewDidChangeSelection:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -591,8 +591,21 @@
|
||||
index = row * _numberOfColumns + column;
|
||||
|
||||
if (index >= 0 && index < _items.length)
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
{
|
||||
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPCommandKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
|
||||
{
|
||||
var indexes = [_selectionIndexes copy];
|
||||
|
||||
if ([indexes containsIndex:index])
|
||||
[indexes removeIndex:index];
|
||||
else
|
||||
[indexes addIndex:index];
|
||||
}
|
||||
else
|
||||
indexes = [CPIndexSet indexSetWithIndex:index];
|
||||
|
||||
[self setSelectionIndexes:indexes];
|
||||
}
|
||||
else if (_allowsEmptySelection)
|
||||
[self setSelectionIndexes:[CPIndexSet indexSet]];
|
||||
}
|
||||
@@ -623,8 +636,6 @@
|
||||
|
||||
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
|
||||
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
|
||||
if (!_itemForDragging)
|
||||
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
|
||||
else
|
||||
@@ -726,6 +737,25 @@
|
||||
@end
|
||||
|
||||
@implementation CPCollectionView (KeyboardInteraction)
|
||||
- (CPIndexSet)_selectionForEvent:(CPEvent)anEvent withNewIndex:(int)anIndex direction:(int)aDirection
|
||||
{
|
||||
if (_allowsMultipleSelection && [anEvent modifierFlags] & CPShiftKeyMask)
|
||||
{
|
||||
var indexes = [_selectionIndexes copy],
|
||||
bottomAnchor = [indexes firstIndex],
|
||||
topAnchor = [indexes lastIndex];
|
||||
|
||||
// if the direction is backward (-1) check with the bottom anchor
|
||||
if (aDirection === -1)
|
||||
[indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
|
||||
else
|
||||
[indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
|
||||
}
|
||||
else
|
||||
indexes = [CPIndexSet indexSetWithIndex:anIndex];
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
- (void)_scrollToSelection
|
||||
{
|
||||
@@ -743,23 +773,23 @@
|
||||
|
||||
index = MAX(index - 1, 0);
|
||||
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
[self setSelectionIndexes:[self _selectionForEvent:[CPApp currentEvent] withNewIndex:index direction:-1]];
|
||||
[self _scrollToSelection];
|
||||
}
|
||||
|
||||
- (void)moveRight:(id)sender
|
||||
{
|
||||
var index = MIN([[self selectionIndexes] firstIndex] + 1, [[self items] count]-1);
|
||||
var index = MIN([[self selectionIndexes] lastIndex] + 1, [[self items] count]-1);
|
||||
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
[self setSelectionIndexes:[self _selectionForEvent:[CPApp currentEvent] withNewIndex:index direction:1]];
|
||||
[self _scrollToSelection];
|
||||
}
|
||||
|
||||
- (void)moveDown:(id)sender
|
||||
{
|
||||
var index = MIN([[self selectionIndexes] firstIndex] + [self numberOfColumns], [[self items] count]-1);
|
||||
var index = MIN([[self selectionIndexes] lastIndex] + [self numberOfColumns], [[self items] count]-1);
|
||||
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
[self setSelectionIndexes:[self _selectionForEvent:[CPApp currentEvent] withNewIndex:index direction:1]];
|
||||
[self _scrollToSelection];
|
||||
}
|
||||
|
||||
@@ -771,7 +801,7 @@
|
||||
|
||||
index = MAX(0, index - [self numberOfColumns]);
|
||||
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
[self setSelectionIndexes:[self _selectionForEvent:[CPApp currentEvent] withNewIndex:index direction:-1]];
|
||||
[self _scrollToSelection];
|
||||
}
|
||||
|
||||
|
||||
@@ -422,7 +422,7 @@ var cachedBlackColor,
|
||||
parseInt(parts[1], 10) / 255.0,
|
||||
parseInt(parts[2], 10) / 255.0,
|
||||
parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0
|
||||
]
|
||||
];
|
||||
|
||||
_cssString = aString;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
@import "CPFont.j"
|
||||
@import "CPShadow.j"
|
||||
@import "CPView.j"
|
||||
@import "CPKeyValueBinding.j"
|
||||
|
||||
#include "CoreGraphics/CGGeometry.h"
|
||||
#include "Platform/Platform.h"
|
||||
@@ -75,7 +76,7 @@ CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotific
|
||||
|
||||
var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPControl
|
||||
|
||||
@@ -84,7 +85,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
@implementation CPControl : CPView
|
||||
{
|
||||
id _value;
|
||||
|
||||
|
||||
// Target-Action Support
|
||||
id _target;
|
||||
SEL _action;
|
||||
@@ -126,16 +127,46 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
@"max-size"]];
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self === [CPControl class])
|
||||
{
|
||||
[self exposeBinding:@"value"];
|
||||
[self exposeBinding:@"objectValue"];
|
||||
[self exposeBinding:@"stringValue"];
|
||||
[self exposeBinding:@"integerValue"];
|
||||
[self exposeBinding:@"intValue"];
|
||||
[self exposeBinding:@"doubleValue"];
|
||||
[self exposeBinding:@"floatValue"];
|
||||
|
||||
[self exposeBinding:@"enabled"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
}
|
||||
|
||||
- (void)_replacementKeyPathForBinding:(CPString)aBinding
|
||||
{
|
||||
if (aBinding === @"value")
|
||||
return @"objectValue";
|
||||
|
||||
return [super _replacementKeyPathForBinding:aBinding];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_sendActionOn = CPLeftMouseUpMask;
|
||||
_trackingMouseDownFlags = 0;
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -180,15 +211,16 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
*/
|
||||
- (void)sendAction:(SEL)anAction to:(id)anObject
|
||||
{
|
||||
[self _reverseSetBinding];
|
||||
[CPApp sendAction:anAction to:anObject from:self];
|
||||
}
|
||||
|
||||
- (int)sendActionOn:(int)mask
|
||||
{
|
||||
var previousMask = _sendActionOn;
|
||||
|
||||
|
||||
_sendActionOn = mask;
|
||||
|
||||
|
||||
return previousMask;
|
||||
}
|
||||
|
||||
@@ -201,7 +233,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
{
|
||||
if (_toolTip == aToolTip)
|
||||
return;
|
||||
|
||||
|
||||
_toolTip = aToolTip;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
@@ -236,7 +268,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
// Some subclasses should redefine this with CPLeftMouseDraggedMask
|
||||
if (flag)
|
||||
_sendActionOn |= CPPeriodicMask;
|
||||
else
|
||||
else
|
||||
_sendActionOn &= ~CPPeriodicMask;
|
||||
}
|
||||
|
||||
@@ -254,10 +286,10 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
if (type === CPLeftMouseUp)
|
||||
{
|
||||
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
|
||||
|
||||
|
||||
_trackingMouseDownFlags = 0;
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
if (type === CPLeftMouseDown)
|
||||
@@ -271,20 +303,20 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
{
|
||||
if (!_trackingWasWithinFrame)
|
||||
_continuousTracking = [self startTrackingAt:currentLocation];
|
||||
|
||||
|
||||
else if (_continuousTracking)
|
||||
_continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
|
||||
}
|
||||
else
|
||||
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
|
||||
}
|
||||
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
|
||||
if ((_sendActionOn & (1 << type)) && isWithinFrame)
|
||||
[self sendAction:_action to:_target];
|
||||
|
||||
|
||||
_trackingWasWithinFrame = isWithinFrame;
|
||||
_previousTrackingLocation = currentLocation;
|
||||
}
|
||||
@@ -298,12 +330,15 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)performClick:(id)sender
|
||||
- (void)performClick:(id)sender
|
||||
{
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
[self highlight:YES];
|
||||
[self setState:[self nextState]];
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
|
||||
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
|
||||
}
|
||||
|
||||
@@ -320,7 +355,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
||||
{
|
||||
[self highlight:YES];
|
||||
|
||||
|
||||
return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
|
||||
}
|
||||
|
||||
@@ -338,7 +373,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
{
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
|
||||
[self trackMouse:anEvent];
|
||||
}
|
||||
|
||||
@@ -356,7 +391,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
- (void)setObjectValue:(id)anObject
|
||||
{
|
||||
_value = anObject;
|
||||
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
@@ -430,7 +465,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's int value
|
||||
Returns the receiver's string value
|
||||
*/
|
||||
- (CPString)stringValue
|
||||
{
|
||||
@@ -438,7 +473,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set's the receiver's int value
|
||||
Set's the receiver's string value
|
||||
*/
|
||||
- (void)setStringValue:(CPString)anObject
|
||||
{
|
||||
@@ -485,7 +520,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[self setStringValue:[sender stringValue]];
|
||||
}
|
||||
|
||||
- (void)textDidBeginEditing:(CPNotification)note
|
||||
- (void)textDidBeginEditing:(CPNotification)note
|
||||
{
|
||||
//this looks to prevent false propagation of notifications for other objects
|
||||
if([note object] != self)
|
||||
@@ -494,7 +529,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
||||
}
|
||||
|
||||
- (void)textDidChange:(CPNotification)note
|
||||
- (void)textDidChange:(CPNotification)note
|
||||
{
|
||||
//this looks to prevent false propagation of notifications for other objects
|
||||
if([note object] != self)
|
||||
@@ -503,12 +538,13 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
||||
}
|
||||
|
||||
- (void)textDidEndEditing:(CPNotification)note
|
||||
- (void)textDidEndEditing:(CPNotification)note
|
||||
{
|
||||
//this looks to prevent false propagation of notifications for other objects
|
||||
if([note object] != self)
|
||||
return;
|
||||
|
||||
[self _reverseSetBinding];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
||||
}
|
||||
|
||||
@@ -570,7 +606,7 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling")
|
||||
var CPControlValueKey = "CPControlValueKey",
|
||||
CPControlControlStateKey = @"CPControlControlStateKey",
|
||||
CPControlIsEnabledKey = "CPControlIsEnabledKey",
|
||||
|
||||
|
||||
CPControlTargetKey = "CPControlTargetKey",
|
||||
CPControlActionKey = "CPControlActionKey",
|
||||
CPControlSendActionOnKey = "CPControlSendActionOnKey",
|
||||
@@ -600,7 +636,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
|
||||
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -636,7 +672,7 @@ var _CPControlSizeIdentifiers = [],
|
||||
_CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
|
||||
_CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
|
||||
_CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
|
||||
|
||||
|
||||
function _CPControlIdentifierForControlSize(aControlSize)
|
||||
{
|
||||
return _CPControlSizeIdentifiers[aControlSize];
|
||||
@@ -647,21 +683,21 @@ function _CPControlColorWithPatternImage(sizes, aClassName)
|
||||
var index = 1,
|
||||
count = arguments.length,
|
||||
identifier = "";
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
identifier += arguments[index];
|
||||
|
||||
|
||||
var color = _CPControlCachedColorWithPatternImages[identifier];
|
||||
|
||||
|
||||
if (!color)
|
||||
{
|
||||
var bundle = [CPBundle bundleForClass:[CPControl class]];
|
||||
|
||||
|
||||
color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
|
||||
|
||||
_CPControlCachedColorWithPatternImages[identifier] = color;
|
||||
}
|
||||
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -670,17 +706,17 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
|
||||
var index = 2,
|
||||
count = arguments.length,
|
||||
identifier = "";
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
identifier += arguments[index];
|
||||
|
||||
var color = _CPControlCachedThreePartImagePattern[identifier];
|
||||
|
||||
|
||||
if (!color)
|
||||
{
|
||||
var bundle = [CPBundle bundleForClass:[CPControl class]],
|
||||
path = aClassName + "/" + identifier;
|
||||
|
||||
|
||||
sizes = sizes[identifier];
|
||||
|
||||
color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
|
||||
@@ -688,9 +724,9 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
|
||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
|
||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
|
||||
] isVertical:isVertical]];
|
||||
|
||||
|
||||
_CPControlCachedThreePartImagePattern[identifier] = color;
|
||||
}
|
||||
|
||||
|
||||
return color;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// CPController.j
|
||||
// AppKit
|
||||
//
|
||||
// Created by Ross Boucher 1/15/09
|
||||
// Copyright 280 North
|
||||
//
|
||||
// Adapted from GNUStep
|
||||
// Copyright (C) 2007 Free Software Foundation, Inc
|
||||
// Released under the LGPL.
|
||||
//
|
||||
|
||||
|
||||
var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey";
|
||||
|
||||
@implementation CPController : CPObject
|
||||
{
|
||||
CPArray _editors;
|
||||
CPArray _declaredKeys;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_editors = [];
|
||||
_declaredKeys = [];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if ([_declaredKeys count] > 0)
|
||||
[aCoder encodeObject:_declaredKeys forKey:CPControllerDeclaredKeysKey];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aDecoder
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_editors = [];
|
||||
_declaredKeys = [aDecoder decodeObjectForKey:CPControllerDeclaredKeysKey] || [];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isEditing
|
||||
{
|
||||
return [_editors count] > 0;
|
||||
}
|
||||
|
||||
- (BOOL)commitEditing
|
||||
{
|
||||
var index = 0,
|
||||
count = _editors.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
if (![[_editors objectAtIndex:i] commitEditing])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)discardEditing
|
||||
{
|
||||
[_editors makeObjectsPerformSelector:@selector(discardEditing)];
|
||||
}
|
||||
|
||||
- (void)objectDidBeginEditing:(id)anEditor
|
||||
{
|
||||
[_editors addObject:anEditor];
|
||||
}
|
||||
|
||||
- (void)objectDidEndEditing:(id)anEditor
|
||||
{
|
||||
[_editors removeObject:anEditor];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -167,7 +167,9 @@ var currentCursor = nil,
|
||||
{
|
||||
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
||||
return [CPCursor cursorWithCSSString:@"-webkit-grab"];
|
||||
else if (CPBrowserIsEngine(CPGeckoBrowserEngine) || CPBrowserIsEngine(CPOperaBrowserEngine))
|
||||
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||
return [CPCursor cursorWithCSSString:@"-moz-grab"];
|
||||
else if (CPBrowserIsEngine(CPOperaBrowserEngine))
|
||||
return [CPCursor cursorWithCSSString:@"move"];
|
||||
|
||||
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit only. move in FFMac|Opera
|
||||
@@ -177,8 +179,10 @@ var currentCursor = nil,
|
||||
{
|
||||
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
||||
return [CPCursor cursorWithCSSString:@"-webkit-grabbing"];
|
||||
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||
return [CPCursor cursorWithCSSString:@"-moz-grabbing"];
|
||||
|
||||
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit only
|
||||
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit || FF
|
||||
}
|
||||
|
||||
+ (CPCursor)disappearingItemCursor
|
||||
@@ -193,7 +197,7 @@ var currentCursor = nil,
|
||||
|
||||
+ (void)unhide
|
||||
{
|
||||
[self _setCursorCSS:[currentCursor _cssString]]
|
||||
[self _setCursorCSS:[currentCursor _cssString]];
|
||||
}
|
||||
|
||||
+ (void)setHiddenUntilMouseMoves:(BOOL)flag
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import "CPText.j"
|
||||
|
||||
#include "CoreGraphics/CGGeometry.h"
|
||||
|
||||
@@ -41,7 +42,7 @@ CPAppKitDefined = 13;
|
||||
CPSystemDefined = 14;
|
||||
CPApplicationDefined = 15;
|
||||
CPPeriodic = 16;
|
||||
CPCursorUpdate = 17;
|
||||
CPCursorUpdate = 17;
|
||||
CPScrollWheel = 22;
|
||||
CPOtherMouseDown = 25;
|
||||
CPOtherMouseUp = 26;
|
||||
@@ -52,8 +53,7 @@ CPTouchStart = 28;
|
||||
CPTouchMove = 29;
|
||||
CPTouchEnd = 30;
|
||||
CPTouchCancel = 31;
|
||||
|
||||
|
||||
|
||||
CPAlphaShiftKeyMask = 1 << 16;
|
||||
CPShiftKeyMask = 1 << 17;
|
||||
CPControlKeyMask = 1 << 18;
|
||||
@@ -87,26 +87,102 @@ CPPeriodicMask = 1 << CPPeriodic;
|
||||
CPScrollWheelMask = 1 << CPScrollWheel;
|
||||
CPAnyEventMask = 0xffffffff;
|
||||
|
||||
CPDOMEventDoubleClick = "dblclick",
|
||||
CPDOMEventMouseDown = "mousedown",
|
||||
CPDOMEventMouseUp = "mouseup",
|
||||
CPDOMEventMouseMoved = "mousemove",
|
||||
CPDOMEventMouseDragged = "mousedrag",
|
||||
CPDOMEventKeyUp = "keyup",
|
||||
CPDOMEventKeyDown = "keydown",
|
||||
CPDOMEventKeyPress = "keypress";
|
||||
CPDOMEventCopy = "copy";
|
||||
CPDOMEventPaste = "paste";
|
||||
CPDOMEventScrollWheel = "mousewheel";
|
||||
CPDOMEventTouchStart = "touchstart";
|
||||
CPDOMEventTouchMove = "touchmove";
|
||||
CPDOMEventTouchEnd = "touchend";
|
||||
CPDOMEventTouchCancel = "touchcancel";
|
||||
CPUpArrowFunctionKey = "\uF700";
|
||||
CPDownArrowFunctionKey = "\uF701";
|
||||
CPLeftArrowFunctionKey = "\uF702";
|
||||
CPRightArrowFunctionKey = "\uF703";
|
||||
CPF1FunctionKey = "\uF704";
|
||||
CPF2FunctionKey = "\uF705";
|
||||
CPF3FunctionKey = "\uF706";
|
||||
CPF4FunctionKey = "\uF707";
|
||||
CPF5FunctionKey = "\uF708";
|
||||
CPF6FunctionKey = "\uF709";
|
||||
CPF7FunctionKey = "\uF70A";
|
||||
CPF8FunctionKey = "\uF70B";
|
||||
CPF9FunctionKey = "\uF70C";
|
||||
CPF10FunctionKey = "\uF70D";
|
||||
CPF11FunctionKey = "\uF70E";
|
||||
CPF12FunctionKey = "\uF70F";
|
||||
CPF13FunctionKey = "\uF710";
|
||||
CPF14FunctionKey = "\uF711";
|
||||
CPF15FunctionKey = "\uF712";
|
||||
CPF16FunctionKey = "\uF713";
|
||||
CPF17FunctionKey = "\uF714";
|
||||
CPF18FunctionKey = "\uF715";
|
||||
CPF19FunctionKey = "\uF716";
|
||||
CPF20FunctionKey = "\uF717";
|
||||
CPF21FunctionKey = "\uF718";
|
||||
CPF22FunctionKey = "\uF719";
|
||||
CPF23FunctionKey = "\uF71A";
|
||||
CPF24FunctionKey = "\uF71B";
|
||||
CPF25FunctionKey = "\uF71C";
|
||||
CPF26FunctionKey = "\uF71D";
|
||||
CPF27FunctionKey = "\uF71E";
|
||||
CPF28FunctionKey = "\uF71F";
|
||||
CPF29FunctionKey = "\uF720";
|
||||
CPF30FunctionKey = "\uF721";
|
||||
CPF31FunctionKey = "\uF722";
|
||||
CPF32FunctionKey = "\uF723";
|
||||
CPF33FunctionKey = "\uF724";
|
||||
CPF34FunctionKey = "\uF725";
|
||||
CPF35FunctionKey = "\uF726";
|
||||
CPInsertFunctionKey = "\uF727";
|
||||
CPDeleteFunctionKey = "\uF728";
|
||||
CPHomeFunctionKey = "\uF729";
|
||||
CPBeginFunctionKey = "\uF72A";
|
||||
CPEndFunctionKey = "\uF72B";
|
||||
CPPageUpFunctionKey = "\uF72C";
|
||||
CPPageDownFunctionKey = "\uF72D";
|
||||
CPPrintScreenFunctionKey = "\uF72E";
|
||||
CPScrollLockFunctionKey = "\uF72F";
|
||||
CPPauseFunctionKey = "\uF730";
|
||||
CPSysReqFunctionKey = "\uF731";
|
||||
CPBreakFunctionKey = "\uF732";
|
||||
CPResetFunctionKey = "\uF733";
|
||||
CPStopFunctionKey = "\uF734";
|
||||
CPMenuFunctionKey = "\uF735";
|
||||
CPUserFunctionKey = "\uF736";
|
||||
CPSystemFunctionKey = "\uF737";
|
||||
CPPrintFunctionKey = "\uF738";
|
||||
CPClearLineFunctionKey = "\uF739";
|
||||
CPClearDisplayFunctionKey = "\uF73A";
|
||||
CPInsertLineFunctionKey = "\uF73B";
|
||||
CPDeleteLineFunctionKey = "\uF73C";
|
||||
CPInsertCharFunctionKey = "\uF73D";
|
||||
CPDeleteCharFunctionKey = "\uF73E";
|
||||
CPPrevFunctionKey = "\uF73F";
|
||||
CPNextFunctionKey = "\uF740";
|
||||
CPSelectFunctionKey = "\uF741";
|
||||
CPExecuteFunctionKey = "\uF742";
|
||||
CPUndoFunctionKey = "\uF743";
|
||||
CPRedoFunctionKey = "\uF744";
|
||||
CPFindFunctionKey = "\uF745";
|
||||
CPHelpFunctionKey = "\uF746";
|
||||
CPModeSwitchFunctionKey = "\uF747";
|
||||
CPEscapeFunctionKey = "\u001B";
|
||||
|
||||
|
||||
CPDOMEventDoubleClick = "dblclick",
|
||||
CPDOMEventMouseDown = "mousedown",
|
||||
CPDOMEventMouseUp = "mouseup",
|
||||
CPDOMEventMouseMoved = "mousemove",
|
||||
CPDOMEventMouseDragged = "mousedrag",
|
||||
CPDOMEventKeyUp = "keyup",
|
||||
CPDOMEventKeyDown = "keydown",
|
||||
CPDOMEventKeyPress = "keypress";
|
||||
CPDOMEventCopy = "copy";
|
||||
CPDOMEventPaste = "paste";
|
||||
CPDOMEventScrollWheel = "mousewheel";
|
||||
CPDOMEventTouchStart = "touchstart";
|
||||
CPDOMEventTouchMove = "touchmove";
|
||||
CPDOMEventTouchEnd = "touchend";
|
||||
CPDOMEventTouchCancel = "touchcancel";
|
||||
|
||||
var _CPEventPeriodicEventPeriod = 0,
|
||||
_CPEventPeriodicEventTimer = nil;
|
||||
_CPEventPeriodicEventTimer = nil,
|
||||
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPEvent
|
||||
CPEvent encapsulates the details of a Cappuccino keyboard or mouse event.
|
||||
@@ -155,7 +231,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code
|
||||
{
|
||||
return [[self alloc] _initKeyEventWithType:anEventType location:aPoint modifierFlags:modifierFlags
|
||||
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
|
||||
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
|
||||
characters:characters charactersIgnoringModifiers:unmodCharacters isARepeat:repeatKey keyCode:code];
|
||||
}
|
||||
|
||||
@@ -173,7 +249,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
@throws CPInternalInconsistencyException if an invalid event type is provided
|
||||
@return the new mouse event
|
||||
*/
|
||||
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
|
||||
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
|
||||
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
|
||||
{
|
||||
@@ -204,12 +280,12 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
|
||||
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
|
||||
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_type = anEventType;
|
||||
@@ -222,7 +298,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
_pressure = aPressure;
|
||||
_window = [CPApp windowWithWindowNumber:aWindowNumber];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -232,7 +308,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_type = anEventType;
|
||||
@@ -246,7 +322,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
_keyCode = code;
|
||||
_windowNumber = aWindowNumber;
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -256,7 +332,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_type = anEventType;
|
||||
@@ -267,7 +343,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
_subtype = aSubtype;
|
||||
_data1 = aData1;
|
||||
_data2 = aData2;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -445,23 +521,76 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
return _deltaZ;
|
||||
}
|
||||
|
||||
- (BOOL)_triggersKeyEquivalent:(CPString)aKeyEquivalent withModifierMask:aKeyEquivalentModifierMask
|
||||
{
|
||||
if (!aKeyEquivalent)
|
||||
return NO;
|
||||
|
||||
if (_CPEventUpperCaseRegex.test(aKeyEquivalent))
|
||||
aKeyEquivalentModifierMask |= CPShiftKeyMask;
|
||||
|
||||
if (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) && (aKeyEquivalentModifierMask & CPCommandKeyMask))
|
||||
{
|
||||
aKeyEquivalentModifierMask |= CPControlKeyMask;
|
||||
aKeyEquivalentModifierMask &= ~CPCommandKeyMask;
|
||||
}
|
||||
|
||||
if ((_modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) !== aKeyEquivalentModifierMask)
|
||||
return NO;
|
||||
|
||||
// Treat \r and \n as the same key equivalent. See issue #710.
|
||||
if (_characters === CPNewlineCharacter || _characters === CPCarriageReturnCharacter)
|
||||
return CPNewlineCharacter === aKeyEquivalent || CPCarriageReturnCharacter === aKeyEquivalent;
|
||||
|
||||
return [_characters caseInsensitiveCompare:aKeyEquivalent] === CPOrderedSame;
|
||||
}
|
||||
|
||||
- (BOOL)_couldBeKeyEquivalent
|
||||
{
|
||||
if (_type !== CPKeyDown)
|
||||
return NO;
|
||||
|
||||
var characterCount = _characters.length;
|
||||
|
||||
if (!characterCount)
|
||||
return NO;
|
||||
|
||||
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
|
||||
return YES;
|
||||
|
||||
for(var i=0; i<characterCount; i++)
|
||||
{
|
||||
switch(_characters.charAt(i))
|
||||
{
|
||||
case CPBackspaceCharacter:
|
||||
case CPDeleteCharacter:
|
||||
case CPDeleteFunctionKey:
|
||||
case CPTabCharacter:
|
||||
case CPCarriageReturnCharacter:
|
||||
case CPNewlineCharacter:
|
||||
case CPEscapeFunctionKey:
|
||||
case CPPageUpFunctionKey:
|
||||
case CPPageDownFunctionKey:
|
||||
case CPLeftArrowFunctionKey:
|
||||
case CPUpArrowFunctionKey:
|
||||
case CPRightArrowFunctionKey:
|
||||
case CPDownArrowFunctionKey:
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
// FIXME: More cases? Space?
|
||||
return _type === CPKeyDown &&
|
||||
_modifierFlags & (CPCommandKeyMask | CPControlKeyMask) &&
|
||||
[_characters length] > 0;
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Generates periodic events every \c aPeriod seconds.
|
||||
Gene rates periodic events every \c aPeriod seconds.
|
||||
@param aDelay the number of seconds before the first event
|
||||
@param aPeriod the length of time in seconds between successive events
|
||||
*/
|
||||
+ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod
|
||||
{
|
||||
_CPEventPeriodicEventPeriod = aPeriod;
|
||||
|
||||
|
||||
// FIXME: OH TIMERS!!!
|
||||
_CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0);
|
||||
}
|
||||
@@ -473,9 +602,9 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
{
|
||||
if (_CPEventPeriodicEventTimer === nil)
|
||||
return;
|
||||
|
||||
|
||||
window.clearTimeout(_CPEventPeriodicEventTimer);
|
||||
|
||||
|
||||
_CPEventPeriodicEventTimer = nil;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,16 @@ CPScaleProportionally = 0;
|
||||
CPScaleToFit = 1;
|
||||
CPScaleNone = 2;
|
||||
|
||||
CPImageAlignCenter = 0;
|
||||
CPImageAlignTop = 1;
|
||||
CPImageAlignTopLeft = 2;
|
||||
CPImageAlignTopRight = 3;
|
||||
CPImageAlignLeft = 4;
|
||||
CPImageAlignBottom = 5;
|
||||
CPImageAlignBottomLeft = 6;
|
||||
CPImageAlignBottomRight = 7;
|
||||
CPImageAlignRight = 8;
|
||||
|
||||
var CPImageViewShadowBackgroundColor = nil;
|
||||
|
||||
var LEFT_SHADOW_INSET = 3.0,
|
||||
@@ -52,14 +62,15 @@ var LEFT_SHADOW_INSET = 3.0,
|
||||
*/
|
||||
@implementation CPImageView : CPControl
|
||||
{
|
||||
DOMElement _DOMImageElement;
|
||||
DOMElement _DOMImageElement;
|
||||
|
||||
BOOL _hasShadow;
|
||||
CPView _shadowView;
|
||||
BOOL _hasShadow;
|
||||
CPView _shadowView;
|
||||
|
||||
BOOL _isEditable;
|
||||
BOOL _isEditable;
|
||||
|
||||
CGRect _imageRect;
|
||||
CGRect _imageRect;
|
||||
CPImageAlignment _imageAlignment;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -191,6 +202,30 @@ var LEFT_SHADOW_INSET = 3.0,
|
||||
[self hideOrDisplayContents];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the type of image alignment that should be used to
|
||||
render the image.
|
||||
@param anImageAlignment the type of scaling to use
|
||||
*/
|
||||
- (void)setImageAlignment:(CPImageAlignment)anImageAlignment
|
||||
{
|
||||
if (_imageAlignment == anImageAlignment)
|
||||
return;
|
||||
|
||||
_imageAlignment = anImageAlignment;
|
||||
|
||||
if (![self image])
|
||||
return;
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (unsigned)imageAlignment
|
||||
{
|
||||
return _imageAlignment;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the type of image scaling that should be used to
|
||||
render the image.
|
||||
@@ -318,8 +353,45 @@ var LEFT_SHADOW_INSET = 3.0,
|
||||
#endif
|
||||
}
|
||||
|
||||
var x = (boundsWidth - width) / 2.0,
|
||||
y = (boundsHeight - height) / 2.0;
|
||||
var x, y;
|
||||
|
||||
switch (_imageAlignment)
|
||||
{
|
||||
case CPImageAlignLeft:
|
||||
case CPImageAlignTopLeft:
|
||||
case CPImageAlignBottomLeft:
|
||||
x = 0.0;
|
||||
break;
|
||||
|
||||
case CPImageAlignRight:
|
||||
case CPImageAlignTopRight:
|
||||
case CPImageAlignBottomRight:
|
||||
x = boundsWidth - width;
|
||||
break;
|
||||
|
||||
default:
|
||||
x = (boundsWidth - width) / 2.0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_imageAlignment)
|
||||
{
|
||||
case CPImageAlignTop:
|
||||
case CPImageAlignTopLeft:
|
||||
case CPImageAlignTopRight:
|
||||
y = 0.0;
|
||||
break;
|
||||
|
||||
case CPImageAlignBottom:
|
||||
case CPImageAlignBottomLeft:
|
||||
case CPImageAlignBottomRight:
|
||||
y = boundsHeight - height;
|
||||
break;
|
||||
|
||||
default:
|
||||
y = (boundsHeight - height) / 2.0;
|
||||
break;
|
||||
}
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
|
||||
@@ -380,10 +452,11 @@ var LEFT_SHADOW_INSET = 3.0,
|
||||
|
||||
@end
|
||||
|
||||
var CPImageViewImageKey = @"CPImageViewImageKey",
|
||||
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
|
||||
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
|
||||
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
|
||||
var CPImageViewImageKey = @"CPImageViewImageKey",
|
||||
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
|
||||
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
|
||||
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
|
||||
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
|
||||
|
||||
@implementation CPImageView (CPCoding)
|
||||
|
||||
@@ -416,6 +489,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
|
||||
#endif
|
||||
|
||||
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
|
||||
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
|
||||
|
||||
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
|
||||
[self setEditable:YES];
|
||||
@@ -450,6 +524,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
|
||||
_subviews = actualSubviews;
|
||||
|
||||
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
|
||||
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
|
||||
|
||||
if (_isEditable)
|
||||
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
|
||||
|
||||
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* CPKeyValueBinding.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Ross Boucher 1/13/09
|
||||
* Copyright 280 North, Inc.
|
||||
*
|
||||
* Adapted from GNUStep
|
||||
* Released under the LGPL.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPArray.j>
|
||||
@import <Foundation/CPDictionary.j>
|
||||
@import <Foundation/CPValueTransformer.j>
|
||||
|
||||
var exposedBindingsMap = [CPDictionary new],
|
||||
bindingsMap = [CPDictionary new];
|
||||
|
||||
var CPBindingOperationAnd = 0,
|
||||
CPBindingOperationOr = 1;
|
||||
|
||||
@implementation CPKeyValueBinding : CPObject
|
||||
{
|
||||
CPDictionary _info;
|
||||
id _source;
|
||||
}
|
||||
|
||||
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
|
||||
{
|
||||
var bindings = [exposedBindingsMap objectForKey:[aClass hash]];
|
||||
|
||||
if (!bindings)
|
||||
{
|
||||
bindings = [];
|
||||
[exposedBindingsMap setObject:bindings forKey:[aClass hash]];
|
||||
}
|
||||
|
||||
bindings.push(aBinding);
|
||||
}
|
||||
|
||||
+ (CPArray)exposedBindingsForClass:(Class)aClass
|
||||
{
|
||||
return [[exposedBindingsMap objectForKey:[aClass hash]] copy];
|
||||
}
|
||||
|
||||
+ (CPKeyValueBinding)getBinding:(CPString)aBinding forObject:(id)anObject
|
||||
{
|
||||
return [[bindingsMap objectForKey:[anObject hash]] objectForKey:aBinding];
|
||||
}
|
||||
|
||||
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
|
||||
{
|
||||
var theBinding = [self getBinding:aBinding forObject:anObject];
|
||||
|
||||
if (theBinding)
|
||||
return theBinding._info;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (CPDictionary)allBindingsForObject:(id)anObject
|
||||
{
|
||||
return [bindingsMap objectForKey:[anObject hash]];
|
||||
}
|
||||
|
||||
+ (void)unbind:(CPString)aBinding forObject:(id)anObject
|
||||
{
|
||||
var bindings = [bindingsMap objectForKey:[anObject hash]];
|
||||
|
||||
if (!bindings)
|
||||
return;
|
||||
|
||||
var theBinding = [bindings objectForKey:aBinding];
|
||||
|
||||
if (!theBinding)
|
||||
return;
|
||||
|
||||
var infoDictionary = theBinding._info,
|
||||
observedObject = [infoDictionary objectForKey:CPObservedObjectKey],
|
||||
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey];
|
||||
|
||||
[observedObject removeObserver:theBinding forKeyPath:keyPath];
|
||||
[bindings removeObjectForKey:aBinding];
|
||||
}
|
||||
|
||||
+ (void)unbindAllForObject:(id)anObject
|
||||
{
|
||||
var bindings = [bindingsMap objectForKey:[anObject hash]];
|
||||
if (!bindings)
|
||||
return;
|
||||
|
||||
var allKeys = [bindings allKeys],
|
||||
count = allKeys.length;
|
||||
|
||||
while (count--)
|
||||
[anObject unbind:[bindings objectForKey:allKeys[count]]];
|
||||
|
||||
[bindingsMap removeObjectForKey:[anObject hash]];
|
||||
}
|
||||
|
||||
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_source = aSource;
|
||||
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
|
||||
|
||||
if (options)
|
||||
[_info setObject:options forKey:CPOptionsKey];
|
||||
|
||||
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
|
||||
|
||||
var bindings = [bindingsMap objectForKey:[_source hash]];
|
||||
if (!bindings)
|
||||
{
|
||||
bindings = [CPDictionary new];
|
||||
[bindingsMap setObject:bindings forKey:[_source hash]];
|
||||
}
|
||||
|
||||
[bindings setObject:self forKey:aName];
|
||||
[self setValueFor:aBinding];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)aBinding
|
||||
{
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [destination valueForKeyPath:keyPath];
|
||||
|
||||
newValue = [self transformValue:newValue withOptions:options];
|
||||
[_source setValue:newValue forKey:aBinding];
|
||||
}
|
||||
|
||||
- (void)reverseSetValueFor:(CPString)aBinding
|
||||
{
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [_source valueForKeyPath:aBinding];
|
||||
|
||||
newValue = [self reverseTransformValue:newValue withOptions:options];
|
||||
[destination setValue:newValue forKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
|
||||
{
|
||||
if (!changes)
|
||||
return;
|
||||
|
||||
[self setValueFor:context];
|
||||
}
|
||||
|
||||
- (id)transformValue:(id)aValue withOptions:(CPDictionary)options
|
||||
{
|
||||
var valueTransformerName,
|
||||
valueTransformer,
|
||||
placeholder;
|
||||
|
||||
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
|
||||
valueTransformer;
|
||||
|
||||
if (valueTransformerName)
|
||||
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
|
||||
else
|
||||
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
|
||||
|
||||
if (valueTransformer)
|
||||
aValue = [valueTransformer transformedValue:aValue];
|
||||
|
||||
switch (aValue)
|
||||
{
|
||||
case CPMultipleValuesMarker: return [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
|
||||
|
||||
case CPNoSelectionMarker: return [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
|
||||
|
||||
case CPNotApplicableMarker: if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
|
||||
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+aValue];
|
||||
|
||||
return [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
|
||||
|
||||
case nil:
|
||||
case undefined: return [options objectForKey:CPNullPlaceholderBindingOption] || nil;
|
||||
}
|
||||
|
||||
return aValue;
|
||||
}
|
||||
|
||||
- (id)reverseTransformValue:(id)aValue withOptions: (CPDictionary)options
|
||||
{
|
||||
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
|
||||
valueTransformer;
|
||||
|
||||
if (valueTransformerName)
|
||||
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
|
||||
else
|
||||
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
|
||||
|
||||
if (valueTransformer && [[valueTransformer class] allowsReverseTransformation])
|
||||
aValue = [valueTransformer transformedValue:aValue];
|
||||
|
||||
return aValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPObject (KeyValueBindingCreation)
|
||||
|
||||
+ (void)exposeBinding:(CPString)aBinding
|
||||
{
|
||||
[CPKeyValueBinding exposeBinding:aBinding forClass:[self class]];
|
||||
}
|
||||
|
||||
- (CPArray)exposedBindings
|
||||
{
|
||||
var exposedBindings = [],
|
||||
theClass = [self class];
|
||||
|
||||
while(theClass)
|
||||
{
|
||||
var temp = [CPKeyValueBinding exposedBindingsForClass:theClass];
|
||||
|
||||
if (temp)
|
||||
[exposedBindings addObjectsFromArray:temp];
|
||||
|
||||
theClass = [theClass superclass];
|
||||
}
|
||||
|
||||
return exposedBindings;
|
||||
}
|
||||
|
||||
- (Class)valueClassForBinding:(CPString)binding
|
||||
{
|
||||
return [CPString class];
|
||||
}
|
||||
|
||||
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
|
||||
{
|
||||
if (!anObject || !aKeyPath)
|
||||
return CPLog.error("Invalid object or path on "+self+" for "+aBinding);
|
||||
|
||||
//if (![[self exposedBindings] containsObject:aBinding])
|
||||
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
|
||||
|
||||
[self unbind:aBinding];
|
||||
[[CPKeyValueBinding alloc] initWithBinding:[anObject _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
|
||||
}
|
||||
|
||||
- (CPDictionary)infoForBinding:(CPString)aBinding
|
||||
{
|
||||
return [CPKeyValueBinding infoForBinding:aBinding forObject:self];
|
||||
}
|
||||
|
||||
- (void)unbind:(CPString)aBinding
|
||||
{
|
||||
[CPKeyValueBinding unbind:aBinding forObject:self];
|
||||
}
|
||||
|
||||
- (id)_replacementKeyPathForBinding:(CPString)binding
|
||||
{
|
||||
return binding;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPKeyValueOrBinding : CPKeyValueBinding
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)aBinding
|
||||
{
|
||||
var bindings = [bindingsMap valueForKey:[_source hash]];
|
||||
|
||||
if (!bindings)
|
||||
return;
|
||||
|
||||
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationOr) forKey:aBinding];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
|
||||
{
|
||||
[self setValueFor:context];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPKeyValueAndBinding : CPKeyValueBinding
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)aBinding
|
||||
{
|
||||
var bindings = [bindingsMap objectForKey:[_source hash]];
|
||||
|
||||
if (!bindings)
|
||||
return;
|
||||
|
||||
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationAnd) forKey:aBinding];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObejct change:(CPDictionary)changes context:(id)context
|
||||
{
|
||||
[self setValueFor:context];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
|
||||
{
|
||||
var bindingName = key,
|
||||
theBinding,
|
||||
count = 1;
|
||||
|
||||
while (theBinding = [bindings objectForKey:bindingName])
|
||||
{
|
||||
var infoDictionary = theBinding._info,
|
||||
object = [infoDictionary objectForKey:CPObservedObjectKey],
|
||||
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
|
||||
options = [infoDictionary objectForKey:CPOptionsKey];
|
||||
|
||||
var value = [theBinding transformValue:[object valueForKeyPath:keyPath] withOptions:options];
|
||||
|
||||
if (value == operation)
|
||||
return operation;
|
||||
|
||||
bindingName = [CPString stringWithFormat:@"%@%i", key, ++count];
|
||||
}
|
||||
|
||||
return !operation;
|
||||
}
|
||||
|
||||
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
|
||||
{
|
||||
var theBinding = [bindings objectForKey:targetKey],
|
||||
infoDictionary = theBinding._info,
|
||||
|
||||
object = [infoDictionary objectForKey:CPObservedObjectKey],
|
||||
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
|
||||
options = [infoDictionary objectForKey:CPOptionsKey],
|
||||
|
||||
target = [object valueForKeyPath:keyPath],
|
||||
selector = [options objectForKey:CPSelectorNameBindingOption];
|
||||
|
||||
if (!target || !selector)
|
||||
return;
|
||||
|
||||
var invocation = [CPInvocation invocationWithMethodSignature:[target methodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
|
||||
var bindingName = argumentKey
|
||||
count = 1;
|
||||
|
||||
while (theBinding = [bindings objectForKey:bindingName])
|
||||
{
|
||||
infoDictionary = theBinding._info;
|
||||
|
||||
keyPath = [infoDictionary objectForKey:CPObserverKeyPathKey];
|
||||
object = [[infoDictionary objectForKey:CPObservedObjectKey] valueForKeyPath:keyPath];
|
||||
|
||||
if (object)
|
||||
[invocation setArgument:object atIndex:++count];
|
||||
|
||||
bindingName = [CPString stringWithFormat:@"%@%i", argumentKey, count];
|
||||
}
|
||||
|
||||
[invocation invoke];
|
||||
}
|
||||
|
||||
// Keys in options dictionary
|
||||
|
||||
// Keys in dictionary returned by infoForBinding
|
||||
CPObservedObjectKey = @"CPObservedObjectKey";
|
||||
CPObservedKeyPathKey = @"CPObservedKeyPathKey";
|
||||
CPOptionsKey = @"CPOptionsKey";
|
||||
|
||||
// special markers
|
||||
CPMultipleValuesMarker = @"CPMultipleValuesMarker";
|
||||
CPNoSelectionMarker = @"CPNoSelectionMarker";
|
||||
CPNotApplicableMarker = @"CPNotApplicableMarker";
|
||||
|
||||
// Binding name constants
|
||||
CPAlignmentBinding = @"CPAlignmentBinding";
|
||||
CPEditableBinding = @"CPEditableBinding";
|
||||
CPEnabledBinding = @"CPEnabledBinding";
|
||||
CPFontBinding = @"CPFontBinding";
|
||||
CPHiddenBinding = @"CPHiddenBinding";
|
||||
CPSelectedIndexBinding = @"CPSelectedIndexBinding";
|
||||
CPTextColorBinding = @"CPTextColorBinding";
|
||||
CPToolTipBinding = @"CPToolTipBinding";
|
||||
CPValueBinding = @"value";
|
||||
|
||||
//Binding options constants
|
||||
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelectionBindingOption";
|
||||
CPAllowsNullArgumentBindingOption = @"CPAllowsNullArgumentBindingOption";
|
||||
CPConditionallySetsEditableBindingOption = @"CPConditionallySetsEditableBindingOption";
|
||||
CPConditionallySetsEnabledBindingOption = @"CPConditionallySetsEnabledBindingOption";
|
||||
CPConditionallySetsHiddenBindingOption = @"CPConditionallySetsHiddenBindingOption";
|
||||
CPContinuouslyUpdatesValueBindingOption = @"CPContinuouslyUpdatesValueBindingOption";
|
||||
CPCreatesSortDescriptorBindingOption = @"CPCreatesSortDescriptorBindingOption";
|
||||
CPDeletesObjectsOnRemoveBindingsOption = @"CPDeletesObjectsOnRemoveBindingsOption";
|
||||
CPDisplayNameBindingOption = @"CPDisplayNameBindingOption";
|
||||
CPDisplayPatternBindingOption = @"CPDisplayPatternBindingOption";
|
||||
CPHandlesContentAsCompoundValueBindingOption = @"CPHandlesContentAsCompoundValueBindingOption";
|
||||
CPInsertsNullPlaceholderBindingOption = @"CPInsertsNullPlaceholderBindingOption";
|
||||
CPInvokesSeparatelyWithArrayObjectsBindingOption = @"CPInvokesSeparatelyWithArrayObjectsBindingOption";
|
||||
CPMultipleValuesPlaceholderBindingOption = @"CPMultipleValuesPlaceholderBindingOption";
|
||||
CPNoSelectionPlaceholderBindingOption = @"CPNoSelectionPlaceholderBindingOption";
|
||||
CPNotApplicablePlaceholderBindingOption = @"CPNotApplicablePlaceholderBindingOption";
|
||||
CPNullPlaceholderBindingOption = @"CPNullPlaceholderBindingOption";
|
||||
CPPredicateFormatBindingOption = @"CPPredicateFormatBindingOption";
|
||||
CPRaisesForNotApplicableKeysBindingOption = @"CPRaisesForNotApplicableKeysBindingOption";
|
||||
CPSelectorNameBindingOption = @"CPSelectorNameBindingOption";
|
||||
CPSelectsAllWhenSettingContentBindingOption = @"CPSelectsAllWhenSettingContentBindingOption";
|
||||
CPValidatesImmediatelyBindingOption = @"CPValidatesImmediatelyBindingOption";
|
||||
CPValueTransformerNameBindingOption = @"CPValueTransformerNameBindingOption";
|
||||
CPValueTransformerBindingOption = @"CPValueTransformerBindingOption";
|
||||
|
||||
@@ -50,11 +50,11 @@ var _CPMenuBarVisible = NO,
|
||||
_CPMenuBarAttributes = nil,
|
||||
_CPMenuBarSharedWindow = nil;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPMenu
|
||||
|
||||
Menus provide the user with a list of actions and/or submenus. Submenus themselves are full fledged menus
|
||||
Menus provide the user with a list of actions and/or submenus. Submenus themselves are full fledged menus
|
||||
and so a heirarchical structure appears.
|
||||
*/
|
||||
@implementation CPMenu : CPObject
|
||||
@@ -69,12 +69,12 @@ var _CPMenuBarVisible = NO,
|
||||
float _minimumWidth;
|
||||
|
||||
CPMutableArray _items;
|
||||
|
||||
|
||||
BOOL _autoenablesItems;
|
||||
BOOL _showsStateColumn;
|
||||
|
||||
id _delegate;
|
||||
|
||||
|
||||
CPMenuItem _highlightedIndex;
|
||||
_CPMenuWindow _menuWindow;
|
||||
}
|
||||
@@ -95,7 +95,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if (_CPMenuBarVisible === menuBarShouldBeVisible)
|
||||
return;
|
||||
|
||||
|
||||
_CPMenuBarVisible = menuBarShouldBeVisible;
|
||||
|
||||
if ([CPPlatform supportsNativeMainMenu])
|
||||
@@ -105,13 +105,13 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if (!_CPMenuBarSharedWindow)
|
||||
_CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init];
|
||||
|
||||
|
||||
[_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]];
|
||||
|
||||
|
||||
[_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
|
||||
[_CPMenuBarSharedWindow setIconImage:_CPMenuBarIconImage];
|
||||
[_CPMenuBarSharedWindow setIconImageAlphaValue:_CPMenuBarIconImageAlphaValue];
|
||||
|
||||
|
||||
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
|
||||
[_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
|
||||
[_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
|
||||
@@ -120,12 +120,12 @@ var _CPMenuBarVisible = NO,
|
||||
[_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
|
||||
[_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
|
||||
[_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
|
||||
|
||||
|
||||
[_CPMenuBarSharedWindow orderFront:self];
|
||||
}
|
||||
else
|
||||
[_CPMenuBarSharedWindow orderOut:self];
|
||||
|
||||
|
||||
// FIXME: There must be a better way to do this.
|
||||
#if PLATFORM(DOM)
|
||||
[[CPPlatformWindow primaryPlatformWindow] resizeEvent:nil];
|
||||
@@ -159,9 +159,9 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if (_CPMenuBarAttributes == attributes)
|
||||
return;
|
||||
|
||||
|
||||
_CPMenuBarAttributes = [attributes copy];
|
||||
|
||||
|
||||
var textColor = [attributes objectForKey:@"CPMenuBarTextColor"],
|
||||
titleColor = [attributes objectForKey:@"CPMenuBarTitleColor"],
|
||||
textShadowColor = [attributes objectForKey:@"CPMenuBarTextShadowColor"],
|
||||
@@ -169,40 +169,40 @@ var _CPMenuBarVisible = NO,
|
||||
highlightColor = [attributes objectForKey:@"CPMenuBarHighlightColor"],
|
||||
highlightTextColor = [attributes objectForKey:@"CPMenuBarHighlightTextColor"],
|
||||
highlightTextShadowColor = [attributes objectForKey:@"CPMenuBarHighlightTextShadowColor"];
|
||||
|
||||
|
||||
if (!textColor && titleColor)
|
||||
[_CPMenuBarAttributes setObject:titleColor forKey:@"CPMenuBarTextColor"];
|
||||
|
||||
|
||||
else if (textColor && !titleColor)
|
||||
[_CPMenuBarAttributes setObject:textColor forKey:@"CPMenuBarTitleColor"];
|
||||
|
||||
|
||||
else if (!textColor && !titleColor)
|
||||
{
|
||||
[_CPMenuBarAttributes setObject:[CPColor colorWithRed:0.051 green:0.2 blue:0.275 alpha:1.0] forKey:@"CPMenuBarTextColor"];
|
||||
[_CPMenuBarAttributes setObject:[CPColor colorWithRed:0.051 green:0.2 blue:0.275 alpha:1.0] forKey:@"CPMenuBarTitleColor"];
|
||||
}
|
||||
|
||||
|
||||
if (!textShadowColor && titleShadowColor)
|
||||
[_CPMenuBarAttributes setObject:titleShadowColor forKey:@"CPMenuBarTextShadowColor"];
|
||||
|
||||
|
||||
else if (textShadowColor && !titleShadowColor)
|
||||
[_CPMenuBarAttributes setObject:textShadowColor forKey:@"CPMenuBarTitleShadowColor"];
|
||||
|
||||
|
||||
else if (!textShadowColor && !titleShadowColor)
|
||||
{
|
||||
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTextShadowColor"];
|
||||
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTitleShadowColor"];
|
||||
}
|
||||
|
||||
|
||||
if (!highlightColor)
|
||||
[_CPMenuBarAttributes setObject:[CPColor colorWithCalibratedRed:94.0/255.0 green:130.0/255.0 blue:186.0/255.0 alpha:1.0] forKey:@"CPMenuBarHighlightColor"];
|
||||
|
||||
|
||||
if (!highlightTextColor)
|
||||
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarHighlightTextColor"];
|
||||
|
||||
|
||||
if (!highlightTextShadowColor)
|
||||
[_CPMenuBarAttributes setObject:[CPColor blackColor] forKey:@"CPMenuBarHighlightTextShadowColor"];
|
||||
|
||||
|
||||
if (_CPMenuBarSharedWindow)
|
||||
{
|
||||
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
|
||||
@@ -231,7 +231,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if (self === [CPApp mainMenu])
|
||||
return MENUBAR_HEIGHT;
|
||||
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@@ -249,18 +249,18 @@ var _CPMenuBarVisible = NO,
|
||||
- (id)initWithTitle:(CPString)aTitle
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_title = aTitle;
|
||||
_items = [];
|
||||
|
||||
|
||||
_autoenablesItems = YES;
|
||||
_showsStateColumn = YES;
|
||||
|
||||
[self setMinimumWidth:0];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
[aMenuItem setMenu:self];
|
||||
[_items insertObject:aMenuItem atIndex:anIndex];
|
||||
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidAddItemNotification
|
||||
object:self
|
||||
@@ -306,7 +306,7 @@ var _CPMenuBarVisible = NO,
|
||||
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex
|
||||
{
|
||||
var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent];
|
||||
|
||||
|
||||
[self insertItem:item atIndex:anIndex];
|
||||
|
||||
return item;
|
||||
@@ -351,10 +351,10 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if (anIndex < 0 || anIndex >= _items.length)
|
||||
return;
|
||||
|
||||
|
||||
[_items[anIndex] setMenu:nil];
|
||||
[_items removeObjectAtIndex:anIndex];
|
||||
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidRemoveItemNotification
|
||||
object:self
|
||||
@@ -369,7 +369,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if ([aMenuItem menu] != self)
|
||||
return;
|
||||
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidChangeItemNotification
|
||||
object:self
|
||||
@@ -385,10 +385,10 @@ var _CPMenuBarVisible = NO,
|
||||
- (CPMenuItem)itemWithTag:(int)aTag
|
||||
{
|
||||
var index = [self indexOfItemWithTag:aTag];
|
||||
|
||||
|
||||
if (index == CPNotFound)
|
||||
return nil;
|
||||
|
||||
|
||||
return _items[index];
|
||||
}
|
||||
|
||||
@@ -400,10 +400,10 @@ var _CPMenuBarVisible = NO,
|
||||
- (CPMenuItem)itemWithTitle:(CPString)aTitle
|
||||
{
|
||||
var index = [self indexOfItemWithTitle:aTitle];
|
||||
|
||||
|
||||
if (index == CPNotFound)
|
||||
return nil;
|
||||
|
||||
|
||||
return _items[index];
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
if ([aMenuItem menu] !== self)
|
||||
return CPNotFound;
|
||||
|
||||
|
||||
return [_items indexOfObjectIdenticalTo:aMenuItem];
|
||||
}
|
||||
|
||||
@@ -455,7 +455,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
var index = 0,
|
||||
count = _items.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
if ([_items[index] title] === aTitle)
|
||||
return index;
|
||||
@@ -472,7 +472,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
var index = 0,
|
||||
count = _items.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
if ([_items[index] tag] == aTag)
|
||||
return index;
|
||||
@@ -490,11 +490,11 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
var index = 0,
|
||||
count = _items.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var item = _items[index];
|
||||
|
||||
|
||||
if ([item target] == aTarget && (!anAction || [item action] == anAction))
|
||||
return index;
|
||||
}
|
||||
@@ -511,7 +511,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
var index = 0,
|
||||
count = _items.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
if ([[_items[index] representedObject] isEqual:anObject])
|
||||
return index;
|
||||
@@ -528,7 +528,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
var index = 0,
|
||||
count = _items.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
if ([_items[index] submenu] == aMenu)
|
||||
return index;
|
||||
@@ -546,7 +546,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
[aMenuItem setTarget:aMenuItem];
|
||||
[aMenuItem setAction:@selector(submenuAction:)];
|
||||
|
||||
|
||||
[aMenuItem setSubmenu:aMenu];
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ var _CPMenuBarVisible = NO,
|
||||
itemIndex = [self indexOfItem:anItem];
|
||||
|
||||
if (itemIndex === CPNotFound)
|
||||
throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, menu item " +
|
||||
throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, menu item " +
|
||||
anItem + " is not present in menu " + self;
|
||||
}
|
||||
|
||||
@@ -784,10 +784,10 @@ var _CPMenuBarVisible = NO,
|
||||
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
|
||||
{
|
||||
var delegate = [aMenu delegate];
|
||||
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||
[delegate menuWillOpen:aMenu];
|
||||
|
||||
|
||||
if (!aFont)
|
||||
aFont = [CPFont systemFontOfSize:12.0];
|
||||
|
||||
@@ -938,17 +938,7 @@ var _CPMenuBarVisible = NO,
|
||||
var item = _items[index],
|
||||
modifierMask = [item keyEquivalentModifierMask];
|
||||
|
||||
if ([item keyEquivalent] === [[item keyEquivalent] uppercaseString])
|
||||
modifierMask |= CPShiftKeyMask;
|
||||
|
||||
if (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) && (modifierMask & CPCommandKeyMask))
|
||||
{
|
||||
modifierMask |= CPControlKeyMask;
|
||||
modifierMask &= ~CPCommandKeyMask;
|
||||
}
|
||||
|
||||
if ((modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) == modifierMask &&
|
||||
[characters caseInsensitiveCompare:[item keyEquivalent]] == CPOrderedSame)
|
||||
if ([anEvent _triggersKeyEquivalent:[item keyEquivalent] withModifierMask:[item keyEquivalentModifierMask]])
|
||||
{
|
||||
if ([item isEnabled])
|
||||
[self performActionForItemAtIndex:index];
|
||||
@@ -956,7 +946,7 @@ var _CPMenuBarVisible = NO,
|
||||
{
|
||||
//beep?
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -975,7 +965,7 @@ var _CPMenuBarVisible = NO,
|
||||
- (void)performActionForItemAtIndex:(unsigned)anIndex
|
||||
{
|
||||
var item = _items[anIndex];
|
||||
|
||||
|
||||
[CPApp sendAction:[item action] to:[item target] from:item];
|
||||
}
|
||||
|
||||
@@ -1064,7 +1054,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_title = [aCoder decodeObjectForKey:CPMenuTitleKey];
|
||||
@@ -1076,7 +1066,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
|
||||
|
||||
[self setMinimumWidth:0];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ var SharedMenuManager = nil;
|
||||
|
||||
// Close Menu Event.
|
||||
if (type === CPAppKitDefined)
|
||||
return [self completeTracking]
|
||||
return [self completeTracking];
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
@import "CPView.j"
|
||||
@import "_CPMenuItemView.j"
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPMenuItem
|
||||
|
||||
@@ -43,39 +43,39 @@
|
||||
|
||||
CPString _title;
|
||||
//CPAttributedString _attributedTitle;
|
||||
|
||||
|
||||
CPFont _font;
|
||||
|
||||
|
||||
id _target;
|
||||
SEL _action;
|
||||
|
||||
|
||||
BOOL _isEnabled;
|
||||
BOOL _isHidden;
|
||||
|
||||
|
||||
int _tag;
|
||||
int _state;
|
||||
|
||||
|
||||
CPImage _image;
|
||||
CPImage _alternateImage;
|
||||
CPImage _onStateImage;
|
||||
CPImage _offStateImage;
|
||||
CPImage _mixedStateImage;
|
||||
|
||||
|
||||
CPMenu _submenu;
|
||||
CPMenu _menu;
|
||||
|
||||
|
||||
CPString _keyEquivalent;
|
||||
unsigned _keyEquivalentModifierMask;
|
||||
|
||||
|
||||
int _mnemonicLocation;
|
||||
|
||||
|
||||
BOOL _isAlternate;
|
||||
int _indentationLevel;
|
||||
|
||||
|
||||
CPString _toolTip;
|
||||
id _representedObject;
|
||||
CPView _view;
|
||||
|
||||
|
||||
_CPMenuItemView _menuItemView;
|
||||
}
|
||||
|
||||
@@ -94,19 +94,19 @@
|
||||
- (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_isSeparator = NO;
|
||||
|
||||
_title = aTitle;
|
||||
_action = anAction;
|
||||
|
||||
|
||||
_isEnabled = YES;
|
||||
|
||||
|
||||
_tag = 0;
|
||||
_state = CPOffState;
|
||||
|
||||
|
||||
_keyEquivalent = aKeyEquivalent || @"";
|
||||
_keyEquivalentModifierMask = CPPlatformActionKeyMask;
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
_mnemonicLocation = CPNotFound;
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
{
|
||||
if (_isHidden == isHidden)
|
||||
return;
|
||||
|
||||
|
||||
_isHidden = isHidden;
|
||||
|
||||
[_menu itemChanged:self];
|
||||
@@ -173,9 +173,9 @@
|
||||
{
|
||||
if (_isHidden)
|
||||
return YES;
|
||||
|
||||
|
||||
var supermenu = [_menu supermenu];
|
||||
|
||||
|
||||
if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
|
||||
return YES;
|
||||
|
||||
@@ -228,11 +228,11 @@
|
||||
|
||||
if (_title == aTitle)
|
||||
return;
|
||||
|
||||
|
||||
_title = aTitle;
|
||||
|
||||
|
||||
[_menuItemView setDirty];
|
||||
|
||||
|
||||
[_menu itemChanged:self];
|
||||
}
|
||||
|
||||
@@ -260,11 +260,11 @@
|
||||
{
|
||||
if (_font == aFont)
|
||||
return;
|
||||
|
||||
|
||||
_font = aFont;
|
||||
|
||||
[_menu itemChanged:self];
|
||||
|
||||
|
||||
[_menuItemView setDirty];
|
||||
}
|
||||
|
||||
@@ -316,9 +316,9 @@ CPOffState
|
||||
{
|
||||
if (_state == aState)
|
||||
return;
|
||||
|
||||
|
||||
_state = aState;
|
||||
|
||||
|
||||
[_menu itemChanged:self];
|
||||
|
||||
[_menuItemView setDirty];
|
||||
@@ -346,11 +346,11 @@ CPOffState
|
||||
{
|
||||
if (_image == anImage)
|
||||
return;
|
||||
|
||||
|
||||
_image = anImage;
|
||||
|
||||
[_menuItemView setDirty];
|
||||
|
||||
|
||||
[_menu itemChanged:self];
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ CPOffState
|
||||
{
|
||||
if (_onStateImage == anImage)
|
||||
return;
|
||||
|
||||
|
||||
_onStateImage = anImage;
|
||||
[_menu itemChanged:self];
|
||||
}
|
||||
@@ -409,7 +409,7 @@ CPOffState
|
||||
{
|
||||
if (_offStateImage == anImage)
|
||||
return;
|
||||
|
||||
|
||||
_offStateImage = anImage;
|
||||
[_menu itemChanged:self];
|
||||
}
|
||||
@@ -430,7 +430,7 @@ CPOffState
|
||||
{
|
||||
if (_mixedStateImage == anImage)
|
||||
return;
|
||||
|
||||
|
||||
_mixedStateImage = anImage;
|
||||
[_menu itemChanged:self];
|
||||
}
|
||||
@@ -648,14 +648,14 @@ CPControlKeyMask
|
||||
- (void)setTitleWithMnemonicLocation:(CPString)aTitle
|
||||
{
|
||||
var location = [aTitle rangeOfString:@"&"].location;
|
||||
|
||||
|
||||
if (location == CPNotFound)
|
||||
[self setTitle:aTitle];
|
||||
else
|
||||
{
|
||||
[self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
|
||||
[self setMnemonicLocation:location];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -696,7 +696,7 @@ CPControlKeyMask
|
||||
{
|
||||
if (aLevel < 0)
|
||||
[CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than or equal to 0."];
|
||||
|
||||
|
||||
_indentationLevel = MIN(15, aLevel);
|
||||
}
|
||||
|
||||
@@ -755,11 +755,11 @@ CPControlKeyMask
|
||||
{
|
||||
if (_view === aView)
|
||||
return;
|
||||
|
||||
|
||||
_view = aView;
|
||||
|
||||
|
||||
[_menuItemView setDirty];
|
||||
|
||||
|
||||
[_menu itemChanged:self];
|
||||
}
|
||||
|
||||
@@ -790,7 +790,7 @@ CPControlKeyMask
|
||||
{
|
||||
if (!_menuItemView)
|
||||
_menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
|
||||
|
||||
|
||||
return _menuItemView;
|
||||
}
|
||||
|
||||
@@ -844,15 +844,15 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
|
||||
|
||||
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
|
||||
|
||||
|
||||
// _font;
|
||||
|
||||
|
||||
_target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
|
||||
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
|
||||
|
||||
@@ -887,7 +887,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
||||
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
|
||||
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -901,11 +901,11 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
||||
[aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
|
||||
|
||||
[aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
|
||||
|
||||
|
||||
[aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
|
||||
[aCoder encodeObject:_action forKey:CPMenuItemActionKey];
|
||||
|
||||
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
|
||||
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
|
||||
ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
|
||||
|
||||
ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
|
||||
@@ -913,7 +913,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
||||
|
||||
ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
|
||||
ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
|
||||
|
||||
|
||||
ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
|
||||
ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
|
||||
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
|
||||
|
||||
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
|
||||
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
|
||||
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
|
||||
|
||||
var bundle = [CPBundle bundleForClass:self];
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ var _CPMenuItemSelectionColor = nil,
|
||||
return;
|
||||
|
||||
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
|
||||
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
|
||||
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
|
||||
|
||||
var bundle = [CPBundle bundleForClass:self];
|
||||
|
||||
|
||||
@@ -0,0 +1,614 @@
|
||||
|
||||
@import <Foundation/CPDictionary.j>
|
||||
|
||||
@import "CPController.j"
|
||||
|
||||
|
||||
@implementation CPObjectController : CPController
|
||||
{
|
||||
id _contentObject;
|
||||
id _selection;
|
||||
|
||||
Class _objectClass;
|
||||
|
||||
BOOL _isEditable;
|
||||
BOOL _automaticallyPreparesContent;
|
||||
|
||||
CPCountedSet _observedKeys;
|
||||
}
|
||||
|
||||
+ (id)initialize
|
||||
{
|
||||
[self exposeBinding:@"editable"];
|
||||
[self exposeBinding:@"contentObject"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingContentObject
|
||||
{
|
||||
return [CPSet setWithObjects:"content"];
|
||||
}
|
||||
|
||||
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
|
||||
{
|
||||
if (aKey === @"contentObject")
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingCanAdd
|
||||
{
|
||||
return [CPSet setWithObject:"editable"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingCanInsert
|
||||
{
|
||||
return [CPSet setWithObject:"editable"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingCanRemove
|
||||
{
|
||||
return [CPSet setWithObjects:"editable", "selection"];
|
||||
}
|
||||
|
||||
- (id)initWithContent:(id)aContent
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
[self setContent:aContent];
|
||||
[self setEditable:YES];
|
||||
[self setObjectClass:[CPMutableDictionary class]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)content
|
||||
{
|
||||
return _contentObject;
|
||||
}
|
||||
|
||||
- (void)setContent:(id)aContent
|
||||
{
|
||||
[self willChangeValueForKey:@"contentObject"];
|
||||
[self _selectionWillChange];
|
||||
|
||||
_contentObject = aContent;
|
||||
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
[self _selectionDidChange];
|
||||
}
|
||||
|
||||
- (void)_setContentObject:(id)aContent
|
||||
{
|
||||
[self setContent:aContent];
|
||||
}
|
||||
|
||||
- (id)_contentObject
|
||||
{
|
||||
return [self content];
|
||||
}
|
||||
|
||||
- (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
|
||||
{
|
||||
_automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
|
||||
}
|
||||
|
||||
- (BOOL)automaticallyPreparesContent
|
||||
{
|
||||
return _automaticallyPreparesContent;
|
||||
}
|
||||
|
||||
- (void)prepareContent
|
||||
{
|
||||
[self setContent:[self newObject]];
|
||||
}
|
||||
|
||||
- (void)setObjectClass:(Class)aClass
|
||||
{
|
||||
_objectClass = aClass;
|
||||
}
|
||||
|
||||
- (Class)objectClass
|
||||
{
|
||||
return _objectClass;
|
||||
}
|
||||
|
||||
- (id)newObject
|
||||
{
|
||||
return [[[self objectClass] alloc] init];
|
||||
}
|
||||
|
||||
- (void)addObject:(id)anObject
|
||||
{
|
||||
[self setContent:anObject];
|
||||
|
||||
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
}
|
||||
|
||||
- (void)removeObject:(id)anObject
|
||||
{
|
||||
if ([self content] === anObject)
|
||||
[self setContent:nil];
|
||||
|
||||
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
}
|
||||
|
||||
- (void)add:(id)aSender
|
||||
{
|
||||
// FIXME: This should happen on the next run loop?
|
||||
[self addObject:[self newObject]];
|
||||
}
|
||||
|
||||
- (BOOL)canAdd
|
||||
{
|
||||
return [self isEditable];
|
||||
}
|
||||
|
||||
- (void)remove:(id)aSender
|
||||
{
|
||||
// FIXME: This should happen on the next run loop?
|
||||
[self removeObject:[self content]];
|
||||
}
|
||||
|
||||
- (BOOL)canRemove
|
||||
{
|
||||
return [self isEditable] && [[self selectedObjects] count];
|
||||
}
|
||||
|
||||
- (void)setEditable:(BOOL)shouldBeEditable
|
||||
{
|
||||
_isEditable = shouldBeEditable;
|
||||
}
|
||||
|
||||
- (BOOL)isEditable
|
||||
{
|
||||
return _isEditable;
|
||||
}
|
||||
|
||||
- (CPArray)selectedObjects
|
||||
{
|
||||
return [[_CPObservableArray alloc] initWithObjects:[_contentObject] count:1];
|
||||
}
|
||||
|
||||
- (id)selection
|
||||
{
|
||||
return _selection;
|
||||
}
|
||||
|
||||
- (void)_selectionWillChange
|
||||
{
|
||||
[_selection controllerWillChange];
|
||||
[self willChangeValueForKey:@"selection"];
|
||||
}
|
||||
|
||||
- (void)_selectionDidChange
|
||||
{
|
||||
if (_selection === undefined || _selection === nil)
|
||||
_selection = [[CPControllerSelectionProxy alloc] initWithController:self];
|
||||
|
||||
[_selection controllerDidChange];
|
||||
[self didChangeValueForKey:@"selection"];
|
||||
}
|
||||
|
||||
- (id)observedKeys
|
||||
{
|
||||
return _observedKeys;
|
||||
}
|
||||
|
||||
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
|
||||
{
|
||||
[_observedKeys addObject:aKeyPath];
|
||||
[super addObserver:anObserver forKeyPath:aKeyPath options:options context:context];
|
||||
}
|
||||
|
||||
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
|
||||
{
|
||||
[_observedKeys removeObject:aKeyPath];
|
||||
[super removeObserver:anObserver forKeyPath:aKeyPath];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
|
||||
CPObjectControllerIsEditableKey = @"CPObjectControllerIsEditableKey",
|
||||
CPObjectControllerAutomaticallyPreparesContentKey = @"CPObjectControllerAutomaticallyPreparesContentKey";
|
||||
|
||||
@implementation CPObjectController (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
|
||||
objectClass = CPClassFromString(objectClassName);
|
||||
|
||||
// FIXME: Error if objectClass === nil
|
||||
|
||||
[self setObjectClass:objectClass];
|
||||
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
|
||||
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
|
||||
|
||||
_observedKeys = [[CPCountedSet alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[aCoder encodeObject:CPStringFromClass(objectClass) forKey:CPObjectControllerObjectClassNameKey];
|
||||
[aCoder encodeObject:[self isEditable] forKey:CPObjectControllerIsEditableKey];
|
||||
|
||||
if (![self automaticallyPreparesContent])
|
||||
[aCoder encodeBOOL:YES forKey:CPObjectControllerAutomaticallyPreparesContentKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPObservationProxy : CPObject
|
||||
{
|
||||
id _keyPath;
|
||||
id _observer;
|
||||
id _object;
|
||||
|
||||
BOOL _notifyObject;
|
||||
|
||||
id _context;
|
||||
int _options;
|
||||
}
|
||||
|
||||
- (id)initWithKeyPath:(id)aKeyPath observer:(id)anObserver object:(id)anObject
|
||||
{
|
||||
if (self=[super init])
|
||||
{
|
||||
_keyPath = aKeyPath;
|
||||
_observer = anObserver;
|
||||
_object = anObject;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)observer
|
||||
{
|
||||
return _observer;
|
||||
}
|
||||
|
||||
- (id)keyPath
|
||||
{
|
||||
return _keyPath;
|
||||
}
|
||||
|
||||
- (id)context
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
- (int)options
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
|
||||
- (void)setNotifyObject:(BOOL)notify
|
||||
{
|
||||
_notifyObject = notify;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)anObject
|
||||
{
|
||||
if ([anObject class] === [self class])
|
||||
{
|
||||
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
|
||||
{
|
||||
if (_notifyObject)
|
||||
[_object observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
|
||||
|
||||
[_observer observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return [super description] + [CPString stringWithFormat:@"observation proxy for %@ on key path %@", _observer, _keyPath];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPObservableArray : CPMutableArray
|
||||
{
|
||||
CPArray _observationProxies;
|
||||
}
|
||||
|
||||
+ (id)alloc
|
||||
{
|
||||
var a = [];
|
||||
a.isa = self;
|
||||
|
||||
var ivars = class_copyIvarList(self),
|
||||
count = ivars.length;
|
||||
|
||||
while (count--)
|
||||
a[ivar_getName(ivars[count])] = nil;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return "<_CPObservableArray: "+[super description]+" >";
|
||||
}
|
||||
|
||||
- (id)initWithArray:(CPArray)anArray
|
||||
{
|
||||
if (self = [super initWithArray:anArray])
|
||||
{
|
||||
_observationProxies = [];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithObjects:(CPArray)objects count:(unsigned)count
|
||||
{
|
||||
if (self = [super initWithObjects:objects count:count])
|
||||
{
|
||||
_observationProxies = [];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
|
||||
{
|
||||
if (aKeyPath.indexOf("@") === 0)
|
||||
{
|
||||
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
|
||||
|
||||
proxy._options = options;
|
||||
proxy._context = context;
|
||||
|
||||
[_observationProxies addObject:proxy];
|
||||
|
||||
var dotIndex = aKeyPath.indexOf("."),
|
||||
remaining = aKeyPath.substring(dotIndex+1),
|
||||
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
|
||||
|
||||
[self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
|
||||
}
|
||||
else
|
||||
{
|
||||
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
|
||||
[self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
|
||||
{
|
||||
if (aKeyPath.indexOf("@") === 0)
|
||||
{
|
||||
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
|
||||
index = [_observationProxies indexOfObject:proxy];
|
||||
|
||||
proxy = [_observationProxies objectAtIndex:index];
|
||||
|
||||
var dotIndex = aKeyPath.indexOf("."),
|
||||
remaining = aKeyPath.substring(dotIndex+1),
|
||||
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
|
||||
|
||||
[self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
|
||||
}
|
||||
else
|
||||
{
|
||||
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
|
||||
[self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
|
||||
{
|
||||
for (var i=0, count=[_observationProxies count]; i<count; i++)
|
||||
{
|
||||
var proxy = [_observationProxies objectAtIndex:i],
|
||||
keyPath = [proxy keyPath],
|
||||
operator = keyPath.indexOf(".") === 0;
|
||||
|
||||
if (operator)
|
||||
[self willChangeValueForKey:keyPath];
|
||||
|
||||
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
|
||||
|
||||
if (operator)
|
||||
[self didChangeValueForKey:keyPath];
|
||||
}
|
||||
|
||||
[super insertObject:anObject atIndex:anIndex];
|
||||
}
|
||||
|
||||
- (void)removeObjectAtIndex:(unsigned)anIndex
|
||||
{
|
||||
for (var i=0, count=[_observationProxies count]; i<count; i++)
|
||||
{
|
||||
var proxy = [_observationProxies objectAtIndex:i],
|
||||
keyPath = [proxy keyPath],
|
||||
operator = keyPath.indexOf(".") === 0;
|
||||
|
||||
if (operator)
|
||||
[self willChangeValueForKey:keyPath];
|
||||
|
||||
[anObject removeObserver:proxy forKeyPath:keyPath];
|
||||
|
||||
if (operator)
|
||||
[self didChangeValueForKey:keyPath];
|
||||
}
|
||||
|
||||
[self removeObjectAtIndex:anIndex];
|
||||
}
|
||||
|
||||
- (void)addObject:(id)anObject
|
||||
{
|
||||
[self insertObject:anObject atIndex:[self count]];
|
||||
}
|
||||
|
||||
- (void)removeLastObject
|
||||
{
|
||||
[self removeObjectAtIndex:[self count]];
|
||||
}
|
||||
|
||||
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
|
||||
{
|
||||
var currentObject = [self objectAtIndex:anIndex];
|
||||
|
||||
for (var i=0, count=[_observationProxies count]; i<count; i++)
|
||||
{
|
||||
var proxy = [_observationProxies objectAtIndex:i],
|
||||
keyPath = [proxy keyPath],
|
||||
operator = keyPath.indexOf(".") === 0;
|
||||
|
||||
if (operator)
|
||||
[self willChangeValueForKey:keyPath];
|
||||
|
||||
[currentObject removeObserver:proxy forKeyPath:keyPath];
|
||||
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
|
||||
|
||||
if (operator)
|
||||
[self didChangeValueForKey:keyPath];
|
||||
}
|
||||
|
||||
[self replaceObjectAtIndex:anIndex withObject:anObject];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPControllerSelectionProxy : CPObject
|
||||
{
|
||||
id _controller;
|
||||
id _keys;
|
||||
|
||||
CPDictionary _cachedValues;
|
||||
CPArray _observationProxies;
|
||||
}
|
||||
|
||||
- (id)initWithController:(id)aController
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_cachedValues = [CPDictionary dictionary];
|
||||
_observationProxies = [CPArray array];
|
||||
_controller = aController;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)valueForKey:(CPString)aKey
|
||||
{
|
||||
var value = [_cachedValues objectForKey:aKey];
|
||||
|
||||
if (value !== undefined && value !== nil)
|
||||
return value;
|
||||
|
||||
var allValues = [[_controller selectedObjects] valueForKeyPath:aKey],
|
||||
count = [allValues count];
|
||||
|
||||
if (!count)
|
||||
value = CPNoSelectionMarker;
|
||||
else if (count === 1)
|
||||
value = [allValues objectAtIndex:0];
|
||||
else
|
||||
{
|
||||
if ([_controller alwaysUsesMultipleValuesMarker])
|
||||
value = CPMultipleValuesMarker;
|
||||
else
|
||||
{
|
||||
value = [allValues objectAtIndex:0];
|
||||
|
||||
for (var i=0, count=[allValues count]; i<count && value!=CPMultipleValuesMarker; i++)
|
||||
{
|
||||
if (![value isEqual:[allValues objectAtIndex:i]])
|
||||
value = CPMultipleValuesMarker;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[_cachedValues setValue:value forKey:aKey];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
- (unsigned)count
|
||||
{
|
||||
return [_cachedValues count];
|
||||
}
|
||||
|
||||
- (id)keyEnumerator
|
||||
{
|
||||
return [_cachedValues keyEnumerator];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forKey:(CPString)aKey
|
||||
{
|
||||
[[_controller selectedObjects] setValue:aValue forKey:aKey];
|
||||
}
|
||||
|
||||
-(void)controllerWillChange
|
||||
{
|
||||
_keys = [_cachedValues allKeys];
|
||||
|
||||
if (!_keys)
|
||||
return;
|
||||
|
||||
for (var i=0, count=_keys.length; i<count; i++)
|
||||
[self willChangeValueForKey:_keys[i]];
|
||||
|
||||
[_cachedValues removeAllObjects];
|
||||
}
|
||||
|
||||
-(void)controllerDidChange
|
||||
{
|
||||
[_cachedValues removeAllObjects];
|
||||
|
||||
if (!_keys)
|
||||
return;
|
||||
|
||||
for (var i=0, count=_keys.length; i<count; i++)
|
||||
[self didChangeValueForKey:_keys[i]];
|
||||
|
||||
_keys = nil;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
|
||||
{
|
||||
[_cachedValues removeObjectForKey:aKeyPath];
|
||||
}
|
||||
|
||||
- (void)addObserver:(id)anObject forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
|
||||
{
|
||||
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
|
||||
|
||||
[proxy setNotifyObject:YES];
|
||||
[_observationProxies addObject:proxy];
|
||||
|
||||
[[_controller selectedObjects] addObserver:proxy forKeyPath:aKeyPath options:options context:context];
|
||||
}
|
||||
|
||||
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
|
||||
{
|
||||
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
|
||||
index = [_observationProxies indexOfObject:proxy];
|
||||
|
||||
[[_controller selectedObjects] removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
|
||||
[_observationProxies removeObjectAtIndex:index];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -50,12 +50,30 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_
|
||||
|
||||
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10;
|
||||
|
||||
|
||||
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2,
|
||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3,
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 4,
|
||||
CPOutlineViewDelegate_outlineView_isGroupItem_ = 1 << 5;
|
||||
CPOutlineViewDelegate_outlineView_didClickTableColumn_ = 1 << 2,
|
||||
CPOutlineViewDelegate_outlineView_didDragTableColumn_ = 1 << 3,
|
||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 4,
|
||||
CPOutlineViewDelegate_outlineView_isGroupItem_ = 1 << 5,
|
||||
CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ = 1 << 6,
|
||||
CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ = 1 << 7,
|
||||
CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_ = 1 << 8,
|
||||
CPOutlineViewDelegate_outlineView_shouldCollapseItem_ = 1 << 9,
|
||||
CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_ = 1 << 10,
|
||||
CPOutlineViewDelegate_outlineView_shouldExpandItem_ = 1 << 11,
|
||||
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ = 1 << 12,
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 13,
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ = 1 << 14,
|
||||
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ = 1 << 15,
|
||||
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ = 1 << 16,
|
||||
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ = 1 << 17,
|
||||
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ = 1 << 18,
|
||||
CPOutlineViewDelegate_outlineView_sizeToFitWidthOfColumn_ = 1 << 19,
|
||||
CPOutlineViewDelegate_outlineView_toolTipForView_rect_tableColumn_item_mouseLocation_ = 1 << 20,
|
||||
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ = 1 << 21,
|
||||
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ = 1 << 22,
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 23,
|
||||
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ = 1 << 24;
|
||||
|
||||
CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
@@ -79,10 +97,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
CPArray _disclosureControlsForRows;
|
||||
CPData _disclosureControlData;
|
||||
CPArray _disclosureControlQueue;
|
||||
|
||||
|
||||
BOOL _shouldRetargetItem;
|
||||
id _retargetedItem;
|
||||
|
||||
|
||||
BOOL _shouldRetargetChildIndex;
|
||||
CPInteger _retargedChildIndex;
|
||||
CPTimer _dragHoverTimer;
|
||||
@@ -107,7 +125,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
_retargetedItem = nil;
|
||||
_shouldRetargetItem = NO;
|
||||
|
||||
|
||||
_retargedChildIndex = nil;
|
||||
_shouldRetargetChildIndex = NO;
|
||||
_startHoverTime = nil;
|
||||
@@ -238,7 +256,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
{
|
||||
var children = itemInfo.children,
|
||||
childIndex = children.length;
|
||||
|
||||
|
||||
while (childIndex--)
|
||||
[self expandItem:children[childIndex] expandChildren:YES];
|
||||
}
|
||||
@@ -374,7 +392,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
return nil;
|
||||
|
||||
var parent = itemInfo.parent;
|
||||
|
||||
|
||||
// Check if the parent is the root item because we never return the actual root item
|
||||
if (itemInfo[[parent UID]] === _rootItemInfo)
|
||||
parent = nil;
|
||||
@@ -396,10 +414,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
|
||||
{
|
||||
[super _performSelection:select forRow:rowIndex context:context];
|
||||
|
||||
|
||||
var control = _disclosureControlsForRows[rowIndex],
|
||||
selector = select ? @"setThemeState:" : @"unsetThemeState:";
|
||||
|
||||
|
||||
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
@@ -469,20 +487,42 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
_outlineViewDelegate = aDelegate;
|
||||
_implementedOutlineViewDelegateMethods = 0;
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_;
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_;
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:heightOfRowByItem:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_heightOfRowByItem_;
|
||||
var delegateMethods = [
|
||||
CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ , @selector(outlineView:dataViewForTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_didClickTableColumn_ , @selector(outlineView:didClickTableColumn:),
|
||||
CPOutlineViewDelegate_outlineView_didDragTableColumn_ , @selector(outlineView:didDragTableColumn:),
|
||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:),
|
||||
CPOutlineViewDelegate_outlineView_isGroupItem_ , @selector(outlineView:isGroupItem:),
|
||||
CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ , @selector(outlineView:mouseDownInHeaderOfTableColumn:),
|
||||
CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ , @selector(outlineView:nextTypeSelectMatchFromItem:toItem:forString:),
|
||||
CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_ , @selector(outlineView:selectionIndexesForProposedSelection:),
|
||||
CPOutlineViewDelegate_outlineView_shouldCollapseItem_ , @selector(outlineView:shouldCollapseItem:),
|
||||
CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_ , @selector(outlineView:shouldEditTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_shouldExpandItem_ , @selector(outlineView:shouldExpandItem:),
|
||||
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ , @selector(outlineView:shouldReorderColumn:toColumn:),
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectItem_ , @selector(outlineView:shouldSelectItem:),
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ , @selector(outlineView:shouldSelectTableColumn:),
|
||||
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ , @selector(outlineView:shouldShowOutlineViewForItem:),
|
||||
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ , @selector(outlineView:shouldShowViewExpansionForTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ , @selector(outlineView:shouldTrackView:forTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ , @selector(outlineView:shouldTypeSelectForEvent:withCurrentSearchString:),
|
||||
CPOutlineViewDelegate_outlineView_sizeToFitWidthOfColumn_ , @selector(outlineView:sizeToFitWidthOfColumn:),
|
||||
CPOutlineViewDelegate_outlineView_toolTipForView_rect_tableColumn_item_mouseLocation_, @selector(outlineView:toolTipForView:rect:tableColumn:item:mouseLocation:),
|
||||
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ , @selector(outlineView:typeSelectStringForTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ , @selector(outlineView:willDisplayOutlineView:forTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ , @selector(outlineView:willDisplayView:forTableColumn:item:),
|
||||
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ , @selector(selectionShouldChangeInOutlineView:)
|
||||
],
|
||||
delegateCount = [delegateMethods count];
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:willDisplayView:forTableColumn:item:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_;
|
||||
for (var i=0; i < delegateCount; i += 2)
|
||||
{
|
||||
var bitMask = delegateMethods[i],
|
||||
selector = delegateMethods[i+1];
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:isGroupItem:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_isGroupItem_;
|
||||
if ([_outlineViewDelegate respondsToSelector:selector])
|
||||
_implementedOutlineViewDelegateMethods |= bitMask;
|
||||
}
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
|
||||
[defaultCenter
|
||||
@@ -600,10 +640,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
_dropItem = theItem;
|
||||
_retargetedItem = theItem;
|
||||
_shouldRetargetItem = YES;
|
||||
|
||||
|
||||
_retargedChildIndex = theIndex;
|
||||
_shouldRetargetChildIndex = YES;
|
||||
|
||||
|
||||
// set CPTableView's _retargetedDropRow based on retargetedItem and retargetedChildIndex
|
||||
var retargetedItemInfo = (_retargetedItem !== nil) ? _itemInfosForItems[[_retargetedItem UID]] : _rootItemInfo,
|
||||
retargetedChildItem = (_retargedChildIndex !== CPOutlineViewDropOnItemIndex) ? retargetedItemInfo.children[_retargedChildIndex] : _retargetedItem;
|
||||
@@ -623,7 +663,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
{
|
||||
if (_shouldRetargetItem)
|
||||
return _retargetedItem;
|
||||
|
||||
|
||||
var lowerLevel = [self levelForRow:theLowerRowIndex]
|
||||
upperItem = [self itemAtRow:theUpperRowIndex];
|
||||
upperLevel = [self levelForItem:upperItem];
|
||||
@@ -642,7 +682,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
// Check the next parent
|
||||
upperItem = [self parentForItem:upperItem];
|
||||
}
|
||||
|
||||
|
||||
return [self parentForItem:[self itemAtRow:theLowerRowIndex]];
|
||||
}
|
||||
|
||||
@@ -652,10 +692,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset],
|
||||
parentItem = [self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset],
|
||||
level = [self levelForItem:parentItem];
|
||||
|
||||
rect.origin.x = (level + 1) * [self indentationPerLevel];
|
||||
|
||||
rect.origin.x = (level + 1) * [self indentationPerLevel];
|
||||
rect.size.width -= rect.origin.x; // This assumes that the x returned by super is zero
|
||||
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
@@ -823,7 +863,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
@end
|
||||
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
|
||||
{
|
||||
if (!anItem)
|
||||
@@ -836,55 +876,55 @@ var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
|
||||
dataSource = _outlineViewDataSource,
|
||||
itemUID = [anItem UID],
|
||||
itemInfo = itemInfosForItems[itemUID];
|
||||
|
||||
|
||||
// If we're not in the tree, then just bail.
|
||||
if (!itemInfo)
|
||||
return [];
|
||||
|
||||
|
||||
// See if the item itself can be swapped out.
|
||||
var parent = itemInfo.parent,
|
||||
parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo,
|
||||
parentChildren = parentItemInfo.children,
|
||||
index = [parentChildren indexOfObjectIdenticalTo:anItem],
|
||||
newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
|
||||
|
||||
|
||||
if (anItem !== newItem)
|
||||
{
|
||||
itemInfosForItems[[anItem UID]] = nil;
|
||||
itemInfosForItems[[newItem UID]] = itemInfo;
|
||||
|
||||
|
||||
parentChildren[index] = newItem;
|
||||
_itemsForRows[itemInfo.row] = newItem;
|
||||
}
|
||||
|
||||
|
||||
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
|
||||
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
|
||||
}
|
||||
}
|
||||
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate)
|
||||
{
|
||||
with(anOutlineView)
|
||||
{
|
||||
var itemInfosForItems = _itemInfosForItems,
|
||||
dataSource = _outlineViewDataSource;
|
||||
|
||||
|
||||
if (!anItem)
|
||||
var itemInfo = _rootItemInfo;
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
// Get the existing info if it exists.
|
||||
var itemUID = [anItem UID],
|
||||
itemInfo = itemInfosForItems[itemUID];
|
||||
|
||||
|
||||
// If we're not in the tree, then just bail.
|
||||
if (!itemInfo)
|
||||
return [];
|
||||
|
||||
|
||||
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
|
||||
|
||||
|
||||
// If we were previously expanded, but now no longer expandable, "de-expand".
|
||||
// NOTE: we are *not* collapsing, thus no notification is posted.
|
||||
if (!itemInfo.isExpandable && itemInfo.isExpanded)
|
||||
@@ -893,72 +933,72 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
itemInfo.children = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The root item does not count as a descendant.
|
||||
var weight = itemInfo.weight,
|
||||
descendants = anItem ? [anItem] : [];
|
||||
|
||||
|
||||
if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) ||
|
||||
![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
|
||||
{
|
||||
var index = 0,
|
||||
count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
|
||||
level = itemInfo.level + 1;
|
||||
|
||||
|
||||
itemInfo.children = [];
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
|
||||
childItemInfo = itemInfosForItems[[childItem UID]];
|
||||
|
||||
|
||||
if (!childItemInfo)
|
||||
{
|
||||
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
|
||||
itemInfosForItems[[childItem UID]] = childItemInfo;
|
||||
}
|
||||
|
||||
|
||||
itemInfo.children[index] = childItem;
|
||||
|
||||
|
||||
var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
|
||||
|
||||
|
||||
childItemInfo.parent = anItem;
|
||||
childItemInfo.level = level;
|
||||
descendants = descendants.concat(childDescendants);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
itemInfo.weight = descendants.length;
|
||||
|
||||
|
||||
if (!isIntermediate)
|
||||
{
|
||||
// row = -1 is the root item, so just go to row 0 since it is ignored.
|
||||
var index = MAX(itemInfo.row, 0),
|
||||
itemsForRows = _itemsForRows;
|
||||
|
||||
|
||||
descendants.unshift(index, weight);
|
||||
|
||||
|
||||
itemsForRows.splice.apply(itemsForRows, descendants);
|
||||
|
||||
|
||||
var count = itemsForRows.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
itemInfosForItems[[itemsForRows[index] UID]].row = index;
|
||||
|
||||
|
||||
var deltaWeight = itemInfo.weight - weight;
|
||||
|
||||
|
||||
if (deltaWeight !== 0)
|
||||
{
|
||||
var parent = itemInfo.parent;
|
||||
|
||||
|
||||
while (parent)
|
||||
{
|
||||
var parentItemInfo = itemInfosForItems[[parent UID]];
|
||||
|
||||
|
||||
parentItemInfo.weight += deltaWeight;
|
||||
parent = parentItemInfo.parent;
|
||||
}
|
||||
|
||||
|
||||
if (anItem)
|
||||
_rootItemInfo.weight += deltaWeight;
|
||||
}
|
||||
@@ -1003,16 +1043,16 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
{
|
||||
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_))
|
||||
return NO;
|
||||
|
||||
|
||||
var rowIndexes = [];
|
||||
[theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil];
|
||||
|
||||
|
||||
var rowIndex = [rowIndexes count],
|
||||
items = [];
|
||||
|
||||
|
||||
while (rowIndex--)
|
||||
[items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]];
|
||||
|
||||
|
||||
return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard];
|
||||
}
|
||||
|
||||
@@ -1020,15 +1060,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
{
|
||||
if (_outlineView._shouldRetargetChildIndex)
|
||||
return _outlineView._retargedChildIndex;
|
||||
|
||||
|
||||
var childIndex = CPNotFound;
|
||||
|
||||
|
||||
if (theDropOperation === CPTableViewDropAbove)
|
||||
{
|
||||
var parentItem = [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset],
|
||||
itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo,
|
||||
children = itemInfo.children;
|
||||
|
||||
|
||||
childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]];
|
||||
|
||||
if (childIndex === CPNotFound)
|
||||
@@ -1043,12 +1083,12 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset
|
||||
{
|
||||
if (theDropOperation === CPTableViewDropAbove)
|
||||
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
|
||||
|
||||
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
|
||||
|
||||
return [_outlineView itemAtRow:theRow];
|
||||
}
|
||||
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo
|
||||
proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation
|
||||
{
|
||||
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_))
|
||||
@@ -1069,14 +1109,14 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id <CPDraggingInfo>)theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation
|
||||
{
|
||||
{
|
||||
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_))
|
||||
return NO;
|
||||
|
||||
var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil],
|
||||
parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location];
|
||||
childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location];
|
||||
|
||||
|
||||
_outlineView._retargetedItem = nil;
|
||||
_outlineView._shouldRetargetItem = NO;
|
||||
|
||||
@@ -1106,15 +1146,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
- (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow
|
||||
{
|
||||
var dataView = nil;
|
||||
|
||||
|
||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
|
||||
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
|
||||
dataViewForTableColumn:theTableColumn
|
||||
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
|
||||
dataViewForTableColumn:theTableColumn
|
||||
item:[_outlineView itemAtRow:theRow]];
|
||||
|
||||
if (!dataView)
|
||||
dataView = [theTableColumn dataViewForRow:theRow];
|
||||
|
||||
dataView = [theTableColumn dataViewForRow:theRow];
|
||||
|
||||
return dataView;
|
||||
}
|
||||
|
||||
@@ -1122,7 +1162,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
{
|
||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_))
|
||||
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -1205,13 +1245,34 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
CGContextAddLineToPoint(context, 9.0, 0.0);
|
||||
CGContextAddLineToPoint(context, 4.5, 8.0);
|
||||
CGContextAddLineToPoint(context, 0.0, 0.0);
|
||||
|
||||
CGContextClosePath(context);
|
||||
var isHighlighted = [self hasThemeState:CPThemeStateHighlighted];
|
||||
var color = [self hasThemeState:CPThemeStateSelected] ? (isHighlighted ? [CPColor lightGrayColor] : [CPColor whiteColor]) : (isHighlighted ? [CPColor blackColor] : [CPColor grayColor]);
|
||||
|
||||
CGContextSetFillColor(context, color);
|
||||
CGContextClosePath(context);
|
||||
CGContextSetFillColor(context,
|
||||
colorForDisclosureTriangle([self hasThemeState:CPThemeStateSelected],
|
||||
[self hasThemeState:CPThemeStateHighlighted]));
|
||||
CGContextFillPath(context);
|
||||
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0.0, 0.0);
|
||||
if(_angle === 0.0) {
|
||||
CGContextAddLineToPoint(context, 4.5, 8.0);
|
||||
CGContextAddLineToPoint(context, 9.0, 0.0);
|
||||
} else {
|
||||
CGContextAddLineToPoint(context, 4.5, 8.0);
|
||||
}
|
||||
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.8]);
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var colorForDisclosureTriangle = function(isSelected, isHighlighted) {
|
||||
return isSelected
|
||||
? (isHighlighted
|
||||
? [CPColor colorWithCalibratedWhite:0.9 alpha: 1.0]
|
||||
: [CPColor colorWithCalibratedWhite:1.0 alpha: 1.0])
|
||||
: (isHighlighted
|
||||
? [CPColor colorWithCalibratedWhite:0.4 alpha: 1.0]
|
||||
: [CPColor colorWithCalibratedWhite:0.5 alpha: 1.0]);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ var VISIBLE_MARGIN = 7.0;
|
||||
|
||||
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPPopUpButton
|
||||
|
||||
@@ -42,7 +42,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
{
|
||||
int _selectedIndex;
|
||||
CPRectEdge _preferredEdge;
|
||||
|
||||
|
||||
CPMenu _menu;
|
||||
}
|
||||
|
||||
@@ -60,21 +60,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_selectedIndex = CPNotFound;
|
||||
_preferredEdge = CPMaxYEdge;
|
||||
|
||||
|
||||
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
||||
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
|
||||
[self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"];
|
||||
|
||||
|
||||
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
|
||||
|
||||
[self setPullsDown:shouldPullDown];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
{
|
||||
var index = 0,
|
||||
count = [titles count];
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
[self addItemWithTitle:titles[index]];
|
||||
}
|
||||
@@ -159,11 +159,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
{
|
||||
var items = [self itemArray],
|
||||
count = [items count];
|
||||
|
||||
|
||||
while (count--)
|
||||
if ([items[count] title] == aTitle)
|
||||
[self removeItemAtIndex:count];
|
||||
|
||||
|
||||
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
- (void)removeAllItems
|
||||
{
|
||||
var count = [_menu numberOfItems];
|
||||
|
||||
|
||||
while (count--)
|
||||
[_menu removeItemAtIndex:0];
|
||||
}
|
||||
@@ -206,7 +206,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
{
|
||||
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
|
||||
return nil;
|
||||
|
||||
|
||||
return [_menu itemAtIndex:_selectedIndex];
|
||||
}
|
||||
|
||||
@@ -253,15 +253,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
{
|
||||
if (_selectedIndex == anIndex)
|
||||
return;
|
||||
|
||||
|
||||
if (_selectedIndex >= 0 && ![self pullsDown])
|
||||
[[self selectedItem] setState:CPOffState];
|
||||
|
||||
|
||||
_selectedIndex = anIndex;
|
||||
|
||||
if (_selectedIndex >= 0 && ![self pullsDown])
|
||||
[[self selectedItem] setState:CPOnState];
|
||||
|
||||
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
|
||||
if (_menu)
|
||||
{
|
||||
[defaultCenter
|
||||
@@ -330,7 +330,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
}
|
||||
|
||||
_menu = aMenu;
|
||||
|
||||
|
||||
if (_menu)
|
||||
{
|
||||
[defaultCenter
|
||||
@@ -338,20 +338,20 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
selector:@selector(menuDidAddItem:)
|
||||
name:CPMenuDidAddItemNotification
|
||||
object:_menu];
|
||||
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(menuDidChangeItem:)
|
||||
name:CPMenuDidChangeItemNotification
|
||||
object:_menu];
|
||||
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(menuDidRemoveItem:)
|
||||
name:CPMenuDidRemoveItemNotification
|
||||
object:_menu];
|
||||
}
|
||||
|
||||
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
@@ -396,12 +396,13 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
{
|
||||
var titles = [],
|
||||
items = [self itemArray],
|
||||
|
||||
index = 0,
|
||||
count = [items count];
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
items.push([items[index] title]);
|
||||
titles.push([items[index] title]);
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -519,14 +520,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
else
|
||||
{
|
||||
var index = [self indexOfItemWithTitle:aTitle];
|
||||
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
[self addItemWithTitle:aTitle];
|
||||
|
||||
|
||||
index = [self numberOfItems] - 1;
|
||||
}
|
||||
|
||||
|
||||
[self selectItemAtIndex:index];
|
||||
}
|
||||
}
|
||||
@@ -554,7 +555,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
if ([self pullsDown])
|
||||
{
|
||||
var items = [_menu itemArray];
|
||||
|
||||
|
||||
if ([items count] > 0)
|
||||
item = items[0];
|
||||
}
|
||||
@@ -573,22 +574,22 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
- (void)menuDidAddItem:(CPNotification)aNotification
|
||||
{
|
||||
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
|
||||
|
||||
|
||||
if (_selectedIndex < 0)
|
||||
[self selectItemAtIndex:0];
|
||||
|
||||
|
||||
else if (index == _selectedIndex)
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
|
||||
|
||||
else if (index < _selectedIndex)
|
||||
++_selectedIndex;
|
||||
|
||||
|
||||
if (index == 0 && [self pullsDown])
|
||||
{
|
||||
var items = [_menu itemArray];
|
||||
|
||||
|
||||
[items[0] setHidden:YES];
|
||||
|
||||
|
||||
if (items.length > 0)
|
||||
[items[1] setHidden:NO];
|
||||
}
|
||||
@@ -613,10 +614,10 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
if ([self pullsDown] && index != 0)
|
||||
return;
|
||||
|
||||
|
||||
if (![self pullsDown] && index != _selectedIndex)
|
||||
return;
|
||||
|
||||
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
@@ -627,7 +628,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
- (void)menuDidRemoveItem:(CPNotification)aNotification
|
||||
{
|
||||
var numberOfItems = [self numberOfItems];
|
||||
|
||||
|
||||
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
|
||||
[self selectItemAtIndex:numberOfItems - 1];
|
||||
else
|
||||
@@ -737,7 +738,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
// Nothing is currently selected
|
||||
@@ -746,7 +747,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
|
||||
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -758,7 +759,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
|
||||
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
|
||||
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
|
||||
}
|
||||
|
||||
@@ -22,23 +22,23 @@
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
|
||||
CPDeleteKeyCode = 8;
|
||||
CPTabKeyCode = 9;
|
||||
CPReturnKeyCode = 13;
|
||||
CPEscapeKeyCode = 27;
|
||||
CPSpaceKeyCode = 32;
|
||||
CPPageUpKeyCode = 33;
|
||||
CPPageDownKeyCode = 34;
|
||||
CPLeftArrowKeyCode = 37;
|
||||
CPUpArrowKeyCode = 38;
|
||||
CPRightArrowKeyCode = 39;
|
||||
CPDownArrowKeyCode = 40;
|
||||
CPDeleteKeyCode = 8;
|
||||
CPTabKeyCode = 9;
|
||||
CPReturnKeyCode = 13;
|
||||
CPEscapeKeyCode = 27;
|
||||
CPSpaceKeyCode = 32;
|
||||
CPPageUpKeyCode = 33;
|
||||
CPPageDownKeyCode = 34;
|
||||
CPLeftArrowKeyCode = 37;
|
||||
CPUpArrowKeyCode = 38;
|
||||
CPRightArrowKeyCode = 39;
|
||||
CPDownArrowKeyCode = 40;
|
||||
CPDeleteForwardKeyCode = 46;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPResponder
|
||||
|
||||
|
||||
Subclasses of CPResonder can be part of the responder chain.
|
||||
*/
|
||||
@implementation CPResponder : CPObject
|
||||
@@ -106,39 +106,36 @@ CPDownArrowKeyCode = 40;
|
||||
{
|
||||
var event = events[index];
|
||||
|
||||
switch([event keyCode])
|
||||
switch([[event characters] characterAtIndex:0])
|
||||
{
|
||||
case CPPageUpKeyCode: [self doCommandBySelector:@selector(pageUp:)];
|
||||
break;
|
||||
case CPPageDownKeyCode: [self doCommandBySelector:@selector(pageDown:)];
|
||||
break;
|
||||
case CPLeftArrowKeyCode: [self doCommandBySelector:@selector(moveLeft:)];
|
||||
break;
|
||||
case CPRightArrowKeyCode: [self doCommandBySelector:@selector(moveRight:)];
|
||||
break;
|
||||
case CPUpArrowKeyCode: [self doCommandBySelector:@selector(moveUp:)];
|
||||
break;
|
||||
case CPDownArrowKeyCode: [self doCommandBySelector:@selector(moveDown:)];
|
||||
break;
|
||||
case CPDeleteKeyCode: [self doCommandBySelector:@selector(deleteBackward:)];
|
||||
break;
|
||||
case CPReturnKeyCode:
|
||||
case 3: [self doCommandBySelector:@selector(insertLineBreak:)];
|
||||
break;
|
||||
|
||||
case CPEscapeKeyCode: [self doCommandBySelector:@selector(cancel:)];
|
||||
break;
|
||||
case CPPageUpFunctionKey: [self doCommandBySelector:@selector(pageUp:)];
|
||||
break;
|
||||
case CPPageDownFunctionKey: [self doCommandBySelector:@selector(pageDown:)];
|
||||
break;
|
||||
case CPLeftArrowFunctionKey: [self doCommandBySelector:@selector(moveLeft:)];
|
||||
break;
|
||||
case CPRightArrowFunctionKey: [self doCommandBySelector:@selector(moveRight:)];
|
||||
break;
|
||||
case CPUpArrowFunctionKey: [self doCommandBySelector:@selector(moveUp:)];
|
||||
break;
|
||||
case CPDownArrowFunctionKey: [self doCommandBySelector:@selector(moveDown:)];
|
||||
break;
|
||||
case CPDeleteCharacter: [self doCommandBySelector:@selector(deleteBackward:)];
|
||||
break;
|
||||
case CPCarriageReturnCharacter:
|
||||
case CPNewlineCharacter: [self doCommandBySelector:@selector(insertLineBreak:)];
|
||||
break;
|
||||
|
||||
case CPTabKeyCode: var shift = [event modifierFlags] & CPShiftKeyMask;
|
||||
case CPEscapeFunctionKey: [self doCommandBySelector:@selector(cancel:)];
|
||||
break;
|
||||
|
||||
if (!shift)
|
||||
[self doCommandBySelector:@selector(insertTab:)];
|
||||
else
|
||||
[self doCommandBySelector:@selector(insertBackTab:)];
|
||||
case CPTabCharacter: if (!([event modifierFlags] & CPShiftKeyMask))
|
||||
[self doCommandBySelector:@selector(insertTab:)];
|
||||
else
|
||||
[self doCommandBySelector:@selector(insertBackTab:)];
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
default: [self insertText:[event characters]];
|
||||
default: [self insertText:[event characters]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,7 +312,7 @@ CPDownArrowKeyCode = 40;
|
||||
if([self respondsToSelector:aSelector])
|
||||
{
|
||||
[self performSelector:aSelector withObject:anObject];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -366,10 +363,10 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "CoreGraphics/CGGeometry.h"
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPScrollView
|
||||
|
||||
@@ -44,12 +44,12 @@
|
||||
BOOL _hasVerticalScroller;
|
||||
BOOL _hasHorizontalScroller;
|
||||
BOOL _autohidesScrollers;
|
||||
|
||||
|
||||
CPScroller _verticalScroller;
|
||||
CPScroller _horizontalScroller;
|
||||
|
||||
|
||||
int _recursionCount;
|
||||
|
||||
|
||||
float _verticalLineScroll;
|
||||
float _verticalPageScroll;
|
||||
float _horizontalLineScroll;
|
||||
@@ -158,11 +158,11 @@
|
||||
|
||||
if (_recursionCount > 5)
|
||||
return;
|
||||
|
||||
|
||||
++_recursionCount;
|
||||
|
||||
var documentView = [self documentView];
|
||||
|
||||
|
||||
if (!documentView)
|
||||
{
|
||||
if (_autohidesScrollers)
|
||||
@@ -250,7 +250,7 @@
|
||||
[_verticalScroller setFloatValue:0.0];
|
||||
[_verticalScroller setKnobProportion:1.0];
|
||||
}
|
||||
|
||||
|
||||
if (shouldShowHorizontalScroller)
|
||||
{
|
||||
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
|
||||
@@ -279,13 +279,13 @@
|
||||
{
|
||||
if (_horizontalScroller === aScroller)
|
||||
return;
|
||||
|
||||
|
||||
[_horizontalScroller removeFromSuperview];
|
||||
[_horizontalScroller setTarget:nil];
|
||||
[_horizontalScroller setAction:nil];
|
||||
|
||||
|
||||
_horizontalScroller = aScroller;
|
||||
|
||||
|
||||
[_horizontalScroller setTarget:self];
|
||||
[_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
|
||||
|
||||
@@ -339,13 +339,13 @@
|
||||
{
|
||||
if (_verticalScroller === aScroller)
|
||||
return;
|
||||
|
||||
|
||||
[_verticalScroller removeFromSuperview];
|
||||
[_verticalScroller setTarget:nil];
|
||||
[_verticalScroller setAction:nil];
|
||||
|
||||
|
||||
_verticalScroller = aScroller;
|
||||
|
||||
|
||||
[_verticalScroller setTarget:self];
|
||||
[_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
|
||||
|
||||
@@ -403,7 +403,7 @@
|
||||
return;
|
||||
|
||||
_autohidesScrollers = autohidesScrollers;
|
||||
|
||||
|
||||
[self reflectScrolledClipView:_contentView];
|
||||
}
|
||||
|
||||
@@ -480,30 +480,30 @@
|
||||
/* @ignore */
|
||||
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
|
||||
{
|
||||
var value = [aScroller floatValue],
|
||||
documentFrame = [[_contentView documentView] frame];
|
||||
var value = [aScroller floatValue],
|
||||
documentFrame = [[_contentView documentView] frame],
|
||||
contentBounds = [_contentView bounds];
|
||||
|
||||
switch ([_verticalScroller hitPart])
|
||||
{
|
||||
case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerKnobSlot:
|
||||
case CPScrollerKnob:
|
||||
// We want integral bounds!
|
||||
default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
|
||||
}
|
||||
|
||||
|
||||
[_contentView scrollToPoint:contentBounds.origin];
|
||||
}
|
||||
|
||||
@@ -513,21 +513,21 @@
|
||||
var value = [aScroller floatValue],
|
||||
documentFrame = [[self documentView] frame],
|
||||
contentBounds = [_contentView bounds];
|
||||
|
||||
|
||||
switch ([_horizontalScroller hitPart])
|
||||
{
|
||||
case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
|
||||
break;
|
||||
|
||||
|
||||
case CPScrollerKnobSlot:
|
||||
case CPScrollerKnob:
|
||||
// We want integral bounds!
|
||||
@@ -668,7 +668,7 @@
|
||||
*/
|
||||
- (void)scrollWheel:(CPEvent)anEvent
|
||||
{
|
||||
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] * _horizontalLineScroll
|
||||
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] * _horizontalLineScroll
|
||||
deltaY:[anEvent deltaY] * _verticalLineScroll];
|
||||
}
|
||||
|
||||
@@ -771,7 +771,7 @@ var CPScrollViewContentViewKey = "CPScrollViewContentView",
|
||||
|
||||
_horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
|
||||
_horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
|
||||
|
||||
|
||||
_contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
|
||||
_headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
|
||||
|
||||
@@ -793,25 +793,25 @@ var CPScrollViewContentViewKey = "CPScrollViewContentView",
|
||||
// Do to the anything goes nature of decoding, our subviews may not exist yet, so layout at the end of the run loop when we're sure everything is in a correct state.
|
||||
[[CPRunLoop currentRunLoop] performSelector:@selector(reflectScrolledClipView:) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
|
||||
[aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
|
||||
[aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey];
|
||||
|
||||
[aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
|
||||
[aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
|
||||
|
||||
|
||||
[aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
|
||||
[aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
|
||||
[aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
|
||||
[aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
|
||||
|
||||
|
||||
[aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
|
||||
[aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
|
||||
[aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
|
||||
|
||||
@@ -581,7 +581,7 @@ var CPSearchFieldSearchImage = nil,
|
||||
|
||||
- (void)_sendPartialString
|
||||
{
|
||||
[[self target] performSelector:[self action] withObject:self];
|
||||
[self _sendAction:self];
|
||||
}
|
||||
|
||||
- (void)_searchFieldCancel:(id)sender
|
||||
|
||||
@@ -362,14 +362,14 @@ CPCircularSlider = 1;
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
|
||||
{
|
||||
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
@import "CPColorPicker.j"
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
|
||||
/*
|
||||
@ignore
|
||||
*/
|
||||
|
||||
@@ -152,7 +152,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
_isPaneSplitter = shouldBePaneSplitter;
|
||||
|
||||
if(_DOMDividerElements[_drawingDivider])
|
||||
[self _setupDOMDivider]
|
||||
[self _setupDOMDivider];
|
||||
|
||||
// The divider changes size when pane splitter mode is toggled, so the
|
||||
// subviews need to change size too.
|
||||
|
||||
@@ -50,7 +50,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
CPSortDescriptor _sortDescriptorPrototype;
|
||||
BOOL _isHidden;
|
||||
CPString _headerToolTip;
|
||||
|
||||
|
||||
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
|
||||
}
|
||||
|
||||
@@ -72,18 +72,23 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
_maxWidth = 1000000.0;
|
||||
_resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask;
|
||||
_disableResizingPosting = NO;
|
||||
|
||||
|
||||
[self setIdentifier:anIdentifier];
|
||||
|
||||
var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[self setHeaderView:header];
|
||||
|
||||
|
||||
var textDataView = [CPTextField new];
|
||||
[textDataView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[textDataView setValue:[CPColor colorWithHexString:@"333333"] forThemeAttribute:@"text-color"];
|
||||
|
||||
[textDataView setValue:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0]
|
||||
forThemeAttribute:"text-color"];
|
||||
|
||||
[textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateSelectedDataView];
|
||||
[textDataView setValue:[CPFont boldSystemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateSelectedDataView];
|
||||
[textDataView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[textDataView setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateSelectedDataView];
|
||||
[textDataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
|
||||
[textDataView setValue:CGInsetMake(0.0, 0.0, 0.0, 5.0) forThemeAttribute:@"content-inset"];
|
||||
|
||||
[self setDataView:textDataView];
|
||||
}
|
||||
|
||||
@@ -123,19 +128,19 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
{
|
||||
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self],
|
||||
dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex;
|
||||
|
||||
|
||||
if (dirtyTableColumnRangeIndex < 0)
|
||||
tableView._dirtyTableColumnRangeIndex = index;
|
||||
else
|
||||
tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex);
|
||||
|
||||
|
||||
var rows = tableView._exposedRows,
|
||||
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
|
||||
|
||||
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
|
||||
|
||||
// FIXME: Would be faster with some sort of -setNeedsDisplayInColumns: that updates a dirtyTableColumnForDisplay cache; then marked columns would relayout their data views at display time.
|
||||
[tableView _layoutDataViewsInRows:rows columns:columns];
|
||||
[tableView tile];
|
||||
|
||||
|
||||
if (!_disableResizingPosting)
|
||||
[self _postDidResizeNotificationWithOldWidth:oldWidth];
|
||||
}
|
||||
@@ -292,7 +297,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
// unarchive the data view cache
|
||||
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
|
||||
newDataView.identifier = dataViewUID;
|
||||
|
||||
|
||||
return newDataView;
|
||||
}
|
||||
|
||||
@@ -325,7 +330,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns YES if the user can edit cells associated with the receiver by double-clicking the
|
||||
Returns YES if the user can edit cells associated with the receiver by double-clicking the
|
||||
column in the NSTableView, NO otherwise.
|
||||
*/
|
||||
- (BOOL)isEditable
|
||||
@@ -366,7 +371,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
//Setting Tool Tips
|
||||
|
||||
/*
|
||||
Sets the tooltip string that is displayed when the cursor pauses over the
|
||||
Sets the tooltip string that is displayed when the cursor pauses over the
|
||||
header cell of the receiver.
|
||||
*/
|
||||
- (void)setHeaderToolTip:(CPString)aToolTip
|
||||
@@ -389,6 +394,73 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTableColumn (Bindings)
|
||||
|
||||
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
|
||||
{
|
||||
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
|
||||
|
||||
if (![aBinding isEqual:@"someListOfExceptedBindings(notAcceptedBindings)"])
|
||||
[[self tableView] _establishBindingsIfUnbound:anObject];
|
||||
}
|
||||
|
||||
- (void)prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
|
||||
{
|
||||
var bindingsDictionary = [CPKeyValueBinding allBindingsForObject:self],
|
||||
keys = [bindingsDictionary allKeys];
|
||||
|
||||
for (var i=0, count = [keys count]; i<count; i++)
|
||||
{
|
||||
var bindingName = keys[i],
|
||||
bindingPath = [aDataView _replacementKeyPathForBinding:bindingName],
|
||||
bindingInfo = [bindingsDictionary objectForKey:bindingName]._info,
|
||||
destination = [bindingInfo objectForKey:CPObservedObjectKey],
|
||||
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
|
||||
dotIndex = keyPath.lastIndexOf("."),
|
||||
value;
|
||||
|
||||
if (dotIndex === CPNotFound)
|
||||
value = [[destination valueForKeyPath:keyPath] objectAtIndex:aRow];
|
||||
else
|
||||
{
|
||||
/*
|
||||
Optimize the prototypical use case where the key path describes a value
|
||||
in an array. Without this optimization, we call CPArray's valueForKey
|
||||
which generates as many values as objects in the array, of which we then
|
||||
pick one and throw away the rest.
|
||||
|
||||
The optimization is to get the array and access the value directly. This
|
||||
turns the operation into a single access regardless of how long the model
|
||||
array is.
|
||||
*/
|
||||
|
||||
var firstPart = keyPath.substring(0, dotIndex),
|
||||
secondPart = keyPath.substring(dotIndex+1),
|
||||
firstValue = [destination valueForKeyPath:firstPart];
|
||||
|
||||
if ([firstValue isKindOfClass:CPArray])
|
||||
value = [[firstValue objectAtIndex:aRow] valueForKeyPath:secondPart];
|
||||
else
|
||||
value = [[firstValue valueForKeyPath:secondPart] objectAtIndex:aRow];
|
||||
}
|
||||
|
||||
// console.log(bindingName+" : "+keyPath+" : "+aRow+" : "+[[destination valueForKeyPath:keyPath] objectAtIndex:aRow]);
|
||||
[aDataView setValue:value forKey:bindingPath];
|
||||
}
|
||||
}
|
||||
|
||||
//- (void)objectValue
|
||||
//{
|
||||
// return nil;
|
||||
//}
|
||||
|
||||
- (void)setValue:(CPArray)content
|
||||
{
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||
CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
|
||||
CPTableColumnDataViewKey = @"CPTableColumnDataViewKey",
|
||||
@@ -398,6 +470,7 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey",
|
||||
CPTableColumnIsHiddenkey = @"CPTableColumnIsHiddenKey",
|
||||
CPSortDescriptorPrototypeKey = @"CPSortDescriptorPrototypeKey";
|
||||
CPTableColumnIsHiddenkey = @"CPTableColumnIsHiddenKey";
|
||||
|
||||
@implementation CPTableColumn (CPCoding)
|
||||
|
||||
|
||||
@@ -42,11 +42,13 @@
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_textField = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(5, 1, CGRectGetWidth([self bounds]) - 10, CGRectGetHeight([self bounds]) - 1)];
|
||||
_textField = [[_CPImageAndTextView alloc] initWithFrame:
|
||||
CGRectMake(5.0, 0.0, CGRectGetWidth([self bounds]) - 10.0, CGRectGetHeight([self bounds]))];
|
||||
|
||||
[_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||
|
||||
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[_textField setTextColor: [CPColor colorWithHexString: @"333333"]];
|
||||
[_textField setTextColor:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0]];
|
||||
[_textField setFont:[CPFont boldSystemFontOfSize:12.0]];
|
||||
[_textField setAlignment:CPLeftTextAlignment];
|
||||
[_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
|
||||
@@ -61,13 +63,13 @@
|
||||
var themeState = [self themeState];
|
||||
|
||||
if(themeState & CPThemeStateSelected && themeState & CPThemeStateHighlighted)
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]];
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 23.0))]];
|
||||
else if (themeState & CPThemeStateSelected)
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]];
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 23.0))]];
|
||||
else if (themeState & CPThemeStateHighlighted)
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]];
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 23.0))]];
|
||||
else
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]];
|
||||
}
|
||||
|
||||
- (void)setStringValue:(CPString)string
|
||||
@@ -174,7 +176,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
|
||||
_columnOldWidth = 0.0;
|
||||
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* CPText.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Alexander Ljungberg.
|
||||
* Copyright 2010, WireLoad, LLC.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPView.j"
|
||||
|
||||
CPEnterCharacter = "\u0003";
|
||||
CPBackspaceCharacter = "\u0008";
|
||||
CPTabCharacter = "\u0009";
|
||||
CPNewlineCharacter = "\u000a";
|
||||
CPFormFeedCharacter = "\u000c";
|
||||
CPCarriageReturnCharacter = "\u000d";
|
||||
CPBackTabCharacter = "\u0019";
|
||||
CPDeleteCharacter = "\u007f";
|
||||
@@ -536,12 +536,12 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
CPTextFieldInputIsActive = NO;
|
||||
|
||||
if (document.attachEvent)
|
||||
{
|
||||
CPTextFieldCachedSelectStartFunction = nil;
|
||||
CPTextFieldCachedDragFunction = nil;
|
||||
|
||||
{
|
||||
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
||||
|
||||
CPTextFieldCachedSelectStartFunction = nil;
|
||||
CPTextFieldCachedDragFunction = nil;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -574,20 +574,46 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
// Don't track! (ever?)
|
||||
if ([self isEditable] && [self isEnabled])
|
||||
return [[self window] makeFirstResponder:self];
|
||||
else if ([self isSelectable])
|
||||
{
|
||||
if (document.attachEvent)
|
||||
{
|
||||
CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
|
||||
CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
|
||||
|
||||
[[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
|
||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
|
||||
}
|
||||
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
}
|
||||
else
|
||||
return [[self nextResponder] mouseDown:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseUp:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEditable] || ![self isEnabled])
|
||||
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
|
||||
[[self nextResponder] mouseUp:anEvent];
|
||||
else if ([self isSelectable])
|
||||
{
|
||||
if (document.attachEvent)
|
||||
{
|
||||
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
||||
|
||||
CPTextFieldCachedSelectStartFunction = nil
|
||||
CPTextFieldCachedDragFunction = nil;
|
||||
}
|
||||
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEditable] || ![self isEnabled])
|
||||
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
|
||||
[[self nextResponder] mouseDragged:anEvent];
|
||||
else if ([self isSelectable])
|
||||
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
}
|
||||
|
||||
- (void)keyUp:(CPEvent)anEvent
|
||||
|
||||
@@ -329,7 +329,11 @@ var CPToolbarConfigurationsByIdentifier = nil;
|
||||
return _itemsSortedByVisibilityPriority;
|
||||
}
|
||||
|
||||
- (void)validateVisibleToolbarItems
|
||||
/*!
|
||||
Validates the visible toolbar items by sending a validate message to
|
||||
each visible toolbar item.
|
||||
*/
|
||||
- (void)validateVisibleItems
|
||||
{
|
||||
var toolbarItems = [self visibleItems],
|
||||
count = [toolbarItems count];
|
||||
|
||||
@@ -1679,7 +1679,7 @@ setBoundsOrigin:
|
||||
var theWindow = [self window];
|
||||
|
||||
[theWindow _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
|
||||
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes]
|
||||
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
|
||||
[theWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
|
||||
|
||||
_registeredDraggedTypesArray = nil;
|
||||
|
||||
@@ -79,9 +79,9 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
|
||||
view = [self _targetView:dictionary]
|
||||
startFrame = [self _startFrame:dictionary]
|
||||
endFrame = [self _endFrame:dictionary]
|
||||
view = [self _targetView:dictionary],
|
||||
startFrame = [self _startFrame:dictionary],
|
||||
endFrame = [self _endFrame:dictionary],
|
||||
differenceFrame = _CGRectMakeZero();
|
||||
|
||||
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
|
||||
|
||||
@@ -194,13 +194,13 @@ var SHADOW_MARGIN_LEFT = 20.0,
|
||||
SHADOW_MARGIN_TOP = 10.0,
|
||||
SHADOW_MARGIN_BOTTOM = 10.0,
|
||||
SHADOW_DISTANCE = 5.0,
|
||||
|
||||
|
||||
_CPWindowShadowColor = nil;
|
||||
|
||||
|
||||
var CPWindowSaveImage = nil,
|
||||
CPWindowSavingImage = nil;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPWindow
|
||||
|
||||
@@ -213,33 +213,33 @@ var CPWindowSaveImage = nil,
|
||||
<p>A window always contains a content view which is the highest level view available for public (application) use. This view fills the area of the window inside any decoration/border. This is the only part of the window that application programmers are allowed to draw in directly.</p>
|
||||
|
||||
<p>You can convert between view coordinates and window base coordinates using the [CPView -convertPoint:fromView:], [CPView -convertPoint:toView:], [CPView -convertRect:fromView:], and [CPView -convertRect:toView:] methods with a nil view argument.
|
||||
|
||||
|
||||
@par Delegate Methods
|
||||
|
||||
|
||||
@delegate -(void)windowDidResize:(CPNotification)notification;
|
||||
Sent from the notification center when the window has been resized.
|
||||
@param notification contains information about the resize event
|
||||
|
||||
|
||||
@delegate -(CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
|
||||
Called to obtain the undo manager for a window
|
||||
@param window the window for which to return the undo manager
|
||||
@return the window's undo manager
|
||||
|
||||
|
||||
@delegate -(void)windowDidBecomeMain:(CPNotification)notification;
|
||||
Sent from the notification center when the delegate's window becomes
|
||||
the main window.
|
||||
@param notification contains information about the event
|
||||
|
||||
|
||||
@delegate -(void)windowDidResignMain:(CPNotification)notification;
|
||||
Sent from the notification center when the delegate's window has
|
||||
resigned main window status.
|
||||
@param notification contains information about the event
|
||||
|
||||
|
||||
@delegate -(void)windowDidResignKey:(CPNotification)notification;
|
||||
Sent from the notification center when the delegate's window has
|
||||
resigned key window status.
|
||||
@param notification contains information about the event
|
||||
|
||||
|
||||
@delegate -(BOOL)windowShouldClose:(id)window;
|
||||
Called when the user tries to close the window.
|
||||
@param window the window to close
|
||||
@@ -311,12 +311,12 @@ var CPWindowSaveImage = nil,
|
||||
#endif
|
||||
|
||||
unsigned _autoresizingMask;
|
||||
|
||||
|
||||
BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector;
|
||||
|
||||
BOOL _isFullPlatformWindow;
|
||||
_CPWindowFullPlatformWindowSession _fullPlatformWindowSession;
|
||||
|
||||
|
||||
CPDictionary _sheetContext;
|
||||
CPWindow _parentView;
|
||||
BOOL _isSheet;
|
||||
@@ -330,9 +330,9 @@ var CPWindowSaveImage = nil,
|
||||
{
|
||||
if (self != [CPWindow class])
|
||||
return;
|
||||
|
||||
|
||||
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
||||
|
||||
|
||||
CPWindowSavingImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(16.0, 16.0)]
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ CPTexturedBackgroundWindowMask
|
||||
- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
|
||||
@@ -393,7 +393,7 @@ CPTexturedBackgroundWindowMask
|
||||
// Set up our window number.
|
||||
_windowNumber = [CPApp._windows count];
|
||||
CPApp._windows[_windowNumber] = self;
|
||||
|
||||
|
||||
_styleMask = aStyleMask;
|
||||
|
||||
[self setLevel:CPNormalWindowLevel];
|
||||
@@ -408,15 +408,15 @@ CPTexturedBackgroundWindowMask
|
||||
[_windowView setNextResponder:self];
|
||||
|
||||
[self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
|
||||
|
||||
|
||||
// Create a generic content view.
|
||||
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
|
||||
|
||||
|
||||
_firstResponder = self;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement = document.createElement("div");
|
||||
|
||||
|
||||
_DOMElement.style.position = "absolute";
|
||||
_DOMElement.style.visibility = "visible";
|
||||
_DOMElement.style.zIndex = 0;
|
||||
@@ -442,7 +442,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -660,7 +660,7 @@ CPTexturedBackgroundWindowMask
|
||||
if (shouldAnimate)
|
||||
{
|
||||
var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
|
||||
|
||||
|
||||
[animation startAnimation];
|
||||
}
|
||||
else
|
||||
@@ -742,8 +742,10 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)orderFront:(id)aSender
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
[_platformWindow orderFront:self];
|
||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||
#endif
|
||||
|
||||
if (_firstResponder === self || !_firstResponder)
|
||||
[self makeFirstResponder:[self initialFirstResponder]];
|
||||
@@ -771,13 +773,17 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)orderOut:(id)aSender
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
if ([self _sharesChromeWithPlatformWindow])
|
||||
[_platformWindow orderOut:self];
|
||||
#endif
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
|
||||
[_delegate windowWillClose:self];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
|
||||
#endif
|
||||
|
||||
[self _updateMainAndKeyWindows];
|
||||
}
|
||||
@@ -789,7 +795,9 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
[_platformWindow order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]];
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -874,12 +882,12 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (_contentView)
|
||||
[_contentView removeFromSuperview];
|
||||
|
||||
|
||||
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
|
||||
|
||||
|
||||
_contentView = aView;
|
||||
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
|
||||
|
||||
|
||||
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
[_windowView addSubview:_contentView];
|
||||
}
|
||||
@@ -935,24 +943,24 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (CGSizeEqualToSize(_minSize, aSize))
|
||||
return;
|
||||
|
||||
|
||||
_minSize = CGSizeCreateCopy(aSize);
|
||||
|
||||
var size = CGSizeMakeCopy([self frame].size),
|
||||
needsFrameChange = NO;
|
||||
|
||||
|
||||
if (size.width < _minSize.width)
|
||||
{
|
||||
size.width = _minSize.width;
|
||||
needsFrameChange = YES;
|
||||
}
|
||||
|
||||
|
||||
if (size.height < _minSize.height)
|
||||
{
|
||||
size.height = _minSize.height;
|
||||
needsFrameChange = YES;
|
||||
}
|
||||
|
||||
|
||||
if (needsFrameChange)
|
||||
[self setFrameSize:size];
|
||||
}
|
||||
@@ -975,24 +983,24 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (CGSizeEqualToSize(_maxSize, aSize))
|
||||
return;
|
||||
|
||||
|
||||
_maxSize = CGSizeCreateCopy(aSize);
|
||||
|
||||
var size = CGSizeMakeCopy([self frame].size),
|
||||
needsFrameChange = NO;
|
||||
|
||||
|
||||
if (size.width > _maxSize.width)
|
||||
{
|
||||
size.width = _maxSize.width;
|
||||
needsFrameChange = YES;
|
||||
}
|
||||
|
||||
|
||||
if (size.height > _maxSize.height)
|
||||
{
|
||||
size.height = _maxSize.height;
|
||||
needsFrameChange = YES;
|
||||
}
|
||||
|
||||
|
||||
if (needsFrameChange)
|
||||
[self setFrameSize:size];
|
||||
}
|
||||
@@ -1033,10 +1041,10 @@ CPTexturedBackgroundWindowMask
|
||||
if (_hasShadow && !_shadowView)
|
||||
{
|
||||
var bounds = [_windowView bounds];
|
||||
|
||||
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE,
|
||||
|
||||
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE,
|
||||
SHADOW_MARGIN_LEFT + CGRectGetWidth(bounds) + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_TOP + CGRectGetHeight(bounds) + SHADOW_MARGIN_BOTTOM)];
|
||||
|
||||
|
||||
if (!_CPWindowShadowColor)
|
||||
{
|
||||
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
||||
@@ -1059,7 +1067,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[_shadowView setBackgroundColor:_CPWindowShadowColor];
|
||||
[_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
|
||||
#endif
|
||||
@@ -1125,7 +1133,7 @@ CPTexturedBackgroundWindowMask
|
||||
selector:@selector(windowDidBecomeKey:)
|
||||
name:CPWindowDidBecomeKeyNotification
|
||||
object:self];
|
||||
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
@@ -1221,7 +1229,7 @@ CPTexturedBackgroundWindowMask
|
||||
if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
|
||||
{
|
||||
_firstResponder = self;
|
||||
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -1274,9 +1282,9 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)setTitle:(CPString)aTitle
|
||||
{
|
||||
_title = aTitle;
|
||||
|
||||
|
||||
[_windowView setTitle:aTitle];
|
||||
|
||||
|
||||
[self _synchronizeMenuBarTitleWithWindowTitle];
|
||||
}
|
||||
|
||||
@@ -1528,7 +1536,7 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)makeKeyAndOrderFront:(id)aSender
|
||||
{
|
||||
[self orderFront:self];
|
||||
|
||||
|
||||
[self makeKeyWindow];
|
||||
[self makeMainWindow];
|
||||
}
|
||||
@@ -1592,7 +1600,7 @@ CPTexturedBackgroundWindowMask
|
||||
if (!pasteboardTypes)
|
||||
return;
|
||||
|
||||
[_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes]
|
||||
[_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes];
|
||||
|
||||
if ([_inclusiveRegisteredDraggedTypes count] === 0)
|
||||
_inclusiveRegisteredDraggedTypes = nil;
|
||||
@@ -1623,7 +1631,7 @@ CPTexturedBackgroundWindowMask
|
||||
return;
|
||||
|
||||
[self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
|
||||
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes]
|
||||
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
|
||||
[self _noteRegisteredDraggedTypes:_registeredDraggedTypes];
|
||||
|
||||
_registeredDraggedTypesArray = nil;
|
||||
@@ -1636,7 +1644,7 @@ CPTexturedBackgroundWindowMask
|
||||
- (CPArray)registeredDraggedTypes
|
||||
{
|
||||
if (!_registeredDraggedTypesArray)
|
||||
_registeredDraggedTypesArray = [_registeredDraggedTypes allObjects]
|
||||
_registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
|
||||
|
||||
return _registeredDraggedTypesArray;
|
||||
}
|
||||
@@ -1662,9 +1670,9 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (_isDocumentEdited == isDocumentEdited)
|
||||
return;
|
||||
|
||||
|
||||
_isDocumentEdited = isDocumentEdited;
|
||||
|
||||
|
||||
[CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
|
||||
|
||||
[_windowView setDocumentEdited:isDocumentEdited];
|
||||
@@ -1682,11 +1690,11 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (_isDocumentSaving == isDocumentSaving)
|
||||
return;
|
||||
|
||||
|
||||
_isDocumentSaving = isDocumentSaving;
|
||||
|
||||
|
||||
[self _synchronizeSaveMenuWithDocumentSaving];
|
||||
|
||||
|
||||
[_windowView windowDidChangeDocumentSaving];
|
||||
}
|
||||
|
||||
@@ -1703,16 +1711,16 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
var mainMenu = [CPApp mainMenu],
|
||||
index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
|
||||
|
||||
|
||||
if (index == CPNotFound)
|
||||
return;
|
||||
|
||||
|
||||
var item = [mainMenu itemAtIndex:index];
|
||||
|
||||
|
||||
if (_isDocumentSaving)
|
||||
{
|
||||
CPWindowSaveImage = [item image];
|
||||
|
||||
|
||||
[item setTitle:@"Saving..."];
|
||||
[item setImage:CPWindowSavingImage];
|
||||
[item setEnabled:NO];
|
||||
@@ -1802,7 +1810,7 @@ CPTexturedBackgroundWindowMask
|
||||
if (![_delegate windowShouldClose:self])
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Only check self is delegate does NOT implement this. This also ensures this when delegate == self (returns true).
|
||||
else if ([self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self])
|
||||
return;
|
||||
@@ -1812,8 +1820,8 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
var index = [documents indexOfObject:[_windowController document]];
|
||||
|
||||
[documents[index] shouldCloseWindowController:_windowController
|
||||
delegate:self
|
||||
[documents[index] shouldCloseWindowController:_windowController
|
||||
delegate:self
|
||||
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
|
||||
contextInfo:{documents:[documents copy], visited:0, index:index}];
|
||||
}
|
||||
@@ -1837,8 +1845,8 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
[windowController setDocument:documents[index]];
|
||||
|
||||
[documents[index] shouldCloseWindowController:_windowController
|
||||
delegate:self
|
||||
[documents[index] shouldCloseWindowController:_windowController
|
||||
delegate:self
|
||||
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
|
||||
contextInfo:context];
|
||||
}
|
||||
@@ -1875,7 +1883,7 @@ CPTexturedBackgroundWindowMask
|
||||
// FIXME: Also check if we can resize and titlebar.
|
||||
if ([self isVisible])
|
||||
return YES;
|
||||
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -1997,25 +2005,25 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (_toolbar === aToolbar)
|
||||
return;
|
||||
|
||||
|
||||
// If this has an owner, dump it!
|
||||
[[aToolbar _window] setToolbar:nil];
|
||||
|
||||
|
||||
// This is no longer out toolbar.
|
||||
[_toolbar _setWindow:nil];
|
||||
|
||||
|
||||
_toolbar = aToolbar;
|
||||
|
||||
|
||||
// THIS is our toolbar.
|
||||
[_toolbar _setWindow:self];
|
||||
|
||||
|
||||
[self _noteToolbarChanged];
|
||||
}
|
||||
|
||||
- (void)toggleToolbarShown:(id)aSender
|
||||
{
|
||||
var toolbar = [self toolbar];
|
||||
|
||||
|
||||
[toolbar setVisible:![toolbar isVisible]];
|
||||
}
|
||||
|
||||
@@ -2031,10 +2039,10 @@ CPTexturedBackgroundWindowMask
|
||||
else
|
||||
{
|
||||
newFrame = CGRectMakeCopy([self frame]);
|
||||
|
||||
|
||||
newFrame.origin = frame.origin;
|
||||
}
|
||||
|
||||
|
||||
[self setFrame:newFrame];
|
||||
/*
|
||||
[_windowView setAnimatingToolbar:YES];
|
||||
@@ -2060,7 +2068,7 @@ CPTexturedBackgroundWindowMask
|
||||
var attachedSheet = [self attachedSheet];
|
||||
var contentRect = [[self contentView] frame],
|
||||
sheetFrame = CGRectMakeCopy([attachedSheet frame]);
|
||||
|
||||
|
||||
sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
|
||||
sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
|
||||
|
||||
@@ -2072,8 +2080,8 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
var sheetFrame = [aSheet frame];
|
||||
|
||||
_sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
|
||||
|
||||
_sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
|
||||
|
||||
[self _attachSheetWindow:aSheet];
|
||||
}
|
||||
|
||||
@@ -2083,12 +2091,12 @@ CPTexturedBackgroundWindowMask
|
||||
var sheetFrame = [aSheet frame],
|
||||
frame = [self frame],
|
||||
sheetContent = [aSheet contentView];
|
||||
|
||||
|
||||
[self _setUpMasksForView:sheetContent];
|
||||
|
||||
|
||||
aSheet._isSheet = YES;
|
||||
aSheet._parentView = self;
|
||||
|
||||
|
||||
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width)/2),
|
||||
originy = frame.origin.y + [[self contentView] frame].origin.y,
|
||||
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
|
||||
@@ -2096,7 +2104,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
|
||||
[CPApp runModalForWindow:aSheet];
|
||||
|
||||
|
||||
[aSheet orderFront:self];
|
||||
[aSheet setFrame:startFrame display:YES animate:NO];
|
||||
_sheetContext["opened"] = YES;
|
||||
@@ -2104,7 +2112,7 @@ CPTexturedBackgroundWindowMask
|
||||
[aSheet _setFrame:endFrame delegate:self duration:0.2 curve:CPAnimationEaseOut];
|
||||
|
||||
// Should run the main loop here until _isAnimating = FALSE
|
||||
[aSheet becomeKeyWindow];
|
||||
[aSheet becomeKeyWindow];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
@@ -2115,9 +2123,9 @@ CPTexturedBackgroundWindowMask
|
||||
endFrame = CGRectMakeCopy(startFrame);
|
||||
|
||||
endFrame.size.height = 0;
|
||||
|
||||
|
||||
_sheetContext["frame"] = startFrame;
|
||||
|
||||
|
||||
var sheetContent = [sheet contentView];
|
||||
[self _setUpMasksForView:sheetContent];
|
||||
|
||||
@@ -2133,27 +2141,27 @@ CPTexturedBackgroundWindowMask
|
||||
return;
|
||||
|
||||
var sheetContent = [sheet contentView];
|
||||
|
||||
|
||||
if (_sheetContext["opened"] === YES)
|
||||
{
|
||||
[self _restoreMasksForView:sheetContent];
|
||||
return;
|
||||
}
|
||||
|
||||
[CPApp stopModal];
|
||||
|
||||
[CPApp stopModal];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
|
||||
|
||||
[sheet orderOut:self];
|
||||
|
||||
var lastFrame = _sheetContext["frame"];
|
||||
[sheet setFrame:lastFrame];
|
||||
|
||||
|
||||
[self _restoreMasksForView:sheetContent];
|
||||
|
||||
var delegate = _sheetContext["modalDelegate"],
|
||||
endSelector = _sheetContext["endSelector"];
|
||||
|
||||
if (delegate != nil && endSelector != nil)
|
||||
if (delegate != nil && endSelector != nil)
|
||||
objj_msgSend(delegate, endSelector, sheet, _sheetContext["returnCode"], _sheetContext["contextInfo"]);
|
||||
|
||||
_sheetContext = nil;
|
||||
@@ -2165,7 +2173,7 @@ CPTexturedBackgroundWindowMask
|
||||
var views = [aView subviews];
|
||||
|
||||
[views addObject:aView];
|
||||
|
||||
|
||||
for (var i = 0, count = [views count]; i < count; i++)
|
||||
{
|
||||
var view = [views objectAtIndex:i],
|
||||
@@ -2181,7 +2189,7 @@ CPTexturedBackgroundWindowMask
|
||||
var views = [aView subviews];
|
||||
|
||||
[views addObject:aView];
|
||||
|
||||
|
||||
for (var i = 0, count = [views count]; i < count; i++)
|
||||
{
|
||||
var view = [views objectAtIndex:i],
|
||||
@@ -2199,7 +2207,7 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (_sheetContext === nil)
|
||||
return nil;
|
||||
|
||||
|
||||
return _sheetContext["sheet"];
|
||||
}
|
||||
|
||||
@@ -2280,7 +2288,7 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)recalculateKeyViewLoop
|
||||
{
|
||||
var subviews = [];
|
||||
|
||||
|
||||
[self _appendSubviewsOf:_contentView toArray:subviews];
|
||||
|
||||
var keyViewOrder = [subviews sortedArrayUsingFunction:keyViewComparator context:_contentView],
|
||||
@@ -2288,7 +2296,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
for (var i=0; i<count; i++)
|
||||
[keyViewOrder[i] setNextKeyView:keyViewOrder[(i+1)%count]];
|
||||
|
||||
|
||||
_keyViewLoopIsDirty = NO;
|
||||
}
|
||||
|
||||
@@ -2309,7 +2317,7 @@ CPTexturedBackgroundWindowMask
|
||||
return;
|
||||
|
||||
_autorecalculatesKeyViewLoop = shouldRecalculate;
|
||||
|
||||
|
||||
if (_keyViewLoopIsDirty)
|
||||
[self recalculateKeyViewLoop];
|
||||
else if (_autorecalculatesKeyViewLoop)
|
||||
@@ -2365,7 +2373,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
_defaultButton = aButton;
|
||||
|
||||
[_defaultButton setDefaultButton:YES];
|
||||
[_defaultButton setDefaultButton:YES];
|
||||
}
|
||||
|
||||
- (CPButton)defaultButton
|
||||
@@ -2432,7 +2440,7 @@ var keyViewComparator = function(a, b, context)
|
||||
{
|
||||
if ([self isFullPlatformWindow])
|
||||
return [self setFrame:[_platformWindow visibleFrame]];
|
||||
|
||||
|
||||
if (_autoresizingMask == CPWindowNotSizable)
|
||||
return;
|
||||
|
||||
@@ -2447,7 +2455,7 @@ var keyViewComparator = function(a, b, context)
|
||||
newFrame.origin.x += dX;
|
||||
if (_autoresizingMask & CPWindowWidthSizable)
|
||||
newFrame.size.width += dX;
|
||||
|
||||
|
||||
if (_autoresizingMask & CPWindowMinYMargin)
|
||||
newFrame.origin.y += dY;
|
||||
if (_autoresizingMask & CPWindowHeightSizable)
|
||||
@@ -2619,7 +2627,7 @@ var interpolate = function(fromValue, toValue, progress)
|
||||
@implementation _CPWindowFrameAnimation : CPAnimation
|
||||
{
|
||||
CPWindow _window;
|
||||
|
||||
|
||||
CGRect _startFrame;
|
||||
CGRect _targetFrame;
|
||||
}
|
||||
@@ -2627,31 +2635,31 @@ var interpolate = function(fromValue, toValue, progress)
|
||||
- (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
|
||||
{
|
||||
self = [super initWithDuration:0.2 animationCurve:CPAnimationLinear];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_window = aWindow;
|
||||
|
||||
|
||||
_targetFrame = CGRectMakeCopy(aTargetFrame);
|
||||
_startFrame = CGRectMakeCopy([_window frame]);
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)startAnimation
|
||||
{
|
||||
[super startAnimation];
|
||||
|
||||
|
||||
_window._isAnimating = YES;
|
||||
}
|
||||
|
||||
- (void)setCurrentProgress:(float)aProgress
|
||||
{
|
||||
[super setCurrentProgress:aProgress];
|
||||
|
||||
|
||||
var value = [self currentValue];
|
||||
|
||||
|
||||
if (value == 1.0)
|
||||
_window._isAnimating = NO;
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
if (_window)
|
||||
return;
|
||||
|
||||
[[CPBundle bundleForClass:[_cibOwner class]] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]];
|
||||
[[CPBundle mainBundle] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -424,7 +424,7 @@
|
||||
if (_windowCibPath)
|
||||
return _windowCibPath;
|
||||
|
||||
return [[CPBundle bundleForClass:[_cibOwner class]] pathForResource:_windowCibName + @".cib"];
|
||||
return [[CPBundle mainBundle] pathForResource:_windowCibName + @".cib"];
|
||||
}
|
||||
|
||||
// Setting and Getting Window Attributes
|
||||
|
||||
@@ -150,7 +150,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
|
||||
|
||||
var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
|
||||
|
||||
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects]
|
||||
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
|
||||
[objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
|
||||
[objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
|
||||
|
||||
|
||||
@@ -160,7 +160,9 @@ var PrimaryPlatformWindow = NULL;
|
||||
|
||||
_contentRect = _CGRectMakeCopy(aRect);
|
||||
|
||||
[self updateNativeContentRect];
|
||||
#if PLATFORM(DOM)
|
||||
[self updateNativeContentRect];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)updateFromNativeContentRect
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* THIS DOCUMENTATION STOLEN DIRECTLY FROM GOOGLE CLOSURE (licensed under Apache 2)
|
||||
*
|
||||
*
|
||||
* Different web browsers have very different keyboard event handling. Most
|
||||
* importantly is that only certain browsers repeat keydown events:
|
||||
* IE, Opera, FF/Win32, and Safari 3 repeat keydown events.
|
||||
@@ -111,6 +111,7 @@
|
||||
@import <Foundation/CPRunLoop.j>
|
||||
|
||||
@import "CPEvent.j"
|
||||
@import "CPText.j"
|
||||
@import "CPCompatibility.j"
|
||||
|
||||
@import "CPDOMWindowLayer.j"
|
||||
@@ -138,10 +139,23 @@ var KeyCodesToPrevent = {},
|
||||
MozKeyCodeToKeyCodeMap = {
|
||||
61: 187, // =, equals
|
||||
59: 186 // ;, semicolon
|
||||
};
|
||||
},
|
||||
KeyCodesToFunctionUnicodeMap = {};
|
||||
|
||||
KeyCodesToPrevent[CPKeyCodes.A] = YES;
|
||||
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.BACKSPACE] = CPDeleteCharacter;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.DELETE] = CPDeleteFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.TAB] = CPTabCharacter;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.ENTER] = CPCarriageReturnCharacter;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.ESC] = CPEscapeFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.PAGE_UP] = CPPageUpFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.PAGE_DOWN] = CPPageDownFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.LEFT] = CPLeftArrowFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.UP] = CPUpArrowFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.RIGHT] = CPRightArrowFunctionKey;
|
||||
KeyCodesToFunctionUnicodeMap[CPKeyCodes.DOWN] = CPDownArrowFunctionKey;
|
||||
|
||||
var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
@implementation CPPlatformWindow (DOM)
|
||||
@@ -306,11 +320,11 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
keyEventSelector = @selector(keyEvent:),
|
||||
keyEventImplementation = class_getMethodImplementation(theClass, keyEventSelector),
|
||||
keyEventCallback = function (anEvent) { keyEventImplementation(self, nil, anEvent); },
|
||||
|
||||
|
||||
mouseEventSelector = @selector(mouseEvent:),
|
||||
mouseEventImplementation = class_getMethodImplementation(theClass, mouseEventSelector),
|
||||
mouseEventCallback = function (anEvent) { mouseEventImplementation(self, nil, anEvent); },
|
||||
|
||||
|
||||
contextMenuEventSelector = @selector(contextMenuEvent:),
|
||||
contextMenuEventImplementation = class_getMethodImplementation(theClass, contextMenuEventSelector),
|
||||
contextMenuEventCallback = function (anEvent) { return contextMenuEventImplementation(self, nil, anEvent); },
|
||||
@@ -318,7 +332,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
scrollEventSelector = @selector(scrollEvent:),
|
||||
scrollEventImplementation = class_getMethodImplementation(theClass, scrollEventSelector),
|
||||
scrollEventCallback = function (anEvent) { scrollEventImplementation(self, nil, anEvent); },
|
||||
|
||||
|
||||
touchEventSelector = @selector(touchEvent:),
|
||||
touchEventImplementation = class_getMethodImplementation(theClass, touchEventSelector),
|
||||
touchEventCallback = function (anEvent) { touchEventImplementation(self, nil, anEvent); };
|
||||
@@ -356,7 +370,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
_DOMWindow.addEventListener("DOMMouseScroll", scrollEventCallback, NO);
|
||||
_DOMWindow.addEventListener("mousewheel", scrollEventCallback, NO);
|
||||
|
||||
_DOMWindow.addEventListener("resize", resizeEventCallback, NO);
|
||||
_DOMWindow.addEventListener("resize", resizeEventCallback, NO);
|
||||
|
||||
_DOMWindow.addEventListener("unload", function()
|
||||
{
|
||||
@@ -400,16 +414,16 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
theDocument.attachEvent("onmousemove", mouseEventCallback);
|
||||
theDocument.attachEvent("ondblclick", mouseEventCallback);
|
||||
theDocument.attachEvent("oncontextmenu", contextMenuEventCallback);
|
||||
|
||||
|
||||
theDocument.attachEvent("onkeyup", keyEventCallback);
|
||||
theDocument.attachEvent("onkeydown", keyEventCallback);
|
||||
theDocument.attachEvent("onkeypress", keyEventCallback);
|
||||
|
||||
|
||||
_DOMWindow.attachEvent("onresize", resizeEventCallback);
|
||||
|
||||
|
||||
_DOMWindow.onmousewheel = scrollEventCallback;
|
||||
theDocument.onmousewheel = scrollEventCallback;
|
||||
|
||||
|
||||
_DOMBodyElement.ondrag = function () { return NO; };
|
||||
_DOMBodyElement.onselectstart = function () { return _DOMWindow.event.srcElement === _DOMPasteboardElement; };
|
||||
|
||||
@@ -596,12 +610,12 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
|
||||
sourceElement = (aDOMEvent.target || aDOMEvent.srcElement),
|
||||
windowNumber = [[CPApp keyWindow] windowNumber],
|
||||
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
(aDOMEvent.metaKey ? CPCommandKeyMask : 0);
|
||||
|
||||
//We want to stop propagation if this is a command key AND this character or keycode has been added to our blacklist
|
||||
//We want to stop propagation if this is a command key AND this character or keycode has been added to our blacklist
|
||||
StopDOMEventPropagation = !!(!(modifierFlags & (CPControlKeyMask | CPCommandKeyMask)) ||
|
||||
CharacterKeysToPrevent[String.fromCharCode(aDOMEvent.keyCode || aDOMEvent.charCode).toLowerCase()] ||
|
||||
KeyCodesToPrevent[aDOMEvent.keyCode]);
|
||||
@@ -618,7 +632,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
else
|
||||
_keyCode = aDOMEvent.keyCode;
|
||||
|
||||
var characters = String.fromCharCode(_keyCode).toLowerCase();
|
||||
var characters = KeyCodesToFunctionUnicodeMap[_keyCode] || String.fromCharCode(_keyCode).toLowerCase();
|
||||
overrideCharacters = (modifierFlags & CPShiftKeyMask || _capsLockActive) ? characters.toUpperCase() : characters;
|
||||
|
||||
// check for caps lock state
|
||||
@@ -633,7 +647,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
var eligibleForCopyPaste = [self _validateCopyCutOrPasteEvent:aDOMEvent flags:modifierFlags];
|
||||
|
||||
// If this could be a native PASTE event, then we need to further examine it before
|
||||
// If this could be a native PASTE event, then we need to further examine it before
|
||||
// sending a CPEvent. Select our element to see if anything gets pasted in it.
|
||||
if (characters === "v" && eligibleForCopyPaste)
|
||||
{
|
||||
@@ -646,7 +660,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
isNativePasteEvent = YES;
|
||||
}
|
||||
|
||||
// However, of this could be a native COPY event, we need to let the normal event-process take place so it
|
||||
// However, of this could be a native COPY event, we need to let the normal event-process take place so it
|
||||
// can capture our internal Cappuccino pasteboard.
|
||||
else if ((characters == "c" || characters == "x") && eligibleForCopyPaste)
|
||||
{
|
||||
@@ -668,10 +682,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
//this branch is taken by "remedial" key events
|
||||
// In this state we continue to keypress and send the CPEvent
|
||||
}
|
||||
|
||||
|
||||
case "keypress":
|
||||
// we unconditionally break on keypress events with modifiers,
|
||||
// because we forced the event to be sent on the keydown
|
||||
// we unconditionally break on keypress events with modifiers,
|
||||
// because we forced the event to be sent on the keydown
|
||||
if (aDOMEvent.type === "keypress" && (modifierFlags & (CPControlKeyMask | CPCommandKeyMask)))
|
||||
break;
|
||||
|
||||
@@ -682,7 +696,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
_lastKey = keyCode;
|
||||
_charCodes[keyCode] = charCode;
|
||||
|
||||
var characters = overrideCharacters || String.fromCharCode(charCode),
|
||||
var characters = overrideCharacters || KeyCodesToFunctionUnicodeMap[charCode] || String.fromCharCode(charCode),
|
||||
charactersIgnoringModifiers = characters.toLowerCase();
|
||||
|
||||
// Safari won't send proper capitalization during cmd-key events
|
||||
@@ -700,10 +714,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case "keyup": var keyCode = aDOMEvent.keyCode,
|
||||
charCode = _charCodes[keyCode];
|
||||
|
||||
|
||||
_keyCode = -1;
|
||||
_lastKey = -1;
|
||||
_charCodes[keyCode] = nil;
|
||||
@@ -714,12 +728,12 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if (keyCode === CPKeyCodes.CAPS_LOCK)
|
||||
_capsLockActive = NO;
|
||||
|
||||
var characters = String.fromCharCode(charCode),
|
||||
var characters = KeyCodesToFunctionUnicodeMap[charCode] || String.fromCharCode(charCode),
|
||||
charactersIgnoringModifiers = characters.toLowerCase();
|
||||
|
||||
|
||||
if (!(modifierFlags & CPShiftKeyMask) && (modifierFlags & CPCommandKeyMask) && !_capsLockActive)
|
||||
characters = charactersIgnoringModifiers;
|
||||
|
||||
|
||||
event = [CPEvent keyEventWithType:CPKeyUp location:location modifierFlags:modifierFlags
|
||||
timestamp: timestamp windowNumber:windowNumber context:nil
|
||||
characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO keyCode:keyCode];
|
||||
@@ -867,10 +881,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
{
|
||||
x += element.offsetLeft;
|
||||
y += element.offsetTop;
|
||||
|
||||
|
||||
} while (element = element.offsetParent);
|
||||
}
|
||||
|
||||
|
||||
location = _CGPointMake((x + ((aDOMEvent.clientX - 8) / 15)), (y + ((aDOMEvent.clientY - 8) / 15)));
|
||||
}
|
||||
else if (aDOMEvent._overrideLocation)
|
||||
@@ -882,9 +896,9 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
deltaY = 0.0,
|
||||
windowNumber = 0,
|
||||
timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
|
||||
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
(aDOMEvent.metaKey ? CPCommandKeyMask : 0);
|
||||
|
||||
StopDOMEventPropagation = YES;
|
||||
@@ -903,31 +917,31 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
deltaX = aDOMEvent.wheelDeltaX / 120.0;
|
||||
deltaY = aDOMEvent.wheelDeltaY / 120.0;
|
||||
}
|
||||
|
||||
|
||||
else if (aDOMEvent.wheelDelta)
|
||||
deltaY = aDOMEvent.wheelDelta / 120.0;
|
||||
|
||||
else if (aDOMEvent.detail)
|
||||
|
||||
else if (aDOMEvent.detail)
|
||||
deltaY = -aDOMEvent.detail / 3.0;
|
||||
|
||||
|
||||
else
|
||||
return;
|
||||
return;
|
||||
|
||||
if(!CPFeatureIsCompatible(CPJavaScriptNegativeMouseWheelValues))
|
||||
{
|
||||
deltaX = -deltaX;
|
||||
deltaY = -deltaY;
|
||||
}
|
||||
|
||||
|
||||
var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags
|
||||
timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0 ];
|
||||
|
||||
|
||||
event._DOMEvent = aDOMEvent;
|
||||
event._deltaX = deltaX;
|
||||
event._deltaY = deltaY;
|
||||
|
||||
|
||||
[CPApp sendEvent:event];
|
||||
|
||||
|
||||
if (StopDOMEventPropagation)
|
||||
CPDOMEventStop(aDOMEvent, self);
|
||||
|
||||
@@ -970,7 +984,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if (aDOMEvent.touches && (aDOMEvent.touches.length == 1 || (aDOMEvent.touches.length == 0 && aDOMEvent.changedTouches.length == 1)))
|
||||
{
|
||||
var newEvent = {};
|
||||
|
||||
|
||||
switch(aDOMEvent.type)
|
||||
{
|
||||
case CPDOMEventTouchStart: newEvent.type = CPDOMEventMouseDown;
|
||||
@@ -984,27 +998,27 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
}
|
||||
|
||||
var touch = aDOMEvent.touches.length ? aDOMEvent.touches[0] : aDOMEvent.changedTouches[0];
|
||||
|
||||
|
||||
newEvent.clientX = touch.clientX;
|
||||
newEvent.clientY = touch.clientY;
|
||||
|
||||
|
||||
newEvent.timestamp = aDOMEvent.timestamp;
|
||||
newEvent.target = aDOMEvent.target;
|
||||
|
||||
|
||||
newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
|
||||
|
||||
|
||||
newEvent.preventDefault = function(){if(aDOMEvent.preventDefault) aDOMEvent.preventDefault()};
|
||||
newEvent.stopPropagation = function(){if(aDOMEvent.stopPropagation) aDOMEvent.stopPropagation()};
|
||||
|
||||
|
||||
[self mouseEvent:newEvent];
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aDOMEvent.preventDefault)
|
||||
aDOMEvent.preventDefault();
|
||||
|
||||
|
||||
if (aDOMEvent.stopPropagation)
|
||||
aDOMEvent.stopPropagation();
|
||||
}
|
||||
@@ -1026,7 +1040,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
_overriddenEventType = nil;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
var event,
|
||||
@@ -1034,9 +1048,9 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
|
||||
sourceElement = (aDOMEvent.target || aDOMEvent.srcElement),
|
||||
windowNumber = 0,
|
||||
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
(aDOMEvent.metaKey ? CPCommandKeyMask : 0);
|
||||
|
||||
StopDOMEventPropagation = YES;
|
||||
@@ -1062,7 +1076,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if(_mouseIsDown)
|
||||
{
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, _mouseDownIsRightClick ? CPRightMouseUp : CPLeftMouseUp, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseUp, timestamp, location), 0);
|
||||
|
||||
|
||||
_mouseIsDown = NO;
|
||||
_lastMouseUp = event;
|
||||
_mouseDownWindow = nil;
|
||||
@@ -1075,7 +1089,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (type === "mousedown")
|
||||
{
|
||||
if (sourceElement.tagName === "INPUT" && sourceElement != _DOMFocusElement)
|
||||
@@ -1091,11 +1105,11 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
//fake a down and up event so that event tracking mode will work correctly
|
||||
[CPApp sendEvent:[CPEvent mouseEventWithType:CPLeftMouseDown location:location modifierFlags:modifierFlags
|
||||
timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
|
||||
timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
|
||||
clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]];
|
||||
|
||||
[CPApp sendEvent:[CPEvent mouseEventWithType:CPLeftMouseUp location:location modifierFlags:modifierFlags
|
||||
timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
|
||||
timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
|
||||
clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]];
|
||||
|
||||
return;
|
||||
@@ -1116,7 +1130,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
_mouseIsDown = YES;
|
||||
_lastMouseDown = event;
|
||||
}
|
||||
|
||||
|
||||
else // if (type === "mousemove" || type === "drag")
|
||||
{
|
||||
if (_DOMEventMode)
|
||||
@@ -1130,7 +1144,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if (event && (!isDragging || !supportsNativeDragAndDrop))
|
||||
{
|
||||
event._DOMEvent = aDOMEvent;
|
||||
|
||||
|
||||
[CPApp sendEvent:event];
|
||||
}
|
||||
|
||||
@@ -1157,7 +1171,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
if (!layer)
|
||||
return [];
|
||||
|
||||
|
||||
return [layer orderedWindows];
|
||||
}
|
||||
|
||||
@@ -1170,19 +1184,19 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if (!layer && aFlag)
|
||||
{
|
||||
layer = [[CPDOMWindowLayer alloc] initWithLevel:aLevel];
|
||||
|
||||
|
||||
[_windowLayers setObject:layer forKey:aLevel];
|
||||
|
||||
// Find the nearest layer. This is similar to a binary search,
|
||||
// Find the nearest layer. This is similar to a binary search,
|
||||
// only we know we won't find the value.
|
||||
var low = 0,
|
||||
high = _windowLevels.length - 1,
|
||||
middle;
|
||||
|
||||
|
||||
while (low <= high)
|
||||
{
|
||||
middle = FLOOR((low + high) / 2);
|
||||
|
||||
|
||||
if (_windowLevels[middle] > aLevel)
|
||||
high = middle - 1;
|
||||
else
|
||||
@@ -1190,7 +1204,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
}
|
||||
|
||||
var insertionIndex = 0;
|
||||
if (middle !== undefined)
|
||||
if (middle !== undefined)
|
||||
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1
|
||||
|
||||
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
|
||||
@@ -1198,7 +1212,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
_DOMBodyElement.appendChild(layer._DOMElement);
|
||||
}
|
||||
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
@@ -1206,11 +1220,11 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
{
|
||||
[CPPlatform initializeScreenIfNecessary];
|
||||
|
||||
// Grab the appropriate level for the layer, and create it if
|
||||
// Grab the appropriate level for the layer, and create it if
|
||||
// necessary (if we are not simply removing the window).
|
||||
var layer = [self layerAtLevel:[aWindow level] create:aPlace !== CPWindowOut];
|
||||
|
||||
// Ignore otherWindow, simply remove this window from it's level.
|
||||
// Ignore otherWindow, simply remove this window from it's level.
|
||||
// If layer is nil, this will be a no-op.
|
||||
if (aPlace === CPWindowOut)
|
||||
return [layer removeWindow:aWindow];
|
||||
@@ -1263,10 +1277,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
// Skip any windows above or at the dragging level.
|
||||
if (levels[levelCount] >= CPDraggingWindowLevel)
|
||||
continue;
|
||||
|
||||
|
||||
var windows = [layers objectForKey:levels[levelCount]]._windows,
|
||||
windowCount = windows.length;
|
||||
|
||||
|
||||
while (windowCount--)
|
||||
{
|
||||
var theWindow = windows[windowCount];
|
||||
@@ -1278,7 +1292,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
return [theWindow _dragHitTest:aPoint pasteboard:aPasteboard];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -1308,7 +1322,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
- (CPWindow)hitTest:(CPPoint)location
|
||||
{
|
||||
if (self._only)
|
||||
if (self._only)
|
||||
return self._only;
|
||||
|
||||
var levels = _windowLevels,
|
||||
@@ -1324,7 +1338,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
while (windowCount-- && !theWindow)
|
||||
{
|
||||
var candidateWindow = windows[windowCount];
|
||||
|
||||
|
||||
if (!candidateWindow._ignoresMouseEvents && [candidateWindow containsPoint:location])
|
||||
theWindow = candidateWindow;
|
||||
}
|
||||
@@ -1334,10 +1348,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
}
|
||||
|
||||
/*!
|
||||
When using command (mac) or control (windows), keys are propagated to the browser by default.
|
||||
When using command (mac) or control (windows), keys are propagated to the browser by default.
|
||||
To prevent a character key from propagating (to prevent its default action, and instead use it
|
||||
in your own application), use these methods. These methods are additive -- the list builds until you clear it.
|
||||
|
||||
|
||||
@param characters a list of characters to stop propagating keypresses to the browser.
|
||||
*/
|
||||
+ (void)preventCharacterKeysFromPropagating:(CPArray)characters
|
||||
@@ -1418,11 +1432,11 @@ var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
|
||||
{
|
||||
if (!aComparisonEvent)
|
||||
return 1;
|
||||
|
||||
|
||||
var comparisonLocation = [aComparisonEvent locationInWindow];
|
||||
|
||||
return (aTimestamp - [aComparisonEvent timestamp] < CLICK_TIME_DELTA &&
|
||||
ABS(comparisonLocation.x - aLocation.x) < CLICK_SPACE_DELTA &&
|
||||
|
||||
return (aTimestamp - [aComparisonEvent timestamp] < CLICK_TIME_DELTA &&
|
||||
ABS(comparisonLocation.x - aLocation.x) < CLICK_SPACE_DELTA &&
|
||||
ABS(comparisonLocation.y - aLocation.y) < CLICK_SPACE_DELTA) ? [aComparisonEvent clickCount] + 1 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 141 B After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 254 B |
|
After Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 588 B After Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 572 B After Width: | Height: | Size: 260 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 271 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 248 B |
|
After Width: | Height: | Size: 242 B |
|
After Width: | Height: | Size: 282 B |
|
After Width: | Height: | Size: 278 B |
|
After Width: | Height: | Size: 130 B |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 193 B |
|
After Width: | Height: | Size: 894 B |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 140 B |
|
After Width: | Height: | Size: 140 B |
|
After Width: | Height: | Size: 124 B |
|
After Width: | Height: | Size: 228 B |
|
After Width: | Height: | Size: 227 B |
|
After Width: | Height: | Size: 124 B |
|
After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 124 B |
|
After Width: | Height: | Size: 241 B |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 245 B |
|
After Width: | Height: | Size: 124 B |
|
After Width: | Height: | Size: 244 B |
|
After Width: | Height: | Size: 251 B |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 146 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 227 B |
|
After Width: | Height: | Size: 227 B |
|
After Width: | Height: | Size: 227 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 199 B |
|
After Width: | Height: | Size: 199 B |
|
After Width: | Height: | Size: 184 B |
|
After Width: | Height: | Size: 126 B |
|
After Width: | Height: | Size: 184 B |
|
After Width: | Height: | Size: 126 B |
|
After Width: | Height: | Size: 211 B |