Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.
Does anyone know how to get to use the NSwindow MyDocument.xib from the menu MainMen.xib.

Would i have to use the first responder to access it or what?

Thanks in advance again

Stephen
 
Does anyone know how to get to use the NSwindow MyDocument.xib from the menu MainMen.xib.

Would i have to use the first responder to access it or what?

Thanks in advance again

Stephen

I'm not sure what you are asking? Normally an action message from a menu item gets passed to the first responder. If it does not respond to that message then the message gets passed down the responder chain. If a document window is the key window then the document object will receive the message.

I'd read this document.
 
To make the Borderless Window become Key (thus activating the Text View) pop in my piece of code from Post #02 into the NSWindow Subclass. If you like I can send you via PM my code to make a Borderless NSWindow in IB have a blurred underlay and be semi transparent. It shows the desktop, but its blurred since the Window is above everything. I'm not publicly releasing the code yet since I have to work out some stuff but it works great already.

Anything else you need, just PM or post here. Sorry for the time-delay. I'm in Australia.

AB
 
For Accessing NSWindows from MyDocument in MainMenu.xib or vice-versa, do the following.


Import this above:

#import "FirstDocumentOutletsAndActionsViewController.h"

the original #import "OriginalDocumentOutletsAndActionsViewController.h" or whatever.

Pop this in an Action:

Code:
FirstDocument  *firstNib = [[FirstDocument alloc] initWithNibName:@"MainMenu" bundle:[NSBundle mainBundle]];
	SecondDocument *secondNib = [[SecondDocument alloc] initWithNibName:@"MyDocument" bundle:[NSBundle mainBundle]];

The above won't do anything by itself. What that does is allows the code in the NSWindow subclass to access the windows/outlets from the other Nib with its Controller.

Such as the following example:

Document 1:
-Window 1
-Controller
--Outlets
---window
---button

Document 2:
-Working Window
-NSWindow Subclass Controller
--Outlets and Actions
---GoFullScreen:
---EndFullScreen:

Xcode:

Code:
#import "FullScreenWindow.h"
#import "ControllerFromDocumentOne" //this allows things to be read, but not until you have my sample in.

- (void)awakeFromNib {
       FirstDocument  *firstNib = [[FirstDocument alloc] initWithNibName:@"MainMenu" bundle:[NSBundle mainBundle]];
	SecondDocument *secondNib = [[SecondDocument alloc] initWithNibName:@"MyDocument" bundle:[NSBundle mainBundle]];
//In here, the code reads MyDocument.nib from your compiled App's bundle.  Then, somewhere else along in your code you can reference to it or even copy it into the new window/control it from the source files you are working on.
}

- (IBAction)goFullScreen:(id)sender {
       //do something here
}

Hope it helps,

AB
 
Soo I should just post that code at the top of the new file I create to hold the action.

The second part should that be inserted into the .m file?

Here is my code soo far without the implementation.

Thanks

Stephen
 

Attachments

  • Archive.zip
    64.7 KB · Views: 66
My code

As I said, I've been working on what amounts to the identical problem on my home machine (though I use a Mac at both home and work), my Xcode project + source and a separate built version of the application are attached. Just ignore the stuff related to my custom view, i.e. EBGFView.h/.m and SpinningTriangle.h/.m — they need quite a bit of work and are not currently even in the model-view-controller paradigm.

As you can see, I've linked my toggle full screen menubar entry (which is command+f since I'll have no real text editing and hence didn't need most of the default edit menu) to the first responder, then devolved all the window swapping stuff (with an attempt at a transition animation and logic to grab whichever display the window is on rather than always the main one if that can be determined) to my NSDocument derivative (in MyDocument.h/.m). That I'm using and subsequently defining a custom view for animated OpenGL content with keyboard input is not really relevant to most of this thread and its current implementation is definitely less than ideal for a whole bunch of reasons.

I guess that if you start a new document based application, you should have a couple of .m files — main.m which I've never heard of a reason to change and the NSDocument derivative, which can do all the necessary window switching.

I'll try to take a look at your code later rather than just posting my own completely alternative set.
 

Attachments

  • Application.zip
    22.7 KB · Views: 69
  • Project.zip
    56.5 KB · Views: 70
In the action that drives your application to Full Screen. This is because you need to access the window from the other NIB in your source files. You could probably still put the "NSBundle mainBundle" bits in the AwakeFromNib caller, but the other bit you definitely need to put in the Action that drives the app to Full Screen.

Also, you are writing this for college? iWrite, nice name. But if they have used Mac's before now, I would change the UI substantially since it practically mimics TextEdit at the moment.....:D

AB
 
Thanks people.

Thomas i'lllook over your code when I get home in college the now.

AllBrooke I get what you are meaning now. Illl try and implement it when I get home as my college doesn't have macs.

Yes it is for my lecturer, he said he doesnt mind if its looking like TextEdit as long as the code is diffrent from the one found in the Developer/Examples/AppKit/TextEdit.

Thanks fro all your help so far

Stephen
 
Right i have now set up my MyDocument.h to look like this:

Code:
@interface MyDocument : NSDocument
{
	IBOutlet NSTextView *textView;
	NSAttributedString *mString;
	
	IBOutlet NSWindow *targetWindow;
	
	BOOL fullScreen;
	NSWindow *fullScreenWindow;
}
- (NSAttributedString *)string;
- (void)setString:(NSAttributedString *)value;
@end


And my MyDocument.m to look like this:

Code:
@interface IWriteWindow : NSWindow {
}

@end

@implementation IWriteWindow

- (BOOL)canBecomeKeyWindow
{
	return YES;
}

@end



@implementation MyDocument

- (id)init
{
    self = [super init];
    if (self) {
    
    }
	
	if (mString == nil) {
		mString =[[NSAttributedString alloc] initWithString:@""];
	}
	
    return self;
}

- (NSString *)windowNibName
{
    // Override returning the nib file name of the document
    // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
    return @"MyDocument";
}

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];
	
	fullScreen = NO;
	[targetWindow setContentAspectRatio:NSMakeSize(4, 3)];
	
	[textView setRulerVisible:YES];
	
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	NSData *colorAsData;
	colorAsData = [defaults objectForKey:BNRTextViewBgColorKey];
	
	[textView setBackgroundColor:[NSKeyedUnarchiver unarchiveObjectWithData:colorAsData]];
	
	NSUserDefaults *textDefaults = [NSUserDefaults standardUserDefaults];
	NSData *textColorAsData;
	textColorAsData = [textDefaults objectForKey:BNRTextViewTextColorKey];
	
	[textView setTextColor:[NSKeyedUnarchiver unarchiveObjectWithData:textColorAsData]];
	
	if ([self string] != nil) {
		[[textView textStorage] setAttributedString:[self string]];
	}
	
}

- (NSRect)getTargetFrameForScreen:(NSScreen *)screen
{
	NSRect screenFrame = [screen frame];
	int screenWidth = (int)screenFrame.size.width;
	int screenHeight = (int)screenFrame.size.height;
	int targetWidth, targetHeight;
	
	if (screenWidth * 3 != screenHeight * 4)
	{
		if (screenWidth * 3 > screenHeight * 4)
		{
			targetWidth = (screenHeight *4)/3;
			targetHeight = screenWidth;
		}
	}
	else
	{
		targetWidth = screenWidth;
		targetHeight = screenHeight;
	}
	
	NSRect targetFrmae;
	targetFrmae.size.width = targetWidth;
	targetFrmae.size.width = targetHeight;
	targetFrmae.origin.x = (screenFrame.size.width - targetFrmae.size.width) * 0.5;
	targetFrmae.origin.y = (screenFrame.size.height - targetFrmae.size.height) * 0.5;
	
	return targetFrmae;
}

- (void)toggleFullScreen:(NSMenuItem *)menuItem
{
	if (!fullScreen)
	{
		NSScreen *targetScreen = [targetWindow screen];
		NSView *content = [targetWindow contentView];
		
		fullScreenWindow = [[IWriteWindow alloc]
							initWithContentRect:[targetWindow contentRectForFrameRect:[targetWindow frame]]
									  styleMask:NSBorderlessWindowMask
										backing:NSBackingStoreBuffered
										  defer:NO
							screen:targetScreen];
		
		[content retain];
		[targetWindow setContentView:nil];
		[fullScreenWindow setContentView:content];
		[content release];
		
		[fullScreenWindow makeKeyAndOrderFront:nil];
		[fullScreenWindow setDelegate:self];
		
		[targetWindow orderOut:nil];
		
		int windowLevel = CGShieldingWindowLevel();
		NSNumber *screenNumber = [[[targetWindow screen] deviceDescription] objectForKey:@"NSScreenNumber"];
		CGDisplayCapture(screenNumber ? [screenNumber unsignedLongValue] : kCGDirectMainDisplay);
		[fullScreenWindow setLevel:windowLevel];
		
		[fullScreenWindow setFrame:[self getTargetFrameForScreen:targetScreen] display:YES animate:YES];
		
		fullScreen = YES;
	}
	else
	{
		NSNumber *screenNumber = [[[fullScreenWindow screen] deviceDescription] objectForKey:@"NSScreenNumber"];
		CGDisplayRelease(screenNumber ? [screenNumber unsignedLongValue] : kCGDirectMainDisplay);
		
		[fullScreenWindow setFrame:[targetWindow contentRectForFrameRect:[targetWindow frame]] display:YES animate:YES];
		
		NSView *content = [fullScreenWindow contentView];
		[content retain];
		[fullScreenWindow setContentView:nil];
		[targetWindow setContentView:content];
		[content release];
		
		[targetWindow makeKeyAndOrderFront:nil];
		
		[fullScreenWindow release];
		
		fullScreenWindow = nil;
		
		fullScreen = NO;
	}
}

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
    NSData *data;
	[self setString:[textView textStorage]];
	data = [NSArchiver archivedDataWithRootObject:[self string]];
	return data;
}

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
    NSAttributedString *tempString = [NSUnarchiver unarchiveObjectWithData:data];
	[self setString:tempString];
	return YES;
}

- (NSAttributedString *)string
{
	return [[mString retain] autorelease];
}

- (void)setString:(NSAttributedString *)newValue
{
	if (mString != newValue) {
		if (mString) [mString release];
		mString = [newValue copy];
	}
}

- (void)textDidChange:(NSNotification *)notification
{
	[self setString:[textView textStorage]];
}

@end

Now my application will open in fullscreen but the textview disappers after a second and im left with a blank screen any help?

And Thomas thanks soo much for your application code helped me sooo much :)

AllBrooke I couldn't seem to get your code to work perhaps I was implementing it wrong??

Thanks :)

Stephen
 
Here's a link to a video presentation by Aaron Hillegass at the Atlanta CocoaHeads meeting dealing with the text system. It might be helpful if you choose to expand your project. I learned a lot from it myself, so hopefully some of you guys will too.
 
Aaron Hillegas is a great programmer wish I could go to one of his lectures :(

Thanks for that link helped me understand about attributed strings and so.

Thanks.

Stephen
 
With respect to my code, you should probably replace or remove getTargetFrameForScreen — for my purposes it is supposed to calculate the optimal 4:3 rectangle on a screen, in fact I've neglected to allow for the fact that secondary screens have an origin other than (0, 0), so the code will function incorrectly if you attempt to toggle to full screen any window on a secondary screen.
 
So what is the frame that I should set for
Code:
[fullScreenWindow setFrame: ... display:YES animate:YES]
??

Thanks

Stephen

EDIT ... Got it I just removed that line and left me with the textView in the middle of the screen :)

Thanks soo much for your help Thomas :)

Stephen
 
Up to that line, the code should have:

(1) put a shield up on the view containing the majority of the original window;
(2) created a new, borderless window that is above the shield, the same size and in the same position as the content view of the original window;
(3) transferred the content of the original window to the new window;
(4) hidden the original window (which isn't necessary if you have a single screen, but if you have multiple screens then obviously part of the window may still be visible on a different screen).

That line requests an animated transition for the borderless window from its current dimensions to dimensions that fill the screen. I've used that other function, which isn't quite correct, to figure out how to fill as much of the screen as possible while still having the content appear with a 4:3 aspect ratio (you'll notice I also lock the content view of the normal window to 4:3 elsewhere, so you can't scale it to anything other than that aspect ratio).

You could use [targetScreen frame] in place of [self getTargetFrameForScreen:targetScreen] to say "resize to entirely fill the screen, whatever the aspect ratio".
 
aww now that looks nice with the animation. Thanks soo much for all your help and that.

If you would like I can post up and you can have a look over what I have done or that.

Thnaks

Stephen
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.