Permalink
Browse files

Added: Search panel by clicking on the Status bar.

  • Loading branch information...
1 parent 54088bc commit 2f67f95034c4787dad935f475ec9c5323aed4f64 @shpakovski committed Jul 5, 2011
View
445 Panel.xib

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -11,6 +11,14 @@
DD4F7C1513C30F9F00825C6E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C1413C30F9F00825C6E /* main.m */; };
DD4F7C1C13C30F9F00825C6E /* ApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C1B13C30F9F00825C6E /* ApplicationDelegate.m */; };
DD4F7C1F13C30F9F00825C6E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD4F7C1D13C30F9F00825C6E /* MainMenu.xib */; };
+ DD4F7C3813C317A500825C6E /* MenubarController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C3713C317A500825C6E /* MenubarController.m */; };
+ DD4F7C3C13C3180800825C6E /* StatusItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C3B13C3180800825C6E /* StatusItemView.m */; };
+ DD4F7C3F13C318D600825C6E /* PanelController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C3E13C318D600825C6E /* PanelController.m */; };
+ DD4F7C4113C31B4A00825C6E /* Panel.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD4F7C4013C31B4A00825C6E /* Panel.xib */; };
+ DD4F7C4413C31BD200825C6E /* Panel.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C4313C31BD200825C6E /* Panel.m */; };
+ DD4F7C4713C3208500825C6E /* BackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4F7C4613C3208500825C6E /* BackgroundView.m */; };
+ DD4F7C4B13C322FA00825C6E /* Status.png in Resources */ = {isa = PBXBuildFile; fileRef = DD4F7C4913C322FA00825C6E /* Status.png */; };
+ DD4F7C4C13C322FA00825C6E /* StatusHighlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = DD4F7C4A13C322FA00825C6E /* StatusHighlighted.png */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -25,6 +33,19 @@
DD4F7C1A13C30F9F00825C6E /* ApplicationDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApplicationDelegate.h; sourceTree = "<group>"; };
DD4F7C1B13C30F9F00825C6E /* ApplicationDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApplicationDelegate.m; sourceTree = "<group>"; };
DD4F7C1E13C30F9F00825C6E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ DD4F7C3613C317A500825C6E /* MenubarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenubarController.h; sourceTree = "<group>"; };
+ DD4F7C3713C317A500825C6E /* MenubarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MenubarController.m; sourceTree = "<group>"; };
+ DD4F7C3A13C3180800825C6E /* StatusItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatusItemView.h; sourceTree = "<group>"; };
+ DD4F7C3B13C3180800825C6E /* StatusItemView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StatusItemView.m; sourceTree = "<group>"; };
+ DD4F7C3D13C318D600825C6E /* PanelController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PanelController.h; sourceTree = "<group>"; };
+ DD4F7C3E13C318D600825C6E /* PanelController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PanelController.m; sourceTree = "<group>"; };
+ DD4F7C4013C31B4A00825C6E /* Panel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = Panel.xib; sourceTree = "<group>"; };
+ DD4F7C4213C31BD200825C6E /* Panel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Panel.h; sourceTree = "<group>"; };
+ DD4F7C4313C31BD200825C6E /* Panel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Panel.m; sourceTree = "<group>"; };
+ DD4F7C4513C3208500825C6E /* BackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackgroundView.h; sourceTree = "<group>"; };
+ DD4F7C4613C3208500825C6E /* BackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BackgroundView.m; sourceTree = "<group>"; };
+ DD4F7C4913C322FA00825C6E /* Status.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Status.png; sourceTree = "<group>"; };
+ DD4F7C4A13C322FA00825C6E /* StatusHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusHighlighted.png; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -73,6 +94,7 @@
isa = PBXGroup;
children = (
DD4F7C2613C311DF00825C6E /* Controllers */,
+ DD4F7C3913C317EC00825C6E /* Views */,
DD4F7C0F13C30F9F00825C6E /* Supporting Files */,
);
name = Sources;
@@ -93,13 +115,18 @@
children = (
DD4F7C1A13C30F9F00825C6E /* ApplicationDelegate.h */,
DD4F7C1B13C30F9F00825C6E /* ApplicationDelegate.m */,
+ DD4F7C3613C317A500825C6E /* MenubarController.h */,
+ DD4F7C3713C317A500825C6E /* MenubarController.m */,
+ DD4F7C3D13C318D600825C6E /* PanelController.h */,
+ DD4F7C3E13C318D600825C6E /* PanelController.m */,
);
name = Controllers;
sourceTree = "<group>";
};
DD4F7C2813C3123E00825C6E /* User Interface */ = {
isa = PBXGroup;
children = (
+ DD4F7C4813C322D800825C6E /* Graphics */,
DD4F7C2913C3124300825C6E /* XIBs */,
);
name = "User Interface";
@@ -109,10 +136,33 @@
isa = PBXGroup;
children = (
DD4F7C1D13C30F9F00825C6E /* MainMenu.xib */,
+ DD4F7C4013C31B4A00825C6E /* Panel.xib */,
);
name = XIBs;
sourceTree = "<group>";
};
+ DD4F7C3913C317EC00825C6E /* Views */ = {
+ isa = PBXGroup;
+ children = (
+ DD4F7C4213C31BD200825C6E /* Panel.h */,
+ DD4F7C4313C31BD200825C6E /* Panel.m */,
+ DD4F7C3A13C3180800825C6E /* StatusItemView.h */,
+ DD4F7C3B13C3180800825C6E /* StatusItemView.m */,
+ DD4F7C4513C3208500825C6E /* BackgroundView.h */,
+ DD4F7C4613C3208500825C6E /* BackgroundView.m */,
+ );
+ name = Views;
+ sourceTree = "<group>";
+ };
+ DD4F7C4813C322D800825C6E /* Graphics */ = {
+ isa = PBXGroup;
+ children = (
+ DD4F7C4913C322FA00825C6E /* Status.png */,
+ DD4F7C4A13C322FA00825C6E /* StatusHighlighted.png */,
+ );
+ name = Graphics;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -161,6 +211,9 @@
buildActionMask = 2147483647;
files = (
DD4F7C1F13C30F9F00825C6E /* MainMenu.xib in Resources */,
+ DD4F7C4113C31B4A00825C6E /* Panel.xib in Resources */,
+ DD4F7C4B13C322FA00825C6E /* Status.png in Resources */,
+ DD4F7C4C13C322FA00825C6E /* StatusHighlighted.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -173,6 +226,11 @@
files = (
DD4F7C1513C30F9F00825C6E /* main.m in Sources */,
DD4F7C1C13C30F9F00825C6E /* ApplicationDelegate.m in Sources */,
+ DD4F7C3813C317A500825C6E /* MenubarController.m in Sources */,
+ DD4F7C3C13C3180800825C6E /* StatusItemView.m in Sources */,
+ DD4F7C3F13C318D600825C6E /* PanelController.m in Sources */,
+ DD4F7C4413C31BD200825C6E /* Panel.m in Sources */,
+ DD4F7C4713C3208500825C6E /* BackgroundView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1,7 +1,15 @@
-@interface ApplicationDelegate : NSObject <NSApplicationDelegate> {
- NSWindow *window;
+#import "MenubarController.h"
+#import "PanelController.h"
+
+@interface ApplicationDelegate : NSObject <NSApplicationDelegate, PanelControllerDelegate> {
+@private
+ MenubarController *_menubarController;
+ PanelController *_panelController;
}
-@property (assign) IBOutlet NSWindow *window;
+@property (nonatomic, retain) MenubarController *menubarController;
+@property (nonatomic, readonly) PanelController *panelController;
+
+- (IBAction)togglePanel:(id)sender;
@end
@@ -1,12 +1,77 @@
#import "ApplicationDelegate.h"
+void *kContextActivePanel = &kContextActivePanel;
+
@implementation ApplicationDelegate
-@synthesize window;
+@synthesize menubarController = _menubarController;
+
+#pragma mark -
+
+- (void)dealloc
+{
+ [_menubarController release];
+ [_panelController removeObserver:self forKeyPath:@"hasActivePanel"];
+ [_panelController release];
+
+ [super dealloc];
+}
+
+#pragma mark -
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if (context == kContextActivePanel)
+ {
+ self.menubarController.hasActiveIcon = self.panelController.hasActivePanel;
+ }
+ else
+ {
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+ }
+}
+
+#pragma mark - NSApplicationDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
- // Insert code here to initialize your application
+ // Install icon into the menu bar
+ [self.menubarController = [[MenubarController alloc] init] release];
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ // Remove the icon from the menu bar
+ self.menubarController = nil;
+
+ return NSTerminateNow;
+}
+
+#pragma mark - Actions
+
+- (IBAction)togglePanel:(id)sender
+{
+ self.menubarController.hasActiveIcon = !self.menubarController.hasActiveIcon;
+ self.panelController.hasActivePanel = self.menubarController.hasActiveIcon;
+}
+
+#pragma mark - Public accessors
+
+- (PanelController *)panelController
+{
+ if (_panelController == nil)
+ {
+ _panelController = [[PanelController alloc] initWithDelegate:self];
+ [_panelController addObserver:self forKeyPath:@"hasActivePanel" options:NSKeyValueObservingOptionInitial context:kContextActivePanel];
+ }
+ return _panelController;
+}
+
+#pragma mark - PanelControllerDelegate
+
+- (StatusItemView *)statusItemViewForPanelController:(PanelController *)controller
+{
+ return self.menubarController.statusItemView;
}
@end
View
@@ -0,0 +1,11 @@
+#define ARROW_WIDTH 12
+#define ARROW_HEIGHT 8
+
+@interface BackgroundView : NSView
+{
+ NSInteger _arrowX;
+}
+
+@property (nonatomic, assign) NSInteger arrowX;
+
+@end
View
@@ -0,0 +1,75 @@
+#import "BackgroundView.h"
+
+#define FILL_OPACITY .9
+#define STROKE_OPACITY .8
+
+#define LINE_THICKNESS 1
+#define CORNER_RADIUS 6
+
+#define SEARCH_INSET 10
+
+@implementation BackgroundView
+
+@synthesize arrowX = _arrowX;
+
+#pragma mark -
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+ NSRect contentRect = NSInsetRect([self bounds], LINE_THICKNESS, LINE_THICKNESS);
+ NSBezierPath *path = [NSBezierPath bezierPath];
+
+ [path moveToPoint:NSMakePoint(_arrowX, NSMaxY(contentRect))];
+ [path lineToPoint:NSMakePoint(_arrowX + ARROW_WIDTH / 2, NSMaxY(contentRect) - ARROW_HEIGHT)];
+ [path lineToPoint:NSMakePoint(NSMaxX(contentRect) - CORNER_RADIUS, NSMaxY(contentRect) - ARROW_HEIGHT)];
+
+ NSPoint topRightCorner = NSMakePoint(NSMaxX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT);
+ [path curveToPoint:NSMakePoint(NSMaxX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT - CORNER_RADIUS)
+ controlPoint1:topRightCorner controlPoint2:topRightCorner];
+
+ [path lineToPoint:NSMakePoint(NSMaxX(contentRect), NSMinY(contentRect) + CORNER_RADIUS)];
+
+ NSPoint bottomRightCorner = NSMakePoint(NSMaxX(contentRect), NSMinY(contentRect));
+ [path curveToPoint:NSMakePoint(NSMaxX(contentRect) - CORNER_RADIUS, NSMinY(contentRect))
+ controlPoint1:bottomRightCorner controlPoint2:bottomRightCorner];
+
+ [path lineToPoint:NSMakePoint(NSMinX(contentRect) + CORNER_RADIUS, NSMinY(contentRect))];
+
+ [path curveToPoint:NSMakePoint(NSMinX(contentRect), NSMinY(contentRect) + CORNER_RADIUS)
+ controlPoint1:contentRect.origin controlPoint2:contentRect.origin];
+
+ [path lineToPoint:NSMakePoint(NSMinX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT - CORNER_RADIUS)];
+
+ NSPoint topLeftCorner = NSMakePoint(NSMinX(contentRect), NSMaxY(contentRect) - ARROW_HEIGHT);
+ [path curveToPoint:NSMakePoint(NSMinX(contentRect) + CORNER_RADIUS, NSMaxY(contentRect) - ARROW_HEIGHT)
+ controlPoint1:topLeftCorner controlPoint2:topLeftCorner];
+
+ [path lineToPoint:NSMakePoint(_arrowX - ARROW_WIDTH / 2, NSMaxY(contentRect) - ARROW_HEIGHT)];
+ [path closePath];
+
+ [[NSColor colorWithDeviceWhite:1 alpha:FILL_OPACITY] setFill];
+ [path fill];
+
+ [NSGraphicsContext saveGraphicsState];
+
+ NSBezierPath *clip = [NSBezierPath bezierPathWithRect:[self bounds]];
+ [clip appendBezierPath:path];
+ [clip addClip];
+
+ [path setLineWidth:LINE_THICKNESS * 2];
+ [[NSColor colorWithDeviceWhite:0.5 alpha:STROKE_OPACITY] setStroke];
+ [path stroke];
+
+ [NSGraphicsContext restoreGraphicsState];
+}
+
+#pragma mark -
+#pragma mark Public accessors
+
+- (void)setArrowX:(NSInteger)value
+{
+ _arrowX = value;
+ [self setNeedsDisplay:YES];
+}
+
+@end
View
@@ -0,0 +1,16 @@
+#define STATUS_ITEM_VIEW_WIDTH 24.0
+
+#pragma mark -
+
+@class StatusItemView;
+
+@interface MenubarController : NSObject {
+@private
+ StatusItemView *_statusItemView;
+}
+
+@property (nonatomic, assign) BOOL hasActiveIcon;
+@property (nonatomic, readonly) NSStatusItem *statusItem;
+@property (nonatomic, readonly) StatusItemView *statusItemView;
+
+@end
View
@@ -0,0 +1,52 @@
+#import "MenubarController.h"
+#import "StatusItemView.h"
+
+@implementation MenubarController
+
+@synthesize statusItemView = _statusItemView;
+
+#pragma mark -
+
+- (id)init
+{
+ if ((self = [super init]))
+ {
+ // Install status item into the menu bar
+ NSStatusItem *statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:STATUS_ITEM_VIEW_WIDTH];
+ _statusItemView = [[StatusItemView alloc] initWithStatusItem:statusItem];
+ _statusItemView.image = [NSImage imageNamed:@"Status"];
+ _statusItemView.alternateImage = [NSImage imageNamed:@"StatusHighlighted"];
+ _statusItemView.action = @selector(togglePanel:);
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSStatusBar systemStatusBar] removeStatusItem:self.statusItem];
+ [_statusItemView release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Public accessors
+
+- (NSStatusItem *)statusItem
+{
+ NSStatusItem *item = self.statusItemView.statusItem;
+ return item;
+}
+
+#pragma mark -
+
+- (BOOL)hasActiveIcon
+{
+ return self.statusItemView.isHighlighted;
+}
+
+- (void)setHasActiveIcon:(BOOL)flag
+{
+ self.statusItemView.isHighlighted = flag;
+}
+
+@end
View
@@ -0,0 +1,2 @@
+@interface Panel : NSPanel
+@end
View
@@ -0,0 +1,15 @@
+#import "Panel.h"
+
+@implementation Panel
+
+- (BOOL)canBecomeKeyWindow;
+{
+ return YES;
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent;
+{
+ [[self contentView] setNeedsDisplay:YES];
+}
+
+@end
Oops, something went wrong.

0 comments on commit 2f67f95

Please sign in to comment.