How do I create a modal sheet window exclusively by programming. Interface builder seems to me over the hand, I'm at the beginning and I want to learn programming, not how I arrange some elements graphically.
I've heard on several programmers that is possible.
I tried without success:
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSWindow* mywindow;
NSButton* button;
IBOutlet NSPanel* theSheet;
}
- (void) buildWnd;
#end
#implementation AppDelegate
- (void) buildWnd {
button = [[[NSButton alloc] initWithFrame:NSMakeRect(50, 225, 90, 25)] autorelease];
[button setTitle:#"button"];
[button setTarget:self];
[button setAction:#selector(OnbuttonClick:)];
[button setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
mywindow = [[NSWindow alloc] initWithContentRect: NSMakeRect(100, 100, 700, 500) styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable backing: NSBackingStoreBuffered defer: NO];
[mywindow center];
[mywindow setTitle:#"Sheet example"];
[[mywindow contentView] addSubview:button];
[mywindow setIsVisible:YES];
}
- (IBAction) showTheSheet:(id)sender {
}
-(IBAction) endTheSheet:(id)sender {
[mywindow endSheet: theSheet];
}
- (void) applicationWillFinishLaunching: (NSNotification *)notification {
[self buildMenu];
[self buildWnd];
}
- (void) applicationDidFinishLaunching: (NSNotification *)notification {
}
- (IBAction) OnButtonClick:(id)sender {
NSLog(#"OnButtonClick");
[mywindow beginSheet: theSheet
completionHandler:^(NSModalResponse returnCode) {
[NSApp stopModalWithCode: returnCode];
}];
[NSApp runModalForWindow: theSheet];
}
#end
int main() {
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application run];
return 0;
}
I receive this error message: AppDelegate OnbuttonClick: unrecognized selector sent to instance.
Where I'm wrong please?
You neglected to set up the sheet. This example should run in Xcode by replacing the main.m with the code below and deleting the pre-supplied AppDelegate files:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
NSPanel *sheet;
}
- (void) buildWnd;
#end
#implementation AppDelegate
- (void) showBtnAction:(id)sender {
[window beginSheet: sheet completionHandler:^(NSModalResponse returnCode) {
[NSApp stopModalWithCode: returnCode];
}];
[NSApp runModalForWindow: sheet];
}
-(void) hideSheet:(id)sender {
[window endSheet: sheet];
}
- (void) buildWnd {
window = [[NSWindow alloc] initWithContentRect: NSMakeRect(100, 100, 700, 500) styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable backing: NSBackingStoreBuffered defer: NO];
[window center];
[window setTitle:#"Sheet example"];
[window setIsVisible:YES];
// **** Sheet Panel **** //
sheet = [[NSPanel alloc] initWithContentRect:NSMakeRect( 0, 0, 500, 450 )
styleMask:NSWindowStyleMaskDocModalWindow backing:NSBackingStoreBuffered defer:YES];
[sheet center];
[sheet setTitle:#"NSPanel"];
// **** OK Button on Sheet **** //
NSButton *okayBtn = [[NSButton alloc] initWithFrame:NSMakeRect(50, 225, 50, 25)];
[okayBtn setTitle:#"OK"];
[okayBtn setBezelStyle:NSBezelStyleRounded ];
[okayBtn setTarget:self];
[okayBtn setAction:#selector(hideSheet:)];
[[sheet contentView] addSubview:okayBtn];
// **** Show Button **** //
NSButton *showBtn = [[NSButton alloc] initWithFrame:NSMakeRect(50, 225, 150, 25)];
[showBtn setTitle:#"Show sheet"];
[showBtn setBezelStyle:NSBezelStyleRounded ];
[showBtn setAction:#selector(showBtnAction:)];
[showBtn setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
[[window contentView] addSubview:showBtn];
// **** Quit btn **** //
NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect(650, 5, 40, 40 )];
[quitBtn setBezelStyle:NSBezelStyleCircular ];
[quitBtn setTitle: #"Q" ];
[quitBtn setAutoresizingMask: NSViewMinXMargin];
[quitBtn setAction:#selector(terminate:)];
[[window contentView] addSubview: quitBtn];
}
- (void) applicationWillFinishLaunching: (NSNotification *)notification {
[self buildWnd];
}
- (void) applicationDidFinishLaunching: (NSNotification *)notification {
}
#end
int main() {
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application run];
return 0;
}
Related
The menu bar of the MAC should display the menu title and submenus I set.
NSMenu *subMenu = [[NSMenu alloc] initWithTitle:YMLocalizedString(#"assistant.menu.title")];
[subMenu addItems:#[preventRevokeItem,
autoAuthItem,
groupMgrMenu,
newWeChatItem,
forwardAndReplyItem,
]];
NSMenuItem *menuItem = [[NSMenuItem alloc] init];
menuItem.target = self;
menuItem.enabled = NO;
[menuItem setTitle:YMLocalizedString(#"assistant.menu.title")];
[menuItem setSubmenu:subMenu];
[[[NSApplication sharedApplication] mainMenu] addItem:menuItem];
This example may be run in Xcode by deleting the main.m code and replacing it with the following. Also delete the pre-supplied AppDelegate files.
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
}
- (void) menuAction: (id)sender;
- (void) buildMenu;
- (void) buildWindow;
#end
#implementation AppDelegate
- (void) menuAction: (id)sender {
NSBeep();
NSLog(#"%#", sender);
}
- (void) buildMenu {
NSMenu *menubar = [NSMenu new];
NSMenuItem *menuBarItem = [NSMenuItem new];
[menubar addItem:menuBarItem];
[NSApp setMainMenu:menubar];
NSMenu *appMenu = [NSMenu new];
NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle:#"Quit"
action:#selector(terminate:) keyEquivalent:#"q"];
[appMenu addItem:quitMenuItem];
[menuBarItem setSubmenu:appMenu];
// **** Asst Menu **** //
NSMenuItem *asstMenuItem = [menubar addItemWithTitle:#"" action:nil keyEquivalent:#""];
NSMenu *asstMenu = [[NSMenu alloc] initWithTitle:#"assistant.menu.title"];
[menubar setSubmenu: asstMenu forItem:asstMenuItem];
NSArray *itemArray = #[#"preventRevokeItem", #"autoAuthItem", #"groupMgrMenu", #"newWeChatItem", #"forwardAndReplyItem"];
[asstMenu addItemWithTitle: itemArray[0] action:#selector(menuAction:) keyEquivalent:#""];
[asstMenu addItemWithTitle: itemArray[1] action:#selector(menuAction:) keyEquivalent:#""];
[asstMenu addItemWithTitle: itemArray[2] action:#selector(menuAction:) keyEquivalent:#""];
[asstMenu addItemWithTitle: itemArray[3] action:#selector(menuAction:) keyEquivalent:#""];
[asstMenu addItemWithTitle: itemArray[4] action:#selector(menuAction:) keyEquivalent:#""];
}
- (void) buildWindow {
#define _wndW 300
#define _wndH 250
window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )
styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable
backing: NSBackingStoreBuffered defer: NO];
[window center];
[window setTitle: #"Test window"];
[window makeKeyAndOrderFront: nil];
// ***** Quit btn ***** //
NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 5, 40, 40 )];
[quitBtn setBezelStyle:NSBezelStyleCircular ];
[quitBtn setTitle: #"Q" ];
[quitBtn setAutoresizingMask: NSViewMinXMargin];
[quitBtn setAction:#selector(terminate:)];
[[window contentView] addSubview: quitBtn];
}
- (void) applicationWillFinishLaunching: (NSNotification *)notification {
[self buildMenu];
[self buildWindow];
}
- (void) applicationDidFinishLaunching: (NSNotification *)notification {
}
#end
int main () {
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application run];
return 0;
}
I have embedded an NSTableView inside an NSScrollView as shown in this example but for some reason, setting the column width only works correctly when initially setting it. Changing it later, i.e. in response to a button click, doesn't do anything at all. I do it like this:
[col setMinWidth:1000];
[col setMaxWidth:1000];
[col setWidth:1000];
After those calls col.width correctly returns 1000 but the NSTableView doesn't show the change. It still looks as before, i.e. longer entries are still cut off using ... even though the column width is 1000 points now.
I have tried to call [tableView setNeedsDisplay:YES] after changing the column width but it doesn't help. Calling setNeedsDisplay on the NSScrollView doesn't help either. I've also tried playing with NSTableColumn's resizingMask and NSTableView's columnAutoresizingStyle but all to no avail. Trying to change the column width just doesn't work here. Any ideas?
EDIT
Here's the code for reference:
listDelegate = [[MyListDelegate alloc] initWithChoices:array];
scrollview = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 52, rect.size.width - 2 * 20, 200)];
tableview = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, rect.size.width - 2 * 20 - 16, 200)];
column = [[NSTableColumn alloc] initWithIdentifier:#"Column"];
[column setWidth:400];
[tableview addTableColumn:column];
[tableview setHeaderView:nil];
[tableview setDelegate:listDelegate];
[tableview setDataSource:listDelegate];
[tableview reloadData];
[scrollview setDocumentView:tableview];
[scrollview setHasVerticalScroller:YES];
[scrollview setHasHorizontalScroller:YES];
[[win contentView] addSubview:scrollview];
[scrollview release];
[column release];
The list delegate looks like this:
#interface MyListDelegate : NSObject
{
NSArray *choices;
}
- (id)initWithChoices:(NSArray *)c;
#end
#implementation MyListDelegate
- (id)initWithChoices:(NSArray *)c
{
if(!(self = [super init])) return nil;
choices = c;
return self;
}
- (int)numberOfRowsInTableView:(NSTableView *)_tableView
{
return (int) [choices count];
}
- (id)tableView:(NSTableView *)_tableView objectValueForTableColumn:(NSTableColumn *) tableColumn row:(int)row
{
return [choices objectAtIndex:row];
}
- (BOOL)tableView:(NSTableView *)_tableView shouldEditTableColumn:(NSTableColumn *) tableColumn row:(int)row
{
return NO;
}
#end
And when the button is pressed, the following code is executed:
NSTableColumn *col = [[tableview tableColumns] objectAtIndex:0];
[col setMinWidth:1000];
[col setMaxWidth:1000];
[col setWidth:1000];
It looks like a bug to me. [col setMinWidth:1000] also sets the width to 1000 but doesn't update the table view. [col setWidth:1000] doesn't do anything because the width is 1000. Fix: set the width first:
[col setWidth:1000];
[col setMinWidth:1000];
[col setMaxWidth:1000];
Here's one technique to change the column width of a table view.
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate, NSTableViewDataSource> {
NSWindow *window;
NSTableColumn *column1;
}
- (void) myBtnAction;
- (void) buildMenu;
- (void) buildWindow;
#end
#implementation AppDelegate
- (void) myBtnAction {
[column1 setWidth:150];
}
- (void) buildMenu {
NSMenu *menubar = [NSMenu new];
NSMenuItem *menuBarItem = [NSMenuItem new];
[menubar addItem:menuBarItem];
[NSApp setMainMenu:menubar];
NSMenu *appMenu = [NSMenu new];
NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle:#"Quit" action:#selector(terminate:) keyEquivalent:#"q"];
[appMenu addItem:quitMenuItem];
[menuBarItem setSubmenu:appMenu];
}
- (void) buildWindow {
#define _wndW 500
#define _wndH 350
window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )
styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable
backing: NSBackingStoreBuffered defer: NO];
[window center];
[window setTitle: #"Test window"];
[window makeKeyAndOrderFront: nil];
// **** TableView_SO **** //
NSScrollView *scrlView = [[NSScrollView alloc] initWithFrame:NSMakeRect(60, 100, 380, 200)];
NSTableView *tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 364, 200)];
// create columns for our table
column1 = [[NSTableColumn alloc] initWithIdentifier:#"Col1"];
NSTableColumn * column2 = [[NSTableColumn alloc] initWithIdentifier:#"Col2"];
[column1 setWidth:252];
[column2 setWidth:198];
// generally you want to add at least one column to the table view.
[tableView addTableColumn:column1];
[tableView addTableColumn:column2];
[tableView setDelegate:self];
[tableView setDataSource:self];
[tableView reloadData];
// embed table view in the scroll view, and add the scroll view to window.
[scrlView setDocumentView:tableView];
[scrlView setHasVerticalScroller:YES];
[[window contentView] addSubview:scrlView];
// **** Button **** //
NSButton *myBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, 30, 135, 30 )];
[myBtn setBezelStyle:NSBezelStyleRounded ];
[myBtn setTitle: #"Change Col1 Width"];
[myBtn setAction: #selector (myBtnAction)];
[[window contentView] addSubview: myBtn];
// **** Quit btn **** //
NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 5, 40, 40 )];
[quitBtn setBezelStyle:NSBezelStyleCircular ];
[quitBtn setTitle: #"Q" ];
[quitBtn setAutoresizingMask: NSViewMinXMargin];
[quitBtn setAction:#selector(terminate:)];
[[window contentView] addSubview: quitBtn];
}
- (void) applicationWillFinishLaunching: (NSNotification *)notification {
[self buildMenu];
[self buildWindow];
}
- (void) applicationDidFinishLaunching: (NSNotification *)notification {
}
#end
int main (){
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application run];
return 0;
}
I have created a custom NSView with an AVPlayer embedded and it is not showing at all
this is my header:
#interface VideoPlayer : NSView
- (void)loadVideo;
#end
Implementation:
#implementation VideoPlayer
AVPlayer *avPlayer;
AVPlayerLayer* playerLayer;
- (instancetype)initWithFrame:(NSRect)rect {
self = [super initWithFrame:rect];
[self setWantsLayer:YES];
[self setNeedsDisplay:YES];
self.hidden = NO;
return self;
}
-(void) loadVideo {
[avPlayer pause];
avPlayer = nil;
playerLayer = nil;
NSURL *videoURL = [NSURL fileURLWithPath:#"file://~/Documents/tests.mp4"];
//same error with a valid url
//NSURL *videoURL = [NSURL URLWithString:#"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4"];
avPlayer = [AVPlayer playerWithURL:videoURL];
playerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];
playerLayer.frame = self.frame;//or your desired CGRect
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
//playerLayer.masksToBounds = YES;
[self.layer addSublayer:playerLayer];
[avPlayer play];
}
#end
And this is how I am creating the view:
view = [[VideoPlayer alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)];
view.hidden = false;
[view loadVideo];
[parent_view addSubview:view];
I have tried multiple combinations, but the result is always the same... Nothing is being rendered on the application.
On the other hand, if I override the method drawRect in my view like this:
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
[[NSColor whiteColor] setFill];
NSRectFill(dirtyRect);
[super drawRect:dirtyRect];
}
I am getting a white rectangle where it is suppose to show my video which is expected. So I assume that I am missing something else, but most of the examples are using UIView which is not an option for me at this moment (I am working with some specific constraints)
Any thoughts?
Thank you
Update:
This finally worked for me:
-(void) loadVideo {
AVPlayer *avPlayer = [AVPlayer playerWithURL:[NSURL URLWithString:#"file://localhost/Users/xxxxxxxx/Documents/xxxxxxx.mp4"]];
AVPlayerView *playerView = [[AVPlayerView alloc] initWithFrame:self.bounds];
[playerView setPlayer:avPlayer];
[self addSubview:playerView];
[playerView.player play];
}
To perhaps make things a little clearer the following source code will create a basic AVPlayer for audio files. Note that the addition of both AVKit and AVFoundation frameworks are required for AVPlayerView and AVPlayer respectively. The code uses automatic reference counting and may be run in Terminal or used in Xcode by replacing main.m and AppDelegate and deleting the main nib in info.plist. To run in Terminal, copy/paste code into a file named avplayer.m and use the cmdLine as shown below. Apple docs state that it only runs on MacOS.
/*
To run in Terminal: clang avplayer.m -fobjc-arc -framework Cocoa -framework AVKit -framework AVFoundation -o avplayer && ./avplayer
*/
#import <Cocoa/Cocoa.h>
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
AVPlayerView *playerView;
}
- (void) openAction;
- (void) buildMenu;
- (void) buildWindow;
#end
#implementation AppDelegate
- (void) openAction {
NSOpenPanel *op = [NSOpenPanel openPanel];
if ( [op runModal] == NSModalResponseOK ) {
AVPlayer *player = [AVPlayer playerWithURL:[op URL]];
[playerView setPlayer:player];
[window setTitleWithRepresentedFilename:[[op URL]lastPathComponent]];
}
}
- (void) buildMenu {
NSMenu *menubar = [NSMenu new];
NSMenuItem *menuBarItem = [NSMenuItem new] ;
[menubar addItem:menuBarItem];
[NSApp setMainMenu:menubar];
NSMenu *appMenu = [NSMenu new];
NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle:#"Quit" action:#selector(terminate:) keyEquivalent:#"q"];
[appMenu addItem:quitMenuItem];
[menuBarItem setSubmenu:appMenu];
}
- (void) buildWindow {
#define _wndW 500
#define _wndH 400
window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH ) styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable backing: NSBackingStoreBuffered defer: NO];
[window center];
[window setTitle: #"Test window"];
[window makeKeyAndOrderFront: nil];
// **** AVPlayerView **** //
playerView = [[AVPlayerView alloc] initWithFrame:NSMakeRect( 0, 60, _wndW, _wndH - 60)];
[[window contentView] addSubview:playerView];
// **** Open Button **** //
NSButton *myBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, 20, 125, 30 )];
[myBtn setBezelStyle:NSBezelStyleRounded ];
[myBtn setTitle: #"Open audio file"];
[myBtn setAction: #selector (openAction)];
[[window contentView] addSubview: myBtn];
// **** Quit btn **** //
NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 5, 40, 40 )];
[quitBtn setBezelStyle:NSBezelStyleCircular ];
[quitBtn setTitle: #"Q" ];
[quitBtn setAutoresizingMask: NSViewMinXMargin];
[quitBtn setAction:#selector(terminate:)];
[[window contentView] addSubview: quitBtn];
}
- (void) applicationWillFinishLaunching: (NSNotification *)notification {
[self buildMenu];
[self buildWindow];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return YES;
}
#end
int main () {
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application run];
return 0;
}
Make sure that you add the AVKit framework to your project.
There is a header in AVKit framework called AVPlayerView.h
Then all you need to do to see the player is to call it:
// **** AVPlayer ***** //
AVPlayerView *playerView = [[AVPlayerView alloc] initWithFrame:NSMakeRect( 0, 0, _wndW, _wndH - 100)];
[[window contentView] addSubview:playerView];
I have a programmatic demo which I could post if you are unable to get it to work.
Here is the thing:
I have created a custom NSMenuItem with a custom NSView in it.
Everything works fine except that I can't get the NSMenuItem to get highlighted (= change the background color on mouseover).
I'm trying to do it inside the drawRect method, as shown in other answers posted here.
What am I doing wrong?
The NSView subclass:
#interface customView : NSView
#end
#implementation customView
- (id)initWithFrame:(NSRect)frame
{
NSRect theRect = NSMakeRect(0, 0, 200, 30);
self = [super initWithFrame:theRect];
if (self) {
NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:theRect
options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow |NSTrackingActiveAlways)
owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
return self;
}
#define menuItem ([self enclosingMenuItem])
- (void) drawRect: (NSRect) rect {
BOOL isHighlighted = [menuItem isHighlighted];
if (isHighlighted) {
//this nslog never happens
NSLog(#"it's highlighted");
}
- (void)mouseUp:(NSEvent*) event {
NSMenuItem* mitem = [self enclosingMenuItem];
NSMenu* m = [mitem menu];
[m cancelTracking];
NSLog(#"you clicked the %ld item",[m indexOfItem: mitem]);
}
#end
The NSMenuItem subclass:
(I add subviews on the custom view here so i can have access to the controls through the NSMenuItem instance)
#interface customItem : NSMenuItem{
}
-(void)setTheText:(NSString*)theString;
#property NSTextField *theLabel;
#end
#import "customItem.h"
#import "customView.h"
#implementation customItem
#synthesize theLabel;
-(id)init{
if (self){
customView *cv = [[customView alloc] init];
theLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 8, 130, 17)];
[theLabel setEditable:NO];
[theLabel setBordered:NO];
NSButton *myButton = [[NSButton alloc] initWithFrame:NSMakeRect(170, 7, 20, 20)];
NSButton *myButton1 = [[NSButton alloc] initWithFrame:NSMakeRect(150, 7, 20, 20)];
[myButton setBezelStyle:NSCircularBezelStyle];
[myButton1 setBezelStyle:NSCircularBezelStyle];
[myButton setTitle:#""];
[myButton1 setTitle:#""];
[cv addSubview:myButton];
[cv addSubview:myButton1];
[cv addSubview:theLabel];
[self setView:cv];
[theLabel setStringValue:#"A Value "];
}
return self;
}
-(void)setTheText:(NSString *)theString{
[theLabel setStringValue:theString];
}
#end
And this is the App Delegate :
#interface AppDelegate : NSObject <NSApplicationDelegate>{
NSStatusItem *statusItem;
IBOutlet NSMenu *theMenu;
}
#property (assign) IBOutlet NSWindow *window;
#end
#import "customItem.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
}
- (void)awakeFromNib{
statusItem = [[NSStatusBar systemStatusBar]
statusItemWithLength:NSSquareStatusItemLength];
NSBundle *bundle = [NSBundle mainBundle];
NSImage *statusImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:#"barIcon" ofType:#"png"]];
NSImage *highlightImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:#"barIcon_H" ofType:#"png"]];
[statusItem setImage:statusImage];
[statusItem setAlternateImage:highlightImage];
[statusItem setMenu:theMenu];
[theMenu removeAllItems];
customItem *mi = [[customItem alloc] init];
[theMenu addItem:mi];
customItem *mi2 = [[customItem alloc] init];
[theMenu addItem:mi2];
}
#end
This is what i get:
No need to add Booleans or anything else, you can do it from within your custom NSView which is attached to your NSMenuItem
- (void)drawRect:(NSRect)rect {
[super drawRect:rect];
//Handle the hightlight
if ([[self enclosingMenuItem] isHighlighted])
{
[self.lbl_title setTextColor:[NSColor whiteColor]];
[self.lbl_amount setTextColor:[NSColor colorWithDeviceRed:151.0f/255.0f green:164.0f/255.0f blue:179.0f/255.0f alpha:1.0f]];
[[NSColor selectedMenuItemColor] setFill];
}
else
{
[self.lbl_title setTextColor:[NSColor blackColor]];
[self.lbl_amount setTextColor:[NSColor whiteColor]];
[[self backgroundColor] setFill];
}
NSRectFill(rect);}
OK i think i got it.
I added a public bool variable in the NSView subclass.
Then i used
-(void)mouseEntered:(NSEvent *)theEvent
and
-(void)mouseExited:(NSEvent *)theEvent
to set the variable to YES or to NO. After setting the variable i used
[self setNeedsDisplay:YES]
to call
-(void) drawRect: (NSRect) rect
That's how i got it working :)
Here is the right way of changing the background colour (highlighting the item) without maintaining a local variable and force the view to draw again,
-(void)mouseEntered:(NSEvent *)event {
self.layer.backgroundColor = [[NSColor blueColor] colorWithAlphaComponent:0.3].CGColor;
[theLabel setTextColor:[NSColor whiteColor]];
}
-(void)mouseExited:(NSEvent *)event {
self.layer.backgroundColor = [NSColor clearColor].CGColor;
[theLabel setTextColor:[NSColor blackColor]];
}
Make sure you also set [self setWantsLayer:YES] before changing the layer background colour.
I creating NSWindow programmatically and i can't receive any keyboard messages. Instead of this i typing in Xcode editor, but my window is in focus at this time. How i can intercept this events?
Here is my code:
//// delegate
#interface MyDelegate : NSObject
#end
#implementation MyDelegate
#end
//// view
#interface MyView : NSView
#end
#implementation MyView
- (BOOL)isOpaque { return YES;}
- (BOOL)canBecomeKeyView { return YES;}
- (BOOL)acceptsFirstResponder { return YES;}
- (void)keyDown:(NSEvent *)event
{
printf("PRESS\n"); // it's ignoring
}
#end
//// main
int main(int argc, const char **argv){
[NSApplication sharedApplication];
NSWindow *window = [[NSWindow alloc]
initWithContentRect:NSMakeRect( 0, 0, 100, 100 )
styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setContentView: [[MyView alloc] init]];
[window setDelegate: [[MyDelegate alloc] init] ];
[window setAcceptsMouseMovedEvents:YES];
[window setLevel: NSFloatingWindowLevel];
[window makeKeyAndOrderFront: nil];
[NSApp run];
return 0;
}
You need to make the application a foreground application. This is required for the main window to receive key events.
ProcessSerialNumber psn = {0, kCurrentProcess};
OSStatus status =
TransformProcessType(&psn, kProcessTransformToForegroundApplication);