Browse Source

【批量处理】- 添加页眉页脚、bates码

jiajie 1 year ago
parent
commit
23d1b36294

+ 96 - 0
PDF Office/PDF Master.xcodeproj/project.pbxproj

@@ -2585,6 +2585,12 @@
 		BB853C9D2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB853C9C2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift */; };
 		BB853C9E2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB853C9C2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift */; };
 		BB853C9F2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB853C9C2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift */; };
+		BB853CAA2AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB853CA92AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift */; };
+		BB853CAB2AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB853CA92AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift */; };
+		BB853CAC2AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB853CA92AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift */; };
+		BB853CAE2AF8FA67009C20C1 /* KMHeaderFooterManagerWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB853CAD2AF8FA66009C20C1 /* KMHeaderFooterManagerWindowController.xib */; };
+		BB853CAF2AF8FA67009C20C1 /* KMHeaderFooterManagerWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB853CAD2AF8FA66009C20C1 /* KMHeaderFooterManagerWindowController.xib */; };
+		BB853CB02AF8FA67009C20C1 /* KMHeaderFooterManagerWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB853CAD2AF8FA66009C20C1 /* KMHeaderFooterManagerWindowController.xib */; };
 		BB86C1ED28F544F4005AD968 /* CPDFListView+Event.m in Sources */ = {isa = PBXBuildFile; fileRef = BB86C1EC28F544F4005AD968 /* CPDFListView+Event.m */; };
 		BB86C1EE28F544F4005AD968 /* CPDFListView+Event.m in Sources */ = {isa = PBXBuildFile; fileRef = BB86C1EC28F544F4005AD968 /* CPDFListView+Event.m */; };
 		BB86C1EF28F544F4005AD968 /* CPDFListView+Event.m in Sources */ = {isa = PBXBuildFile; fileRef = BB86C1EC28F544F4005AD968 /* CPDFListView+Event.m */; };
@@ -3226,6 +3232,21 @@
 		BBEC00E5295C4D3C00A26C98 /* KMBatesPageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEC00E4295C4D3C00A26C98 /* KMBatesPageInfoView.swift */; };
 		BBEC00E6295C4D3C00A26C98 /* KMBatesPageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEC00E4295C4D3C00A26C98 /* KMBatesPageInfoView.swift */; };
 		BBEC00E7295C4D3C00A26C98 /* KMBatesPageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEC00E4295C4D3C00A26C98 /* KMBatesPageInfoView.swift */; };
+		BBEFD0182AF9BD24003FABD8 /* KMDataVersionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0172AF9BD24003FABD8 /* KMDataVersionManager.swift */; };
+		BBEFD0192AF9BD24003FABD8 /* KMDataVersionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0172AF9BD24003FABD8 /* KMDataVersionManager.swift */; };
+		BBEFD01A2AF9BD24003FABD8 /* KMDataVersionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0172AF9BD24003FABD8 /* KMDataVersionManager.swift */; };
+		BBEFD01C2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD01B2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift */; };
+		BBEFD01D2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD01B2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift */; };
+		BBEFD01E2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD01B2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift */; };
+		BBEFD0202AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBEFD01F2AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib */; };
+		BBEFD0212AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBEFD01F2AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib */; };
+		BBEFD0222AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBEFD01F2AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib */; };
+		BBEFD0242AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0232AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift */; };
+		BBEFD0252AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0232AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift */; };
+		BBEFD0262AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0232AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift */; };
+		BBEFD0282AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0272AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift */; };
+		BBEFD0292AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0272AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift */; };
+		BBEFD02A2AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEFD0272AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift */; };
 		BBF170582AE296B90013CE02 /* KMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF170572AE296B90013CE02 /* KMView.swift */; };
 		BBF170592AE296B90013CE02 /* KMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF170572AE296B90013CE02 /* KMView.swift */; };
 		BBF1705A2AE296B90013CE02 /* KMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF170572AE296B90013CE02 /* KMView.swift */; };
@@ -4532,6 +4553,8 @@
 		BB853C942AF8DCC6009C20C1 /* KMBatchOperateRemovePasswordViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KMBatchOperateRemovePasswordViewController.xib; sourceTree = "<group>"; };
 		BB853C982AF8E39D009C20C1 /* KMRemovePasswordOperationQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMRemovePasswordOperationQueue.swift; sourceTree = "<group>"; };
 		BB853C9C2AF8E436009C20C1 /* KMBatchRemovePasswordOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchRemovePasswordOperation.swift; sourceTree = "<group>"; };
+		BB853CA92AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMHeaderFooterManagerWindowController.swift; sourceTree = "<group>"; };
+		BB853CAD2AF8FA66009C20C1 /* KMHeaderFooterManagerWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KMHeaderFooterManagerWindowController.xib; sourceTree = "<group>"; };
 		BB86C1EB28F544F4005AD968 /* CPDFListView+Event.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CPDFListView+Event.h"; sourceTree = "<group>"; };
 		BB86C1EC28F544F4005AD968 /* CPDFListView+Event.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CPDFListView+Event.m"; sourceTree = "<group>"; };
 		BB86C1F028F54535005AD968 /* CPDFListView+KeyEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CPDFListView+KeyEvent.h"; sourceTree = "<group>"; };
@@ -4761,6 +4784,11 @@
 		BBEC00D8295C39FD00A26C98 /* KMBatesPropertyInfoController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMBatesPropertyInfoController.xib; sourceTree = "<group>"; };
 		BBEC00E0295C410A00A26C98 /* KMBatesPrefixInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatesPrefixInfoView.swift; sourceTree = "<group>"; };
 		BBEC00E4295C4D3C00A26C98 /* KMBatesPageInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatesPageInfoView.swift; sourceTree = "<group>"; };
+		BBEFD0172AF9BD24003FABD8 /* KMDataVersionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMDataVersionManager.swift; sourceTree = "<group>"; };
+		BBEFD01B2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchOperateAddHeaderFooterViewController.swift; sourceTree = "<group>"; };
+		BBEFD01F2AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KMBatchOperateAddHeaderFooterViewController.xib; sourceTree = "<group>"; };
+		BBEFD0232AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchAddHeaderFooterOperation.swift; sourceTree = "<group>"; };
+		BBEFD0272AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMHeaderFooterTableCellView.swift; sourceTree = "<group>"; };
 		BBF170572AE296B90013CE02 /* KMView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMView.swift; sourceTree = "<group>"; };
 		BBF245572AE78D0300037D08 /* KMBatchOperateWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchOperateWindowController.swift; sourceTree = "<group>"; };
 		BBF2455C2AE78FF900037D08 /* KMBatchWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchWindow.swift; sourceTree = "<group>"; };
@@ -5455,6 +5483,7 @@
 		9F1F82C6292F631A0092C4B4 /* PDFTools */ = {
 			isa = PBXGroup;
 			children = (
+				BB853CA02AF8F947009C20C1 /* AddHeaderFooter */,
 				BB35C49C297535C800D46EE2 /* Redact */,
 				BB1EC7FA2967B24100EC0BC3 /* PageEdit */,
 				BBC2BCC2295DA8700036B983 /* Crop */,
@@ -8058,6 +8087,51 @@
 			path = Model;
 			sourceTree = "<group>";
 		};
+		BB853CA02AF8F947009C20C1 /* AddHeaderFooter */ = {
+			isa = PBXGroup;
+			children = (
+				BB853CA32AF8F9C4009C20C1 /* Model */,
+				BB853CA42AF8F9CF009C20C1 /* View */,
+				BB853CA22AF8F9BA009C20C1 /* VC */,
+				BB853CA12AF8F99A009C20C1 /* WindowComtroller */,
+			);
+			path = AddHeaderFooter;
+			sourceTree = "<group>";
+		};
+		BB853CA12AF8F99A009C20C1 /* WindowComtroller */ = {
+			isa = PBXGroup;
+			children = (
+				BB853CA92AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift */,
+				BB853CAD2AF8FA66009C20C1 /* KMHeaderFooterManagerWindowController.xib */,
+			);
+			path = WindowComtroller;
+			sourceTree = "<group>";
+		};
+		BB853CA22AF8F9BA009C20C1 /* VC */ = {
+			isa = PBXGroup;
+			children = (
+				BBEFD01B2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift */,
+				BBEFD01F2AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib */,
+			);
+			path = VC;
+			sourceTree = "<group>";
+		};
+		BB853CA32AF8F9C4009C20C1 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+				BBEFD0232AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift */,
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		BB853CA42AF8F9CF009C20C1 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				BBEFD0272AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
 		BB86C20628F5566C005AD968 /* AppKitCategories */ = {
 			isa = PBXGroup;
 			children = (
@@ -8263,6 +8337,7 @@
 			isa = PBXGroup;
 			children = (
 				BB8F4564295AA3ED0037EA22 /* KMHeaderFooterManager.swift */,
+				BBEFD0172AF9BD24003FABD8 /* KMDataVersionManager.swift */,
 			);
 			path = Tools;
 			sourceTree = "<group>";
@@ -9409,6 +9484,7 @@
 				9F853A052947137500DF644E /* newtab_h.pdf in Resources */,
 				9F8539FC2947137500DF644E /* throbber_waiting.png in Resources */,
 				ADBC2CFE299CA6C7006280C8 /* KMPrintDuplexPrintingSetView.xib in Resources */,
+				BBEFD0202AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib in Resources */,
 				BB65A0402AF8863F003A27A0 /* GeneralPreferences.xib in Resources */,
 				BBEC00D4295C33D600A26C98 /* KMCreateBatesController.xib in Resources */,
 				BB99ACD2292E2AEF0048AFD9 /* KMMergeCollectionViewItem.xib in Resources */,
@@ -9588,6 +9664,7 @@
 				ADE787A52AA5A833002EC85A /* KMAccountExceptionWindowController.xib in Resources */,
 				BBFBE6C528DD7B98008B2335 /* Main.storyboard in Resources */,
 				9F0201752A1B488C00C9B673 /* KMAITranslationVC.xib in Resources */,
+				BB853CAE2AF8FA67009C20C1 /* KMHeaderFooterManagerWindowController.xib in Resources */,
 				9F0201812A1BAC1600C9B673 /* KMAIRewritingVC.xib in Resources */,
 				AD85D1B02AF09C79000F4D28 /* KMHomeQuickToolsWindowCollectionViewItem.xib in Resources */,
 				ADE3C1E729A5ABC200793B13 /* KMLoginWindowController.xib in Resources */,
@@ -9644,6 +9721,7 @@
 				9FF94F1529A7476000B1EF69 /* KMDesignPropertySelector.xib in Resources */,
 				AD8810AD29A8463600178CA1 /* KMAccountInfoWindowController.xib in Resources */,
 				BBB29BCF2AEA190E005F1B6B /* KMToolbarCustomViewController.xib in Resources */,
+				BBEFD0212AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib in Resources */,
 				ADF1569829A62D31001D1018 /* KMLoginLeftImageView.xib in Resources */,
 				89316856296E45CA0073EA59 /* KMImageAccessoryController.xib in Resources */,
 				BBC3483F2955A60B008D2CD1 /* KMBackgroundPropertyInfoController.xib in Resources */,
@@ -9857,6 +9935,7 @@
 				9F0CB49329683DEE00007028 /* KMPropertiesPanelLineSubVC.xib in Resources */,
 				BB8F454B295A9CDC0037EA22 /* KMHeaderFooterListController.xib in Resources */,
 				AD85D1B12AF09C79000F4D28 /* KMHomeQuickToolsWindowCollectionViewItem.xib in Resources */,
+				BB853CAF2AF8FA67009C20C1 /* KMHeaderFooterManagerWindowController.xib in Resources */,
 				AD85D1A82AF09864000F4D28 /* KMHomeQuickToolsWindowController.xib in Resources */,
 				BB69C95D299116FD0001A9B1 /* five_line_score.pdf in Resources */,
 				8942F7FC2926089200389627 /* KMSignatureViewController.xib in Resources */,
@@ -9978,6 +10057,7 @@
 				8997012428F41AB8009AF911 /* KMLeftSideViewController.xib in Resources */,
 				ADAFDA872AEB804B00F084BC /* KMQucikToolCollectionViewItem.xib in Resources */,
 				9FBA0F0329015A82001117AF /* KMFastToolCollectionViewItem.xib in Resources */,
+				BB853CB02AF8FA67009C20C1 /* KMHeaderFooterManagerWindowController.xib in Resources */,
 				ADBC372629CA923E00D93208 /* KMComparative.plist in Resources */,
 				9FDD0FA12952FF4D000C4DAD /* global.json in Resources */,
 				89E4E73A2964148E002DBA6F /* KMAnnotationPropertiesViewController.xib in Resources */,
@@ -10086,6 +10166,7 @@
 				9FD0FA5029D43D6800F2AB0D /* KMDeviceBrowserWindowController.xib in Resources */,
 				ADC63E3C2A49813E00854E02 /* KMSubscribeSuccessWindowController.xib in Resources */,
 				AD68783A29A60FC0005B5210 /* KMLoginView.xib in Resources */,
+				BBEFD0222AF9E5BC003FABD8 /* KMBatchOperateAddHeaderFooterViewController.xib in Resources */,
 				899700ED28F3E4D3009AF911 /* MainWindowController.xib in Resources */,
 				BB65A0422AF8863F003A27A0 /* GeneralPreferences.xib in Resources */,
 				89E4E70D2963D62C002DBA6F /* KMAnnotationFontWindowController.xib in Resources */,
@@ -10340,6 +10421,7 @@
 				AD867F9C29D9853200F00440 /* KMBOTAOutlineRowView.swift in Sources */,
 				9FD0D2AB2AD5143D00DA3FF8 /* KMTableRowView.swift in Sources */,
 				BB146FDB299DC0D100784A6A /* GTLRDriveService.m in Sources */,
+				BBEFD0282AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift in Sources */,
 				F37322E7292DF9410013862C /* CPDFAnnotationModel.m in Sources */,
 				9FBA0EF92900188F001117AF /* KMFastToolCollectionView.swift in Sources */,
 				BBFE6E752930E53000142C01 /* KMMergePopoverViewController.swift in Sources */,
@@ -10617,6 +10699,7 @@
 				89D9895E28FD21E6003A3E87 /* KMAnnotationCollectionView.swift in Sources */,
 				BBD1F793296FE92500343885 /* KMPageEditSplitSettingView.swift in Sources */,
 				BB897241294C028A0045787C /* KMWatermarkAdjectiveSegementControl.swift in Sources */,
+				BBEFD01C2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift in Sources */,
 				9F3D818E29A22AD90087B5AD /* Date+KMExtensions.swift in Sources */,
 				89E4E76129656A88002DBA6F /* KMAnnotationStampViewController.m in Sources */,
 				89E4E755296427E5002DBA6F /* NSImage_SKExtensions.m in Sources */,
@@ -10706,6 +10789,7 @@
 				BB2EDF54296E815E003BCF58 /* KMPageEditBaseItemView.swift in Sources */,
 				9F1FE4EA29406E4700E952CA /* NSBezierPath+MCAdditions.m in Sources */,
 				BBCE57102A72712200508EFC /* NSWindowController+KMExtension.swift in Sources */,
+				BBEFD0182AF9BD24003FABD8 /* KMDataVersionManager.swift in Sources */,
 				BBAFFB1B29CDD19C00C56112 /* KMMergeSelect.swift in Sources */,
 				BB853C7D2AF8B5D6009C20C1 /* KMBatchOperateAddPasswordViewController.swift in Sources */,
 				ADD1B6BB29420B4A00C3FFF7 /* KMPrintPreviewView.swift in Sources */,
@@ -10744,6 +10828,7 @@
 				ADAFD9F32AE68A7400F084BC /* KMCreatPDFView.swift in Sources */,
 				BBB9B32E299A5D6D004F3235 /* GTMAppAuthFetcherAuthorization.m in Sources */,
 				BB3198162AC55E6D00107371 /* CPDFDocument+KMExtension.swift in Sources */,
+				BBEFD0242AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */,
 				894A00F22976314C0070ED83 /* KMPDFViewPanelSetViewController.swift in Sources */,
 				BB135C2A29B6CD9A00FD5965 /* KMTools.swift in Sources */,
 				89D2D2BD29486D2400BFF5FE /* KMSignatureCellView.swift in Sources */,
@@ -10898,6 +10983,7 @@
 				F3732323292DFFFE0013862C /* CPDFListView+Extension.m in Sources */,
 				BB4EEF4C2976544F003A3537 /* KMRedactAligementView.swift in Sources */,
 				9F1FE4C029406E4700E952CA /* NSWindow+CTThemed.m in Sources */,
+				BB853CAA2AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift in Sources */,
 				9F0CB48729683DC400007028 /* KMPropertiesPanelPresetColorSubVC.swift in Sources */,
 				9F1FE50229406E4700E952CA /* CTTabStripModelOrderController.m in Sources */,
 				BB49ECFE293F459500C82CA2 /* KMConvertPPTsWindowController.swift in Sources */,
@@ -11112,6 +11198,7 @@
 				ADBC373D29CA9AE100D93208 /* KMComparativeManager.swift in Sources */,
 				BB147009299DC0D100784A6A /* OIDRegistrationRequest.m in Sources */,
 				BBBB6CDB2AD15B900035AA66 /* CPDFFreeTextAnnotation+PDFListView.swift in Sources */,
+				BBEFD01D2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift in Sources */,
 				BB853C642AF87428009C20C1 /* KMBatchOperateRemoveWatermarkViewController.swift in Sources */,
 				ADAFDA3F2AE8F32400F084BC /* KMAdvertisementManager.swift in Sources */,
 				BBA19F4829AE27DA001A285A /* KMAnnotationTableRowView.swift in Sources */,
@@ -11164,6 +11251,7 @@
 				BBF8A3FE2AE8B04100788BAC /* KMBatchOperateFile.swift in Sources */,
 				ADBC375529CAE94700D93208 /* KMComparativeOutlineSectionCell.swift in Sources */,
 				BB853C7E2AF8B5D6009C20C1 /* KMBatchOperateAddPasswordViewController.swift in Sources */,
+				BBEFD0292AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift in Sources */,
 				8942F7C02923670F00389627 /* KMBOTAManagerClass.swift in Sources */,
 				ADAFDA772AEB5FCD00F084BC /* KMHomeHistoryCollectionItem.swift in Sources */,
 				BB897242294C028A0045787C /* KMWatermarkAdjectiveSegementControl.swift in Sources */,
@@ -11300,6 +11388,7 @@
 				BBFDFAA72AF3899400E08AA2 /* PasswordWindowController.swift in Sources */,
 				8942F80029260EC700389627 /* KMLeftMethodMode.swift in Sources */,
 				BB49ED1E293F4FB200C82CA2 /* KMConvertPPTsSettingView.swift in Sources */,
+				BBEFD0192AF9BD24003FABD8 /* KMDataVersionManager.swift in Sources */,
 				9FA607DA28F8227500B46586 /* KMBox.swift in Sources */,
 				BB146FD3299DC0D100784A6A /* GTLRDateTime.m in Sources */,
 				AD9527BF295294E20039D2BC /* KMPrintPageModel.swift in Sources */,
@@ -11436,6 +11525,7 @@
 				8997012028F41AB8009AF911 /* KMLeftSideViewController.swift in Sources */,
 				BBC70EB12AEA80EC00AC1585 /* KMToolbarCustomWindowController.swift in Sources */,
 				ADBC2D12299CCD05006280C8 /* KMTextfieldButton.swift in Sources */,
+				BBEFD0252AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */,
 				9F1FE49429406E4700E952CA /* common.m in Sources */,
 				BB6347C52AF24F6300F5438E /* KMBatchoperateConvertCollectionViewItem.swift in Sources */,
 				AD0FA51329A9FA8600EDEB50 /* KMResetPasswordView.swift in Sources */,
@@ -11637,6 +11727,7 @@
 				9FDD0F852952FC9C000C4DAD /* KMAliasLightParser.swift in Sources */,
 				ADBC2D38299F0A5A006280C8 /* KMPrintHelpViewController.swift in Sources */,
 				9FBC48C0299E23B100CA39D7 /* NSViewController+DesignToken.swift in Sources */,
+				BB853CAB2AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift in Sources */,
 				ADB2D6E7294740F30029D2B3 /* KMPrintPaperSetWindowController.swift in Sources */,
 				9F53D5542AD683A700CCF9D8 /* KMAnnotationPropertyBaseController.swift in Sources */,
 				BB2EDF47296E4618003BCF58 /* KMPageEditTools.swift in Sources */,
@@ -11966,6 +12057,7 @@
 				BBA19F4529ADE6A3001A285A /* KMBookMarkRowView.swift in Sources */,
 				9F0201982A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */,
 				9FDD0FAC29534FCC000C4DAD /* KMAliasLight.swift in Sources */,
+				BBEFD01A2AF9BD24003FABD8 /* KMDataVersionManager.swift in Sources */,
 				BBF38A64294F53FD0086D025 /* KMWatermarkFileView.swift in Sources */,
 				899700F828F4051B009AF911 /* KMAnnotationViewController.swift in Sources */,
 				BBDA8A6F2A31F9A6006A2C4E /* KMDesignStepperView.swift in Sources */,
@@ -11988,6 +12080,7 @@
 				BB8F4578295AFA2D0037EA22 /* KMHeaderFooterAdjectiveInfoBaseView.swift in Sources */,
 				F3F0B27529B8ACD000722957 /* CPDFListViewDragObject.m in Sources */,
 				F34BF9552953DA91002C25A2 /* NSGeometry+PDFListView.m in Sources */,
+				BB853CAC2AF8FA46009C20C1 /* KMHeaderFooterManagerWindowController.swift in Sources */,
 				BB897230294B08DE0045787C /* KMWatermarkViewController.swift in Sources */,
 				BB8B17342907B63D001C5EA5 /* CipherTextView.swift in Sources */,
 				ADBC375229CAE27900D93208 /* KMComparativeOutlineRowView.swift in Sources */,
@@ -12003,6 +12096,7 @@
 				BB6DD80E29347F77001F0544 /* KMSecureEncryptWindowController.swift in Sources */,
 				AD53B70029AC5FCD00D61E81 /* KMLightMemberToken.swift in Sources */,
 				9F1FE4A129406E4700E952CA /* HoverButton.m in Sources */,
+				BBEFD0262AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */,
 				BB8F4580295B00130037EA22 /* KMWatermarkAdjectiveTools.swift in Sources */,
 				BBB9B312299A5D6D004F3235 /* KMCloudDownloadOperationQueue.m in Sources */,
 				BB147046299DC0D200784A6A /* OIDURLQueryComponent.m in Sources */,
@@ -12065,6 +12159,7 @@
 				BBD7FE062A1323F000F96075 /* KMCustomTableRowView.swift in Sources */,
 				9F0CB4C6298625F400007028 /* NSColor+KMExtensions.swift in Sources */,
 				BBC745F4295F0DD00072C2ED /* KMCropSettingPageSizeView.swift in Sources */,
+				BBEFD01E2AF9E5AA003FABD8 /* KMBatchOperateAddHeaderFooterViewController.swift in Sources */,
 				9F1FE50729406E4700E952CA /* CTTabStripDragController.m in Sources */,
 				BB65A0562AF8B90F003A27A0 /* KMDisplayPreferences.swift in Sources */,
 				BB146FEC299DC0D100784A6A /* GTLRDuration.m in Sources */,
@@ -12504,6 +12599,7 @@
 				9F0CB4A9296CF19600007028 /* KMPropertiesPanelListMenuSubVC.swift in Sources */,
 				BBB5C80929F4CEE40054F261 /* KMLinkAnnotationPropertyEmptyController.swift in Sources */,
 				BB3AAB9B2987BEA900992A5A /* KMWatermarkPDFView_OC.m in Sources */,
+				BBEFD02A2AFA285A003FABD8 /* KMHeaderFooterTableCellView.swift in Sources */,
 				BBC3482629559506008D2CD1 /* KMBackgroundManager.swift in Sources */,
 				BBCE57162A72713A00508EFC /* NSViewController+KMExtension.swift in Sources */,
 				BB146FB6299DC0D100784A6A /* GTLRUtilities.m in Sources */,

+ 15 - 0
PDF Office/PDF Master.xcodeproj/xcuserdata/kdanmobile.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -273,6 +273,21 @@
                   endingLineNumber = "332"
                   offsetFromSymbolStart = "299">
                </Location>
+               <Location
+                  uuid = "4AA5DDA9-7119-40D7-89B4-F368372F819A - 89e3ff688b88713e"
+                  shouldBeEnabled = "Yes"
+                  ignoreCount = "0"
+                  continueAfterRunningActions = "No"
+                  symbolName = "PDF_Master.KMEditPDFTextManager.setFontAlignment(alignment: __C.NSTextAlignment) -&gt; ()"
+                  moduleName = "PDF Master"
+                  usesParentBreakpointCondition = "Yes"
+                  urlString = "file:///Users/kdanmobile/PDF_Office/PDF%20Office/PDF%20Master/Class/PDFWindowController/Side/RightSide/EditPDF/Manager/KMEditPDFTextManager.swift"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  startingLineNumber = "332"
+                  endingLineNumber = "332"
+                  offsetFromSymbolStart = "192">
+               </Location>
             </Locations>
          </BreakpointContent>
       </BreakpointProxy>

+ 21 - 10
PDF Office/PDF Master/Class/Batch/WindowController/KMBatchOperateRightViewController.swift

@@ -42,9 +42,20 @@ class KMBatchOperateRightViewController: NSViewController{
         vc.isBackground = true
         return vc
     }()
-    //    var addHeaderFooterViewController: KMBatchOperateAddHeaderFooterViewController?
+    lazy var addHeaderFooterViewController: KMBatchOperateAddHeaderFooterViewController? = {
+        let vc = KMBatchOperateAddHeaderFooterViewController(files: self.files)
+        vc.operateType = .AddHeaderFooter
+        vc.isBatchOperation = true
+        return vc
+    }()
     //    var removeHeaderFooterViewController: KMBatchOperateRemoveHeaderFooterViewController?
-    //    var addBatesViewController: KMBatchOperateAddHeaderFooterViewController?
+    lazy var addBatesViewController: KMBatchOperateAddHeaderFooterViewController? = {
+        let vc = KMBatchOperateAddHeaderFooterViewController(files: self.files)
+        vc.operateType = .AddBates
+        vc.isBates = true
+        vc.isBatchOperation = true
+        return vc
+    }()
     //    var removeBatesViewController: KMBatchOperateRemoveHeaderFooterViewController?
     lazy var addPasswordViewController: KMBatchOperateAddPasswordViewController? = {
         let vc = KMBatchOperateAddPasswordViewController(files: self.files)
@@ -98,20 +109,20 @@ class KMBatchOperateRightViewController: NSViewController{
                         make?.edges.equalTo()(self.view)
                     })
                 } else if _currentType == .AddHeaderFooter {
-//                    self.view.addSubview(self.addHeaderFooterViewController.view)
-//                    self.addHeaderFooterViewController?.view.mas_makeConstraints({ make in
-//                        make?.edges.equalTo()(self.view)
-//                    })
+                    self.view.addSubview(self.addHeaderFooterViewController!.view)
+                    self.addHeaderFooterViewController?.view.mas_makeConstraints({ make in
+                        make?.edges.equalTo()(self.view)
+                    })
                 } else if _currentType == .RemoveHeaderFooter {
 //                    self.view.addSubview(self.removeHeaderFooterViewController.view)
 //                    self.removeHeaderFooterViewController?.view.mas_makeConstraints({ make in
 //                        make?.edges.equalTo()(self.view)
 //                    })
                 } else if _currentType == .AddBates {
-//                    self.view.addSubview(self.addBatesViewController.view)
-//                    self.addBatesViewController?.view.mas_makeConstraints({ make in
-//                        make?.edges.equalTo()(self.view)
-//                    })
+                    self.view.addSubview(self.addBatesViewController!.view)
+                    self.addBatesViewController?.view.mas_makeConstraints({ make in
+                        make?.edges.equalTo()(self.view)
+                    })
                 } else if _currentType == .RemoveBates {
 //                    self.view.addSubview(self.removeBatesViewController.view)
 //                    self.removeBatesViewController?.view.mas_makeConstraints({ make in

+ 290 - 0
PDF Office/PDF Master/Class/PDFTools/AddHeaderFooter/Model/KMBatchAddHeaderFooterOperation.swift

@@ -0,0 +1,290 @@
+//
+//  KMBatchAddHeaderFooterOperation.swift
+//  PDF Master
+//
+//  Created by liujiajie on 2023/11/7.
+//
+
+import Foundation
+
+let supportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last
+let mainBundleIdentifier = Bundle.main.bundleIdentifier ?? ""
+let kTempSavePath = supportDirectory?.stringByAppendingPathComponent(mainBundleIdentifier)
+
+class KMBatchAddHeaderFooterOperation: KMBatchOperation{
+    var headerFooter: KMHeaderFooterObject?
+    var pdfDocument: CPDFDocument?
+    var password: String?
+    
+    init(file: KMBatchOperateFile, headerFooter: KMHeaderFooterObject) {
+        super.init(file: file)
+        self.headerFooter = headerFooter
+        self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: file.filePath))
+        self.password = file.password
+        if ((self.pdfDocument?.isLocked) != nil) {
+            self.pdfDocument?.unlock(withPassword: file.password)
+        }
+    }
+    func currentParameter() -> KMBatchBaseParameter {
+        if ((headerFooter?.isBates) != nil) {
+            return operateFile!.addBatesInfo
+        }
+        return operateFile!.addHeaderFooterInfo
+    }
+    override func start() {
+        if !self.isCancelled {
+            self.delegate?.fileBeginOperate?(self.operateFile!, info: self.currentParameter())
+            willChangeValue(forKey: "isExecuting")
+            self.hasExcuting = true
+            didChangeValue(forKey: "isExecuting")
+            if !FileManager.default.fileExists(atPath: self.operateFile!.filePath) {
+                self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("File Not Exist", nil)), info: self.operateFile!.removeBatesInfo)
+                
+                self.willChangeValue(forKey: "isFinished")
+                self.hasFinished = true
+                self.didChangeValue(forKey: "isFinished")
+                return
+            }
+            
+            if self.pdfDocument == nil {
+                self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", nil)), info: self.operateFile!.removeWatermarkInfo)
+                self.willChangeValue(forKey: "isFinished")
+                self.hasFinished = true
+                self.didChangeValue(forKey: "isFinished")
+                return
+            }
+            
+            if !self.pdfDocument!.allowsPrinting || !self.pdfDocument!.allowsCopying {
+                self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("This is a secured document. Editing is not permitted.", nil)), info: self.operateFile!.removeWatermarkInfo)
+                self.willChangeValue(forKey: "isFinished")
+                self.hasFinished = true
+                self.didChangeValue(forKey: "isFinished")
+                return
+            }
+            self.saveAsPDFToPath((self.operateFile?.currentOperateInfo?.fetchDestinationFilepath())!)
+            
+        }else {
+            willChangeValue(forKey: "isFinished")
+            willChangeValue(forKey: "isExecuting")
+            hasExcuting = false
+            hasFinished = true
+            didChangeValue(forKey: "isExecuting")
+            didChangeValue(forKey: "isFinished")
+        }
+    }
+    override func cancel() {
+        //        super.cancel()
+        if isExecuting {
+            operateFile!.removeWatermarkInfo.status = .Waiting
+            if FileManager.default.fileExists(atPath: self.currentParameter().outPutPath!) { try? FileManager.default.removeItem(atPath: self.currentParameter().outPutPath!)
+            }
+            self.delegate?.fileOperateCanceled?(self.operateFile!, info: self.currentParameter())
+            
+            willChangeValue(forKey: "isFinished")
+            hasFinished = true
+            didChangeValue(forKey: "isFinished")
+        } else {
+            willChangeValue(forKey: "isCancelled")
+            hasCanceled = true
+            didChangeValue(forKey: "isCancelled")
+        }
+    }
+    
+    func saveAsPDFToPath(_ path: String) {
+        var filePath = self.pdfDocument?.documentURL?.path
+        let password = self.password
+        if filePath == nil {
+            var str = String(format: "%@.pdf", KMLocalizedString("Untitled", nil))
+            let writeSuccess = self.pdfDocument!.write(to: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!))
+            if writeSuccess {
+                let newDocument: CPDFDocument = CPDFDocument(url: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!))
+                if #available(macOS 13.0, *) {
+                    filePath = newDocument.documentURL?.path()
+                } else {
+                    // Fallback on earlier versions
+                }
+            } else {
+                NSSound.beep()
+                return
+            }
+        }
+        
+        guard let document = CPDFDocument(url: URL(fileURLWithPath: filePath!)) else {
+            return
+        }
+        
+        if let password = password {
+            document.unlock(withPassword: password)
+        }
+        
+        let font = NSFont.boldSystemFont(ofSize: self.headerFooter?.fontSize ?? 16.0)
+        let style = NSMutableParagraphStyle()
+        style.alignment = .center
+        style.lineBreakMode = .byCharWrapping
+        var dictionary = [NSAttributedString.Key: Any]()
+        dictionary[.paragraphStyle] = style
+        dictionary[.font] = font
+        let size = "text".boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: dictionary).size
+        
+        if ((self.headerFooter?.isBates) != nil) {
+            var bates: CPDFHeaderFooter = document.bates()
+            bates.margin = NSEdgeInsets(top: max(CGFloat(self.headerFooter!.topMargin) - size.height, 0), left: CGFloat(self.headerFooter!.leftMargin), bottom: max(CGFloat(self.headerFooter!.bottomMargin) - size.height, 0), right: CGFloat(self.headerFooter!.rightMargin))
+            
+            var arr = [NSNumber]()
+            for i in 0..<(self.operateFile?.addBatesInfo.pagesArray?.count ?? 0) {
+                var tmp = self.operateFile?.addBatesInfo.pagesArray?[i].intValue
+                tmp! -= 1
+                let number = NSNumber(value: tmp ?? 0)
+                arr.append(number)
+            }
+            if arr.count < 1 {
+                let error = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil)])
+                self.delegate?.fileOperateFailed?(self.operateFile!, error: error, info: self.operateFile!.addBatesInfo)
+                
+                willChangeValue(forKey: "isFinished")
+                self.hasFinished = true
+                didChangeValue(forKey: "isFinished")
+                return
+            }
+            let pagesString = arr.map{ "\($0)" }.joined(separator: ",")
+            if pagesString.count > 0 {
+                bates.pageString = pagesString
+            } else {
+                let pageString = String(format: "0-%ld", document.pageCount-1)
+                bates.pageString = pageString
+            }
+            
+            let topLeftString = self.headerFooter?.topLeftString
+            let topCenterString = self.headerFooter?.topCenterString
+            let topRightString = self.headerFooter?.topRightString
+            let bottomLeftString = self.headerFooter?.bottomLeftString
+            let bottomCenterString = self.headerFooter?.bottomCenterString
+            let bottomRightString = self.headerFooter?.bottomRightString
+            let items = [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
+            for i in 0..<items.count {
+                let text = items[i]
+                bates.setText(text, at: UInt(Int(i)))
+                bates.setTextColor(self.headerFooter?.textColor, at: UInt(Int(i)))
+                bates.setFontSize(self.headerFooter?.fontSize ?? 16.0, at: UInt(Int(i)))
+            }
+            
+            bates.update()
+        } else {
+            let headerFooterNew = document.headerFooter()
+            headerFooterNew?.margin = NSEdgeInsets(top: max(CGFloat(self.headerFooter!.topMargin)-size.height, 0), left: CGFloat(self.headerFooter!.leftMargin), bottom: max(CGFloat(self.headerFooter!.bottomMargin)-size.height, 0), right: CGFloat(self.headerFooter!.rightMargin))
+            
+            var arr = [NSNumber]()
+            for i in 0..<(self.operateFile?.addHeaderFooterInfo.pagesArray?.count ?? 0) {
+                var tmp = self.operateFile?.addHeaderFooterInfo.pagesArray?[i].intValue
+                tmp! -= 1
+                let number = NSNumber(value: tmp ?? 0)
+                arr.append(number)
+            }
+            if arr.count < 1 {
+                let error = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil)])
+                self.delegate?.fileOperateFailed?(self.operateFile!, error: error, info: self.operateFile!.addHeaderFooterInfo)
+                willChangeValue(forKey: "isFinished")
+                self.hasFinished = true
+                didChangeValue(forKey: "isFinished")
+                return
+            }
+            let pagesString = arr.map{ "\($0)" }.joined(separator: ",")
+            if pagesString.count > 0 {
+                headerFooterNew?.pageString = pagesString
+            } else {
+                let pageString = String(format: "0-%ld", document.pageCount-1)
+                headerFooterNew?.pageString = pageString
+            }
+            let num: Int = Int(self.headerFooter?.startString ?? "0") ?? 0
+            let pageCount = Int(document.pageCount) + num - 1
+            
+            let topLeftString = convertPageFormat(oldString: self.headerFooter!.topLeftString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
+            let topCenterString = convertPageFormat(oldString: self.headerFooter!.topCenterString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
+            let topRightString = convertPageFormat(oldString: self.headerFooter!.topRightString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
+            let bottomLeftString = convertPageFormat(oldString: self.headerFooter!.bottomLeftString, startPage: self.headerFooter!.startString, pageCount: "\(pageCount)")
+            let bottomCenterString = convertPageFormat(oldString: self.headerFooter!.bottomCenterString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
+            let bottomRightString = convertPageFormat(oldString: self.headerFooter!.bottomRightString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
+            let items = [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
+            for i in 0..<items.count {
+                let text = items[i]
+                headerFooterNew?.setText(text, at: UInt(i))
+                headerFooterNew?.setTextColor(self.headerFooter!.textColor, at: UInt(Int(i)))
+                headerFooterNew?.setFontSize(self.headerFooter!.fontSize, at: UInt(Int(i)))
+            }
+            
+            headerFooterNew?.update()
+        }
+        
+        let documentPath = NSTemporaryDirectory()
+        let tempPath = documentPath.appending(filePath!.lastPathComponent)
+        if FileManager.default.fileExists(atPath: tempPath) {
+            try? FileManager.default.removeItem(atPath: tempPath)
+        }
+        
+        let result = document.write(to: URL(fileURLWithPath: tempPath))
+        if result {
+            if FileManager.default.fileExists(atPath: path) {
+                try? FileManager.default.removeItem(atPath: path)
+            }
+            try? FileManager.default.moveItem(atPath: tempPath, toPath: path)
+        } else {
+            try? FileManager.default.removeItem(atPath: tempPath)
+        }
+        if result {
+            self.delegate?.fileOperateSuccessed?(self.operateFile!, info: self.currentParameter())
+        } else {
+            self.delegate?.fileOperateFailed?(self.operateFile!, error: self.defaultError(), info: self.currentParameter())
+        }
+        
+        willChangeValue(forKey: "isFinished")
+        self.hasFinished = true
+        didChangeValue(forKey: "isFinished")
+    }
+    func defaultError() -> NSError {
+        return errorWithMsg(NSLocalizedString("Failed", comment: ""))
+    }
+}
+
+func convertPageFormat(oldString: String, startPage: String, pageCount: String) -> String {
+    let pageFormatArray = ["1", "1 of n", "1/n", "Page 1", "Page 1 of n"]
+    var newString = oldString
+    for pageFormat in pageFormatArray {
+        let format = "<<(pageFormat)>>"
+        if newString.contains(format) {
+            var tString: String? = nil
+            if pageFormat == "1" {
+                tString = "<<\(startPage)>>"
+            } else if pageFormat == "1 of n" {
+                tString = "\(startPage) of \(pageCount)"
+            } else if pageFormat == "1/n" {
+                tString = "\(startPage)/\(pageCount)"
+            } else if pageFormat == "Page 1" {
+                tString = "Page <<\(startPage)>>"
+            } else if pageFormat == "Page 1 of n" {
+                tString = "Page <<\(startPage)>> of \(pageCount)"
+            }
+            
+            newString = newString.replacingOccurrences(of: format, with: tString ?? "")
+        }
+    }
+    
+    newString = convertDateFormat(oldString: newString)
+    return newString
+}
+func convertDateFormat(oldString: String) -> String { 
+    var newString = oldString
+    for dateFormat in KMHeaderFooterManager.defaultManager.dateFormatArray {
+        if newString.contains(dateFormat) {
+            let formatString = dateFormat.replacingOccurrences(of: "m", with: "M")
+            let replace = "<<\(dateFormat)>>"
+            
+            let date = Date()
+            let dateFormatter = DateFormatter()
+            dateFormatter.dateFormat = formatString
+            let dateString = dateFormatter.string(from: date)
+            newString = newString.replacingOccurrences(of: replace, with: dateString)
+        }
+    }
+    
+    return newString
+}

+ 497 - 0
PDF Office/PDF Master/Class/PDFTools/AddHeaderFooter/VC/KMBatchOperateAddHeaderFooterViewController.swift

@@ -0,0 +1,497 @@
+//
+//  KMBatchOperateAddHeaderFooterViewController.swift
+//  PDF Master
+//
+//  Created by liujiajie on 2023/11/7.
+//
+
+import Cocoa
+
+class KMBatchOperateAddHeaderFooterViewController: KMBatchOperateBaseViewController, NSTableViewDelegate,NSTableViewDataSource{
+    var isBates = false
+    var onlyManagerTemplate = false
+    var isBatchOperation = false
+    var pdfView: PDFView?
+    
+    @IBOutlet var topBaseView: NSView!
+    @IBOutlet var bottomBaseView: NSView!
+    @IBOutlet var tableView: NSTableView!
+    @IBOutlet var titleLabel: NSTextField!
+    @IBOutlet var actionButton: NSButton!
+    @IBOutlet var managerTemplateTitleLabel: NSTextField!
+    @IBOutlet var addButton: NSButton!
+    @IBOutlet var blankView: KMBlankView!
+    
+    @IBOutlet var managerTemplateTopConstraint: NSLayoutConstraint!
+    
+    @IBOutlet var managerTemplateButtonHeightConstraint: NSButton!
+    @IBOutlet var topHeightConstraint: NSLayoutConstraint!
+    
+    var haveFiles = false
+    var currentObject: KMHeaderFooterObject?
+    
+    override var interfaceStatus: KMBatchOperateInterfaceStatus?{
+        set{
+            super.interfaceStatus = newValue
+            if newValue == .PrepareProcess {
+                DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
+                    let files = NSMutableArray()
+                    for url in self.successFilePathURLArray! {
+                        if FileManager.default.fileExists(atPath: url.path) {
+                            files.add(url)
+                        }
+                    }
+                    if files.count > 0 {
+                        let workspace = NSWorkspace.shared
+                        workspace.activateFileViewerSelecting(files as! [URL])
+                    }
+                }
+                self.actionButton.tag = 1
+                self.actionButton.title = KMLocalizedString("Apply", nil)
+                self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
+            } else {
+                self.actionButton.tag = 0
+                self.actionButton.title = KMLocalizedString("Cancel", nil)
+                self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
+            }
+        }
+        get{
+            return super.interfaceStatus
+        }
+    }
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        localizedLanguage()
+        configuInterface()
+        NotificationCenter.default.addObserver(self, selector: #selector(headerFootersNotification(notification:)), name: Notification.Name(rawValue: "KMBatchOperateHeaderFootersNotification"), object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: Notification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(batchFilesCountNotification(notification:)), name: NSNotification.Name("KMBatchFilesCountNotification"), object: nil)
+    }
+    func localizedLanguage() {
+        self.addButton.title = KMLocalizedString("Add Template", nil)
+        self.actionButton.title = KMLocalizedString("Apply", nil)
+        self.titleLabel.stringValue = KMLocalizedString("Apply", nil)
+    }
+    func configuInterface() {
+        self.titleLabel.font = NSFont.systemFont(ofSize: 14)
+        self.titleLabel.textColor = KMAppearance.Layout.h0Color()
+        self.tableView.enclosingScrollView?.borderType = .noBorder
+        self.actionButton.wantsLayer = true
+        self.addButton.wantsLayer = true
+        
+        self.topHeightConstraint.constant = 0
+        self.topBaseView.isHidden = true
+        self.addButton.imagePosition = .imageLeft
+        self.addButton.image = NSImage(named: "KMImageNameHeaderFooterAddBtn")
+        self.addButton.layer?.backgroundColor = KMAppearance.Interactive.s0Color().cgColor
+        self.addButton.setTitleColor(KMAppearance.Layout.h0Color())
+        
+        
+        self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
+        self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
+        self.actionButton.imagePosition = .noImage
+        if !self.onlyManagerTemplate {
+            if self.files?.count ?? 0 > 0 {
+                self.haveFiles = true
+            } else {
+                self.haveFiles = false
+            }
+        } else {
+            self.haveFiles = true
+        }
+        updateActionButtonbackgroundColor()
+        
+        self.addButton.layer?.cornerRadius = 1.0
+        self.actionButton.layer?.cornerRadius = 1.0
+        
+        self.topBaseView.wantsLayer = true
+        self.topBaseView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor
+        self.bottomBaseView.wantsLayer = true
+        self.bottomBaseView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor
+        self.managerTemplateTitleLabel.font = NSFont.systemFont(ofSize: 14)
+        self.managerTemplateTitleLabel.textColor = KMAppearance.Layout.h0Color()
+        
+        self.titleLabel.isHidden = false
+        self.addButton.isHidden = false
+        self.managerTemplateTitleLabel.isHidden = true
+        
+        self.managerTemplateTitleLabel.stringValue = NSLocalizedString("Manage Templates", comment: "")
+        
+        self.view.addSubview(self.blankView)
+        self.blankView.mas_makeConstraints { make in
+            make?.top.equalTo()(self.topBaseView.mas_bottom)
+            make?.left.equalTo()(self.view)
+            make?.right.equalTo()(self.view)
+            make?.bottom.equalTo()(self.bottomBaseView.mas_top)
+            make?.height.greaterThanOrEqualTo()(200)
+        }
+        
+        self.blankView.titleLabel.stringValue = KMLocalizedString("No Templates", nil)
+        
+        self.tableView.backgroundColor = KMAppearance.Layout.l0Color()
+        
+        let menu = NSMenu(title: "")
+        if !self.isBatchOperation && !self.isBates {
+            menu.addItem(withTitle: NSLocalizedString("Batch Add Header & Footer", comment: ""), action: #selector(buttonItemClick_addBatch(_:)), keyEquivalent: "")
+        } else if !self.isBatchOperation && self.isBates {
+            menu.addItem(withTitle: NSLocalizedString("Batch Add Bates Numbers", comment: ""), action: #selector(buttonItemClick_addBatch(_:)), keyEquivalent: "")
+        }
+        if !self.isBates {
+            menu.addItem(withTitle: NSLocalizedString("Remove All Header & Footer Templates", comment: ""), action: #selector(buttonItemClick_CleanAll(_:)), keyEquivalent: "")
+        } else {
+            menu.addItem(withTitle: NSLocalizedString("Remove All Bates Numbers Templates", comment: ""), action: #selector(buttonItemClick_CleanAll(_:)), keyEquivalent: "")
+        }
+        self.view.menu = menu
+        
+        updateViewColor()
+    }
+    func updateActionButtonbackgroundColor() {
+        let row = self.tableView.selectedRow 
+        if (self.files?.count ?? 0 > 0 || self.pdfView != nil) && row > -1 {
+            self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
+            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
+        } else {
+            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color().withAlphaComponent(0.6))
+            self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().withAlphaComponent(0.6).cgColor
+        }
+    }
+    @objc func buttonItemClick_addBatch(_ sender: Any) {
+        let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController")
+        if #available(macOS 10.13, *) {
+            baseWindowController.window?.makeKeyAndOrderFront(nil)
+        } else {
+            baseWindowController.showWindow(nil)
+        }
+        var arr = NSMutableArray()
+        let file = KMBatchOperateFile(filePath: self.pdfView!.document!.documentURL!.path, type: self.isBates ? .AddBates : .AddHeaderFooter)
+        arr.add(file)
+        baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: self.isBates ? .AddBates : .AddHeaderFooter, files: arr as! [KMBatchOperateFile])
+    }
+    @objc func buttonItemClick_CleanAll(_ sender: Any) {
+        let alert = NSAlert()
+        alert.alertStyle = .warning
+        alert.messageText = ""
+        alert.informativeText = NSLocalizedString("Are you sure to delete all templates?", comment: "")
+        alert.addButton(withTitle: NSLocalizedString("Delete", comment: ""))
+        alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
+        alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
+            if response == .alertFirstButtonReturn {
+                self.deleteAll()
+            }
+        }
+    }
+    @objc func headerFootersNotification(notification: Notification) {
+        if let addHeaderFooter = notification.object as? KMBatchOperateAddHeaderFooterViewController {
+            if self != addHeaderFooter {
+                loadData()
+            }
+        }
+    }
+    @objc func themeChanged(notification: Notification) {
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+            self.updateViewColor()
+        }
+    }
+    @objc func batchFilesCountNotification(notification: Notification)  {
+        let files = notification.object as? [Any]
+        if files?.count ?? 0 > 0 {
+            haveFiles = true
+        } else {
+            haveFiles = false
+        }
+        updateActionButtonbackgroundColor()
+    }
+    func loadData() {
+        self.tableView.reloadData()
+    }
+    func updateViewColor() {
+        if KMAppearance.isDarkMode() {
+            self.bottomBaseView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor
+            self.addButton.layer?.backgroundColor = NSColor(red: 0.337, green: 0.345, blue: 0.353, alpha: 1).cgColor
+            self.addButton.setTitleColor(NSColor.white)
+            self.actionButton.layer?.backgroundColor = NSColor(red: 0.306, green: 0.498, blue: 0.859, alpha: 1).cgColor
+            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
+        } else {
+            self.bottomBaseView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1.000, alpha: 1).cgColor
+            self.addButton.layer?.backgroundColor = NSColor(red: 0.855, green: 0.859, blue: 0.871, alpha: 1).cgColor
+            self.addButton.setTitleColor(NSColor(red: 0.055, green: 0.067, blue: 0.078, alpha: 1))
+            self.actionButton.layer?.backgroundColor = NSColor(red: 0.153, green: 0.235, blue: 0.384, alpha: 1).cgColor
+            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
+        }
+    }
+    func deleteAll() {
+        if self.isBates {
+            for waterMark in KMHeaderFooterManager.defaultManager.onlyBatesObjects {
+                KMHeaderFooterManager.defaultManager.removeHeaderFooter(waterMark)
+            }
+        } else {
+            for waterMark in KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects {
+                KMHeaderFooterManager.defaultManager.removeHeaderFooter(waterMark)
+            }
+        }
+        loadData()
+        reloadTable()
+        postNotification()
+    }
+    func reloadTable() {
+        self.tableView.noteNumberOfRowsChanged()
+        var count = 0
+        var array: [KMHeaderFooterObject] = []
+        if self.isBates {
+            count = KMHeaderFooterManager.defaultManager.onlyBatesObjects.count
+            array = KMHeaderFooterManager.defaultManager.onlyBatesObjects
+        } else {
+            count = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.count
+            array = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects
+        }
+        if array.contains(self.currentObject!) {
+            let row = array.firstIndex(of: self.currentObject!)!
+            let indexSet = IndexSet(integer: row)
+            self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
+        }
+        updateActionButtonbackgroundColor()
+    }
+    func postNotification() {
+        NotificationCenter.default.post(name: NSNotification.Name("KMBatchOperateHeaderFootersNotification"), object: self)
+    }
+    
+    @IBAction func buttonClicked_AddHeaderFooter(_ sender: Any) {
+//        guard let windowController = self.view.window?.windowController else { return }
+//        var filePath: String?
+//        var password: String?
+//        if let mainWC = windowController as? MainWindowController {
+//            //            filePath = mainWC.pdfView?.document?.documentURL?.path
+//            //            password = (mainWC.pdfView?.document as? CPDFDocument)?.password
+//        }
+//        let wc = KMHeaderFooterManagerWindowController(baseFile: filePath, headerFooter: nil, password: password, type: .KMBatchModifyTemplateType_Add)
+//        wc.isBates = self.isBates
+//        wc.operateCallBack = { [weak self] obj in
+//            self?.currentObject = obj
+//            self?.loadData()
+//            self?.postNotification()
+//            DispatchQueue.main.async {
+//                guard let strongSelf = self else {
+//                    return
+//                }
+//                strongSelf.tableView.selectRowIndexes(IndexSet(integer: 0), byExtendingSelection: false)
+//            }
+//        }
+//        wc.beginSheetModal(for: NSApp.keyWindow!, completionHandler: nil)
+    }
+    
+    @IBAction func buttonClicked_Action(_ sender: Any) {
+        
+    }
+    func checkAndResetTask() -> Bool {
+        if files?.count ?? 0 < 1 {
+            return false
+        }
+        for i in 0..<(files?.count ?? 0) {
+            if let file = files?[i] as? KMBatchOperateFile {
+                if isBates {
+                    file.addBatesInfo.resetState()
+                } else {
+                    file.addHeaderFooterInfo.resetState()
+                }
+            }
+        }
+        return true
+    }
+    func choosePathAndBeginOperation(_ obj: Any) {
+        let openPanel = NSOpenPanel()
+        openPanel.canChooseFiles = false
+        openPanel.canChooseDirectories = true
+        openPanel.canCreateDirectories = true
+        openPanel.beginSheetModal(for: self.view.window!) { (result) in
+            if result == NSApplication.ModalResponse.OK {
+                for fileURL in openPanel.urls {
+                    self.choosePath = fileURL.path
+                    if self.isBates {
+                        self.beginAddBates(obj as! KMHeaderFooterObject)
+                    } else {
+                        self.beginAddHeaderFooter(obj as! KMHeaderFooterObject)
+                    }
+                }
+            }
+        }
+    }
+    func beginAddBates(_ bates: KMHeaderFooterObject) {
+        hiddenWindowCloseButtonIfNeeded()
+        successFilePathURLArray?.removeAll()
+        for i in 0..<(files?.count ?? 0) {
+            if let file = files?[i] as? KMBatchOperateFile {
+                if file.fileType == .PDF {
+                    file.addBatesInfo.savePath = choosePath
+                    if file.status == .Waiting {
+                        let operation = KMBatchAddHeaderFooterOperation(file: file, headerFooter: bates)
+                        operation.delegate = self
+                        queue?.addOperation(operation)
+                    }
+                }
+            }
+        }
+        if queue?.operationCount ?? 0 > 0 {
+            interfaceStatus = .Processing
+        }
+    }
+    func beginAddHeaderFooter(_ headerFooter: KMHeaderFooterObject) {
+        hiddenWindowCloseButtonIfNeeded()
+        successFilePathURLArray?.removeAll()
+        for i in 0..<(files?.count ?? 0) {
+            if let file = files?[i] as? KMBatchOperateFile {
+                if file.fileType == .PDF {
+                    file.addHeaderFooterInfo.savePath = choosePath
+                    if file.status == .Waiting {
+                        let operation = KMBatchAddHeaderFooterOperation(file: file, headerFooter: headerFooter)
+                        operation.delegate = self
+                        queue?.addOperation(operation)
+                    }
+                }
+            }
+        }
+        if queue?.operationCount ?? 0 > 0 {
+            interfaceStatus = .Processing
+        }
+    }
+    func modify(obj: KMHeaderFooterObject) {
+//        let windowController = self.view.window?.windowController
+//        var filePath: String? = nil
+//        var password: String? = nil
+//        if let mainWindowController = windowController as? MainWindowController {
+//            filePath = mainWindowController.mainViewController.listView?.document?.documentURL?.path
+//            let document = mainWindowController.mainViewController.listView?.document as? CPDFDocument
+//            password = document?.password
+//        }
+//        let wc = KMHeaderFooterManagerWindowController(baseFile: filePath, headerFooter: obj, password: password, type: .KMBatchModifyTemplateType_Edit)
+//        wc?.isBates = self.isBates
+//        let blockSelf = self
+//        wc?.operateCallBack = { obj in
+//            blockSelf.currentObject = obj
+//            blockSelf.loadData()
+//            blockSelf.reloadTable()
+//            blockSelf.postNotification()
+//        }
+//        wc?.beginSheetModalForWindow(NSApp.keyWindow, completionHandler: nil)
+    }
+    func delete(obj: KMHeaderFooterObject) {
+        KMHeaderFooterManager.defaultManager.removeHeaderFooter(obj)
+        loadData()
+        reloadTable()
+        postNotification()
+    }
+    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+        let action = menuItem.action
+        if action == #selector(buttonItemClick_CleanAll(_:)) {
+            if (self.isBates && KMHeaderFooterManager.defaultManager.onlyBatesObjects.count < 1) || (!self.isBates && KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.count < 1){
+                return false
+            }
+            return true
+        }
+        return true
+    }
+    func headerFooterInterfaceSelectHeaderFooter(headerFooter: KMHeaderFooterObject) {
+        self.tableView.reloadData()
+        if let index = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.index(of: headerFooter) {
+            let indexSet = IndexSet(integer: index)
+            self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
+        }
+    }
+    func batesInterfaceSelectBates(headerFooter: KMHeaderFooterObject) {
+        self.tableView.reloadData()
+        if let index = KMHeaderFooterManager.defaultManager.onlyBatesObjects.index(of: headerFooter) {
+            let indexSet = IndexSet(integer: index)
+            self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
+        }
+    }
+   
+    func numberOfRows(in tableView: NSTableView) -> Int {
+        var count = 0
+        if self.isBates {
+            count = KMHeaderFooterManager.defaultManager.onlyBatesObjects.count
+        } else {
+            count = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.count
+        }
+        self.blankView.isHidden = count != 0
+        return count
+    }
+    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
+        var obj: KMHeaderFooterObject? = nil
+        if self.isBates {
+            obj = KMHeaderFooterManager.defaultManager.onlyBatesObjects[row]
+        } else {
+            obj = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row]
+        }
+        guard let cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "mainCell"), owner: self) as? KMHeaderFooterTableCellView else {
+            return nil
+        }
+        
+        cellView.updateInterface(obj!)
+        cellView.headerFooterTableCellViewCallback = { type in
+            if type == .Edit {
+                let indexSet = IndexSet(integer: row)
+                self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
+                self.currentObject = obj
+                self.modify(obj: obj!)
+            } else {
+                self.delete(obj: obj!)
+            }
+        }
+        return cellView
+    }
+    func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
+        let rowView = KMTableRowView() 
+        return rowView
+    }
+    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { 
+        if self.isBates {
+            return KMHeaderFooterManager.defaultManager.onlyBatesObjects[row].cellHeight
+        } else {
+            return KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row].cellHeight
+        }
+    }
+    func tableViewSelectionDidChange(_ notification: Notification) {
+        let row = self.tableView.selectedRow
+        updateActionButtonbackgroundColor()
+        if row == -1 { return }
+        if self.isBates {
+            let bates = KMHeaderFooterManager.defaultManager.onlyBatesObjects[row]
+            self.currentObject = bates
+            for i in 0..<(self.files?.count ?? 0) {
+                let file = self.files?[i]
+                file?.addBatesInfo.pageChoice = bates.pageChoice
+                if file?.addBatesInfo.pageChoice == .Input {
+                    let arr = allPageNumbers(bates.pagesString)
+                    let sortedArray: NSArray = file!.pagesArrayIntersect(with: arr) as NSArray
+                    if sortedArray.count < 1 {
+                        file?.addBatesInfo.pageChoice = .All
+                    } else {
+                        file!.addBatesInfo.pageRangeString = sortedArray.componentsJoined(by: ",")
+                    }
+                }
+            }
+        } else {
+            let headerFooter = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row]
+            self.currentObject = headerFooter
+            for i in 0..<(self.files?.count ?? 0) {
+                let file = self.files?[i]
+                file?.addHeaderFooterInfo.pageChoice = headerFooter.pageChoice
+                if file?.addHeaderFooterInfo.pageChoice == .Input {
+                    let arr = allPageNumbers(headerFooter.pagesString)
+                    let sortedArray: NSArray = file!.pagesArrayIntersect(with: arr) as NSArray
+                    if sortedArray.count < 1 {
+                        file?.addHeaderFooterInfo.pageChoice = .All
+                    } else {
+                        file!.addHeaderFooterInfo.pageRangeString = sortedArray.componentsJoined(by: ",")
+                    }
+                }
+            }
+        }
+        reloadTable()
+        NotificationCenter.default.post(name: NSNotification.Name(rawValue: kNeedChangePageRangeNotification), object: nil)
+    }
+}

+ 378 - 0
PDF Office/PDF Master/Class/PDFTools/AddHeaderFooter/VC/KMBatchOperateAddHeaderFooterViewController.xib

@@ -0,0 +1,378 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22154"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMBatchOperateAddHeaderFooterViewController" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="actionButton" destination="aa8-yb-Q1W" id="m9M-WM-7ZS"/>
+                <outlet property="addButton" destination="PXy-j3-0y8" id="F1f-zr-hGA"/>
+                <outlet property="blankView" destination="80T-Pv-2C2" id="QdG-Gt-P47"/>
+                <outlet property="bottomBaseView" destination="eJd-b3-7bH" id="Ibd-JS-CLC"/>
+                <outlet property="managerTemplateButtonHeightConstraint" destination="PXy-j3-0y8" id="J9P-MM-L2Z"/>
+                <outlet property="managerTemplateTitleLabel" destination="o4K-Vf-ilV" id="MDl-zj-PP3"/>
+                <outlet property="managerTemplateTopConstraint" destination="Xes-Jb-WZX" id="IEN-Em-aAT"/>
+                <outlet property="tableView" destination="0eN-Es-bL4" id="jaG-I7-Baw"/>
+                <outlet property="titleLabel" destination="jyn-eq-WaY" id="EUc-f2-KHa"/>
+                <outlet property="topBaseView" destination="giD-Sl-32p" id="gjc-CJ-E9a"/>
+                <outlet property="topHeightConstraint" destination="cOy-sr-ouW" id="qf6-po-gPi"/>
+                <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 id="Hz6-mo-xeY">
+            <rect key="frame" x="0.0" y="0.0" width="370" height="350"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="9qx-V5-Jd7">
+                    <rect key="frame" x="0.0" y="347" width="370" height="5"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="1" id="HjX-lB-1Up"/>
+                    </constraints>
+                </box>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="giD-Sl-32p">
+                    <rect key="frame" x="0.0" y="309" width="370" height="40"/>
+                    <subviews>
+                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="jyn-eq-WaY">
+                            <rect key="frame" x="14" y="12" width="37" height="16"/>
+                            <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="WeW-kK-Lrg">
+                                <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>
+                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="o4K-Vf-ilV">
+                            <rect key="frame" x="167" y="12" width="37" height="16"/>
+                            <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="1e8-Sy-y2Y">
+                                <font key="font" metaFont="system"/>
+                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="o4K-Vf-ilV" firstAttribute="centerX" secondItem="giD-Sl-32p" secondAttribute="centerX" id="Dbj-vt-vz4"/>
+                        <constraint firstItem="jyn-eq-WaY" firstAttribute="leading" secondItem="giD-Sl-32p" secondAttribute="leading" constant="16" id="KA0-Xy-uu3"/>
+                        <constraint firstItem="jyn-eq-WaY" firstAttribute="centerY" secondItem="giD-Sl-32p" secondAttribute="centerY" id="Vdc-Su-6R2"/>
+                        <constraint firstAttribute="height" constant="40" id="cOy-sr-ouW"/>
+                        <constraint firstItem="o4K-Vf-ilV" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="giD-Sl-32p" secondAttribute="leading" id="dcl-TW-Z2H"/>
+                        <constraint firstItem="o4K-Vf-ilV" firstAttribute="centerY" secondItem="giD-Sl-32p" secondAttribute="centerY" id="ssc-sP-mYV"/>
+                    </constraints>
+                </customView>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="eJd-b3-7bH">
+                    <rect key="frame" x="0.0" y="0.0" width="370" height="108"/>
+                    <subviews>
+                        <button tag="1" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PXy-j3-0y8">
+                            <rect key="frame" x="16" y="60" width="338" height="32"/>
+                            <buttonCell key="cell" type="bevel" title="Button" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="KWy-VT-uxN" customClass="KMButtomCell">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="32" id="uM2-r9-cKk"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonClicked_AddHeaderFooter:" target="-2" id="pZm-Br-7Ck"/>
+                            </connections>
+                        </button>
+                        <button translatesAutoresizingMaskIntoConstraints="NO" id="aa8-yb-Q1W">
+                            <rect key="frame" x="16" y="20" width="338" height="32"/>
+                            <buttonCell key="cell" type="square" title="Button" bezelStyle="shadowlessSquare" alignment="center" imageScaling="proportionallyDown" inset="2" id="uCF-0y-9Pc">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="32" id="IFw-zv-Kb1"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonClicked_Action:" target="-2" id="XPf-9S-eCz"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="aa8-yb-Q1W" firstAttribute="top" secondItem="PXy-j3-0y8" secondAttribute="bottom" constant="8" id="6N6-a0-BO0"/>
+                        <constraint firstItem="PXy-j3-0y8" firstAttribute="leading" secondItem="aa8-yb-Q1W" secondAttribute="leading" id="Sr9-ID-JkR"/>
+                        <constraint firstItem="aa8-yb-Q1W" firstAttribute="centerX" secondItem="eJd-b3-7bH" secondAttribute="centerX" id="Vae-wx-aHk"/>
+                        <constraint firstItem="PXy-j3-0y8" firstAttribute="top" secondItem="eJd-b3-7bH" secondAttribute="top" constant="16" id="Xes-Jb-WZX"/>
+                        <constraint firstItem="aa8-yb-Q1W" firstAttribute="leading" secondItem="eJd-b3-7bH" secondAttribute="leading" constant="16" id="kI9-0V-hq5"/>
+                        <constraint firstAttribute="trailing" secondItem="aa8-yb-Q1W" secondAttribute="trailing" constant="16" id="kLs-YI-hh2"/>
+                        <constraint firstAttribute="bottom" secondItem="aa8-yb-Q1W" secondAttribute="bottom" constant="20" id="kg9-Go-tT6"/>
+                        <constraint firstItem="PXy-j3-0y8" firstAttribute="trailing" secondItem="aa8-yb-Q1W" secondAttribute="trailing" id="zGq-kh-n9C"/>
+                    </constraints>
+                </customView>
+                <scrollView autohidesScrollers="YES" horizontalLineScroll="169" horizontalPageScroll="10" verticalLineScroll="169" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A9Y-d2-oxV">
+                    <rect key="frame" x="0.0" y="108" width="370" height="201"/>
+                    <clipView key="contentView" drawsBackground="NO" id="ATh-yG-UOc">
+                        <rect key="frame" x="1" y="1" width="368" height="199"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="169" rowSizeStyle="automatic" viewBased="YES" id="0eN-Es-bL4">
+                                <rect key="frame" x="0.0" y="0.0" width="368" height="199"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
+                                <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
+                                <tableColumns>
+                                    <tableColumn width="336" minWidth="10" maxWidth="3.4028234663852886e+38" id="x20-Pt-oxb">
+                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
+                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+                                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        </tableHeaderCell>
+                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="HEs-BS-QXq">
+                                            <font key="font" metaFont="system"/>
+                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                        </textFieldCell>
+                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+                                        <prototypeCellViews>
+                                            <tableCellView identifier="mainCell" id="VP4-RR-pct" customClass="KMHeaderFooterTableCellView">
+                                                <rect key="frame" x="0.0" y="0.0" width="348" height="169"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                <subviews>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="3Kd-AU-7ga">
+                                                        <rect key="frame" x="14" y="137" width="272" height="16"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="Kw2-xc-Q1u">
+                                                            <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>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tRN-9P-gle">
+                                                        <rect key="frame" x="14" y="118" width="35" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="aXa-CV-kaA">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qqc-iY-fIB">
+                                                        <rect key="frame" x="14" y="99" width="35" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="2J2-rc-TWJ">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="J33-zX-sTc">
+                                                        <rect key="frame" x="14" y="80" width="35" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="99R-pu-cyP">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pAu-om-ewh">
+                                                        <rect key="frame" x="14" y="61" width="35" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="600-Wj-BK5">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Eal-Nx-CcF">
+                                                        <rect key="frame" x="14" y="42" width="35" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="EWs-qD-mpF">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rLG-NR-NW1">
+                                                        <rect key="frame" x="14" y="23" width="35" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="ZBx-bQ-2E9">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="TZY-9G-iRS">
+                                                        <rect key="frame" x="16" y="-2" width="316" height="5"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="height" constant="1" id="48q-6P-J1R"/>
+                                                        </constraints>
+                                                    </box>
+                                                    <customView horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="5xJ-ir-jKT">
+                                                        <rect key="frame" x="284" y="137" width="48" height="16"/>
+                                                        <subviews>
+                                                            <button horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="SK1-2x-iZm" customClass="KMButton">
+                                                                <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                                                <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="KMImageNameUXIconBtnEditHov" imagePosition="only" alignment="center" imageScaling="proportionallyUpOrDown" inset="2" id="SX0-qA-IKS">
+                                                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                                    <font key="font" metaFont="system"/>
+                                                                </buttonCell>
+                                                                <constraints>
+                                                                    <constraint firstAttribute="height" constant="16" id="OT4-1u-rup"/>
+                                                                    <constraint firstAttribute="width" constant="16" id="dJp-dA-bLS"/>
+                                                                </constraints>
+                                                                <connections>
+                                                                    <action selector="buttonClicked_Edit:" target="VP4-RR-pct" id="L4p-CF-FZH"/>
+                                                                </connections>
+                                                            </button>
+                                                            <button horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="sKu-du-R5y" customClass="KMButton">
+                                                                <rect key="frame" x="32" y="0.0" width="16" height="16"/>
+                                                                <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="KMImageNameUXIconBtnCloseNor" imagePosition="only" alignment="center" imageScaling="proportionallyUpOrDown" inset="2" id="sW8-Zv-8Wd">
+                                                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                                    <font key="font" metaFont="system"/>
+                                                                </buttonCell>
+                                                                <constraints>
+                                                                    <constraint firstAttribute="width" constant="16" id="Gt0-Hr-UIb"/>
+                                                                    <constraint firstAttribute="height" constant="16" id="T6M-Aa-RY8"/>
+                                                                </constraints>
+                                                                <connections>
+                                                                    <action selector="buttonClicked_Delete:" target="VP4-RR-pct" id="Ner-fk-AEY"/>
+                                                                </connections>
+                                                            </button>
+                                                        </subviews>
+                                                        <constraints>
+                                                            <constraint firstItem="sKu-du-R5y" firstAttribute="leading" secondItem="SK1-2x-iZm" secondAttribute="trailing" constant="16" id="395-h4-j7O"/>
+                                                            <constraint firstItem="SK1-2x-iZm" firstAttribute="top" secondItem="5xJ-ir-jKT" secondAttribute="top" id="CE1-Js-pl5"/>
+                                                            <constraint firstAttribute="trailing" secondItem="sKu-du-R5y" secondAttribute="trailing" id="E3f-z9-0Lj"/>
+                                                            <constraint firstItem="sKu-du-R5y" firstAttribute="top" secondItem="5xJ-ir-jKT" secondAttribute="top" id="mD0-MJ-1b2"/>
+                                                            <constraint firstItem="SK1-2x-iZm" firstAttribute="leading" secondItem="5xJ-ir-jKT" secondAttribute="leading" id="rGJ-a0-ALm"/>
+                                                            <constraint firstAttribute="bottom" secondItem="SK1-2x-iZm" secondAttribute="bottom" id="vci-dZ-1ay"/>
+                                                            <constraint firstAttribute="bottom" secondItem="sKu-du-R5y" secondAttribute="bottom" id="yjh-y0-o5D"/>
+                                                        </constraints>
+                                                    </customView>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="rLG-NR-NW1" secondAttribute="trailing" id="2sr-VM-vrs"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Eal-Nx-CcF" secondAttribute="trailing" id="4aH-M4-jjH"/>
+                                                    <constraint firstAttribute="trailing" secondItem="5xJ-ir-jKT" secondAttribute="trailing" constant="16" id="AT0-lL-YUO"/>
+                                                    <constraint firstItem="qqc-iY-fIB" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="leading" id="F4d-tj-kVN"/>
+                                                    <constraint firstItem="pAu-om-ewh" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="leading" id="Fld-oq-SEI"/>
+                                                    <constraint firstItem="rLG-NR-NW1" firstAttribute="top" secondItem="Eal-Nx-CcF" secondAttribute="bottom" constant="4" id="IBC-Dc-U9u"/>
+                                                    <constraint firstItem="J33-zX-sTc" firstAttribute="top" secondItem="qqc-iY-fIB" secondAttribute="bottom" constant="4" id="IMB-iR-OYC"/>
+                                                    <constraint firstItem="J33-zX-sTc" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="leading" id="Q2I-5G-Eum"/>
+                                                    <constraint firstItem="rLG-NR-NW1" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="leading" id="Rqm-pn-BU4"/>
+                                                    <constraint firstAttribute="trailing" secondItem="TZY-9G-iRS" secondAttribute="trailing" constant="16" id="TA4-nT-MeW"/>
+                                                    <constraint firstItem="TZY-9G-iRS" firstAttribute="leading" secondItem="VP4-RR-pct" secondAttribute="leading" constant="16" id="VjC-Hx-Ldx"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="qqc-iY-fIB" secondAttribute="trailing" id="VpB-3J-9Wt"/>
+                                                    <constraint firstItem="pAu-om-ewh" firstAttribute="top" secondItem="J33-zX-sTc" secondAttribute="bottom" constant="4" id="XNN-wr-I8b"/>
+                                                    <constraint firstItem="tRN-9P-gle" firstAttribute="top" secondItem="3Kd-AU-7ga" secondAttribute="bottom" constant="4" id="cXS-4O-gBh"/>
+                                                    <constraint firstAttribute="bottom" secondItem="TZY-9G-iRS" secondAttribute="bottom" id="eq6-RL-JB3"/>
+                                                    <constraint firstItem="3Kd-AU-7ga" firstAttribute="top" secondItem="VP4-RR-pct" secondAttribute="top" constant="16" id="fTO-ue-z06"/>
+                                                    <constraint firstItem="tRN-9P-gle" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="leading" id="gg4-6X-p7r"/>
+                                                    <constraint firstItem="5xJ-ir-jKT" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="trailing" id="iYJ-4C-0uo"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="pAu-om-ewh" secondAttribute="trailing" id="iei-2N-qQE"/>
+                                                    <constraint firstItem="Eal-Nx-CcF" firstAttribute="top" secondItem="pAu-om-ewh" secondAttribute="bottom" constant="4" id="s6q-Qw-YEB"/>
+                                                    <constraint firstItem="Eal-Nx-CcF" firstAttribute="leading" secondItem="3Kd-AU-7ga" secondAttribute="leading" id="sWY-a4-8Kb"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="J33-zX-sTc" secondAttribute="trailing" id="t0S-H6-kXJ"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="tRN-9P-gle" secondAttribute="trailing" id="t4F-hb-XBe"/>
+                                                    <constraint firstItem="3Kd-AU-7ga" firstAttribute="leading" secondItem="VP4-RR-pct" secondAttribute="leading" constant="16" id="u6B-KH-tyg"/>
+                                                    <constraint firstItem="5xJ-ir-jKT" firstAttribute="centerY" secondItem="3Kd-AU-7ga" secondAttribute="centerY" id="uvZ-2B-rQs"/>
+                                                    <constraint firstItem="qqc-iY-fIB" firstAttribute="top" secondItem="tRN-9P-gle" secondAttribute="bottom" constant="4" id="yMH-MD-07G"/>
+                                                </constraints>
+                                                <connections>
+                                                    <outlet property="auxiliaryView" destination="5xJ-ir-jKT" id="Uqv-gy-zRg"/>
+                                                    <outlet property="deleteButtonl" destination="sKu-du-R5y" id="MsJ-ip-CVd"/>
+                                                    <outlet property="editButton" destination="SK1-2x-iZm" id="OOB-Nd-aum"/>
+                                                    <outlet property="textFiled1" destination="tRN-9P-gle" id="dWO-ci-lm6"/>
+                                                    <outlet property="textFiled2" destination="qqc-iY-fIB" id="3ac-EG-CQU"/>
+                                                    <outlet property="textFiled3" destination="J33-zX-sTc" id="bJY-Mf-S8s"/>
+                                                    <outlet property="textFiled4" destination="pAu-om-ewh" id="uRw-DN-vAg"/>
+                                                    <outlet property="textFiled5" destination="Eal-Nx-CcF" id="E9S-GA-POP"/>
+                                                    <outlet property="textFiled6" destination="rLG-NR-NW1" id="8vn-54-1qv"/>
+                                                    <outlet property="titleTextFiled" destination="3Kd-AU-7ga" id="Vkn-8b-ciy"/>
+                                                </connections>
+                                            </tableCellView>
+                                        </prototypeCellViews>
+                                    </tableColumn>
+                                </tableColumns>
+                                <connections>
+                                    <outlet property="dataSource" destination="-2" id="Gpk-VF-8j5"/>
+                                    <outlet property="delegate" destination="-2" id="ANb-dZ-7L7"/>
+                                </connections>
+                            </tableView>
+                        </subviews>
+                        <nil key="backgroundColor"/>
+                    </clipView>
+                    <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="D4P-vY-6mp">
+                        <rect key="frame" x="1" y="118" width="238" height="16"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </scroller>
+                    <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="2y3-I9-SPX">
+                        <rect key="frame" x="224" y="17" width="15" height="102"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </scroller>
+                </scrollView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="giD-Sl-32p" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="1" id="6GQ-Ua-1ZP"/>
+                <constraint firstAttribute="trailing" secondItem="9qx-V5-Jd7" secondAttribute="trailing" id="8xi-xG-Saj"/>
+                <constraint firstAttribute="bottom" secondItem="eJd-b3-7bH" secondAttribute="bottom" id="97h-Xc-tqt"/>
+                <constraint firstItem="giD-Sl-32p" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="9WY-9S-Ghv"/>
+                <constraint firstItem="9qx-V5-Jd7" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="Bgd-VA-0B5"/>
+                <constraint firstItem="9qx-V5-Jd7" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="HqE-3p-LT8"/>
+                <constraint firstItem="A9Y-d2-oxV" firstAttribute="top" secondItem="giD-Sl-32p" secondAttribute="bottom" id="aKm-iJ-4Gu"/>
+                <constraint firstItem="A9Y-d2-oxV" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="c3z-zg-i8Z"/>
+                <constraint firstItem="eJd-b3-7bH" firstAttribute="top" secondItem="A9Y-d2-oxV" secondAttribute="bottom" id="e78-4t-YJS"/>
+                <constraint firstAttribute="trailing" secondItem="A9Y-d2-oxV" secondAttribute="trailing" id="ewu-Lv-JPt"/>
+                <constraint firstAttribute="trailing" secondItem="giD-Sl-32p" secondAttribute="trailing" id="fuZ-Of-f66"/>
+                <constraint firstAttribute="trailing" secondItem="eJd-b3-7bH" secondAttribute="trailing" id="imI-hE-nwo"/>
+                <constraint firstItem="eJd-b3-7bH" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="m3F-en-8Wx"/>
+            </constraints>
+            <point key="canvasLocation" x="-7" y="151"/>
+        </customView>
+        <customView id="80T-Pv-2C2" customClass="KMBlankView" customModule="PDF_Master" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="436" height="400"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="Wfy-jQ-a6K">
+                    <rect key="frame" x="81" y="98" width="275" height="204"/>
+                    <subviews>
+                        <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="NBT-eP-974">
+                            <rect key="frame" x="67" y="64" width="140" height="140"/>
+                            <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="KMImageNameEmptyHeaderandfooter" id="qDG-em-ADl"/>
+                        </imageView>
+                        <textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="KUY-vh-cL7">
+                            <rect key="frame" x="91" y="32" width="92" height="16"/>
+                            <textFieldCell key="cell" title="Multiline Label" id="LFF-qa-5YV">
+                                <font key="font" metaFont="system"/>
+                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                        <textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Clu-hg-vwb">
+                            <rect key="frame" x="91" y="8" width="92" height="16"/>
+                            <textFieldCell key="cell" title="Multiline Label" id="hQs-VR-mjE">
+                                <font key="font" metaFont="system"/>
+                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="Clu-hg-vwb" firstAttribute="top" secondItem="KUY-vh-cL7" secondAttribute="bottom" constant="8" id="0nz-qB-SHQ"/>
+                        <constraint firstAttribute="bottom" secondItem="Clu-hg-vwb" secondAttribute="bottom" constant="8" id="AeM-OZ-i2D"/>
+                        <constraint firstItem="KUY-vh-cL7" firstAttribute="centerX" secondItem="Wfy-jQ-a6K" secondAttribute="centerX" id="OMF-HP-XLw"/>
+                        <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Clu-hg-vwb" secondAttribute="trailing" id="OMl-Rh-h3Z"/>
+                        <constraint firstItem="Clu-hg-vwb" firstAttribute="centerX" secondItem="Wfy-jQ-a6K" secondAttribute="centerX" id="P3k-tM-Dsq"/>
+                        <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="KUY-vh-cL7" secondAttribute="trailing" id="VHH-T3-yDz"/>
+                        <constraint firstItem="NBT-eP-974" firstAttribute="top" secondItem="Wfy-jQ-a6K" secondAttribute="top" id="WO1-E4-Fq8"/>
+                        <constraint firstItem="NBT-eP-974" firstAttribute="centerX" secondItem="Wfy-jQ-a6K" secondAttribute="centerX" id="cfx-oK-hyO"/>
+                        <constraint firstItem="KUY-vh-cL7" firstAttribute="top" secondItem="NBT-eP-974" secondAttribute="bottom" constant="16" id="mMM-BP-YMM"/>
+                        <constraint firstAttribute="width" constant="275" id="nMV-Lg-2ia"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="Wfy-jQ-a6K" firstAttribute="centerX" secondItem="80T-Pv-2C2" secondAttribute="centerX" id="h4g-Wj-yd0"/>
+                <constraint firstItem="Wfy-jQ-a6K" firstAttribute="centerY" secondItem="80T-Pv-2C2" secondAttribute="centerY" id="hao-gz-Jud"/>
+            </constraints>
+            <connections>
+                <outlet property="imageView" destination="NBT-eP-974" id="dx3-ZA-kbs"/>
+                <outlet property="secondTitleLabel" destination="Clu-hg-vwb" id="Y5w-ef-fy4"/>
+                <outlet property="titleLabel" destination="KUY-vh-cL7" id="Z3n-8f-cdf"/>
+            </connections>
+            <point key="canvasLocation" x="-76" y="641"/>
+        </customView>
+    </objects>
+    <resources>
+        <image name="KMImageNameEmptyHeaderandfooter" width="140" height="140"/>
+        <image name="KMImageNameUXIconBtnCloseNor" width="16" height="16"/>
+        <image name="KMImageNameUXIconBtnEditHov" width="16" height="16"/>
+    </resources>
+</document>

+ 145 - 0
PDF Office/PDF Master/Class/PDFTools/AddHeaderFooter/View/KMHeaderFooterTableCellView.swift

@@ -0,0 +1,145 @@
+//
+//  KMHeaderFooterTableCellView.swift
+//  PDF Master
+//
+//  Created by liujiajie on 2023/11/7.
+//
+
+import Cocoa
+
+typealias HeaderFooterTableCellViewCallback = (_ type: KMBatchModifyTemplateType) -> ()
+
+class KMHeaderFooterTableCellView: NSTableCellView {
+    var headerFooterTableCellViewCallback: HeaderFooterTableCellViewCallback?
+    @IBOutlet var textFiled1: NSTextField!
+    @IBOutlet var textFiled2: NSTextField!
+    @IBOutlet var textFiled3: NSTextField!
+    @IBOutlet var textFiled4: NSTextField!
+    @IBOutlet var textFiled5: NSTextField!
+    @IBOutlet var textFiled6: NSTextField!
+    @IBOutlet var titleTextFiled: NSTextField!
+    @IBOutlet var auxiliaryView: NSView!
+    @IBOutlet var editButton: KMButton!
+    @IBOutlet var deleteButtonl: KMButton!
+    
+    override func prepareForReuse() {
+        super.prepareForReuse()
+        self.textFiled1.stringValue = ""
+        self.textFiled2.stringValue = ""
+        self.textFiled3.stringValue = ""
+        self.textFiled4.stringValue = ""
+        self.textFiled5.stringValue = ""
+        self.textFiled5.stringValue = ""
+        self.titleTextFiled.stringValue = ""
+        self.auxiliaryView.isHidden = true
+    }
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        self.titleTextFiled.textColor = KMAppearance.Layout.h0Color()
+        self.textFiled1.textColor = KMAppearance.Layout.h0Color()
+        self.textFiled2.textColor = KMAppearance.Layout.h0Color()
+        self.textFiled3.textColor = KMAppearance.Layout.h0Color()
+        self.textFiled4.textColor = KMAppearance.Layout.h0Color()
+        self.textFiled5.textColor = KMAppearance.Layout.h0Color()
+        self.textFiled6.textColor = KMAppearance.Layout.h1Color()
+        
+        self.textFiled1.stringValue = ""
+        self.textFiled2.stringValue = ""
+        self.textFiled3.stringValue = ""
+        self.textFiled4.stringValue = ""
+        self.textFiled5.stringValue = ""
+        self.textFiled6.stringValue = ""
+        self.titleTextFiled.stringValue = ""
+        self.auxiliaryView.isHidden = true
+        
+        self.wantsLayer = true
+    
+        self.editButton.mouseMoveCallback = {[weak self] mouseEntered in
+            if mouseEntered {
+                self?.editButton.image = NSImage(named: KMImageNameUXIconBtnEditHov)
+            } else {
+                self?.editButton.image = NSImage(named: KMImageNameUXIconBtnEditNor)
+            }
+        }
+        self.deleteButtonl.mouseMoveCallback = {[weak self] mouseEntered in
+            if mouseEntered {
+                self?.deleteButtonl.image = NSImage(named: KMImageNameUXIconBtnCloseHov)
+            } else {
+                self?.deleteButtonl.image = NSImage(named: KMImageNameUXIconBtnCloseNor)
+            }
+        }
+        self.newTrackingArea()
+    }
+    func newTrackingArea() {
+        let trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .inVisibleRect, .activeAlways, .mouseMoved], owner: self, userInfo: nil)
+        self.addTrackingArea(trackingArea)
+    }
+    func appendBaseString(_ string: String) -> String {
+        var appendString = string
+        return appendString
+    }
+    func updateInterface(_ obj: KMHeaderFooterObject) { 
+        var arr = NSMutableArray()
+        if obj.topLeftString.count > 0 {
+            arr.add(appendBaseString(NSLocalizedString("Left Header Text", comment: ""), withString: appendBaseString(obj.topLeftString)))
+        }
+        if obj.topCenterString.count > 0 {
+            arr.add(appendBaseString(NSLocalizedString("Center Header Text", comment: ""), withString: appendBaseString(obj.topCenterString)))
+        }
+        if obj.topRightString.count > 0 {
+            arr.add(appendBaseString(NSLocalizedString("Right Header Text", comment: ""), withString: appendBaseString(obj.topRightString)))
+        }
+        if obj.bottomLeftString.count > 0 {
+            arr.add(appendBaseString(NSLocalizedString("Left Footer Text", comment: ""), withString: appendBaseString(obj.bottomLeftString)))
+        }
+        if obj.bottomCenterString.count > 0 {
+            arr.add(appendBaseString(NSLocalizedString("Center Footer Text", comment: ""), withString: appendBaseString(obj.bottomCenterString)))
+        }
+        if obj.bottomRightString.count > 0 {
+            arr.add(appendBaseString(NSLocalizedString("Right Footer Text", comment: ""), withString: appendBaseString(obj.bottomRightString)))
+        }
+        for i in 0..<arr.count {
+            switch i {
+            case 0:
+                self.textFiled1.stringValue = arr[i] as! String
+            case 1:
+                self.textFiled2.stringValue = arr[i] as! String
+            case 2:
+                self.textFiled3.stringValue = arr[i] as! String
+            case 3:
+                self.textFiled4.stringValue = arr[i] as! String
+            case 4:
+                self.textFiled5.stringValue = arr[i] as! String
+            case 5:
+                self.textFiled6.stringValue = arr[i] as! String
+            default:
+                break
+            }
+        }
+        self.titleTextFiled.stringValue = obj.headerFooterID 
+    }
+    func appendBaseString(_ prefixString: String, withString suffixString: String) -> String {
+        return "(prefixString): (suffixString)"
+    }
+    override func mouseEntered(with event: NSEvent) {
+        super.mouseEntered(with: event)
+        self.auxiliaryView.isHidden = false
+        self.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
+    }
+    override func mouseExited(with event: NSEvent) {
+        super.mouseExited(with: event)
+        self.auxiliaryView.isHidden = true
+        
+        self.layer?.backgroundColor = NSColor.clear.cgColor
+    }
+    @IBAction func buttonClicked_Edit(_ sender: Any) {
+        if let callback = self.headerFooterTableCellViewCallback {
+            callback(.Edit)
+        }
+    }
+    @IBAction func buttonClicked_Delete(_ sender: Any) {
+        if let callback = self.headerFooterTableCellViewCallback {
+            callback(.Delete)
+        }
+    }
+}

+ 374 - 0
PDF Office/PDF Master/Class/PDFTools/AddHeaderFooter/WindowComtroller/KMHeaderFooterManagerWindowController.swift

@@ -0,0 +1,374 @@
+//
+//  KMHeaderFooterManagerWindowController.swift
+//  PDF Master
+//
+//  Created by liujiajie on 2023/11/6.
+//
+
+import Cocoa
+
+typealias HeaderFooterOperateCallBack = (_ obj: KMHeaderFooterObject) -> ()
+
+class KMHeaderFooterManagerWindowController: NSWindowController{
+    var operateCallBack: HeaderFooterOperateCallBack?
+    var isBates: Bool = false
+    var onlyManagerTemplate: Bool = false
+    
+    lazy var filePath: String = {
+        var str = Bundle.main.path(forResource: "Quick Start Guide", ofType: "pdf")
+        return str ?? ""
+    }()
+    var password: String = ""
+    var type:KMBatchModifyTemplateType = .Add
+    var pdfdocument: CPDFDocument?
+    lazy var headerFooterObj: KMHeaderFooterObject? = {
+        let obj = KMHeaderFooterObject()
+        obj.isBates = self.isBates
+        if self.isBates {
+            obj.headerFooterID = KMHeaderFooterManager.defaultManager.fetchBatesAvailableName()
+        }else {
+            obj.headerFooterID = KMHeaderFooterManager.defaultManager.fetchHeaderFooterAvailableName()
+        }
+        initialID = obj.headerFooterID
+        return obj
+    }()
+    var originalHeaderFooterObj: KMHeaderFooterObject?
+    lazy var dateFormatArray: Array<Any> = {
+        let arr = KMHeaderFooterManager.defaultManager.dateFormatArray
+        return arr
+    }()
+    var initialID: String?
+    
+    @IBOutlet var pdfView: KMWatermarkPDFView!
+    @IBOutlet var currentPageIndexTextField: NSTextField!
+    @IBOutlet var totalPageCountLabel: NSTextField!
+
+    @IBOutlet var textBox: NSBox!
+    @IBOutlet var textLabel: NSTextField!
+    @IBOutlet var fontSizeLabel: NSTextField!
+    @IBOutlet var fontSizeCombobox: NSComboBox!
+    @IBOutlet var textColorLabel: NSTextField!
+    @IBOutlet var textColorWell: NSColorWell!
+
+    @IBOutlet var marginBox: NSBox!
+    @IBOutlet var marginLabel: NSTextField!
+    @IBOutlet var topMarginLabel: NSTextField!
+    @IBOutlet var topMargintextField: NSTextField!
+    @IBOutlet var topMarginStepper: NSStepper!
+    @IBOutlet var bottomMarginLabel: NSTextField!
+    @IBOutlet var bottomMarginTextField: NSTextField!
+    @IBOutlet var bottomMarginStepper: NSStepper!
+    @IBOutlet var leftMarginLabel: NSTextField!
+    @IBOutlet var leftMarginTextField: NSTextField!
+    @IBOutlet var leftMarginStepper: NSStepper!
+    @IBOutlet var rightMarginLabel: NSTextField!
+    @IBOutlet var rightMarginTextField: NSTextField!
+    @IBOutlet var rightMarginStepper: NSStepper!
+
+    @IBOutlet var formatBox: NSBox!
+    @IBOutlet var formatLabel: NSTextField!
+    @IBOutlet var dateFormateLabel: NSTextField!
+    @IBOutlet var dateFormateCombobox: NSComboBox!
+    @IBOutlet var pageLabel: NSTextField!
+    @IBOutlet var pageCombobox: NSComboBox!
+    @IBOutlet var beginPageLabel: NSTextField!
+    @IBOutlet var beginPageCombobox: NSComboBox!
+
+    @IBOutlet var topLeftLabel: NSTextField!
+    @IBOutlet var topLeftTextView: NSTextView!
+    @IBOutlet var topCenterLabel: NSTextField!
+    @IBOutlet var topCenterTextView: NSTextView!
+    @IBOutlet var topRightLabel: NSTextField!
+    @IBOutlet var topRightTextView: NSTextView!
+    @IBOutlet var bottomLeftLabel: NSTextField!
+    @IBOutlet var bottomLeftTextView: NSTextView!
+    @IBOutlet var bottomCenterLabel: NSTextField!
+    @IBOutlet var BottomCenterTextView: NSTextView!
+    @IBOutlet var bottomRightLabel: NSTextField!
+    @IBOutlet var bottomRightTextView: NSTextView!
+    @IBOutlet var pageRangeLabel: NSTextField!
+    @IBOutlet var pageRangeCombobox: NSComboBox!
+    @IBOutlet var saveToTemplateButton: NSButton!
+    @IBOutlet var templateNameLabel: NSTextField!
+    @IBOutlet var templateNameTextField: NSTextField!
+
+    @IBOutlet var  topLeftButton: NSButton!
+    @IBOutlet var  topCentButton: NSButton!
+    @IBOutlet var  topRightButton: NSButton!
+    @IBOutlet var  bottomLeftButton: NSButton!
+    @IBOutlet var  bottomCenterButton: NSButton!
+    @IBOutlet var  bottomRightButton: NSButton!
+
+    @IBOutlet var  batchButton: NSButton!
+    @IBOutlet var  cancelButton: NSButton!
+    @IBOutlet var  applyButton: NSButton!
+
+    @IBOutlet var batesBox: NSBox!
+    @IBOutlet var prefixLabel: NSTextField!
+    @IBOutlet var prefixTextField: NSTextField!
+    @IBOutlet var suffixLabel: NSTextField!
+    @IBOutlet var suffixTextField: NSTextField!
+    @IBOutlet var batesNumberLabel: NSTextField!
+    @IBOutlet var batesNumberTextField: NSTextField!
+    @IBOutlet var batesNumberStepper: NSStepper!
+
+    @IBOutlet var batesStartPageLabel: NSTextField!
+    @IBOutlet var batesStartpageCombobox: NSComboBox!
+    @IBOutlet var constraint: NSLayoutConstraint!
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+        DistributedNotificationCenter.default().removeObserver(self)
+    }
+    
+    convenience init(baseFile:String, obj:KMHeaderFooterObject, password:String, type:KMBatchModifyTemplateType) {
+        self.init(windowNibName: "KMHeaderFooterManagerWindowController")
+        self.filePath = baseFile
+        self.password = password
+        self.headerFooterObj = obj
+        self.originalHeaderFooterObj = obj
+        self.initialID = obj.headerFooterID
+        self.type = type
+        self.pdfdocument = CPDFDocument(url: URL(fileURLWithPath: self.filePath))
+        if ((self.pdfdocument?.isLocked) != nil) {
+            self.pdfdocument?.unlock(withPassword: password)
+        }
+        if ((self.pdfdocument?.isLocked) != nil) {
+            return
+        }
+    }
+    override func windowDidLoad() {
+        super.windowDidLoad()
+        configuUI()
+        loadData()
+        NotificationCenter.default.addObserver(self, selector: #selector(pageChangeNotification(notification:)), name: Notification.Name(rawValue: "CPDFViewPageChangedNotification"), object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: Notification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
+    }
+    func configuUI() { 
+        topLeftButton.wantsLayer = true
+        topCentButton.wantsLayer = true
+        topRightButton.wantsLayer = true
+        bottomLeftButton.wantsLayer = true
+        bottomCenterButton.wantsLayer = true
+        bottomRightButton.wantsLayer = true
+        topLeftButton.layer?.borderWidth = 1.0
+        topCentButton.layer?.borderWidth = 1.0
+        topRightButton.layer?.borderWidth = 1.0
+        bottomLeftButton.layer?.borderWidth = 1.0
+        bottomCenterButton.layer?.borderWidth = 1.0
+        bottomRightButton.layer?.borderWidth = 1.0
+        topLeftButton.layer?.cornerRadius = 1.0 
+        topCentButton.layer?.cornerRadius = 1.0
+        topRightButton.layer?.cornerRadius = 1.0
+        bottomLeftButton.layer?.cornerRadius = 1.0
+        bottomCenterButton.layer?.cornerRadius = 1.0
+        bottomRightButton.layer?.cornerRadius = 1.0
+        updateViewColor()
+        
+        let textViewArr: [NSTextView] = [topLeftTextView, topCenterTextView, topRightTextView, bottomLeftTextView, BottomCenterTextView, bottomRightTextView]
+        for textView in textViewArr {
+            textView.wantsLayer = true
+            // textView.layer?.borderWidth = 1.0
+            // textView.layer?.borderColor = NSColor.gridColor.cgColor
+        }
+        
+        textColorWell.color = headerFooterObj?.textColor ?? .black
+        pdfView.document = pdfdocument
+//        pdfView. = headerFooterObj
+        pdfView.autoScales = true
+//        pdfView.documentView?.enclosingScrollView?.hasVerticalScroller = false
+//        pdfView.documentView?.enclosingScrollView?.hasHorizontalScroller = false
+//        
+//        currentPageIndexTextField.stringValue = NSLocalizedString("1", comment: "")
+//        batesStartPageLabel.stringValue = String(format: "%@:", NSLocalizedString("Start Page Number", comment: ""))
+//        let numberFormatter = currentPageIndexTextField.formatter as? NSNumberFormatter
+//        numberFormatter?.maximum = NSNumber(value: pdfdocument.pageCount)
+//        totalPageCountLabel.stringValue = String(format: "/ %ld", pdfdocument.pageCount)
+//        
+//        previewLabel.stringValue = NSLocalizedString("Preview", comment: "")
+        textLabel.stringValue = NSLocalizedString("Font Size", comment: "")
+        fontSizeLabel.stringValue = String(format: "%@:", NSLocalizedString("Size", comment: ""))
+        textColorLabel.stringValue = String(format: "%@:", NSLocalizedString("Color", comment: ""))
+        
+        marginLabel.stringValue = NSLocalizedString("Margin", comment: "")
+        topMarginLabel.stringValue = String(format: "%@:", NSLocalizedString("Top", comment: ""))
+        bottomMarginLabel.stringValue = String(format: "%@:", NSLocalizedString("Bottom", comment: ""))
+        leftMarginLabel.stringValue = String(format: "%@:", NSLocalizedString("Left", comment: ""))
+        rightMarginLabel.stringValue = String(format: "%@:", NSLocalizedString("Right", comment: ""))
+        
+        topMarginLabel.toolTip = String(format: "%@:", NSLocalizedString("Top", comment: ""))
+        bottomMarginLabel.toolTip = String(format: "%@:", NSLocalizedString("Bottom", comment: ""))
+        leftMarginLabel.toolTip = String(format: "%@:", NSLocalizedString("Left", comment: ""))
+        rightMarginLabel.toolTip = String(format: "%@:", NSLocalizedString("Right", comment: ""))
+        
+        topMarginLabel.allowsExpansionToolTips = true
+        bottomMarginLabel.allowsExpansionToolTips = true
+        leftMarginLabel.allowsExpansionToolTips = true
+        rightMarginLabel.allowsExpansionToolTips = true
+        
+        formatLabel.stringValue = NSLocalizedString("Page Number and Date Format", comment: "")
+        dateFormateLabel.stringValue = String(format: "%@:", NSLocalizedString("Date", comment: ""))
+        pageLabel.stringValue = String(format: "%@:", NSLocalizedString("Page", comment: ""))
+        beginPageLabel.stringValue = String(format: "%@:", NSLocalizedString("Start Page Number", comment: ""))
+        
+        formatLabel.toolTip = NSLocalizedString("Page Number and Date Format", comment: "")
+        dateFormateLabel.toolTip = String(format: "%@:", NSLocalizedString("Date", comment: ""))
+        pageLabel.toolTip = String(format: "%@:", NSLocalizedString("Page", comment: ""))
+        beginPageLabel.toolTip = String(format: "%@:", NSLocalizedString("Start Page Number", comment: ""))
+        
+        topLeftLabel.stringValue = NSLocalizedString("Left Header Text", comment: "")
+        topCenterLabel.stringValue = NSLocalizedString("Center Header Text", comment: "")
+        topRightLabel.stringValue = NSLocalizedString("Right Header Text", comment: "")
+        bottomLeftLabel.stringValue = NSLocalizedString("Left Footer Text", comment: "")
+        bottomCenterLabel.stringValue = NSLocalizedString("Center Footer Text", comment: "")
+        bottomRightLabel.stringValue = NSLocalizedString("Right Footer Text", comment: "")
+        
+        topLeftLabel.toolTip = NSLocalizedString("Left Header Text", comment: "")
+        topCenterLabel.toolTip = NSLocalizedString("Center Header Text", comment: "")
+        topRightLabel.toolTip = NSLocalizedString("Right Header Text", comment: "")
+        bottomLeftLabel.toolTip = NSLocalizedString("Left Footer Text", comment: "")
+        
+        
+    }
+    func loadData(){
+        self.leftMarginTextField.stringValue = String(format: "%ld", self.headerFooterObj?.leftMargin ?? 0)
+        self.rightMarginTextField.stringValue = String(format: "%ld", self.headerFooterObj?.rightMargin ?? 0)
+        self.topMargintextField.stringValue = String(format: "%ld", self.headerFooterObj?.topMargin ?? 0)
+        self.bottomMarginTextField.stringValue = String(format: "%ld", self.headerFooterObj?.bottomMargin ?? 0)
+        self.leftMarginStepper.integerValue = self.headerFooterObj?.leftMargin ?? 0
+        self.rightMarginStepper.integerValue = self.headerFooterObj?.rightMargin ?? 0
+        self.topMarginStepper.integerValue = self.headerFooterObj?.topMargin ?? 0
+        self.bottomMarginStepper.integerValue = self.headerFooterObj?.bottomMargin ?? 0
+
+        var fontSizeArray = NSMutableArray()
+        for i in 0..<self.fontSizeCombobox.objectValues.count {
+            let obj = self.fontSizeCombobox.objectValues[i] as! String
+            fontSizeArray.add(NSNumber(integerLiteral: Int(obj) ?? 0))
+        }
+        self.fontSizeCombobox.removeAllItems()
+        self.fontSizeCombobox.addItems(withObjectValues: fontSizeArray as! [Any])
+        let index = self.fontSizeCombobox.indexOfItem(withObjectValue: self.headerFooterObj?.fontSize ?? 0.0)
+        if (index == NSNotFound) {
+            self.fontSizeCombobox.selectItem(at: index)
+        } else {
+            self.fontSizeCombobox.integerValue = Int(self.headerFooterObj?.fontSize ?? 0)
+        }
+
+        self.dateFormateCombobox.removeAllItems()
+        self.dateFormateCombobox.addItems(withObjectValues: self.dateFormatArray)
+        let obj = self.headerFooterObj?.dateFormatString
+        var isContain: Bool = (((self.dateFormateCombobox.objectValues as? [String])?.contains(obj ?? "")) != nil)
+       
+        if isContain {
+            self.dateFormateCombobox.selectItem(withObjectValue: obj)
+        }
+        let obj1 = self.headerFooterObj?.pageFormatString
+        var isContain1: Bool = (((self.pageCombobox.objectValues as? [String])?.contains(obj1 ?? "")) != nil)
+        if  isContain1{
+            self.pageCombobox.selectItem(withObjectValue: obj1)
+        } else {
+            self.pageCombobox.stringValue = ""
+        }
+
+        var pages = [String]()
+        for i in 0..<(self.pdfdocument?.pageCount ?? 0) {
+            pages.append("\(i+1)")
+        }
+        self.beginPageCombobox.formatter = TextFieldFormatter()
+        self.beginPageCombobox.isEditable = false
+        self.beginPageCombobox.removeAllItems()
+        self.beginPageCombobox.addItems(withObjectValues: pages)
+        let obj2 = self.headerFooterObj?.startString
+        var isContain2: Bool = (((self.beginPageCombobox.objectValues as? [String])?.contains(obj2 ?? "")) != nil)
+        if  isContain2{
+            self.beginPageCombobox.selectItem(withObjectValue: obj2)
+        }
+        
+        self.batesStartpageCombobox.formatter = TextFieldFormatter()
+        self.batesStartpageCombobox.isEditable = false
+        self.batesStartpageCombobox.removeAllItems()
+        self.batesStartpageCombobox.addItems(withObjectValues: pages)
+        let obj3 = self.headerFooterObj?.startString
+        var isContain3: Bool = (((self.batesStartpageCombobox.objectValues as? [String])?.contains(obj3 ?? "")) != nil)
+        if isContain3 {
+            self.batesStartpageCombobox.selectItem(withObjectValue: obj3)
+        }
+        if .All == self.headerFooterObj?.pageChoice {
+            self.pageRangeCombobox.isEditable = false
+            self.pageRangeCombobox.selectItem(at: 0)
+        } else if .Odd == self.headerFooterObj?.pageChoice {
+            self.pageRangeCombobox.isEditable = false 
+            self.pageRangeCombobox.selectItem(at: 1)
+        } else if .Even == self.headerFooterObj?.pageChoice {
+            self.pageRangeCombobox.isEditable = false
+            self.pageRangeCombobox.selectItem(at: 2)
+        } else if .Input == self.headerFooterObj?.pageChoice {
+            self.pageRangeCombobox.isEditable = true
+            self.pageRangeCombobox.selectItem(at: 3)
+            self.pageRangeCombobox.stringValue = self.headerFooterObj?.pagesString ?? ""
+            let sting = self.headerFooterObj?.pagesString
+            if sting?.count ?? 0 > 0 {
+                let array = sting?.components(separatedBy: ",") ?? []
+                var pagesString = ""
+                for (i, index) in array.enumerated() {
+                    if i == array.count - 1 {
+                        pagesString += "(Int(index)! + 1)"
+                    } else {
+                        pagesString += "(Int(index)! + 1),"
+                    }
+                }
+                self.pageRangeCombobox.stringValue = pagesString
+            }
+        }
+        self.topLeftTextView.string = self.headerFooterObj?.topLeftString ?? ""
+        self.topCenterTextView.string = self.headerFooterObj?.topCenterString ?? ""
+        self.topRightTextView.string = self.headerFooterObj?.topRightString ?? ""
+        self.bottomLeftTextView.string = self.headerFooterObj?.bottomLeftString ?? ""
+        self.BottomCenterTextView.string = self.headerFooterObj?.bottomCenterString ?? ""
+        self.bottomRightTextView.string = self.headerFooterObj?.bottomRightString ?? ""
+        self.templateNameTextField.stringValue = self.headerFooterObj?.headerFooterID ?? ""
+        if self.topLeftTextView.string.count <= 0 && self.topCenterTextView.string.count <= 0 && self.topRightTextView.string.count <= 0 && self.bottomLeftTextView.string.count <= 0 && self.BottomCenterTextView.string.count <= 0 && self.bottomRightTextView.string.count <= 0 {
+            self.applyButton.isEnabled = false
+        } else {
+            self.applyButton.isEnabled = true
+        }
+    }
+    
+    @objc func pageChangeNotification(notification: Notification) {
+        self.currentPageIndexTextField.stringValue = self.pdfView.currentPage().label
+    }
+    @objc func themeChanged(notification: Notification) {
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+            self.updateViewColor()
+        }
+    }
+    func updateViewColor() {
+        if KMAppearance.isDarkMode() {
+            topLeftButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            topCentButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            topRightButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            bottomLeftButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            bottomCenterButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            bottomRightButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            topLeftButton.layer?.backgroundColor = NSColor(red: 54/255.0, green: 54/255.0, blue: 54/255.0, alpha: 0.85).cgColor
+            topCentButton.layer?.backgroundColor = NSColor(red: 54/255.0, green: 54/255.0, blue: 54/255.0, alpha: 0.85).cgColor
+            topRightButton.layer?.backgroundColor = NSColor(red: 54/255.0, green: 54/255.0, blue: 54/255.0, alpha: 0.85).cgColor
+            bottomLeftButton.layer?.backgroundColor = NSColor(red: 54/255.0, green: 54/255.0, blue: 54/255.0, alpha: 0.85).cgColor
+            bottomCenterButton.layer?.backgroundColor = NSColor(red: 54/255.0, green: 54/255.0, blue: 54/255.0, alpha: 0.85).cgColor
+            bottomRightButton.layer?.backgroundColor = NSColor(red: 54/255.0, green: 54/255.0, blue: 54/255.0, alpha: 0.85).cgColor
+        } else {
+            topLeftButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            topCentButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            topRightButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            bottomLeftButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            bottomCenterButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            bottomRightButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.3).cgColor
+            topLeftButton.layer?.backgroundColor = NSColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 0.85).cgColor
+            topCentButton.layer?.backgroundColor = NSColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 0.85).cgColor
+            topRightButton.layer?.backgroundColor = NSColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 0.85).cgColor
+            bottomLeftButton.layer?.backgroundColor = NSColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 0.85).cgColor
+            bottomCenterButton.layer?.backgroundColor = NSColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 0.85).cgColor
+            bottomRightButton.layer?.backgroundColor = NSColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 0.85).cgColor
+        }
+    }
+}

File diff suppressed because it is too large
+ 1226 - 0
PDF Office/PDF Master/Class/PDFTools/AddHeaderFooter/WindowComtroller/KMHeaderFooterManagerWindowController.xib


+ 4 - 4
PDF Office/PDF Master/Class/PDFTools/AddPassword/Model/KMBatchAddPasswordOperation.swift

@@ -9,12 +9,12 @@ import Foundation
 
 class KMBatchAddPasswordOperation: KMBatchOperation{
     var passwordObj: KMSetPasswordObject?
-    var pdfDocument: PDFDocument?
+    var pdfDocument: CPDFDocument?
     
     init(file: KMBatchOperateFile, password: KMSetPasswordObject) {
         super.init(file: file)
         self.passwordObj = password
-        self.pdfDocument = PDFDocument(url: URL(fileURLWithPath: file.filePath))
+        self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: file.filePath))
         if ((self.pdfDocument?.isLocked) != nil) {
             self.pdfDocument?.unlock(withPassword: file.password)
         }
@@ -50,7 +50,7 @@ class KMBatchAddPasswordOperation: KMBatchOperation{
                 return
             }
          
-            let attributes = NSMutableDictionary(dictionary: self.pdfDocument!.documentAttributes!, copyItems: true)
+            let attributes = NSMutableDictionary(dictionary: self.pdfDocument!.documentAttributes()!, copyItems: true)
             if ((self.passwordObj?.needOpenPassword) != nil) {
                 attributes.setValue(self.passwordObj?.openPassword, forKey: (kCGPDFContextUserPassword as NSString) as String)
             } else {
@@ -83,7 +83,7 @@ class KMBatchAddPasswordOperation: KMBatchOperation{
             if self.passwordObj?.keyword.count ?? 0 > 0 {
                 attributes.setValue([self.passwordObj?.keyword], forKey: kCGPDFContextKeywords as String)
             }
-            let isSuccess = self.pdfDocument?.write(toFile: (self.operateFile?.addPasswordInfo.fetchDestinationFilepath())!, withOptions: (attributes as? [PDFDocumentWriteOption : Any]))
+            let isSuccess = self.pdfDocument?.write(toFile: (self.operateFile?.addPasswordInfo.fetchDestinationFilepath())!, withOptions: (attributes as? [CPDFDocumentWriteOption : Any]))
             if isSuccess! {
                 self.delegate?.fileOperateSuccessed?(self.operateFile!, info: self.operateFile!.addPasswordInfo)
             } else {

+ 66 - 0
PDF Office/PDF Master/Class/PDFTools/HeaderFooter/Tools/KMDataVersionManager.swift

@@ -0,0 +1,66 @@
+//
+//  KMDataVersionManager.swift
+//  PDF Master
+//
+//  Created by liujiajie on 2023/11/7.
+//
+
+import Foundation
+
+let KMBatesManagerVersion = "KMBatesManagerVersion"
+
+class KMDataVersionManager: NSObject{
+    class func updateBatesData() -> Bool {
+        var defaults = UserDefaults.standard
+        if  (defaults.object(forKey: KMBatesManagerVersion) != nil) {
+            defaults.setValue("1", forKey: KMBatesManagerVersion)
+            return true
+        }
+        return false
+    }
+    
+    class func refrshBatesData(bates: KMHeaderFooterObject?) -> KMHeaderFooterObject? {
+        if bates == nil {
+            return nil
+        }
+        var str: String 
+        if bates?.batesDigits ?? 0 > 0 {
+            str = String(format: "%@<<%@,%ld>>%@", bates!.batesPrefixString, bates!.startString, bates!.batesDigits, bates!.batesSuffixString)
+        } else {
+            str =  String(format: "%@<<%@>>%@", bates!.batesPrefixString, bates!.startString, bates!.batesSuffixString)
+        }
+        bates!.topLeftString = KMDataVersionManager.newBateString(oldString: bates!.topLeftString, bates: bates!, match: str)
+        bates!.topCenterString = KMDataVersionManager.newBateString(oldString: bates!.topCenterString, bates: bates!, match: str)
+        bates!.topRightString = KMDataVersionManager.newBateString(oldString: bates!.topRightString, bates: bates!, match: str)
+        bates!.bottomLeftString = KMDataVersionManager.newBateString(oldString: bates!.bottomLeftString, bates: bates!, match: str)
+        bates!.bottomCenterString = KMDataVersionManager.newBateString(oldString: bates!.bottomCenterString, bates: bates!, match: str)
+        bates!.bottomRightString = KMDataVersionManager.newBateString(oldString: bates!.bottomRightString, bates: bates!, match: str)
+        return bates
+    }
+    class func newBateString(oldString: String, bates: KMHeaderFooterObject, match: String) -> String {
+        let regex = try! NSRegularExpression(pattern: match, options: []) 
+        let results = regex.matches(in: oldString, options: [], range: NSRange(location: 0, length: oldString.count))
+        var newString = oldString
+        for object in results {
+            let range = object.range 
+            var tString: String
+            if bates.batesDigits > 0 {
+                tString = "<<#(bates.batesDigits)#(bates.startString)"
+            } else {
+                tString = "<<#(bates.startString)"
+            }
+            if bates.batesPrefixString.count > 0 {
+                tString += "#\(bates.batesPrefixString)"
+            } else if bates.batesPrefixString.count < 1 && bates.batesSuffixString.count > 0 {
+                tString += "#"
+            }
+            if bates.batesSuffixString.count > 0 {
+                tString += "#\(bates.batesSuffixString)"
+            }
+            tString += ">>"
+            let resultStr = (oldString as NSString).substring(with: range) 
+            newString = newString.replacingOccurrences(of: resultStr, with: tString)
+        }
+        return newString
+    }
+}

+ 341 - 2
PDF Office/PDF Master/Class/PDFTools/HeaderFooter/Tools/KMHeaderFooterManager.swift

@@ -7,14 +7,304 @@
 
 import Cocoa
 
-class KMHeaderFooterManager: NSObject {
+let kHeaderFooterInfoSaveKey = "kHeaderFooterInfoSaveKey"
+
+class KMHeaderFooterObject: NSObject, NSCopying, NSCoding{
+    var type: KMBatchHeaderFooterType = .HeaderFooter
+    var leftMargin: Int = 30
+    var rightMargin: Int = 30
+    var bottomMargin: Int = 30
+    var topMargin: Int = 30
+    var topLeftString: String = ""
+    var topCenterString: String = ""
+    var topRightString: String = ""
+    var bottomLeftString: String = ""
+    var bottomCenterString: String = ""
+    var bottomRightString: String = ""
+    var startString: String = "1"
+    var fontSize: CGFloat = 16.0
+    var textColor: NSColor = .black
+    var pagesString: String = ""
+    var isBates: Bool = false
+    var batesPrefixString: String = ""
+    var batesSuffixString: String = ""
+    var batesDigits: Int = 0
+    var hasHeader: Bool = false
+    var hasFooter: Bool = false
+    var cellHeight: CGFloat = 0.0{
+        willSet{
+            
+        }
+        didSet {
+            if cellHeight < 0.1 {
+                var baseHeight: CGFloat = 33.0 + 24.0
+                if self.topLeftString.count > 0 {
+                    baseHeight += 20.0
+                }
+                
+                if topCenterString.count > 0 {
+                    baseHeight += 20.0
+                }
+                
+                if topRightString.count > 0 {
+                    baseHeight += 20.0
+                }
+                
+                if bottomLeftString.count > 0 {
+                    baseHeight += 20.0
+                }
+                
+                if bottomCenterString.count > 0 {
+                    baseHeight += 20.0
+                }
+                
+                if bottomRightString.count > 0 {
+                    baseHeight += 20.0
+                }
+                
+                baseHeight -= 4.0
+                cellHeight = baseHeight
+            }
+        }
+    }
+    var headerFooterID: String = ""
+    var pageChoice: KMBatchOperatePageChoice = .All
+    var dateFormatString: String = "m/d"
+    var pageFormatString: String = "1"
+    
+    override init() {
+        super.init()
+        self.topLeftString = ""
+        self.topCenterString = ""
+        self.topRightString = ""
+        self.bottomLeftString = ""
+        self.bottomCenterString = ""
+        self.bottomRightString = ""
+        self.startString = ""
+        self.pagesString = ""
+        self.batesPrefixString = ""
+        self.batesSuffixString = ""
+        self.headerFooterID = ""
+        self.fontSize = 16.0
+        self.dateFormatString = "m/d"
+        self.startString = "1"
+        self.pageFormatString = "1"
+        self.textColor = .black
+        self.leftMargin = 30
+        self.rightMargin = 30
+        self.topMargin = 30
+        self.bottomMargin = 30
+    }
+    
+    func copy(with zone: NSZone? = nil) -> Any {
+        var obj: KMHeaderFooterObject  = KMHeaderFooterObject()
+        obj.type = self.type
+        obj.leftMargin = self.leftMargin
+        obj.rightMargin = self.rightMargin
+        obj.bottomMargin = self.bottomMargin
+        obj.topMargin = self.topMargin
+        obj.topLeftString = self.topLeftString
+        obj.topCenterString = self.topCenterString
+        obj.topRightString = self.topRightString
+        obj.bottomLeftString = self.bottomLeftString
+        obj.bottomCenterString = self.bottomCenterString
+        obj.bottomRightString = self.bottomRightString
+        obj.startString = self.startString
+        obj.fontSize = self.fontSize
+        obj.textColor = self.textColor
+        obj.pagesString = self.pagesString
+        obj.isBates = self.isBates
+        obj.batesPrefixString = self.batesPrefixString
+        obj.batesSuffixString = self.batesSuffixString
+        obj.batesDigits = self.batesDigits
+        obj.headerFooterID = self.headerFooterID
+        obj.hasHeader = self.hasHeader
+        obj.hasFooter = self.hasFooter
+        obj.pageChoice = self.pageChoice
+        obj.pageFormatString = self.pageFormatString
+        obj.dateFormatString = self.dateFormatString
+        return obj;
+    }
+    
+    func encode(with coder: NSCoder) {
+        coder.encode(self.type.rawValue, forKey: "type")
+        coder.encode(self.leftMargin, forKey: "leftMargin")
+        coder.encode(self.rightMargin, forKey: "rightMargin")
+        coder.encode(self.bottomMargin, forKey: "bottomMargin")
+        coder.encode(self.topMargin, forKey: "topMargin")
+        
+        coder.encode(self.topLeftString, forKey: "topLeftString")
+        
+        coder.encode(self.topCenterString, forKey: "topCenterString")
+        coder.encode(self.topRightString, forKey: "topRightString")
+        coder.encode(self.bottomLeftString, forKey: "bottomLeftString")
+        coder.encode(self.bottomCenterString, forKey: "bottomCenterString")
+        coder.encode(self.bottomRightString, forKey: "bottomRightString")
+        coder.encode(self.startString, forKey: "startString")
+        coder.encode(self.fontSize, forKey: "fontSize")
+        coder.encode(self.textColor, forKey: "textColor")
+        
+        coder.encode(self.pagesString, forKey: "pagesString")
+        coder.encode(self.isBates, forKey: "isBates")
+        coder.encode(self.batesPrefixString, forKey: "batesPrefixString")
+        coder.encode(self.batesSuffixString, forKey: "batesSuffixString")
+        coder.encode(self.batesDigits, forKey: "batesDigits")
+        coder.encode(self.hasHeader, forKey: "hasHeader")
+        coder.encode(self.hasFooter, forKey: "hasFooter")
+        coder.encode(self.cellHeight, forKey: "cellHeight")
+        coder.encode(self.headerFooterID, forKey: "headerFooterID")
+        coder.encode(self.pageChoice, forKey: "pageChoice")
+        coder.encode(self.dateFormatString, forKey: "dateFormatString")
+        coder.encode(self.pageFormatString, forKey: "pageFormatString")
+    }
+    
+    required init?(coder: NSCoder) {
+        type = KMBatchHeaderFooterType(rawValue: coder.decodeInteger(forKey: "type")) ?? .HeaderFooter
+        leftMargin = coder.decodeInteger(forKey: "leftMargin")
+        rightMargin = coder.decodeInteger(forKey: "rightMargin")
+        bottomMargin = coder.decodeInteger(forKey: "bottomMargin")
+        topMargin = coder.decodeInteger(forKey: "topMargin")
+        topLeftString = coder.decodeObject(forKey: "topLeftString") as! String
+        topCenterString = coder.decodeObject(forKey: "topCenterString") as! String
+        topRightString = coder.decodeObject(forKey: "topRightString") as! String
+        
+        bottomLeftString = coder.decodeObject(forKey: "bottomLeftString") as! String
+        bottomCenterString = coder.decodeObject(forKey: "bottomCenterString") as! String
+        bottomRightString = coder.decodeObject(forKey: "bottomCenterString") as! String
+        startString = coder.decodeObject(forKey: "startString") as! String
+        fontSize = CGFloat(coder.decodeFloat(forKey: "fontSize"))
+        textColor = coder.decodeObject(forKey: "textColor") as! NSColor
+        pagesString = coder.decodeObject(forKey: "pagesString") as! String
+        isBates = coder.decodeBool(forKey: "isBates")
+        batesPrefixString = coder.decodeObject(forKey: "batesPrefixString") as! String
+        batesSuffixString = coder.decodeObject(forKey: "batesSuffixString") as! String
+        batesDigits = coder.decodeInteger(forKey: "batesDigits")
+        hasHeader = coder.decodeBool(forKey: "hasHeader")
+        hasFooter = coder.decodeBool(forKey: "hasFooter")
+        cellHeight = CGFloat(coder.decodeFloat(forKey: "cellHeight"))
+        headerFooterID = coder.decodeObject(forKey: "headerFooterID") as! String
+        pageChoice = KMBatchOperatePageChoice(rawValue: coder.decodeInteger(forKey: "pageChoice")) ?? .All
+        dateFormatString = coder.decodeObject(forKey: "dateFormatString") as! String
+        pageFormatString =  coder.decodeObject(forKey: "pageFormatString") as! String
+    }
+    
+    func copyData(dataObj: KMHeaderFooterObject) {
+        type = dataObj.type
+        leftMargin = dataObj.leftMargin
+        rightMargin = dataObj.rightMargin
+        bottomMargin = dataObj.bottomMargin
+        topMargin = dataObj.topMargin
+        topLeftString = dataObj.topLeftString
+        topCenterString = dataObj.topCenterString
+        topRightString = dataObj.topRightString
+        bottomLeftString = dataObj.bottomLeftString
+        bottomCenterString = dataObj.bottomCenterString
+        bottomRightString = dataObj.bottomRightString
+        startString = dataObj.startString
+        fontSize = dataObj.fontSize
+        textColor = dataObj.textColor
+        pagesString = dataObj.pagesString
+        isBates = dataObj.isBates
+        batesPrefixString = dataObj.batesPrefixString
+        batesSuffixString = dataObj.batesSuffixString
+        batesDigits = dataObj.batesDigits
+        hasHeader = dataObj.hasHeader
+        hasFooter = dataObj.hasFooter
+        cellHeight = dataObj.cellHeight
+        headerFooterID = dataObj.headerFooterID
+        pageChoice = dataObj.pageChoice
+        dateFormatString = dataObj.dateFormatString
+        pageFormatString = dataObj.pageFormatString
+    }
+}
+
+
+class KMHeaderFooterManager: NSObject, NSCoding{
+    
+    
     let kFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("headerfooter")
     let kPlistPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("headerfooter").stringByAppendingPathComponent("headerfooter.plist")
     
-    static let defaultManager = KMHeaderFooterManager()
+    static let defaultManager: KMHeaderFooterManager = {
+        var manager = KMHeaderFooterManager()
+        if let storedData = UserDefaults.standard.value(forKey: kHeaderFooterInfoSaveKey) as? Data {
+            manager = NSKeyedUnarchiver.unarchiveObject(with: storedData) as! KMHeaderFooterManager
+        } else {
+            manager = KMHeaderFooterManager()
+            if manager.headFooterObjects == nil {
+                manager.headFooterObjects = []
+            }
+        }
+        return manager
+    }()
+    
+    func encode(with coder: NSCoder) {
+        coder.encode(self.headFooterObjects, forKey: "headFooterObjects")
+    }
+    
+    required init?(coder: NSCoder) {
+        self.headFooterObjects = coder.decodeObject(forKey: "headFooterObjects") as? [KMHeaderFooterObject]
+    }
     
     var datas: Array<KMHeaderFooterModel> = []
     
+    var headFooterObjects: [KMHeaderFooterObject]?
+    
+    lazy var dateFormatArray: Array = {
+        let arr = [
+            "m/d",
+            "m/d/yy",
+            "m/d/yyyy",
+            "mm/dd/yy",
+            "mm/dd/yyyy",
+            "d/m/yy",
+            "d/m/yyyy",
+            "dd/mm/yy",
+            "dd/mm/yyyy",
+            "mm/yy",
+            "mm/yyyy",
+            "m.d.yy",
+            "m.d.yyyy",
+            "mm.dd.yy",
+            "mm.dd.yyyy",
+            "mm.yy",
+            "mm.yyyy",
+            "d.m.yy",
+            "d.m.yyyy",
+            "dd.mm.yy",
+            "dd.mm.yyyy",
+            "yy-mm-dd",
+            "yyyy-mm-dd"
+        ]
+        return arr
+    }()
+    
+    lazy var onlyBatesObjects: [KMHeaderFooterObject] = {
+        var arr: [KMHeaderFooterObject] = Array<KMHeaderFooterObject>()
+        for i in 0..<(headFooterObjects?.count ?? 0) {
+            let obj = headFooterObjects?[i]
+            if KMDataVersionManager.updateBatesData() {
+                KMDataVersionManager.refrshBatesData(bates: obj)
+                store()
+            }
+            
+            if obj!.isBates {
+                arr.append(obj!)
+            }
+        }
+        return arr
+    }()
+    lazy var onlyHeaderFooterObjects: [KMHeaderFooterObject] = {
+        var arr: [KMHeaderFooterObject] = Array<KMHeaderFooterObject>()
+        for i in 0..<(headFooterObjects?.count ?? 0) {
+            let obj = headFooterObjects?[i]
+            
+            if !obj!.isBates {
+                arr.append(obj!)
+            }
+        }
+        return arr
+    }()
     override init() {
         super.init()
         if (FileManager.default.fileExists(atPath: kPlistPath!)) {
@@ -38,6 +328,51 @@ class KMHeaderFooterManager: NSObject {
         }
     }
     
+    func store() { 
+        let encodedObject = NSKeyedArchiver.archivedData(withRootObject: self)
+        let defaults = UserDefaults.standard 
+        defaults.set(encodedObject, forKey: kHeaderFooterInfoSaveKey)
+        defaults.synchronize()
+    }
+    
+    func fetchBatesAvailableName() -> String {
+        var availableIndex = 0
+        let nameArray = converArrType(arr: onlyBatesObjects, keyString: "headerFooterID")
+        for i in 0..<nameArray.count {
+            let string = nameArray[i]
+            if string.hasPrefix("Bates") {
+                let index = Int(string.substring(from: "Bates".endIndex))!
+                if index >= availableIndex {
+                    availableIndex = index + 1
+                }
+            }
+        }
+        return String(format: "Bates%ld", availableIndex)
+    }
+    
+    func fetchHeaderFooterAvailableName() -> String {
+        var availableIndex = 0
+        let nameArray = converArrType(arr: onlyHeaderFooterObjects, keyString: "headerFooterID")
+        for i in 0..<nameArray.count {
+            let string = nameArray[i]
+            if string.hasPrefix("HeaderFooter") {
+                let index = Int(string.substring(from: "HeaderFooter".endIndex))!
+                if index >= availableIndex {
+                    availableIndex = index + 1
+                }
+            }
+        }
+        return  String(format: "HeaderFooter%ld", availableIndex)
+    }
+    
+    func converArrType(arr: Array<KMHeaderFooterObject>, keyString: String) -> [String] {
+        var newArr = NSMutableArray()
+        for item in arr {
+            newArr.add(item.headerFooterID)
+        }
+        return newArr as! [String]
+    }
+    
     func addTemplate(_ model: KMHeaderFooterModel) -> Bool {
         if (!FileManager.default.fileExists(atPath: kFolderPath!)) {
             let create: ()? = try?FileManager.default.createDirectory(atPath: kFolderPath!, withIntermediateDirectories: false)
@@ -175,6 +510,10 @@ class KMHeaderFooterManager: NSObject {
         
         return result
     }
+    func removeHeaderFooter(_ obj: KMHeaderFooterObject) {
+        self.headFooterObjects?.removeObject(obj) 
+        self.store()
+    }
     
     /**
         `Private Methods`