Revision: 16083
http://sourceforge.net/p/skim-app/code/16083
Author: hofman
Date: 2026-03-22 18:15:30 +0000 (Sun, 22 Mar 2026)
Log Message:
-----------
use NSSplitViewController for splitviews in main window
Modified Paths:
--------------
trunk/LeftSideView.xib
trunk/MainWindow.xib
trunk/RightSideView.xib
trunk/SKLeftSideViewController.m
trunk/SKMainWindowController.h
trunk/SKMainWindowController.m
trunk/SKMainWindowController_Actions.m
trunk/SKMainWindowController_FullScreen.m
trunk/SKMainWindowController_UI.m
trunk/SKRightSideViewController.m
trunk/SKSideViewController.h
trunk/SKSideViewController.m
Modified: trunk/LeftSideView.xib
===================================================================
--- trunk/LeftSideView.xib 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/LeftSideView.xib 2026-03-22 18:15:30 UTC (rev 16083)
@@ -16,96 +16,109 @@
<outlet property="groupedFindArrayController" destination="97"
id="181"/>
<outlet property="groupedFindTableView" destination="128"
id="174"/>
<outlet property="searchField" destination="138" id="171"/>
+ <outlet property="sideView" destination="85" id="gcH-NK-Qen"/>
<outlet property="thumbnailArrayController"
destination="yPq-rX-KPQ" id="zwc-qS-kJH"/>
<outlet property="thumbnailTableView" destination="101"
id="180"/>
<outlet property="tocOutlineView" destination="119" id="189"/>
<outlet property="topBar" destination="134" id="194"/>
<outlet property="topConstraint" destination="whT-Z9-oOB"
id="93r-ij-GdN"/>
- <outlet property="view" destination="85" id="172"/>
+ <outlet property="view" destination="il2-Kq-ue6"
id="f4H-49-cME"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder"
customClass="FirstResponder"/>
- <customObject id="-3" userLabel="Application" customClass="NSObject"/>
- <customView translatesAutoresizingMaskIntoConstraints="NO" id="85"
userLabel="LeftSideView">
+ <customView id="il2-Kq-ue6">
<rect key="frame" x="0.0" y="0.0" width="200" height="400"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES"
flexibleMinY="YES"/>
<subviews>
- <customView translatesAutoresizingMaskIntoConstraints="NO"
id="133">
- <rect key="frame" x="0.0" y="0.0" width="200"
height="364"/>
+ <customView translatesAutoresizingMaskIntoConstraints="NO"
id="85" userLabel="LeftSideView" customClass="SKGroupView">
+ <rect key="frame" x="0.0" y="0.0" width="200"
height="400"/>
<subviews>
- <customView fixedFrame="YES"
translatesAutoresizingMaskIntoConstraints="NO" id="142">
+ <customView
translatesAutoresizingMaskIntoConstraints="NO" id="133">
<rect key="frame" x="0.0" y="0.0" width="200"
height="364"/>
- <autoresizingMask key="autoresizingMask"
widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <customView fixedFrame="YES"
translatesAutoresizingMaskIntoConstraints="NO" id="142">
+ <rect key="frame" x="0.0" y="0.0"
width="200" height="364"/>
+ <autoresizingMask key="autoresizingMask"
widthSizable="YES" heightSizable="YES"/>
+ </customView>
+ </subviews>
</customView>
- </subviews>
- </customView>
- <customView translatesAutoresizingMaskIntoConstraints="NO"
id="134" customClass="SKTopBarView">
- <rect key="frame" x="0.0" y="364" width="200" height="36"/>
- <subviews>
- <segmentedControl hidden="YES"
verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO"
id="93">
- <rect key="frame" x="9" y="6" width="61"
height="23"/>
- <segmentedCell key="cell" borderStyle="border"
alignment="left" style="texturedSquare" trackingMode="selectOne" id="106">
- <font key="font" metaFont="system"/>
- <segments>
- <segment image="FindViewAdorn"
imageScaling="none" width="25"/>
- <segment image="GroupedFindViewAdorn"
imageScaling="none" width="25" tag="1"/>
- </segments>
- <connections>
- <binding destination="90"
name="selectedTag" keyPath="selection.findPaneState" id="187"/>
- </connections>
- </segmentedCell>
- <connections>
- <binding destination="90" name="selectedTag"
keyPath="selection.findPaneState" id="144"/>
- </connections>
- </segmentedControl>
- <segmentedControl verticalHuggingPriority="750"
translatesAutoresizingMaskIntoConstraints="NO" id="140">
- <rect key="frame" x="9" y="6" width="61"
height="23"/>
- <segmentedCell key="cell" borderStyle="border"
alignment="left" style="texturedSquare" trackingMode="selectOne" id="141">
- <font key="font" metaFont="system"/>
- <segments>
- <segment image="ThumbnailViewAdorn"
imageScaling="none" width="25"/>
- <segment image="OutlineViewAdorn"
imageScaling="none" width="25" tag="1"/>
- </segments>
- </segmentedCell>
- <connections>
- <binding destination="90" name="selectedTag"
keyPath="selection.leftSidePaneState" id="155"/>
- </connections>
- </segmentedControl>
- <searchField verticalHuggingPriority="750"
horizontalCompressionResistancePriority="250" textCompletion="NO"
translatesAutoresizingMaskIntoConstraints="NO" id="138">
- <rect key="frame" x="77" y="7" width="115"
height="22"/>
+ <customView
translatesAutoresizingMaskIntoConstraints="NO" id="134"
customClass="SKTopBarView">
+ <rect key="frame" x="0.0" y="364" width="200"
height="36"/>
+ <subviews>
+ <segmentedControl hidden="YES"
verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO"
id="93">
+ <rect key="frame" x="9" y="6" width="61"
height="23"/>
+ <segmentedCell key="cell"
borderStyle="border" alignment="left" style="texturedSquare"
trackingMode="selectOne" id="106">
+ <font key="font" metaFont="system"/>
+ <segments>
+ <segment image="FindViewAdorn"
imageScaling="none" width="25"/>
+ <segment
image="GroupedFindViewAdorn" imageScaling="none" width="25" tag="1"/>
+ </segments>
+ <connections>
+ <binding destination="90"
name="selectedTag" keyPath="selection.findPaneState" id="187"/>
+ </connections>
+ </segmentedCell>
+ <connections>
+ <binding destination="90"
name="selectedTag" keyPath="selection.findPaneState" id="144"/>
+ </connections>
+ </segmentedControl>
+ <segmentedControl
verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO"
id="140">
+ <rect key="frame" x="9" y="6" width="61"
height="23"/>
+ <segmentedCell key="cell"
borderStyle="border" alignment="left" style="texturedSquare"
trackingMode="selectOne" id="141">
+ <font key="font" metaFont="system"/>
+ <segments>
+ <segment
image="ThumbnailViewAdorn" imageScaling="none" width="25"/>
+ <segment image="OutlineViewAdorn"
imageScaling="none" width="25" tag="1"/>
+ </segments>
+ </segmentedCell>
+ <connections>
+ <binding destination="90"
name="selectedTag" keyPath="selection.leftSidePaneState" id="155"/>
+ </connections>
+ </segmentedControl>
+ <searchField verticalHuggingPriority="750"
horizontalCompressionResistancePriority="250" textCompletion="NO"
translatesAutoresizingMaskIntoConstraints="NO" id="138">
+ <rect key="frame" x="77" y="7" width="115"
height="22"/>
+ <constraints>
+ <constraint firstAttribute="width"
relation="greaterThanOrEqual" constant="20" id="EJG-YR-pIX"/>
+ </constraints>
+ <searchFieldCell key="cell"
scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES"
borderStyle="bezel" placeholderString="" bezelStyle="round" id="139"
customClass="SKSearchFieldCell">
+ <font key="font" metaFont="system"/>
+ <color key="textColor"
name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor"
name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </searchFieldCell>
+ </searchField>
+ </subviews>
<constraints>
- <constraint firstAttribute="width"
relation="greaterThanOrEqual" constant="20" id="EJG-YR-pIX"/>
+ <constraint firstItem="138"
firstAttribute="centerY" secondItem="134" secondAttribute="centerY"
id="6aJ-h2-CfD"/>
+ <constraint firstAttribute="trailing"
secondItem="138" secondAttribute="trailing" priority="251" constant="8"
id="IkV-bB-83C"/>
+ <constraint firstItem="140"
firstAttribute="leading" secondItem="134" secondAttribute="leading"
constant="10" id="UXL-kL-U6I"/>
+ <constraint firstItem="138"
firstAttribute="leading" secondItem="93" secondAttribute="trailing"
constant="8" symbolic="YES" id="Vwf-8s-KXn"/>
+ <constraint firstItem="138"
firstAttribute="leading" secondItem="140" secondAttribute="trailing"
constant="8" symbolic="YES" id="fm2-6f-79d"/>
+ <constraint firstItem="140"
firstAttribute="centerY" secondItem="134" secondAttribute="centerY"
id="h7J-Na-3Nd"/>
+ <constraint firstItem="93"
firstAttribute="leading" secondItem="134" secondAttribute="leading"
constant="10" id="iGp-4q-uif"/>
+ <constraint firstAttribute="height"
constant="36" id="w8i-xX-Pnp"/>
+ <constraint firstItem="93"
firstAttribute="centerY" secondItem="134" secondAttribute="centerY"
id="yZS-bf-pOA"/>
</constraints>
- <searchFieldCell key="cell" scrollable="YES"
lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel"
placeholderString="" bezelStyle="round" id="139"
customClass="SKSearchFieldCell">
- <font key="font" metaFont="system"/>
- <color key="textColor" name="controlTextColor"
catalog="System" colorSpace="catalog"/>
- <color key="backgroundColor"
name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
- </searchFieldCell>
- </searchField>
+ </customView>
</subviews>
<constraints>
- <constraint firstItem="138" firstAttribute="centerY"
secondItem="134" secondAttribute="centerY" id="6aJ-h2-CfD"/>
- <constraint firstAttribute="trailing" secondItem="138"
secondAttribute="trailing" priority="251" constant="8" id="IkV-bB-83C"/>
- <constraint firstItem="140" firstAttribute="leading"
secondItem="134" secondAttribute="leading" constant="10" id="UXL-kL-U6I"/>
- <constraint firstItem="138" firstAttribute="leading"
secondItem="93" secondAttribute="trailing" constant="8" symbolic="YES"
id="Vwf-8s-KXn"/>
- <constraint firstItem="138" firstAttribute="leading"
secondItem="140" secondAttribute="trailing" constant="8" symbolic="YES"
id="fm2-6f-79d"/>
- <constraint firstItem="140" firstAttribute="centerY"
secondItem="134" secondAttribute="centerY" id="h7J-Na-3Nd"/>
- <constraint firstItem="93" firstAttribute="leading"
secondItem="134" secondAttribute="leading" constant="10" id="iGp-4q-uif"/>
- <constraint firstAttribute="height" constant="36"
id="w8i-xX-Pnp"/>
- <constraint firstItem="93" firstAttribute="centerY"
secondItem="134" secondAttribute="centerY" id="yZS-bf-pOA"/>
+ <constraint firstAttribute="bottom" secondItem="133"
secondAttribute="bottom" id="T6W-X1-XBt"/>
+ <constraint firstAttribute="trailing" secondItem="133"
secondAttribute="trailing" id="TOn-mO-lFR"/>
+ <constraint firstItem="133" firstAttribute="leading"
secondItem="85" secondAttribute="leading" id="b3U-uC-wKa"/>
+ <constraint firstItem="134" firstAttribute="leading"
secondItem="85" secondAttribute="leading" id="bJW-UQ-x3H"/>
+ <constraint firstItem="133" firstAttribute="top"
secondItem="134" secondAttribute="bottom" id="bWR-sc-XNl"/>
+ <constraint firstAttribute="trailing" secondItem="134"
secondAttribute="trailing" id="sVN-Yz-bpb"/>
+ <constraint firstItem="134" firstAttribute="top"
secondItem="85" secondAttribute="top" id="whT-Z9-oOB"/>
</constraints>
</customView>
</subviews>
<constraints>
- <constraint firstAttribute="bottom" secondItem="133"
secondAttribute="bottom" id="T6W-X1-XBt"/>
- <constraint firstAttribute="trailing" secondItem="133"
secondAttribute="trailing" id="TOn-mO-lFR"/>
- <constraint firstItem="133" firstAttribute="leading"
secondItem="85" secondAttribute="leading" id="b3U-uC-wKa"/>
- <constraint firstItem="134" firstAttribute="leading"
secondItem="85" secondAttribute="leading" id="bJW-UQ-x3H"/>
- <constraint firstItem="133" firstAttribute="top"
secondItem="134" secondAttribute="bottom" id="bWR-sc-XNl"/>
- <constraint firstAttribute="trailing" secondItem="134"
secondAttribute="trailing" id="sVN-Yz-bpb"/>
- <constraint firstItem="134" firstAttribute="top"
secondItem="85" secondAttribute="top" id="whT-Z9-oOB"/>
+ <constraint firstItem="85" firstAttribute="leading"
secondItem="il2-Kq-ue6" secondAttribute="leading" id="OGl-7j-VbO"/>
+ <constraint firstItem="85" firstAttribute="top"
secondItem="il2-Kq-ue6" secondAttribute="top" id="VBq-wv-XF8"/>
+ <constraint firstAttribute="trailing" secondItem="85"
secondAttribute="trailing" id="Y6W-nh-lKB"/>
+ <constraint firstAttribute="bottom" secondItem="85"
secondAttribute="bottom" id="hu9-VR-ClP"/>
</constraints>
- <point key="canvasLocation" x="267" y="154"/>
+ <point key="canvasLocation" x="-110" y="136"/>
</customView>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
<scrollView focusRingType="none" borderType="none"
autohidesScrollers="YES" horizontalLineScroll="34" horizontalPageScroll="10"
verticalLineScroll="34" verticalPageScroll="10" hasHorizontalScroller="NO"
usesPredominantAxisScrolling="NO"
translatesAutoresizingMaskIntoConstraints="NO" id="98">
<rect key="frame" x="0.0" y="0.0" width="198" height="400"/>
<clipView key="contentView" drawsBackground="NO"
translatesAutoresizingMaskIntoConstraints="NO" id="Mfb-HY-gcR">
Modified: trunk/MainWindow.xib
===================================================================
--- trunk/MainWindow.xib 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/MainWindow.xib 2026-03-22 18:15:30 UTC (rev 16083)
@@ -8,15 +8,7 @@
<objects>
<customObject id="-2" userLabel="File's Owner"
customClass="SKMainWindowController">
<connections>
- <outlet property="centerContentView" destination="1321"
id="1526"/>
- <outlet property="findBarTopConstraint"
destination="Twe-rt-5Qm" id="9jp-xi-0gz"/>
- <outlet property="leftSideContentView" destination="769"
id="774"/>
- <outlet property="pdfContentView" destination="1315"
id="1527"/>
- <outlet property="pdfSplitView" destination="1314" id="1318"/>
- <outlet property="rightSideContentView" destination="770"
id="775"/>
- <outlet property="splitView" destination="1385" id="1448"/>
<outlet property="statusBar" destination="2Zw-iS-Qai"
id="5oD-6z-7iD"/>
- <outlet property="topConstraint" destination="kue-s7-oZq"
id="Tun-Zg-UFY"/>
<outlet property="window" destination="5" id="18"/>
</connections>
</customObject>
@@ -33,54 +25,6 @@
<rect key="frame" x="0.0" y="0.0" width="1000" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"
heightSizable="YES"/>
<subviews>
- <splitView dividerStyle="thin" vertical="YES"
translatesAutoresizingMaskIntoConstraints="NO" id="1385"
customClass="SKSplitView">
- <rect key="frame" x="0.0" y="22" width="1000"
height="578"/>
- <subviews>
- <customView fixedFrame="YES" id="769"
customClass="SKGroupView">
- <rect key="frame" x="0.0" y="0.0" width="250"
height="578"/>
- <autoresizingMask key="autoresizingMask"/>
- </customView>
- <customView id="1321">
- <rect key="frame" x="251" y="0.0" width="498"
height="578"/>
- <autoresizingMask key="autoresizingMask"
flexibleMaxX="YES" flexibleMinY="YES"/>
- <subviews>
- <splitView dividerStyle="paneSplitter"
translatesAutoresizingMaskIntoConstraints="NO" id="1314"
customClass="SKSplitView">
- <rect key="frame" x="0.0" y="0.0"
width="498" height="578"/>
- <subviews>
- <customView fixedFrame="YES"
id="1315">
- <rect key="frame" x="0.0"
y="0.0" width="498" height="578"/>
- <autoresizingMask
key="autoresizingMask"/>
- </customView>
- </subviews>
- <holdingPriorities>
- <real value="250"/>
- </holdingPriorities>
- <connections>
- <outlet property="delegate"
destination="-2" id="1317"/>
- </connections>
- </splitView>
- </subviews>
- <constraints>
- <constraint firstAttribute="bottom"
secondItem="1314" secondAttribute="bottom" id="BwS-so-46O"/>
- <constraint firstAttribute="trailing"
secondItem="1314" secondAttribute="trailing" id="OE4-7n-0dl"/>
- <constraint firstItem="1314"
firstAttribute="top" secondItem="1321" secondAttribute="top" id="Twe-rt-5Qm"/>
- <constraint firstItem="1314"
firstAttribute="leading" secondItem="1321" secondAttribute="leading"
id="xoo-8V-ElE"/>
- </constraints>
- </customView>
- <customView fixedFrame="YES" id="770"
customClass="SKGroupView">
- <rect key="frame" x="750" y="0.0" width="250"
height="578"/>
- <autoresizingMask key="autoresizingMask"/>
- </customView>
- </subviews>
- <holdingPriorities>
- <real value="250"/>
- <real value="250"/>
- <real value="250"/>
- </holdingPriorities>
- <connections>
- <outlet property="delegate" destination="-2"
id="1449"/>
- </connections>
- </splitView>
<customView translatesAutoresizingMaskIntoConstraints="NO"
id="2Zw-iS-Qai" customClass="SKStatusBar">
<rect key="frame" x="0.0" y="0.0" width="1000"
height="22"/>
<constraints>
@@ -90,11 +34,7 @@
</subviews>
<constraints>
<constraint firstAttribute="bottom"
secondItem="2Zw-iS-Qai" secondAttribute="bottom" id="Lpk-GO-C0x"/>
- <constraint firstItem="2Zw-iS-Qai" firstAttribute="top"
secondItem="1385" secondAttribute="bottom" id="N1d-xY-GK9"/>
- <constraint firstAttribute="trailing" secondItem="1385"
secondAttribute="trailing" id="P20-vk-75c"/>
<constraint firstAttribute="trailing"
secondItem="2Zw-iS-Qai" secondAttribute="trailing" id="Rpa-Nl-KNp"/>
- <constraint firstItem="1385" firstAttribute="leading"
secondItem="6" secondAttribute="leading" id="cwR-tV-s3T"/>
- <constraint firstItem="1385" firstAttribute="top"
secondItem="6" secondAttribute="top" id="kue-s7-oZq"/>
<constraint firstItem="2Zw-iS-Qai"
firstAttribute="leading" secondItem="6" secondAttribute="leading"
id="vlN-aY-PV4"/>
</constraints>
</view>
Modified: trunk/RightSideView.xib
===================================================================
--- trunk/RightSideView.xib 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/RightSideView.xib 2026-03-22 18:15:30 UTC (rev 16083)
@@ -13,6 +13,7 @@
<outlet property="noteArrayController" destination="7"
id="57"/>
<outlet property="noteOutlineView" destination="31" id="56"/>
<outlet property="searchField" destination="22" id="54"/>
+ <outlet property="sideView" destination="4" id="iH4-jx-VtY"/>
<outlet property="snapshotArrayController" destination="8"
id="58"/>
<outlet property="snapshotTableView" destination="13" id="59"/>
<outlet property="topBar" destination="19" id="64"/>
@@ -22,7 +23,7 @@
</customObject>
<customObject id="-1" userLabel="First Responder"
customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
- <customView translatesAutoresizingMaskIntoConstraints="NO" id="4"
userLabel="RightSideView">
+ <customView translatesAutoresizingMaskIntoConstraints="NO" id="4"
userLabel="RightSideView" customClass="SKGroupView">
<rect key="frame" x="0.0" y="0.0" width="200" height="400"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO"
id="18">
@@ -112,7 +113,7 @@
<tableColumnResizingMask key="resizingMask"
resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="ZGN-Pg-55C"
customClass="SKNoteTableCellView">
- <rect key="frame" x="11" y="1"
width="93" height="15"/>
+ <rect key="frame" x="1" y="1"
width="93" height="15"/>
<autoresizingMask
key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField
horizontalCompressionResistancePriority="250"
verticalCompressionResistancePriority="250" allowsExpansionToolTips="YES"
preferredMaxLayoutWidth="122" translatesAutoresizingMaskIntoConstraints="NO"
id="T6H-tX-biW">
@@ -148,7 +149,7 @@
</connections>
</tableCellView>
<customView identifier="row"
translatesAutoresizingMaskIntoConstraints="NO" id="84k-Om-OZ4"
customClass="SKNoteTableRowView">
- <rect key="frame" x="11" y="18"
width="93" height="17"/>
+ <rect key="frame" x="1" y="18"
width="93" height="17"/>
<autoresizingMask
key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
</prototypeCellViews>
@@ -161,7 +162,7 @@
<imageCell key="dataCell"
refusesFirstResponder="YES" alignment="left" animates="YES" id="38"
customClass="SKAnnotationTypeImageCell"/>
<prototypeCellViews>
<tableCellView id="dka-Zp-1o0">
- <rect key="frame" x="107" y="1"
width="21" height="17"/>
+ <rect key="frame" x="97" y="1"
width="21" height="17"/>
<autoresizingMask
key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView
horizontalHuggingPriority="251" verticalHuggingPriority="251"
horizontalCompressionResistancePriority="250"
verticalCompressionResistancePriority="250"
translatesAutoresizingMaskIntoConstraints="NO" id="Wy1-6F-s9I"
customClass="SKAnnotationTypeImageView">
@@ -235,7 +236,7 @@
</textFieldCell>
<prototypeCellViews>
<tableCellView id="rnK-rN-FoS">
- <rect key="frame" x="131" y="1"
width="46" height="17"/>
+ <rect key="frame" x="121" y="1"
width="46" height="17"/>
<autoresizingMask
key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField
horizontalCompressionResistancePriority="250"
verticalCompressionResistancePriority="250" allowsExpansionToolTips="YES"
translatesAutoresizingMaskIntoConstraints="NO" id="iuK-OP-ap6">
Modified: trunk/SKLeftSideViewController.m
===================================================================
--- trunk/SKLeftSideViewController.m 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKLeftSideViewController.m 2026-03-22 18:15:30 UTC (rev 16083)
@@ -80,6 +80,8 @@
- (void)viewDidLoad {
[super viewDidLoad];
+ [sideView setAccessibilityLabel:NSLocalizedString(@"contents pane",
@"Accessibility description")];
+
[button setHelp:NSLocalizedString(@"View Thumbnails", @"Tool tip message")
forSegment:SKSidePaneStateThumbnail];
[button setHelp:NSLocalizedString(@"View Table of Contents", @"Tool tip
message") forSegment:SKSidePaneStateOutline];
[alternateButton setHelp:NSLocalizedString(@"Separate search results",
@"Tool tip message") forSegment:SKFindPaneStateSingular];
Modified: trunk/SKMainWindowController.h
===================================================================
--- trunk/SKMainWindowController.h 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKMainWindowController.h 2026-03-22 18:15:30 UTC (rev 16083)
@@ -73,12 +73,12 @@
@class SKPresentationNotesAuxiliary;
@interface SKMainWindowController : NSWindowController
<SKSnapshotWindowControllerDelegate, SKThumbnailDelegate,
SKFindControllerDelegate, SKPDFViewDelegate, SKPDFDocumentDelegate,
NSTouchBarDelegate> {
- SKSplitView *splitView;
- NSLayoutConstraint *topConstraint;
+ NSSplitViewController *splitViewController;
+ NSSplitViewController *pdfSplitViewController;
+
NSView *centerContentView;
- SKSplitView *pdfSplitView;
- NSView *pdfContentView;
+
SKPDFView *pdfView;
SKSecondaryPDFView *secondaryPdfView;
@@ -97,9 +97,6 @@
SKOverviewView *overviewView;
NSView *overviewContentView;
- NSView *leftSideContentView;
- NSView *rightSideContentView;
-
SKStatusBar *statusBar;
SKFindController *findController;
@@ -155,10 +152,6 @@
NSMutableDictionary<NSString *, id> *savedNormalSetup;
- CGFloat lastLeftSidePaneWidth;
- CGFloat lastRightSidePaneWidth;
- CGFloat lastSplitPDFHeight;
-
CGFloat titleBarHeight;
CGFloat thumbnailCacheSize;
@@ -188,11 +181,11 @@
unsigned int updatingFont:1;
unsigned int updatingFontAttributes:1;
unsigned int updatingLine:1;
- unsigned int settingUpWindow:1;
unsigned int isEditingPDF:1;
unsigned int isEditingTable:1;
unsigned int isSwitchingFullScreen:1;
unsigned int isAnimatingFindBar:1;
+ unsigned int isAnimatingSplitPDF:1;
unsigned int wantsPresentationOrFullScreen:1;
unsigned int hasCropped:1;
unsigned int fullSizeContent:1;
@@ -202,18 +195,10 @@
} mwcFlags;
}
-@property (nonatomic, nullable, strong) IBOutlet SKSplitView *splitView;
-@property (nonatomic, nullable, strong) IBOutlet NSLayoutConstraint
*topConstraint;
+@property (nonatomic, nullable, strong) IBOutlet SKStatusBar *statusBar;
-@property (nonatomic, nullable, strong) IBOutlet NSView *centerContentView;
-@property (nonatomic, nullable, strong) IBOutlet SKSplitView *pdfSplitView;
-@property (nonatomic, nullable, strong) IBOutlet NSView *pdfContentView;
-@property (nonatomic, nullable, strong) IBOutlet NSLayoutConstraint
*findBarTopConstraint;
+@property (nonatomic, nullable, readonly) NSSplitView *splitView;
-@property (nonatomic, nullable, strong) IBOutlet SKStatusBar *statusBar;
-
-@property (nonatomic, nullable, strong) IBOutlet NSView *leftSideContentView,
*rightSideContentView;
-
@property (nonatomic, nullable, strong) NSString *searchString;
- (SKTransitionController *)transitionControllerCreating:(BOOL)create;
Modified: trunk/SKMainWindowController.m
===================================================================
--- trunk/SKMainWindowController.m 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKMainWindowController.m 2026-03-22 18:15:30 UTC (rev 16083)
@@ -122,6 +122,11 @@
#define MAX_PAGE_COLUMN_WIDTH_1 50.0
#define MAX_MIN_COLUMN_WIDTH 100.0
+#define DEFAULT_SIDE_PANE_WIDTH 250.0
+#define MIN_SIDE_PANE_WIDTH 100.0
+#define MIN_PDF_PANE_WIDTH 100.0
+#define MIN_PDF_PANE_HEIGHT 50.0
+
#define SEARCHRESULTS_KEY @"searchResults"
#define GROUPEDSEARCHRESULTS_KEY @"groupedSearchResults"
#define NOTES_KEY @"notes"
@@ -215,8 +220,8 @@
@implementation SKMainWindowController
-@synthesize splitView, topConstraint, centerContentView, pdfSplitView,
pdfContentView, findBarTopConstraint, statusBar, pdfView, secondaryPdfView,
leftSideContentView, rightSideContentView, presentationNotesDocument,
presentationNotesOffset, notes, thumbnails, snapshots, searchResults,
groupedSearchResults, tags, rating, pageLabel, interactionMode,
placeholderPdfDocument;
-@dynamic pdfDocument, selectedNotes, hasNotes, widgetProperties, currentPage,
leftSidePaneState, rightSidePaneState, findPaneState, displaysFindPane,
leftSidePaneIsOpen, rightSidePaneIsOpen, searchString, hasNoteToolbar,
hasOverview, notesMenu;
+@synthesize statusBar, pdfView, secondaryPdfView, presentationNotesDocument,
presentationNotesOffset, notes, thumbnails, snapshots, searchResults,
groupedSearchResults, tags, rating, pageLabel, interactionMode,
placeholderPdfDocument;
+@dynamic splitView, pdfDocument, selectedNotes, hasNotes, widgetProperties,
currentPage, leftSidePaneState, rightSidePaneState, findPaneState,
displaysFindPane, leftSidePaneIsOpen, rightSidePaneIsOpen, searchString,
hasNoteToolbar, hasOverview, notesMenu;
+ (BOOL)automaticallyNotifiesObserversOfPageLabel { return NO; }
@@ -250,9 +255,6 @@
pageLabels = [[NSArray alloc] init];
lastViewedPages = [[NSPointerArray alloc]
initWithOptions:NSPointerFunctionsOpaqueMemory |
NSPointerFunctionsIntegerPersonality];
- lastLeftSidePaneWidth = 0.0;
- lastRightSidePaneWidth = 0.0;
- lastSplitPDFHeight = 0.0;
titleBarHeight = 0.0;
thumbnailCacheSize = 0.0;
snapshotCacheSize = 0.0;
@@ -274,13 +276,13 @@
}
- (void)dealloc {
- if (mwcFlags.needsCleanup == 1)
+ if (mwcFlags.needsCleanup)
SKENSURE_MAIN_THREAD( [self cleanup]; );
}
// this is called from windowWillClose:
- (void)cleanup {
- mwcFlags.needsCleanup = 0;
+ mwcFlags.needsCleanup = NO;
if (activity) {
[[NSProcessInfo processInfo] endActivity:activity];
activity = nil;
@@ -290,8 +292,6 @@
[self clearWidgets];
[self unregisterAsObserver];
[[self window] setDelegate:nil];
- [splitView setDelegate:nil];
- [pdfSplitView setDelegate:nil];
[leftSideController setMainController:nil];
[rightSideController setMainController:nil];
[toolbarController setMainController:nil];
@@ -312,10 +312,8 @@
NSDocument *doc = [self document];
NSUserDefaults *sud = [NSUserDefaults standardUserDefaults];
- mwcFlags.needsCleanup = 0;
+ mwcFlags.needsCleanup = YES;
- mwcFlags.settingUpWindow = 1;
-
// Set up the panes and subviews, needs to be done before we resize them
leftSideController = [[SKLeftSideViewController alloc] init];
@@ -323,13 +321,43 @@
rightSideController = [[SKRightSideViewController alloc] init];
[rightSideController setMainController:self];
- // make sure the first thing we call on the side view controllers is its
view so their nib is loaded
- [leftSideContentView addSubviewWithConstraints:leftSideController.view];
- [rightSideContentView addSubviewWithConstraints:rightSideController.view];
+ splitViewController = [[NSSplitViewController alloc] init];
- [leftSideContentView setAccessibilityLabel:NSLocalizedString(@"contents
pane", @"Accessibility description")];
- [rightSideContentView setAccessibilityLabel:NSLocalizedString(@"notes
pane", @"Accessibility description")];
+ NSSplitViewItem *item = [NSSplitViewItem
sidebarWithViewController:leftSideController];
+ [item setMinimumThickness:MIN_SIDE_PANE_WIDTH];
+ [item setCanCollapse:YES];
+ [item setHoldingPriority:260.0];
+ [item setSpringLoaded:NO];
+ if (@available(macOS 11.0, *))
+ [item setAllowsFullHeightLayout:NO];
+ [splitViewController addSplitViewItem:item];
+ NSViewController *viewController = [[NSViewController alloc] init];
+ centerContentView = [[NSView alloc] init];
+ [viewController setView:centerContentView];
+ item = [NSSplitViewItem splitViewItemWithViewController:viewController];
+ [item setMinimumThickness:MIN_PDF_PANE_WIDTH];
+ [item setHoldingPriority:250.0];
+ [splitViewController addSplitViewItem:item];
+ item = [NSSplitViewItem
splitViewItemWithViewController:rightSideController];
+ [item setMinimumThickness:MIN_SIDE_PANE_WIDTH];
+ [item setCanCollapse:YES];
+ [item setHoldingPriority:255.0];
+ [splitViewController addSplitViewItem:item];
+ NSView *view = [splitViewController view];
+ NSView *contentView = [window contentView];
+ NSArray *constraints = @[[[view leadingAnchor]
constraintEqualToAnchor:[contentView leadingAnchor]],
+ [[contentView trailingAnchor] constraintEqualToAnchor:[view
trailingAnchor]],
+ [[view topAnchor] constraintEqualToAnchor:[(mwcFlags.fullSizeContent ?
contentView : [window contentLayoutGuide]) topAnchor]],
+ [[statusBar topAnchor] constraintEqualToAnchor:[view bottomAnchor]]];
+ [view setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [contentView addSubview:view];
+ [NSLayoutConstraint activateConstraints:constraints];
+
+ // this sets the default widths to return to and ensures that the side
views are loaded
+ [self setLeftSideWidth:@DEFAULT_SIDE_PANE_WIDTH];
+ [self setRightSideWidth:@DEFAULT_SIDE_PANE_WIDTH];
+
if (mwcFlags.fullSizeContent) {
[leftSideController setCurrentView:[[leftSideController currentView]
superview]];
[rightSideController setCurrentView:[[rightSideController currentView]
superview]];
@@ -341,8 +369,7 @@
[rightSideController displayTableAtIndex:mwcFlags.rightSidePaneState
animate:NO];
// we need to create the PDFView before setting the toolbar
- pdfView = [[SKPDFView alloc] initWithFrame:[pdfContentView bounds]];
- [pdfView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ pdfView = [[SKPDFView alloc] initWithFrame:[centerContentView bounds]];
// Set up the window
@@ -374,10 +401,6 @@
titleBarHeight = NSHeight([window frame]) - NSHeight([window
contentLayoutRect]);
[leftSideController setTopInset:titleBarHeight];
[rightSideController setTopInset:titleBarHeight];
- } else if (topConstraint) {
- [topConstraint setActive:NO];
- topConstraint = [[splitView topAnchor]
constraintEqualToAnchor:[[window contentLayoutGuide] topAnchor]];
- [topConstraint setActive:YES];
}
[self setWindowFrameAutosaveNameOrCascade:SKMainWindowFrameAutosaveName];
@@ -429,8 +452,28 @@
[leftSideController.button setEnabled:NO
forSegment:SKSidePaneStateOutline];
// Due to a bug in Leopard we should only resize and swap in the PDFView
after loading the PDFDocument
- [pdfContentView addSubviewWithConstraints:pdfView];
+ pdfSplitViewController = [[NSSplitViewController alloc] init];
+
+ viewController = [[NSViewController alloc] init];
+ [viewController setView:pdfView];
+ item = [NSSplitViewItem splitViewItemWithViewController:viewController];
+ [item setMinimumThickness:MIN_PDF_PANE_HEIGHT + titleBarHeight];
+ [pdfSplitViewController addSplitViewItem:item];
+
+ [[pdfSplitViewController splitView] setVertical:NO];
+
+ view = [pdfSplitViewController view];
+ constraints = @[[[view leadingAnchor]
constraintEqualToAnchor:[centerContentView leadingAnchor]],
+ [[centerContentView trailingAnchor] constraintEqualToAnchor:[view
trailingAnchor]],
+ [[view topAnchor] constraintEqualToAnchor:[centerContentView
topAnchor]],
+ [[centerContentView bottomAnchor] constraintEqualToAnchor:[view
bottomAnchor]]];
+ if (mwcFlags.fullSizeContent == NO)
+ findBarTopConstraint = [constraints objectAtIndex:2];
+ [view setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [centerContentView addSubview:view];
+ [NSLayoutConstraint activateConstraints:constraints];
+
if (hasWindowSetup == NO) {
NSInteger windowSizeOption = [sud
integerForKey:SKInitialWindowSizeOptionKey];
@@ -524,8 +567,6 @@
} else {
[savedNormalSetup removeAllObjects];
}
-
- mwcFlags.settingUpWindow = 0;
}
- (void)applySetup:(NSDictionary *)setup{
@@ -1216,6 +1257,10 @@
#pragma mark Accessors
+- (NSSplitView *)splitView {
+ return [splitViewController splitView];
+}
+
- (PDFDocument *)pdfDocument{
return [pdfView document];
}
@@ -1322,7 +1367,7 @@
if ([self interactionMode] == SKPresentationMode)
return [sideWindow isVisible];
else
- return NO == [splitView isSubviewCollapsed:leftSideContentView];
+ return NO == [[[splitViewController splitViewItems] firstObject]
isCollapsed];
}
- (BOOL)rightSidePaneIsOpen {
@@ -1329,25 +1374,37 @@
if ([self interactionMode] == SKPresentationMode)
return NO;
else
- return NO == [splitView isSubviewCollapsed:rightSideContentView];
+ return NO == [[[splitViewController splitViewItems] lastObject]
isCollapsed];
}
- (NSNumber *)leftSideWidth {
- return [splitView isSubviewCollapsed:leftSideContentView] ? @0.0 :
[NSNumber numberWithDouble:NSWidth([leftSideContentView frame])];
+ NSSplitViewItem *item = [[splitViewController splitViewItems] firstObject];
+ return [item isCollapsed] ? @0.0 : [NSNumber
numberWithDouble:NSWidth([[[item viewController] view] frame])];
}
- (void)setLeftSideWidth:(NSNumber *)leftSideWidth {
- if (leftSideWidth)
- [splitView setPosition:[leftSideWidth doubleValue] ofDividerAtIndex:0];
+ if (leftSideWidth) {
+ CGFloat width = [leftSideWidth doubleValue];
+ [[[splitViewController splitViewItems] firstObject] setCollapsed:width
<= 0.0];
+ if (width > 0.0)
+ [[splitViewController splitView] setPosition:width
ofDividerAtIndex:0];
+ }
}
- (NSNumber *)rightSideWidth {
- return [splitView isSubviewCollapsed:rightSideContentView] ? @0.0 :
[NSNumber numberWithDouble:NSWidth([rightSideContentView frame])];
+ NSSplitViewItem *item = [[splitViewController splitViewItems] lastObject];
+ return [item isCollapsed] ? @0.0 : [NSNumber
numberWithDouble:NSWidth([[[item viewController] view] frame])];
}
- (void)setRightSideWidth:(NSNumber *)rightSideWidth {
- if (rightSideWidth)
- [splitView setPosition:[splitView
maxPossiblePositionOfDividerAtIndex:1] - [splitView dividerThickness] -
[rightSideWidth doubleValue] ofDividerAtIndex:1];
+ if (rightSideWidth) {
+ CGFloat width = [rightSideWidth doubleValue];
+ [[[splitViewController splitViewItems] lastObject] setCollapsed:width
<= 0.0];
+ if (width > 0.0) {
+ NSSplitView *sv = [splitViewController splitView];
+ [sv setPosition:[sv maxPossiblePositionOfDividerAtIndex:1] - [sv
dividerThickness] - width ofDividerAtIndex:1];
+ }
+ }
}
- (BOOL)hasNotes {
@@ -1598,7 +1655,7 @@
}
BOOL isPresentation = [self interactionMode] == SKPresentationMode;
- NSView *oldView = isPresentation ? presentationView : splitView;
+ NSView *oldView = isPresentation ? presentationView : [splitViewController
view];
NSView *contentView = [oldView superview];
BOOL hasStatus = isPresentation == NO && [statusBar isVisible];
NSArray *constraints = @[
@@ -1665,7 +1722,7 @@
// don't check interactionMode as this can be called from enterPresentation
BOOL isPresentation = 0 == ([[overviewContentView window] styleMask] &
NSWindowStyleMaskTitled);
- NSView *newView = isPresentation ? presentationView : splitView;
+ NSView *newView = isPresentation ? presentationView : [splitViewController
view];
NSView *newKeyView = isPresentation ? presentationView : pdfView;
NSView *contentView = [overviewContentView superview];
BOOL hasStatus = isPresentation == NO && [statusBar isVisible];
@@ -1794,20 +1851,18 @@
CGFloat barHeight = [findController height];
NSWindow *window = [self window];
- if (mwcFlags.fullSizeContent)
- findBarTopConstraint = nil;
- else
- findBarTopConstraint = [[pdfSplitView topAnchor]
constraintEqualToAnchor:[contentView topAnchor]];
-
if ([window firstResponderIsDescendantOf:findBar])
[window makeFirstResponder:pdfView];
if (mwcFlags.fullSizeContent) {
+ findBarTopConstraint = nil;
[[pdfView embeddedScrollView]
setAutomaticallyAdjustsContentInsets:YES];
if ([pdfView autoScales] && ([pdfView extendedDisplayMode] &
kPDFDisplaySinglePageContinuous) == 0) {
[pdfView setAutoScales:NO];
[pdfView setAutoScales:YES];
}
+ } else {
+ findBarTopConstraint = [[[pdfSplitViewController view] topAnchor]
constraintEqualToAnchor:[contentView topAnchor]];
}
if (animate) {
@@ -1845,24 +1900,23 @@
} else if (mwcFlags.isAnimatingFindBar == 0) {
BOOL animate = [NSView shouldShowSlideAnimation];
- NSView *contentView = mwcFlags.fullSizeContent ? pdfContentView :
centerContentView;
CGFloat barHeight = [findController height];
NSLayoutConstraint *barTopConstraint = [findController topConstraint];
NSArray *constraints = nil;
[barTopConstraint setConstant:animate ? -barHeight : 0.0];
- [contentView addSubview:findBar];
+ [centerContentView addSubview:findBar];
constraints = @[
- [[findBar leadingAnchor] constraintEqualToAnchor:[contentView
leadingAnchor]],
- [[contentView trailingAnchor] constraintEqualToAnchor:[findBar
trailingAnchor]],
- [[findBar topAnchor] constraintEqualToAnchor:[contentView
topAnchor] constant:titleBarHeight]];
+ [[findBar leadingAnchor]
constraintEqualToAnchor:[centerContentView leadingAnchor]],
+ [[centerContentView trailingAnchor]
constraintEqualToAnchor:[findBar trailingAnchor]],
+ [[findBar topAnchor] constraintEqualToAnchor:[centerContentView
topAnchor] constant:titleBarHeight]];
[NSLayoutConstraint activateConstraints:constraints];
if (mwcFlags.fullSizeContent == NO) {
[findBarTopConstraint setActive:NO];
- [[[pdfSplitView topAnchor] constraintEqualToAnchor:[findBar
bottomAnchor]] setActive:YES];
+ [[[[pdfSplitViewController view] topAnchor]
constraintEqualToAnchor:[findBar bottomAnchor]] setActive:YES];
}
findBarTopConstraint = [constraints objectAtIndex:2];
- [contentView layoutSubtreeIfNeeded];
+ [centerContentView layoutSubtreeIfNeeded];
[findController didAddFindBar];
@@ -1889,7 +1943,7 @@
mwcFlags.isAnimatingFindBar = NO;
}];
} else {
- [contentView layoutSubtreeIfNeeded];
+ [centerContentView layoutSubtreeIfNeeded];
[[self window] recalculateKeyViewLoop];
[findField selectText:nil];
}
@@ -2644,6 +2698,7 @@
[findBarTopConstraint setConstant:titleBarHeight];
[[pdfView embeddedScrollView]
setContentInsets:NSEdgeInsetsMake([findController height] + titleBarHeight,
0.0, 0.0, 0.0)];
}
+ [[[pdfSplitViewController splitViewItems] firstObject]
setMinimumThickness:MIN_PDF_PANE_HEIGHT + titleBarHeight];
}
} else if (context == &SKMainWindowTransitionsObservationContext) {
Modified: trunk/SKMainWindowController_Actions.m
===================================================================
--- trunk/SKMainWindowController_Actions.m 2026-03-22 17:27:45 UTC (rev
16082)
+++ trunk/SKMainWindowController_Actions.m 2026-03-22 18:15:30 UTC (rev
16083)
@@ -82,14 +82,12 @@
#import "SKPresentationView.h"
#import "NSUserDefaults_SKExtensions.h"
#import "SKNoteToolbarController.h"
+#import "NSView_SKExtensions.h"
#define STATUSBAR_HEIGHT 22.0
-#define DEFAULT_SIDE_PANE_WIDTH 250.0
-#define MIN_SIDE_PANE_WIDTH 100.0
+#define MIN_SPLIT_PANE_HEIGHT 50.0
-#define DEFAULT_SPLIT_PDF_FACTOR 0.3
-
#define SKShowNoteToolbarInFullScreenKey @"SKShowNoteToolbarInFullScreen"
@interface SKMainWindowController (SKPrivateUI)
@@ -783,7 +781,7 @@
- (IBAction)toggleStatusBar:(id)sender {
[[NSUserDefaults standardUserDefaults] setBool:(NO == [statusBar
isVisible]) forKey:SKShowStatusBarKey];
- NSView *view = [self hasOverview] ? overviewContentView : splitView;
+ NSView *view = [self hasOverview] ? overviewContentView :
[splitViewController view];
[statusBar toggleBelowView:view animate:sender != nil];
}
@@ -792,11 +790,14 @@
[self hideOverviewAnimating:YES completionHandler:^{ [self
searchPDF:sender]; }];
return;
}
- if ([self leftSidePaneIsOpen] == NO)
+ BOOL animating = NO;
+ if ([self leftSidePaneIsOpen] == NO) {
+ animating = [NSView shouldShowSlideAnimation];
[self toggleLeftSidePane:sender];
+ }
// workaround for an AppKit bug: when selecting immediately before the
animation, the search fields does not display its text
- if ([splitView isAnimating])
- [splitView enqueueOperation:^{ [leftSideController.searchField
selectText:self]; }];
+ if (animating)
+ [leftSideController.searchField performSelector:@selector(selectText:)
withObject:nil afterDelay:0.25];
else
[leftSideController.searchField selectText:self];
}
@@ -806,11 +807,14 @@
[self hideOverviewAnimating:YES completionHandler:^{ [self
filterNotes:sender]; }];
return;
}
- if ([self rightSidePaneIsOpen] == NO)
+ BOOL animating = NO;
+ if ([self rightSidePaneIsOpen] == NO) {
+ animating = [NSView shouldShowSlideAnimation];
[self toggleRightSidePane:sender];
+ }
// workaround for an AppKit bug: when selecting immediately before the
animation, the search fields does not display its text
- if ([splitView isAnimating])
- [splitView enqueueOperation:^{ [rightSideController.searchField
selectText:self]; }];
+ if (animating)
+ [rightSideController.searchField
performSelector:@selector(selectText:) withObject:nil afterDelay:0.25];
else
[rightSideController.searchField selectText:self];
}
@@ -1025,19 +1029,15 @@
} else if ([self hasOverview]) {
[self hideOverviewAnimating:sender != nil completionHandler:^{ [self
toggleLeftSidePane:sender]; }];
} else {
- CGFloat position = [splitView minPossiblePositionOfDividerAtIndex:0];
- if ([self leftSidePaneIsOpen]) {
- if ([[self window]
firstResponderIsDescendantOf:leftSideContentView])
+ NSSplitViewItem *item = [[splitViewController splitViewItems]
firstObject];
+ BOOL collapse = [item isCollapsed] == NO;
+ if ([self leftSidePaneIsOpen])
+ if ([[self window] firstResponderIsDescendantOf:[[item
viewController] view]])
[[self window] makeFirstResponder:pdfView];
- lastLeftSidePaneWidth = fmaxf(MIN_SIDE_PANE_WIDTH,
NSWidth([leftSideContentView frame]));
- } else {
- if(lastLeftSidePaneWidth <= 0.0)
- lastLeftSidePaneWidth = DEFAULT_SIDE_PANE_WIDTH; // a
reasonable value to start
- if (lastLeftSidePaneWidth > 0.5 * NSWidth([centerContentView
frame]))
- lastLeftSidePaneWidth = floor(0.5 * NSWidth([centerContentView
frame]));
- position = lastLeftSidePaneWidth;
- }
- [splitView setPosition:position ofDividerAtIndex:0 animate:sender !=
nil];
+ if (sender == nil || [NSView shouldShowSlideAnimation] == NO)
+ [item setCollapsed:collapse];
+ else
+ [[item animator] setCollapsed:collapse];
}
}
@@ -1046,21 +1046,24 @@
} else if ([self hasOverview]) {
[self hideOverviewAnimating:sender != nil completionHandler:^{ [self
toggleRightSidePane:sender]; }];
} else {
- CGFloat position = [splitView maxPossiblePositionOfDividerAtIndex:1];
- if ([self rightSidePaneIsOpen]) {
- if ([[self window]
firstResponderIsDescendantOf:rightSideContentView])
+ NSSplitViewItem *item = [[splitViewController splitViewItems]
lastObject];
+ BOOL collapse = [item isCollapsed] == NO;
+ if ([self leftSidePaneIsOpen])
+ if ([[self window] firstResponderIsDescendantOf:[[item
viewController] view]])
[[self window] makeFirstResponder:pdfView];
- lastRightSidePaneWidth = fmaxf(MIN_SIDE_PANE_WIDTH,
NSWidth([rightSideContentView frame]));
- [splitView setPosition:position ofDividerAtIndex:1 animate:sender
!= nil];
+ if (sender == nil || [NSView shouldShowSlideAnimation] == NO) {
+ [item setCollapsed:collapse];
+ } else if (mwcFlags.autoResizeNoteRows) {
+ mwcFlags.autoResizeNoteRows = NO;
+ [NSAnimationContext runAnimationGroup:^(NSAnimationContext
*context){
+ [[item animator] setCollapsed:collapse];
+ } completionHandler:^{
+ mwcFlags.autoResizeNoteRows = YES;
+ if (collapse == NO)
+ [self resetNoteRowHeights];
+ }];
} else {
- if(lastRightSidePaneWidth <= 0.0)
- lastRightSidePaneWidth = DEFAULT_SIDE_PANE_WIDTH; // a
reasonable value to start
- if (lastRightSidePaneWidth > 0.5 * NSWidth([centerContentView
frame]))
- lastRightSidePaneWidth = floor(0.5 *
NSWidth([centerContentView frame]));
- position -= lastRightSidePaneWidth + [splitView dividerThickness];
- [splitView setPosition:position ofDividerAtIndex:1 animate:sender
!= nil];
- if (mwcFlags.autoResizeNoteRows && [splitView isAnimating])
- [splitView enqueueOperation:^{ [self resetNoteRowHeights]; }];
+ [[item animator] setCollapsed:collapse];
}
}
}
@@ -1085,46 +1088,54 @@
}
- (IBAction)toggleSplitPDF:(id)sender {
- if ([pdfSplitView isAnimating])
- return;
-
if ([self hasOverview]) {
[self hideOverviewAnimating:YES completionHandler:^{ [self
toggleSplitPDF:sender]; }];
return;
}
+ if (mwcFlags.isAnimatingSplitPDF)
+ return;
+
if ([secondaryPdfView window]) {
- lastSplitPDFHeight = NSHeight([secondaryPdfView frame]);
+ NSSplitViewItem *item = [[pdfSplitViewController splitViewItems]
lastObject];
- [pdfSplitView setPosition:[pdfSplitView
maxPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0 animate:YES];
- if ([pdfSplitView isAnimating]) {
- [pdfSplitView enqueueOperation:^{
- [secondaryPdfView removeFromSuperview];
- [pdfSplitView adjustSubviews];
- }];
+ if ([item isCollapsed] || [NSView shouldShowSlideAnimation] == NO) {
+ [item setCollapsed:YES];
+ [[pdfSplitViewController splitView]
setDividerStyle:NSSplitViewDividerStyleThin];
+ [pdfSplitViewController removeSplitViewItem:item];
} else {
- [secondaryPdfView removeFromSuperview];
- [pdfSplitView adjustSubviews];
+ mwcFlags.isAnimatingSplitPDF = YES;
+ [NSAnimationContext runAnimationGroup:^(NSAnimationContext
*context){
+ [[item animator] setCollapsed:YES];
+ } completionHandler:^{
+ [[pdfSplitViewController splitView]
setDividerStyle:NSSplitViewDividerStyleThin];
+ [pdfSplitViewController removeSplitViewItem:item];
+ mwcFlags.isAnimatingSplitPDF = NO;
+ }];
}
} else {
NSRect frame = [pdfView bounds];
+ NSSplitViewItem *item = nil;
- if (lastSplitPDFHeight <= 0.0)
- lastSplitPDFHeight = floor(DEFAULT_SPLIT_PDF_FACTOR *
(NSHeight(frame) - titleBarHeight));
-
- CGFloat position = NSHeight(frame) - lastSplitPDFHeight -
[pdfSplitView dividerThickness];
-
if (secondaryPdfView == nil) {
NSPoint point = frame.origin;
PDFPage *page = nil;
BOOL fixedAtBottom = [[[pdfView embeddedScrollView] contentView]
isFlipped] == NO;
- secondaryPdfView = [[SKSecondaryPDFView alloc]
initWithFrame:NSMakeRect(0.0, 0.0, NSWidth(frame), lastSplitPDFHeight)];
+ secondaryPdfView = [[SKSecondaryPDFView alloc]
initWithFrame:NSMakeRect(0.0, 0.0, NSWidth(frame), 250.0)];
[secondaryPdfView setAutoresizingMask:NSViewWidthSizable |
NSViewHeightSizable];
- [secondaryPdfView setHidden:YES];
- [pdfSplitView addSubview:secondaryPdfView];
+
+ NSViewController *viewController = [[NSViewController alloc] init];
+ [viewController setView:secondaryPdfView];
+ item = [NSSplitViewItem
splitViewItemWithViewController:viewController];
+ [item setCanCollapse:YES];
+ [item setCollapsed:YES];
+ [item setMinimumThickness:MIN_SPLIT_PANE_HEIGHT];
+ [pdfSplitViewController addSplitViewItem:item];
+ [[pdfSplitViewController splitView]
setDividerStyle:NSSplitViewDividerStylePaneSplitter];
+
// Because of a PDFView bug, display properties can not be changed
before it is placed in a window
[secondaryPdfView setSynchronizedPDFView:pdfView];
[secondaryPdfView setBackgroundColor:[pdfView backgroundColor]];
@@ -1132,7 +1143,7 @@
[secondaryPdfView setInterpolationQuality:[[NSUserDefaults
standardUserDefaults] integerForKey:SKInterpolationQualityKey]];
[secondaryPdfView setSynchronizeZoom:YES];
[secondaryPdfView setDocument:[pdfView document]];
- point.y += fixedAtBottom ? -lastSplitPDFHeight :
lastSplitPDFHeight + [pdfSplitView dividerThickness];
+ point.y += fixedAtBottom ? -250.0 : 250.0 +
[[pdfSplitViewController splitView] dividerThickness];
page = [pdfView pageForPoint:point nearest:YES];
[secondaryPdfView goToPage:page];
[secondaryPdfView layoutDocumentView];
@@ -1144,11 +1155,26 @@
[secondaryPdfView resetHistory];
} else {
- [secondaryPdfView setHidden:YES];
- [pdfSplitView addSubview:secondaryPdfView];
+ NSViewController *viewController = [[NSViewController alloc] init];
+ [viewController setView:secondaryPdfView];
+ item = [NSSplitViewItem
splitViewItemWithViewController:viewController];
+ [item setCanCollapse:YES];
+ [item setCollapsed:YES];
+ [item setMinimumThickness:50.0];
+ [pdfSplitViewController addSplitViewItem:item];
+ [[pdfSplitViewController splitView]
setDividerStyle:NSSplitViewDividerStylePaneSplitter];
}
- [pdfSplitView setPosition:position ofDividerAtIndex:0 animate:YES];
+ if ([NSView shouldShowSlideAnimation]) {
+ mwcFlags.isAnimatingSplitPDF = YES;
+ [NSAnimationContext runAnimationGroup:^(NSAnimationContext
*context){
+ [[item animator] setCollapsed:NO];
+ } completionHandler:^{
+ mwcFlags.isAnimatingSplitPDF = NO;
+ }];
+ } else {
+ [item setCollapsed:NO];
+ }
}
[[self window] recalculateKeyViewLoop];
Modified: trunk/SKMainWindowController_FullScreen.m
===================================================================
--- trunk/SKMainWindowController_FullScreen.m 2026-03-22 17:27:45 UTC (rev
16082)
+++ trunk/SKMainWindowController_FullScreen.m 2026-03-22 18:15:30 UTC (rev
16083)
@@ -91,11 +91,11 @@
#pragma mark Side Windows
- (void)showSideWindow {
- if ([[leftSideController.view window]
firstResponderIsDescendantOf:leftSideController.view])
- [[leftSideController.view window] makeFirstResponder:nil];
+ if ([[leftSideController.view window]
firstResponderIsDescendantOf:leftSideController.sideView])
+ [[leftSideController.sideView window] makeFirstResponder:nil];
if (sideWindow == nil)
- sideWindow = [[SKSideWindow alloc]
initWithView:leftSideController.view];
+ sideWindow = [[SKSideWindow alloc]
initWithView:leftSideController.sideView];
if (mwcFlags.fullSizeContent) {
[leftSideController.topBar setStyle:SKTopBarStylePresentation];
@@ -116,10 +116,10 @@
}
- (void)hideSideWindow {
- if ([[leftSideController.view window] isEqual:sideWindow]) {
+ if ([[leftSideController.sideView window] isEqual:sideWindow]) {
[sideWindow remove];
- if ([sideWindow firstResponderIsDescendantOf:leftSideController.view])
+ if ([sideWindow
firstResponderIsDescendantOf:leftSideController.sideView])
[sideWindow makeFirstResponder:nil];
if (mwcFlags.fullSizeContent) {
[leftSideController.topBar setStyle:SKTopBarStyleSearchBar];
@@ -128,9 +128,9 @@
[leftSideController.topBar setDrawsBackground:YES];
}
- [leftSideController.view setFrame:[leftSideContentView bounds]];
+ [leftSideController.sideView setFrame:[leftSideController.view
bounds]];
- [leftSideContentView
addSubviewWithConstraints:leftSideController.view];
+ [leftSideController.view
addSubviewWithConstraints:leftSideController.sideView];
[self setLeftSidePaneState:mwcFlags.savedLeftSidePaneState];
Modified: trunk/SKMainWindowController_UI.m
===================================================================
--- trunk/SKMainWindowController_UI.m 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKMainWindowController_UI.m 2026-03-22 18:15:30 UTC (rev 16083)
@@ -110,11 +110,6 @@
#define SKLeftSidePaneWidthKey @"SKLeftSidePaneWidth"
#define SKRightSidePaneWidthKey @"SKRightSidePaneWidth"
-#define MIN_SIDE_PANE_WIDTH 100.0
-#define DEFAULT_SPLIT_PANE_HEIGHT 200.0
-#define MIN_SPLIT_PANE_HEIGHT 50.0
-#define MIN_PDF_PANE_HEIGHT 50.0
-
#define SNAPSHOT_HEIGHT 200.0
#define EXTRA_ROW_HEIGHT 2.0
@@ -1603,12 +1598,13 @@
- (BOOL)PDFView:(PDFView *)aPDFView performAction:(PDFAction *)action {
if ([action isKindOfClass:[PDFActionGoTo class]] && ([NSEvent
modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) ==
NSEventModifierFlagShift) {
- if ([secondaryPdfView window] == nil)
+ BOOL animating = NO;
+ if ([secondaryPdfView window] == nil) {
+ animating = [NSView shouldShowSlideAnimation];
[self toggleSplitPDF:nil];
- if ([pdfSplitView isAnimating]) {
- [pdfSplitView enqueueOperation:^{
- [secondaryPdfView performAction:action];
- }];
+ }
+ if (animating) {
+ [secondaryPdfView performSelector:@selector(performAction:)
withObject:action afterDelay:0.25];
} else {
[secondaryPdfView performAction:action];
}
@@ -1653,147 +1649,6 @@
return [[self document] undoManager];
}
-#pragma mark NSSplitView delegate protocol
-
-- (BOOL)splitView:(NSSplitView *)aSplitView canCollapseSubview:(NSView
*)subview {
- if ([aSplitView isEqual:splitView]) {
- return [subview isEqual:centerContentView] == NO;
- } else if ([aSplitView isEqual:pdfSplitView]) {
- return [subview isEqual:secondaryPdfView];
- }
- return NO;
-}
-
-- (BOOL)splitView:(NSSplitView *)aSplitView
doubleClickedOnDividerAtIndex:(NSInteger)dividerIndex {
- if ([aSplitView isEqual:splitView]) {
- if (dividerIndex == 0)
- [self toggleLeftSidePane:aSplitView];
- else if (dividerIndex == 1)
- [self toggleRightSidePane:aSplitView];
- } else if ([aSplitView isEqual:pdfSplitView]) {
- if (dividerIndex == 0) {
- CGFloat position = [pdfSplitView
maxPossiblePositionOfDividerAtIndex:dividerIndex];
- if (NSHeight([pdfContentView frame]) >= position) {
- if (lastSplitPDFHeight <= 0.0)
- lastSplitPDFHeight = DEFAULT_SPLIT_PANE_HEIGHT;
- if (lastSplitPDFHeight > NSHeight([pdfContentView frame]))
- lastSplitPDFHeight = floor(0.5 * NSHeight([pdfView
frame]));
- position -= lastSplitPDFHeight;
- } else {
- lastSplitPDFHeight = NSHeight([secondaryPdfView frame]);
- }
- [pdfSplitView setPosition:position ofDividerAtIndex:dividerIndex
animate:YES];
- }
- }
- return NO;
-}
-
-- (BOOL)splitView:(NSSplitView *)aSplitView
shouldHideDividerAtIndex:(NSInteger)dividerIndex {
- return [aSplitView isEqual:splitView];
-}
-
-- (CGFloat)splitView:(NSSplitView *)aSplitView
constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex
{
- if ([aSplitView respondsToSelector:@selector(isAnimating)] &&
[(SKSplitView *)aSplitView isAnimating])
- return proposedMax;
- else if ([aSplitView isEqual:splitView] && dividerIndex == 1)
- return proposedMax - MIN_SIDE_PANE_WIDTH;
- else if ([aSplitView isEqual:pdfSplitView])
- return proposedMax - MIN_SPLIT_PANE_HEIGHT;
- return proposedMax;
-}
-
-- (CGFloat)splitView:(NSSplitView *)aSplitView
constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex
{
- if ([aSplitView respondsToSelector:@selector(isAnimating)] &&
[(SKSplitView *)aSplitView isAnimating])
- return proposedMin;
- else if ([aSplitView isEqual:splitView] && dividerIndex == 0)
- return proposedMin + MIN_SIDE_PANE_WIDTH;
- else if ([aSplitView isEqual:pdfSplitView])
- return proposedMin + titleBarHeight + MIN_PDF_PANE_HEIGHT;
- return proposedMin;
-}
-
-- (void)splitView:(NSSplitView *)aSplitView
resizeSubviewsWithOldSize:(NSSize)oldSize {
- if ([aSplitView isEqual:splitView]) {
- NSView *leftView = [[aSplitView subviews] objectAtIndex:0];
- NSView *mainView = [[aSplitView subviews] objectAtIndex:1];
- NSView *rightView = [[aSplitView subviews] objectAtIndex:2];
- BOOL leftCollapsed = [aSplitView isSubviewCollapsed:leftView];
- BOOL rightCollapsed = [aSplitView isSubviewCollapsed:rightView];
- NSSize leftSize = [leftView frame].size;
- NSSize mainSize = [mainView frame].size;
- NSSize rightSize = [rightView frame].size;
- CGFloat contentWidth = NSWidth([aSplitView frame]);
-
- if (leftCollapsed)
- leftSize.width = 0.0;
- else
- contentWidth -= [aSplitView dividerThickness];
- if (rightCollapsed)
- rightSize.width = 0.0;
- else
- contentWidth -= [aSplitView dividerThickness];
-
- if (contentWidth < leftSize.width + rightSize.width) {
- CGFloat oldContentWidth = oldSize.width;
- if (leftCollapsed == NO)
- oldContentWidth -= [aSplitView dividerThickness];
- if (rightCollapsed == NO)
- oldContentWidth -= [aSplitView dividerThickness];
- CGFloat resizeFactor = contentWidth / oldContentWidth;
- leftSize.width = floor(resizeFactor * leftSize.width);
- rightSize.width = floor(resizeFactor * rightSize.width);
- }
-
- mainSize.width = contentWidth - leftSize.width - rightSize.width;
- leftSize.height = rightSize.height = mainSize.height =
NSHeight([aSplitView frame]);
- if (leftCollapsed == NO)
- [leftView setFrameSize:leftSize];
- if (rightCollapsed == NO)
- [rightView setFrameSize:rightSize];
- [mainView setFrameSize:mainSize];
- } else if ([aSplitView isEqual:pdfSplitView] && [[aSplitView subviews]
count] > 1) {
- NSView *topView = [[aSplitView subviews] objectAtIndex:0];
- NSView *bottomView = [[aSplitView subviews] objectAtIndex:1];
- NSSize topSize = [topView frame].size;
- NSSize bottomSize = [bottomView frame].size;
- CGFloat contentHeight = NSHeight([aSplitView frame]) - [aSplitView
dividerThickness];
-
- if (bottomSize.height <= 0.0 || contentHeight < titleBarHeight +
MIN_PDF_PANE_HEIGHT + MIN_SPLIT_PANE_HEIGHT) {
- topSize.height = contentHeight;
- bottomSize.height = 0.0;
- } else {
- if (rand() % 2 == 0) {
- topSize.height = floor(contentHeight * topSize.height /
(oldSize.height - [aSplitView dividerThickness]));
- bottomSize.height = contentHeight - topSize.height;
- } else {
- bottomSize.height = floor(contentHeight * bottomSize.height /
(oldSize.height - [aSplitView dividerThickness]));
- topSize.height = contentHeight - bottomSize.height;
- }
- if (bottomSize.height < MIN_SPLIT_PANE_HEIGHT) {
- bottomSize.height = MIN_SPLIT_PANE_HEIGHT;
- topSize.height = contentHeight - MIN_SPLIT_PANE_HEIGHT;
- } else if (topSize.height < titleBarHeight + MIN_PDF_PANE_HEIGHT) {
- topSize.height = titleBarHeight - MIN_PDF_PANE_HEIGHT;
- bottomSize.height = contentHeight - titleBarHeight -
MIN_PDF_PANE_HEIGHT;
- }
- }
- topSize.width = bottomSize.width = NSWidth([aSplitView frame]);
- [topView setFrameSize:topSize];
- [bottomView setFrameSize:bottomSize];
- }
- [aSplitView adjustSubviews];
-}
-
-- (void)splitViewDidResizeSubviews:(NSNotification *)notification {
- id sender = [notification object];
- if ([sender isEqual:splitView] && [[[self window] frameAutosaveName]
length] && mwcFlags.settingUpWindow == 0) {
- CGFloat leftWidth = [splitView isSubviewCollapsed:leftSideContentView]
? 0.0 : NSWidth([leftSideContentView frame]);
- CGFloat rightWidth = [splitView
isSubviewCollapsed:rightSideContentView] ? 0.0 : NSWidth([rightSideContentView
frame]);
- [[NSUserDefaults standardUserDefaults] setFloat:leftWidth
forKey:SKLeftSidePaneWidthKey];
- [[NSUserDefaults standardUserDefaults] setFloat:rightWidth
forKey:SKRightSidePaneWidthKey];
- }
-}
-
#pragma mark UI validation
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
@@ -2136,7 +1991,7 @@
}
- (void)handleNoteViewFrameDidChangeNotification:(NSNotification
*)notification {
- if (mwcFlags.autoResizeNoteRows && [splitView isAnimating] == NO) {
+ if (mwcFlags.autoResizeNoteRows) {
[rightSideController.noteOutlineView resetRowHeights];
[rightSideController.noteOutlineView
noteHeightOfRowsChangedAnimating:NO];
}
@@ -2151,6 +2006,15 @@
undoGroupOldPropertiesPerNote = nil;
}
+- (void)handleSplitViewDidResizeSubviewsNotification:(NSNotification
*)notification {
+ NSSplitViewItem *item = [[splitViewController splitViewItems] firstObject];
+ CGFloat width = [item isCollapsed] ? 0.0 : NSWidth([[[item viewController]
view] frame]);
+ [[NSUserDefaults standardUserDefaults] setFloat:width
forKey:SKLeftSidePaneWidthKey];
+ item = [[splitViewController splitViewItems] lastObject];
+ width = [item isCollapsed] ? 0.0 : NSWidth([[[item viewController] view]
frame]);
+ [[NSUserDefaults standardUserDefaults] setFloat:width
forKey:SKRightSidePaneWidthKey];
+}
+
#pragma mark Observer registration
- (void)registerForNotifications {
@@ -2177,6 +2041,10 @@
// PDFPage
[nc addObserver:self
selector:@selector(handlePageLabelsChangedNotification:)
name:SKPDFPageLabelsChangedNotification
object:nil];
+ // NSSplitView
+ if ([[[self window] frameAutosaveName] length])
+ [nc addObserver:self
selector:@selector(handleSplitViewDidResizeSubviewsNotification:)
+ name:NSSplitViewDidResizeSubviewsNotification
object:[splitViewController splitView]];
}
@end
Modified: trunk/SKRightSideViewController.m
===================================================================
--- trunk/SKRightSideViewController.m 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKRightSideViewController.m 2026-03-22 18:15:30 UTC (rev 16083)
@@ -75,6 +75,8 @@
- (void)viewDidLoad {
[super viewDidLoad];
+ [sideView setAccessibilityLabel:NSLocalizedString(@"notes pane",
@"Accessibility description")];
+
[button setHelp:NSLocalizedString(@"View Notes", @"Tool tip message")
forSegment:SKSidePaneStateNote];
[button setHelp:NSLocalizedString(@"View Snapshots", @"Tool tip message")
forSegment:SKSidePaneStateSnapshot];
Modified: trunk/SKSideViewController.h
===================================================================
--- trunk/SKSideViewController.h 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKSideViewController.h 2026-03-22 18:15:30 UTC (rev 16083)
@@ -43,6 +43,7 @@
@class SKMainWindowController, SKTopBarView;
@interface SKSideViewController : NSViewController {
+ NSView *sideView;
SKTopBarView *topBar;
NSLayoutConstraint *topConstraint;
NSSegmentedControl *button;
@@ -53,6 +54,7 @@
BOOL isAnimating;
}
+@property (nonatomic, nullable, strong) IBOutlet NSView *sideView;
@property (nonatomic, nullable, strong) IBOutlet SKTopBarView *topBar;
@property (nonatomic, nullable, strong) IBOutlet NSLayoutConstraint
*topConstraint;
@property (nonatomic, nullable, strong) IBOutlet NSSegmentedControl *button,
*alternateButton;
Modified: trunk/SKSideViewController.m
===================================================================
--- trunk/SKSideViewController.m 2026-03-22 17:27:45 UTC (rev 16082)
+++ trunk/SKSideViewController.m 2026-03-22 18:15:30 UTC (rev 16083)
@@ -50,7 +50,7 @@
@implementation SKSideViewController
-@synthesize mainController, topBar, topConstraint, button, alternateButton,
searchField, currentView;
+@synthesize mainController, sideView, topBar, topConstraint, button,
alternateButton, searchField, currentView;
@dynamic topInset, tableViews;
- (void)viewDidLoad {
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit