* Headers/Additions/GNUstepGUI/GSTheme.h: Remove GSScrollViewBottomCorner

part name, instead themes should just provide a part called NSScrollView.

	Add -scrollViewScrollersOverlapBorders method.

	* Source/GSTheme.m: Remove GSScrollViewBottomCorner part name.
	* Source/GSThemeDrawing.m: Add -scrollViewScrollersOverlapBorders.
	* Source/GSThemeDrawing.m (-drawBrowserRect:...): If
	-scrollViewScrollersOverlapBorders is enabled, fill the browser background
	with the NSScrollView tile.
	* Source/GSThemeDrawing.m (-drawScrollViewRect:...): If
	-scrollViewScrollersOverlapBorders is enabled, fill the scroll view background
	with the NSScrollView tile.
	* Source/NSScroller.m (-rectForPart:): Change the meaning of the
	GSScrollerKnobOvershoot default so the knob only overlaps the buttons
	by this much (rather than both ends of the track). Turns out this is more
	useful for themes.
	* Source/NSScrollView.m (-tile): Add support for
	-[GSTheme scrollViewScrollersOverlapBorders]
	* Source/NSBrowser.m (-tile): Add support for
	-[GSTheme scrollViewScrollersOverlapBorders] and
	-[GSTheme scrollViewUseBottomCorner]

	The overall point of these additions is to support NSScrollView and
	NSBrowser looking like: http://jesseross.com/clients/gnustep/ui/concepts/


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@37238 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Eric Wasylishen 2013-10-15 23:26:51 +00:00
parent 4e1aeabe94
commit 310b7d5786
7 changed files with 209 additions and 54 deletions

View file

@ -1,3 +1,31 @@
2013-10-15 Eric Wasylishen <ewasylishen@gmail.com>
* Headers/Additions/GNUstepGUI/GSTheme.h: Remove GSScrollViewBottomCorner
part name, instead themes should just provide a part called NSScrollView.
Add -scrollViewScrollersOverlapBorders method.
* Source/GSTheme.m: Remove GSScrollViewBottomCorner part name.
* Source/GSThemeDrawing.m: Add -scrollViewScrollersOverlapBorders.
* Source/GSThemeDrawing.m (-drawBrowserRect:...): If
-scrollViewScrollersOverlapBorders is enabled, fill the browser background
with the NSScrollView tile.
* Source/GSThemeDrawing.m (-drawScrollViewRect:...): If
-scrollViewScrollersOverlapBorders is enabled, fill the scroll view background
with the NSScrollView tile.
* Source/NSScroller.m (-rectForPart:): Change the meaning of the
GSScrollerKnobOvershoot default so the knob only overlaps the buttons
by this much (rather than both ends of the track). Turns out this is more
useful for themes.
* Source/NSScrollView.m (-tile): Add support for
-[GSTheme scrollViewScrollersOverlapBorders]
* Source/NSBrowser.m (-tile): Add support for
-[GSTheme scrollViewScrollersOverlapBorders] and
-[GSTheme scrollViewUseBottomCorner]
The overall point of these additions is to support NSScrollView and
NSBrowser looking like: http://jesseross.com/clients/gnustep/ui/concepts/
2013-10-15 Eric Wasylishen <ewasylishen@gmail.com>
* Source/NSTableView.m (-tile): Check the GSScrollViewNoInnerBorder

View file

@ -268,9 +268,6 @@ APPKIT_EXPORT NSString *GSScrollerUpArrow;
APPKIT_EXPORT NSString *GSScrollerVerticalKnob;
APPKIT_EXPORT NSString *GSScrollerVerticalSlot;
/* Scroll view parts */
APPKIT_EXPORT NSString *GSScrollViewBottomCorner;
/* Names for table view parts */
APPKIT_EXPORT NSString *GSTableHeader;
APPKIT_EXPORT NSString *GSTableCorner;
@ -891,7 +888,22 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
*/
- (float) defaultScrollerWidth;
- (BOOL) scrolViewUseBottomCorner;
/**
* If YES, instructs NSScrollView to leave an empty square space where
* the horizontal and vertical scrollers meet.
*
* Controlled by user default GSScrollViewUseBottomCorner; default YES.
*/
- (BOOL) scrollViewUseBottomCorner;
/**
* If YES, instructs NSScrollView to make the scrollers overlap the border.
* The scroll view border is drawn using the NSScrollView part, which
* must be provided by the theme if this method returns YES.
*
* Controlled by user default GSScrollViewScrollersOverlapBorders; default NO;
*/
- (BOOL) scrollViewScrollersOverlapBorders;
/**
* Method for toolbar theming.

View file

@ -77,9 +77,6 @@ NSString *GSScrollerUpArrow = @"GSScrollerUpArrow";
NSString *GSScrollerVerticalKnob = @"GSScrollerVerticalKnob";
NSString *GSScrollerVerticalSlot = @"GSScrollerVerticalSlot";
// Scroll view parts
NSString *GSScrollViewBottomCorner = @"GSScrollViewBottomCorner";
// Table view part names
NSString *GSTableHeader = @"GSTableHeader";
NSString *GSTableCorner = @"GSTableCorner";

View file

@ -611,7 +611,7 @@
return defaultScrollerWidth;
}
- (BOOL) scrolViewUseBottomCorner
- (BOOL) scrollViewUseBottomCorner
{
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
if ([defs objectForKey: @"GSScrollViewUseBottomCorner"] != nil)
@ -621,6 +621,16 @@
return YES;
}
- (BOOL) scrollViewScrollersOverlapBorders
{
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
if ([defs objectForKey: @"GSScrollViewScrollersOverlapBorders"] != nil)
{
return [defs boolForKey: @"GSScrollViewScrollersOverlapBorders"];
}
return NO;
}
- (NSColor *) toolbarBackgroundColor
{
NSColor *color;
@ -2435,6 +2445,21 @@ typedef enum {
}
}
}
if (![self browserUseBezels]
&& [self scrollViewScrollersOverlapBorders])
{
NSRect baseRect = NSMakeRect(0, 0, bounds.size.width, 1);
NSRect colFrame = [browser frameOfColumn: [browser firstVisibleColumn]];
NSRect scrollViewRect = NSUnionRect(baseRect, colFrame);
GSDrawTiles *tiles = [self tilesNamed: @"NSScrollView"
state: GSThemeNormalState];
[self fillRect: scrollViewRect
withTiles: tiles
background: [NSColor clearColor]];
}
}
- (CGFloat) browserColumnSeparation
@ -2521,6 +2546,7 @@ typedef enum {
NSRect bounds = [view bounds];
BOOL hasInnerBorder = ![[NSUserDefaults standardUserDefaults]
boolForKey: @"GSScrollViewNoInnerBorder"];
GSDrawTiles *tiles = nil;
name = [theme nameForElement: self];
if (name == nil)
@ -2528,28 +2554,38 @@ typedef enum {
name = @"NSScrollView";
}
color = [theme colorNamed: name state: GSThemeNormalState];
tiles = [theme tilesNamed: name state: GSThemeNormalState];
if (color == nil)
{
color = [NSColor controlDarkShadowColor];
}
switch (borderType)
if (tiles == nil)
{
case NSNoBorder:
break;
case NSLineBorder:
[color set];
NSFrameRect(bounds);
break;
case NSBezelBorder:
[theme drawGrayBezel: bounds withClip: rect];
break;
case NSGrooveBorder:
[theme drawGroove: bounds withClip: rect];
break;
switch (borderType)
{
case NSNoBorder:
break;
case NSLineBorder:
[color set];
NSFrameRect(bounds);
break;
case NSBezelBorder:
[theme drawGrayBezel: bounds withClip: rect];
break;
case NSGrooveBorder:
[theme drawGroove: bounds withClip: rect];
break;
}
}
else
{
[self fillRect: bounds
withTiles: tiles
background: [NSColor clearColor]];
}
if (hasInnerBorder)
@ -2600,26 +2636,6 @@ typedef enum {
DPSstroke(ctxt);
}
}
if (![self scrolViewUseBottomCorner]
&& [scrollView hasHorizontalScroller]
&& [scrollView hasVerticalScroller])
{
NSScroller *vertScroller = [scrollView verticalScroller];
NSScroller *horizScroller = [scrollView horizontalScroller];
NSRect bottomCornerRect = NSMakeRect([vertScroller frame].origin.x,
[horizScroller frame].origin.y,
NSWidth([vertScroller frame]),
NSHeight([horizScroller frame]));
GSDrawTiles *tiles = [self tilesNamed: GSScrollViewBottomCorner
state: GSThemeNormalState];
[self fillRect: bottomCornerRect
withTiles: tiles
background: [NSColor clearColor]];
}
}
- (void) drawSliderBorderAndBackground: (NSBorderType)aType

View file

@ -1811,6 +1811,12 @@ static BOOL browserUseBezels;
else
rect.size.width = _frame.size.width -
(rect.origin.x + bezelBorderSize.width);
// FIXME: Assumes left-side scrollers
if ([[GSTheme theme] scrollViewScrollersOverlapBorders])
{
rect.size.width -= 1;
}
}
if (rect.size.width < 0)
@ -1863,6 +1869,8 @@ static BOOL browserUseBezels;
NSSize bezelBorderSize = NSZeroSize;
NSInteger i, num, columnCount, delta;
CGFloat frameWidth;
const BOOL overlapBorders = [[GSTheme theme] scrollViewScrollersOverlapBorders];
const BOOL useBottomCorner = [[GSTheme theme] scrollViewUseBottomCorner];
if (browserUseBezels)
bezelBorderSize = [[GSTheme theme] sizeForBorderType: NSBezelBorder];
@ -1892,6 +1900,21 @@ static BOOL browserUseBezels;
else
_columnSize.height -= scrollerWidth + (2 * bezelBorderSize.height);
// "Bottom corner" box
if (!browserUseBezels && !useBottomCorner)
{
_scrollerRect.origin.x += scrollerWidth;
_scrollerRect.size.width -= scrollerWidth;
}
/** Horizontall expand the scroller by GSScrollerKnobOvershoot on the left */
if (overlapBorders)
{
// FIXME: Assumes left scroller
_scrollerRect.origin.x -= 1;
_scrollerRect.size.width += 1;
}
if (!NSEqualRects(_scrollerRect, [_horizontalScroller frame]))
{
[_horizontalScroller setFrame: _scrollerRect];

View file

@ -1064,6 +1064,12 @@ static CGFloat scrollerWidth;
[self tile];
}
static NSRectEdge
GSOppositeEdge(NSRectEdge edge)
{
return (edge == NSMinXEdge) ? NSMaxXEdge : NSMinXEdge;
}
- (void) tile
{
NSRect headerRect, contentRect;
@ -1075,8 +1081,9 @@ static CGFloat scrollerWidth;
CGFloat innerBorderWidth = [[NSUserDefaults standardUserDefaults]
boolForKey: @"GSScrollViewNoInnerBorder"] ? 0.0 : 1.0;
BOOL useBottomCorner = [[GSTheme theme] scrolViewUseBottomCorner];
const BOOL useBottomCorner = [[GSTheme theme] scrollViewUseBottomCorner];
const BOOL overlapBorders = [[GSTheme theme] scrollViewScrollersOverlapBorders];
style = NSInterfaceStyleForKey(@"NSScrollViewInterfaceStyle", nil);
if (style == NSMacintoshInterfaceStyle
@ -1098,7 +1105,11 @@ static CGFloat scrollerWidth;
}
/* Prepare the contentRect by insetting the borders. */
contentRect = NSInsetRect(_bounds, border.width, border.height);
contentRect = _bounds;
if (!overlapBorders)
contentRect = NSInsetRect(contentRect, border.width, border.height);
if (contentRect.size.width < 0 || contentRect.size.height < 0)
{
/* FIXME ... should we do something else when given
@ -1108,6 +1119,32 @@ static CGFloat scrollerWidth;
[self _synchronizeHeaderAndCornerView];
if (overlapBorders)
{
if (_borderType != NSNoBorder)
{
if (!(_hasHeaderView || _hasCornerView))
{
// Inset 1px on the top
NSDivideRect(contentRect, NULL, &contentRect, 1, topEdge);
}
if (!_hasVertScroller)
{
// Inset 1px on the edge where the vertical scroller would be
NSDivideRect(contentRect, NULL, &contentRect, 1, verticalScrollerEdge);
}
if (!_hasHorizScroller)
{
NSDivideRect(contentRect, NULL, &contentRect, 1, bottomEdge);
}
// The vertical edge without a scroller
{
NSDivideRect(contentRect, NULL, &contentRect, 1,
GSOppositeEdge(verticalScrollerEdge));
}
}
}
/* First, allocate vertical space for the headerView / cornerView
(but - NB - the headerView needs to be placed above the clipview
later on, we can't place it now). */
@ -1151,6 +1188,13 @@ static CGFloat scrollerWidth;
scrollerWidth, bottomEdge);
}
/** Vertically expand the scroller by 1pt on each end */
if (overlapBorders)
{
vertScrollerRect.origin.y -= 1;
vertScrollerRect.size.height += 2;
}
[_vertScroller setFrame: vertScrollerRect];
/* Substract 1 for the line that separates the vertical scroller
@ -1167,6 +1211,13 @@ static CGFloat scrollerWidth;
NSDivideRect (contentRect, &horizScrollerRect, &contentRect,
scrollerWidth, bottomEdge);
/** Horizontall expand the scroller by 1pt on each end */
if (overlapBorders)
{
horizScrollerRect.origin.x -= 1;
horizScrollerRect.size.width += 2;
}
[_horizScroller setFrame: horizScrollerRect];
/* Substract 1 for the width for the line that separates the
@ -1300,10 +1351,10 @@ static CGFloat scrollerWidth;
- (BOOL) isOpaque
{
// FIXME: Only needs to be NO in a corner case,
// when [[GSTheme theme] scrolViewUseBottomCorner] is NO
// when [[GSTheme theme] scrollViewUseBottomCorner] is NO
// and the theme tile for the bottom corner is transparent.
// So maybe cache the value of
// [[GSTheme theme] scrolViewUseBottomCorner] and check it here.
// [[GSTheme theme] scrollViewUseBottomCorner] and check it here.
return NO;
}
@ -1739,6 +1790,13 @@ static CGFloat scrollerWidth;
- (void) _themeDidActivate: (NSNotification*)notification
{
// N.B. Reload cached [NSScroller scrollerWidth] since the
// new theme may have a different scroller width.
//
// Since scrollerWidth is a static, it will get overwritten
// several times; doesn't matter though.
scrollerWidth = [NSScroller scrollerWidth];
[self tile];
}

View file

@ -68,8 +68,8 @@ static NSCell *horizontalKnobSlotCell = nil;
static NSCell *verticalKnobSlotCell = nil;
static CGFloat scrollerWidth = 0.0;
/**
* This is the amount (in userspace points) by which the knob slides beyond
* either end of the track. Typical use would be to set it to 1 when both
* This is the amount (in userspace points) by which the knob slides over the
* button ends of the track. Typical use would be to set it to 1 when both
* the knob and the buttons have a 1-point border, so that when the knob is
* at its maximum, it overlaps the button by 1 point giving a resulting
* 1-point wide border.
@ -1229,8 +1229,29 @@ static float buttonsOffset = 1.0; // buttonsWidth = sw - 2*buttonsOffset
knobHeight = buttonsWidth;
/* calc knob's position */
knobPosition = floor((float)_doubleValue * (slotHeight - knobHeight + (2 * scrollerKnobOvershoot)))
- scrollerKnobOvershoot;
{
CGFloat knobOvershootAbove = scrollerKnobOvershoot;
CGFloat knobOvershootBelow = scrollerKnobOvershoot;
if (arrowsSameEnd
&& _arrowsPosition == NSScrollerArrowsMinEnd)
{
knobOvershootBelow = 0;
}
else if (arrowsSameEnd
&& _arrowsPosition == NSScrollerArrowsMaxEnd)
{
knobOvershootAbove = 0;
}
else if (_arrowsPosition == NSScrollerArrowsNone)
{
knobOvershootAbove = 0;
knobOvershootBelow = 0;
}
knobPosition = floor((float)_doubleValue * (slotHeight - knobHeight + knobOvershootAbove + knobOvershootBelow))
- knobOvershootAbove;
}
if (arrowsSameEnd)
{