Skip to content

Commit

Permalink
Updated for new API
Browse files Browse the repository at this point in the history
phoenix3200 committed Mar 21, 2011
1 parent 8810f06 commit a92bf30
Showing 16 changed files with 1,376 additions and 415 deletions.
6 changes: 5 additions & 1 deletion StatusBarItemClient.h → LSStatusBarClient.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@

@interface StatusBarItemClient : NSObject
@interface LSStatusBarClient : NSObject
{
bool _isLocal;
NSDictionary* _currentMessage;
NSArray* _titleStrings;
}

+ (id) sharedInstance;

- (id) init;

- (NSDictionary*) currentMessage;
- (void) retrieveCurrentMessage;
- (bool) processCurrentMessage;
- (void) updateStatusBar;

- (void) setProperties: (id) properties forItem: (NSString*) item;

- (NSString*) titleStringAtIndex: (int) idx;

@end
265 changes: 265 additions & 0 deletions LSStatusBarClient.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@

//#define TESTING

#import "common.h"
#import "defines.h"

#import "classes.h"
#import "LSStatusBarClient.h"
#import "LSStatusBarServer.h"
#import "UIStatusBarCustomItem.h"

void UpdateStatusBar(CFNotificationCenterRef center, LSStatusBarClient* client)
{
[client updateStatusBar];
}

@implementation LSStatusBarClient

+ (id) sharedInstance
{
static LSStatusBarClient* client;

if(!client)
{
client = [[self alloc] init];
}
return client;
}

- (id) init
{
self = [super init];
if(self)
{
_isLocal = $SpringBoard ? YES : NO;

CFNotificationCenterRef darwin = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationCenterAddObserver(darwin, self, (CFNotificationCallback) UpdateStatusBar, (CFStringRef) @"libstatusbar_changed", NULL, NULL);

[self updateStatusBar];

}
return self;
}

- (NSDictionary*) currentMessage
{
return _currentMessage;
}

- (void) retrieveCurrentMessage
{
[_currentMessage release];
if(_isLocal)
{
_currentMessage = [[[LSStatusBarServer sharedInstance] currentMessage] retain];
}
else
{ CPDistributedMessagingCenter* dmc = [CPDistributedMessagingCenter centerNamed: @"com.apple.springboard.libstatusbar"];

_currentMessage = [[dmc sendMessageAndReceiveReplyName: @"currentMessage" userInfo: nil] retain];
}
NSDesc(_currentMessage);
}

- (NSString*) titleStringAtIndex: (int) idx
{
if(idx < (int)[_titleStrings count])
{
return [_titleStrings objectAtIndex: idx];
}
return nil;
}

- (bool) processCurrentMessage
{
bool ret = NO;

//NSMutableDictionary *processedMessage = [_currentMessage mutableCopy];

NSMutableArray* processedKeys = [[_currentMessage objectForKey: @"keys"] mutableCopy];


[_titleStrings release];
_titleStrings = [[_currentMessage objectForKey: @"titleStrings"] retain];


/*
if(_titleStrings)
{
[processedMessage removeObjectForKey: @"titleStrings"];
}
*/

int keyidx = 22;

NSDesc(_currentMessage);
extern NSMutableArray* customItems[3];

for(int i=0; i<3; i++)
{
if(customItems[i])
{
NSDesc(customItems[i]);
int cnt = [customItems[i] count]-1;
/*
extern NSMutableArray* allCustomItems;
if(allCustomItems)
{
int cnt = [allCustomItems count]-1;
*/
for(; cnt>= 0; cnt--)
// for(UIStatusBarCustomItem* item in customItems[i])
{
UIStatusBarCustomItem* item = [customItems[i] objectAtIndex: cnt];
//UIStatusBarCustomItem* item = [allCustomItems objectAtIndex: cnt];

NSString* indicatorName = [item indicatorName];

NSObject* properties = nil;
if(_currentMessage)
{
properties = [_currentMessage objectForKey: indicatorName];
}

if(!properties)
{
ret = YES;

NSLog(@"removing item: %@", indicatorName);
[item removeAllViews];
//[allCustomItems removeObjectAtIndex: cnt];
[customItems[i] removeObjectAtIndex: cnt];
// [customItems[i] removeObject: item];
}
else
{
NSLog(@"keeping item: %@", indicatorName);
//[processedMessage removeObjectForKey: indicatorName];
[processedKeys removeObject: indicatorName];

int &type(MSHookIvar<int>(item, "_type"));
if(type > keyidx)
keyidx = type;

item.properties = [properties isKindOfClass: [NSDictionary class]] ? (NSDictionary*) properties : nil;
}
}
}
else
{
NSLog(@"creating array");
customItems[i] = [[NSMutableArray alloc] init];
}
}

keyidx++;

if(processedKeys && [processedKeys count])
{
ret = YES;
GETCLASS(UIStatusBarItem);
for(NSString* key in processedKeys)//processedMessage)
{
NSLog(@"adding item: %@", key);

UIStatusBarCustomItem* item = [$UIStatusBarItem itemWithType: keyidx++];
[item setIndicatorName: key];

NSObject* properties = [_currentMessage objectForKey: key];
item.properties = [properties isKindOfClass: [NSDictionary class]] ? (NSDictionary*) properties : nil;


if([item leftOrder])
{
if(!customItems[0])
{
customItems[0] = [[NSMutableArray alloc] init];
}
[customItems[0] addObject: item];
}
else if([item rightOrder])
{
if(!customItems[1])
{
customItems[1] = [[NSMutableArray alloc] init];
}
[customItems[1] addObject: item];
}
else
{
if(!customItems[2])
{
customItems[2] = [[NSMutableArray alloc] init];
}
[customItems[2] addObject: item];
}
}
}


//if(_titleStrings && [_titleStrings count])

// too many cases; just refresh the damn thing.
{
ret = YES;
}



[processedKeys release];

NSLog(@"processCurrentMessage? %@", ret ? @"YES" : @"NO");
return ret;
}

- (void) updateStatusBar
{
SelLog();

[self retrieveCurrentMessage];

// need a decent guard band because we do call before UIApp exists
if([self processCurrentMessage] && UIApp)
{
UIStatusBarForegroundView* _foregroundView = MSHookIvar<UIStatusBarForegroundView*>([UIApp statusBar], "_foregroundView");
if(_foregroundView)
{
//[_foregroundView _reflowItemViewsWithDuration: 0.0f suppressCenterAnimation: YES];

[_foregroundView setStatusBarData: (StatusBarData*) [$UIStatusBarServer getStatusBarData] actions: 1 animated: YES];
}
}
}

- (void) setProperties: (id) properties forItem: (NSString*) item
{
SelLog();
if(item)
{
NSString* bundleId = [[NSBundle mainBundle] bundleIdentifier];

if(_isLocal)
{
[[LSStatusBarServer sharedInstance] setProperties: properties forItem: item bundle: bundleId];
}
else
{


NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:
item, @"item",
properties, @"properties",
bundleId, @"bundle",
nil];

CPDistributedMessagingCenter* dmc = [CPDistributedMessagingCenter centerNamed: @"com.apple.springboard.libstatusbar"];

[dmc sendMessageName: @"setProperties:userInfo:" userInfo: dict];
[dict release];
}
}
}

@end
67 changes: 67 additions & 0 deletions LSStatusBarItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
enum StatusBarAlignment
{
StatusBarAlignmentLeft = 1,
StatusBarAlignmentRight = 2,
StatusBarAlignmentCenter = 4
};


@interface LSStatusBarItem : NSObject
{
NSString* _identifier;
NSMutableDictionary* _properties;
NSMutableSet* _delegates;
BOOL _manualUpdate;
}

+ (void) updateItems;

- (void) dealloc;
- (void) setProperties: (NSDictionary*) dict;

@end


@interface LSStatusBarItem (API)

- (id) initWithIdentifier: (NSString*) identifier alignment: (StatusBarAlignment) alignment;

// bitmasks (e.g. left or right) are not supported yet
@property (nonatomic, readonly) StatusBarAlignment alignment;

@property (nonatomic, getter=isVisible) BOOL visible;

// useful only with left/right alignment - will throw error for center alignment
@property (nonatomic, assign) NSString* imageName;

// useful only with center alignment - will throw error otherwise
// will not be visible on the lockscreen
@property (nonatomic, assign) NSString* titleString;

// set to NO and manually call update if you need to make multiple changes
@property (nonatomic, getter=isManualUpdate) BOOL manualUpdate;

// manually call if manualUpdate = YES
- (void) update;

@end




@interface LSStatusBarItem (Unimplemented)


// leave alone unless you want to limit which apps your icon shows up in
@property (nonatomic, assign) NSString* exclusiveToApp;

// convenience methods?
//@property (nonatomic, getter=isSpringBoardOnly) BOOL springBoardOnly;
//@property (getter=isCurrentAppOnly) BOOL currentAppOnly;

// delegate must respond to @selector(statusBarAction:); only valid from inside of SpringBoard
- (void) addTouchDelegate: (id) delegate;
- (void) removeTouchDelegate: (id) delegate;


@end
257 changes: 257 additions & 0 deletions LSStatusBarItem.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@


//#define TESTING

#import "common.h"
#import "defines.h"

#import "LSStatusBarItem.h"
#import "LSStatusBarClient.h"


NSMutableDictionary* sbitems = nil;

@implementation LSStatusBarItem


+ (void) updateItems
{
NSDictionary* currentMessage = [[LSStatusBarClient sharedInstance] currentMessage];

if(!sbitems)
{
sbitems = [NSMutableDictionary new];
}

for(NSString* key in sbitems)
{
NSDictionary* dict = [currentMessage objectForKey: key];

if(dict)
{
NSArray* idArray = [sbitems objectForKey: key];
for(LSStatusBarItem* item in idArray)
{
[item setProperties: dict];
}
}
}
}


- (id) initWithIdentifier: (NSString*) identifier alignment: (StatusBarAlignment) alignment
{
if(!identifier)
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: No identifer specified"];
}

if(!alignment)
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Alignment not specified"];
}

if(!UIApp)
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Wait for UIApp to load!"];
}


if((self = [super init]))
{
// get the current message
NSDictionary* currentMessage;
{
LSStatusBarClient* client = [LSStatusBarClient sharedInstance];

currentMessage = [client currentMessage];
if(!currentMessage)
[client retrieveCurrentMessage];

if(!currentMessage)
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Cannot retrieve the current message!"];
}

}

// save all the settings
{
_identifier = [identifier retain];

[self setProperties: [currentMessage objectForKey: _identifier]];

NSNumber* align = [_properties objectForKey: @"alignment"];
if(!align)
{
[_properties setObject: [NSNumber numberWithInt: alignment] forKey: @"alignment"];
}
else if([align intValue] != alignment)
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: You cannot specify a new alignment!"];
}
}

// keep track of StatusBarItem(s)
{
if(!sbitems)
{
sbitems = [NSMutableDictionary new];
}

NSMutableArray* idArray = [sbitems objectForKey: identifier];
if(!idArray)
{
// this creates a retain/release-less NSMutableArray
idArray = (NSMutableArray*) CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
[sbitems setObject: idArray forKey: identifier];
CFRelease(idArray);
}

if(idArray)
{
[idArray addObject: self];
}
}
return self;
}

return nil;
}


- (void) dealloc
{
if(sbitems)
{
NSMutableArray* idArray = [sbitems objectForKey: _identifier];

// kill the current item count
if(idArray)
{
[idArray removeObject: self];

if([idArray count] == 0)
{
// item is no longer in use by this process, let the server no
[[LSStatusBarClient sharedInstance] setProperties: nil forItem: _identifier];
}
}

[_identifier release];
[_properties release];
}

[super dealloc];
}


- (void) setProperties: (NSDictionary*) dict
{
if(!dict)
{
_properties = [NSMutableDictionary new];
}
else
{
_properties = [dict mutableCopy];
}
}


- (StatusBarAlignment) alignment
{
NSNumber* alignment = [_properties objectForKey: @"alignment"];
return alignment ? (StatusBarAlignment) [alignment intValue] : StatusBarAlignmentLeft;
}

- (void) setVisible: (BOOL) visible
{
[_properties setObject: [NSNumber numberWithBool: visible] forKey: @"visible"];

if(!_manualUpdate)
[self update];
}

- (BOOL) isVisible
{
NSNumber* visible = [_properties objectForKey: @"visible"];
return visible ? [visible boolValue] : YES;
}


- (void) setImageName: (NSString*) imageName
{
if(self.alignment & StatusBarAlignmentCenter)
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Cannot use images with a center alignment"];
}
[_properties setObject: imageName forKey: @"imageName"];

if(!_manualUpdate)
[self update];
}

- (NSString*) imageName
{
return [_properties objectForKey: @"imageName"];
}

- (void) setTitleString: (NSString*) string
{
if(self.alignment & (StatusBarAlignmentLeft | StatusBarAlignmentRight))
{
[NSException raise: NSInternalInconsistencyException format: @"LSStatusBarItem: Cannot use a title string with a side alignment"];
}

[_properties setObject: string forKey: @"titleString"];

if(!_manualUpdate)
[self update];
}

- (NSString*) titleString
{
return [_properties objectForKey: @"titleString"];
}


- (void) setManualUpdate: (BOOL) manualUpdate
{
_manualUpdate = manualUpdate;
}

- (BOOL) isManualUpdate
{
return _manualUpdate;
}

- (void) update
{
SelLog();
[[LSStatusBarClient sharedInstance] setProperties: _properties forItem: _identifier];
}


// future API

- (void) setExclusiveToApp: (NSString*) bundleId
{
[_properties setObject: bundleId forKey: @"exclusiveToApp"];
}

- (NSString*) exclusiveToApp
{
return [_properties objectForKey: @"exclusiveToApp"];
}

- (void) addTouchDelegate: (id) delegate
{
}

- (void) removeTouchDelegate: (id) delegate
{
}


@end
16 changes: 14 additions & 2 deletions StatusBarItemServer.h → LSStatusBarServer.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@

@interface StatusBarItemServer : NSObject
@interface LSStatusBarServer : NSObject
{
CPDistributedMessagingCenter *_dmc;
NSMutableDictionary* _currentMessage;
NSMutableArray* _currentKeys;
NSMutableDictionary* _currentKeyUsage;

CFRunLoopTimerRef timer;
}

+ (id) sharedInstance;

- (id) init;

- (void) appDidExit: (NSString*) bundle;

- (void) setProperties: (NSString*) message userInfo: (NSDictionary*) userInfo;
- (void) setProperties: (id) properties forItem: (NSString*) item;
- (void) setProperties: (id) properties forItem: (NSString*) item bundle: (NSString*) bundle;

- (NSMutableDictionary*) currentMessage;

- (void) incrementTimer;
- (void) updateLockStatus;

- (void) startTimer;
- (void) stopTimer;

@end
356 changes: 356 additions & 0 deletions LSStatusBarServer.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,356 @@

//#define TESTING

#import "common.h"
#import "defines.h"

#import "classes.h"
#import "LSStatusBarServer.h"

#import "LSStatusBarItem.h"


void updateLockStatus(CFNotificationCenterRef center, LSStatusBarServer* server)
{
NSLine();
[server updateLockStatus];
}

void incrementTimer()//CFRunLoopTimerRef timer, LSStatusBarServer* self)
{
[[LSStatusBarServer sharedInstance] incrementTimer];
}


@implementation LSStatusBarServer


+ (id) sharedInstance
{
static LSStatusBarServer* server;

if(!server)
{
server = [[self alloc] init];
}
return server;
}


- (id) init
{
self = [super init];
if(self)
{
_dmc = [CPDistributedMessagingCenter centerNamed: @"com.apple.springboard.libstatusbar"];
[_dmc runServerOnCurrentThread];
[_dmc registerForMessageName: @"currentMessage" target: self selector: @selector(currentMessage)];
[_dmc registerForMessageName: @"setProperties:userInfo:" target: self selector: @selector(setProperties:userInfo:)];

_currentMessage = [[NSMutableDictionary alloc] init];
_currentKeys = [[NSMutableArray alloc] init];
_currentKeyUsage = [[NSMutableDictionary alloc] init];

CFNotificationCenterRef darwin = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationCenterAddObserver(darwin, self, (CFNotificationCallback) updateLockStatus, (CFStringRef) @"com.apple.springboard.lockstate", self, NULL);

}
return self;
}




- (NSMutableDictionary*) currentMessage
{
return _currentMessage;
}


- (void) processMessageCommon
{
NSMutableArray* titleStrings = [NSMutableArray array];
for(NSString* key in _currentKeys)
{
NSDictionary* dict = [_currentMessage objectForKey: key];

if(!dict || ![dict isKindOfClass: [NSDictionary class]])
continue;

NSNumber* alignment = [dict objectForKey: @"alignment"];
if(alignment && ((StatusBarAlignment) [alignment intValue]) == StatusBarAlignmentCenter)
{
NSLine();
NSNumber* visible = [dict objectForKey: @"visible"];
if(!visible || [visible boolValue])
{
NSLine();
if(NSString* titleString = [dict objectForKey: @"titleString"])
{
NSLine();
[titleStrings addObject: titleString];
}
}
}
}

[_currentMessage setValue: _currentKeys forKey: @"keys"];
NSDesc(_currentKeys);



if([titleStrings count])
{
[_currentMessage setValue: titleStrings forKey: @"titleStrings"];

[self startTimer];
}
else
{
[_currentMessage setValue: nil forKey: @"titleStrings"];

//if(!timer)
// notify_post("libstatusbar_changed");
[self stopTimer];
}
NSDesc(_currentMessage);

notify_post("libstatusbar_changed");
}

- (void) setProperties: (id) properties forItem: (NSString*) item bundle: (NSString*) bundle
{
SelLog();
if(!item || !bundle)
{
NSLog(@"missing info. returning...");
return;
}

// get the current item usage by bundles
NSMutableArray* bundles = [_currentKeyUsage objectForKey: item];
if(!bundles)
{
bundles = [NSMutableArray array];
[_currentKeyUsage setObject: bundles forKey: item];
}

int itemIdx = [_currentKeys indexOfObject: item];

if(properties)
{
[_currentMessage setValue: properties forKey: item];

if(![bundles containsObject: bundle])
{
[bundles addObject: bundle];
}

if(itemIdx == NSNotFound)
{
[_currentKeys addObject: item];
}
}
else
{
[bundles removeObject: bundle];
NSLog(@"removing object");

if([bundles count]==0)
{
// object is truly dead
[_currentMessage setValue: nil forKey: item];

if(itemIdx!=NSNotFound)
[_currentKeys removeObjectAtIndex: itemIdx];
}
}

/*
int itemIdx = [_currentKeys indexOfObject: item];
if(!properties && itemIdx != NSNotFound)
{
[_currentKeys removeObjectAtIndex: itemIdx];
}
else if(properties && itemIdx == NSNotFound)
{
[_currentKeys addObject: item];
}
*/


// find all title strings

[self processMessageCommon];
}


- (void) appDidExit: (NSString*) bundle
{


int nKeys = [_currentKeys count];
for(int i=nKeys - 1; i>=0; i--)
{
NSString* item = [_currentKeys objectAtIndex: i];

NSMutableArray* bundles = [_currentKeyUsage objectForKey: item];
if(!bundles)
{
continue;
}

if([bundles containsObject: bundle])
{
[bundles removeObject: bundle];
NSLog(@"removing object");

if([bundles count]==0)
{
// object is truly dead
[_currentMessage setValue: nil forKey: item];

int itemIdx = [_currentKeys indexOfObject: item];
if(itemIdx!=NSNotFound)
[_currentKeys removeObjectAtIndex: itemIdx];
}
}
}

[self processMessageCommon];
}




- (void) setProperties: (NSString*) message userInfo: (NSDictionary*) userInfo
{
NSString* item = [userInfo objectForKey: @"item"];
NSDictionary* properties = [userInfo objectForKey: @"properties"];
NSString* bundleId = [userInfo objectForKey: @"bundle"];

[self setProperties: properties forItem: item bundle: bundleId];
}

- (void) startTimer
{
NSLine();

// is timer already running?
if(timer)
{
NSLog(@"timer is already active. Leaving it alone");
return;
}

// check lock status
uint64_t locked;
{
int token = 0;
notify_register_check("com.apple.springboard.lockstate", &token);
notify_get_state(token, &locked);
}

NSLine();

// reset timer state
[self stopTimer];
NSLine();

if(!locked)
{
NSLine();

NSArray* titleStrings = [_currentMessage objectForKey: @"titleStrings"];
if(titleStrings && [titleStrings count])
{
NSLine();

timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+3.5f, 3.5f, 0, 0, (CFRunLoopTimerCallBack) incrementTimer, NULL);
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes);
}
}
NSLine();

}

- (void) stopTimer
{
NSLine();

// reset the statusbar state
{
const char* notif = "libstatusbar_changed";

uint64_t value = NSNotFound;
int token = 0;
notify_register_check(notif, &token);

notify_set_state(token, value);

if(timer) // only post a notification if the timer was running
notify_post(notif);
}

// kill timer
if(timer)
{
CFRunLoopTimerInvalidate(timer);
CFRelease(timer);
timer = nil;
}
NSLine();
}


- (void) incrementTimer
{
NSLine();

NSArray* titleStrings = [_currentMessage objectForKey: @"titleStrings"];

const char* notif = "libstatusbar_changed";

if(titleStrings && [titleStrings count])
{
uint64_t value;
int token = 0;
notify_register_check(notif, &token);
notify_get_state(token, &value);

value++;
if(value > [titleStrings count])
{
value = 0;
}

NSLog(@"idx = %ld", value);

notify_set_state(token, value);
notify_post(notif);
}
else
{
[self stopTimer];
/*
NSLog(@"idx = %ld", value);
CFRunLoopTimerInvalidate(timer);
CFRelease(timer);
timer = nil;
notify_post(notif);
*/
}
}


- (void) updateLockStatus
{
[self stopTimer];
[self startTimer];
}



@end
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
TWEAK_NAME = libstatusbar
libstatusbar_OBJCC_FILES = libstatusbar.mm Classes.mm \
StatusBarItemClient.mm StatusBarItemServer.mm \
UIStatusBarCustomItem.mm UIStatusBarCustomItemView.mm
LSStatusBarClient.mm LSStatusBarServer.mm \
UIStatusBarCustomItem.mm UIStatusBarCustomItemView.mm \
LSStatusBarItem.mm # Testing.mm
libstatusbar_FRAMEWORKS = UIKit
libstatusbar_PRIVATE_FRAMEWORKS = AppSupport SpringboardServices

25 changes: 25 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Libstatusbar: pwning the statusbar for you.

Libstatusbar is chiefly a compatibility library for 3.x-like statusbar icon support under 4.x, but allows for a more advanced API for custom time strings and icon swapping.


All icons should be placed in either:

3.x style, does not support retina icons:
Silver: /System/Library/CoreServices/SpringBoard/Default_<name>.png
Black: /System/Library/CoreServices/SpringBoard/FSO_<name>.png

4.x style, supports retina (@2x) icons:
Silver: /System/Library/Frameworks/UIKit.framework/Silver_<name>.png
Black: /System/Library/Frameworks/UIKit.framework/Black_<name>.png

--- BASIC API ---

3.x-style, simply add/remove items. These will appear in the right list.

[UIApp addStatusBarImageNamed: (NSString*) name];
[UIApp removeStatusBarImageNamed: (NSString*) name];

--- ADVANCED API ---

See LSStatusBarItem.h for the API and Testing.mm for example usage
170 changes: 0 additions & 170 deletions StatusBarItemClient.mm

This file was deleted.

68 changes: 0 additions & 68 deletions StatusBarItemServer.mm

This file was deleted.

88 changes: 88 additions & 0 deletions Testing.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@

#import "common.h"
#import "defines.h"

#import "classes.h"

#import "LSStatusBarItem.h"


LSStatusBarItem* playItem;

void addPlay()
{
playItem = [[LSStatusBarItem alloc] initWithIdentifier: @"libstatusbar.Play" alignment: StatusBarAlignmentLeft];
playItem.imageName = @"Play";
// [UIApp addStatusBarImageNamed: @"Bluetooth"];
}

void playToBT()
{
playItem.imageName = @"Bluetooth";
}

LSStatusBarItem* centerItem;

LSStatusBarItem* centerItem2;


void addCenterText()
{
centerItem = [[LSStatusBarItem alloc] initWithIdentifier: @"libstatusbar.Center" alignment: StatusBarAlignmentCenter];
centerItem.titleString = @"Test string";

centerItem2 = [[LSStatusBarItem alloc] initWithIdentifier: @"libstatusbar.Center2" alignment: StatusBarAlignmentCenter];
centerItem2.titleString = @"is a reallly long test string";
}

void modifyCenterText()
{
[playItem release];

centerItem2.titleString = @"is an even longer test string to fill the screen";
}


void DelayedTesting()
{
{
{
float delay = 4.0f;
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) addPlay;

CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL);
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes);
}
{
float delay = 16.0f;
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) playToBT;

CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL);
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes);
}
{
float delay = 2.0f;
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) addCenterText;

CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL);
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes);
}

{
float delay = 30.0f;
CFRunLoopTimerCallBack callback = (CFRunLoopTimerCallBack) modifyCenterText;

CFRunLoopTimerRef waitTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()+delay, 0.0f, 0, 0, callback, NULL);
CFRunLoopAddTimer(CFRunLoopGetMain(), waitTimer, kCFRunLoopCommonModes);
}
}
}

__attribute__((constructor)) void TestingStart()
{
GETCLASS(MobileSafariWindow);
if($MobileSafariWindow)
{
DelayedTesting();
}
}
4 changes: 4 additions & 0 deletions UIStatusBarCustomItem.h
Original file line number Diff line number Diff line change
@@ -12,6 +12,10 @@

- (void) setIndicatorName: (NSString*) name;

//@property (nonatomic, retain) NSString* indicatorName;
@property (nonatomic, retain) NSDictionary* properties;


@end

void ClassCreate_UIStatusBarCustomItem();
58 changes: 57 additions & 1 deletion UIStatusBarCustomItem.mm
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@
#import "classes.h"
#import "UIStatusBarCustomItem.h"

#import "LSStatusBarItem.h"

//Class $UIStatusBarCustomItem;

int UIStatusBarCustomItem$type(UIStatusBarCustomItem* self, SEL sel)
@@ -14,6 +16,15 @@

int UIStatusBarCustomItem$leftOrder(UIStatusBarCustomItem* self, SEL sel)
{
if(NSDictionary* properties = [self properties])
{
NSNumber* nsalign = [properties objectForKey: @"alignment"];
StatusBarAlignment alignment = nsalign ? (StatusBarAlignment) [nsalign intValue] : StatusBarAlignmentRight;
if(alignment & StatusBarAlignmentLeft)
{
return 15;
}
}
return 0;
}

@@ -26,7 +37,23 @@

int UIStatusBarCustomItem$rightOrder(UIStatusBarCustomItem* self, SEL sel)
{
return 15;
if(NSDictionary* properties = [self properties])
{
NSNumber* nsalign = [properties objectForKey: @"alignment"];
StatusBarAlignment alignment = nsalign ? (StatusBarAlignment) [nsalign intValue] : StatusBarAlignmentRight;
if(alignment & StatusBarAlignmentRight)
{
return 15;
}
else
{
return 0;
}
}
else
{
return 15;
}
}

int UIStatusBarCustomItem$priority(UIStatusBarCustomItem* self, SEL sel)
@@ -41,6 +68,13 @@

NSString* UIStatusBarCustomItem$indicatorName(UIStatusBarCustomItem* self, SEL sel)
{
if(NSDictionary* properties = [self properties])
{
NSString* name = [properties objectForKey: @"imageName"];
if(name)
return name;
}

NSString* &_indicatorName(MSHookIvar<NSString*>(self, "_indicatorName"));
return _indicatorName;
}
@@ -53,6 +87,21 @@

}


NSDictionary* UIStatusBarCustomItem$properties(UIStatusBarCustomItem* self, SEL sel)
{
NSDictionary* &_properties(MSHookIvar<NSDictionary*>(self, "_properties"));
return _properties;
}

void UIStatusBarCustomItem$setProperties$(UIStatusBarCustomItem* self, SEL sel, NSDictionary* properties)
{
NSDictionary* &_properties(MSHookIvar<NSDictionary*>(self, "_properties"));
[_properties release];
_properties = [properties retain];
}


UIStatusBarItemView* UIStatusBarCustomItem$viewForManager$(id self, SEL sel, id manager)
{
CFMutableDictionaryRef &_views(MSHookIvar<CFMutableDictionaryRef>(self, "_views"));
@@ -110,8 +159,15 @@ void ClassCreate_UIStatusBarCustomItem()

class_addMethod($UIStatusBarCustomItem, @selector(removeAllViews), (IMP) UIStatusBarCustomItem$removeAllViews, "v@:");


class_addIvar($UIStatusBarCustomItem, "_properties", sizeof(id), 0x4, "@");

class_addIvar($UIStatusBarCustomItem, "_indicatorName", sizeof(id), 0x4, "@");
class_addMethod($UIStatusBarCustomItem, @selector(indicatorName), (IMP) UIStatusBarCustomItem$indicatorName, "@@:");
class_addMethod($UIStatusBarCustomItem, @selector(setIndicatorName:), (IMP) UIStatusBarCustomItem$setIndicatorName$, "v@:@");

class_addMethod($UIStatusBarCustomItem, @selector(properties), (IMP) UIStatusBarCustomItem$properties, "@@:");
class_addMethod($UIStatusBarCustomItem, @selector(setProperties:), (IMP) UIStatusBarCustomItem$setProperties$, "v@:@");

objc_registerClassPair($UIStatusBarCustomItem);
}
3 changes: 3 additions & 0 deletions classlist.h
Original file line number Diff line number Diff line change
@@ -9,3 +9,6 @@ CLCLASS(SpringBoard);

CLCLASS(UIStatusBarCustomItemView);
CLCLASS(UIStatusBarCustomItem);

CLCLASS(UIStatusBarItemView);
CLCLASS(UIStatusBarTimeItemView);
4 changes: 4 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
@@ -23,8 +23,12 @@ extern "C" int SBSSpringBoardServerPort();
#import "UIStatusBarForegroundView.h"
#import "UIStatusBarServer.h"

#import "UIStatusBar.h"
#import "UIStatusBarTimeItemView.h"

#import "CPDistributedMessagingCenter.h"

// structures listed here are NOT valid for iOS 4.2+ - at least two more "items" exist
/*
struct StatusBarData
{
399 changes: 228 additions & 171 deletions libstatusbar.mm

Large diffs are not rendered by default.

0 comments on commit a92bf30

Please sign in to comment.