mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-11-10 00:48:45 +00:00
AppKit: Replace OS behaviour API with theme-driven window frame layout
Eliminate brittle platform-specific branching and the incomplete host-platform OS behaviour API, replacing them with a unified layout model where window frames, titles, and controls derive entirely from the active theme, with platform variants selected through a private function. * CPApplication.j: - Remove setOSBehavior:, OSBehavior, shouldMimicWindows, and simulatesWindows accessors, along with associated Info.plist keys and user defaults. - Set default theme selection through _CPThemeVariant. * CPApplication_Constants.j: Remove OS behaviour constants, dictionary, and notification. * CPCompatibility.j: Add _CPBrowserOperatingSystem to return the detected host operating system. * CPTheme.j: Remove CPThemeStateWindowsPlatform; add _CPThemeVariant to return the base theme. * CPWindow.j: Remove the _close delegation to the window view. * _CPStandardWindowView.j: - Remove OS behaviour observer, _close, and _osBehaviorDidChange:. - Position buttons and title using theme values during layout, applying fallback defaults when theme values are absent. - Read title bar and sheet values from the view's active theme rather than the default theme. * _CPTitleableWindowView.j: Query title-margin dynamically during layout instead of caching.
This commit is contained in:
1 parent
073b18b162
commit
c062669fb5
7 files changed
+126
-288
No files matched your search
+2
-72
@@ -127,10 +127,6 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
CPMenuItem _windowsMenuSeparator;
|
||||
|
||||
CPThemeBlend _themeBlend @accessors(property=themeBlend);
|
||||
|
||||
// OS behavior
|
||||
CPApplicationOSBehavior _OSBehavior;
|
||||
BOOL _simulatesWindows;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -163,9 +159,6 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
_eventListenerInsertionIndex = 0;
|
||||
|
||||
_windows = [[CPNull null]];
|
||||
|
||||
_OSBehavior = CPApplicationLegacyOSBehavior;
|
||||
_simulatesWindows = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1503,44 +1496,6 @@ 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)
|
||||
@@ -1667,35 +1622,10 @@ var _CPAppBootstrapperActions = nil;
|
||||
+ (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
|
||||
{
|
||||
[[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"]];
|
||||
var baseTheme = [CPTheme themeNamed:[CPApplication defaultThemeName]];
|
||||
|
||||
// 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.");
|
||||
}
|
||||
[CPTheme setDefaultTheme:_CPThemeVariant(baseTheme, nil, _CPBrowserOperatingSystem())];
|
||||
|
||||
[self performActions];
|
||||
}
|
||||
|
||||
@@ -39,15 +39,3 @@ 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
|
||||
};
|
||||
@@ -355,6 +355,14 @@ function CPBrowserIsOperatingSystem(anOperatingSystem)
|
||||
return OPERATING_SYSTEM === anOperatingSystem;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the host operating system, as detected when this file loads.
|
||||
*/
|
||||
function _CPBrowserOperatingSystem()
|
||||
{
|
||||
return OPERATING_SYSTEM;
|
||||
}
|
||||
|
||||
OPERATING_SYSTEM = CPOtherOperatingSystem;
|
||||
|
||||
if (USER_AGENT.indexOf("Mac") !== -1)
|
||||
|
||||
+13
-1
@@ -291,6 +291,18 @@ var CPThemesByName = { },
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
Returns the variant of a theme for an appearance and a host platform. The variants
|
||||
of one theme share its metrics. They differ in colours and images, and in the place
|
||||
of decoration such as the window buttons and the title. This function selects no
|
||||
variant yet: it returns the base theme for every appearance and every host, so
|
||||
every host has the base theme's look.
|
||||
*/
|
||||
function _CPThemeVariant(aBaseTheme, anAppearance, aPlatform)
|
||||
{
|
||||
return aBaseTheme;
|
||||
}
|
||||
|
||||
var CPThemeNameKey = @"CPThemeNameKey",
|
||||
CPThemeAttributesKey = @"CPThemeAttributesKey";
|
||||
|
||||
@@ -817,7 +829,7 @@ CPThemeStateControlSizeMini = CPThemeState("controlSizeMini");
|
||||
CPThemeStateControlSizeLarge = CPThemeState("controlSizeLarge");
|
||||
CPThemeStateAlternateState = CPThemeState("alternate");
|
||||
CPThemeStateComposedControl = CPThemeState("composed");
|
||||
CPThemeStateWindowsPlatform = CPThemeState("windowsPlatform");
|
||||
|
||||
CPThemeStateNormalString = String(CPThemeStateNormal);
|
||||
CPThemeStateHUD = CPThemeState("hud");
|
||||
|
||||
|
||||
@@ -2614,10 +2614,6 @@ 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,7 +22,6 @@
|
||||
|
||||
@import "CPButton.j"
|
||||
@import "_CPTitleableWindowView.j"
|
||||
@import "CPApplication_Constants.j"
|
||||
|
||||
@class _CPDocModalWindowView
|
||||
|
||||
@@ -68,13 +67,18 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
The head view draws with the theme values of its window view, in the window view's
|
||||
current state, so it follows the window's theme. It read them from the default
|
||||
theme, so under any other theme it drew the default theme's height and colours.
|
||||
*/
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
var gradientHeight = [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView],
|
||||
var gradientHeight = [_parentView valueForThemeAttribute:@"gradient-height"],
|
||||
bounds = [self bounds],
|
||||
bezelHeadColor = [[CPTheme defaultTheme] valueForAttributeWithName:_isSheet ? @"bezel-head-sheet-color" : @"bezel-head-color" inState:[_parentView themeState] forClass:_CPStandardWindowView];
|
||||
bezelHeadColor = [_parentView currentValueForThemeAttribute:_isSheet ? @"bezel-head-sheet-color" : @"bezel-head-color"];
|
||||
|
||||
// Apply the border/background color to self (the container) so borders are drawn on the outside
|
||||
[self setBackgroundColor:bezelHeadColor];
|
||||
@@ -84,18 +88,19 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
// Set x=0.0 to avoid 1px gap. Width is reduced by 2.0.
|
||||
[_solidView setFrame:CGRectMake(0.0, gradientHeight, CGRectGetWidth(bounds) - 2.0, CGRectGetHeight(bounds) - gradientHeight)];
|
||||
[_solidView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"solid-color" forClass:_CPStandardWindowView]];
|
||||
[_solidView setBackgroundColor:[_parentView currentValueForThemeAttribute:@"solid-color"]];
|
||||
}
|
||||
|
||||
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
|
||||
{
|
||||
var bounds = [self bounds],
|
||||
width = CGRectGetWidth(bounds) - 2.0; // Account for border inset
|
||||
width = CGRectGetWidth(bounds) - 2.0, // Account for border inset
|
||||
gradientHeight = [_parentView valueForThemeAttribute:@"gradient-height"];
|
||||
|
||||
if (width < 0) width = 0;
|
||||
|
||||
[_gradientView setFrameSize:CGSizeMake(width, [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])];
|
||||
[_solidView setFrameSize:CGSizeMake(width, CGRectGetHeight(bounds) - [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])];
|
||||
[_gradientView setFrameSize:CGSizeMake(width, gradientHeight)];
|
||||
[_solidView setFrameSize:CGSizeMake(width, CGRectGetHeight(bounds) - gradientHeight)];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -235,22 +240,14 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
[self addSubview:_minimizeButton];
|
||||
}
|
||||
|
||||
[self _updateWindowButtons:YES];
|
||||
[self _updateWindowButtons];
|
||||
[self updateTrackingAreas];
|
||||
[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]];
|
||||
@@ -293,168 +290,64 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
[_bodyView setFrame:CGRectMake(0.0, dividerMinY, width, CGRectGetHeight(bounds) - dividerMinY)];
|
||||
|
||||
[_titleField setFrame:CGRectMake(_buttonsWidth, 0, width - _buttonsWidth * 2.0, _titleBarHeight)];
|
||||
[self _layoutTitleField];
|
||||
|
||||
var contentFrame = [_bodyView frame];
|
||||
[[theWindow contentView] setFrame:CGRectInset(contentFrame, 1.0, 1.0)];
|
||||
}
|
||||
|
||||
- (void)_updateWindowButtons:(BOOL)shouldRefreshLayout
|
||||
/*
|
||||
The buttons are placed from the theme values on every layout, so a change of theme
|
||||
moves them. They were placed only when the view was made, so the window kept the
|
||||
old theme's positions. The positions come from the theme alone, with no branch for
|
||||
the host platform. A theme without positions gets fixed defaults.
|
||||
*/
|
||||
- (void)_updateWindowButtons
|
||||
{
|
||||
if (shouldRefreshLayout)
|
||||
var closeOrigin = CGPointMakeCopy([self currentValueForThemeAttribute:@"close-image-origin"] || CGPointMake(8.0, 8.0)),
|
||||
minimizeOrigin = CGPointMakeCopy([self currentValueForThemeAttribute:@"minimize-image-origin"] || CGPointMake(27.0, 7.0)),
|
||||
zoomOrigin = CGPointMakeCopy([self currentValueForThemeAttribute:@"zoom-image-origin"] || CGPointMake(46.0, 8.0)),
|
||||
delta1 = minimizeOrigin.x - closeOrigin.x,
|
||||
delta2 = zoomOrigin.x - minimizeOrigin.x;
|
||||
|
||||
_buttonsWidth = 0;
|
||||
|
||||
if (_styleMask & CPClosableWindowMask)
|
||||
{
|
||||
var mimicWindows = [CPApp shouldMimicWindows];
|
||||
var closeSize = [self currentValueForThemeAttribute:@"close-image-size"] || CGSizeMake(16.0, 16.0);
|
||||
|
||||
if (mimicWindows)
|
||||
[self setThemeState:CPThemeStateWindowsPlatform];
|
||||
else
|
||||
[self unsetThemeState:CPThemeStateWindowsPlatform];
|
||||
[_closeButton setFrame:CGRectMake(closeOrigin.x, closeOrigin.y, closeSize.width, closeSize.height)];
|
||||
|
||||
// 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];
|
||||
_buttonsWidth = closeOrigin.x + closeSize.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
minimizeOrigin.x -= delta1;
|
||||
zoomOrigin.x -= delta1;
|
||||
}
|
||||
|
||||
if (_styleMask & CPMiniaturizableWindowMask)
|
||||
{
|
||||
var minimizeSize = [self currentValueForThemeAttribute:@"minimize-image-size"] || CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_minimizeButton setFrame:CGRectMake(minimizeOrigin.x, minimizeOrigin.y, minimizeSize.width, minimizeSize.height)];
|
||||
|
||||
_buttonsWidth = minimizeOrigin.x + minimizeSize.width;
|
||||
}
|
||||
else
|
||||
zoomOrigin.x -= delta2;
|
||||
|
||||
if (_styleMask & CPResizableWindowMask)
|
||||
{
|
||||
var zoomSize = [self currentValueForThemeAttribute:@"zoom-image-size"] || CGSizeMake(16.0, 16.0);
|
||||
|
||||
[_zoomButton setFrame:CGRectMake(zoomOrigin.x, zoomOrigin.y, zoomSize.width, zoomSize.height)];
|
||||
|
||||
_buttonsWidth = zoomOrigin.x + zoomSize.width;
|
||||
}
|
||||
|
||||
if (_buttonsWidth > 0)
|
||||
_buttonsWidth += closeOrigin.x;
|
||||
|
||||
[self _updateCloseButton];
|
||||
|
||||
@@ -464,6 +357,29 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
[_zoomButton setAlternateImage:[self currentValueForThemeAttribute:@"zoom-image-highlighted-button"]];
|
||||
}
|
||||
|
||||
/*
|
||||
The title fills the space between the buttons and the same width on the other side.
|
||||
When that is too narrow for the title, the title gives up the space on the other
|
||||
side first. The title margin is read from the theme here, so a change of theme
|
||||
moves the title.
|
||||
*/
|
||||
- (void)_layoutTitleField
|
||||
{
|
||||
var width = CGRectGetWidth([self bounds]),
|
||||
titleMargin = [self currentValueForThemeAttribute:@"title-margin"],
|
||||
titleWidth = width - 2.0 * _buttonsWidth;
|
||||
|
||||
if (titleWidth < _minimumTitleFieldSize)
|
||||
{
|
||||
if (width - _buttonsWidth - titleMargin < _minimumTitleFieldSize)
|
||||
titleWidth = width - _buttonsWidth - titleMargin;
|
||||
else
|
||||
titleWidth = _minimumTitleFieldSize;
|
||||
}
|
||||
|
||||
[_titleField setFrame:CGRectMake(_buttonsWidth, 0, titleWidth, _titleBarHeight)];
|
||||
}
|
||||
|
||||
- (void)_updateCloseButton
|
||||
{
|
||||
if (_isDocumentEdited)
|
||||
@@ -478,11 +394,6 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_osBehaviorDidChange:(id)application
|
||||
{
|
||||
[self _updateWindowButtons:YES];
|
||||
}
|
||||
|
||||
- (void)setDocumentEdited:(BOOL)isEdited
|
||||
{
|
||||
_isDocumentEdited = isEdited;
|
||||
@@ -526,7 +437,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
[_bodyView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"body-color" forClass:_CPDocModalWindowView]];
|
||||
[_bodyView setBackgroundColor:[[self actualTheme] valueForAttributeWithName:@"body-color" forClass:_CPDocModalWindowView]];
|
||||
|
||||
// Move the shadow view down so it is inside the content border
|
||||
var shadowFrame = [_sheetShadowView frame];
|
||||
@@ -542,7 +453,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
dy = [self toolbarMaxY] + dividerHeight;
|
||||
|
||||
if (_toolbarView && [self showsToolbar])
|
||||
dy = [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView];
|
||||
dy = [self valueForThemeAttribute:@"gradient-height"];
|
||||
|
||||
if (enable)
|
||||
dy = -dy;
|
||||
@@ -562,26 +473,15 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
var width = [self bounds].size.width,
|
||||
mimicWindows = [CPApp shouldMimicWindows];
|
||||
|
||||
[super layoutSubviews];
|
||||
|
||||
if (_closeButton || _minimizeButton || _zoomButton)
|
||||
[self _updateWindowButtons:NO];
|
||||
[self _updateWindowButtons];
|
||||
[self _layoutTitleField];
|
||||
|
||||
[_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
|
||||
@@ -650,9 +550,6 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
|
||||
var triggeredButton = [[anEvent trackingArea] userInfo],
|
||||
state = CPThemeStateHovered;
|
||||
|
||||
if ([CPApp shouldMimicWindows])
|
||||
state = state.and(CPThemeStateWindowsPlatform);
|
||||
|
||||
if (triggeredButton === _closeButton)
|
||||
{
|
||||
if (_isDocumentEdited)
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
CPTextField _titleField;
|
||||
int _minimumTitleFieldSize;
|
||||
int _titleBarHeight;
|
||||
int _titleMargin;
|
||||
}
|
||||
|
||||
+ (int)titleBarHeight
|
||||
@@ -67,7 +66,8 @@
|
||||
{
|
||||
// We cache some values for optimization
|
||||
_titleBarHeight = [[self class] titleBarHeight];
|
||||
_titleMargin = [self currentValueForThemeAttribute:@"title-margin"];
|
||||
|
||||
var titleMargin = [self currentValueForThemeAttribute:@"title-margin"];
|
||||
|
||||
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
[_titleField setAutoresizingMask:CPViewWidthSizable];
|
||||
[self setTitle:@""];
|
||||
|
||||
[_titleField setFrame:CGRectMake(_titleMargin, 3.0, CGRectGetWidth([self bounds]) - 2 * _titleMargin, CGRectGetHeight([_titleField frame]))];
|
||||
[_titleField setFrame:CGRectMake(titleMargin, 3.0, CGRectGetWidth([self bounds]) - 2 * titleMargin, CGRectGetHeight([_titleField frame]))];
|
||||
|
||||
[self addSubview:_titleField];
|
||||
|
||||
@@ -100,11 +100,18 @@
|
||||
|
||||
var theWindow = [self window],
|
||||
bounds = [self bounds],
|
||||
width = CGRectGetWidth(bounds);
|
||||
width = CGRectGetWidth(bounds),
|
||||
titleMargin = [self currentValueForThemeAttribute:@"title-margin"];
|
||||
|
||||
// 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(_titleMargin, 0, width - 2 * _titleMargin, _titleBarHeight)];
|
||||
/*
|
||||
The title margin is read from the theme at each tile, so the title follows a
|
||||
change of theme. It was copied when the view was made, so the title kept the
|
||||
old theme's margin.
|
||||
|
||||
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(titleMargin, 0, width - 2 * titleMargin, _titleBarHeight)];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
|
||||
Reference in new issue
Block a user