mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-09 04:07:12 +00:00
Merge branch 'pl_2918' into Aristo3
This commit is contained in:
@@ -122,6 +122,10 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
CPPanel _aboutPanel;
|
||||
|
||||
CPThemeBlend _themeBlend @accessors(property=themeBlend);
|
||||
|
||||
// OS behavior
|
||||
CPApplicationOSBehavior _OSBehavior;
|
||||
BOOL _simulatesWindows;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -154,6 +158,9 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
_eventListenerInsertionIndex = 0;
|
||||
|
||||
_windows = [[CPNull null]];
|
||||
|
||||
_OSBehavior = CPApplicationLegacyOSBehavior;
|
||||
_simulatesWindows = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1263,6 +1270,44 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo3");
|
||||
}
|
||||
|
||||
// See CPApplication_Constants.j for comments
|
||||
- (void)setOSBehavior:(CPApplicationOSBehavior)anOSBehavior
|
||||
{
|
||||
// Verify if provided OS behavior is valid
|
||||
if ([[CPApplicationOSBehaviors allKeysForObject:anOSBehavior] count] == 0)
|
||||
{
|
||||
CPLog.warn("CPApplication setOSBehavior: invalid CPApplicationOSBehavior (received "+anOSBehavior+"). Ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
_OSBehavior = anOSBehavior;
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationOSBehaviorDidChangeNotification object:CPApp userInfo:nil];
|
||||
}
|
||||
|
||||
- (CPApplicationOSBehavior)OSBehavior
|
||||
{
|
||||
return _OSBehavior;
|
||||
}
|
||||
|
||||
- (BOOL)shouldMimicWindows
|
||||
{
|
||||
return (_OSBehavior == CPApplicationFollowOSBehavior) && (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) || _simulatesWindows);
|
||||
}
|
||||
|
||||
- (void)setSimulatesWindows:(BOOL)shouldSimulateWindows
|
||||
{
|
||||
if (_simulatesWindows === shouldSimulateWindows)
|
||||
return;
|
||||
|
||||
_simulatesWindows = shouldSimulateWindows;
|
||||
}
|
||||
|
||||
- (BOOL)simulatesWindows
|
||||
{
|
||||
return _simulatesWindows;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var _CPModalSessionMake = function(aWindow, aStopCode)
|
||||
@@ -1391,6 +1436,34 @@ var _CPAppBootstrapperActions = nil;
|
||||
[[CPApplication sharedApplication] setThemeBlend:aThemeBlend];
|
||||
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
|
||||
|
||||
// Search in the Info.plist if the special CPApplicationSimulateWindowsOS flag is set (for testing)
|
||||
[CPApp setSimulatesWindows:!![[CPBundle mainBundle] objectForInfoDictionaryKey:"CPApplicationSimulateWindowsOS"]];
|
||||
|
||||
// Before loading the main CIB, try to find if a CPApplicationOSBehavior is specified in the Info.plist or in the user defaults
|
||||
// (with user defaults precedence). Value stored must be a string representing the name of the OS behavior.
|
||||
var plistOSBehavior = [[CPBundle mainBundle] objectForInfoDictionaryKey:"CPApplicationOSBehavior"],
|
||||
userOSBehavior = [[CPUserDefaults standardUserDefaults] objectForKey:@"CPApplicationOSBehavior"];
|
||||
|
||||
if (userOSBehavior)
|
||||
{
|
||||
var osBehavior = [CPApplicationOSBehaviors objectForKey:userOSBehavior];
|
||||
|
||||
if (osBehavior)
|
||||
[CPApp setOSBehavior:osBehavior];
|
||||
else
|
||||
CPLog.warn("Invalid CPApplicationOSBehavior specified in user defaults (found:"+userOSBehavior+"). Ignored.");
|
||||
}
|
||||
|
||||
else if (plistOSBehavior)
|
||||
{
|
||||
var osBehavior = [CPApplicationOSBehaviors objectForKey:plistOSBehavior];
|
||||
|
||||
if (osBehavior)
|
||||
[CPApp setOSBehavior:osBehavior];
|
||||
else
|
||||
CPLog.warn("Invalid CPApplicationOSBehavior specified in Info.plist (found:"+plistOSBehavior+"). Ignored.");
|
||||
}
|
||||
|
||||
[self performActions];
|
||||
}
|
||||
|
||||
|
||||
@@ -39,3 +39,15 @@ CPTerminateLater = -1; // not currently supported
|
||||
CPRunStoppedResponse = -1000;
|
||||
CPRunAbortedResponse = -1001;
|
||||
CPRunContinuesResponse = -1002;
|
||||
|
||||
// Should the application follow Cappuccino UX-UI (which is OSX like) or OS UX-UI (mainly Windows) ?
|
||||
// See explanation on https://github.com/cappuccino/cappuccino/wiki/CPApplicationSelectedOSBehavior
|
||||
@typedef CPApplicationOSBehavior
|
||||
CPApplicationLegacyOSBehavior = 1;
|
||||
CPApplicationFollowOSBehavior = 2;
|
||||
|
||||
CPApplicationOSBehaviorDidChangeNotification = @"CPApplicationOSBehaviorDidChangeNotification";
|
||||
CPApplicationOSBehaviors = @{
|
||||
@"CPApplicationLegacyOSBehavior": CPApplicationLegacyOSBehavior,
|
||||
@"CPApplicationFollowOSBehavior": CPApplicationFollowOSBehavior
|
||||
};
|
||||
|
||||
@@ -816,6 +816,7 @@ CPThemeStateControlSizeSmall = CPThemeState("controlSizeSmall");
|
||||
CPThemeStateControlSizeMini = CPThemeState("controlSizeMini");
|
||||
CPThemeStateAlternateState = CPThemeState("alternate");
|
||||
CPThemeStateComposedControl = CPThemeState("composed");
|
||||
CPThemeStateWindowsPlatform = CPThemeState("windowsPlatform");
|
||||
|
||||
CPThemeStateNormalString = String(CPThemeStateNormal);
|
||||
|
||||
|
||||
@@ -2533,6 +2533,10 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self];
|
||||
|
||||
// Give a chance to the _windowView to do things before closing (for example, remove an observer)
|
||||
if ([_windowView respondsToSelector:@selector(_close)])
|
||||
[_windowView _close];
|
||||
|
||||
[_parentWindow removeChildWindow:self];
|
||||
[self _orderOutRecursively:NO];
|
||||
[self _detachFromChildrenClosing:!_parentWindow];
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
@import "CPButton.j"
|
||||
@import "_CPTitleableWindowView.j"
|
||||
@import "CPApplication_Constants.j"
|
||||
|
||||
@class _CPDocModalWindowView
|
||||
|
||||
@@ -97,9 +98,16 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
CPButton _closeButton;
|
||||
CPButton _minimizeButton;
|
||||
CPButton _zoomButton;
|
||||
|
||||
BOOL _isDocumentEdited;
|
||||
BOOL _isSheet;
|
||||
|
||||
CPTrackingArea _closeButtonTrackingArea;
|
||||
CPTrackingArea _minimizeButtonTrackingArea;
|
||||
CPTrackingArea _zoomButtonTrackingArea;
|
||||
|
||||
int _buttonsWidth;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -123,6 +131,8 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
@"close-image-highlighted-button": [CPNull null],
|
||||
@"unsaved-image-button": [CPNull null],
|
||||
@"unsaved-image-highlighted-button": [CPNull null],
|
||||
@"zoom-image-button": [CPNull null],
|
||||
@"zoom-image-highlighted-button": [CPNull null]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -154,7 +164,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
var theClass = [self class],
|
||||
bounds = [self bounds];
|
||||
|
||||
_headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), [self valueForThemeAttribute:@"title-bar-height"]) windowView:self];
|
||||
_headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), _titleBarHeight) windowView:self];
|
||||
|
||||
[_headView setAutoresizingMask:CPViewWidthSizable];
|
||||
[_headView setHitTests:NO];
|
||||
@@ -181,30 +191,50 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
if (_styleMask & CPClosableWindowMask)
|
||||
{
|
||||
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 8.0, 16.0, 16.0)];
|
||||
_closeButton = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_closeButton setButtonType:CPMomentaryChangeButton];
|
||||
[_closeButton setBordered:NO];
|
||||
[self _updateCloseButton];
|
||||
|
||||
[self addSubview:_closeButton];
|
||||
}
|
||||
|
||||
if (_styleMask & CPMiniaturizableWindowMask && ![CPPlatform isBrowser])
|
||||
if (_styleMask & CPMiniaturizableWindowMask)
|
||||
{
|
||||
_minimizeButton = [[CPButton alloc] initWithFrame:CGRectMake(27.0, 7.0, 16.0, 16.0)];
|
||||
_minimizeButton = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_minimizeButton setButtonType:CPMomentaryChangeButton];
|
||||
[_minimizeButton setBordered:NO];
|
||||
|
||||
[self addSubview:_minimizeButton];
|
||||
}
|
||||
|
||||
if (_styleMask & CPResizableWindowMask)
|
||||
{
|
||||
_zoomButton = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_zoomButton setButtonType:CPMomentaryChangeButton];
|
||||
[_zoomButton setBordered:NO];
|
||||
|
||||
[self addSubview:_zoomButton];
|
||||
}
|
||||
|
||||
[self _updateWindowButtons:YES];
|
||||
[self tile];
|
||||
|
||||
// Observe CPApplicationOSBehaviorDidChangeNotification
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_osBehaviorDidChange:) name:CPApplicationOSBehaviorDidChangeNotification object:CPApp];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// This will be called by CPWindow -close so the observer can be removed
|
||||
- (void)_close
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPApplicationOSBehaviorDidChangeNotification object:CPApp];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
[_closeButton setTarget:[self window]];
|
||||
@@ -212,11 +242,14 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
[_minimizeButton setTarget:[self window]];
|
||||
[_minimizeButton setAction:@selector(performMiniaturize:)];
|
||||
|
||||
[_zoomButton setTarget:[self window]];
|
||||
[_zoomButton setAction:@selector(performZoom:)];
|
||||
}
|
||||
|
||||
- (CGSize)toolbarOffset
|
||||
{
|
||||
return CGSizeMake(0.0, [self valueForThemeAttribute:@"title-bar-height"]);
|
||||
return CGSizeMake(0.0, _titleBarHeight);
|
||||
}
|
||||
|
||||
- (void)tile
|
||||
@@ -246,14 +279,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
[_bodyView setFrame:CGRectMake(0.0, dividerMinY, width, CGRectGetHeight(bounds) - dividerMinY)];
|
||||
|
||||
var leftOffset = 8;
|
||||
|
||||
if (_closeButton)
|
||||
leftOffset += 19.0;
|
||||
if (_minimizeButton)
|
||||
leftOffset += 19.0;
|
||||
|
||||
[_titleField setFrame:CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [self valueForThemeAttribute:@"title-bar-height"])];
|
||||
[_titleField setFrame:CGRectMake(_buttonsWidth, 0, width - _buttonsWidth * 2.0, _titleBarHeight)];
|
||||
|
||||
var contentFrame = [_bodyView frame];
|
||||
[[theWindow contentView] setFrame:CGRectInset(contentFrame, 1.0, 1.0)];
|
||||
@@ -287,11 +313,173 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
}
|
||||
*/
|
||||
|
||||
- (void)_updateWindowButtons:(BOOL)shouldRefreshLayout
|
||||
{
|
||||
if (shouldRefreshLayout)
|
||||
{
|
||||
var mimicWindows = [CPApp shouldMimicWindows];
|
||||
|
||||
if (mimicWindows)
|
||||
[self setThemeState:CPThemeStateWindowsPlatform];
|
||||
else
|
||||
[self unsetThemeState:CPThemeStateWindowsPlatform];
|
||||
|
||||
// Remember that on Cappuccino, buttons are (left to right) : close - minimize - zoom
|
||||
// and that on Windows, (also left to right) : minimize - zoom - close
|
||||
|
||||
var offset,
|
||||
mask,
|
||||
closeThemeOrigin = CGPointMakeCopy([self currentValueForThemeAttribute:@"close-image-origin"] || CGPointMakeZero()),
|
||||
minimizeThemeOrigin = CGPointMakeCopy([self currentValueForThemeAttribute:@"minimize-image-origin"] || CGPointMakeZero()),
|
||||
zoomThemeOrigin = CGPointMakeCopy([self currentValueForThemeAttribute:@"zoom-image-origin"] || CGPointMakeZero()),
|
||||
closeThemeSize = CGSizeMakeZero(),
|
||||
minimizeThemeSize = CGSizeMakeZero(),
|
||||
zoomThemeSize = CGSizeMakeZero(),
|
||||
delta1,
|
||||
delta2;
|
||||
|
||||
// For retro-compatibility
|
||||
if (![self isCSSBased])
|
||||
{
|
||||
if (mimicWindows)
|
||||
{
|
||||
// There's no zoom button in Aristo2
|
||||
closeThemeOrigin = CGPointMake(-24.0, 8.0);
|
||||
minimizeThemeOrigin = CGPointMake(-43.0, 8.0);
|
||||
|
||||
// FIXME: if someone designs a zoom button in Aristo2 one day, use those values
|
||||
// closeThemeOrigin = CGPointMake(-24.0, 8.0);
|
||||
// minimizeThemeOrigin = CGPointMake(-62.0, 8.0);
|
||||
// zoomThemeOrigin = CGPointMake(-43.0, 8.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
closeThemeOrigin = CGPointMake(8.0, 8.0);
|
||||
minimizeThemeOrigin = CGPointMake(27.0, 8.0);
|
||||
zoomThemeOrigin = CGPointMake(46.0, 8.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (mimicWindows)
|
||||
{
|
||||
offset = [self bounds].size.width;
|
||||
mask = CPViewMinXMargin;
|
||||
delta1 = zoomThemeOrigin.x - closeThemeOrigin.x;
|
||||
delta2 = minimizeThemeOrigin.x - zoomThemeOrigin.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
mask = CPViewMaxXMargin;
|
||||
delta1 = minimizeThemeOrigin.x - closeThemeOrigin.x;
|
||||
delta2 = zoomThemeOrigin.x - minimizeThemeOrigin.x;
|
||||
}
|
||||
|
||||
_buttonsWidth = 0;
|
||||
|
||||
if (_styleMask & CPClosableWindowMask)
|
||||
{
|
||||
closeThemeSize = [self currentValueForThemeAttribute:@"close-image-size"];
|
||||
|
||||
// For retro-compatibility:
|
||||
if (!closeThemeSize)
|
||||
closeThemeSize = CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_closeButton setFrame:CGRectMake(closeThemeOrigin.x + offset, closeThemeOrigin.y, closeThemeSize.width, closeThemeSize.height)];
|
||||
[_closeButton setAutoresizingMask:mask];
|
||||
|
||||
_buttonsWidth = ABS(closeThemeOrigin.x) + (mimicWindows ? 0 : closeThemeSize.width);
|
||||
}
|
||||
else
|
||||
{
|
||||
minimizeThemeOrigin.x -= delta1;
|
||||
zoomThemeOrigin.x -= delta1;
|
||||
}
|
||||
|
||||
if (mimicWindows)
|
||||
{
|
||||
if (_styleMask & CPResizableWindowMask)
|
||||
{
|
||||
zoomThemeSize = [self currentValueForThemeAttribute:@"zoom-image-size"];
|
||||
|
||||
// For retro-compatibility:
|
||||
if (!zoomThemeSize)
|
||||
zoomThemeSize = CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_zoomButton setFrame:CGRectMake(zoomThemeOrigin.x + offset, zoomThemeOrigin.y, zoomThemeSize.width, zoomThemeSize.height)];
|
||||
[_zoomButton setAutoresizingMask:mask];
|
||||
|
||||
_buttonsWidth = ABS(zoomThemeOrigin.x);
|
||||
}
|
||||
else
|
||||
minimizeThemeOrigin.x -= delta2;
|
||||
|
||||
if (_styleMask & CPMiniaturizableWindowMask)
|
||||
{
|
||||
minimizeThemeSize = [self currentValueForThemeAttribute:@"minimize-image-size"];
|
||||
|
||||
// For retro-compatibility:
|
||||
if (!minimizeThemeSize)
|
||||
minimizeThemeSize = CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_minimizeButton setFrame:CGRectMake(minimizeThemeOrigin.x + offset, minimizeThemeOrigin.y, minimizeThemeSize.width, minimizeThemeSize.height)];
|
||||
[_minimizeButton setAutoresizingMask:mask];
|
||||
|
||||
_buttonsWidth = ABS(minimizeThemeOrigin.x);
|
||||
}
|
||||
|
||||
if (_buttonsWidth > 0)
|
||||
_buttonsWidth += ABS(closeThemeOrigin.x) - closeThemeSize.width;
|
||||
}
|
||||
else // not win
|
||||
{
|
||||
if (_styleMask & CPMiniaturizableWindowMask)
|
||||
{
|
||||
minimizeThemeSize = [self currentValueForThemeAttribute:@"minimize-image-size"];
|
||||
|
||||
// For retro-compatibility:
|
||||
if (!minimizeThemeSize)
|
||||
minimizeThemeSize = CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_minimizeButton setFrame:CGRectMake(minimizeThemeOrigin.x + offset, minimizeThemeOrigin.y, minimizeThemeSize.width, minimizeThemeSize.height)];
|
||||
[_minimizeButton setAutoresizingMask:mask];
|
||||
|
||||
_buttonsWidth = minimizeThemeOrigin.x + minimizeThemeSize.width;
|
||||
}
|
||||
else
|
||||
zoomThemeOrigin.x -= delta2;
|
||||
|
||||
if (_styleMask & CPResizableWindowMask)
|
||||
{
|
||||
zoomThemeSize = [self currentValueForThemeAttribute:@"zoom-image-size"];
|
||||
|
||||
// For retro-compatibility:
|
||||
if (!zoomThemeSize)
|
||||
zoomThemeSize = CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_zoomButton setFrame:CGRectMake(zoomThemeOrigin.x + offset, zoomThemeOrigin.y, zoomThemeSize.width, zoomThemeSize.height)];
|
||||
[_zoomButton setAutoresizingMask:mask];
|
||||
|
||||
_buttonsWidth = zoomThemeOrigin.x + zoomThemeSize.width;
|
||||
}
|
||||
|
||||
if (_buttonsWidth > 0)
|
||||
_buttonsWidth += closeThemeOrigin.x;
|
||||
}
|
||||
|
||||
[self updateTrackingAreas];
|
||||
}
|
||||
|
||||
[self _updateCloseButton];
|
||||
|
||||
[_minimizeButton setImage:[self currentValueForThemeAttribute:@"minimize-image-button"]];
|
||||
[_minimizeButton setAlternateImage:[self currentValueForThemeAttribute:@"minimize-image-highlighted-button"]];
|
||||
[_zoomButton setImage:[self currentValueForThemeAttribute:@"zoom-image-button"]];
|
||||
[_zoomButton setAlternateImage:[self currentValueForThemeAttribute:@"zoom-image-highlighted-button"]];
|
||||
}
|
||||
|
||||
- (void)_updateCloseButton
|
||||
{
|
||||
[_closeButton setFrameSize:[self valueForThemeAttribute:@"close-image-size"]];
|
||||
[_closeButton setFrameOrigin:[self valueForThemeAttribute:@"close-image-origin"]];
|
||||
|
||||
if (_isDocumentEdited)
|
||||
{
|
||||
[_closeButton setImage:[self currentValueForThemeAttribute:@"unsaved-image-button"]];
|
||||
@@ -304,9 +492,15 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_osBehaviorDidChange:(id)application
|
||||
{
|
||||
[self _updateWindowButtons:YES];
|
||||
}
|
||||
|
||||
- (void)setDocumentEdited:(BOOL)isEdited
|
||||
{
|
||||
_isDocumentEdited = isEdited;
|
||||
|
||||
[self _updateCloseButton];
|
||||
}
|
||||
|
||||
@@ -337,9 +531,10 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
[_dividerView setHidden:enable];
|
||||
}
|
||||
|
||||
[_closeButton setHidden:enable];
|
||||
[_closeButton setHidden:enable];
|
||||
[_minimizeButton setHidden:enable];
|
||||
[_titleField setHidden:enable];
|
||||
[_zoomButton setHidden:enable];
|
||||
[_titleField setHidden:enable];
|
||||
|
||||
[[self window] setMovable:!enable];
|
||||
|
||||
@@ -381,28 +576,35 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
var bounds = [self bounds];
|
||||
var width = [self bounds].size.width,
|
||||
mimicWindows = [CPApp shouldMimicWindows];
|
||||
|
||||
[super layoutSubviews];
|
||||
[self _updateCloseButton];
|
||||
|
||||
[_minimizeButton setImage:[self valueForThemeAttribute:@"minimize-image-button"]];
|
||||
[_minimizeButton setAlternateImage:[self valueForThemeAttribute:@"minimize-image-highlighted-button"]];
|
||||
if (_closeButton || _minimizeButton || _zoomButton)
|
||||
[self _updateWindowButtons:NO];
|
||||
|
||||
[_dividerView setBackgroundColor:[self valueForThemeAttribute:@"divider-color"]];
|
||||
[_bodyView setBackgroundColor:[self valueForThemeAttribute:@"body-color"]];
|
||||
|
||||
[_headView setNeedsLayout];
|
||||
|
||||
if (width - 2 * _buttonsWidth < _minimumTitleFieldSize)
|
||||
{
|
||||
if (width - _buttonsWidth - _titleMargin < _minimumTitleFieldSize)
|
||||
[_titleField setFrame:CGRectMake((mimicWindows ? _titleMargin : _buttonsWidth), 0, width - _buttonsWidth - _titleMargin, _titleBarHeight)];
|
||||
else
|
||||
[_titleField setFrame:CGRectMake((mimicWindows ? width - _buttonsWidth - _minimumTitleFieldSize : _buttonsWidth), 0, _minimumTitleFieldSize, _titleBarHeight)];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)_minimumResizeSize
|
||||
{
|
||||
// The minimum width is such that the close button would always be visible.
|
||||
// We give the same margin to the right of the button as there is to the left.
|
||||
var size = [super _minimumResizeSize],
|
||||
closeSize = [self valueForThemeAttribute:@"close-image-size"],
|
||||
closeOrigin = [self valueForThemeAttribute:@"close-image-origin"];
|
||||
// The minimum width is such that the close/minimize/zoom button(s) would always be visible.
|
||||
// We give the same margin to the right of the button(s) as there is to the left.
|
||||
var size = CGSizeMakeCopy([super _minimumResizeSize]);
|
||||
|
||||
size.width = closeSize.width + (closeOrigin.x * 2);
|
||||
size.width = _buttonsWidth;
|
||||
size.height += _CPStandardWindowViewDividerViewHeight;
|
||||
|
||||
return size;
|
||||
@@ -413,4 +615,94 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
return [_bodyView frame].origin.y;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Hover management for buttons
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
if (_closeButtonTrackingArea)
|
||||
[_closeButton removeTrackingArea:_closeButtonTrackingArea];
|
||||
|
||||
if (_minimizeButtonTrackingArea)
|
||||
[_minimizeButton removeTrackingArea:_minimizeButtonTrackingArea];
|
||||
|
||||
if (_zoomButtonTrackingArea)
|
||||
[_zoomButton removeTrackingArea:_zoomButtonTrackingArea];
|
||||
|
||||
if (_closeButton)
|
||||
{
|
||||
_closeButtonTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveAlways | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:_closeButton];
|
||||
[_closeButton addTrackingArea:_closeButtonTrackingArea];
|
||||
}
|
||||
|
||||
if (_minimizeButton)
|
||||
{
|
||||
_minimizeButtonTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveAlways | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:_minimizeButton];
|
||||
[_minimizeButton addTrackingArea:_minimizeButtonTrackingArea];
|
||||
}
|
||||
|
||||
if (_zoomButton)
|
||||
{
|
||||
_zoomButtonTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveAlways | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:_zoomButton];
|
||||
[_zoomButton addTrackingArea:_zoomButtonTrackingArea];
|
||||
}
|
||||
|
||||
[super updateTrackingAreas];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
var triggeredButton = [[anEvent trackingArea] userInfo],
|
||||
state = CPThemeStateHovered;
|
||||
|
||||
if ([CPApp shouldMimicWindows])
|
||||
state = state.and(CPThemeStateWindowsPlatform);
|
||||
|
||||
if (triggeredButton === _closeButton)
|
||||
{
|
||||
if (_isDocumentEdited)
|
||||
[_closeButton setImage:[self valueForThemeAttribute:@"unsaved-image-button" inState:state]];
|
||||
else
|
||||
[_closeButton setImage:[self valueForThemeAttribute:@"close-image-button" inState:state]];
|
||||
}
|
||||
else if (triggeredButton === _minimizeButton)
|
||||
{
|
||||
[_minimizeButton setImage:[self valueForThemeAttribute:@"minimize-image-button" inState:state]];
|
||||
}
|
||||
else if (triggeredButton === _zoomButton)
|
||||
{
|
||||
[_zoomButton setImage:[self valueForThemeAttribute:@"zoom-image-button" inState:state]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
var triggeredButton = [[anEvent trackingArea] userInfo];
|
||||
|
||||
if (triggeredButton === _closeButton)
|
||||
{
|
||||
if (_isDocumentEdited)
|
||||
[_closeButton setImage:[self currentValueForThemeAttribute:@"unsaved-image-button"]];
|
||||
else
|
||||
[_closeButton setImage:[self currentValueForThemeAttribute:@"close-image-button"]];
|
||||
}
|
||||
else if (triggeredButton === _minimizeButton)
|
||||
{
|
||||
[_minimizeButton setImage:[self currentValueForThemeAttribute:@"minimize-image-button"]];
|
||||
}
|
||||
else if (triggeredButton === _zoomButton)
|
||||
{
|
||||
[_zoomButton setImage:[self currentValueForThemeAttribute:@"zoom-image-button"]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
@implementation _CPTitleableWindowView : _CPWindowView
|
||||
{
|
||||
CPTextField _titleField;
|
||||
int _minimumTitleFieldSize;
|
||||
int _titleBarHeight;
|
||||
int _titleMargin;
|
||||
}
|
||||
|
||||
+ (int)titleBarHeight
|
||||
@@ -47,7 +50,7 @@
|
||||
|
||||
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
|
||||
{
|
||||
var frameRect = CGRectMakeCopy(aContentRect),
|
||||
var frameRect = [super frameRectForContentRect:aContentRect],
|
||||
titleBarHeight = [self titleBarHeight];
|
||||
|
||||
frameRect.origin.y -= titleBarHeight;
|
||||
@@ -62,15 +65,19 @@
|
||||
|
||||
if (self)
|
||||
{
|
||||
// We cache some values for optimization
|
||||
_titleBarHeight = [[self class] titleBarHeight];
|
||||
_titleMargin = [self currentValueForThemeAttribute:@"title-margin"];
|
||||
|
||||
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[_titleField setHitTests:NO];
|
||||
[_titleField setStringValue:@"Untitled"];
|
||||
[_titleField sizeToFit];
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
[_titleField setStringValue:@""];
|
||||
[self setTitle:@""];
|
||||
|
||||
[_titleField setFrame:CGRectMake(20.0, 3.0, CGRectGetWidth([self bounds]) - 40.0, CGRectGetHeight([_titleField frame]))];
|
||||
[_titleField setFrame:CGRectMake(_titleMargin, 3.0, CGRectGetWidth([self bounds]) - 2 * _titleMargin, CGRectGetHeight([_titleField frame]))];
|
||||
|
||||
[self addSubview:_titleField];
|
||||
|
||||
@@ -83,6 +90,8 @@
|
||||
- (void)setTitle:(CPString)aTitle
|
||||
{
|
||||
[_titleField setStringValue:aTitle];
|
||||
|
||||
_minimumTitleFieldSize = [_titleField _minimumFrameSize].width;
|
||||
}
|
||||
|
||||
- (void)tile
|
||||
@@ -95,7 +104,7 @@
|
||||
|
||||
// The vertical alignment of the title is set by the theme, so just give it all available space. By default
|
||||
// the title will vertically centre within.
|
||||
[_titleField setFrame:CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])];
|
||||
[_titleField setFrame:CGRectMake(_titleMargin, 0, width - 2 * _titleMargin, _titleBarHeight)];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
|
||||
Reference in New Issue
Block a user