Skip to content
This repository has been archived by the owner on Sep 4, 2018. It is now read-only.

Commit

Permalink
Fix ATZSegmentedControl's focus ring and click area
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaumealgis committed Jul 11, 2015
1 parent fedf79b commit 1a4dc5a
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 76 deletions.
6 changes: 6 additions & 0 deletions Alcatraz.xcodeproj/project.pbxproj
Expand Up @@ -57,6 +57,7 @@
8AD5249F174102F9008B451F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8AD524A2174102F9008B451F /* Localizable.strings */; };
8ADC22341A2AD5B800DB7BCA /* ATZPreviewImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ADC22331A2AD5B800DB7BCA /* ATZPreviewImageButton.m */; };
8AF670C919C2DE8A00E1C168 /* ATZSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AF670C819C2DE8A00E1C168 /* ATZSegmentedControl.m */; };
F0DF961E1B40416400DF68CC /* ATZSegmentedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0DF961D1B40416400DF68CC /* ATZSegmentedCell.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -143,6 +144,8 @@
8ADC22331A2AD5B800DB7BCA /* ATZPreviewImageButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ATZPreviewImageButton.m; path = Views/ATZPreviewImageButton.m; sourceTree = "<group>"; };
8AF670C719C2DE8A00E1C168 /* ATZSegmentedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ATZSegmentedControl.h; path = Views/ATZSegmentedControl.h; sourceTree = "<group>"; };
8AF670C819C2DE8A00E1C168 /* ATZSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ATZSegmentedControl.m; path = Views/ATZSegmentedControl.m; sourceTree = "<group>"; };
F0DF961C1B40416300DF68CC /* ATZSegmentedCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZSegmentedCell.h; sourceTree = "<group>"; };
F0DF961D1B40416400DF68CC /* ATZSegmentedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATZSegmentedCell.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -329,6 +332,8 @@
8ADC22331A2AD5B800DB7BCA /* ATZPreviewImageButton.m */,
8AF670C719C2DE8A00E1C168 /* ATZSegmentedControl.h */,
8AF670C819C2DE8A00E1C168 /* ATZSegmentedControl.m */,
F0DF961C1B40416300DF68CC /* ATZSegmentedCell.h */,
F0DF961D1B40416400DF68CC /* ATZSegmentedCell.m */,
);
name = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -456,6 +461,7 @@
8917DA191726B63B00F0B2D2 /* ATZGit.m in Sources */,
8917DA1A1726B63B00F0B2D2 /* ATZShell.m in Sources */,
89B4F2BE172FF5AC001FD2E3 /* ATZPBXProjParser.m in Sources */,
F0DF961E1B40416400DF68CC /* ATZSegmentedCell.m in Sources */,
8A133EE319C235FD0068FCB9 /* ATZPackageListTableCellView.m in Sources */,
8A1732A81A2694BB002033D6 /* NSColor+Alcatraz.m in Sources */,
894714E817302F63003CDDA7 /* ATZInstaller.m in Sources */,
Expand Down
37 changes: 16 additions & 21 deletions Alcatraz/ATZPluginWindowController.xib
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ATZPluginWindowController">
Expand All @@ -23,7 +23,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" unifiedTitleAndToolbar="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="545" height="449"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="545" height="449"/>
<autoresizingMask key="autoresizingMask"/>
Expand All @@ -32,28 +32,22 @@
<rect key="frame" x="0.0" y="417" width="545" height="32"/>
<subviews>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="reu-CB-C0i" customClass="ATZSegmentedControl">
<rect key="frame" x="15" y="8" width="92" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="90" id="jvF-qg-y7j"/>
</constraints>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="roundRect" trackingMode="selectOne" id="5Tl-2Y-k8p">
<font key="font" size="11" name="HelveticaNeue"/>
<rect key="frame" x="16" y="4" width="111" height="24"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="separated" trackingMode="selectOne" id="5Tl-2Y-k8p">
<font key="font" metaFont="system"/>
<segments>
<segment label="All" width="37" selected="YES"/>
<segment label="Installed" width="38" tag="1"/>
<segment label="All" selected="YES"/>
<segment label="Installed" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="segmentedControlPressed:" target="-2" id="CPU-ex-EvU"/>
</connections>
</segmentedControl>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Wxk-Va-YMt" customClass="ATZSegmentedControl">
<rect key="frame" x="115" y="8" width="202" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="200" id="gNb-dE-2sJ"/>
</constraints>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="roundRect" trackingMode="selectOne" id="TlD-Cy-glk">
<font key="font" size="11" name="HelveticaNeue"/>
<rect key="frame" x="143" y="4" width="259" height="24"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="separated" trackingMode="selectOne" id="TlD-Cy-glk">
<font key="font" metaFont="system"/>
<segments>
<segment label="Plugins" selected="YES"/>
<segment label="Color Themes" tag="1"/>
Expand All @@ -74,13 +68,13 @@
</textField>
</subviews>
<constraints>
<constraint firstAttribute="centerY" secondItem="reu-CB-C0i" secondAttribute="centerY" constant="2" id="2rj-TD-hfT"/>
<constraint firstAttribute="centerY" secondItem="reu-CB-C0i" secondAttribute="centerY" id="2rj-TD-hfT"/>
<constraint firstAttribute="centerY" secondItem="hsV-nN-jHO" secondAttribute="centerY" constant="2" id="4if-cW-Xnv"/>
<constraint firstItem="Wxk-Va-YMt" firstAttribute="centerY" secondItem="reu-CB-C0i" secondAttribute="centerY" id="D5D-79-kC3"/>
<constraint firstItem="reu-CB-C0i" firstAttribute="leading" secondItem="0Fa-9p-0gT" secondAttribute="leading" constant="16" id="ELF-J2-Y4x"/>
<constraint firstAttribute="trailing" secondItem="hsV-nN-jHO" secondAttribute="trailing" constant="14" id="J89-aJ-Yya"/>
<constraint firstAttribute="height" constant="32" id="Yci-xm-ezL"/>
<constraint firstItem="Wxk-Va-YMt" firstAttribute="leading" secondItem="reu-CB-C0i" secondAttribute="trailing" constant="10" id="eMS-g8-tnJ"/>
<constraint firstItem="Wxk-Va-YMt" firstAttribute="leading" secondItem="reu-CB-C0i" secondAttribute="trailing" constant="16" id="eMS-g8-tnJ"/>
</constraints>
</customView>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ydl-IO-qKb">
Expand All @@ -90,9 +84,10 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnReordering="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowSizeStyle="automatic" viewBased="YES" id="Xmj-hd-CPE">
<rect key="frame" x="0.0" y="0.0" width="545" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn editable="NO" width="542" minWidth="40" maxWidth="1000" id="JR1-SH-OCh">
Expand Down Expand Up @@ -228,7 +223,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" utility="YES" HUD="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="139" y="81" width="276" height="378"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="WQe-dv-pdE">
<rect key="frame" x="0.0" y="0.0" width="276" height="378"/>
<autoresizingMask key="autoresizingMask"/>
Expand Down
26 changes: 26 additions & 0 deletions Alcatraz/ATZSegmentedCell.h
@@ -0,0 +1,26 @@
//
// Copyright (c) 2014 Marin Usalj | supermar.in
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import <Cocoa/Cocoa.h>

@interface ATZSegmentedCell : NSSegmentedCell

@end
142 changes: 142 additions & 0 deletions Alcatraz/ATZSegmentedCell.m
@@ -0,0 +1,142 @@
//
// Copyright (c) 2014 Marin Usalj | supermar.in
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import "ATZSegmentedCell.h"
#import "NSColor+Alcatraz.h"

static NSInteger const ATZSegmentRoundedMajorVersion = 10;
static NSInteger const ATZSegmentRoundedMinorVersion = 9;

static CGFloat const ATZSegmentsVerticalPadding = 1.f;
static CGFloat const ATZSegmentsHorizontalPadding = 6.f;

@implementation ATZSegmentedCell

#pragma mark - Initializers

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self updateAllSegmentsWidth];
}
return self;
}

- (instancetype)initTextCell:(NSString *)aString
{
self = [super initTextCell:aString];
if (self) {
[self updateAllSegmentsWidth];
}
return self;
}

- (instancetype)initImageCell:(NSImage *)image
{
self = [super initImageCell:image];
if (self) {
[self updateAllSegmentsWidth];
}
return self;
}

#pragma mark - Custom drawing

- (void)_drawBackgroundWithFrame:(NSRect)frame inView:(NSView *)controlView {
return;
}

- (void)drawSegment:(NSInteger)segment inFrame:(NSRect)frame withView:(NSView *)controlView {
NSString* text = [self labelForSegment:segment];
NSMutableDictionary* attributes = [[self defaultAttributes] mutableCopy];
NSRect backgroundRect = [self labelBackgroundFrameForSegment:segment inFrame:frame];

// Draw the blue background if the segment is selected
if ([self isSelectedForSegment:segment]) {
attributes[NSForegroundColorAttributeName] = [NSColor whiteColor];

CGFloat cornerRadius = [self shouldUseRoundedPillStyle] ? floorf(backgroundRect.size.height/2) : 4;
NSBezierPath *backgroundPath = [NSBezierPath bezierPathWithRoundedRect:backgroundRect xRadius:cornerRadius yRadius:cornerRadius];
[[NSColor selectedItemColor] setFill];
[backgroundPath fill];
}

// Draw the text centered
[text drawInRect:backgroundRect withAttributes:attributes];

}

#pragma mark - Overring getters and setters

- (void)setLabel:(NSString *)label forSegment:(NSInteger)segment {
[super setLabel:label forSegment:segment];

CGFloat width = [self widthForSegmentLabel:label];
[self setWidth:width forSegment:segment];
}

#pragma mark - Private methods

- (NSDictionary*)defaultAttributes {
NSFont* font = [NSFont fontWithName:@"HelveticaNeue" size:11.f];
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSCenterTextAlignment];

return @{
NSFontAttributeName: font,
NSParagraphStyleAttributeName: style,
NSKernAttributeName: @(0.3)
};
}

- (NSRect)labelBackgroundFrameForSegment:(NSInteger)segment inFrame:(NSRect)frame {
NSString* text = [self labelForSegment:segment];
NSMutableDictionary* attributes = [[self defaultAttributes] mutableCopy];
CGSize labelSize = [text sizeWithAttributes:attributes];
CGFloat verticalInset = (frame.size.height - labelSize.height) / 2 - ATZSegmentsVerticalPadding;

return CGRectInset(frame, 0, verticalInset);
}

- (void)updateAllSegmentsWidth {
for (NSInteger segment = 0; segment < self.segmentCount; segment++) {
NSString *label = [self labelForSegment:segment];
CGFloat width = [self widthForSegmentLabel:label];
[self setWidth:width forSegment:segment];
}
}

- (CGFloat)widthForSegmentLabel:(NSString *)label {
return [self widthForSegmentLabel:label withAttributes:[self defaultAttributes]];
}

- (CGFloat)widthForSegmentLabel:(NSString *)label withAttributes:(NSDictionary*)attributes {
NSSize textSize = [label boundingRectWithSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesDeviceMetrics attributes:attributes].size;
return textSize.width + 2 * ATZSegmentsHorizontalPadding;
}

- (BOOL)shouldUseRoundedPillStyle {
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
return version.majorVersion <= ATZSegmentRoundedMajorVersion
&& version.minorVersion <= ATZSegmentRoundedMinorVersion;
}

@end

0 comments on commit 1a4dc5a

Please sign in to comment.