Skip to content

Commit

Permalink
Merge branch 'features/rearrange-columns'
Browse files Browse the repository at this point in the history
  • Loading branch information
Sören Kuklau committed Apr 6, 2024
2 parents a464bd4 + 1f31234 commit 5066fc2
Show file tree
Hide file tree
Showing 8 changed files with 1,789 additions and 1,367 deletions.
41 changes: 41 additions & 0 deletions Mastonaut/Features/ArrangeColumns/ArrangeColumnsViewItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// ArrangeColumnsViewItem.swift
// Mastonaut
//
// Created by Sören Kuklau on 30.10.23.
//

import Cocoa

class ArrangeColumnsViewItem: NSCollectionViewItem {
@IBOutlet var box: NSBox!

@IBOutlet var label: NSTextField!
@IBOutlet var image: NSImageView!

private var columnViewController: ColumnViewController?

private var arrangeColumnsController: ArrangeColumnsWindowController?

func set(columnViewController: ColumnViewController, arrangeColumnsController: ArrangeColumnsWindowController) {
guard let label,
let columnMode = columnViewController.modelRepresentation as? ColumnMode
else { return }

self.columnViewController = columnViewController
self.arrangeColumnsController = arrangeColumnsController

label.stringValue = columnMode.getTitle()
image.image = columnMode.getImage()
}

@IBAction func closeColumn(_ sender: Any) {
guard let columnViewController,
let closeColumn = arrangeColumnsController?.closeColumn
else { return }

closeColumn(columnViewController)

arrangeColumnsController?.reloadData()
}
}
63 changes: 63 additions & 0 deletions Mastonaut/Features/ArrangeColumns/ArrangeColumnsViewItem.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22689"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ArrangeColumnsViewItem" customModule="Mastonaut" customModuleProvider="target">
<connections>
<outlet property="image" destination="Y0n-ws-Gdk" id="suK-he-3cs"/>
<outlet property="label" destination="22P-Y3-Q72" id="Juq-BL-I6k"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="200" height="80"/>
<subviews>
<box fixedFrame="YES" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="9UB-SI-fmz">
<rect key="frame" x="11" y="8" width="179" height="62"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<view key="contentView" id="tgq-rP-zBX">
<rect key="frame" x="4" y="5" width="171" height="54"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="Y0n-ws-Gdk">
<rect key="frame" x="9" y="17" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="owz-SP-BK2"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="22P-Y3-Q72">
<rect key="frame" x="31" y="12" width="122" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="left" title="Label" id="iWm-Nh-4yg">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vGV-yE-8bo">
<rect key="frame" x="145" y="14" width="25" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="xmark.circle.fill" catalog="system" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" imageScaling="proportionallyDown" inset="2" id="4ca-Sf-PTn">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="closeColumn:" target="-2" id="QvA-Yl-Xds"/>
</connections>
</button>
</subviews>
</view>
</box>
</subviews>
<point key="canvasLocation" x="-134" y="61"/>
</customView>
</objects>
<resources>
<image name="xmark.circle.fill" catalog="system" width="15" height="15"/>
</resources>
</document>
96 changes: 96 additions & 0 deletions Mastonaut/Features/ArrangeColumns/ArrangeColumnsWindow.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22689"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ArrangeColumnsWindowController" customModule="Mastonaut" customModuleProvider="target">
<connections>
<outlet property="collectionView" destination="IYj-mm-J94" id="o9z-OV-Bcl"/>
<outlet property="window" destination="QvC-M9-y7g" id="JJW-gE-XPl"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="160"/>
<rect key="screenRect" x="0.0" y="0.0" width="1512" height="944"/>
<view key="contentView" wantsLayer="YES" misplaced="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="545" height="160"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6Cq-CW-6uC">
<rect key="frame" x="476" y="13" width="66" height="32"/>
<buttonCell key="cell" type="push" title="Done" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7Es-C0-NLl">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<constraints>
<constraint firstAttribute="width" constant="52" id="Lm6-OQ-lpO"/>
</constraints>
<connections>
<action selector="done:" target="-2" id="yzo-Rh-xBg"/>
</connections>
</button>
<scrollView wantsLayer="YES" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" verticalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="ljS-sl-Ta6">
<rect key="frame" x="0.0" y="60" width="555" height="100"/>
<clipView key="contentView" id="dbb-ln-cTG">
<rect key="frame" x="1" y="1" width="553" height="98"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView selectable="YES" id="IYj-mm-J94">
<rect key="frame" x="0.0" y="0.0" width="553" height="98"/>
<autoresizingMask key="autoresizingMask" heightSizable="YES"/>
<collectionViewGridLayout key="collectionViewLayout" maximumNumberOfRows="1" id="EsS-OT-eL1">
<size key="minimumItemSize" width="200" height="80"/>
<size key="maximumItemSize" width="200" height="80"/>
</collectionViewGridLayout>
<color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<connections>
<outlet property="dataSource" destination="-2" id="Kih-GP-SaT"/>
<outlet property="delegate" destination="-2" id="wv6-nL-h2D"/>
</connections>
</collectionView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="4uH-08-XGx">
<rect key="frame" x="1" y="144" width="233" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="CiV-bN-SRm">
<rect key="frame" x="-100" y="-100" width="16" height="157"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fcq-zJ-X8L">
<rect key="frame" x="18" y="23" width="447" height="14"/>
<textFieldCell key="cell" title="Drag the boxes to rearrange their corresponding columns, or click an X to close one." id="SZh-XP-vcq">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="6Cq-CW-6uC" firstAttribute="top" secondItem="ljS-sl-Ta6" secondAttribute="bottom" constant="20" symbolic="YES" id="2Sp-XX-kB7"/>
<constraint firstItem="ljS-sl-Ta6" firstAttribute="top" secondItem="EiT-Mj-1SZ" secondAttribute="top" id="3pO-N8-pRM"/>
<constraint firstAttribute="trailing" secondItem="ljS-sl-Ta6" secondAttribute="trailing" id="BLQ-yM-BLG"/>
<constraint firstItem="ljS-sl-Ta6" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" id="D6y-1Y-bcC"/>
<constraint firstItem="6Cq-CW-6uC" firstAttribute="leading" secondItem="fcq-zJ-X8L" secondAttribute="trailing" constant="20" id="HBF-lm-XSF"/>
<constraint firstAttribute="trailing" secondItem="6Cq-CW-6uC" secondAttribute="trailing" constant="20" symbolic="YES" id="frT-qQ-vuH"/>
<constraint firstItem="fcq-zJ-X8L" firstAttribute="firstBaseline" secondItem="6Cq-CW-6uC" secondAttribute="firstBaseline" id="j3Y-mM-s8b"/>
<constraint firstAttribute="bottom" secondItem="6Cq-CW-6uC" secondAttribute="bottom" constant="20" symbolic="YES" id="wrs-0i-lrt"/>
<constraint firstItem="fcq-zJ-X8L" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" constant="20" symbolic="YES" id="zEp-45-kWN"/>
</constraints>
</view>
<point key="canvasLocation" x="1.5" y="125"/>
</window>
</objects>
</document>
108 changes: 108 additions & 0 deletions Mastonaut/Features/ArrangeColumns/ArrangeColumnsWindowController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// ArrangeColumnsViewController.swift
// Mastonaut
//
// Created by Sören Kuklau on 30.10.23.
//

import Foundation
import UniformTypeIdentifiers

class ArrangeColumnsWindowController: NSWindowController, NSCollectionViewDelegate, NSCollectionViewDataSource {
@IBOutlet private unowned var collectionView: NSCollectionView!

@IBOutlet private(set) unowned var button: NSButton!

override var windowNibName: NSNib.Name? {
return "ArrangeColumnsWindow"
}

private enum ReuseIdentifiers {
static let item = NSUserInterfaceItemIdentifier(rawValue: "item")
}

override func awakeFromNib() {
super.awakeFromNib()

collectionView.register(ArrangeColumnsViewItem.self,
forItemWithIdentifier: ReuseIdentifiers.item)

collectionView.registerForDraggedTypes([.string])
collectionView.setDraggingSourceOperationMask(.every, forLocal: true)
collectionView.setDraggingSourceOperationMask(.every, forLocal: false)
}

var getColumnViewControllers: (() -> [ColumnViewController])?
var moveColumnViewController: ((ColumnViewController, Int) -> Void)?
var closeColumn: ((ColumnViewController) -> Void)?

func numberOfSections(in collectionView: NSCollectionView) -> Int {
1
}

func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
getColumnViewControllers?().count ?? 0
}

func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let identifier = ReuseIdentifiers.item
let item = collectionView.makeItem(withIdentifier: identifier, for: indexPath)

let index = indexPath.item

guard let viewItem = item as? ArrangeColumnsViewItem,
let getColumnViewControllers,
getColumnViewControllers().count >= index
else { return item }

viewItem.set(columnViewController: getColumnViewControllers()[index], arrangeColumnsController: self)

return viewItem
}

func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {
return String(indexPath.item) as NSString
}

func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
print("proposed index path: \(proposedDropIndexPath.pointee.item), drop operation: \(proposedDropOperation.pointee)")

return .move
}

func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {
print("dropping at: \(indexPath.item)")

guard let stringResult = draggingInfo.draggingPasteboard.propertyList(forType: .string) as? String,
let stringUtf8Data = stringResult.data(using: .utf8)
else { return false }

guard let item = try? JSONDecoder().decode(Int.self, from: stringUtf8Data),
let getColumnViewControllers,
let moveColumnViewController
else { return false }

let colController = getColumnViewControllers()[item]

print("Moving \(colController) to \(indexPath.item)")

moveColumnViewController(colController, indexPath.item)

collectionView.reloadData()

return true
}

func reloadData() {
collectionView.reloadData()

// if only one column remains, there's nothing left for the user to do in the sheet
if let viewControllers = getColumnViewControllers?(), viewControllers.count == 1 {
close()
}
}

@IBAction func done(_ sender: Any) {
close()
}
}
Loading

0 comments on commit 5066fc2

Please sign in to comment.