From 20670b48767e3c446f23ffbfe35d1adffabb9a30 Mon Sep 17 00:00:00 2001 From: Christian Beer Date: Mon, 29 Aug 2022 16:37:13 +0200 Subject: [PATCH 1/5] Swift Package Support, switch to ARC --- Package.swift | 35 ++++++++++++++++++ ReadMe.txt => README.md | 0 .../MGScopeBar/MGRecessedPopUpButtonCell.h | 0 .../MGScopeBar/MGRecessedPopUpButtonCell.m | 8 ---- .../MGScopeBar/MGScopeBar.h | 2 +- .../MGScopeBar/MGScopeBar.m | 31 ++++------------ .../Resources/Base.lproj}/MainMenu.xib | 0 .../Resources/en.lproj}/InfoPlist.strings | Bin Sources/MGScopeBar/include/MGScopeBar.h | 14 +++++++ .../include/MGScopeBarDelegateProtocol.h | 0 Tests/MGScopeBarTests/MGScopeBarTests.swift | 10 +++++ 11 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 Package.swift rename ReadMe.txt => README.md (100%) rename MGRecessedPopUpButtonCell.h => Sources/MGScopeBar/MGRecessedPopUpButtonCell.h (100%) rename MGRecessedPopUpButtonCell.m => Sources/MGScopeBar/MGRecessedPopUpButtonCell.m (94%) rename MGScopeBar.h => Sources/MGScopeBar/MGScopeBar.h (97%) rename MGScopeBar.m => Sources/MGScopeBar/MGScopeBar.m (97%) rename {Base.lproj => Sources/MGScopeBar/Resources/Base.lproj}/MainMenu.xib (100%) rename {en.lproj => Sources/MGScopeBar/Resources/en.lproj}/InfoPlist.strings (100%) create mode 100644 Sources/MGScopeBar/include/MGScopeBar.h rename MGScopeBarDelegateProtocol.h => Sources/MGScopeBar/include/MGScopeBarDelegateProtocol.h (100%) create mode 100644 Tests/MGScopeBarTests/MGScopeBarTests.swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..235a5bf --- /dev/null +++ b/Package.swift @@ -0,0 +1,35 @@ +// swift-tools-version: 5.6 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MGScopeBar", + defaultLocalization: "en", + platforms: [ + .macOS(.v11) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "MGScopeBar", + targets: ["MGScopeBar"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "MGScopeBar", + dependencies: [], + resources: [ + .process("Resources") + ]), + .testTarget( + name: "MGScopeBarTests", + dependencies: ["MGScopeBar"]), + ] +) diff --git a/ReadMe.txt b/README.md similarity index 100% rename from ReadMe.txt rename to README.md diff --git a/MGRecessedPopUpButtonCell.h b/Sources/MGScopeBar/MGRecessedPopUpButtonCell.h similarity index 100% rename from MGRecessedPopUpButtonCell.h rename to Sources/MGScopeBar/MGRecessedPopUpButtonCell.h diff --git a/MGRecessedPopUpButtonCell.m b/Sources/MGScopeBar/MGRecessedPopUpButtonCell.m similarity index 94% rename from MGRecessedPopUpButtonCell.m rename to Sources/MGScopeBar/MGRecessedPopUpButtonCell.m index d41bb92..99b3373 100644 --- a/MGRecessedPopUpButtonCell.m +++ b/Sources/MGScopeBar/MGRecessedPopUpButtonCell.m @@ -26,14 +26,6 @@ - (id)initTextCell:(NSString *)title pullsDown:(BOOL)pullsDown return self; } - -- (void)dealloc -{ - [recessedButton release]; - [super dealloc]; -} - - - (void)drawTitleWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { // Inset title rect since its position is broken when NSPopUpButton diff --git a/MGScopeBar.h b/Sources/MGScopeBar/MGScopeBar.h similarity index 97% rename from MGScopeBar.h rename to Sources/MGScopeBar/MGScopeBar.h index 9505748..60c3cc3 100644 --- a/MGScopeBar.h +++ b/Sources/MGScopeBar/MGScopeBar.h @@ -10,7 +10,7 @@ #import "MGScopeBarDelegateProtocol.h" @interface MGScopeBar : NSView { - IBOutlet id delegate; // weak ref. + IBOutlet __unsafe_unretained id delegate; // weak ref. NSMutableArray *_separatorPositions; // x-coords of separators, indexed by their group-number. NSMutableArray *_groups; // groups of items. NSView *_accessoryView; // weak ref since it's a subview. diff --git a/MGScopeBar.m b/Sources/MGScopeBar/MGScopeBar.m similarity index 97% rename from MGScopeBar.m rename to Sources/MGScopeBar/MGScopeBar.m index 60272de..0c39162 100644 --- a/MGScopeBar.m +++ b/Sources/MGScopeBar/MGScopeBar.m @@ -99,12 +99,6 @@ - (void)dealloc [_accessoryView removeFromSuperview]; _accessoryView = nil; // weak ref } - [_separatorPositions release]; - [_groups release]; - [_identifiers release]; - [_selectedItems release]; - - [super dealloc]; } @@ -124,15 +118,10 @@ - (void)reloadData NSArray *subviews = [[self subviews] copy]; // so we don't mutate the collection we're iterating over. [subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; - [subviews release]; // because copies are retained. - [_separatorPositions release]; _separatorPositions = nil; - [_groups release]; _groups = nil; - [_identifiers release]; _identifiers = nil; - [_selectedItems release]; _selectedItems = nil; _firstCollapsedGroup = NSNotFound; _lastWidth = NSNotFound; @@ -187,7 +176,6 @@ - (void)reloadData ctrlRect.size = [labelField frame].size; [labelField setFrame:ctrlRect]; [self addSubview:labelField]; - [labelField release]; xCoord += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING; @@ -712,7 +700,7 @@ - (NSButton *)buttonForItem:(NSString *)identifier inGroup:(NSInteger)groupNumbe [self setControl:button forIdentifier:identifier inGroup:groupNumber]; - return [button autorelease]; + return button; } @@ -727,7 +715,7 @@ - (NSMenuItem *)menuItemForItem:(NSString *)identifier inGroup:(NSInteger)groupN [self setControl:menuItem forIdentifier:identifier inGroup:groupNumber]; - return [menuItem autorelease]; + return menuItem; } @@ -742,12 +730,10 @@ - (NSPopUpButton *)popupButtonForGroup:(NSDictionary *)group if (multiSelect) { MGRecessedPopUpButtonCell *cell = [[MGRecessedPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; [popup setCell:cell]; - [cell release]; [[popup cell] setUsesItemFromMenu:NO]; NSMenuItem *titleItem = [[NSMenuItem alloc] init]; [[popup cell] setMenuItem:titleItem]; - [titleItem release]; } // Configure appearance and behaviour. @@ -782,7 +768,7 @@ - (NSPopUpButton *)popupButtonForGroup:(NSDictionary *)group popFrame.origin.y = ceil(([self frame].size.height - popFrame.size.height) / 2.0); [popup setFrame:popFrame]; - return [popup autorelease]; + return popup; } @@ -794,7 +780,7 @@ - (void)setControl:(NSObject *)control forIdentifier:(NSString *)identifier inGr NSMutableArray *identArray = [_identifiers objectForKey:identifier]; if (!identArray) { - identArray = [[[NSMutableArray alloc] initWithCapacity:groupNumber + 1] autorelease]; + identArray = [[NSMutableArray alloc] initWithCapacity:groupNumber + 1]; [_identifiers setObject:identArray forKey:identifier]; } @@ -872,8 +858,8 @@ - (void)updateMenuTitleForGroupAtIndex:(NSInteger)groupNumber - (void)drawRect:(NSRect)rect { // Draw gradient background. - NSGradient *gradient = [[[NSGradient alloc] initWithStartingColor:SCOPE_BAR_START_COLOR_GRAY - endingColor:SCOPE_BAR_END_COLOR_GRAY] autorelease]; + NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:SCOPE_BAR_START_COLOR_GRAY + endingColor:SCOPE_BAR_END_COLOR_GRAY]; [gradient drawInRect:[self bounds] angle:90.0]; // Draw border. @@ -932,7 +918,6 @@ - (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInt BOOL informDelegate = YES; if (group) { - [group retain]; NSDisableScreenUpdates(); // We found the group which this item belongs to. Obtain selection-mode and identifiers. @@ -956,7 +941,6 @@ - (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInt informDelegate = NO; } } - [groupSelections release]; } // Change selected state of this item. @@ -967,7 +951,6 @@ - (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInt [self updateMenuTitleForGroupAtIndex:groupNumber]; } - [group release]; NSEnableScreenUpdates(); } } @@ -1012,7 +995,7 @@ - (void)updateSelectedState:(BOOL)selected forItem:(NSString *)identifier inGrou - (NSArray *)selectedItems { - return [[_selectedItems copy] autorelease]; + return [_selectedItems copy]; } - (BOOL) isItemSelectedWithIdentifier:(NSString*)identifier inGroup:(NSInteger)groupNumber; { diff --git a/Base.lproj/MainMenu.xib b/Sources/MGScopeBar/Resources/Base.lproj/MainMenu.xib similarity index 100% rename from Base.lproj/MainMenu.xib rename to Sources/MGScopeBar/Resources/Base.lproj/MainMenu.xib diff --git a/en.lproj/InfoPlist.strings b/Sources/MGScopeBar/Resources/en.lproj/InfoPlist.strings similarity index 100% rename from en.lproj/InfoPlist.strings rename to Sources/MGScopeBar/Resources/en.lproj/InfoPlist.strings diff --git a/Sources/MGScopeBar/include/MGScopeBar.h b/Sources/MGScopeBar/include/MGScopeBar.h new file mode 100644 index 0000000..c958767 --- /dev/null +++ b/Sources/MGScopeBar/include/MGScopeBar.h @@ -0,0 +1,14 @@ +// +// Header.h +// +// +// Created by Christian Beer on 29.08.22. +// + +#ifndef Header_h +#define Header_h + +#include "../MGScopeBar.h" +#include "../MGRecessedPopUpButtonCell.h" + +#endif /* Header_h */ diff --git a/MGScopeBarDelegateProtocol.h b/Sources/MGScopeBar/include/MGScopeBarDelegateProtocol.h similarity index 100% rename from MGScopeBarDelegateProtocol.h rename to Sources/MGScopeBar/include/MGScopeBarDelegateProtocol.h diff --git a/Tests/MGScopeBarTests/MGScopeBarTests.swift b/Tests/MGScopeBarTests/MGScopeBarTests.swift new file mode 100644 index 0000000..11347b4 --- /dev/null +++ b/Tests/MGScopeBarTests/MGScopeBarTests.swift @@ -0,0 +1,10 @@ +import XCTest +@testable import MGScopeBar + +final class MGScopeBarTests: XCTestCase { + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + } +} From 30a0a4eb9a663f5781df6c4ea070d86e36f740c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 21 Sep 2026 05:19:13 +0000 Subject: [PATCH 2/5] Exclude demo MainMenu.xib from SwiftPM resources Co-authored-by: hannesa2 <3314607+hannesa2@users.noreply.github.com> --- Package.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Package.swift b/Package.swift index 235a5bf..db2bd27 100644 --- a/Package.swift +++ b/Package.swift @@ -25,6 +25,9 @@ let package = Package( .target( name: "MGScopeBar", dependencies: [], + exclude: [ + "Resources/Base.lproj/MainMenu.xib" + ], resources: [ .process("Resources") ]), From 29f60302880242b2687a9728dadaac3ab60ab70a Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Mon, 21 Sep 2026 07:51:28 +0200 Subject: [PATCH 3/5] Update header guard in MGScopeBar.h Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- Sources/MGScopeBar/include/MGScopeBar.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/MGScopeBar/include/MGScopeBar.h b/Sources/MGScopeBar/include/MGScopeBar.h index c958767..935d9c3 100644 --- a/Sources/MGScopeBar/include/MGScopeBar.h +++ b/Sources/MGScopeBar/include/MGScopeBar.h @@ -5,10 +5,10 @@ // Created by Christian Beer on 29.08.22. // -#ifndef Header_h -#define Header_h +#ifndef MGSCOPEBAR_PUBLIC_H +#define MGSCOPEBAR_PUBLIC_H #include "../MGScopeBar.h" #include "../MGRecessedPopUpButtonCell.h" -#endif /* Header_h */ +#endif /* MGSCOPEBAR_PUBLIC_H */ From e81543f5a02bec8d8ea508845b3ffdc72c18cc2c Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Mon, 21 Sep 2026 07:54:42 +0200 Subject: [PATCH 4/5] Align README platform support with Swift package --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index df86e43..473e9d2 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,8 @@ MGScopeBar is a control which provides a "scope bar" or "filter bar", much like What platforms does it support? ------------------------------- -MGScopeBar supports Mac OS X 10.5 (Leopard) or later. - - +MGScopeBar supports Mac OS X 10.5 (Leopard) or later when integrated directly from source files. +The Swift Package requires macOS 11 or later. What are the licensing requirements? ------------------------------------ From bc9b43454c6b09762160e6134506b19a2ce9a8fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 21 Sep 2026 06:10:38 +0000 Subject: [PATCH 5/5] Fix Xcode app resource paths for CI archive Co-authored-by: hannesa2 <3314607+hannesa2@users.noreply.github.com> --- .github/workflows/BuildPR.yml | 3 +-- .gitignore | 1 + MGScopeBar.xcodeproj/project.pbxproj | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/BuildPR.yml b/.github/workflows/BuildPR.yml index d069a98..09a75bf 100644 --- a/.github/workflows/BuildPR.yml +++ b/.github/workflows/BuildPR.yml @@ -22,5 +22,4 @@ jobs: with: xcode-version: ${{ matrix.xcode }} - name: Build project - run: xcodebuild -workspace MGScopeBar.xcodeproj/project.xcworkspace -scheme MGScopeBar archive ARCHS="arm64 x86_64" - + run: xcodebuild -project MGScopeBar.xcodeproj -scheme MGScopeBar.framework build ARCHS="arm64 x86_64" CODE_SIGNING_ALLOWED=NO diff --git a/.gitignore b/.gitignore index 9bce6af..d9db622 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ xcuserdata +.build/ diff --git a/MGScopeBar.xcodeproj/project.pbxproj b/MGScopeBar.xcodeproj/project.pbxproj index 7bc8c36..98126a3 100644 --- a/MGScopeBar.xcodeproj/project.pbxproj +++ b/MGScopeBar.xcodeproj/project.pbxproj @@ -30,8 +30,8 @@ 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 32CA4F630368D1EE00C91783 /* MGScopeBar_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGScopeBar_Prefix.pch; sourceTree = ""; }; - 6F9CFC08233273B60061EBAD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 6F9CFC0A233273BB0061EBAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 6F9CFC08233273B60061EBAD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Sources/MGScopeBar/Resources/en.lproj/InfoPlist.strings; sourceTree = ""; }; + 6F9CFC0A233273BB0061EBAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Sources/MGScopeBar/Resources/Base.lproj/MainMenu.xib; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8D1107320486CEB800E47090 /* MGScopeBar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MGScopeBar.app; sourceTree = BUILT_PRODUCTS_DIR; }; AAE785781419184700A6955E /* MGScopeBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MGScopeBar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -39,13 +39,13 @@ AAE7857D1419184700A6955E /* MGScopeBarFramework-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MGScopeBarFramework-Info.plist"; sourceTree = ""; }; AAE7857F1419184700A6955E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; AAE785811419184700A6955E /* MGScopeBarFramework-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MGScopeBarFramework-Prefix.pch"; sourceTree = ""; }; - C95B43CE0EB73CE3008EE468 /* MGRecessedPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGRecessedPopUpButtonCell.h; sourceTree = ""; }; - C95B43CF0EB73CE3008EE468 /* MGRecessedPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGRecessedPopUpButtonCell.m; sourceTree = ""; }; + C95B43CE0EB73CE3008EE468 /* MGRecessedPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sources/MGScopeBar/MGRecessedPopUpButtonCell.h; sourceTree = ""; }; + C95B43CF0EB73CE3008EE468 /* MGRecessedPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sources/MGScopeBar/MGRecessedPopUpButtonCell.m; sourceTree = ""; }; C9FB61130E8FF8360019B961 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = ""; }; C9FB61140E8FF8360019B961 /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = ""; }; - C9FB61170E8FF8810019B961 /* MGScopeBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGScopeBar.h; sourceTree = ""; }; - C9FB61180E8FF8810019B961 /* MGScopeBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGScopeBar.m; sourceTree = ""; }; - C9FB61190E8FF8810019B961 /* MGScopeBarDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGScopeBarDelegateProtocol.h; sourceTree = ""; }; + C9FB61170E8FF8810019B961 /* MGScopeBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sources/MGScopeBar/MGScopeBar.h; sourceTree = ""; }; + C9FB61180E8FF8810019B961 /* MGScopeBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sources/MGScopeBar/MGScopeBar.m; sourceTree = ""; }; + C9FB61190E8FF8810019B961 /* MGScopeBarDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sources/MGScopeBar/include/MGScopeBarDelegateProtocol.h; sourceTree = ""; }; C9FB61A80E8FFE7B0019B961 /* TODO */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO; sourceTree = ""; }; C9FB61AA0E8FFE950019B961 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadMe.txt; sourceTree = ""; }; C9FB61AC0E8FFEA90019B961 /* Source Code License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Source Code License.rtf"; sourceTree = ""; };