mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 21:17:03 +00:00
260 lines
6.0 KiB
Plaintext
260 lines
6.0 KiB
Plaintext
/*
|
|
* CPRunLoop.j
|
|
* Foundation
|
|
*
|
|
* Created by Francisco Tolmasky.
|
|
* Copyright 2008, 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 "CPObject.j"
|
|
import "CPArray.j"
|
|
import "CPString.j"
|
|
|
|
/*
|
|
@global
|
|
@group CPRunLoopMode
|
|
*/
|
|
CPDefaultRunLoopMode = @"CPDefaultRunLoopMode";
|
|
|
|
function _CPRunLoopPerformCompare(lhs, rhs)
|
|
{
|
|
return [rhs order] - [lhs order];
|
|
}
|
|
|
|
var _CPRunLoopPerformPool = [],
|
|
_CPRunLoopPerformPoolCapacity = 5;
|
|
|
|
/* @ignore */
|
|
@implementation _CPRunLoopPerform : CPObject
|
|
{
|
|
id _target;
|
|
SEL _selector;
|
|
id _argument;
|
|
unsigned _order;
|
|
CPArray _runLoopModes;
|
|
}
|
|
|
|
+ (void)_poolPerform:(_CPRunLoopPerform)aPerform
|
|
{
|
|
if (!aPerform || _CPRunLoopPerformPool.length >= _CPRunLoopPerformPoolCapacity)
|
|
return;
|
|
|
|
_CPRunLoopPerformPool.push(aPerform);
|
|
}
|
|
|
|
+ (_CPRunLoopPerform)performWithSelector:(SEL)aSelector target:(id)aTarget argument:(id)anArgument order:(unsigned)anOrder modes:(CPArray)modes
|
|
{
|
|
if (_CPRunLoopPerformPool.length)
|
|
{
|
|
var perform = _CPRunLoopPerformPool.pop();
|
|
|
|
perform._target = aTarget;
|
|
perform._selector = aSelector;
|
|
perform._arguments = anArgument;
|
|
perform._order = anOrder;
|
|
perform._runLoopModes = modes;
|
|
|
|
return perform;
|
|
}
|
|
|
|
return [[self alloc] initWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes];
|
|
}
|
|
|
|
- (id)initWithSelector:(SEL)aSelector target:(SEL)aTarget argument:(id)anArgument order:(unsigned)anOrder modes:(CPArray)modes
|
|
{
|
|
self = [super init];
|
|
|
|
if (self)
|
|
{
|
|
_selector = aSelector;
|
|
_target = aTarget;
|
|
_argument = anArgument;
|
|
_order = anOrder;
|
|
_runLoopModes = modes;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (SEL)selector
|
|
{
|
|
return _selector;
|
|
}
|
|
|
|
- (id)target
|
|
{
|
|
return _target;
|
|
}
|
|
|
|
- (id)argument
|
|
{
|
|
return _argument;
|
|
}
|
|
|
|
- (unsigned)order
|
|
{
|
|
return _order;
|
|
}
|
|
|
|
- (BOOL)fireInMode:(CPString)aRunLoopMode
|
|
{
|
|
if ([_runLoopModes containsObject:aRunLoopMode])
|
|
{
|
|
[_target performSelector:_selector withObject:_argument];
|
|
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
@end
|
|
|
|
/*
|
|
CPRunLoop instances handle various utility tasks that must be performed repetitively in an application, such as processing input events.
|
|
|
|
There is one run loop per application, which may always be obtained through the +currentRunLoop method,
|
|
*/
|
|
@implementation CPRunLoop : CPObject
|
|
{
|
|
CPArray _queuedPerforms;
|
|
CPArray _orderedPerforms;
|
|
BOOL _isPerformingSelectors;
|
|
}
|
|
|
|
/*
|
|
@ignore
|
|
*/
|
|
+ (void)initialize
|
|
{
|
|
if (self != [CPRunLoop class])
|
|
return;
|
|
|
|
CPMainRunLoop = [[CPRunLoop alloc] init];
|
|
}
|
|
|
|
- (id)init
|
|
{
|
|
self = [super init];
|
|
|
|
if (self)
|
|
{
|
|
_queuedPerforms = [];
|
|
_orderedPerforms = [];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
/*
|
|
Returns the application's singleton <objj>CPRunLoop</objj>.
|
|
*/
|
|
+ (CPRunLoop)currentRunLoop
|
|
{
|
|
return CPMainRunLoop;
|
|
}
|
|
|
|
/*
|
|
Returns the application's singleton <objj>CPRunLoop</objj>.
|
|
*/
|
|
+ (CPRunLoop)mainRunLoop
|
|
{
|
|
return CPMainRunLoop;
|
|
}
|
|
|
|
/*
|
|
Performs the specified selector on the specified target. The method will be invoked synchronously.
|
|
@param aSelector the selector of the method to invoke
|
|
@param aTarget the target of the selector
|
|
@param anArgument the method argument
|
|
@param anOrder the message priority
|
|
@param modes the modes variable isn't respected.
|
|
*/
|
|
- (void)performSelector:(SEL)aSelector target:(id)aTarget argument:(id)anArgument order:(int)anOrder modes:(CPArray)modes
|
|
{
|
|
var perform = [_CPRunLoopPerform performWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes];
|
|
|
|
if (_isPerformingSelectors)
|
|
_queuedPerforms.push(perform);
|
|
else
|
|
{
|
|
var count = _orderedPerforms.length;
|
|
|
|
// We sort ourselves in reverse because we iterate this list backwards.
|
|
while (count--)
|
|
if (anOrder < [_orderedPerforms[count] order])
|
|
break;
|
|
|
|
_orderedPerforms.splice(count + 1, 0, perform);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Cancels the specified selector and target.
|
|
@param aSelector the selector of the method to invoke
|
|
@param aTarget the target to invoke the method on
|
|
@param the argument for the method
|
|
*/
|
|
- (void)cancelPerformSelector:(SEL)aSelector target:(id)aTarget argument:(id)anArgument
|
|
{
|
|
var count = _orderedPerforms.length;
|
|
|
|
while (count--)
|
|
{
|
|
var perform = _orderedPerforms[count];
|
|
|
|
if ([perform selector] == aSelector && [perform target] == aTarget && [perform argument] == anArgument)
|
|
[_orderedPerforms removeObjectAtIndex:count];
|
|
}
|
|
}
|
|
|
|
/*
|
|
@ignore
|
|
*/
|
|
- (void)performSelectors
|
|
{
|
|
if (_isPerformingSelectors)
|
|
return;
|
|
|
|
_isPerformingSelectors = YES;
|
|
|
|
var index = _orderedPerforms.length;
|
|
|
|
while (index--)
|
|
{
|
|
var perform = _orderedPerforms[index];
|
|
|
|
if ([perform fireInMode:CPDefaultRunLoopMode])
|
|
{
|
|
[_CPRunLoopPerform _poolPerform:perform];
|
|
|
|
_orderedPerforms.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
_isPerformingSelectors = NO;
|
|
|
|
if (_queuedPerforms.length)
|
|
{
|
|
_orderedPerforms = _orderedPerforms.concat(_queuedPerforms);
|
|
_orderedPerforms.sort(_CPRunLoopPerformCompare);
|
|
}
|
|
|
|
_queuedPerforms = [];
|
|
}
|
|
|
|
@end |