More redesign changes.
This commit is contained in:
10
src/Grapp.entitlements
Normal file
10
src/Grapp.entitlements
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<false/>
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -19,7 +19,11 @@ enum ViewConstants {
|
|||||||
static let spacing2: CGFloat = 2
|
static let spacing2: CGFloat = 2
|
||||||
static let spacing5: CGFloat = 2
|
static let spacing5: CGFloat = 2
|
||||||
static let spacing10: CGFloat = 10
|
static let spacing10: CGFloat = 10
|
||||||
|
static let spacing15: CGFloat = 15
|
||||||
static let spacing20: CGFloat = 20
|
static let spacing20: CGFloat = 20
|
||||||
|
static let spacing25: CGFloat = 25
|
||||||
|
static let spacing30: CGFloat = 30
|
||||||
|
static let spacing35: CGFloat = 35
|
||||||
static let spacing40: CGFloat = 40
|
static let spacing40: CGFloat = 40
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ $(EXEC): ./arm64/$(EXEC)
|
|||||||
@lipo -create -output $(EXEC) $^
|
@lipo -create -output $(EXEC) $^
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
$(EXEC).app: $(EXEC)
|
$(EXEC).app: $(EXEC)
|
||||||
@rm -rf $@
|
@rm -rf $@
|
||||||
@mkdir -p $@/Contents/MacOS/ && \
|
@mkdir -p $@/Contents/MacOS/ && \
|
||||||
@@ -81,7 +82,11 @@ $(EXEC).app: $(EXEC)
|
|||||||
cp Info.plist $@/Contents/ && \
|
cp Info.plist $@/Contents/ && \
|
||||||
cp resources/AppIcon.icns $@/Contents/Resources/ && \
|
cp resources/AppIcon.icns $@/Contents/Resources/ && \
|
||||||
cp $(EXEC) $@/Contents/MacOS/ && \
|
cp $(EXEC) $@/Contents/MacOS/ && \
|
||||||
codesign -s ${DEVELOPER_ID} -f --timestamp -o runtime $(EXEC).app
|
$(if $(DEBUG), \
|
||||||
|
codesign --entitlements Grapp.entitlements \
|
||||||
|
-s ${APPLE_DEVELOPMENT} -f --timestamp -o runtime $(EXEC).app, \
|
||||||
|
codesign -s ${APPLE_DEVELOPER_ID_APPLICATION} -f --timestamp \
|
||||||
|
-o runtime $(EXEC).app)
|
||||||
|
|
||||||
all: $(EXEC).app
|
all: $(EXEC).app
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ class ProgramTableViewCell: NSTableCellView {
|
|||||||
appIconImage.heightAnchor.constraint(equalToConstant: 40),
|
appIconImage.heightAnchor.constraint(equalToConstant: 40),
|
||||||
appIconImage.topAnchor.constraint(equalTo: topAnchor),
|
appIconImage.topAnchor.constraint(equalTo: topAnchor),
|
||||||
appIconImage.bottomAnchor.constraint(equalTo: bottomAnchor),
|
appIconImage.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||||
appIconImage.leadingAnchor.constraint(equalTo: leadingAnchor),
|
appIconImage.leadingAnchor.constraint(equalTo: leadingAnchor,
|
||||||
|
constant: ViewConstants.spacing5),
|
||||||
|
|
||||||
titleField.topAnchor.constraint(
|
titleField.topAnchor.constraint(
|
||||||
equalTo: appIconImage.topAnchor,
|
equalTo: appIconImage.topAnchor,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Carbon
|
|||||||
// NOTE: This is the corner radius of the backgrounView view that acts as
|
// NOTE: This is the corner radius of the backgrounView view that acts as
|
||||||
// a window frame and an NSViewController's view that clips all
|
// a window frame and an NSViewController's view that clips all
|
||||||
// elements inside of it.
|
// elements inside of it.
|
||||||
fileprivate let windowCornerRadius = 20.0
|
fileprivate let windowCornerRadius = 15.0
|
||||||
|
|
||||||
class SearchViewController: NSViewController, NSTextFieldDelegate,
|
class SearchViewController: NSViewController, NSTextFieldDelegate,
|
||||||
NSPopoverDelegate, NSTableViewDataSource, NSTableViewDelegate
|
NSPopoverDelegate, NSTableViewDataSource, NSTableViewDelegate
|
||||||
@@ -48,7 +48,6 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
|
|
||||||
private var contentView: NSView = {
|
private var contentView: NSView = {
|
||||||
let view = NSView()
|
let view = NSView()
|
||||||
|
|
||||||
// Clip all content to window's rounded frame emulated by
|
// Clip all content to window's rounded frame emulated by
|
||||||
// backgroundView.
|
// backgroundView.
|
||||||
view.wantsLayer = true
|
view.wantsLayer = true
|
||||||
@@ -59,31 +58,26 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var appIconImage: NSImageView = {
|
|
||||||
let image = NSImageView()
|
|
||||||
image.image =
|
|
||||||
NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
|
|
||||||
image.imageScaling = .scaleAxesIndependently
|
|
||||||
image.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
return image
|
|
||||||
}()
|
|
||||||
|
|
||||||
private var searchInput: EditableNSTextField = {
|
private var searchInput: EditableNSTextField = {
|
||||||
let textField = EditableNSTextField()
|
let textField = EditableNSTextField()
|
||||||
textField.placeholderString = "Search programs . . ."
|
textField.isBezeled = false
|
||||||
textField.usesSingleLineMode = false
|
textField.maximumNumberOfLines = 1
|
||||||
|
textField.usesSingleLineMode = true
|
||||||
|
textField.lineBreakMode = .byTruncatingHead
|
||||||
|
textField.focusRingType = .none
|
||||||
|
textField.placeholderString = "Program Search"
|
||||||
textField.bezelStyle = .roundedBezel
|
textField.bezelStyle = .roundedBezel
|
||||||
textField.font = NSFont.systemFont(
|
textField.font = NSFont.systemFont(
|
||||||
ofSize: NSFontDescriptor.preferredFontDescriptor(
|
ofSize: NSFontDescriptor.preferredFontDescriptor(
|
||||||
forTextStyle: .title3).pointSize, weight: .medium)
|
forTextStyle: .largeTitle).pointSize, weight: .medium)
|
||||||
textField.translatesAutoresizingMaskIntoConstraints = false
|
textField.translatesAutoresizingMaskIntoConstraints = false
|
||||||
return textField
|
return textField
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var settingsButton: NSButton = {
|
private var settingsButton: NSButton = {
|
||||||
let button = NSButton()
|
let button = NSButton()
|
||||||
button.image = systemImage("gearshape.fill", .title2, .large,
|
button.image = systemImage("gear.circle.fill", .title1, .large,
|
||||||
.init(paletteColors: [.labelColor, .systemRed]))
|
.init(paletteColors: [.labelColor, .systemGray]))
|
||||||
button.isBordered = false
|
button.isBordered = false
|
||||||
button.action = #selector(openSettings)
|
button.action = #selector(openSettings)
|
||||||
button.sizeToFit()
|
button.sizeToFit()
|
||||||
@@ -127,25 +121,16 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
view.addSubview(backgroundView)
|
view.addSubview(backgroundView)
|
||||||
view.addSubview(contentView)
|
view.addSubview(contentView)
|
||||||
|
|
||||||
contentView.addSubview(appIconImage)
|
|
||||||
contentView.addSubview(searchInput)
|
contentView.addSubview(searchInput)
|
||||||
contentView.addSubview(settingsButton)
|
contentView.addSubview(settingsButton)
|
||||||
contentView.addSubview(tableScrollView)
|
contentView.addSubview(tableScrollView)
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewBottomAnchorTable: NSLayoutConstraint?
|
var tableViewHeightAnchor: NSLayoutConstraint?
|
||||||
var viewBottomAnchorImage: NSLayoutConstraint?
|
|
||||||
|
|
||||||
private func setConstraints() {
|
private func setConstraints() {
|
||||||
viewBottomAnchorTable = tableScrollView.bottomAnchor.constraint(
|
tableViewHeightAnchor = tableScrollView.heightAnchor.constraint(equalToConstant: 0)
|
||||||
equalTo: contentView.bottomAnchor,
|
tableViewHeightAnchor?.isActive = true
|
||||||
constant: -ViewConstants.spacing10)
|
|
||||||
viewBottomAnchorImage = appIconImage.bottomAnchor.constraint(
|
|
||||||
equalTo: contentView.bottomAnchor,
|
|
||||||
constant: -ViewConstants.spacing10)
|
|
||||||
|
|
||||||
viewBottomAnchorTable?.isActive = false
|
|
||||||
viewBottomAnchorImage?.isActive = true
|
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
view.topAnchor.constraint(equalTo: contentView.topAnchor,
|
view.topAnchor.constraint(equalTo: contentView.topAnchor,
|
||||||
@@ -175,37 +160,29 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
backgroundView.trailingAnchor.constraint(
|
backgroundView.trailingAnchor.constraint(
|
||||||
equalTo: contentView.trailingAnchor),
|
equalTo: contentView.trailingAnchor),
|
||||||
|
|
||||||
appIconImage.widthAnchor.constraint(equalToConstant: 60),
|
searchInput.widthAnchor.constraint(equalToConstant: 350),
|
||||||
appIconImage.heightAnchor.constraint(
|
searchInput.topAnchor.constraint(
|
||||||
equalTo: appIconImage.widthAnchor, multiplier: 1),
|
|
||||||
|
|
||||||
appIconImage.topAnchor.constraint(
|
|
||||||
equalTo: contentView.topAnchor,
|
equalTo: contentView.topAnchor,
|
||||||
constant: ViewConstants.spacing10),
|
constant: ViewConstants.spacing10),
|
||||||
appIconImage.leadingAnchor.constraint(
|
|
||||||
equalTo: contentView.leadingAnchor,
|
|
||||||
constant: ViewConstants.spacing10),
|
|
||||||
|
|
||||||
searchInput.widthAnchor.constraint(equalToConstant: 300),
|
|
||||||
searchInput.centerYAnchor.constraint(
|
|
||||||
equalTo: appIconImage.centerYAnchor),
|
|
||||||
searchInput.leadingAnchor.constraint(
|
searchInput.leadingAnchor.constraint(
|
||||||
equalTo: appIconImage.trailingAnchor,
|
equalTo: contentView.leadingAnchor,
|
||||||
constant: ViewConstants.spacing10),
|
constant: ViewConstants.spacing15),
|
||||||
|
|
||||||
settingsButton.firstBaselineAnchor.constraint(
|
settingsButton.centerYAnchor.constraint(
|
||||||
equalTo: searchInput.firstBaselineAnchor),
|
equalTo: searchInput.centerYAnchor),
|
||||||
settingsButton.leadingAnchor.constraint(
|
settingsButton.leadingAnchor.constraint(
|
||||||
equalTo: searchInput.trailingAnchor,
|
equalTo: searchInput.trailingAnchor,
|
||||||
constant: ViewConstants.spacing10),
|
constant: ViewConstants.spacing5),
|
||||||
settingsButton.trailingAnchor.constraint(
|
settingsButton.trailingAnchor.constraint(
|
||||||
equalTo: contentView.trailingAnchor,
|
equalTo: contentView.trailingAnchor,
|
||||||
constant: -ViewConstants.spacing10),
|
constant: -ViewConstants.spacing10),
|
||||||
|
|
||||||
tableScrollView.heightAnchor.constraint(equalToConstant: 210),
|
// tableScrollView.heightAnchor.constraint(equalToConstant: 210),
|
||||||
tableScrollView.topAnchor.constraint(
|
tableScrollView.topAnchor.constraint(
|
||||||
equalTo: appIconImage.bottomAnchor,
|
equalTo: searchInput.bottomAnchor,
|
||||||
constant: ViewConstants.spacing10),
|
constant: ViewConstants.spacing10),
|
||||||
|
tableScrollView.bottomAnchor.constraint(
|
||||||
|
equalTo: contentView.bottomAnchor),
|
||||||
tableScrollView.leadingAnchor.constraint(
|
tableScrollView.leadingAnchor.constraint(
|
||||||
equalTo: contentView.leadingAnchor),
|
equalTo: contentView.leadingAnchor),
|
||||||
tableScrollView.trailingAnchor.constraint(
|
tableScrollView.trailingAnchor.constraint(
|
||||||
@@ -232,7 +209,6 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
key == kVK_UpArrow
|
key == kVK_UpArrow
|
||||||
{
|
{
|
||||||
controller.programsTableViewSelection -= 1
|
controller.programsTableViewSelection -= 1
|
||||||
|
|
||||||
} else if modsContains(keys: OSCtrl, in: modifiers) &&
|
} else if modsContains(keys: OSCtrl, in: modifiers) &&
|
||||||
key == kVK_ANSI_N ||
|
key == kVK_ANSI_N ||
|
||||||
modsContainsNone(in: modifiers) &&
|
modsContainsNone(in: modifiers) &&
|
||||||
@@ -277,6 +253,9 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
|
|
||||||
keyboardEvents?.start()
|
keyboardEvents?.start()
|
||||||
|
|
||||||
|
// TODO: This doesn't play well when the window is expanded with
|
||||||
|
// search results, causing it to reappear in a slightly
|
||||||
|
// above usual position.
|
||||||
view.window?.center()
|
view.window?.center()
|
||||||
|
|
||||||
view.window?.makeFirstResponder(searchInput)
|
view.window?.makeFirstResponder(searchInput)
|
||||||
@@ -297,11 +276,9 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
|
|
||||||
private func reloadProgramsTableViewData() {
|
private func reloadProgramsTableViewData() {
|
||||||
if programsList.count > 0 {
|
if programsList.count > 0 {
|
||||||
viewBottomAnchorTable?.isActive = true
|
tableViewHeightAnchor?.constant = 210
|
||||||
viewBottomAnchorImage?.isActive = false
|
|
||||||
} else {
|
} else {
|
||||||
viewBottomAnchorTable?.isActive = false
|
tableViewHeightAnchor?.constant = 0
|
||||||
viewBottomAnchorImage?.isActive = true
|
|
||||||
}
|
}
|
||||||
programsTableView.reloadData()
|
programsTableView.reloadData()
|
||||||
}
|
}
|
||||||
@@ -376,13 +353,6 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
IndexSet(integer: programsTableViewSelection),
|
IndexSet(integer: programsTableViewSelection),
|
||||||
byExtendingSelection: false)
|
byExtendingSelection: false)
|
||||||
programsTableView.scrollRowToVisible(programsTableViewSelection)
|
programsTableView.scrollRowToVisible(programsTableViewSelection)
|
||||||
|
|
||||||
if programsList.count > 0 {
|
|
||||||
appIconImage.image = programsList[0].img
|
|
||||||
} else {
|
|
||||||
appIconImage.image =
|
|
||||||
NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func control(_ control: NSControl, textView: NSTextView,
|
func control(_ control: NSControl, textView: NSTextView,
|
||||||
@@ -454,4 +424,10 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
|
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tableViewSelectionDidChange(_ notification: Notification) {
|
||||||
|
if programsTableView.selectedRow != programsTableViewSelection {
|
||||||
|
programsTableViewSelection = programsTableView.selectedRow
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user