Add code to dismiss popover if another window issmade key. Minor corrections to GSToolTips.m so that it uses the RELEASE/AUTORELEASE macros.

This commit is contained in:
Gregory John Casamento 2021-10-02 17:28:24 -04:00
parent 166ea25ef0
commit 87e30f8514
4 changed files with 203 additions and 35 deletions

View file

@ -1,3 +1,10 @@
2021-10-02 Gregory John Casamento <greg.casamento@gmail.com>
* Source/GSToolTips.m: Use RELEASE and AUTORELEASE macros where
appropriate. Minor fixes.
* Source/NSPopover.m: Add code to draw an outline outside of the
view. Add GSPopoverPanel and GSPopoverView private classes.
2021-09-30 Gregory John Casamento <greg.casamento@gmail.com>
* Source/NSPopover.m: Fix an issue with NSPopover loading the

View file

@ -60,7 +60,7 @@ enum {
typedef NSInteger NSPopoverBehavior;
/* Forward declarations */
@class NSViewController, NSWindow, NSView, NSNotification;
@class NSViewController, NSPanel, NSView, NSNotification;
@protocol NSPopoverDelegate;
/* Class */
@ -75,7 +75,7 @@ typedef NSInteger NSPopoverBehavior;
NSRect _positioningRect;
BOOL _shown;
NSWindow *_realWindow;
NSPanel *_realPanel;
}
/* Properties */

View file

@ -174,7 +174,7 @@
- (id) initWithContentRect: (NSRect)contentRect
styleMask: (NSUInteger)aStyle
backing: (NSBackingStoreType)bufferingType
defer: (BOOL)flag;
defer: (BOOL)flag
{
self = [super initWithContentRect: contentRect
styleMask: aStyle
@ -182,7 +182,7 @@
defer: flag];
if (self)
{
[self setContentView: [[[GSTTView alloc] initWithFrame: contentRect] autorelease]];
[self setContentView: AUTORELEASE([[GSTTView alloc] initWithFrame: contentRect])];
}
return self;
}
@ -452,7 +452,7 @@ static BOOL restoreMouseMoved;
{
((NSViewPtr)view)->_rFlags.has_trkrects = 0;
}
[indexes release];
RELEASE(indexes);
}
- (void) removeToolTip: (NSToolTipTag)tag

View file

@ -34,62 +34,195 @@
#import "AppKit/NSPopover.h"
#import "AppKit/NSViewController.h"
#import "AppKit/NSView.h"
#import "AppKit/NSWindow.h"
#import "AppKit/NSPanel.h"
#import "AppKit/NSNibLoading.h"
#import "AppKit/NSStoryboard.h"
#import "AppKit/NSGraphics.h"
// Popover window
// Popover private classes
@interface GSPopoverWindow : NSWindow
@interface GSPopoverView : NSView
{
NSView *_contentView;
}
@end
@implementation GSPopoverWindow : NSWindow
@implementation GSPopoverView
- (instancetype) initWithFrame: (NSRect)frame
{
self = [super initWithFrame: frame];
if (self)
{
[self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
}
return self;
}
- (void) setContentView: (NSView *)view
{
if (view != nil)
{
ASSIGN(_contentView, view);
[_contentView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
[self addSubview: _contentView];
}
else
{
[_contentView removeFromSuperview];
}
}
- (void) drawRect: (NSRect)dirtyRect
{
NSRectEdge sides[] = {NSMinXEdge, NSMaxYEdge, NSMaxXEdge, NSMinYEdge};
NSColor *black = [NSColor blackColor];
NSColor *white = [NSColor whiteColor];
NSColor *colors[] = {white, white, black, black};
NSRect bounds = [self bounds];
[super drawRect: dirtyRect];
NSDrawColorTiledRects(bounds, bounds, sides, colors, 4);
}
@end
@interface GSPopoverPanel : NSPanel
@end
@implementation GSPopoverPanel
- (id) initWithContentRect: (NSRect)contentRect
styleMask: (NSUInteger)aStyle
backing: (NSBackingStoreType)bufferingType
defer: (BOOL)flag
{
self = [super initWithContentRect: contentRect
styleMask: aStyle
backing: bufferingType
defer: flag];
if (self)
{
[super setContentView: AUTORELEASE([[GSPopoverView alloc] initWithFrame: contentRect])];
}
return self;
}
- (void) orderOut: (id)sender
{
[super orderOut: sender];
[self close];
}
- (BOOL) canBecomeKeyWindow
{
return NO;
}
- (BOOL) canBecomeMainWindow
{
return NO;
}
- (void) setContentView: (NSView *)view
{
[[super contentView] addSubview: view];
}
- (NSView *) contentView
{
NSArray *subviews = [[super contentView] subviews];
if ([subviews count] == 0)
{
return nil;
}
return [subviews objectAtIndex: 0];
}
@end
/* Class */
@implementation NSPopover
/* Properties */
/**
* Sets the animate flag. If YES then the popover will animate when it appears or disappears.
*/
- (void) setAnimates: (BOOL)flag
{
_animates = flag;
}
/**
* Returns current value of the animate flag.
*/
- (BOOL) animates
{
return _animates;
}
/**
* Sets ths appearance of the popover. Minimal is the default. HUD is not supported.
*/
- (void) setAppearance: (NSPopoverAppearance)value
{
_appearance = value;
}
/**
* Returns the current appearance setting.
*/
- (NSPopoverAppearance) appearance
{
return _appearance;
}
/**
* Sets current popup behavior. Valid settings are:
* NSPopupBehaviorApplicationDefined, NSPopupBehaviorTransient,
* NSPopupBehaviorSemiTransient.
*/
- (void) setBehavior: (NSPopoverBehavior)value
{
_behavior = value;
}
/**
* Returns current behavior setting
*/
- (NSPopoverBehavior) behavior
{
return _behavior;
}
/**
* Accepts an NSSize value for the current content size.
*/
- (void) setContentSize: (NSSize)value
{
_contentSize = value;
}
/**
* Returns an NSSize representing the size of the NSPopover content view.
*/
- (NSSize) contentSize
{
return _contentSize;
}
/**
* Sets the contentViewController. If in a storyboard this is automatically set
* but if this is in a model that is NOT a storyboard (nib, xib, gorm, etc) then there must be
* a model with the same name as the class name of the contentViewController. Also,
* This model must have the "view" outlet set to the view that will be shown
* in the popup, if both of these conditions are not met, then the code will
* throw an NSInternalInconsistency exception to report the issue back to the
* user.
*/
- (void) setContentViewController: (NSViewController *)controller
{
if ([NSStoryboard mainStoryboard] == nil)
@ -114,49 +247,77 @@
ASSIGN(_contentViewController, controller);
}
/**
* Returns the current contentViewController.
*/
- (NSViewController *) contentViewController
{
return _contentViewController;
}
/**
* Set delegate
*/
- (void) setDelegate: (id)value
{
_delegate = value;
}
/**
* Return delegate
*/
- (id) delegate
{
return _delegate;
}
/**
* Set relative position of the popup to the view it is associated with.
*/
- (void) setPositioningRect: (NSRect)value
{
_positioningRect = value;
}
/**
* Return the NSRect.
*/
- (NSRect) positioningRect
{
return _positioningRect;
}
/**
* Is the popover being shown.
*/
- (BOOL) isShown
{
return _shown;
}
/* Methods */
/**
* Close the popover.
*/
- (void) close
{
[_realWindow close];
[_realWindow setDelegate:nil];
[_realPanel close];
[_realPanel setDelegate:nil];
}
/**
* Close the popover.
*/
- (IBAction) performClose: (id)sender
{
[_realWindow performClose:sender];
[_realWindow setDelegate:nil];
[_realPanel performClose:sender];
[_realPanel setDelegate:nil];
}
/**
* Show the popover relative to the specified rect on the edge specified.
*/
- (void) showRelativeToRect: (NSRect)positioningRect
ofView: (NSView *)positioningView
preferredEdge: (NSRectEdge)preferredEdge
@ -170,19 +331,24 @@
view = [_contentViewController view];
viewFrame = [view frame];
if (!_realWindow)
if (!_realPanel)
{
_realWindow = [[GSPopoverWindow alloc] initWithContentRect: viewFrame
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreRetained
defer: NO];
_realPanel = [[GSPopoverPanel alloc] initWithContentRect: viewFrame
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreRetained
defer: NO];
[_realPanel setBackgroundColor: [NSColor darkGrayColor]];
[_realPanel setReleasedWhenClosed: YES];
[_realPanel setExcludedFromWindowsMenu: YES];
[_realPanel setLevel: NSPopUpMenuWindowLevel];
[_realPanel setAutodisplay: NO];
[_realPanel setDelegate: self];
[_realPanel setContentView: view];
}
[_realWindow setDelegate: self];
[_realWindow setBackgroundColor: [NSColor darkGrayColor]];
screenRect = [[positioningView window] convertRectToScreen:positioningRect];
windowFrame = [_realWindow frame];
windowFrame = [_realPanel frame];
windowFrame.origin = screenRect.origin;
if(NSMinXEdge == preferredEdge)
@ -202,14 +368,13 @@
windowFrame.origin.x += viewFrame.size.width;
}
[_realWindow setFrame: windowFrame display: YES];
NSLog(@"Showing relative to in window %@",NSStringFromRect(positioningRect));
NSLog(@"Showing relative to in screen %@",NSStringFromRect(screenRect));
[[_realWindow contentView] addSubview: view];
[_realWindow setDelegate: self];
[_realWindow makeKeyAndOrderFront:self];
[_realPanel setFrame: windowFrame display: YES];
[_realPanel makeKeyAndOrderFront:self];
NSDebugLog(@"Showing relative to in window %@",NSStringFromRect(positioningRect));
NSDebugLog(@"Showing relative to in screen %@",NSStringFromRect(screenRect));
_shown = YES;
}
- (BOOL) windowShouldClose: (id)sender
@ -231,11 +396,6 @@
userInfo:nil];
}
- (void) windowDidResignMain: (NSNotification *)notification
{
[_realWindow close];
}
- (id) initWithCoder: (NSCoder *)coder
{
if (nil != (self = [super initWithCoder:coder]))
@ -284,4 +444,5 @@
[coder encodeObject:_contentViewController];
}
}
@end