diff --git a/Podfile b/Podfile index d7af0ab..f85d616 100644 --- a/Podfile +++ b/Podfile @@ -4,6 +4,6 @@ platform :ios, '8.0' inhibit_all_warnings! target 'mapcache-ios' do - pod 'geopackage-ios', '~> 3.3.0' + pod 'geopackage-ios', '~> 4.0.1' pod 'Fingertips', '~> 0.5.0' end diff --git a/mapcache-ios-geopackage.sketch b/mapcache-ios-geopackage.sketch index 2b68c6f..ba80196 100644 Binary files a/mapcache-ios-geopackage.sketch and b/mapcache-ios-geopackage.sketch differ diff --git a/mapcache-ios.xcodeproj/project.pbxproj b/mapcache-ios.xcodeproj/project.pbxproj index 1e9024c..ee7938e 100644 --- a/mapcache-ios.xcodeproj/project.pbxproj +++ b/mapcache-ios.xcodeproj/project.pbxproj @@ -9,12 +9,11 @@ /* Begin PBXBuildFile section */ 040136751AF94FB200C92AFC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 040136741AF94FB200C92AFC /* main.m */; }; 040136781AF94FB200C92AFC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 040136771AF94FB200C92AFC /* AppDelegate.m */; }; - 040136811AF94FB200C92AFC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0401367F1AF94FB200C92AFC /* Main.storyboard */; }; 040136831AF94FB200C92AFC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 040136821AF94FB200C92AFC /* Images.xcassets */; }; 040136861AF94FB200C92AFC /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 040136841AF94FB200C92AFC /* LaunchScreen.xib */; }; 040136921AF94FB200C92AFC /* mapcache_iosTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 040136911AF94FB200C92AFC /* mapcache_iosTests.m */; }; 04082B531B4EBE6F00D65E6B /* MCDownloadGeopackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 04082B521B4EBE6F00D65E6B /* MCDownloadGeopackage.m */; }; - 04082B561B4F18A000D65E6B /* GPKGSUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 04082B551B4F18A000D65E6B /* GPKGSUtils.m */; }; + 04082B561B4F18A000D65E6B /* MCUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 04082B551B4F18A000D65E6B /* MCUtils.m */; }; 043A45821B79442C001B8FC5 /* GPKGSDownloadTilesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 043A45811B79442C001B8FC5 /* GPKGSDownloadTilesViewController.m */; }; 043A45851B7A54C2001B8FC5 /* GPKGSSelectFeatureTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 043A45841B7A54C2001B8FC5 /* GPKGSSelectFeatureTableViewController.m */; }; 043A458B1B7E21E3001B8FC5 /* GPKGSMapPointData.m in Sources */ = {isa = PBXBuildFile; fileRef = 043A458A1B7E21E3001B8FC5 /* GPKGSMapPointData.m */; }; @@ -22,28 +21,26 @@ 043A45981B83B4AB001B8FC5 /* GPGKSMapPointInitializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 043A45971B83B4AB001B8FC5 /* GPGKSMapPointInitializer.m */; }; 043A459E1B84AA5D001B8FC5 /* GPKGSMapPointDataTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 043A459D1B84AA5D001B8FC5 /* GPKGSMapPointDataTypes.m */; }; 044647FC1B4AD1C00052913B /* GPKGSManagerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 044647FB1B4AD1C00052913B /* GPKGSManagerViewController.m */; }; - 044647FF1B4AF3870052913B /* GPKGSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 044647FE1B4AF3870052913B /* GPKGSTable.m */; }; - 044648021B4AF4250052913B /* GPKGSTableTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648011B4AF4250052913B /* GPKGSTableTypes.m */; }; - 044648051B4AF6990052913B /* GPKGSFeatureTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648041B4AF6990052913B /* GPKGSFeatureTable.m */; }; - 044648081B4AF6A70052913B /* GPKGSTileTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648071B4AF6A70052913B /* GPKGSTileTable.m */; }; - 0446480B1B4AFC100052913B /* GPKGSDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0446480A1B4AFC100052913B /* GPKGSDatabase.m */; }; + 044647FF1B4AF3870052913B /* MCTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 044647FE1B4AF3870052913B /* MCTable.m */; }; + 044648021B4AF4250052913B /* MCTableTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648011B4AF4250052913B /* MCTableTypes.m */; }; + 044648051B4AF6990052913B /* MCFeatureTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648041B4AF6990052913B /* MCFeatureTable.m */; }; + 044648081B4AF6A70052913B /* MCTileTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648071B4AF6A70052913B /* MCTileTable.m */; }; + 0446480B1B4AFC100052913B /* MCDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0446480A1B4AFC100052913B /* MCDatabase.m */; }; 044648111B4B1D960052913B /* GPKGSTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648101B4B1D960052913B /* GPKGSTableCell.m */; }; 044648141B4B20950052913B /* GPKGSDatabaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648131B4B20950052913B /* GPKGSDatabaseCell.m */; }; 0446481A1B4C24AD0052913B /* GPKGSActiveTableSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 044648191B4C24AD0052913B /* GPKGSActiveTableSwitch.m */; }; - 0446481E1B4C26DF0052913B /* GPKGSConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 0446481D1B4C26DF0052913B /* GPKGSConstants.m */; }; - 044D6B4B1B627B0000527745 /* GPKGSLoadTilesTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 044D6B4A1B627B0000527745 /* GPKGSLoadTilesTask.m */; }; + 0446481E1B4C26DF0052913B /* MCConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 0446481D1B4C26DF0052913B /* MCConstants.m */; }; + 044D6B4B1B627B0000527745 /* MCLoadTilesTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 044D6B4A1B627B0000527745 /* MCLoadTilesTask.m */; }; 045C94831B4FFE7E0005CCD0 /* GPKGSDisplayTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94821B4FFE7E0005CCD0 /* GPKGSDisplayTextViewController.m */; }; - 045C94861B50226D0005CCD0 /* GPKGSFeatureOverlayTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94851B50226D0005CCD0 /* GPKGSFeatureOverlayTable.m */; }; - 045C94891B5026E00005CCD0 /* GPKGSDatabases.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94881B5026E00005CCD0 /* GPKGSDatabases.m */; }; - 045C948D1B50789D0005CCD0 /* GPKGSMapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C948C1B50789D0005CCD0 /* GPKGSMapView.m */; }; - 045C94901B53EEB80005CCD0 /* GPKGSMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C948F1B53EEB80005CCD0 /* GPKGSMapViewController.m */; }; - 045C94941B56DF620005CCD0 /* GPKGSIndexerTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94931B56DF620005CCD0 /* GPKGSIndexerTask.m */; }; + 045C94861B50226D0005CCD0 /* MCFeatureOverlayTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94851B50226D0005CCD0 /* MCFeatureOverlayTable.m */; }; + 045C94891B5026E00005CCD0 /* MCDatabases.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94881B5026E00005CCD0 /* MCDatabases.m */; }; + 045C94941B56DF620005CCD0 /* MCIndexerTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94931B56DF620005CCD0 /* MCIndexerTask.m */; }; 045C94981B5D384A0005CCD0 /* GPKGSCreateFeaturesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94971B5D384A0005CCD0 /* GPKGSCreateFeaturesViewController.m */; }; - 045C949B1B5D4C560005CCD0 /* GPKGSDecimalValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C949A1B5D4C560005CCD0 /* GPKGSDecimalValidator.m */; }; + 045C949B1B5D4C560005CCD0 /* MCDecimalValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C949A1B5D4C560005CCD0 /* MCDecimalValidator.m */; }; 045C94A91B5DA5C20005CCD0 /* GPKGSBoundingBoxViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 045C94A81B5DA5C20005CCD0 /* GPKGSBoundingBoxViewController.m */; }; 046877F81C68FE9400967470 /* GPKGSLinkedTablesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 046877F71C68FE9400967470 /* GPKGSLinkedTablesViewController.m */; }; 047733BE1B4C371500E523BD /* GPKGSDatabaseOptionsButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 047733BD1B4C371500E523BD /* GPKGSDatabaseOptionsButton.m */; }; - 047733C41B4C3D1200E523BD /* GPKGSProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 047733C31B4C3D1200E523BD /* GPKGSProperties.m */; }; + 047733C41B4C3D1200E523BD /* MCProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 047733C31B4C3D1200E523BD /* MCProperties.m */; }; 047733C61B4C3E3400E523BD /* mapcache.plist in Resources */ = {isa = PBXBuildFile; fileRef = 047733C51B4C3E3400E523BD /* mapcache.plist */; }; 047733C91B4C496600E523BD /* GPKGSTableOptionsButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 047733C81B4C496600E523BD /* GPKGSTableOptionsButton.m */; }; 048C212B1AFBCC9400EBC38B /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 048C212A1AFBCC9400EBC38B /* libsqlite3.dylib */; }; @@ -56,7 +53,7 @@ 04CCC86E1B6122040001296D /* GPKGSLoadTilesData.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CCC86D1B6122040001296D /* GPKGSLoadTilesData.m */; }; 04CCC8711B6122480001296D /* GPKGSCreateTilesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CCC8701B6122480001296D /* GPKGSCreateTilesViewController.m */; }; 04CCC8741B61228D0001296D /* GPKGSCreateTilesData.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CCC8731B61228D0001296D /* GPKGSCreateTilesData.m */; }; - 04DD108E1BD9443F00CC59A0 /* GPKGSTableIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 04DD108D1BD9443F00CC59A0 /* GPKGSTableIndex.m */; }; + 04DD108E1BD9443F00CC59A0 /* MCTableIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 04DD108D1BD9443F00CC59A0 /* MCTableIndex.m */; }; 04E0EE051B69112B0095E53E /* GPKGSAddTileOverlayViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0EE041B69112B0095E53E /* GPKGSAddTileOverlayViewController.m */; }; 04E0EE081B6919D80095E53E /* GPKGSEditTileOverlayViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0EE071B6919D80095E53E /* GPKGSEditTileOverlayViewController.m */; }; 04E0EE0B1B691A3C0095E53E /* GPKGSEditTileOverlayData.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0EE0A1B691A3C0095E53E /* GPKGSEditTileOverlayData.m */; }; @@ -74,11 +71,11 @@ E300A93623313DCE002336A0 /* MCBoundingBoxGuideView.m in Sources */ = {isa = PBXBuildFile; fileRef = E300A93523313DCE002336A0 /* MCBoundingBoxGuideView.m */; }; E300A93923315B9D002336A0 /* MCBoundingBoxPassthroughView.m in Sources */ = {isa = PBXBuildFile; fileRef = E300A93823315B9D002336A0 /* MCBoundingBoxPassthroughView.m */; }; E307AD5A23C52AE200771D29 /* MCTileServerHelpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E307AD5923C52AE200771D29 /* MCTileServerHelpViewController.m */; }; - E308FBC11FBE400500348577 /* MCSingleGeoPackageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E308FBC01FBE400500348577 /* MCSingleGeoPackageView.xib */; }; E308FBC61FBFA7CA00348577 /* MCHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E308FBC51FBFA7CA00348577 /* MCHeaderCell.m */; }; E3100EAF203CAF1E00FFA56E /* MCZoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E3100EAE203CAF1E00FFA56E /* MCZoomCell.xib */; }; E312A3381FAA416500C088FB /* MCDownloadCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = E312A3371FAA416500C088FB /* MCDownloadCoordinator.m */; }; - E331C8ED20FE7645006EFED1 /* MCLayerCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = E331C8EC20FE7645006EFED1 /* MCLayerCoordinator.m */; }; + E31BD62D244E2E2600C18609 /* MCKeyValueDisplayCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E31BD62C244E2E2600C18609 /* MCKeyValueDisplayCell.xib */; }; + E31BD630244E340300C18609 /* MCKeyValueDisplayCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E31BD62F244E340300C18609 /* MCKeyValueDisplayCell.m */; }; E331C8F0210110B3006EFED1 /* MCTileLayerOperationsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E331C8EF210110B3006EFED1 /* MCTileLayerOperationsCell.m */; }; E33F55721FC4A1C000F252FD /* MCSectionTitleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E33F55711FC4A1C000F252FD /* MCSectionTitleCell.xib */; }; E33F55751FC4A25500F252FD /* MCSectionTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E33F55741FC4A25500F252FD /* MCSectionTitleCell.m */; }; @@ -89,6 +86,7 @@ E33FB474202506B500AF509B /* MCBoundingBoxView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E33FB473202506B500AF509B /* MCBoundingBoxView.xib */; }; E3463DE921545F4B00D64FFC /* MCTileHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E3463DE821545F4B00D64FFC /* MCTileHelper.m */; }; E346590F202BB20B001E6E81 /* MCZoomAndQualityViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E346590E202BB20B001E6E81 /* MCZoomAndQualityViewController.m */; }; + E346EC7E2448C23C001A646A /* MCMapPointDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E346EC7D2448C23C001A646A /* MCMapPointDataViewController.m */; }; E3470CC72020E67E0098D783 /* MCColorUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = E3470CC62020E67D0098D783 /* MCColorUtil.m */; }; E3470CC9202126140098D783 /* MCSegmentedControlCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E3470CC8202126140098D783 /* MCSegmentedControlCell.xib */; }; E3470CCC2021962D0098D783 /* MCSegmentedControlCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E3470CCB2021962D0098D783 /* MCSegmentedControlCell.m */; }; @@ -113,7 +111,6 @@ E35B631121BC26F9004E5BB0 /* MCTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E35B631021BC26F9004E5BB0 /* MCTitleCell.m */; }; E35F316221EE7FC2001B720F /* privacypolicy in Resources */ = {isa = PBXBuildFile; fileRef = E35F316121EE7FC2001B720F /* privacypolicy */; }; E35F316521EFEC7E001B720F /* MCNoticeAndAttributionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E35F316421EFEC7E001B720F /* MCNoticeAndAttributionViewController.m */; }; - E363F53B20EC24B200BBF91A /* MCLayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E363F53A20EC24B200BBF91A /* MCLayerViewController.m */; }; E363F54320EFD5A700BBF91A /* MCFeatureLayerOperationsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E363F54220EFD5A700BBF91A /* MCFeatureLayerOperationsCell.xib */; }; E363F54520F0177700BBF91A /* MCTileLayerOperationsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E363F54420F0177700BBF91A /* MCTileLayerOperationsCell.xib */; }; E36D2DCE2017BFBE0097A8DE /* MCPickerViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E36D2DCD2017BFBE0097A8DE /* MCPickerViewCell.xib */; }; @@ -127,16 +124,24 @@ E3A651AD2004407600B8AB27 /* MCFieldWithTitleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E3A651AC2004407600B8AB27 /* MCFieldWithTitleCell.xib */; }; E3A651B0200563AF00B8AB27 /* MCTileLayerDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3A651AF200563AF00B8AB27 /* MCTileLayerDetailsViewController.m */; }; E3A651B32005652400B8AB27 /* MCFieldWithTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E3A651B22005652400B8AB27 /* MCFieldWithTitleCell.m */; }; + E3B7DD502475F1ED00215EF5 /* MCCreateLayerFieldViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B7DD4C2475F1EB00215EF5 /* MCCreateLayerFieldViewController.swift */; }; + E3B7DD512475F1ED00215EF5 /* MCLayerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B7DD4E2475F1EC00215EF5 /* MCLayerCoordinator.swift */; }; E3B9753B1FB3DED400E33E0A /* MCHeaderCellDisplay.xib in Resources */ = {isa = PBXBuildFile; fileRef = E3B9753A1FB3DED400E33E0A /* MCHeaderCellDisplay.xib */; }; E3BED1E0219116FA001AF654 /* MCSettingsCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = E3BED1DF219116FA001AF654 /* MCSettingsCoordinator.m */; }; E3BED1E321911712001AF654 /* MCSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3BED1E221911712001AF654 /* MCSettingsViewController.m */; }; + E3C5FC4824B7D38F00B5E12E /* MCTileMatrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3C5FC4724B7D38F00B5E12E /* MCTileMatrix.swift */; }; E3CF687223D901750005A6EF /* MCTileServerURLManagerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3CF687123D901740005A6EF /* MCTileServerURLManagerViewController.m */; }; E3CF687423DA5FF20005A6EF /* MCTextViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E3CF687323DA5FF20005A6EF /* MCTextViewCell.xib */; }; E3CF687723DA667E0005A6EF /* MCTextViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E3CF687623DA667E0005A6EF /* MCTextViewCell.m */; }; E3CF687A23DA6AC40005A6EF /* MCNewTileServerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3CF687923DA6AC40005A6EF /* MCNewTileServerViewController.m */; }; + E3D651D3240D90340082FF10 /* MCGeoPackageRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = E3D651D2240D90340082FF10 /* MCGeoPackageRepository.m */; }; + E3D80EA223FF59E3006F1014 /* MCDrawingStatusViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3D80EA123FF59E3006F1014 /* MCDrawingStatusViewController.m */; }; + E3D80EA5240076AD006F1014 /* MCDualButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E3D80EA4240076AD006F1014 /* MCDualButtonCell.m */; }; + E3D80EA7240076CC006F1014 /* MCDualButtonCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E3D80EA6240076CC006F1014 /* MCDualButtonCell.xib */; }; E3DE0DEA23E2420D00CB27AF /* UITextView+Validators.m in Sources */ = {isa = PBXBuildFile; fileRef = E3DE0DE923E2420D00CB27AF /* UITextView+Validators.m */; }; E3DE0DED23E3781800CB27AF /* MCCreateGeoPacakgeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3DE0DEC23E3781800CB27AF /* MCCreateGeoPacakgeViewController.m */; }; E3E9ED6923EA407E004C4530 /* mapcache_iosUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E3E9ED6823EA407E004C4530 /* mapcache_iosUITests.m */; }; + E3F9A99C2475F52400DFD043 /* MCLayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3B7DD4F2475F1EC00215EF5 /* MCLayerViewController.m */; }; E3FB856B2134955F002F012E /* NGADrawerCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = E3FB85682134955D002F012E /* NGADrawerCoordinator.m */; }; E3FB856C2134955F002F012E /* NGADrawerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3FB85692134955D002F012E /* NGADrawerViewController.m */; }; E3FB856F21349B5E002F012E /* MCMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3FB856E21349B5E002F012E /* MCMapViewController.m */; }; @@ -181,8 +186,8 @@ 040136911AF94FB200C92AFC /* mapcache_iosTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = mapcache_iosTests.m; sourceTree = ""; }; 04082B511B4EBE6F00D65E6B /* MCDownloadGeopackage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDownloadGeopackage.h; sourceTree = ""; }; 04082B521B4EBE6F00D65E6B /* MCDownloadGeopackage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCDownloadGeopackage.m; sourceTree = ""; }; - 04082B541B4F18A000D65E6B /* GPKGSUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSUtils.h; sourceTree = ""; }; - 04082B551B4F18A000D65E6B /* GPKGSUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSUtils.m; sourceTree = ""; }; + 04082B541B4F18A000D65E6B /* MCUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCUtils.h; sourceTree = ""; }; + 04082B551B4F18A000D65E6B /* MCUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCUtils.m; sourceTree = ""; }; 043A45801B79442C001B8FC5 /* GPKGSDownloadTilesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDownloadTilesViewController.h; sourceTree = ""; }; 043A45811B79442C001B8FC5 /* GPKGSDownloadTilesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDownloadTilesViewController.m; sourceTree = ""; }; 043A45831B7A54C2001B8FC5 /* GPKGSSelectFeatureTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSSelectFeatureTableViewController.h; sourceTree = ""; }; @@ -197,52 +202,52 @@ 043A459D1B84AA5D001B8FC5 /* GPKGSMapPointDataTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSMapPointDataTypes.m; sourceTree = ""; }; 044647FA1B4AD1C00052913B /* GPKGSManagerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSManagerViewController.h; sourceTree = ""; }; 044647FB1B4AD1C00052913B /* GPKGSManagerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSManagerViewController.m; sourceTree = ""; }; - 044647FD1B4AF3870052913B /* GPKGSTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSTable.h; sourceTree = ""; }; - 044647FE1B4AF3870052913B /* GPKGSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSTable.m; sourceTree = ""; }; - 044648001B4AF4250052913B /* GPKGSTableTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSTableTypes.h; sourceTree = ""; }; - 044648011B4AF4250052913B /* GPKGSTableTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSTableTypes.m; sourceTree = ""; }; - 044648031B4AF6990052913B /* GPKGSFeatureTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSFeatureTable.h; sourceTree = ""; }; - 044648041B4AF6990052913B /* GPKGSFeatureTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSFeatureTable.m; sourceTree = ""; }; - 044648061B4AF6A70052913B /* GPKGSTileTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSTileTable.h; sourceTree = ""; }; - 044648071B4AF6A70052913B /* GPKGSTileTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSTileTable.m; sourceTree = ""; }; - 044648091B4AFC100052913B /* GPKGSDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDatabase.h; sourceTree = ""; }; - 0446480A1B4AFC100052913B /* GPKGSDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDatabase.m; sourceTree = ""; }; + 044647FD1B4AF3870052913B /* MCTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCTable.h; sourceTree = ""; }; + 044647FE1B4AF3870052913B /* MCTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCTable.m; sourceTree = ""; }; + 044648001B4AF4250052913B /* MCTableTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCTableTypes.h; sourceTree = ""; }; + 044648011B4AF4250052913B /* MCTableTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCTableTypes.m; sourceTree = ""; }; + 044648031B4AF6990052913B /* MCFeatureTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCFeatureTable.h; sourceTree = ""; }; + 044648041B4AF6990052913B /* MCFeatureTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCFeatureTable.m; sourceTree = ""; }; + 044648061B4AF6A70052913B /* MCTileTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCTileTable.h; sourceTree = ""; }; + 044648071B4AF6A70052913B /* MCTileTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCTileTable.m; sourceTree = ""; }; + 044648091B4AFC100052913B /* MCDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDatabase.h; sourceTree = ""; }; + 0446480A1B4AFC100052913B /* MCDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCDatabase.m; sourceTree = ""; }; 0446480F1B4B1D960052913B /* GPKGSTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSTableCell.h; sourceTree = ""; }; 044648101B4B1D960052913B /* GPKGSTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSTableCell.m; sourceTree = ""; }; 044648121B4B20950052913B /* GPKGSDatabaseCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDatabaseCell.h; sourceTree = ""; }; 044648131B4B20950052913B /* GPKGSDatabaseCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDatabaseCell.m; sourceTree = ""; }; 044648181B4C24AD0052913B /* GPKGSActiveTableSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSActiveTableSwitch.h; sourceTree = ""; }; 044648191B4C24AD0052913B /* GPKGSActiveTableSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSActiveTableSwitch.m; sourceTree = ""; }; - 0446481C1B4C26DF0052913B /* GPKGSConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSConstants.h; sourceTree = ""; }; - 0446481D1B4C26DF0052913B /* GPKGSConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSConstants.m; sourceTree = ""; }; - 044D6B491B627B0000527745 /* GPKGSLoadTilesTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSLoadTilesTask.h; sourceTree = ""; }; - 044D6B4A1B627B0000527745 /* GPKGSLoadTilesTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSLoadTilesTask.m; sourceTree = ""; }; + 0446481C1B4C26DF0052913B /* MCConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCConstants.h; sourceTree = ""; }; + 0446481D1B4C26DF0052913B /* MCConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCConstants.m; sourceTree = ""; }; + 044D6B491B627B0000527745 /* MCLoadTilesTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLoadTilesTask.h; sourceTree = ""; }; + 044D6B4A1B627B0000527745 /* MCLoadTilesTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCLoadTilesTask.m; sourceTree = ""; }; 044D6B4C1B627B2200527745 /* GPKGSLoadTilesProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSLoadTilesProtocol.h; sourceTree = ""; }; 045C94811B4FFE7E0005CCD0 /* GPKGSDisplayTextViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDisplayTextViewController.h; sourceTree = ""; }; 045C94821B4FFE7E0005CCD0 /* GPKGSDisplayTextViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDisplayTextViewController.m; sourceTree = ""; }; - 045C94841B50226D0005CCD0 /* GPKGSFeatureOverlayTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSFeatureOverlayTable.h; sourceTree = ""; }; - 045C94851B50226D0005CCD0 /* GPKGSFeatureOverlayTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSFeatureOverlayTable.m; sourceTree = ""; }; - 045C94871B5026E00005CCD0 /* GPKGSDatabases.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDatabases.h; sourceTree = ""; }; - 045C94881B5026E00005CCD0 /* GPKGSDatabases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDatabases.m; sourceTree = ""; }; + 045C94841B50226D0005CCD0 /* MCFeatureOverlayTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCFeatureOverlayTable.h; sourceTree = ""; }; + 045C94851B50226D0005CCD0 /* MCFeatureOverlayTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCFeatureOverlayTable.m; sourceTree = ""; }; + 045C94871B5026E00005CCD0 /* MCDatabases.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDatabases.h; sourceTree = ""; }; + 045C94881B5026E00005CCD0 /* MCDatabases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCDatabases.m; sourceTree = ""; }; 045C948B1B50789D0005CCD0 /* GPKGSMapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSMapView.h; sourceTree = ""; }; 045C948C1B50789D0005CCD0 /* GPKGSMapView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSMapView.m; sourceTree = ""; }; 045C948E1B53EEB80005CCD0 /* GPKGSMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSMapViewController.h; sourceTree = ""; }; 045C948F1B53EEB80005CCD0 /* GPKGSMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSMapViewController.m; sourceTree = ""; }; - 045C94921B56DF620005CCD0 /* GPKGSIndexerTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSIndexerTask.h; sourceTree = ""; }; - 045C94931B56DF620005CCD0 /* GPKGSIndexerTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSIndexerTask.m; sourceTree = ""; }; + 045C94921B56DF620005CCD0 /* MCIndexerTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIndexerTask.h; sourceTree = ""; }; + 045C94931B56DF620005CCD0 /* MCIndexerTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCIndexerTask.m; sourceTree = ""; }; 045C94951B56E1050005CCD0 /* GPKGSIndexerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSIndexerProtocol.h; sourceTree = ""; }; 045C94961B5D384A0005CCD0 /* GPKGSCreateFeaturesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSCreateFeaturesViewController.h; sourceTree = ""; }; 045C94971B5D384A0005CCD0 /* GPKGSCreateFeaturesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSCreateFeaturesViewController.m; sourceTree = ""; }; - 045C94991B5D4C560005CCD0 /* GPKGSDecimalValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDecimalValidator.h; sourceTree = ""; }; - 045C949A1B5D4C560005CCD0 /* GPKGSDecimalValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDecimalValidator.m; sourceTree = ""; }; + 045C94991B5D4C560005CCD0 /* MCDecimalValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDecimalValidator.h; sourceTree = ""; }; + 045C949A1B5D4C560005CCD0 /* MCDecimalValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCDecimalValidator.m; sourceTree = ""; }; 045C94A71B5DA5C20005CCD0 /* GPKGSBoundingBoxViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSBoundingBoxViewController.h; sourceTree = ""; }; 045C94A81B5DA5C20005CCD0 /* GPKGSBoundingBoxViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSBoundingBoxViewController.m; sourceTree = ""; }; 046877F61C68FE9400967470 /* GPKGSLinkedTablesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSLinkedTablesViewController.h; sourceTree = ""; }; 046877F71C68FE9400967470 /* GPKGSLinkedTablesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSLinkedTablesViewController.m; sourceTree = ""; }; 047733BC1B4C371500E523BD /* GPKGSDatabaseOptionsButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSDatabaseOptionsButton.h; sourceTree = ""; }; 047733BD1B4C371500E523BD /* GPKGSDatabaseOptionsButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSDatabaseOptionsButton.m; sourceTree = ""; }; - 047733C21B4C3D1200E523BD /* GPKGSProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSProperties.h; sourceTree = ""; }; - 047733C31B4C3D1200E523BD /* GPKGSProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSProperties.m; sourceTree = ""; }; + 047733C21B4C3D1200E523BD /* MCProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCProperties.h; sourceTree = ""; }; + 047733C31B4C3D1200E523BD /* MCProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCProperties.m; sourceTree = ""; }; 047733C51B4C3E3400E523BD /* mapcache.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = mapcache.plist; sourceTree = ""; }; 047733C71B4C496600E523BD /* GPKGSTableOptionsButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSTableOptionsButton.h; sourceTree = ""; }; 047733C81B4C496600E523BD /* GPKGSTableOptionsButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSTableOptionsButton.m; sourceTree = ""; }; @@ -265,8 +270,8 @@ 04CCC8701B6122480001296D /* GPKGSCreateTilesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSCreateTilesViewController.m; sourceTree = ""; }; 04CCC8721B61228D0001296D /* GPKGSCreateTilesData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSCreateTilesData.h; sourceTree = ""; }; 04CCC8731B61228D0001296D /* GPKGSCreateTilesData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSCreateTilesData.m; sourceTree = ""; }; - 04DD108C1BD9443F00CC59A0 /* GPKGSTableIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSTableIndex.h; sourceTree = ""; }; - 04DD108D1BD9443F00CC59A0 /* GPKGSTableIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSTableIndex.m; sourceTree = ""; }; + 04DD108C1BD9443F00CC59A0 /* MCTableIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCTableIndex.h; sourceTree = ""; }; + 04DD108D1BD9443F00CC59A0 /* MCTableIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCTableIndex.m; sourceTree = ""; }; 04E0EE031B69112B0095E53E /* GPKGSAddTileOverlayViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSAddTileOverlayViewController.h; sourceTree = ""; }; 04E0EE041B69112B0095E53E /* GPKGSAddTileOverlayViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPKGSAddTileOverlayViewController.m; sourceTree = ""; }; 04E0EE061B6919D80095E53E /* GPKGSEditTileOverlayViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPKGSEditTileOverlayViewController.h; sourceTree = ""; }; @@ -303,12 +308,14 @@ E300A93823315B9D002336A0 /* MCBoundingBoxPassthroughView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCBoundingBoxPassthroughView.m; sourceTree = ""; }; E307AD5823C52AE200771D29 /* MCTileServerHelpViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCTileServerHelpViewController.h; sourceTree = ""; }; E307AD5923C52AE200771D29 /* MCTileServerHelpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCTileServerHelpViewController.m; sourceTree = ""; }; - E308FBC01FBE400500348577 /* MCSingleGeoPackageView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCSingleGeoPackageView.xib; sourceTree = ""; }; E308FBC41FBFA7CA00348577 /* MCHeaderCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCHeaderCell.h; sourceTree = ""; }; E308FBC51FBFA7CA00348577 /* MCHeaderCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCHeaderCell.m; sourceTree = ""; }; E3100EAE203CAF1E00FFA56E /* MCZoomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCZoomCell.xib; sourceTree = ""; }; E312A3361FAA416500C088FB /* MCDownloadCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCDownloadCoordinator.h; sourceTree = ""; }; E312A3371FAA416500C088FB /* MCDownloadCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCDownloadCoordinator.m; sourceTree = ""; }; + E31BD62C244E2E2600C18609 /* MCKeyValueDisplayCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCKeyValueDisplayCell.xib; sourceTree = ""; }; + E31BD62E244E340300C18609 /* MCKeyValueDisplayCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCKeyValueDisplayCell.h; sourceTree = ""; }; + E31BD62F244E340300C18609 /* MCKeyValueDisplayCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCKeyValueDisplayCell.m; sourceTree = ""; }; E331C8EB20FE7645006EFED1 /* MCLayerCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCLayerCoordinator.h; sourceTree = ""; }; E331C8EC20FE7645006EFED1 /* MCLayerCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCLayerCoordinator.m; sourceTree = ""; }; E331C8EF210110B3006EFED1 /* MCTileLayerOperationsCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCTileLayerOperationsCell.m; sourceTree = ""; }; @@ -327,6 +334,8 @@ E3463DE821545F4B00D64FFC /* MCTileHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCTileHelper.m; sourceTree = ""; }; E346590D202BB20B001E6E81 /* MCZoomAndQualityViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCZoomAndQualityViewController.h; sourceTree = ""; }; E346590E202BB20B001E6E81 /* MCZoomAndQualityViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCZoomAndQualityViewController.m; sourceTree = ""; }; + E346EC7C2448C23C001A646A /* MCMapPointDataViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCMapPointDataViewController.h; sourceTree = ""; }; + E346EC7D2448C23C001A646A /* MCMapPointDataViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCMapPointDataViewController.m; sourceTree = ""; }; E3470CC52020E67D0098D783 /* MCColorUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCColorUtil.h; sourceTree = ""; }; E3470CC62020E67D0098D783 /* MCColorUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCColorUtil.m; sourceTree = ""; }; E3470CC8202126140098D783 /* MCSegmentedControlCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCSegmentedControlCell.xib; sourceTree = ""; }; @@ -388,11 +397,17 @@ E3A651AF200563AF00B8AB27 /* MCTileLayerDetailsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCTileLayerDetailsViewController.m; sourceTree = ""; }; E3A651B12005652400B8AB27 /* MCFieldWithTitleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCFieldWithTitleCell.h; sourceTree = ""; }; E3A651B22005652400B8AB27 /* MCFieldWithTitleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCFieldWithTitleCell.m; sourceTree = ""; }; + E3B7DD4A2475F1E900215EF5 /* mapcache-ios-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "mapcache-ios-Bridging-Header.h"; sourceTree = ""; }; + E3B7DD4C2475F1EB00215EF5 /* MCCreateLayerFieldViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MCCreateLayerFieldViewController.swift; sourceTree = ""; }; + E3B7DD4D2475F1EB00215EF5 /* MCLayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLayerViewController.h; sourceTree = ""; }; + E3B7DD4E2475F1EC00215EF5 /* MCLayerCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MCLayerCoordinator.swift; sourceTree = ""; }; + E3B7DD4F2475F1EC00215EF5 /* MCLayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCLayerViewController.m; sourceTree = ""; }; E3B9753A1FB3DED400E33E0A /* MCHeaderCellDisplay.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCHeaderCellDisplay.xib; sourceTree = ""; }; E3BED1DE219116FA001AF654 /* MCSettingsCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCSettingsCoordinator.h; sourceTree = ""; }; E3BED1DF219116FA001AF654 /* MCSettingsCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCSettingsCoordinator.m; sourceTree = ""; }; E3BED1E121911712001AF654 /* MCSettingsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCSettingsViewController.h; sourceTree = ""; }; E3BED1E221911712001AF654 /* MCSettingsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCSettingsViewController.m; sourceTree = ""; }; + E3C5FC4724B7D38F00B5E12E /* MCTileMatrix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCTileMatrix.swift; sourceTree = ""; }; E3CF687023D901740005A6EF /* MCTileServerURLManagerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCTileServerURLManagerViewController.h; sourceTree = ""; }; E3CF687123D901740005A6EF /* MCTileServerURLManagerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCTileServerURLManagerViewController.m; sourceTree = ""; }; E3CF687323DA5FF20005A6EF /* MCTextViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCTextViewCell.xib; sourceTree = ""; }; @@ -400,6 +415,15 @@ E3CF687623DA667E0005A6EF /* MCTextViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCTextViewCell.m; sourceTree = ""; }; E3CF687823DA6AC40005A6EF /* MCNewTileServerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCNewTileServerViewController.h; sourceTree = ""; }; E3CF687923DA6AC40005A6EF /* MCNewTileServerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCNewTileServerViewController.m; sourceTree = ""; }; + E3D651D1240D90340082FF10 /* MCGeoPackageRepository.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCGeoPackageRepository.h; sourceTree = ""; }; + E3D651D2240D90340082FF10 /* MCGeoPackageRepository.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCGeoPackageRepository.m; sourceTree = ""; }; + E3D80E9D23FF3DA0006F1014 /* MCDrawingCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCDrawingCoordinator.h; sourceTree = ""; }; + E3D80E9E23FF3DA0006F1014 /* MCDrawingCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCDrawingCoordinator.m; sourceTree = ""; }; + E3D80EA023FF59E3006F1014 /* MCDrawingStatusViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCDrawingStatusViewController.h; sourceTree = ""; }; + E3D80EA123FF59E3006F1014 /* MCDrawingStatusViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCDrawingStatusViewController.m; sourceTree = ""; }; + E3D80EA3240076AD006F1014 /* MCDualButtonCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCDualButtonCell.h; sourceTree = ""; }; + E3D80EA4240076AD006F1014 /* MCDualButtonCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCDualButtonCell.m; sourceTree = ""; }; + E3D80EA6240076CC006F1014 /* MCDualButtonCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MCDualButtonCell.xib; sourceTree = ""; }; E3DE0DE823E2420D00CB27AF /* UITextView+Validators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITextView+Validators.h"; sourceTree = ""; }; E3DE0DE923E2420D00CB27AF /* UITextView+Validators.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITextView+Validators.m"; sourceTree = ""; }; E3DE0DEB23E3781800CB27AF /* MCCreateGeoPacakgeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCreateGeoPacakgeViewController.h; sourceTree = ""; }; @@ -483,6 +507,7 @@ 044D6B481B627AB400527745 /* load */, 045C949C1B5D89E80005CCD0 /* ui */, E3A492021FA952C100FFE613 /* geopackage */, + E3E3846024352E6000DB7471 /* layer */, 045C94911B56DEFA0005CCD0 /* indexer */, 045C948A1B50785B0005CCD0 /* map */, 0446481B1B4C26BE0052913B /* util */, @@ -530,22 +555,25 @@ 044648151B4C1A8D0052913B /* data */ = { isa = PBXGroup; children = ( - 044647FD1B4AF3870052913B /* GPKGSTable.h */, - 044647FE1B4AF3870052913B /* GPKGSTable.m */, - 044648001B4AF4250052913B /* GPKGSTableTypes.h */, - 044648011B4AF4250052913B /* GPKGSTableTypes.m */, - 044648031B4AF6990052913B /* GPKGSFeatureTable.h */, - 044648041B4AF6990052913B /* GPKGSFeatureTable.m */, - 044648061B4AF6A70052913B /* GPKGSTileTable.h */, - 044648071B4AF6A70052913B /* GPKGSTileTable.m */, - 044648091B4AFC100052913B /* GPKGSDatabase.h */, - 0446480A1B4AFC100052913B /* GPKGSDatabase.m */, - 045C94841B50226D0005CCD0 /* GPKGSFeatureOverlayTable.h */, - 045C94851B50226D0005CCD0 /* GPKGSFeatureOverlayTable.m */, - 045C94871B5026E00005CCD0 /* GPKGSDatabases.h */, - 045C94881B5026E00005CCD0 /* GPKGSDatabases.m */, - 04DD108C1BD9443F00CC59A0 /* GPKGSTableIndex.h */, - 04DD108D1BD9443F00CC59A0 /* GPKGSTableIndex.m */, + E3D651D1240D90340082FF10 /* MCGeoPackageRepository.h */, + E3D651D2240D90340082FF10 /* MCGeoPackageRepository.m */, + 044647FD1B4AF3870052913B /* MCTable.h */, + 044647FE1B4AF3870052913B /* MCTable.m */, + 044648001B4AF4250052913B /* MCTableTypes.h */, + 044648011B4AF4250052913B /* MCTableTypes.m */, + 044648031B4AF6990052913B /* MCFeatureTable.h */, + 044648041B4AF6990052913B /* MCFeatureTable.m */, + 044648061B4AF6A70052913B /* MCTileTable.h */, + 044648071B4AF6A70052913B /* MCTileTable.m */, + 044648091B4AFC100052913B /* MCDatabase.h */, + 0446480A1B4AFC100052913B /* MCDatabase.m */, + 045C94841B50226D0005CCD0 /* MCFeatureOverlayTable.h */, + 045C94851B50226D0005CCD0 /* MCFeatureOverlayTable.m */, + 045C94871B5026E00005CCD0 /* MCDatabases.h */, + 045C94881B5026E00005CCD0 /* MCDatabases.m */, + 04DD108C1BD9443F00CC59A0 /* MCTableIndex.h */, + 04DD108D1BD9443F00CC59A0 /* MCTableIndex.m */, + E3C5FC4724B7D38F00B5E12E /* MCTileMatrix.swift */, ); path = data; sourceTree = ""; @@ -596,14 +624,14 @@ 0446481B1B4C26BE0052913B /* util */ = { isa = PBXGroup; children = ( - 0446481C1B4C26DF0052913B /* GPKGSConstants.h */, - 0446481D1B4C26DF0052913B /* GPKGSConstants.m */, - 047733C21B4C3D1200E523BD /* GPKGSProperties.h */, - 047733C31B4C3D1200E523BD /* GPKGSProperties.m */, - 04082B541B4F18A000D65E6B /* GPKGSUtils.h */, - 04082B551B4F18A000D65E6B /* GPKGSUtils.m */, - 045C94991B5D4C560005CCD0 /* GPKGSDecimalValidator.h */, - 045C949A1B5D4C560005CCD0 /* GPKGSDecimalValidator.m */, + 0446481C1B4C26DF0052913B /* MCConstants.h */, + 0446481D1B4C26DF0052913B /* MCConstants.m */, + 047733C21B4C3D1200E523BD /* MCProperties.h */, + 047733C31B4C3D1200E523BD /* MCProperties.m */, + 04082B541B4F18A000D65E6B /* MCUtils.h */, + 04082B551B4F18A000D65E6B /* MCUtils.m */, + 045C94991B5D4C560005CCD0 /* MCDecimalValidator.h */, + 045C949A1B5D4C560005CCD0 /* MCDecimalValidator.m */, E3470CC52020E67D0098D783 /* MCColorUtil.h */, E3470CC62020E67D0098D783 /* MCColorUtil.m */, E34F32EF220CAF1C0098ED45 /* UITextField+Validators.h */, @@ -617,8 +645,8 @@ 044D6B481B627AB400527745 /* load */ = { isa = PBXGroup; children = ( - 044D6B491B627B0000527745 /* GPKGSLoadTilesTask.h */, - 044D6B4A1B627B0000527745 /* GPKGSLoadTilesTask.m */, + 044D6B491B627B0000527745 /* MCLoadTilesTask.h */, + 044D6B4A1B627B0000527745 /* MCLoadTilesTask.m */, 044D6B4C1B627B2200527745 /* GPKGSLoadTilesProtocol.h */, ); path = load; @@ -651,6 +679,12 @@ 043A45971B83B4AB001B8FC5 /* GPGKSMapPointInitializer.m */, 043A459C1B84AA5D001B8FC5 /* GPKGSMapPointDataTypes.h */, 043A459D1B84AA5D001B8FC5 /* GPKGSMapPointDataTypes.m */, + E3D80E9D23FF3DA0006F1014 /* MCDrawingCoordinator.h */, + E3D80E9E23FF3DA0006F1014 /* MCDrawingCoordinator.m */, + E3D80EA023FF59E3006F1014 /* MCDrawingStatusViewController.h */, + E3D80EA123FF59E3006F1014 /* MCDrawingStatusViewController.m */, + E346EC7C2448C23C001A646A /* MCMapPointDataViewController.h */, + E346EC7D2448C23C001A646A /* MCMapPointDataViewController.m */, ); path = map; sourceTree = ""; @@ -658,8 +692,8 @@ 045C94911B56DEFA0005CCD0 /* indexer */ = { isa = PBXGroup; children = ( - 045C94921B56DF620005CCD0 /* GPKGSIndexerTask.h */, - 045C94931B56DF620005CCD0 /* GPKGSIndexerTask.m */, + 045C94921B56DF620005CCD0 /* MCIndexerTask.h */, + 045C94931B56DF620005CCD0 /* MCIndexerTask.m */, 045C94951B56E1050005CCD0 /* GPKGSIndexerProtocol.h */, ); path = indexer; @@ -798,7 +832,6 @@ E3A651A92003DDE800B8AB27 /* NewLayerWizard */, E3A4920C1FA9885B00FFE613 /* MCDownloadGeopackage.xib */, E3FB85752134A9D8002F012E /* MCGeoPackageList.xib */, - E308FBC01FBE400500348577 /* MCSingleGeoPackageView.xib */, E3FB857021349C31002F012E /* MCMapView.xib */, E3500E5F22B455C800164ABF /* MCDisclaimerView.xib */, E300A93223313D77002336A0 /* MCBoundingBoxGuideView.xib */, @@ -852,6 +885,12 @@ E35B630D21BC24E9004E5BB0 /* MCTitleCell.xib */, E34F32E72204E93C0098ED45 /* MCEmptyStateCell.xib */, E3500E6422B7F36500164ABF /* MCTutorialCell.xib */, + E3D80EA6240076CC006F1014 /* MCDualButtonCell.xib */, + E3D80EA3240076AD006F1014 /* MCDualButtonCell.h */, + E3D80EA4240076AD006F1014 /* MCDualButtonCell.m */, + E31BD62C244E2E2600C18609 /* MCKeyValueDisplayCell.xib */, + E31BD62E244E340300C18609 /* MCKeyValueDisplayCell.h */, + E31BD62F244E340300C18609 /* MCKeyValueDisplayCell.m */, ); path = DisplayCells; sourceTree = ""; @@ -888,6 +927,18 @@ path = settings; sourceTree = ""; }; + E3E3846024352E6000DB7471 /* layer */ = { + isa = PBXGroup; + children = ( + E3B7DD4A2475F1E900215EF5 /* mapcache-ios-Bridging-Header.h */, + E3B7DD4C2475F1EB00215EF5 /* MCCreateLayerFieldViewController.swift */, + E3B7DD4E2475F1EC00215EF5 /* MCLayerCoordinator.swift */, + E3B7DD4D2475F1EB00215EF5 /* MCLayerViewController.h */, + E3B7DD4F2475F1EC00215EF5 /* MCLayerViewController.m */, + ); + path = layer; + sourceTree = ""; + }; E3E9ED6723EA407E004C4530 /* mapcache-iosUITests */ = { isa = PBXGroup; children = ( @@ -988,6 +1039,7 @@ 0401366E1AF94FB200C92AFC = { CreatedOnToolsVersion = 6.3.1; DevelopmentTeam = ZL8G5D9G2H; + LastSwiftMigration = 1140; }; 0401368A1AF94FB200C92AFC = { CreatedOnToolsVersion = 6.3.1; @@ -1033,6 +1085,7 @@ E35B630E21BC24E9004E5BB0 /* MCTitleCell.xib in Resources */, E3470CC9202126140098D783 /* MCSegmentedControlCell.xib in Resources */, E3100EAF203CAF1E00FFA56E /* MCZoomCell.xib in Resources */, + E3D80EA7240076CC006F1014 /* MCDualButtonCell.xib in Resources */, E3B9753B1FB3DED400E33E0A /* MCHeaderCellDisplay.xib in Resources */, E363F54520F0177700BBF91A /* MCTileLayerOperationsCell.xib in Resources */, E354EEDB2006B9B000B062BE /* MCDescriptionCell.xib in Resources */, @@ -1044,12 +1097,11 @@ 047733C61B4C3E3400E523BD /* mapcache.plist in Resources */, E363F54320EFD5A700BBF91A /* MCFeatureLayerOperationsCell.xib in Resources */, E3500E6522B7F36500164ABF /* MCTutorialCell.xib in Resources */, - 040136811AF94FB200C92AFC /* Main.storyboard in Resources */, E34F32E82204E93C0098ED45 /* MCEmptyStateCell.xib in Resources */, E3FB857121349C32002F012E /* MCMapView.xib in Resources */, E3A651AB2003E1B700B8AB27 /* MCCreateLayerView.xib in Resources */, E3CF687423DA5FF20005A6EF /* MCTextViewCell.xib in Resources */, - E308FBC11FBE400500348577 /* MCSingleGeoPackageView.xib in Resources */, + E31BD62D244E2E2600C18609 /* MCKeyValueDisplayCell.xib in Resources */, 040136861AF94FB200C92AFC /* LaunchScreen.xib in Resources */, E33F55721FC4A1C000F252FD /* MCSectionTitleCell.xib in Resources */, E3FB85782134A9E4002F012E /* MCGeoPackageCell.xib in Resources */, @@ -1123,18 +1175,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E3F9A99C2475F52400DFD043 /* MCLayerViewController.m in Sources */, + E3D651D3240D90340082FF10 /* MCGeoPackageRepository.m in Sources */, 04E1D8CD1B66814A002BD947 /* GPKGSManagerLoadTilesViewController.m in Sources */, E354EEDE2006BB9500B062BE /* MCDescriptionCell.m in Sources */, 043A45851B7A54C2001B8FC5 /* GPKGSSelectFeatureTableViewController.m in Sources */, - 045C94901B53EEB80005CCD0 /* GPKGSMapViewController.m in Sources */, 04E0EE0E1B691AD10095E53E /* GPKGSManagerEditTileOverlayViewController.m in Sources */, E36D2DD12017C0A70097A8DE /* MCPickerViewCell.m in Sources */, E308FBC61FBFA7CA00348577 /* MCHeaderCell.m in Sources */, + E3B7DD502475F1ED00215EF5 /* MCCreateLayerFieldViewController.swift in Sources */, 043A458B1B7E21E3001B8FC5 /* GPKGSMapPointData.m in Sources */, E331C8F0210110B3006EFED1 /* MCTileLayerOperationsCell.m in Sources */, E3FB856F21349B5E002F012E /* MCMapViewController.m in Sources */, E3FB857B2134A9F0002F012E /* MCGeoPackageCell.m in Sources */, - 045C94941B56DF620005CCD0 /* GPKGSIndexerTask.m in Sources */, + 045C94941B56DF620005CCD0 /* MCIndexerTask.m in Sources */, 047733C91B4C496600E523BD /* GPKGSTableOptionsButton.m in Sources */, 04E1D8DF1B682D0F002BD947 /* GPKGSFeatureTilesDrawData.m in Sources */, E3CF687223D901750005A6EF /* MCTileServerURLManagerViewController.m in Sources */, @@ -1147,58 +1201,60 @@ E3A4920B1FA9538800FFE613 /* MCGeopackageSingleViewController.m in Sources */, E33F55751FC4A25500F252FD /* MCSectionTitleCell.m in Sources */, 044647FC1B4AD1C00052913B /* GPKGSManagerViewController.m in Sources */, + E3C5FC4824B7D38F00B5E12E /* MCTileMatrix.swift in Sources */, 045C94A91B5DA5C20005CCD0 /* GPKGSBoundingBoxViewController.m in Sources */, 043A45981B83B4AB001B8FC5 /* GPGKSMapPointInitializer.m in Sources */, + E3D80EA5240076AD006F1014 /* MCDualButtonCell.m in Sources */, 04E1D8DC1B682CF4002BD947 /* GPKGSFeatureTilesDrawViewController.m in Sources */, + E3D80EA223FF59E3006F1014 /* MCDrawingStatusViewController.m in Sources */, 0446481A1B4C24AD0052913B /* GPKGSActiveTableSwitch.m in Sources */, E3A651B32005652400B8AB27 /* MCFieldWithTitleCell.m in Sources */, 04E0EE0B1B691A3C0095E53E /* GPKGSEditTileOverlayData.m in Sources */, - 045C94891B5026E00005CCD0 /* GPKGSDatabases.m in Sources */, - 044D6B4B1B627B0000527745 /* GPKGSLoadTilesTask.m in Sources */, + 045C94891B5026E00005CCD0 /* MCDatabases.m in Sources */, + E3B7DD512475F1ED00215EF5 /* MCLayerCoordinator.swift in Sources */, + 044D6B4B1B627B0000527745 /* MCLoadTilesTask.m in Sources */, E3FB856C2134955F002F012E /* NGADrawerViewController.m in Sources */, 04CCC8681B6114EE0001296D /* GPKGSGenerateTilesData.m in Sources */, E300A93623313DCE002336A0 /* MCBoundingBoxGuideView.m in Sources */, - 04DD108E1BD9443F00CC59A0 /* GPKGSTableIndex.m in Sources */, + 04DD108E1BD9443F00CC59A0 /* MCTableIndex.m in Sources */, E3500E6822B7F4F100164ABF /* MCTutorialCell.m in Sources */, 04082B531B4EBE6F00D65E6B /* MCDownloadGeopackage.m in Sources */, 04E1D8D61B66D439002BD947 /* GPKGSEditTilesViewController.m in Sources */, 04E1D8E21B682D5D002BD947 /* GPKGSCreateFeatureTilesViewController.m in Sources */, 04CCC8651B61122A0001296D /* GPKGSGenerateTilesViewController.m in Sources */, - 044648081B4AF6A70052913B /* GPKGSTileTable.m in Sources */, - 047733C41B4C3D1200E523BD /* GPKGSProperties.m in Sources */, + 044648081B4AF6A70052913B /* MCTileTable.m in Sources */, + 047733C41B4C3D1200E523BD /* MCProperties.m in Sources */, E354EEE320091BCD00B062BE /* MCFeatureLayerDetailsViewController.m in Sources */, E33F557A1FC4FF1E00F252FD /* MCLayerCell.m in Sources */, E3A492051FA952F200FFE613 /* MCGeoPackageCoordinator.m in Sources */, - E363F53B20EC24B200BBF91A /* MCLayerViewController.m in Sources */, - 0446481E1B4C26DF0052913B /* GPKGSConstants.m in Sources */, + 0446481E1B4C26DF0052913B /* MCConstants.m in Sources */, E3FB85742134A9B5002F012E /* MCGeoPackageList.m in Sources */, E3A651A82003DDC800B8AB27 /* MCCreateLayerViewController.m in Sources */, 04CCC8711B6122480001296D /* GPKGSCreateTilesViewController.m in Sources */, E35B631121BC26F9004E5BB0 /* MCTitleCell.m in Sources */, + E31BD630244E340300C18609 /* MCKeyValueDisplayCell.m in Sources */, 046877F81C68FE9400967470 /* GPKGSLinkedTablesViewController.m in Sources */, 04CCC85C1B5FF1830001296D /* GPKGSManagerCreateTilesViewController.m in Sources */, E354DB3622BAD89D00FFD477 /* MCSwitchCell.m in Sources */, 047733BE1B4C371500E523BD /* GPKGSDatabaseOptionsButton.m in Sources */, - 044647FF1B4AF3870052913B /* GPKGSTable.m in Sources */, + 044647FF1B4AF3870052913B /* MCTable.m in Sources */, E3CF687723DA667E0005A6EF /* MCTextViewCell.m in Sources */, E33F557F1FCC956A00F252FD /* MCButtonCell.m in Sources */, 04CCC85F1B60225C0001296D /* GPKGSKeyboardConstraint.m in Sources */, 040136781AF94FB200C92AFC /* AppDelegate.m in Sources */, 04E1D8D01B66D366002BD947 /* GPKGSEditContentsViewController.m in Sources */, - E331C8ED20FE7645006EFED1 /* MCLayerCoordinator.m in Sources */, E3500E6322B4653B00164ABF /* MCDisclaimerViewController.m in Sources */, - 044648021B4AF4250052913B /* GPKGSTableTypes.m in Sources */, + 044648021B4AF4250052913B /* MCTableTypes.m in Sources */, E35F316521EFEC7E001B720F /* MCNoticeAndAttributionViewController.m in Sources */, - 045C948D1B50789D0005CCD0 /* GPKGSMapView.m in Sources */, E3A491FF1FA78A4C00FFE613 /* GPKGSManagerCoordinator.m in Sources */, - 045C949B1B5D4C560005CCD0 /* GPKGSDecimalValidator.m in Sources */, + 045C949B1B5D4C560005CCD0 /* MCDecimalValidator.m in Sources */, 04CCC86B1B6121E90001296D /* GPKGSLoadTilesViewController.m in Sources */, E3BED1E0219116FA001AF654 /* MCSettingsCoordinator.m in Sources */, 04CCC8621B60232A0001296D /* GPKGSUIResponder+FirstResponder.m in Sources */, E34F32F1220CAF1C0098ED45 /* UITextField+Validators.m in Sources */, 044648111B4B1D960052913B /* GPKGSTableCell.m in Sources */, 04CCC86E1B6122040001296D /* GPKGSLoadTilesData.m in Sources */, - 044648051B4AF6990052913B /* GPKGSFeatureTable.m in Sources */, + 044648051B4AF6990052913B /* MCFeatureTable.m in Sources */, E300A93923315B9D002336A0 /* MCBoundingBoxPassthroughView.m in Sources */, 043A45911B7E63C1001B8FC5 /* GPKGSEditTypes.m in Sources */, 045C94831B4FFE7E0005CCD0 /* GPKGSDisplayTextViewController.m in Sources */, @@ -1206,15 +1262,16 @@ 04E1D8D31B66D41E002BD947 /* GPKGSEditFeaturesViewController.m in Sources */, E3BED1E321911712001AF654 /* MCSettingsViewController.m in Sources */, 04E0EE051B69112B0095E53E /* GPKGSAddTileOverlayViewController.m in Sources */, - 045C94861B50226D0005CCD0 /* GPKGSFeatureOverlayTable.m in Sources */, + 045C94861B50226D0005CCD0 /* MCFeatureOverlayTable.m in Sources */, E3FB857E2134C533002F012E /* MCGeoPackageListCoordinator.m in Sources */, - 04082B561B4F18A000D65E6B /* GPKGSUtils.m in Sources */, + 04082B561B4F18A000D65E6B /* MCUtils.m in Sources */, E34F32EB2204ECF60098ED45 /* MCEmptyStateCell.m in Sources */, E3FB856B2134955F002F012E /* NGADrawerCoordinator.m in Sources */, 04CCC8741B61228D0001296D /* GPKGSCreateTilesData.m in Sources */, 045C94981B5D384A0005CCD0 /* GPKGSCreateFeaturesViewController.m in Sources */, - 0446480B1B4AFC100052913B /* GPKGSDatabase.m in Sources */, + 0446480B1B4AFC100052913B /* MCDatabase.m in Sources */, 04E1D8D91B66D4CA002BD947 /* GPKGSEditContentsData.m in Sources */, + E346EC7E2448C23C001A646A /* MCMapPointDataViewController.m in Sources */, E34C378F203CD8BC00287CF9 /* MCZoomCell.m in Sources */, E3A651B0200563AF00B8AB27 /* MCTileLayerDetailsViewController.m in Sources */, E355935020F3E3EF00FC1288 /* MCFeatureLayerOperationsCell.m in Sources */, @@ -1392,17 +1449,23 @@ baseConfigurationReference = C87B7FD45C393DE7D862CA13 /* Pods-mapcache-ios.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 31; + CURRENT_PROJECT_VERSION = 40; DEVELOPMENT_TEAM = ZL8G5D9G2H; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "mapcache-ios/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 2.0.1; + MARKETING_VERSION = 2.0.2; PRODUCT_BUNDLE_IDENTIFIER = mil.nga.mapcache; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; + SWIFT_OBJC_BRIDGING_HEADER = "mapcache-ios/layer/mapcache-ios-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Debug; @@ -1412,17 +1475,21 @@ baseConfigurationReference = 317A64B2FA9FC9C408272041 /* Pods-mapcache-ios.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 31; + CURRENT_PROJECT_VERSION = 40; DEVELOPMENT_TEAM = ZL8G5D9G2H; + GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "mapcache-ios/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 2.0.1; + MARKETING_VERSION = 2.0.2; PRODUCT_BUNDLE_IDENTIFIER = mil.nga.mapcache; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; + SWIFT_OBJC_BRIDGING_HEADER = "mapcache-ios/layer/mapcache-ios-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Release; @@ -1430,6 +1497,7 @@ 040136991AF94FB200C92AFC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -1450,6 +1518,7 @@ 0401369A1AF94FB200C92AFC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -1466,6 +1535,7 @@ E3E9ED6E23EA407E004C4530 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -1491,6 +1561,7 @@ E3E9ED6F23EA407E004C4530 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; diff --git a/mapcache-ios.xcodeproj/xcshareddata/xcschemes/mapcache-ios.xcscheme b/mapcache-ios.xcodeproj/xcshareddata/xcschemes/mapcache-ios.xcscheme index 9856ecf..f7fdd52 100644 --- a/mapcache-ios.xcodeproj/xcshareddata/xcschemes/mapcache-ios.xcscheme +++ b/mapcache-ios.xcodeproj/xcshareddata/xcschemes/mapcache-ios.xcscheme @@ -1,6 +1,6 @@ - - - - diff --git a/mapcache-ios/AppDelegate.m b/mapcache-ios/AppDelegate.m index 0f70cf3..9fe5b94 100644 --- a/mapcache-ios/AppDelegate.m +++ b/mapcache-ios/AppDelegate.m @@ -9,8 +9,8 @@ #import "AppDelegate.h" #import "GPKGGeoPackageFactory.h" #import "GPKGSManagerViewController.h" -#import "GPKGSConstants.h" -#import "GPKGSProperties.h" +#import "MCConstants.h" +#import "MCProperties.h" #import "MBFingerTipWindow.h" @interface AppDelegate () @@ -22,7 +22,7 @@ @interface AppDelegate () @implementation AppDelegate - (UIWindow *)window { - if ([GPKGSProperties getBoolOfProperty:GPKGS_ANIMATE_SCREEN_TOUCHES] && !_window) { + if ([MCProperties getBoolOfProperty:GPKGS_ANIMATE_SCREEN_TOUCHES] && !_window) { MBFingerTipWindow * fingerTip = [[MBFingerTipWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; fingerTip.alwaysShowTouches = YES; _window = fingerTip; @@ -52,7 +52,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [_window.rootViewController presentViewController:disclaimer animated:YES completion:nil]; } - _manager = [GPKGGeoPackageFactory getManager]; + _manager = [GPKGGeoPackageFactory manager]; _geoPackages = [[GPKGGeoPackageCache alloc] initWithManager:self.manager]; return YES; @@ -100,9 +100,17 @@ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDiction NSString * fileUrl = [url path]; BOOL imported = false; - GPKGGeoPackageManager * manager = [GPKGGeoPackageFactory getManager]; + GPKGGeoPackageManager * manager = [GPKGGeoPackageFactory manager]; @try { imported = [manager importGeoPackageFromPath:fileUrl andOverride:true andMove:true]; + } @catch (NSException *e) { + NSLog(@"------------------------- AppDelegate - Problem importing geopackage %@\n%@", fileUrl, e.reason); + + UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Problem importing GeoPacakge" message:e.reason preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) {}]; + [alert addAction:defaultAction]; + [self.window.rootViewController presentViewController:alert animated:YES completion:nil]; + } @finally { [manager close]; diff --git a/mapcache-ios/Base.lproj/Main.storyboard b/mapcache-ios/Base.lproj/Main.storyboard deleted file mode 100644 index a43f987..0000000 --- a/mapcache-ios/Base.lproj/Main.storyboard +++ /dev/null @@ -1,3350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mapcache-ios/Images.xcassets/Point.imageset/Contents.json b/mapcache-ios/Images.xcassets/Point.imageset/Contents.json index a68a16d..c2d29ba 100644 --- a/mapcache-ios/Images.xcassets/Point.imageset/Contents.json +++ b/mapcache-ios/Images.xcassets/Point.imageset/Contents.json @@ -1,21 +1,23 @@ { "images" : [ { + "filename" : "Point_3.png", "idiom" : "universal", - "scale" : "1x", - "filename" : "ic_point.png" + "scale" : "1x" }, { + "filename" : "Point_4.png", "idiom" : "universal", "scale" : "2x" }, { + "filename" : "Point_5.png", "idiom" : "universal", "scale" : "3x" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/mapcache-ios/Images.xcassets/Point.imageset/Point_3.png b/mapcache-ios/Images.xcassets/Point.imageset/Point_3.png new file mode 100644 index 0000000..f37993f Binary files /dev/null and b/mapcache-ios/Images.xcassets/Point.imageset/Point_3.png differ diff --git a/mapcache-ios/Images.xcassets/Point.imageset/Point_4.png b/mapcache-ios/Images.xcassets/Point.imageset/Point_4.png new file mode 100644 index 0000000..2ed88af Binary files /dev/null and b/mapcache-ios/Images.xcassets/Point.imageset/Point_4.png differ diff --git a/mapcache-ios/Images.xcassets/Point.imageset/Point_5.png b/mapcache-ios/Images.xcassets/Point.imageset/Point_5.png new file mode 100644 index 0000000..3deeeed Binary files /dev/null and b/mapcache-ios/Images.xcassets/Point.imageset/Point_5.png differ diff --git a/mapcache-ios/Images.xcassets/Point.imageset/ic_point.png b/mapcache-ios/Images.xcassets/Point.imageset/ic_point.png deleted file mode 100644 index 25cf093..0000000 Binary files a/mapcache-ios/Images.xcassets/Point.imageset/ic_point.png and /dev/null differ diff --git a/mapcache-ios/Images.xcassets/ZoomLevel.imageset/Contents.json b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/Contents.json new file mode 100644 index 0000000..09737dc --- /dev/null +++ b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "ZoomLevel.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ZoomLevel@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "ZoomLevel@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel.png b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel.png new file mode 100644 index 0000000..94e172b Binary files /dev/null and b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel.png differ diff --git a/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel@2x.png b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel@2x.png new file mode 100644 index 0000000..414d286 Binary files /dev/null and b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel@2x.png differ diff --git a/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel@3x.png b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel@3x.png new file mode 100644 index 0000000..8f45c4d Binary files /dev/null and b/mapcache-ios/Images.xcassets/ZoomLevel.imageset/ZoomLevel@3x.png differ diff --git a/mapcache-ios/Images.xcassets/boolean.imageset/Boolean.png b/mapcache-ios/Images.xcassets/boolean.imageset/Boolean.png new file mode 100644 index 0000000..20eae38 Binary files /dev/null and b/mapcache-ios/Images.xcassets/boolean.imageset/Boolean.png differ diff --git a/mapcache-ios/Images.xcassets/boolean.imageset/Boolean@2x.png b/mapcache-ios/Images.xcassets/boolean.imageset/Boolean@2x.png new file mode 100644 index 0000000..744c178 Binary files /dev/null and b/mapcache-ios/Images.xcassets/boolean.imageset/Boolean@2x.png differ diff --git a/mapcache-ios/Images.xcassets/boolean.imageset/Boolean@3x.png b/mapcache-ios/Images.xcassets/boolean.imageset/Boolean@3x.png new file mode 100644 index 0000000..e498a9a Binary files /dev/null and b/mapcache-ios/Images.xcassets/boolean.imageset/Boolean@3x.png differ diff --git a/mapcache-ios/Images.xcassets/boolean.imageset/Contents.json b/mapcache-ios/Images.xcassets/boolean.imageset/Contents.json new file mode 100644 index 0000000..0af4006 --- /dev/null +++ b/mapcache-ios/Images.xcassets/boolean.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Boolean.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Boolean@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Boolean@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/mapcache-ios/Images.xcassets/number.imageset/Contents.json b/mapcache-ios/Images.xcassets/number.imageset/Contents.json new file mode 100644 index 0000000..702159d --- /dev/null +++ b/mapcache-ios/Images.xcassets/number.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Number.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Number@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Number@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/mapcache-ios/Images.xcassets/number.imageset/Number.png b/mapcache-ios/Images.xcassets/number.imageset/Number.png new file mode 100644 index 0000000..c0a4d93 Binary files /dev/null and b/mapcache-ios/Images.xcassets/number.imageset/Number.png differ diff --git a/mapcache-ios/Images.xcassets/number.imageset/Number@2x.png b/mapcache-ios/Images.xcassets/number.imageset/Number@2x.png new file mode 100644 index 0000000..eb95c60 Binary files /dev/null and b/mapcache-ios/Images.xcassets/number.imageset/Number@2x.png differ diff --git a/mapcache-ios/Images.xcassets/number.imageset/Number@3x.png b/mapcache-ios/Images.xcassets/number.imageset/Number@3x.png new file mode 100644 index 0000000..b439722 Binary files /dev/null and b/mapcache-ios/Images.xcassets/number.imageset/Number@3x.png differ diff --git a/mapcache-ios/Images.xcassets/text.imageset/Contents.json b/mapcache-ios/Images.xcassets/text.imageset/Contents.json new file mode 100644 index 0000000..37b6503 --- /dev/null +++ b/mapcache-ios/Images.xcassets/text.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Text.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Text@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Text@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/mapcache-ios/Images.xcassets/text.imageset/Text.png b/mapcache-ios/Images.xcassets/text.imageset/Text.png new file mode 100644 index 0000000..a7754c8 Binary files /dev/null and b/mapcache-ios/Images.xcassets/text.imageset/Text.png differ diff --git a/mapcache-ios/Images.xcassets/text.imageset/Text@2x.png b/mapcache-ios/Images.xcassets/text.imageset/Text@2x.png new file mode 100644 index 0000000..0cb0c2b Binary files /dev/null and b/mapcache-ios/Images.xcassets/text.imageset/Text@2x.png differ diff --git a/mapcache-ios/Images.xcassets/text.imageset/Text@3x.png b/mapcache-ios/Images.xcassets/text.imageset/Text@3x.png new file mode 100644 index 0000000..49a5117 Binary files /dev/null and b/mapcache-ios/Images.xcassets/text.imageset/Text@3x.png differ diff --git a/mapcache-ios/data/GPKGSDatabase.h b/mapcache-ios/data/MCDatabase.h similarity index 67% rename from mapcache-ios/data/GPKGSDatabase.h rename to mapcache-ios/data/MCDatabase.h index f004757..38eb412 100644 --- a/mapcache-ios/data/GPKGSDatabase.h +++ b/mapcache-ios/data/MCDatabase.h @@ -7,9 +7,9 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" -@interface GPKGSDatabase : NSObject +@interface MCDatabase : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic) BOOL expanded; @@ -36,19 +36,23 @@ -(NSInteger) getActiveTableCount; --(void) addFeature: (GPKGSTable *) table; +-(void) addFeature: (MCTable *) table; --(void) addFeatureOverlay: (GPKGSTable *) table; +-(void) addFeatureOverlay: (MCTable *) table; --(void) addTile: (GPKGSTable *) table; +-(void) addTile: (MCTable *) table; --(BOOL) exists: (GPKGSTable *) table; +-(BOOL) exists: (MCTable *) table; + +- (BOOL) hasTableNamed:(NSString *)tableName; + +- (MCTable *) tableNamed:(NSString *)tableName; -(BOOL) existsWithTable: (NSString *) table ofType: (enum GPKGSTableType) tableType; --(void) add:(GPKGSTable *) table; +-(void) add:(MCTable *) table; --(void) remove:(GPKGSTable *) table; +-(void) remove:(MCTable *) table; -(BOOL) isEmpty; diff --git a/mapcache-ios/data/GPKGSDatabase.m b/mapcache-ios/data/MCDatabase.m similarity index 84% rename from mapcache-ios/data/GPKGSDatabase.m rename to mapcache-ios/data/MCDatabase.m index ff9a447..415cbcc 100644 --- a/mapcache-ios/data/GPKGSDatabase.m +++ b/mapcache-ios/data/MCDatabase.m @@ -6,9 +6,9 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSDatabase.h" +#import "MCDatabase.h" -@interface GPKGSDatabase () +@interface MCDatabase () @property (nonatomic, strong) NSMutableOrderedSet *featuresSet; @property (nonatomic, strong) NSMutableOrderedSet *featureNamesSet; @@ -19,7 +19,7 @@ @interface GPKGSDatabase () @end -@implementation GPKGSDatabase +@implementation MCDatabase -(instancetype) initWithName: (NSString *) name andExpanded: (BOOL) expanded{ self = [super init]; @@ -54,7 +54,7 @@ -(NSInteger) getFeatureOverlayCount{ -(NSInteger) getActiveFeatureOverlayCount{ int count = 0; - for(GPKGSTable * table in self.featureOverlaysSet){ + for(MCTable * table in self.featureOverlaysSet){ if(table.active){ count++; } @@ -73,7 +73,7 @@ -(NSInteger) getTileCount{ - (NSInteger) activeTileTableCount { NSInteger activeCount = 0; if ([self.tilesSet count] > 0) { - for (GPKGSTable *table in self.tilesSet.array) { + for (MCTable *table in self.tilesSet.array) { if (table.active) { activeCount++; } @@ -86,7 +86,7 @@ - (NSInteger) activeTileTableCount { - (NSInteger) activeFeatureTableCount { NSInteger activeCount = 0; if ([self.featuresSet count] > 0) { - for (GPKGSTable *table in self.tilesSet.array) { + for (MCTable *table in self.tilesSet.array) { if (table.active) { activeCount++; } @@ -112,22 +112,22 @@ -(NSInteger) getActiveTableCount{ return [self getFeatureCount] + [self getTileCount] + [self getActiveFeatureOverlayCount]; } --(void) addFeature: (GPKGSTable *) table{ +-(void) addFeature: (MCTable *) table{ [self.featuresSet addObject:table]; [self.featureNamesSet addObject:table.name]; } --(void) addFeatureOverlay: (GPKGSTable *) table{ +-(void) addFeatureOverlay: (MCTable *) table{ [self.featureOverlaysSet addObject:table]; [self.featureOverlayNamesSet addObject:table.name]; } --(void) addTile: (GPKGSTable *) table{ +-(void) addTile: (MCTable *) table{ [self.tilesSet addObject:table]; [self.tileNamesSet addObject:table.name]; } --(void) removeFeature: (GPKGSTable *) table{ +-(void) removeFeature: (MCTable *) table{ NSUInteger index = [self.featureNamesSet indexOfObject:table.name]; if(index != NSNotFound){ [self.featuresSet removeObjectAtIndex:index]; @@ -135,7 +135,7 @@ -(void) removeFeature: (GPKGSTable *) table{ } } --(void) removeFeatureOverlay: (GPKGSTable *) table{ +-(void) removeFeatureOverlay: (MCTable *) table{ NSUInteger index = [self.featureOverlayNamesSet indexOfObject:table.name]; if(index != NSNotFound){ [self.featureOverlaysSet removeObjectAtIndex:index]; @@ -143,7 +143,7 @@ -(void) removeFeatureOverlay: (GPKGSTable *) table{ } } --(void) removeTile: (GPKGSTable *) table{ +-(void) removeTile: (MCTable *) table{ NSUInteger index = [self.tileNamesSet indexOfObject:table.name]; if(index != NSNotFound){ [self.tilesSet removeObjectAtIndex:index]; @@ -151,10 +151,33 @@ -(void) removeTile: (GPKGSTable *) table{ } } --(BOOL) exists: (GPKGSTable *) table{ +-(BOOL) exists: (MCTable *) table{ return [self existsWithTable:table.name ofType:[table getType]]; } + +- (BOOL) hasTableNamed: (NSString *) tableName { + for (MCTable* table in [self getTables]) { + if ([table.name isEqualToString:tableName]) { + return YES; + } + } + + return NO; +} + + +- (MCTable *) tableNamed:(NSString *)tableName { + for (MCTable* table in [self getTables]) { + if ([table.name isEqualToString:tableName]) { + return table; + } + } + + return nil; +} + + -(BOOL) existsWithTable: (NSString *) table ofType: (enum GPKGSTableType) tableType{ BOOL exists = false; @@ -176,7 +199,7 @@ -(BOOL) existsWithTable: (NSString *) table ofType: (enum GPKGSTableType) tableT return exists; } --(void) add:(GPKGSTable *) table{ +-(void) add:(MCTable *) table{ switch([table getType]){ case GPKGS_TT_FEATURE: [self addFeature:table]; @@ -192,7 +215,7 @@ -(void) add:(GPKGSTable *) table{ } } --(void) remove:(GPKGSTable *) table{ +-(void) remove:(MCTable *) table{ switch([table getType]){ case GPKGS_TT_FEATURE: [self removeFeature:table]; diff --git a/mapcache-ios/data/GPKGSDatabases.h b/mapcache-ios/data/MCDatabases.h similarity index 63% rename from mapcache-ios/data/GPKGSDatabases.h rename to mapcache-ios/data/MCDatabases.h index 4e4bc70..16d570a 100644 --- a/mapcache-ios/data/GPKGSDatabases.h +++ b/mapcache-ios/data/MCDatabases.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSDatabase.h" +#import "MCDatabase.h" extern NSString * const GPKGS_DATABASES_PREFERENCE; extern NSString * const GPKGS_TILE_TABLES_PREFERENCE_SUFFIX; @@ -15,44 +15,26 @@ extern NSString * const GPKGS_FEATURE_TABLES_PREFERENCE_SUFFIX; extern NSString * const GPKGS_FEATURE_OVERLAY_TABLES_PREFERENCE_SUFFIX; extern NSString * const GPKGS_TABLE_VALUES_PREFERENCE; -@interface GPKGSDatabases : NSObject +@interface MCDatabases : NSObject @property (nonatomic) BOOL modified; - -+(GPKGSDatabases *) getInstance; - --(BOOL) exists: (GPKGSTable *) table; - ++(MCDatabases *) getInstance; +-(BOOL) exists: (MCTable *) table; -(BOOL) existsWithDatabase: (NSString *) database andTable: (NSString *) table ofType: (enum GPKGSTableType) tableType; - -- (BOOL)isActive:(GPKGSDatabase *) database; - +- (BOOL)isActive:(MCDatabase *) database; -(NSArray *) featureOverlays: (NSString *) database; - --(GPKGSDatabase *) getDatabaseWithTable:(GPKGSTable *) table; - --(GPKGSDatabase *) getDatabaseWithName:(NSString *) database; - +-(MCDatabase *) getDatabaseWithTable:(MCTable *) table; +-(MCDatabase *) getDatabaseWithName:(NSString *) database; -(NSArray *) getDatabases; - --(void) addTable: (GPKGSTable *) table; - --(void) addTable: (GPKGSTable *) table andUpdatePreferences: (BOOL) updatePreferences; - --(void) removeTable: (GPKGSTable *) table; - --(void) removeTable: (GPKGSTable *) table andPreserveOverlays: (BOOL) preserveOverlays; - +-(void) addTable: (MCTable *) table; +-(void) addTable: (MCTable *) table andUpdatePreferences: (BOOL) updatePreferences; +-(void) removeTable: (MCTable *) table; +-(void) removeTable: (MCTable *) table andPreserveOverlays: (BOOL) preserveOverlays; -(BOOL) isEmpty; - -(int) getTableCount; - -(int) getActiveTableCount; - -(void) clearActive; - -(void) removeDatabase: (NSString *) database andPreserveOverlays: (BOOL) preserveOverlays; - -(void) renameDatabase: (NSString *) database asNewDatabase: (NSString *) newDatabase; @end diff --git a/mapcache-ios/data/GPKGSDatabases.m b/mapcache-ios/data/MCDatabases.m similarity index 81% rename from mapcache-ios/data/GPKGSDatabases.m rename to mapcache-ios/data/MCDatabases.m index 78d497c..e2efe37 100644 --- a/mapcache-ios/data/GPKGSDatabases.m +++ b/mapcache-ios/data/MCDatabases.m @@ -6,11 +6,11 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSDatabases.h" -#import "GPKGSTileTable.h" -#import "GPKGSFeatureTable.h" -#import "GPKGSFeatureOverlayTable.h" -#import "GPKGSFeatureTable.h" +#import "MCDatabases.h" +#import "MCTileTable.h" +#import "MCFeatureTable.h" +#import "MCFeatureOverlayTable.h" +#import "MCFeatureTable.h" NSString * const GPKGS_DATABASES_PREFERENCE = @"databases"; NSString * const GPKGS_TILE_TABLES_PREFERENCE_SUFFIX = @"_tile_tables"; @@ -18,21 +18,21 @@ NSString * const GPKGS_FEATURE_OVERLAY_TABLES_PREFERENCE_SUFFIX = @"_feature_overlay_tables"; NSString * const GPKGS_TABLE_VALUES_PREFERENCE = @"_tables_values_"; -static GPKGSDatabases * instance; +static MCDatabases * instance; -@interface GPKGSDatabases () +@interface MCDatabases () @property (nonatomic, strong) NSUserDefaults * settings; @property (nonatomic, strong) NSMutableDictionary * databases; @end -@implementation GPKGSDatabases +@implementation MCDatabases -+(GPKGSDatabases *) getInstance{ ++(MCDatabases *) getInstance{ if(instance == nil){ NSUserDefaults *settings = [NSUserDefaults standardUserDefaults]; - GPKGSDatabases * active = [[GPKGSDatabases alloc] initWithSettings:settings]; + MCDatabases * active = [[MCDatabases alloc] initWithSettings:settings]; [active loadFromPreferences]; instance = active; } @@ -49,9 +49,9 @@ -(instancetype) initWithSettings: (NSUserDefaults *) settings{ return self; } --(BOOL) exists: (GPKGSTable *) table{ +-(BOOL) exists: (MCTable *) table{ BOOL exists = false; - GPKGSDatabase * database = [self getDatabaseWithTable:table]; + MCDatabase * database = [self getDatabaseWithTable:table]; if(database != nil) { exists = [database exists:table]; } @@ -60,14 +60,14 @@ -(BOOL) exists: (GPKGSTable *) table{ -(BOOL) existsWithDatabase: (NSString *) database andTable: (NSString *) table ofType: (enum GPKGSTableType) tableType{ BOOL exists = false; - GPKGSDatabase * db = [self getDatabaseWithName:database]; + MCDatabase * db = [self getDatabaseWithName:database]; if(db != nil) { exists = [db existsWithTable:table ofType:tableType]; } return exists; } -- (BOOL)isActive:(GPKGSDatabase *) database { +- (BOOL)isActive:(MCDatabase *) database { if ([self.databases objectForKey:database.name] != nil) { return YES; } @@ -82,7 +82,7 @@ -(NSArray *) featureOverlays: (NSString *) database{ NSArray * featureOverlays = [self.settings stringArrayForKey:[self getFeatureOverlayTablesPreferenceKeyForDatabase:database]]; for(NSString * featureOverlay in featureOverlays){ - GPKGSFeatureOverlayTable * featureOverlayTable = [self readFeatureOverlayTable:featureOverlay withDatabase:database]; + MCFeatureOverlayTable * featureOverlayTable = [self readFeatureOverlayTable:featureOverlay withDatabase:database]; if(featureOverlayTable != nil){ [response addObject:featureOverlayTable]; } @@ -91,11 +91,11 @@ -(NSArray *) featureOverlays: (NSString *) database{ return response; } --(GPKGSDatabase *) getDatabaseWithTable:(GPKGSTable *) table{ +-(MCDatabase *) getDatabaseWithTable:(MCTable *) table{ return [self getDatabaseWithName:table.database]; } --(GPKGSDatabase *) getDatabaseWithName:(NSString *) database{ +-(MCDatabase *) getDatabaseWithName:(NSString *) database{ return [self.databases objectForKey:database]; } @@ -103,14 +103,14 @@ -(NSArray *) getDatabases{ return [self.databases allValues]; } --(void) addTable: (GPKGSTable *) table{ +-(void) addTable: (MCTable *) table{ [self addTable:table andUpdatePreferences:true]; } --(void) addTable: (GPKGSTable *) table andUpdatePreferences: (BOOL) updatePreferences{ - GPKGSDatabase * database = [self.databases objectForKey:table.database]; +-(void) addTable: (MCTable *) table andUpdatePreferences: (BOOL) updatePreferences{ + MCDatabase * database = [self.databases objectForKey:table.database]; if(database == nil){ - database = [[GPKGSDatabase alloc] initWithName:table.database andExpanded:false]; + database = [[MCDatabase alloc] initWithName:table.database andExpanded:false]; [self.databases setObject:database forKey:table.database]; } @@ -123,12 +123,12 @@ -(void) addTable: (GPKGSTable *) table andUpdatePreferences: (BOOL) updatePrefer self.modified = true; } --(void) removeTable: (GPKGSTable *) table{ +-(void) removeTable: (MCTable *) table{ [self removeTable:table andPreserveOverlays:false]; } --(void) removeTable: (GPKGSTable *) table andPreserveOverlays: (BOOL) preserveOverlays{ - GPKGSDatabase * database = [self.databases objectForKey:table.database]; +-(void) removeTable: (MCTable *) table andPreserveOverlays: (BOOL) preserveOverlays{ + MCDatabase * database = [self.databases objectForKey:table.database]; if(database != nil){ [database remove:table]; [self removeTableFromPreferences:table]; @@ -138,12 +138,12 @@ -(void) removeTable: (GPKGSTable *) table andPreserveOverlays: (BOOL) preserveOv } if(!preserveOverlays && [table getType] == GPKGS_TT_FEATURE){ NSMutableArray * deleteFeatureOverlays = [[NSMutableArray alloc] init]; - for(GPKGSFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ + for(MCFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ if([featureOverlay.featureTable isEqualToString:table.name]){ [deleteFeatureOverlays addObject:featureOverlay]; } } - for(GPKGSFeatureOverlayTable * featureOverlay in deleteFeatureOverlays){ + for(MCFeatureOverlayTable * featureOverlay in deleteFeatureOverlays){ [self removeTable:featureOverlay]; } } @@ -157,7 +157,7 @@ -(BOOL) isEmpty{ -(int) getTableCount{ int count = 0; - for(GPKGSDatabase * database in [self.databases allValues]){ + for(MCDatabase * database in [self.databases allValues]){ count += [database getTableCount]; } return count; @@ -165,7 +165,7 @@ -(int) getTableCount{ -(int) getActiveTableCount{ int count = 0; - for(GPKGSDatabase * database in [self.databases allValues]){ + for(MCDatabase * database in [self.databases allValues]){ count += [database getActiveTableCount]; } return count; @@ -175,8 +175,8 @@ -(void) clearActive{ NSMutableArray * allDatabases = [[NSMutableArray alloc] init]; [allDatabases addObjectsFromArray:[self.databases allKeys]]; for(NSString * database in allDatabases){ - GPKGSDatabase * db = [self.databases objectForKey:database]; - for(GPKGSTable * table in [db getFeatureOverlays]){ + MCDatabase * db = [self.databases objectForKey:database]; + for(MCTable * table in [db getFeatureOverlays]){ if(table.active){ table.active = false; [self addTable:table andUpdatePreferences:true]; @@ -193,13 +193,13 @@ -(void) removeDatabase: (NSString *) database andPreserveOverlays: (BOOL) preser } -(void) renameDatabase: (NSString *) database asNewDatabase: (NSString *) newDatabase{ - GPKGSDatabase * geoPackageDatabase = [self.databases objectForKey:database]; + MCDatabase * geoPackageDatabase = [self.databases objectForKey:database]; if(geoPackageDatabase != nil){ [self.databases removeObjectForKey:database]; geoPackageDatabase.name = newDatabase; [self.databases setObject:geoPackageDatabase forKey:newDatabase]; [self removeDatabaseFromPreferences:database andPreserveOverlays:false]; - for(GPKGSTable * table in [geoPackageDatabase getTables]){ + for(MCTable * table in [geoPackageDatabase getTables]){ table.database = newDatabase; [self addTableToPreferences:table]; } @@ -217,17 +217,17 @@ -(void) loadFromPreferences{ if(tiles != nil){ for(NSString * tile in tiles){ - [self addTable:[[GPKGSTileTable alloc] initWithDatabase:database andName:tile andCount:0] andUpdatePreferences:false]; + [self addTable:[[MCTileTable alloc] initWithDatabase:database andName:tile andCount:0] andUpdatePreferences:false]; } } if(features != nil){ for(NSString * feature in features){ - [self addTable:[[GPKGSFeatureTable alloc] initWithDatabase:database andName:feature andGeometryType:SF_NONE andCount:0] andUpdatePreferences:false]; + [self addTable:[[MCFeatureTable alloc] initWithDatabase:database andName:feature andGeometryType:SF_NONE andCount:0] andUpdatePreferences:false]; } } if(featureOverlays != nil){ for(NSString * featureOverlay in featureOverlays){ - GPKGSFeatureOverlayTable * featureOverlayTable = [self readFeatureOverlayTable:featureOverlay withDatabase:database]; + MCFeatureOverlayTable * featureOverlayTable = [self readFeatureOverlayTable:featureOverlay withDatabase:database]; if(featureOverlayTable != nil){ [self addTable:featureOverlayTable andUpdatePreferences:false]; } @@ -257,7 +257,7 @@ -(void) removeDatabaseFromPreferences: (NSString *) database andPreserveOverlays [self.settings synchronize]; } --(void) removeTableFromPreferences: (GPKGSTable *) table{ +-(void) removeTableFromPreferences: (MCTable *) table{ switch([table getType]){ case GPKGS_TT_FEATURE: @@ -301,7 +301,7 @@ -(void) removeTableFromPreferences: (GPKGSTable *) table{ [self.settings synchronize]; } --(void) addTableToPreferences: (GPKGSTable *) table{ +-(void) addTableToPreferences: (MCTable *) table{ NSArray * databases = [self.settings stringArrayForKey:GPKGS_DATABASES_PREFERENCE]; if(databases == nil || ![databases containsObject:table.database]){ @@ -365,7 +365,7 @@ -(void) addTableToPreferences: (GPKGSTable *) table{ [self.settings synchronize]; } --(NSString *) getTileTablesPreferenceKeyForTable: (GPKGSTable *) table{ +-(NSString *) getTileTablesPreferenceKeyForTable: (MCTable *) table{ return [self getTileTablesPreferenceKeyForDatabase:table.database]; } @@ -373,7 +373,7 @@ -(NSString *) getTileTablesPreferenceKeyForDatabase: (NSString *) database{ return [NSString stringWithFormat:@"%@%@", database, GPKGS_TILE_TABLES_PREFERENCE_SUFFIX]; } --(NSString *) getFeatureTablesPreferenceKeyForTable: (GPKGSTable *) table{ +-(NSString *) getFeatureTablesPreferenceKeyForTable: (MCTable *) table{ return [self getFeatureTablesPreferenceKeyForDatabase:table.database]; } @@ -381,7 +381,7 @@ -(NSString *) getFeatureTablesPreferenceKeyForDatabase: (NSString *) database{ return [NSString stringWithFormat:@"%@%@", database, GPKGS_FEATURE_TABLES_PREFERENCE_SUFFIX]; } --(NSString *) getFeatureOverlayTablesPreferenceKeyForTable: (GPKGSTable *) table{ +-(NSString *) getFeatureOverlayTablesPreferenceKeyForTable: (MCTable *) table{ return [self getFeatureOverlayTablesPreferenceKeyForDatabase:table.database]; } @@ -389,7 +389,7 @@ -(NSString *) getFeatureOverlayTablesPreferenceKeyForDatabase: (NSString *) data return [NSString stringWithFormat:@"%@%@", database, GPKGS_FEATURE_OVERLAY_TABLES_PREFERENCE_SUFFIX]; } --(void) writeTableValues: (GPKGSTable *) table{ +-(void) writeTableValues: (MCTable *) table{ NSDictionary * values = [table getValues]; @@ -397,10 +397,10 @@ -(void) writeTableValues: (GPKGSTable *) table{ [self.settings synchronize]; } --(GPKGSFeatureOverlayTable *) readFeatureOverlayTable: (NSString *) table withDatabase: (NSString *) database{ +-(MCFeatureOverlayTable *) readFeatureOverlayTable: (NSString *) table withDatabase: (NSString *) database{ NSDictionary * tableValues = [self readTableValues:table withDatabase:database]; - GPKGSFeatureOverlayTable * featureOverlayTable = [[GPKGSFeatureOverlayTable alloc] initWithValues:tableValues]; + MCFeatureOverlayTable * featureOverlayTable = [[MCFeatureOverlayTable alloc] initWithValues:tableValues]; return featureOverlayTable; } @@ -412,7 +412,7 @@ -(NSDictionary *) readTableValues: (NSString *) table withDatabase: (NSString *) return tableValues; } --(void) deleteTableValues: (GPKGSTable *) table{ +-(void) deleteTableValues: (MCTable *) table{ [self deleteTableValues:table.name withDatabase:table.database]; } @@ -421,7 +421,7 @@ -(void) deleteTableValues: (NSString *) table withDatabase: (NSString *) databas [self.settings synchronize]; } --(NSString *) getTableValuesPreferenceKeyForTable: (GPKGSTable *) table{ +-(NSString *) getTableValuesPreferenceKeyForTable: (MCTable *) table{ return [self getTableValuesPreferenceKeyForTable:table.name withDatabase:table.database]; } diff --git a/mapcache-ios/data/GPKGSFeatureOverlayTable.h b/mapcache-ios/data/MCFeatureOverlayTable.h similarity index 94% rename from mapcache-ios/data/GPKGSFeatureOverlayTable.h rename to mapcache-ios/data/MCFeatureOverlayTable.h index 3d3a400..6700472 100644 --- a/mapcache-ios/data/GPKGSFeatureOverlayTable.h +++ b/mapcache-ios/data/MCFeatureOverlayTable.h @@ -6,10 +6,10 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSFeatureTable.h" +#import "MCFeatureTable.h" #import -@interface GPKGSFeatureOverlayTable : GPKGSFeatureTable +@interface MCFeatureOverlayTable : MCFeatureTable @property (nonatomic, strong) NSString *featureTable; @property (nonatomic) int minZoom; diff --git a/mapcache-ios/data/GPKGSFeatureOverlayTable.m b/mapcache-ios/data/MCFeatureOverlayTable.m similarity index 99% rename from mapcache-ios/data/GPKGSFeatureOverlayTable.m rename to mapcache-ios/data/MCFeatureOverlayTable.m index 001500e..e75f6b5 100644 --- a/mapcache-ios/data/GPKGSFeatureOverlayTable.m +++ b/mapcache-ios/data/MCFeatureOverlayTable.m @@ -6,7 +6,7 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSFeatureOverlayTable.h" +#import "MCFeatureOverlayTable.h" #import "GPKGUtils.h" NSString * const GPKGS_FEATURE_OVERLAY_TABLE_FEATURE_TABLE = @"feature_table"; @@ -40,7 +40,7 @@ NSString * const GPKGS_FEATURE_OVERLAY_TABLE_COLOR_SUFFIX_WHITE = @"_white"; NSString * const GPKGS_FEATURE_OVERLAY_TABLE_COLOR_SUFFIX_ALPHA = @"_alpha"; -@implementation GPKGSFeatureOverlayTable +@implementation MCFeatureOverlayTable -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andFeatureTable: (NSString *) featureTable andGeometryType: (enum SFGeometryType) geometryType andCount: (int) count{ self = [super initWithDatabase:database andName:name andGeometryType:geometryType andCount:count]; diff --git a/mapcache-ios/data/GPKGSFeatureTable.h b/mapcache-ios/data/MCFeatureTable.h similarity index 88% rename from mapcache-ios/data/GPKGSFeatureTable.h rename to mapcache-ios/data/MCFeatureTable.h index f6b19aa..1091225 100644 --- a/mapcache-ios/data/GPKGSFeatureTable.h +++ b/mapcache-ios/data/MCFeatureTable.h @@ -6,12 +6,12 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSTable.h" +#import "MCTable.h" #import "SFGeometryTypes.h" extern NSString * const GPKGS_FEATURE_TABLE_GEOMETRY_TYPE; -@interface GPKGSFeatureTable : GPKGSTable +@interface MCFeatureTable : MCTable @property (nonatomic) enum SFGeometryType geometryType; diff --git a/mapcache-ios/data/GPKGSFeatureTable.m b/mapcache-ios/data/MCFeatureTable.m similarity index 94% rename from mapcache-ios/data/GPKGSFeatureTable.m rename to mapcache-ios/data/MCFeatureTable.m index 9d7d2e3..667ce42 100644 --- a/mapcache-ios/data/GPKGSFeatureTable.m +++ b/mapcache-ios/data/MCFeatureTable.m @@ -6,11 +6,11 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSFeatureTable.h" +#import "MCFeatureTable.h" NSString * const GPKGS_FEATURE_TABLE_GEOMETRY_TYPE = @"geometry_type"; -@implementation GPKGSFeatureTable +@implementation MCFeatureTable -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andGeometryType: (enum SFGeometryType) geometryType andCount: (int) count{ self = [super initWithDatabase:database andName:name andCount:count]; diff --git a/mapcache-ios/data/MCGeoPackageRepository.h b/mapcache-ios/data/MCGeoPackageRepository.h new file mode 100644 index 0000000..cd972e0 --- /dev/null +++ b/mapcache-ios/data/MCGeoPackageRepository.h @@ -0,0 +1,57 @@ +// +// MCGeoPackageRepository.h +// mapcache-ios +// +// Created by Tyler Burgett on 3/2/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import +#import +#import "GPKGGeoPackageFactory.h" +#import "GPKGGeoPackageCache.h" +#import "GPKGMultipleFeatureIndexResults.h" +#import "GPKGFeatureIndexListResults.h" +#import "GPKGFeatureIndexManager.h" +#import "GPKGMapShapeConverter.h" +#import "MCDatabase.h" +#import "MCDatabases.h" +#import "MCFeatureTable.h" +#import "MCTileTable.h" +#import "MCTileHelper.h" +#import "MCFeatureOverlayTable.h" +#import "GPKGAlterTable.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface MCGeoPackageRepository : NSObject +@property (nonatomic, strong) NSString *selectedGeoPackageName; +@property (nonatomic, strong) NSString *selectedLayerName; + ++ (MCGeoPackageRepository *) sharedRepository; +- (NSMutableArray *)databaseList; +- (MCDatabases *)activeDatabases; +- (NSMutableArray *)regenerateDatabaseList; +- (MCDatabase *)refreshDatabaseAndUpdateList:(NSString *)databaseName; +- (MCDatabase *)databaseNamed:(NSString *)databaseName; +- (BOOL)exists:(NSString *)geoPackageName; +- (void)deleteGeoPackage:(MCDatabase *)database; +- (BOOL)database:(MCDatabase *)database containsTableNamed:(NSString *)tableName; +- (BOOL)createGeoPackage:(NSString *)geoPackageName; +- (BOOL)copyGeoPacakge:(NSString *)geoPacakgeName to:(NSString *)newName; +- (BOOL)savePoints:(NSArray *) points toDatabase:(MCDatabase *) database table:(MCTable *) table; +- (BOOL)createFeatueLayerIn:(NSString *)database withGeomertyColumns:(GPKGGeometryColumns *)geometryColumns boundingBox:(GPKGBoundingBox *)boundingBox srsId:(NSNumber *) srsId; +- (BOOL) renameTable:(MCTable *) table toNewName:(NSString *)newTableName; +- (NSArray *)tileMatricesForTableNamed:(NSString *) tableName inDatabase:(NSString *)databaseName; +- (GPKGUserRow *)queryRow:(int)rowId fromTableNamed:(NSString *)tableName inDatabase:(NSString *)databaseName; +- (BOOL)saveRow:(GPKGUserRow *)row; +- (GPKGFeatureRow *)newRowInTable:(NSString *) table database:(NSString *)database mapPoint:(GPKGMapPoint *)mapPoint; +- (int)deleteRow:(GPKGUserRow *)featureRow fromDatabase:(NSString *)databaseName; +- (NSArray *)columnsForTable:(NSString *) table database:(NSString *)database; +- (BOOL)addColumn:(GPKGFeatureColumn *)featureColumn to:(MCTable *)table; +- (NSArray *)renameColumn:(GPKGUserColumn*)column newName:(NSString *)newColumnName table:(MCTable *)table; +- (NSArray *)deleteColumn:(GPKGUserColumn*)column table:(MCTable *)table; +@end + +NS_ASSUME_NONNULL_END diff --git a/mapcache-ios/data/MCGeoPackageRepository.m b/mapcache-ios/data/MCGeoPackageRepository.m new file mode 100644 index 0000000..101b4e7 --- /dev/null +++ b/mapcache-ios/data/MCGeoPackageRepository.m @@ -0,0 +1,575 @@ +// +// MCGeoPackageRepository.m +// mapcache-ios +// +// Created by Tyler Burgett on 3/2/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import "MCGeoPackageRepository.h" +#import "mapcache_ios-Swift.h" + +static MCGeoPackageRepository *sharedRepository; + +@interface MCGeoPackageRepository() +@property (nonatomic, strong) GPKGGeoPackageManager *manager; +@property (nonatomic, strong) MCDatabases *activeDatabases; +@property (nonatomic, strong) NSMutableArray *databaseList; +@end + + +@implementation MCGeoPackageRepository +/** + This class is a singleton. + */ ++ (MCGeoPackageRepository *) sharedRepository { + if (sharedRepository == nil) { + sharedRepository = [[self alloc] init]; + } + + return sharedRepository; +} + + +- (id)init { + self = [super init]; + + _databaseList = [[NSMutableArray alloc] init]; + _manager = [GPKGGeoPackageFactory manager]; + _activeDatabases = [MCDatabases getInstance]; + + return self; +} + + +/** + Get an array of the available GeoPackage databases. + */ +- (NSMutableArray *)databaseList { + return _databaseList; +} + + +- (MCDatabases *)activeDatabases { + return _activeDatabases; +} + + +- (NSMutableArray *)regenerateDatabaseList { + _databaseList = [[NSMutableArray alloc] init]; + NSArray *databaseNames = [_manager databases]; + + for(NSString * databaseName in databaseNames){ + [_databaseList addObject: [self readGeoPacakgeIntoDatabase:databaseName]]; + } + + return _databaseList; +} + + +- (MCDatabase *)refreshDatabaseAndUpdateList:(NSString *)databaseName { + MCDatabase * theDatabase = [self readGeoPacakgeIntoDatabase:databaseName]; + + for (int i = 0; i < _databaseList.count; i++) { + MCDatabase *database = [_databaseList objectAtIndex:i]; + if ([database.name isEqualToString:databaseName]) { + [_databaseList replaceObjectAtIndex:i withObject:theDatabase]; + } + } + + return theDatabase; +} + + +- (MCDatabase *) readGeoPacakgeIntoDatabase:(NSString *) databaseName { + MCDatabase * theDatabase = nil; + GPKGGeoPackage * geoPackage = nil; + + @try { + geoPackage = [_manager open:databaseName]; + theDatabase = [[MCDatabase alloc] initWithName:databaseName andExpanded:NO]; + NSMutableArray * tables = [[NSMutableArray alloc] init]; + + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; + for(NSString * tableName in [geoPackage featureTables]){ + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:tableName]; + int count = [featureDao count]; + + GPKGContents * contents = (GPKGContents *)[contentsDao queryForIdObject:tableName]; + GPKGGeometryColumns * geometryColumns = [contentsDao geometryColumns:contents]; + enum SFGeometryType geometryType = [SFGeometryTypes fromName:geometryColumns.geometryTypeName]; + + MCFeatureTable * table = [[MCFeatureTable alloc] initWithDatabase:databaseName andName:tableName andGeometryType:geometryType andCount:count]; + + [tables addObject:table]; + [theDatabase addFeature:table]; + } + + for(NSString * tableName in [geoPackage tileTables]){ + GPKGTileDao * tileDao = [geoPackage tileDaoWithTableName: tableName]; + int count = [tileDao count]; + MCTileTable * table = [[MCTileTable alloc] initWithDatabase:databaseName andName:tableName andCount:count andMinZoom:tileDao.minZoom andMaxZoom:tileDao.maxZoom]; + [table setActive: [_activeDatabases exists:table]]; + + MCTileHelper *tileHelper = [[MCTileHelper alloc] init]; + GPKGTileMatrixSet * tileMatrixSet = tileDao.tileMatrixSet; + GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage tileMatrixSetDao]; + GPKGSpatialReferenceSystem *tileMatrixSetSrs = [tileMatrixSetDao srs:tileMatrixSet]; + GPKGBoundingBox *boundingBox = [tileDao boundingBoxWithZoomLevel:tileDao.maxZoom]; + + table.center = [tileHelper transformBoundingBoxToWgs84:boundingBox withSrs:tileMatrixSetSrs].center; + + for (GPKGTileMatrix *tileMatrix in tileDao.tileMatrices) { + MCTileMatrix *mcTileMatrix = [[MCTileMatrix alloc] init]; + mcTileMatrix.zoomLevel = tileMatrix.zoomLevel; + mcTileMatrix.tileCount = [NSNumber numberWithInt:[tileDao countWithZoomLevel:[tileMatrix.zoomLevel intValue]]]; + mcTileMatrix.matrixWidth = tileMatrix.matrixWidth; + mcTileMatrix.matrixHeight = tileMatrix.matrixHeight; + mcTileMatrix.tileWidth = tileMatrix.tileWidth; + mcTileMatrix.tileHeight = tileMatrix.tileHeight; + mcTileMatrix.pixelXSize = tileMatrix.pixelXSize; + mcTileMatrix.pixelYSize = tileMatrix.pixelYSize; + [table.tileMatrices addObject:mcTileMatrix]; + } + + [tables addObject:table]; + [theDatabase addTile:table]; + } + + for(MCFeatureOverlayTable * table in [_activeDatabases featureOverlays:databaseName]){ + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:table.featureTable]; + int count = [featureDao count]; + [table setCount:count]; + + [tables addObject:table]; + [theDatabase addFeatureOverlay:table]; + } + } @catch(NSException *e) { + NSLog(@"Problem reading database %@ :\n%@",databaseName, e.reason); + } @finally { + if(geoPackage == nil){ + @try { + [self.manager delete:geoPackage.name]; + } + @catch (NSException *exception) { + NSLog(@"Caught Exception trying to delete %@ %@", databaseName, exception.reason); + } + }else{ + [geoPackage close]; + } + } + + return theDatabase; +} + + +//MARK: GeoPackage aka Database operations +/** + Get a database by name. + @return the database you were looking for + */ +- (MCDatabase *)databaseNamed:(NSString *)databaseName { + for (MCDatabase *database in _databaseList) { + if ([database.name isEqualToString:databaseName]) { + return database; + } + } + + return nil; +} + + +/** + Check to see if the database has a table with a specific name. + @param database The MCDatabase you want to search. + @param tableName The table you are looking for + @return a boolean, yes if the table was found, no if it was not. + @return + */ +- (BOOL)database:(MCDatabase *) database containsTableNamed:(NSString *) tableName { + return [database hasTableNamed:tableName]; +} + + +- (BOOL)createGeoPackage:(NSString *)geoPackageName { + return [_manager create:geoPackageName]; +} + + +- (BOOL)copyGeoPacakge:(NSString *)geoPacakgeName to:(NSString *)newName { + return [_manager copy:geoPacakgeName to:newName]; +} + + +- (BOOL)exists:(NSString *)geoPackageName { + return [_manager exists:geoPackageName]; +} + + +- (void)deleteGeoPackage:(MCDatabase *)database { + [self.manager delete:database.name]; + [_activeDatabases removeDatabase:database.name andPreserveOverlays:NO]; + [_databaseList removeObjectIdenticalTo:database]; +} + + +- (BOOL)savePoints:(NSArray *) points toDatabase:(MCDatabase *) database table:(MCTable *) table { + GPKGGeoPackage *geoPackage = nil; + GPKGFeatureIndexManager *indexer = nil; + BOOL saved = YES; + + @try { + geoPackage = [_manager open:database.name]; + GPKGFeatureDao *featureDao = [geoPackage featureDaoWithTableName:table.name]; + NSNumber *srsId = featureDao.geometryColumns.srsId; + indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; + NSArray *indexedTypes = [indexer indexedTypes]; + GPKGMapShapeConverter *converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; + + for (GPKGMapPoint *mapPoint in points) { + SFPoint *point = [converter toPointWithMapPoint:mapPoint]; + GPKGFeatureRow *newPoint = [featureDao newRow]; + GPKGGeometryData *pointGeomData = [[GPKGGeometryData alloc] initWithSrsId:srsId]; + [pointGeomData setGeometry: point]; + [newPoint setGeometry:pointGeomData]; + + [featureDao insert:newPoint]; + // TODO expand the bounds of the geopackage + + if (indexedTypes.count > 0) { + [indexer indexWithFeatureRow:newPoint andFeatureIndexTypes:indexedTypes]; + } + } + + } @catch (NSException *e) { + NSLog(@"Problem while saving points: %@", e.reason); + saved = NO; + } @finally { + if (indexer != nil) { + [indexer close]; + } + + if (geoPackage != nil) { + [geoPackage close]; + } + + [self regenerateDatabaseList]; + return saved; + } +} + + +//MARK: Table aka Layer operations +- (BOOL) createFeatueLayerIn:(NSString *)database withGeomertyColumns:(GPKGGeometryColumns *)geometryColumns boundingBox:(GPKGBoundingBox *)boundingBox srsId:(NSNumber *) srsId { + GPKGGeoPackage * geoPackage; + BOOL didCreateLayer = YES; + + @try { + geoPackage = [_manager open:database]; + //[geoPackage createFeatureTableWithGeometryColumns:geometryColumns andBoundingBox:boundingBox andSrsId:srsId]; + [geoPackage createFeatureTableWithGeometryColumns:geometryColumns andIdColumnName:@"id" andBoundingBox:boundingBox andSrsId:srsId]; + } + @catch (NSException *e) { + // TODO handle this + NSLog(@"There was a problem creating the layer, %@", e.reason); + didCreateLayer = NO; + } @finally { + [geoPackage close]; + [self regenerateDatabaseList]; + return didCreateLayer; + } +} + + +- (BOOL) renameTable:(MCTable *) table toNewName:(NSString *)newTableName { + GPKGGeoPackage *geoPackage; + BOOL didRenameTable = YES; + BOOL addToActive = NO; + + if ([self.activeDatabases exists:table]) { + [self.activeDatabases removeTable:table]; + addToActive = YES; + } + + @try { + geoPackage = [_manager open:table.database]; + NSLog(@"Tables before renaming"); + + for(NSString *table in geoPackage.tables) { + NSLog(@"%@", table); + } + + [geoPackage renameTable:table.name toTable:newTableName]; + MCDatabase *updatedDatabase = [self refreshDatabaseAndUpdateList:table.database];; + + if (addToActive) { + [self.activeDatabases addTable:[updatedDatabase tableNamed:newTableName]]; + } + + NSLog(@"Tables after renaming"); + + for(NSString *table in geoPackage.tables) { + NSLog(@"%@", table); + } + didRenameTable = YES; + } @catch (NSException *e) { + NSLog(@"MCGeoPackageRepository - Probem renaiming table: %@", e.reason); + didRenameTable = NO; + } @finally { + [geoPackage close]; + return didRenameTable; + } +} + + +- (NSArray *)tileMatricesForTableNamed:(NSString *) tableName inDatabase:(NSString *)databaseName { + GPKGGeoPackage *geoPackage = nil; + + @try { + geoPackage = [_manager open:databaseName]; + GPKGTileDao *tileDao = [geoPackage tileDaoWithTableName:tableName]; + return tileDao.tileMatrices; + } @catch(NSException *e) { + NSLog(@"Problem getting tile table details %@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + } +} + + +- (GPKGUserRow *)queryRow:(int)rowId fromTableNamed:(NSString *)tableName inDatabase:(NSString *)databaseName { + GPKGUserRow *userRow = nil; + GPKGGeoPackage *geoPackage = nil; + + @try { + geoPackage = [_manager open:databaseName]; + GPKGFeatureDao* featureDao = [geoPackage featureDaoWithTableName:tableName]; + userRow = [featureDao queryForIdRow:rowId]; + } @catch(NSException *e) { + NSLog(@"Problem querying row: %@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + + return userRow; + } +} + + +- (BOOL)saveRow:(GPKGFeatureRow *)featureRow { + GPKGGeoPackage *geoPackage = nil; + GPKGFeatureIndexManager *indexer = nil; + BOOL saved = YES; + + @try { + geoPackage = [_manager open:self.selectedGeoPackageName]; + GPKGFeatureDao *featureDao = [geoPackage featureDaoWithTableName:self.selectedLayerName]; + + if (featureRow.values[0] && [featureRow.values[0] isKindOfClass:NSNull.class]) { // new row + [featureDao insert:featureRow]; + indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; + NSArray *indexedTypes = [indexer indexedTypes]; + + if (indexedTypes.count > 0) { + [indexer indexWithFeatureRow:featureRow andFeatureIndexTypes:indexedTypes]; + } + + } else { + int update = [featureDao update:featureRow]; + if (update == 0) { + saved = NO; + } + } + + MCDatabase *database = [self databaseNamed:geoPackage.name]; + MCTable *table = [database tableNamed:featureRow.tableName]; + + if (table != nil) { + [_activeDatabases addTable:table]; + } + + self.selectedLayerName = @""; + self.selectedGeoPackageName = @""; + + } @catch (NSException *e) { + NSLog(@"Problem while saving point data: %@", e.reason); + saved = NO; + } @finally { + if (indexer != nil) { + [indexer close]; + } + + if (geoPackage != nil) { + [geoPackage close]; + } + + [self regenerateDatabaseList]; + return saved; + } +} + + +- (GPKGFeatureRow *)newRowInTable:(NSString *) table database:(NSString *)database mapPoint:(GPKGMapPoint *)mapPoint { + GPKGFeatureRow *newRow = nil; + GPKGFeatureIndexManager *indexer = nil; + GPKGGeoPackage *geoPackage = nil; + + @try { + geoPackage = [_manager open:database]; + GPKGFeatureDao *featureDao = [geoPackage featureDaoWithTableName:table]; + newRow = [featureDao newRow]; + NSNumber *srsId = featureDao.geometryColumns.srsId; + indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; + GPKGMapShapeConverter *converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; + + SFPoint *point = [converter toPointWithMapPoint:mapPoint]; + GPKGGeometryData *pointGeomData = [[GPKGGeometryData alloc] initWithSrsId:srsId]; + [pointGeomData setGeometry: point]; + [newRow setGeometry:pointGeomData]; + + } @catch (NSException *e) { + NSLog(@"Problem while deleting point data: %@", e.reason); + newRow = nil; + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + + [self regenerateDatabaseList]; + return newRow; + } + + +} + + +- (int)deleteRow:(GPKGUserRow *)featureRow fromDatabase:(NSString *)databaseName { + GPKGGeoPackage *geoPackage = nil; + int rowsDeleted = 0; + + @try { + geoPackage = [_manager open:databaseName]; + GPKGFeatureDao *featureDao = [geoPackage featureDaoWithTableName:featureRow.table.tableName]; + rowsDeleted = [featureDao delete:featureRow] > 0; + } @catch (NSException *e) { + NSLog(@"Problem while deleting point data: %@", e.reason); + rowsDeleted = 0; + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + + [self regenerateDatabaseList]; + return rowsDeleted; + } +} + + +- (NSArray *)columnsForTable:(NSString *) table database:(NSString *)database { + NSArray *columns = nil; + GPKGGeoPackage *geoPackage =nil; + + @try { + geoPackage = [_manager open:database]; + GPKGFeatureDao* featureDao = [geoPackage featureDaoWithTableName:table]; + columns = [featureDao columns]; + } @catch(NSException *e) { + NSLog(@"Problem querying row: %@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + + return columns; + } +} + + +- (BOOL)addColumn:(GPKGFeatureColumn *)featureColumn to:(MCTable *)table { + BOOL didAdd = YES; + GPKGGeoPackage *geoPackage = nil; + + @try { + geoPackage = [_manager open:table.database]; + GPKGFeatureDao *featureDao = [geoPackage featureDaoWithTableName:table.name]; + [featureDao addColumn:featureColumn]; + } @catch(NSException *e) { + NSLog(@"Problem creating column %@ in %@ table in %@", featureColumn.name, table.name, table.database); + didAdd = NO; + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + } + + return didAdd; +} + + +- (NSArray *)renameColumn:(GPKGUserColumn*)column newName:(NSString *)newColumnName table:(MCTable *)table { + GPKGGeoPackage *geoPackage = nil; + GPKGFeatureDao *featureDao = nil; + + BOOL addToActive = NO; + + if ([self.activeDatabases exists:table]) { + [self.activeDatabases removeTable:table]; + addToActive = YES; + } + + @try { + geoPackage = [_manager open:table.database]; + featureDao = [geoPackage featureDaoWithTableName:table.name]; + [featureDao renameColumn:column toColumn:newColumnName]; + MCDatabase *updatedDatabase = [self refreshDatabaseAndUpdateList:table.database]; + + if (addToActive) { + [self.activeDatabases addTable:[updatedDatabase tableNamed:table.name]]; + } + } @catch(NSException *e) { + NSLog(@"Problem querying row: %@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + + return [featureDao columns]; + } +} + + +- (NSArray *)deleteColumn:(GPKGUserColumn*)column table:(MCTable *)table { + GPKGGeoPackage *geoPackage; + GPKGFeatureDao *featureDao = nil; + BOOL addToActive = NO; + + if ([self.activeDatabases exists:table]) { + [self.activeDatabases removeTable:table]; + addToActive = YES; + } + + @try { + geoPackage = [_manager open:table.database]; + featureDao = [geoPackage featureDaoWithTableName:table.name]; + [featureDao dropColumn:column]; + MCDatabase *updatedDatabase = [self refreshDatabaseAndUpdateList:table.database]; + + if (addToActive) { + [self.activeDatabases addTable:[updatedDatabase tableNamed:table.name]]; + } + } @catch (NSException *e) { + NSLog(@"MCGeoPackageRepository - Probem renaiming table: %@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } + + return [featureDao columns]; + } +} + + +@end diff --git a/mapcache-ios/data/GPKGSTable.h b/mapcache-ios/data/MCTable.h similarity index 92% rename from mapcache-ios/data/GPKGSTable.h rename to mapcache-ios/data/MCTable.h index f378fad..e224397 100644 --- a/mapcache-ios/data/GPKGSTable.h +++ b/mapcache-ios/data/MCTable.h @@ -7,14 +7,14 @@ // #import -#import "GPKGSTableTypes.h" +#import "MCTableTypes.h" extern NSString * const GPKGS_TABLE_DATABASE; extern NSString * const GPKGS_TABLE_NAME; extern NSString * const GPKGS_TABLE_COUNT; extern NSString * const GPKGS_TABLE_ACTIVE; -@interface GPKGSTable : NSObject +@interface MCTable : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *database; diff --git a/mapcache-ios/data/GPKGSTable.m b/mapcache-ios/data/MCTable.m similarity index 97% rename from mapcache-ios/data/GPKGSTable.m rename to mapcache-ios/data/MCTable.m index ef0246d..d385569 100644 --- a/mapcache-ios/data/GPKGSTable.m +++ b/mapcache-ios/data/MCTable.m @@ -6,14 +6,14 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSTable.h" +#import "MCTable.h" NSString * const GPKGS_TABLE_DATABASE = @"database"; NSString * const GPKGS_TABLE_NAME = @"name"; NSString * const GPKGS_TABLE_COUNT = @"count"; NSString * const GPKGS_TABLE_ACTIVE = @"active"; -@implementation GPKGSTable +@implementation MCTable -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andCount: (int) count{ self = [super init]; diff --git a/mapcache-ios/data/GPKGSTableIndex.h b/mapcache-ios/data/MCTableIndex.h similarity index 55% rename from mapcache-ios/data/GPKGSTableIndex.h rename to mapcache-ios/data/MCTableIndex.h index b6766fa..4c9a498 100644 --- a/mapcache-ios/data/GPKGSTableIndex.h +++ b/mapcache-ios/data/MCTableIndex.h @@ -7,14 +7,14 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGFeatureIndexTypes.h" -@interface GPKGSTableIndex : NSObject +@interface MCTableIndex : NSObject -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; @property (nonatomic) enum GPKGFeatureIndexType indexLocation; --(instancetype) initWithTable: (GPKGSTable *) table andIndexLocation: (enum GPKGFeatureIndexType) indexLocation; +-(instancetype) initWithTable: (MCTable *) table andIndexLocation: (enum GPKGFeatureIndexType) indexLocation; @end diff --git a/mapcache-ios/data/GPKGSTableIndex.m b/mapcache-ios/data/MCTableIndex.m similarity index 62% rename from mapcache-ios/data/GPKGSTableIndex.m rename to mapcache-ios/data/MCTableIndex.m index cab1b3c..5667a11 100644 --- a/mapcache-ios/data/GPKGSTableIndex.m +++ b/mapcache-ios/data/MCTableIndex.m @@ -6,11 +6,11 @@ // Copyright © 2015 NGA. All rights reserved. // -#import "GPKGSTableIndex.h" +#import "MCTableIndex.h" -@implementation GPKGSTableIndex +@implementation MCTableIndex --(instancetype) initWithTable: (GPKGSTable *) table andIndexLocation: (enum GPKGFeatureIndexType) indexLocation{ +-(instancetype) initWithTable: (MCTable *) table andIndexLocation: (enum GPKGFeatureIndexType) indexLocation{ self = [super init]; if(self != nil){ self.table = table; diff --git a/mapcache-ios/data/GPKGSTableTypes.h b/mapcache-ios/data/MCTableTypes.h similarity index 93% rename from mapcache-ios/data/GPKGSTableTypes.h rename to mapcache-ios/data/MCTableTypes.h index d4fac7f..2b85ae0 100644 --- a/mapcache-ios/data/GPKGSTableTypes.h +++ b/mapcache-ios/data/MCTableTypes.h @@ -18,7 +18,7 @@ extern NSString * const GPKGS_TT_FEATURE_NAME; extern NSString * const GPKGS_TT_TILE_NAME; extern NSString * const GPKGS_TT_FEATURE_OVERLAY_NAME; -@interface GPKGSTableTypes : NSObject +@interface MCTableTypes : NSObject +(NSString *) name: (enum GPKGSTableType) tableType; diff --git a/mapcache-ios/data/GPKGSTableTypes.m b/mapcache-ios/data/MCTableTypes.m similarity index 96% rename from mapcache-ios/data/GPKGSTableTypes.m rename to mapcache-ios/data/MCTableTypes.m index a11f096..0d5110f 100644 --- a/mapcache-ios/data/GPKGSTableTypes.m +++ b/mapcache-ios/data/MCTableTypes.m @@ -6,14 +6,14 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSTableTypes.h" +#import "MCTableTypes.h" #import "GPKGUtils.h" NSString * const GPKGS_TT_FEATURE_NAME = @"FEATURE"; NSString * const GPKGS_TT_TILE_NAME = @"TILE"; NSString * const GPKGS_TT_FEATURE_OVERLAY_NAME = @"FEATURE_OVERLAY"; -@implementation GPKGSTableTypes +@implementation MCTableTypes +(NSString *) name: (enum GPKGSTableType) tableType{ NSString * name = nil; diff --git a/mapcache-ios/data/MCTileMatrix.swift b/mapcache-ios/data/MCTileMatrix.swift new file mode 100644 index 0000000..1242b9e --- /dev/null +++ b/mapcache-ios/data/MCTileMatrix.swift @@ -0,0 +1,22 @@ +// +// MCTileMatrix.swift +// mapcache-ios +// +// Created by Tyler Burgett on 7/9/20. +// Copyright © 2020 NGA. All rights reserved. +// + +import Foundation + +class MCTileMatrix: NSObject { + + @objc var zoomLevel: NSNumber = 0 + @objc var tileCount: NSNumber = 0 + @objc var matrixWidth: NSNumber = 0 + @objc var matrixHeight: NSNumber = 0 + @objc var tileWidth: NSNumber = 0 + @objc var tileHeight: NSNumber = 0 + @objc var pixelXSize: NSDecimalNumber = 0.0 + @objc var pixelYSize: NSDecimalNumber = 0.0 + +} diff --git a/mapcache-ios/data/GPKGSTileTable.h b/mapcache-ios/data/MCTileTable.h similarity index 66% rename from mapcache-ios/data/GPKGSTileTable.h rename to mapcache-ios/data/MCTileTable.h index 77af313..cbb1d5f 100644 --- a/mapcache-ios/data/GPKGSTileTable.h +++ b/mapcache-ios/data/MCTileTable.h @@ -6,13 +6,17 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSTable.h" +#import "MCTable.h" +#import +#import -@interface GPKGSTileTable : GPKGSTable +@interface MCTileTable : MCTable -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andCount: (int) count; -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andCount: (int) count andMinZoom: (int) minZoom andMaxZoom: (int) maxZoom; @property (nonatomic) int minZoom; @property (nonatomic) int maxZoom; +@property (nonatomic, strong) NSMutableArray *tileMatrices; +@property (nonatomic) CLLocationCoordinate2D center; @end diff --git a/mapcache-ios/data/GPKGSTileTable.m b/mapcache-ios/data/MCTileTable.m similarity index 81% rename from mapcache-ios/data/GPKGSTileTable.m rename to mapcache-ios/data/MCTileTable.m index a2ccc53..cf1a225 100644 --- a/mapcache-ios/data/GPKGSTileTable.m +++ b/mapcache-ios/data/MCTileTable.m @@ -6,17 +6,19 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSTileTable.h" +#import "MCTileTable.h" -@implementation GPKGSTileTable +@implementation MCTileTable -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andCount: (int) count{ self = [super initWithDatabase:database andName:name andCount:count]; + self.tileMatrices = [[NSMutableArray alloc] init]; return self; } -(instancetype) initWithDatabase: (NSString *) database andName: (NSString *) name andCount: (int) count andMinZoom: (int) minZoom andMaxZoom: (int) maxZoom { self = [super initWithDatabase:database andName:name andCount:count]; + self.tileMatrices = [[NSMutableArray alloc] init]; self.minZoom = minZoom; self.maxZoom = maxZoom; return self; diff --git a/mapcache-ios/drawer/NGADrawerCoordinator.h b/mapcache-ios/drawer/NGADrawerCoordinator.h index 1b961a9..905ec12 100644 --- a/mapcache-ios/drawer/NGADrawerCoordinator.h +++ b/mapcache-ios/drawer/NGADrawerCoordinator.h @@ -12,7 +12,7 @@ #import "MCGeoPackageListCoordinator.h" #import "MCMapCoordinator.h" - +@protocol MCMapDelegate; @interface NGADrawerCoordinator : NSObject - (instancetype) initWithBackgroundViewController:(UIViewController *) viewController andMCMapDelegate:(id) mcMapDelegate; - (void) start; diff --git a/mapcache-ios/drawer/NGADrawerCoordinator.m b/mapcache-ios/drawer/NGADrawerCoordinator.m index 8b4a9be..d643097 100644 --- a/mapcache-ios/drawer/NGADrawerCoordinator.m +++ b/mapcache-ios/drawer/NGADrawerCoordinator.m @@ -44,6 +44,10 @@ - (void) start { #pragma mark - NGADrawerViewDelegate methods +/** + Handle state once a drawer finishes it's animation. + This hides the drawers behind the top drawer so if you swipe the view down you see the map not the next drawer down in the stack. + */ - (void) drawerAddAnimationComplete: (NGADrawerViewController *) viewController { if (_drawerStack.count > 1) { NGADrawerViewController *currentTopDrawer = [_drawerStack objectAtIndex:_drawerStack.count -2]; @@ -53,6 +57,9 @@ - (void) drawerAddAnimationComplete: (NGADrawerViewController *) viewController } +/** + Add a new frawer to the stack. + */ - (void) pushDrawer:(NGADrawerViewController *) childViewController { if ([_drawerStack count] > 0) { NGADrawerViewController *drawer = [_drawerStack lastObject]; @@ -68,11 +75,15 @@ - (void) pushDrawer:(NGADrawerViewController *) childViewController { _width = self.backgroundViewController.view.frame.size.width; // The height of the screen minus the bit at the top where the map shows through - childViewController.view.frame = CGRectMake(0, CGRectGetMaxY(self.backgroundViewController.view.frame), _width, CGRectGetMaxY(self.backgroundViewController.view.frame) - 160); + int heightFromTop = [[MCProperties getNumberValueOfProperty:@"nga_drawer_view_space_from_top"] intValue]; + childViewController.view.frame = CGRectMake(0, CGRectGetMaxY(self.backgroundViewController.view.frame), _width, CGRectGetMaxY(self.backgroundViewController.view.frame) - heightFromTop); + [childViewController becameTopDrawer]; } - +/** + Remove the top drawer from the stack. + */ - (void) popDrawer { if ([_drawerStack count] > 1) { NGADrawerViewController *oldTopDrawer = [_drawerStack objectAtIndex:_drawerStack.count -1]; @@ -80,29 +91,51 @@ - (void) popDrawer { NGADrawerViewController *newTopDrawer = [_drawerStack objectAtIndex:_drawerStack.count -1]; [newTopDrawer makeFullView]; [newTopDrawer.view setHidden:NO]; + [newTopDrawer becameTopDrawer]; [oldTopDrawer removeDrawerFromSuperview]; } } +/** + Remove the top drawer from the stack and hide the new top drawer. + Used in cases where you need to see the whole map such as the new tile layer bounding box. + */ - (void) popDrawerAndHide { if ([_drawerStack count] > 1) { NGADrawerViewController *oldTopDrawer = [_drawerStack objectAtIndex:_drawerStack.count -1]; [_drawerStack removeLastObject]; NGADrawerViewController *newTopDrawer = [_drawerStack objectAtIndex:_drawerStack.count -1]; [newTopDrawer makeFullView]; + [newTopDrawer becameTopDrawer]; [newTopDrawer.view setHidden:YES]; [oldTopDrawer removeDrawerFromSuperview]; } } +/** + Set the top drawer to be visible and animate it to show it's full view. + */ - (void) showTopDrawer { if ([_drawerStack count] > 1) { NGADrawerViewController *topDrawer = [_drawerStack objectAtIndex:_drawerStack.count - 1]; [topDrawer makeFullView]; + [topDrawer becameTopDrawer]; [topDrawer.view setHidden:NO]; } } + +/** + Get the top drawer of the drawer stack. + */ +- (NGADrawerViewController *)topDrawer { + if (self.drawerStack.count > 0) { + return [self.drawerStack objectAtIndex:self.drawerStack.count -1]; + } + + return nil; +} + @end diff --git a/mapcache-ios/drawer/NGADrawerViewController.h b/mapcache-ios/drawer/NGADrawerViewController.h index 5f11530..cd8a218 100644 --- a/mapcache-ios/drawer/NGADrawerViewController.h +++ b/mapcache-ios/drawer/NGADrawerViewController.h @@ -1,5 +1,5 @@ // -// MCBottomDrawerViewController.h +// NGADrawerViewController.h // MapDrawer // // Created by Tyler Burgett on 8/20/18. @@ -7,6 +7,7 @@ // #import +#import "MCProperties.h" @protocol NGADrawerViewDelegate - (void) drawerAddAnimationComplete: (UIViewController *) viewController; @@ -16,6 +17,7 @@ - (void) showTopDrawer; @end + @interface NGADrawerViewController : UIViewController @property (nonatomic, strong) id drawerViewDelegate; @property (nonatomic) BOOL swipeEnabled; @@ -27,9 +29,14 @@ - (void) removeDrawerFromSuperview; - (void) addDragHandle; - (void) addCloseButton; +- (void) addAndConstrainSubview:(UIView *) view; - (void) closeDrawer; +- (void) drawerWasCollapsed; +- (void) drawerWasMadeFull; +- (void) becameTopDrawer; - (void) slideDown; -- (BOOL)gestureIsInConflict:(UIPanGestureRecognizer *) recognizer; +- (BOOL) gestureIsInConflict:(UIPanGestureRecognizer *) recognizer; - (void) panGesture:(UIPanGestureRecognizer *) recognizer; - (void) rollUpPanGesture:(UIPanGestureRecognizer *) recognizer withScrollView:(UIScrollView *) scrollView; +- (void) pushOntoStack; @end diff --git a/mapcache-ios/drawer/NGADrawerViewController.m b/mapcache-ios/drawer/NGADrawerViewController.m index e5faeb1..55f1374 100644 --- a/mapcache-ios/drawer/NGADrawerViewController.m +++ b/mapcache-ios/drawer/NGADrawerViewController.m @@ -28,8 +28,8 @@ - (instancetype) initAsFullView: (BOOL) isFullView { - (void)viewDidLoad { [super viewDidLoad]; - _openView = 160; - _collapsedView = [UIScreen mainScreen].bounds.size.height - 140; //120 + _openView = [[MCProperties getNumberValueOfProperty:@"nga_drawer_view_space_from_top"] intValue]; // 160 or 200? Check value in Coordinator pushDrawer + _collapsedView = [UIScreen mainScreen].bounds.size.height - 160; //120 // TODO: make this a property NSLog(@"Screen height: %f", [UIScreen mainScreen].bounds.size.height); _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)]; @@ -91,10 +91,12 @@ - (void) panGesture:(UIPanGestureRecognizer *) recognizer { [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ if (velocity.y >= 0) { self.view.frame = CGRectMake(0, self.collapsedView, self.view.frame.size.width, self.view.frame.size.height); - _isFullView = NO; + self.isFullView = NO; + [self drawerWasCollapsed]; } else { self.view.frame = CGRectMake(0, self.openView, self.view.frame.size.width, self.view.frame.size.height); - _isFullView = YES; + self.isFullView = YES; + [self drawerWasMadeFull]; } } completion:nil]; } @@ -102,6 +104,12 @@ - (void) panGesture:(UIPanGestureRecognizer *) recognizer { } +/** + Called from a child class that contains a scrollview or tableview when the delegate method scrollViewDidScroll is called. + This method checks the state of of the scrollview. If it is at the top and is dragged down, then the swipe event is handled + at the drawer causing it to collapse. Likewise if the drawer is collapsed and a swipe up is detected, rather than scroll the + view the drawer will be set to its full view. + */ - (void) rollUpPanGesture:(UIPanGestureRecognizer *) recognizer withScrollView:(UIScrollView *) scrollView { CGPoint velocity = [scrollView.panGestureRecognizer velocityInView:self.view]; CGFloat y = CGRectGetMinY(self.view.frame); @@ -109,6 +117,7 @@ - (void) rollUpPanGesture:(UIPanGestureRecognizer *) recognizer withScrollView:( duration = duration > 1.3 ? 0.65 : duration; if (scrollView.contentOffset.y < 0 && self.previousContentOffset == 0) { + self.previousContentOffset = scrollView.contentOffset.y; scrollView.scrollEnabled = NO; [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ if (velocity.y >= 0) { @@ -117,10 +126,12 @@ - (void) rollUpPanGesture:(UIPanGestureRecognizer *) recognizer withScrollView:( } completion:^(BOOL finished) { self.isFullView = NO; scrollView.scrollEnabled = YES; + [self drawerWasCollapsed]; }]; } else if (scrollView.contentOffset.y > 0 && !self.isFullView) { + self.previousContentOffset = scrollView.contentOffset.y; [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ if (velocity.y >= 0) { self.view.frame = CGRectMake(0, self.openView, self.view.frame.size.width, self.view.frame.size.height); @@ -128,6 +139,7 @@ - (void) rollUpPanGesture:(UIPanGestureRecognizer *) recognizer withScrollView:( } completion:^(BOOL finished) { scrollView.scrollEnabled = YES; self.isFullView = YES; + [self drawerWasMadeFull]; }]; } @@ -146,18 +158,22 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni } +/** + Deconflict gestures, useful for nesting a tableview in the drawer and gracefully handling the swipe events.. + */ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { - if ([otherGestureRecognizer.view isKindOfClass:UITableView.class]) { return true; } NSLog(@"Checking those recognizers"); - return false; } +/** + Make the drawer its full height, minus the offset at the top of the screen that allows the background view to be seen. + */ - (void) makeFullView { self.view.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height, self.view.frame.size.width, self.view.frame.size.height); self.view.alpha = 0; @@ -170,13 +186,18 @@ - (void) makeFullView { }]; self.isFullView = YES; + [self drawerWasMadeFull]; [_drawerViewDelegate drawerAddAnimationComplete:self]; } +/** + Collapse the drawer. + */ - (void) slideDown { [UIView animateWithDuration:0.3 animations:^{ self.view.frame = CGRectMake(0, self.collapsedView, self.view.frame.size.width, self.view.frame.size.height); + [self drawerWasCollapsed]; self.isFullView = NO; }]; } @@ -193,6 +214,9 @@ - (void) removeDrawerFromSuperview { } +/** + Add a drag handle to the top of the drawer. + */ - (void) addDragHandle { // Taking the width of the drag handle into account when adding it. UIImageView *dragHandle = [[UIImageView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - 36)/2, 8, 36, 4)]; @@ -203,6 +227,9 @@ - (void) addDragHandle { } +/** + Add a close button to the top right corner of the drawer. + */ - (void) addCloseButton { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button addTarget:self @@ -214,11 +241,46 @@ - (void) addCloseButton { } +- (void) pushOntoStack { + [self.drawerViewDelegate pushDrawer:self]; +} + + +/** + Called when the close button is pressed. Override in subclasses to perform any work needed before removing the drwer from the stack. + */ - (void) closeDrawer { NSLog(@"Close button tapped."); } +/** + Called when the drawer is collapesed. Override in children classes to manage the state of the components in the drawer. + */ +- (void) drawerWasCollapsed { + NSLog(@"Drawer collapsed"); +} + + +/** + Called when the drawer is swiped up. Override in children classes to manage the state of the components in the drawer. +*/ +- (void) drawerWasMadeFull { + NSLog(@"Drawer made full view"); +} + + +/** + Called when the drawer becomes the top drawer in the stack. Override in child classes to perform any setup or set state specific to becoming the top drawer. + */ +- (void) becameTopDrawer { + +} + + +/** + Round the top corners of the drawer. + */ - (void) roundViews { self.view.layer.cornerRadius = 5; self.view.clipsToBounds = YES; @@ -228,6 +290,27 @@ - (void) roundViews { } +- (void)addAndConstrainSubview:(UIView *) view { + [self.view addSubview:view]; + + NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:0]; + NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:0]; + NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:0]; + NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; + + + [[view.topAnchor constraintEqualToAnchor:self.view.topAnchor] setActive:YES]; + [[view.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] setActive:YES]; + [[view.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor] setActive:YES]; + [[view.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor] setActive:YES]; + view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; + + view.frame = self.view.frame; + + [self.view addConstraints:@[left, top, right, bottom]]; +} + + - (void) prepareBackgroundView { // iOS 13 dark mode support if ([UIColor respondsToSelector:@selector(systemBackgroundColor)]) { diff --git a/mapcache-ios/geopackage/MCCreateGeoPacakgeViewController.h b/mapcache-ios/geopackage/MCCreateGeoPacakgeViewController.h index 4178184..e3eef04 100644 --- a/mapcache-ios/geopackage/MCCreateGeoPacakgeViewController.h +++ b/mapcache-ios/geopackage/MCCreateGeoPacakgeViewController.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface MCCreateGeoPacakgeViewController : NGADrawerViewController +@interface MCCreateGeoPacakgeViewController : NGADrawerViewController @property (nonatomic, weak) id createGeoPackageDelegate; @end diff --git a/mapcache-ios/geopackage/MCDownloadCoordinator.h b/mapcache-ios/geopackage/MCDownloadCoordinator.h index 571a88e..da0136f 100644 --- a/mapcache-ios/geopackage/MCDownloadCoordinator.h +++ b/mapcache-ios/geopackage/MCDownloadCoordinator.h @@ -8,9 +8,9 @@ #import #import "MCDownloadGeopackage.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" @protocol GPKGSDownloadCoordinatorDelegate diff --git a/mapcache-ios/geopackage/MCDownloadCoordinator.m b/mapcache-ios/geopackage/MCDownloadCoordinator.m index 66d0521..b04c26d 100644 --- a/mapcache-ios/geopackage/MCDownloadCoordinator.m +++ b/mapcache-ios/geopackage/MCDownloadCoordinator.m @@ -45,8 +45,8 @@ - (void)downloadFileViewController:(MCDownloadGeopackage *)controller downloaded [_downloadDelegate downloadCoordinatorCompletitonHandler:YES]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_IMPORT_URL_ERROR] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_IMPORT_URL_ERROR] andMessage:[NSString stringWithFormat:@"There was a problem downloading '%@' from:\n%@\n\n%@", controller.nameTextField.text, controller.urlTextField.text, error]]; } } diff --git a/mapcache-ios/geopackage/MCGeoPackageCoordinator.h b/mapcache-ios/geopackage/MCGeoPackageCoordinator.h index b365058..9389d38 100644 --- a/mapcache-ios/geopackage/MCGeoPackageCoordinator.h +++ b/mapcache-ios/geopackage/MCGeoPackageCoordinator.h @@ -11,10 +11,10 @@ #import #import #import "SFPProjectionFactory.h" -#import "GPKGSLoadTilesTask.h" +#import "MCLoadTilesTask.h" #import "MCGeopackageSingleViewController.h" -#import "GPKGSDatabase.h" -#import "GPKGSDatabases.h" +#import "MCDatabase.h" +#import "MCDatabases.h" #import "GPKGSCreateTilesData.h" #import "GPKGSLoadTilesData.h" #import "GPKGSGenerateTilesData.h" @@ -24,22 +24,23 @@ #import "MCTileLayerDetailsViewController.h" #import "MCBoundingBoxGuideView.h" #import "MCZoomAndQualityViewController.h" -#import "MCLayerViewController.h" #import "GPKGSDisplayTextViewController.h" #import "MCFeatureLayerOperationsCell.h" -#import "MCLayerCoordinator.h" #import "MCMapCoordinator.h" #import "MCTileServerHelpViewController.h" #import "MCSettingsCoordinator.h" #import "MCTileServerURLManagerViewController.h" +#import "MCFeatureLayerDetailsViewController.h" +#import "MCGeoPackageRepository.h" @protocol MCMapDelegate; +@protocol MCLayerCoordinatorDelegate; @protocol MCGeoPackageCoordinatorDelegate - (void) geoPackageCoordinatorCompletionHandlerForDatabase:(NSString *) database withDelete:(BOOL)didDelete; @end -@interface MCGeoPackageCoordinator: NSObject -- (instancetype) initWithDelegate:(id)geoPackageCoordinatorDelegate andDrawerDelegate:(id) drawerDelegate andMapDelegate:(id) mapDelegate andDatabase:(GPKGSDatabase *) database; +@interface MCGeoPackageCoordinator: NSObject +- (instancetype) initWithDelegate:(id)geoPackageCoordinatorDelegate andDrawerDelegate:(id) drawerDelegate andMapDelegate:(id) mapDelegate andDatabase:(MCDatabase *) database; - (void) start; @end diff --git a/mapcache-ios/geopackage/MCGeoPackageCoordinator.m b/mapcache-ios/geopackage/MCGeoPackageCoordinator.m index 84c9588..39c4d44 100644 --- a/mapcache-ios/geopackage/MCGeoPackageCoordinator.m +++ b/mapcache-ios/geopackage/MCGeoPackageCoordinator.m @@ -7,6 +7,7 @@ // #import "MCGeoPackageCoordinator.h" +#import "mapcache_ios-Swift.h" @interface MCGeoPackageCoordinator() @@ -15,30 +16,32 @@ @interface MCGeoPackageCoordinator() @property (nonatomic, strong) id drawerDelegate; @property (nonatomic, strong) id mapDelegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) id drawerViewDelegate; @property (nonatomic, strong) MCFeatureLayerDetailsViewController *featureDetailsController; @property (nonatomic, strong) MCTileLayerDetailsViewController *tileDetailsController; @property (nonatomic, strong) MCBoundingBoxGuideView *boundingBoxGuideViewController; @property (nonatomic, strong) MCZoomAndQualityViewController *zoomAndQualityViewController; -@property (nonatomic, strong) GPKGSDatabases *active; -@property (nonatomic, strong) GPKGSDatabase *database; +@property (nonatomic, strong) MCFeatureLayerDetailsViewController *featureLayerDetailsView; +@property (nonatomic, strong) MCDatabases *active; +@property (nonatomic, strong) MCDatabase *database; @property (nonatomic, strong) GPKGSCreateTilesData * tileData; +@property (nonatomic, strong) MCGeoPackageRepository *repository; @property (nonatomic, strong) NSMutableArray *childCoordinators; @end @implementation MCGeoPackageCoordinator -- (instancetype) initWithDelegate:(id)geoPackageCoordinatorDelegate andDrawerDelegate:(id) drawerDelegate andMapDelegate:(id) mapDelegate andDatabase:(GPKGSDatabase *) database { +- (instancetype) initWithDelegate:(id)geoPackageCoordinatorDelegate andDrawerDelegate:(id) drawerDelegate andMapDelegate:(id) mapDelegate andDatabase:(MCDatabase *) database { self = [super init]; _childCoordinators = [[NSMutableArray alloc] init]; - _manager = [GPKGGeoPackageFactory getManager]; + _manager = [GPKGGeoPackageFactory manager]; + _repository = [MCGeoPackageRepository sharedRepository]; _geoPackageCoordinatorDelegate = geoPackageCoordinatorDelegate; _drawerDelegate = drawerDelegate; _mapDelegate = mapDelegate; _database = database; - _active = [GPKGSDatabases getInstance]; + _active = [MCDatabases getInstance]; return self; } @@ -51,21 +54,20 @@ - (void) start { _geoPackageViewController.delegate = self; _geoPackageViewController.drawerViewDelegate = _drawerDelegate; [_drawerDelegate pushDrawer:_geoPackageViewController]; - - //[_navigationController pushViewController:_geoPackageViewController animated:YES]; // TODO replace with drawer + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateAndReload:) name:MC_GEOPACKAGE_MODIFIED_NOTIFICATION object:nil]; +} + + +- (void)updateAndReload:(NSNotification *) notification { + _database = [_repository refreshDatabaseAndUpdateList:_database.name]; + _geoPackageViewController.database = _database; + [_geoPackageViewController update]; } #pragma mark - GeoPackage View delegate methods -- (void) newLayer { +- (void) newTileLayer { NSLog(@"Coordinator handling new layer"); - - // Future release will bring feature and tile layers, for now starting with just the tiles. -// MCCreateLayerViewController *createLayerViewControler = [[MCCreateLayerViewController alloc] initWithNibName:@"MCCreateLayerView" bundle:nil]; -// createLayerViewControler.delegate = self; -// createLayerViewControler.drawerViewDelegate = _drawerDelegate; -// [createLayerViewControler.drawerViewDelegate pushDrawer:createLayerViewControler]; - NSLog(@"Adding new tile layer"); _tileData = [[GPKGSCreateTilesData alloc] init]; _tileDetailsController = [[MCTileLayerDetailsViewController alloc] initAsFullView:YES]; @@ -75,72 +77,30 @@ - (void) newLayer { } +- (void) newFeatureLayer { + _featureLayerDetailsView = [[MCFeatureLayerDetailsViewController alloc] initAsFullView:YES]; + _featureLayerDetailsView.delegate = self; + _featureLayerDetailsView.drawerViewDelegate = _drawerDelegate; + _featureLayerDetailsView.database = self.database; + [_featureLayerDetailsView pushOntoStack]; +} + + - (void) updateDatabase { - GPKGGeoPackage *geoPackage = nil; - GPKGSDatabase *updatedDatabase = nil; - - @try { - geoPackage = [_manager open:_database.name]; - - GPKGContentsDao *contentsDao = [geoPackage getContentsDao]; - NSMutableArray *tables = [[NSMutableArray alloc] init]; - - updatedDatabase = [[GPKGSDatabase alloc] initWithName:_database.name andExpanded:false]; - - // Handle the Feature Layers - for (NSString *tableName in [geoPackage getFeatureTables]) { - GPKGFeatureDao *featureDao = [geoPackage getFeatureDaoWithTableName:tableName]; - int count = [featureDao count]; - GPKGContents *contents = (GPKGContents *)[contentsDao queryForIdObject:tableName]; - GPKGGeometryColumns *geometryColumns = [contentsDao getGeometryColumns:contents]; - enum SFGeometryType geometryType = [SFGeometryTypes fromName:geometryColumns.geometryTypeName]; - GPKGSFeatureTable *table = [[GPKGSFeatureTable alloc] initWithDatabase:_database.name andName:tableName andGeometryType:geometryType andCount:count]; - - [tables addObject:table]; - [updatedDatabase addFeature:table]; - } - - // Handle the tile layers - for (NSString *tableName in [geoPackage getTileTables]) { - GPKGTileDao *tileDao = [geoPackage getTileDaoWithTableName:tableName]; - int count = [tileDao count]; - - GPKGSTileTable *table = [[GPKGSTileTable alloc] initWithDatabase:_database.name andName:tableName andCount:count andMinZoom:tileDao.minZoom andMaxZoom:tileDao.maxZoom]; - - [tables addObject:table]; - [updatedDatabase addTile:table]; - } - - // TODO: Figure out what to do about overlays - } - @finally { - if (geoPackage == nil) { - @try { - [_manager delete:_database.name]; - } - @catch (NSException *exception) { - } - } else { - if (updatedDatabase != nil) { - _database = updatedDatabase; - _geoPackageViewController.database = _database; - [_geoPackageViewController update]; - } - [geoPackage close]; - } - } + _database = [_repository refreshDatabaseAndUpdateList:self.database.name]; + self.geoPackageViewController.database = _database; + [self.geoPackageViewController update]; } - (void) copyGeoPackage { - //[_navigationController popViewControllerAnimated:YES]; // TODO replace with drawer [_geoPackageCoordinatorDelegate geoPackageCoordinatorCompletionHandlerForDatabase:_database.name withDelete:NO]; } - (void) deleteGeoPackage { NSLog(@"Coordinator handling delete"); - //[_navigationController popViewControllerAnimated:YES]; // TODO replace with drawer + self.geoPackageViewController = nil; [_geoPackageCoordinatorDelegate geoPackageCoordinatorCompletionHandlerForDatabase:_database.name withDelete:YES]; } @@ -148,10 +108,11 @@ - (void) deleteGeoPackage { - (void) callCompletionHandler { NSLog(@"Close pressed"); [_geoPackageCoordinatorDelegate geoPackageCoordinatorCompletionHandlerForDatabase:_database.name withDelete:NO]; + [_repository setSelectedGeoPackageName:@""]; } -- (void) deleteLayer:(GPKGSTable *) table { +- (void) deleteLayer:(MCTable *) table { GPKGGeoPackage *geoPackage = nil; @try { @@ -162,8 +123,8 @@ - (void) deleteLayer:(GPKGSTable *) table { [_mapDelegate updateMapLayers]; } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[NSString stringWithFormat:@"%@ %@ - %@ Table", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL], _database.name, table.name] + [MCUtils showMessageWithDelegate:self + andTitle:[NSString stringWithFormat:@"%@ %@ - %@ Table", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL], _database.name, table.name] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } @finally { @@ -172,11 +133,11 @@ - (void) deleteLayer:(GPKGSTable *) table { } -- (void) toggleLayer:(GPKGSTable *) table; { +- (void) toggleLayer:(MCTable *) table; { if ([_database exists:table]) { if ([_active isActive:_database]) { - GPKGSDatabase *activeDatabase = [_active getDatabaseWithName:_database.name]; + MCDatabase *activeDatabase = [_active getDatabaseWithName:_database.name]; if ([activeDatabase existsWithTable:table.name ofType:table.getType]) { [_active removeTable:table]; } else { @@ -191,52 +152,53 @@ - (void) toggleLayer:(GPKGSTable *) table; { } -- (void) showLayerDetails:(GPKGUserDao *) layerDao { - NSLog(@"In showLayerDetails with %@", layerDao.tableName); - // TODO: Update to show the layerDetailsView in a drawer +- (void) showLayerDetails:(MCTable *) table { + NSLog(@"In showLayerDetails with %@", table.name); + + if ([table isKindOfClass:MCTileTable.class]) { + MCTileTable *tileTable = (MCTileTable *)table; + NSUInteger zoomLevel = tileTable.maxZoom; + [_mapDelegate zoomToPoint:tileTable.center withZoomLevel:zoomLevel]; + } else if ([table isKindOfClass:MCFeatureTable.class]) { + _repository.selectedLayerName = table.name; + } + + MCLayerCoordinator *layerCoordinator = [[MCLayerCoordinator alloc] initWithTable:table drawerDelegate:self.drawerDelegate layerCoordinatorDelegate:self]; + [self.childCoordinators addObject:layerCoordinator]; + + [layerCoordinator start]; } -#pragma mark - CreateLayerViewController delegate methods -- (void) newFeatureLayer { - NSLog(@"Adding new feature layer"); - _featureDetailsController = [[MCFeatureLayerDetailsViewController alloc] init]; - _featureDetailsController.database = _database; - _featureDetailsController.delegate = self; - //[_navigationController pushViewController:_featureDetailsController animated:YES]; // TODO replace with drawer +- (void) setSelectedDatabaseName { + [self.repository setSelectedGeoPackageName:self.database.name]; } -// Temporarily moving this to new layer since initially they can only make tile layers. -- (void) newTileLayer { - NSLog(@"Adding new tile layer"); - _tileData = [[GPKGSCreateTilesData alloc] init]; - _tileDetailsController = [[MCTileLayerDetailsViewController alloc] init]; - _tileDetailsController.delegate = self; - _tileDetailsController.drawerViewDelegate = _drawerDelegate; - // [_navigationController pushViewController:_tileDetailsController animated:YES]; // TODO replace with drawer +#pragma mark - MCFeatureLayerCreationDelegate methods +/** + Add a new feature layer to the GeoPackage. + */ +- (void) createFeatueLayerIn:(NSString *)database withGeomertyColumns:(GPKGGeometryColumns *)geometryColumns andBoundingBox:(GPKGBoundingBox *)boundingBox andSrsId:(NSNumber *) srsId { + NSLog(@"creating layer %@ in database %@ ", geometryColumns.tableName, database); + + BOOL didCreateLayer = [_repository createFeatueLayerIn:database withGeomertyColumns:geometryColumns boundingBox:boundingBox srsId:srsId]; + if (didCreateLayer) { + [_drawerDelegate popDrawer]; + _geoPackageViewController.database = [_repository refreshDatabaseAndUpdateList:_database.name]; + [_geoPackageViewController update]; + } else { + //TODO handle the case where a new feature layer could not be created + } } -#pragma mark - GPKGSFeatureLayerCreationDelegate -- (void) createFeatueLayerIn:(NSString *)database with:(GPKGGeometryColumns *)geometryColumns andBoundingBox:(GPKGBoundingBox *)boundingBox andSrsId:(NSNumber *) srsId { - - GPKGGeoPackage * geoPackage; - @try { - geoPackage = [_manager open:database]; - [geoPackage createFeatureTableWithGeometryColumns:geometryColumns andBoundingBox:boundingBox andSrsId:srsId]; - } - @catch (NSException *e) { - // TODO handle this - NSLog(@"There was a problem creating the layer, %@", e.reason); - } - @finally { - [geoPackage close]; - //[_navigationController popToViewController:_geoPackageViewController animated:YES]; // TODO replace with drawer - [self updateDatabase]; - } - - // TODO handle dismissing the view controllers or displaying an error message +#pragma mark - MCLayerCoordinatorDelegate methods +- (void) layerCoordinatorCompletionHandler { + // TODO update the geopackage view to reflect any changes + _geoPackageViewController.database = [_repository databaseNamed:_database.name]; + [_geoPackageViewController update]; + [self.childCoordinators removeAllObjects]; } @@ -259,7 +221,7 @@ - (void) tileLayerDetailsCompletionHandlerWithName:(NSString *)name URL:(NSStrin [_drawerDelegate popDrawerAndHide]; self.boundingBoxGuideViewController = [[MCBoundingBoxGuideView alloc] init]; self.boundingBoxGuideViewController.delegate = self; - [_mapDelegate setupTileBoundingBoxGuide: self.boundingBoxGuideViewController.view]; + [_mapDelegate setupTileBoundingBoxGuide: self.boundingBoxGuideViewController.view tileUrl:url]; } @@ -280,7 +242,7 @@ - (void) showTileServerList { - (BOOL) isLayerNameAvailable: (NSString *) layerName { - for (GPKGSTable *table in [_database getTables]) { + for (MCTable *table in [_database getTables]) { if ([layerName isEqualToString:table.name]){ return NO; } @@ -340,7 +302,7 @@ - (void) goBackToBoundingBox { [_drawerDelegate popDrawerAndHide]; self.boundingBoxGuideViewController = [[MCBoundingBoxGuideView alloc] init]; self.boundingBoxGuideViewController.delegate = self; - [_mapDelegate setupTileBoundingBoxGuide: self.boundingBoxGuideViewController.view]; + [_mapDelegate setupTileBoundingBoxGuide: self.boundingBoxGuideViewController.view tileUrl:_tileData.loadTiles.url]; } - (NSString *) updateTileDownloadSizeEstimateWith:(NSNumber *) minZoom andMaxZoom:(NSNumber *) maxZoom { @@ -357,7 +319,7 @@ - (NSString *) updateTileDownloadSizeEstimateWith:(NSNumber *) minZoom andMaxZoo } for (int zoom = [minZoom intValue]; zoom <= [maxZoom intValue]; zoom++) { - GPKGTileGrid *tileGrid = [GPKGTileBoundingBoxUtils getTileGridWithWebMercatorBoundingBox:transformedBox andZoom:zoom]; + GPKGTileGrid *tileGrid = [GPKGTileBoundingBoxUtils tileGridWithWebMercatorBoundingBox:transformedBox andZoom:zoom]; count += [tileGrid count]; } @@ -365,9 +327,6 @@ - (NSString *) updateTileDownloadSizeEstimateWith:(NSNumber *) minZoom andMaxZoo } - - - - (void) cancelZoomAndQuality { [self.mapDelegate updateMapLayers]; [self updateDatabase]; @@ -377,24 +336,28 @@ - (void) cancelZoomAndQuality { #pragma mark - MCNewLayerWizardDelegate methods - (void) createTileLayer:(GPKGSCreateTilesData *) tileData { NSLog(@"Coordinator attempting to create tiles"); - GPKGTileScaling *scaling = [GPKGSLoadTilesTask tileScaling]; + GPKGTileScaling *scaling = [MCLoadTilesTask tileScaling]; + + @try { + [MCLoadTilesTask loadTilesWithCallback:self + andDatabase:_database.name + andTable:tileData.name + andUrl:tileData.loadTiles.url + andMinZoom:[tileData.loadTiles.generateTiles.minZoom intValue] + andMaxZoom:[tileData.loadTiles.generateTiles.maxZoom intValue] + andCompressFormat:GPKG_CF_NONE // TODO: let user set this + andCompressQuality:[[MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_COMPRESS_QUALITY_DEFAULT] intValue] + andCompressScale:100 // TODO: let user set this + andXyzTiles:tileData.loadTiles.generateTiles.xyzTiles + andBoundingBox:tileData.loadTiles.generateTiles.boundingBox + andTileScaling:scaling + andAuthority:PROJ_AUTHORITY_EPSG + andCode:[NSString stringWithFormat:@"%d",tileData.loadTiles.epsg] + andLabel:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL]]; + } @catch(NSException *e) { + NSLog(@"MCGeoPacakgeCoordinator - createTileLayer\n%@", e.reason); + } - [GPKGSLoadTilesTask loadTilesWithCallback:self - andDatabase:_database.name - andTable:tileData.name - andUrl:tileData.loadTiles.url - andMinZoom:[tileData.loadTiles.generateTiles.minZoom intValue] - andMaxZoom:[tileData.loadTiles.generateTiles.maxZoom intValue] - andCompressFormat:GPKG_CF_NONE // TODO: let user set this - andCompressQuality:[[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_COMPRESS_QUALITY_DEFAULT] intValue] - andCompressScale:100 // TODO: let user set this - andStandardFormat:tileData.loadTiles.generateTiles.standardWebMercatorFormat - andBoundingBox:tileData.loadTiles.generateTiles.boundingBox - andTileScaling:scaling - andAuthority:PROJ_AUTHORITY_EPSG - andCode:[NSString stringWithFormat:@"%d",tileData.loadTiles.epsg] - andLabel:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL]]; - } diff --git a/mapcache-ios/geopackage/MCGeoPackageList.h b/mapcache-ios/geopackage/MCGeoPackageList.h index 08f5a01..4ab9529 100644 --- a/mapcache-ios/geopackage/MCGeoPackageList.h +++ b/mapcache-ios/geopackage/MCGeoPackageList.h @@ -12,15 +12,16 @@ #import "MCTutorialCell.h" #import "NGADrawerViewController.h" #import "GPKGGeoPackageFactory.h" -#import "GPKGSDatabase.h" -#import "GPKGSDatabases.h" +#import "MCDatabase.h" +#import "MCDatabases.h" +#import "MCColorUtil.h" @protocol MCGeoPacakageListViewDelegate -- (void) didSelectGeoPackage: (GPKGSDatabase*) database; +- (void) didSelectGeoPackage: (MCDatabase*) database; - (void) downloadGeopackageWithExample:(BOOL) prefillExample; -- (void) toggleActive:(GPKGSDatabase *) database; -- (void) deleteGeoPackage:(GPKGSDatabase *) database; +- (void) toggleActive:(MCDatabase *) database; +- (void) deleteGeoPackage:(MCDatabase *) database; - (void) showNewGeoPackageView; @end @@ -29,6 +30,8 @@ - (instancetype) initWithGeoPackages: (NSMutableArray *) geoPackages asFullView: (BOOL) fullView andDelegate:(id) delegate; @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (strong, nonatomic) NSMutableArray *geoPackages; +@property (weak, nonatomic) IBOutlet UIButton *downloadButton; +@property (weak, nonatomic) IBOutlet UIButton *createButton; - (void)toggleGeoPacakge:(NSIndexPath *) indexPath; diff --git a/mapcache-ios/geopackage/MCGeoPackageList.m b/mapcache-ios/geopackage/MCGeoPackageList.m index 629ec4b..b422e5c 100644 --- a/mapcache-ios/geopackage/MCGeoPackageList.m +++ b/mapcache-ios/geopackage/MCGeoPackageList.m @@ -10,7 +10,7 @@ @interface MCGeoPackageList() @property (strong, nonatomic) NSMutableArray *childCoordinators; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @property (nonatomic) BOOL haveScrolled; @end @@ -21,7 +21,7 @@ - (instancetype) initWithGeoPackages: (NSMutableArray *) geoPackages asFullView: self = [super initAsFullView:fullView]; _geoPackages = geoPackages; _geopackageListViewDelegate = delegate; - _active = [GPKGSDatabases getInstance]; + _active = [MCDatabases getInstance]; return self; } @@ -38,6 +38,8 @@ - (void)viewDidLoad { [self.tableView registerNib:[UINib nibWithNibName:@"MCGeoPackageCell" bundle:nil] forCellReuseIdentifier:@"geopackage"]; [self.tableView registerNib:[UINib nibWithNibName:@"MCEmptyStateCell" bundle:nil] forCellReuseIdentifier:@"emptyState"]; [self.tableView registerNib:[UINib nibWithNibName:@"MCTutorialCell" bundle:nil] forCellReuseIdentifier:@"tutorialCell"]; + self.downloadButton.backgroundColor = [MCColorUtil getAccent]; + self.createButton.backgroundColor = [MCColorUtil getAccent]; // iOS 13 dark mode support if ([UIColor respondsToSelector:@selector(systemBackgroundColor)]) { @@ -96,27 +98,6 @@ - (void) updateAndReloadData { - (IBAction)createGeoPackage:(id)sender { [self.geopackageListViewDelegate showNewGeoPackageView]; - - /*UIAlertController *newGeoPackageAlert = [UIAlertController alertControllerWithTitle:@"New GeoPackage" message:@"" preferredStyle:UIAlertControllerStyleAlert]; - [newGeoPackageAlert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { - textField.text = @""; - }]; - - UIAlertAction *confirmCreate = [UIAlertAction actionWithTitle:@"Create" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - NSLog(@"Name: %@", newGeoPackageAlert.textFields[0].text); - - NSString * newName = newGeoPackageAlert.textFields[0].text; - [self.geopackageListViewDelegate createGeoPackage:newName]; - }]; - - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { - [newGeoPackageAlert dismissViewControllerAnimated:YES completion:nil]; - }]; - - [newGeoPackageAlert addAction:confirmCreate]; - [newGeoPackageAlert addAction:cancel]; - - [self presentViewController:newGeoPackageAlert animated:YES completion:nil];*/ } @@ -157,21 +138,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell = [[MCGeoPackageCell alloc] init]; } - GPKGSDatabase *database = [_geoPackages objectAtIndex:indexPath.row]; - - cell.geoPackageNameLabel.text = database.name; - - if ([database getFeatures].count == 1) { - cell.featureLayerDetailsLabel.text = [NSString stringWithFormat:@"%ld Feature layer", (long)[database getFeatures].count]; - } else { - cell.featureLayerDetailsLabel.text = [NSString stringWithFormat:@"%ld Feature layers", (long)[database getFeatures].count]; - } - - if ([database getTileCount] == 1) { - cell.tileLayerDetailsLabel.text = [NSString stringWithFormat:@"%ld Tile layer", (long)[database getTileCount]]; - } else { - cell.tileLayerDetailsLabel.text = [NSString stringWithFormat:@"%ld Tile layers", (long)[database getTileCount]]; - } + MCDatabase *database = [_geoPackages objectAtIndex:indexPath.row]; + [cell setContentWithDatabase:database]; if ([_active isActive:database]) { [cell activeLayersIndicatorOn]; @@ -212,7 +180,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } else if([cell isKindOfClass:[MCTutorialCell class]]){ return; } else { - GPKGSDatabase *selectedGeoPackage = [_geoPackages objectAtIndex:indexPath.row]; + MCDatabase *selectedGeoPackage = [_geoPackages objectAtIndex:indexPath.row]; NSLog(@"didSelectRowAtIndexPath for %@", selectedGeoPackage.name); [_geopackageListViewDelegate didSelectGeoPackage:selectedGeoPackage]; } @@ -259,7 +227,20 @@ - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwip } UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"Delete" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { - [self deleteGeoPackageAtIndexPath:indexPath]; + + UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you want to delete this GeoPackage? This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [self deleteGeoPackageAtIndexPath:indexPath]; + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [deleteAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [deleteAlert addAction:confirmDelete]; + [deleteAlert addAction:cancel]; + [self presentViewController:deleteAlert animated:YES completion:nil]; + completionHandler(YES); }]; delete.backgroundColor = [UIColor redColor]; diff --git a/mapcache-ios/geopackage/MCGeoPackageListCoordinator.h b/mapcache-ios/geopackage/MCGeoPackageListCoordinator.h index 6e60bdc..34e3900 100644 --- a/mapcache-ios/geopackage/MCGeoPackageListCoordinator.h +++ b/mapcache-ios/geopackage/MCGeoPackageListCoordinator.h @@ -8,19 +8,20 @@ #import #import -#import "GPKGSDatabase.h" +#import "MCDatabase.h" #import "MCGeoPackageCoordinator.h" #import "MCGeoPackageList.h" -#import "GPKGSFeatureOverlayTable.h" +#import "MCFeatureOverlayTable.h" #import "MCGeopackageSingleViewController.h" #import "MCGeoPackageCoordinator.h" -#import "GPKGSDatabases.h" +#import "MCDatabases.h" #import "MCDownloadCoordinator.h" -#import "GPKGSTable.h" +#import "MCTable.h" #import "MCMapCoordinator.h" -#import "GPKGSConstants.h" +#import "MCConstants.h" #import "GPKGGeoPackageCache.h" #import "MCCreateGeoPacakgeViewController.h" +#import "MCGeoPackageRepository.h" @protocol MCMapDelegate; diff --git a/mapcache-ios/geopackage/MCGeoPackageListCoordinator.m b/mapcache-ios/geopackage/MCGeoPackageListCoordinator.m index f53c555..c131dc3 100644 --- a/mapcache-ios/geopackage/MCGeoPackageListCoordinator.m +++ b/mapcache-ios/geopackage/MCGeoPackageListCoordinator.m @@ -14,9 +14,10 @@ @interface MCGeoPackageListCoordinator() @property (nonatomic, strong) MCGeoPackageCoordinator *geoPackageCoordinator; @property (nonatomic, strong) MCGeoPackageList *geoPackageListView; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @property (nonatomic, strong) NSMutableArray *databases; @property (nonatomic, strong) GPKGGeoPackageCache *geoPacakageCache; +@property (nonatomic, strong) MCGeoPackageRepository *repository; @end @@ -27,102 +28,39 @@ - (instancetype) init { _childCoordinators = [[NSMutableArray alloc] init]; _databases = [[NSMutableArray alloc] init]; - _manager = [GPKGGeoPackageFactory getManager]; + _manager = [GPKGGeoPackageFactory manager]; + _repository = [MCGeoPackageRepository sharedRepository]; _geoPacakageCache = [[GPKGGeoPackageCache alloc] initWithManager:_manager]; - self.active = [GPKGSDatabases getInstance]; + self.active = [MCDatabases getInstance]; return self; } - (void) start { - [self update]; + _databases = [_repository regenerateDatabaseList]; _geoPackageListView = [[MCGeoPackageList alloc] initWithGeoPackages:_databases asFullView:YES andDelegate:self]; _geoPackageListView.drawerViewDelegate = _drawerViewDelegate; [_geoPackageListView.drawerViewDelegate pushDrawer:_geoPackageListView]; - //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(boundingBoxDrawn:) name:@"boundingBoxResults" object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(geoPackageImported:) name:GPKGS_IMPORT_GEOPACKAGE_NOTIFICATION object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(regenerateAndReload:) name:GPKGS_IMPORT_GEOPACKAGE_NOTIFICATION object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(regenerateAndReload:) name:MC_GEOPACKAGE_MODIFIED_NOTIFICATION object:nil]; } -// TODO make a call to the list view controller to update with the new geopackages, maybe as an array -- (void) update { - self.databases = [[NSMutableArray alloc] init]; - NSArray *databaseNames = [self.manager databases]; - - for(NSString * databaseName in databaseNames){ - GPKGGeoPackage * geoPackage = nil; - @try { - geoPackage = [self.manager open:databaseName]; - - GPKGSDatabase * theDatabase = [[GPKGSDatabase alloc] initWithName:databaseName andExpanded:NO]; - [self.databases addObject:theDatabase]; - NSMutableArray * tables = [[NSMutableArray alloc] init]; - - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; - for(NSString * tableName in [geoPackage getFeatureTables]){ - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:tableName]; - int count = [featureDao count]; - - GPKGContents * contents = (GPKGContents *)[contentsDao queryForIdObject:tableName]; - GPKGGeometryColumns * geometryColumns = [contentsDao getGeometryColumns:contents]; - enum SFGeometryType geometryType = [SFGeometryTypes fromName:geometryColumns.geometryTypeName]; - - GPKGSFeatureTable * table = [[GPKGSFeatureTable alloc] initWithDatabase:databaseName andName:tableName andGeometryType:geometryType andCount:count]; - - [tables addObject:table]; - [theDatabase addFeature:table]; - } - - for(NSString * tableName in [geoPackage getTileTables]){ - GPKGTileDao * tileDao = [geoPackage getTileDaoWithTableName: tableName]; - int count = [tileDao count]; - GPKGSTileTable * table = [[GPKGSTileTable alloc] initWithDatabase:databaseName andName:tableName andCount:count andMinZoom:tileDao.minZoom andMaxZoom:tileDao.maxZoom]; - [table setActive: [self.active exists:table]]; - - [tables addObject:table]; - [theDatabase addTile:table]; - } - - for(GPKGSFeatureOverlayTable * table in [self.active featureOverlays:databaseName]){ - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:table.featureTable]; - int count = [featureDao count]; - [table setCount:count]; - - [tables addObject:table]; - [theDatabase addFeatureOverlay:table]; - } - } - @finally { - if(geoPackage == nil){ - @try { - [self.manager delete:geoPackage.name]; - } - @catch (NSException *exception) { - NSLog(@"Caught Exception trying to delete %@", exception.reason); - } - }else{ - [geoPackage close]; - } - } - } -} - - -- (void)geoPackageImported:(NSNotification *) notification { - [self update]; - _geoPackageListView.geoPackages = _databases; +- (void)regenerateAndReload:(NSNotification *) notification { + [_repository regenerateDatabaseList]; + _geoPackageListView.geoPackages = [_repository databaseList]; [_geoPackageListView.tableView reloadData]; } #pragma mark - MCGeoPackageListViewDelegate method --(void) didSelectGeoPackage:(GPKGSDatabase *)database { +-(void) didSelectGeoPackage:(MCDatabase *)database { _geoPackageCoordinator = [[MCGeoPackageCoordinator alloc] initWithDelegate:self andDrawerDelegate:_drawerViewDelegate andMapDelegate:self.mcMapDelegate andDatabase:database]; [_childCoordinators addObject:_geoPackageCoordinator]; [_geoPackageCoordinator start]; - // TODO: make a call here to move the map to where the data is, and maybe switch on the layers + _repository.selectedGeoPackageName = database.name; [self.mcMapDelegate zoomToSelectedGeoPackage:database.name]; } @@ -141,13 +79,13 @@ - (void) showNewGeoPackageView { } --(void) toggleActive:(GPKGSDatabase *)database { +-(void) toggleActive:(MCDatabase *)database { NSLog(@"Toggling layers for GeoPackage: %@", database.name); BOOL switchOn = ![_active isActive:database]; NSArray *tables = [database getTables]; - for (GPKGSTable *table in tables) { + for (MCTable *table in tables) { if (switchOn){ [_active addTable:table]; } else { @@ -155,8 +93,8 @@ -(void) toggleActive:(GPKGSDatabase *)database { } } - if (!switchOn && [_geoPacakageCache has:database.name]) { - [_geoPacakageCache close:database.name]; + if (!switchOn && [_geoPacakageCache hasName:database.name]) { + [_geoPacakageCache closeByName:database.name]; } // make the call to the map view to update the view @@ -164,8 +102,8 @@ -(void) toggleActive:(GPKGSDatabase *)database { } -- (void)deleteGeoPackage:(GPKGSDatabase *)database { - [self.manager delete:database.name]; +- (void)deleteGeoPackage:(MCDatabase *)database { + [_repository deleteGeoPackage:database]; [self.active removeDatabase:database.name andPreserveOverlays:NO]; [_databases removeObjectIdenticalTo:database]; @@ -195,7 +133,7 @@ -(BOOL) isValidGeoPackageName:(NSString *)name { - (void) createGeoPackage:(NSString *) geoPackageName { NSLog(@"Creating GeoPackage %@", geoPackageName); [_manager create:geoPackageName]; - [self update]; + _databases = [_repository regenerateDatabaseList]; [_geoPackageListView refreshWithGeoPackages:_databases]; } @@ -203,7 +141,7 @@ - (void) createGeoPackage:(NSString *) geoPackageName { #pragma mark - DownloadCoordinatorDelegate - (void) downloadCoordinatorCompletitonHandler:(bool) didDownload { NSLog(@"Downloaded geopakcage"); - [self update]; + _databases = [_repository regenerateDatabaseList]; [_geoPackageListView refreshWithGeoPackages:_databases]; [_childCoordinators removeLastObject]; } @@ -211,13 +149,15 @@ - (void) downloadCoordinatorCompletitonHandler:(bool) didDownload { #pragma mark - MCGeoPackageCoordinatorDelegate method - (void) geoPackageCoordinatorCompletionHandlerForDatabase:(NSString *) database withDelete:(BOOL)didDelete { + _repository.selectedGeoPackageName = @""; + [_childCoordinators removeAllObjects]; + if (didDelete) { - [self.manager delete:database]; + [self deleteGeoPackage:[_repository databaseNamed:database]]; + } else { + _databases = [_repository regenerateDatabaseList]; + [self.geoPackageListView refreshWithGeoPackages:_databases]; } - - [self update]; - self.geoPackageListView.geoPackages = self.databases; - [self.geoPackageListView.tableView reloadData]; } diff --git a/mapcache-ios/geopackage/MCGeopackageSingleViewController.h b/mapcache-ios/geopackage/MCGeopackageSingleViewController.h index a237e6c..15f4850 100644 --- a/mapcache-ios/geopackage/MCGeopackageSingleViewController.h +++ b/mapcache-ios/geopackage/MCGeopackageSingleViewController.h @@ -7,38 +7,40 @@ // #import -#import "GPKGSTable.h" -#import "GPKGSFeatureTable.h" -#import "GPKGSTileTable.h" -#import "GPKGSDatabase.h" -#import "GPKGSDatabases.h" +#import "MCTable.h" +#import "MCFeatureTable.h" +#import "MCTileTable.h" +#import "MCDatabase.h" +#import "MCDatabases.h" #import "MCHeaderCell.h" #import "MCSectionTitleCell.h" #import "MCLayerCell.h" #import "MCButtonCell.h" -#import "GPKGSConstants.h" -#import "GPKGSProperties.h" +#import "MCConstants.h" +#import "MCProperties.h" #import "MCGeoPackageOperationsCell.h" #import #import -#import "GPKGSUtils.h" +#import "MCUtils.h" #import "NGADrawerViewController.h" @protocol MCOperationsDelegate -- (void) newLayer; +- (void) newTileLayer; +- (void) newFeatureLayer; - (void) deleteGeoPackage; - (void) copyGeoPackage; - (void) callCompletionHandler; -- (void) deleteLayer:(GPKGSTable *) table; -- (void) showLayerDetails:(GPKGUserDao *) layerDao; -- (void) toggleLayer:(GPKGSTable *) table; +- (void) deleteLayer:(MCTable *) table; +- (void) showLayerDetails:(MCTable *) table; +- (void) toggleLayer:(MCTable *) table; - (void) updateDatabase; +- (void) setSelectedDatabaseName; @end -@interface MCGeopackageSingleViewController : NGADrawerViewController -@property (strong, nonatomic) GPKGSDatabase *database; +@interface MCGeopackageSingleViewController : NGADrawerViewController +@property (strong, nonatomic) MCDatabase *database; @property (weak, nonatomic) id delegate; - (void) update; - (void) removeLayerNamed:(NSString *) layerName; diff --git a/mapcache-ios/geopackage/MCGeopackageSingleViewController.m b/mapcache-ios/geopackage/MCGeopackageSingleViewController.m index 3cffdb3..de9f06a 100644 --- a/mapcache-ios/geopackage/MCGeopackageSingleViewController.m +++ b/mapcache-ios/geopackage/MCGeopackageSingleViewController.m @@ -13,39 +13,44 @@ @interface MCGeopackageSingleViewController () @property (nonatomic, strong) GPKGGeoPackageManager *manager; @property (nonatomic, strong) UITableView *tableView; @property (nonatomic, strong) UIDocumentInteractionController *shareDocumentController; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @property (nonatomic) BOOL haveScrolled; +@property (nonatomic) CGFloat contentOffset; @end @implementation MCGeopackageSingleViewController - (void) viewDidLoad { [super viewDidLoad]; - self.manager = [GPKGGeoPackageFactory getManager]; - self.active = [GPKGSDatabases getInstance]; + self.manager = [GPKGGeoPackageFactory manager]; + self.active = [MCDatabases getInstance]; CGRect bounds = self.view.bounds; CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y + 32, bounds.size.width, bounds.size.height - 20); self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.tableView.allowsMultipleSelectionDuringEditing = NO; self.tableView.delegate = self; self.tableView.dataSource = self; - self.tableView.estimatedRowHeight = 390.0; + self.tableView.estimatedRowHeight = 141.0; self.tableView.rowHeight = UITableViewAutomaticDimension; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - self.tableView.allowsMultipleSelectionDuringEditing = NO; + self.contentOffset = 0; + [self registerCellTypes]; [self initCellArray]; + self.edgesForExtendedLayout = UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars = NO; self.automaticallyAdjustsScrollViewInsets = NO; - + UIEdgeInsets tabBarInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0); self.tableView.contentInset = tabBarInsets; self.tableView.scrollIndicatorInsets = tabBarInsets; self.haveScrolled = NO; + [self addAndConstrainSubview:self.tableView]; - [self.view addSubview:self.tableView]; + //[self.view addSubview:self.tableView]; [self addDragHandle]; [self addCloseButton]; } @@ -68,43 +73,58 @@ - (void) initCellArray { headerCell.detailLabelOne.text = [self.manager readableSize:_database.name]; // TODO look into threading this NSInteger tileCount = [_database getTileCount]; - NSString *tileText = tileCount == 1 ? @"tile layer" : @"tile layers"; + NSString *tileText = tileCount == 1 ? @"downloaded map" : @"downloaded maps"; headerCell.detailLabelTwo.text = [NSString stringWithFormat:@"%ld %@", tileCount, tileText]; NSInteger featureCount = [_database getFeatureCount]; - NSString *featureText = featureCount == 1 ? @"feature layer" : @"feature layers"; + NSString *featureText = featureCount == 1 ? @"feature collection" : @"feature collections"; headerCell.detailLabelThree.text = [NSString stringWithFormat:@"%ld %@", featureCount, featureText]; MCGeoPackageOperationsCell *geoPackageOperationsCell = [self.tableView dequeueReusableCellWithIdentifier:@"operations"]; geoPackageOperationsCell.delegate = self; - MCSectionTitleCell *layersTitleCell = [self.tableView dequeueReusableCellWithIdentifier:@"sectionTitle"]; - layersTitleCell.sectionTitleLabel.text = @"Layers"; - - // TODO: Convert new layer wizard to work with drawer system for a future release - MCButtonCell *newLayerButtonCell = [self.tableView dequeueReusableCellWithIdentifier:@"buttonCell"]; - [newLayerButtonCell.button setTitle:@"New Layer" forState:UIControlStateNormal]; - newLayerButtonCell.action = GPKGS_ACTION_NEW_LAYER; - newLayerButtonCell.delegate = self; + _cellArray = [[NSMutableArray alloc] initWithObjects: headerCell, geoPackageOperationsCell, nil]; + + MCSectionTitleCell *offlineMapsTitleCell = [self.tableView dequeueReusableCellWithIdentifier:@"sectionTitle"]; + offlineMapsTitleCell.sectionTitleLabel.text = @"Downloaded Maps"; + [_cellArray addObject:offlineMapsTitleCell]; - _cellArray = [[NSMutableArray alloc] initWithObjects: headerCell, geoPackageOperationsCell, layersTitleCell, newLayerButtonCell, nil]; - NSArray *tables = [_database getTables]; + MCButtonCell *newOfflineMapButtonCell = [self.tableView dequeueReusableCellWithIdentifier:@"buttonCell"]; + [newOfflineMapButtonCell.button setTitle:@"Download a map" forState:UIControlStateNormal]; + newOfflineMapButtonCell.action = GPKGS_ACTION_NEW_LAYER; + newOfflineMapButtonCell.delegate = self; + newOfflineMapButtonCell.button.backgroundColor = [MCColorUtil getAccent]; + [_cellArray addObject: newOfflineMapButtonCell]; - for (GPKGSTable *table in tables) { + NSArray *tileTables = [_database getTiles]; + for (MCTable *table in tileTables) { MCLayerCell *layerCell = [self.tableView dequeueReusableCellWithIdentifier:@"layerCell"]; - NSString *typeImageName = @""; + [layerCell setContentsWithTable:table]; - if ([table isMemberOfClass:[GPKGSFeatureTable class]]) { - typeImageName = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_GEOMETRY]; - [layerCell.detailLabel setText: [NSString stringWithFormat:@"%d features", [(GPKGSFeatureTable *)table count]]]; - } else if ([table isMemberOfClass:[GPKGSTileTable class]]) { - typeImageName = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_TILES]; - [layerCell.detailLabel setText:[NSString stringWithFormat:@"Zoom levels %d - %d", [(GPKGSTileTable *)table minZoom], [(GPKGSTileTable *)table maxZoom]]]; + if ([_active exists:table]) { + [layerCell activeIndicatorOn]; + } else { + [layerCell activeIndicatorOff]; } - layerCell.table = table; - layerCell.layerNameLabel.text = table.name; - [layerCell.layerTypeImage setImage:[UIImage imageNamed:typeImageName]]; + [_cellArray addObject:layerCell]; + } + + MCSectionTitleCell *layersTitleCell = [self.tableView dequeueReusableCellWithIdentifier:@"sectionTitle"]; + layersTitleCell.sectionTitleLabel.text = @"Feature Collections"; + [_cellArray addObject:layersTitleCell]; + + MCButtonCell *newLayerButtonCell = [self.tableView dequeueReusableCellWithIdentifier:@"buttonCell"]; + [newLayerButtonCell.button setTitle:@"New feature collection" forState:UIControlStateNormal]; + newLayerButtonCell.action = @"new-collection"; + newLayerButtonCell.delegate = self; + newLayerButtonCell.button.backgroundColor = [MCColorUtil getAccent]; + [_cellArray addObject:newLayerButtonCell]; + + NSArray *featureTables = [_database getFeatures]; + for (MCTable *table in featureTables) { + MCLayerCell *layerCell = [self.tableView dequeueReusableCellWithIdentifier:@"layerCell"]; + [layerCell setContentsWithTable:table]; if ([_active exists:table]) { [layerCell activeIndicatorOn]; @@ -129,7 +149,7 @@ - (void) registerCellTypes { - (void) update { - [self initCellArray]; // May not need to call this, or may need to call it closer to the end + [self initCellArray]; [self.tableView reloadData]; } @@ -158,11 +178,28 @@ - (void) removeLayerNamed:(NSString *)layerName { - (void) closeDrawer { + [super closeDrawer]; [self.drawerViewDelegate popDrawer]; [self.delegate callCompletionHandler]; } +- (void) drawerWasCollapsed { + [super drawerWasCollapsed]; + [self.tableView setScrollEnabled:NO]; +} + + +- (void) drawerWasMadeFull { + [super drawerWasMadeFull]; + [self.tableView setScrollEnabled:YES]; +} + + +- (void) becameTopDrawer { + [self.delegate setSelectedDatabaseName]; +} + #pragma mark - TableView delegate methods - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { return [_cellArray objectAtIndex:indexPath.row]; @@ -186,25 +223,12 @@ - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *) - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { MCLayerCell *layerCell; NSObject *cellObject = [_cellArray objectAtIndex:indexPath.row]; - [self.tableView deselectRowAtIndexPath:indexPath animated:NO]; - // TODO add layer details view - /*if([cellObject isKindOfClass:[MCLayerCell class]]){ + if([cellObject isKindOfClass:[MCLayerCell class]]){ layerCell = (MCLayerCell *) cellObject; - NSString *layerName = layerCell.layerNameLabel.text; - GPKGGeoPackage *geoPackage = [_manager open:_database.name]; - - if ([geoPackage isFeatureTable:layerName]) { - GPKGFeatureDao *featureDao = [geoPackage getFeatureDaoWithTableName:layerName]; - [_delegate showLayerDetails:featureDao]; - [geoPackage close]; - } else if ([geoPackage isTileTable:layerName]) { - GPKGTileDao *tileDao = [geoPackage getTileDaoWithTableName:layerName]; - [_delegate showLayerDetails:tileDao]; - [geoPackage close]; - } - }*/ + [_delegate showLayerDetails:layerCell.table]; + } } @@ -234,8 +258,21 @@ - (UISwipeActionsConfiguration *) tableView:(UITableView *)tableView leadingSwip - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath { UIContextualAction *deleteAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"Delete" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { - MCLayerCell *cell = [_cellArray objectAtIndex:indexPath.row]; - [_delegate deleteLayer:cell.table]; + MCLayerCell *cell = [self.cellArray objectAtIndex:indexPath.row]; + + UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you want to delete this layer? This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [self.delegate deleteLayer:cell.table]; + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [deleteAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [deleteAlert addAction:confirmDelete]; + [deleteAlert addAction:cancel]; + [self presentViewController:deleteAlert animated:YES completion:nil]; + completionHandler(YES); }]; @@ -252,8 +289,8 @@ -(void) deleteGeoPackage { UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you want to delete this GeoPackage? This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { - [self.delegate deleteGeoPackage]; [self.drawerViewDelegate popDrawer]; + [self.delegate deleteGeoPackage]; }]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { @@ -277,7 +314,7 @@ - (void) shareGeoPackage { [_shareDocumentController setUTI:@"public.database"]; [_shareDocumentController presentOpenInMenuFromRect:self.view.bounds inView:self.view animated:YES]; }else{ - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:[NSString stringWithFormat:@"Share Database %@", _database] andMessage:[NSString stringWithFormat:@"No path was found for database %@", _database]]; } @@ -305,13 +342,13 @@ - (void) renameGeoPackage { [self initCellArray]; [self.tableView reloadData]; }else{ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL] andMessage:[NSString stringWithFormat:@"Rename from %@ to %@ was not successful", self.database.name, newName]]; } } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:[NSString stringWithFormat:@"Rename %@ to %@", self.database.name, newName] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } @@ -350,13 +387,13 @@ - (void) copyGeoPackage { [self.delegate copyGeoPackage]; }); }else{ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL] andMessage:[NSString stringWithFormat:@"Copy from %@ to %@ was not successful", database, newName]]; } } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:[NSString stringWithFormat:@"Copy %@ to %@", database, newName] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } @@ -375,15 +412,27 @@ - (void) copyGeoPackage { - (void)performButtonAction:(NSString *) action { - NSLog(@"Button pressed, checking action..."); + NSLog(@"Button pressed, handling action %@", action); if ([action isEqualToString:GPKGS_ACTION_NEW_LAYER]) { - NSLog(@"Button pressed, handling action %@", action); - [_delegate newLayer]; + [_delegate newTileLayer]; + } else if ([action isEqualToString:@"new-collection"]) { + [_delegate newFeatureLayer]; } } +- (BOOL)gestureIsInConflict:(UIPanGestureRecognizer *) recognizer { + CGPoint point = [recognizer locationInView:self.view]; + + if (CGRectContainsPoint(self.tableView.frame, point)) { + return true; + } + + return false; +} + + // Override this method to make the drawer and the scrollview play nice - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (self.haveScrolled) { @@ -404,7 +453,7 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { } -/* Chekcing */ +/* Checking */ - (void)alertTextFieldDidChange:(UITextField *)sender { UIAlertController *alertController = (UIAlertController *)self.presentedViewController; diff --git a/mapcache-ios/geopackage/MCLayerCoordinator.h b/mapcache-ios/geopackage/MCLayerCoordinator.h deleted file mode 100644 index e48ad55..0000000 --- a/mapcache-ios/geopackage/MCLayerCoordinator.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// MCLayerCoordinator.h -// mapcache-ios -// -// Created by Tyler Burgett on 7/17/18. -// Copyright © 2018 NGA. All rights reserved. -// - -#import -#import -#import "GPKGGeoPackageFactory.h" -#import "MCLayerViewController.h" -#import "MCFeatureLayerOperationsCell.h" -#import "MCTileLayerOperationsCell.h" -#import "GPKGSDatabase.h" -#import "GPKGUserDao.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" - - -@interface MCLayerCoordinator : NSObject -- (instancetype) initWithNavigationController:(UINavigationController *) navigationController andDatabase:(GPKGSDatabase *) database - andDao:(GPKGUserDao *) dao; -- (void) start; -@end diff --git a/mapcache-ios/geopackage/MCLayerCoordinator.m b/mapcache-ios/geopackage/MCLayerCoordinator.m deleted file mode 100644 index 9920fa1..0000000 --- a/mapcache-ios/geopackage/MCLayerCoordinator.m +++ /dev/null @@ -1,88 +0,0 @@ -// -// MCLayerCoordinator.m -// mapcache-ios -// -// Created by Tyler Burgett on 7/17/18. -// Copyright © 2018 NGA. All rights reserved. -// - -#import "MCLayerCoordinator.h" - -@interface MCLayerCoordinator() -@property (strong, nonatomic) MCLayerViewController *layerViewController; -@property (strong, nonatomic) GPKGGeoPackageManager *manager; -@property (strong, nonatomic) GPKGUserDao *dao; -@property (strong, nonatomic) GPKGSDatabase *database; -@property (strong, nonatomic) UINavigationController *navigationController; -@end - - -@implementation MCLayerCoordinator - -- (instancetype) initWithNavigationController:(UINavigationController *) navigationController andDatabase:(GPKGSDatabase *) database - andDao:(GPKGUserDao *) dao { - self = [super init]; - _navigationController = navigationController; - _manager = [GPKGGeoPackageFactory getManager]; - _database = database; - _dao = dao; - return self; -} - - -- (void) start { - _layerViewController = [[MCLayerViewController alloc] init]; - _layerViewController.layerDao = _dao; - _layerViewController.delegate = self; - [_navigationController pushViewController:_layerViewController animated:YES]; - [_navigationController setNavigationBarHidden:NO animated:NO]; -} - - -#pragma mark - MCLayerOperationsDelegate methods -- (void) renameLayer:(NSString *) layerName { - NSLog(@"MCLayerCoordinator - renameLayer"); -} - - -- (void) deleteLayer { - NSLog(@"MCLayerCoordinator - deleteLayer"); - - GPKGGeoPackage *geoPackage = [_manager open:_database.name]; - - @try { - [geoPackage deleteTable:_dao.tableName]; - [_navigationController popViewControllerAnimated:YES]; - } - @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[NSString stringWithFormat:@"%@ %@ - %@ Table", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL], _database.name, _dao.tableName] - andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; - } - @finally { - [geoPackage close]; - - } -} - - -- (void) createOverlay { - NSLog(@"MCLayerCoordinator - createLayer"); -} - - -- (void) createTiles { - NSLog(@"MCLayerCoordinator - createTiles"); -} - - -- (void) indexLayer { - NSLog(@"MCLayerCoordinator - indexLayer"); -} - - -- (void) showTileScalingOptions { - NSLog(@"MCLayerCoordinator - showTileScalingOptions"); -} - -@end diff --git a/mapcache-ios/geopackage/MCLayerViewController.h b/mapcache-ios/geopackage/MCLayerViewController.h deleted file mode 100644 index 4405e65..0000000 --- a/mapcache-ios/geopackage/MCLayerViewController.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// MCLayerViewController.h -// mapcache-ios -// -// Created by Tyler Burgett on 7/3/18. -// Copyright © 2018 NGA. All rights reserved. -// - -#import -#import "GPKGUserDao.h" -#import "GPKGFeatureDao.h" -#import "GPKGTileDao.h" -#import "GPKGSFeatureTable.h" -#import "GPKGSTileTable.h" -#import "MCButtonCell.h" -#import "MCSectionTitleCell.h" -#import "MCHeaderCell.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import -#import -#import "MCFeatureLayerOperationsCell.h" -#import "MCTileLayerOperationsCell.h" -#import "SFPProjectionConstants.h" -#import "GPKGOverlayFactory.h" - -@protocol MCLayerOperationsDelegate -- (void) deleteLayer; -- (void) createOverlay; -- (void) indexLayer; -- (void) createTiles; -- (void) renameLayer:(NSString *) layerName; -- (void) showTileScalingOptions; -@end - - -@interface MCLayerViewController : UITableViewController -@property (strong, nonatomic) GPKGUserDao *layerDao; -@property (weak, nonatomic) id delegate; -@end diff --git a/mapcache-ios/geopackage/MCLayerViewController.m b/mapcache-ios/geopackage/MCLayerViewController.m deleted file mode 100644 index b8980ce..0000000 --- a/mapcache-ios/geopackage/MCLayerViewController.m +++ /dev/null @@ -1,233 +0,0 @@ -// -// MCLayerViewController.m -// mapcache-ios -// -// Created by Tyler Burgett on 7/3/18. -// Copyright © 2018 NGA. All rights reserved. -// - -#import "MCLayerViewController.h" - -@interface MCLayerViewController () -@property (strong, nonatomic) NSMutableArray *cellArray; -@property (strong, nonatomic) GPKGFeatureDao *featureDao; -@property (strong, nonatomic) GPKGTileDao *tileDao; -@property (strong, nonatomic) GPKGGeoPackageManager *manager; -@end - -@implementation MCLayerViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - if ([_layerDao isKindOfClass:GPKGFeatureDao.class]) { - _featureDao = (GPKGFeatureDao *) _layerDao; - _tileDao = nil; - } else if ([_layerDao isKindOfClass:GPKGTileDao.class]) { - _tileDao = (GPKGTileDao *) _layerDao; - _featureDao = nil; - } - - [self registerCellTypes]; - [self initCellArray]; - - self.tableView.rowHeight = UITableViewAutomaticDimension; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - self.tableView.allowsMultipleSelection = NO; - - self.edgesForExtendedLayout = UIRectEdgeNone; - self.extendedLayoutIncludesOpaqueBars = NO; - self.automaticallyAdjustsScrollViewInsets = NO; - - UIEdgeInsets tabBarInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0); - self.tableView.contentInset = tabBarInsets; - self.tableView.scrollIndicatorInsets = tabBarInsets; - - // Uncomment the following line to preserve selection between presentations. - // self.clearsSelectionOnViewWillAppear = NO; - - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem; -} - - -- (void) registerCellTypes { - [self.tableView registerNib:[UINib nibWithNibName:@"MCHeaderCellDisplay" bundle:nil] forCellReuseIdentifier:@"header"]; - [self.tableView registerNib:[UINib nibWithNibName:@"MCFeatureLayerOperationsCell" bundle:nil] forCellReuseIdentifier:@"featureButtons"]; - [self.tableView registerNib:[UINib nibWithNibName:@"MCTileLayerOperationsCell" bundle:nil] forCellReuseIdentifier:@"tileButtons"]; -} - - -- (void) initCellArray { - if ([_cellArray count] > 0) { - [_cellArray removeAllObjects]; - } - - MCHeaderCell *headerCell = [self.tableView dequeueReusableCellWithIdentifier:@"header"]; - headerCell.nameLabel.text = _layerDao.tableName; - - GPKGBoundingBox *layerBoundingBox; - SFPProjectionTransform *transformToWebMercator; - - if (_featureDao != nil) { - MCFeatureLayerOperationsCell *featureButtonsCell = [self.tableView dequeueReusableCellWithIdentifier:@"featureButtons"]; - featureButtonsCell.delegate = self; - layerBoundingBox = [_layerDao getBoundingBox]; - headerCell.featureDao = _featureDao; - transformToWebMercator = [[SFPProjectionTransform alloc] initWithFromProjection:_featureDao.projection andToEpsg:PROJ_EPSG_WEB_MERCATOR]; - _cellArray = [[NSMutableArray alloc] initWithObjects:headerCell, featureButtonsCell, nil]; - } else if (_tileDao != nil) { - MCTileLayerOperationsCell *tileButtonsCell = [self.tableView dequeueReusableCellWithIdentifier:@"tileButtons"]; - tileButtonsCell.delegate = self; - layerBoundingBox = [_tileDao getBoundingBoxWithZoomLevel:_tileDao.minZoom]; - transformToWebMercator = [[SFPProjectionTransform alloc] initWithFromProjection:_tileDao.projection andToEpsg:PROJ_EPSG_WEB_MERCATOR]; - headerCell.tileOverlay = [GPKGOverlayFactory tileOverlayWithTileDao:_tileDao]; - _cellArray = [[NSMutableArray alloc] initWithObjects:headerCell, tileButtonsCell, nil]; - } - - if (layerBoundingBox != nil) { - GPKGBoundingBox *webMercatorBoundingBox = [layerBoundingBox transform:transformToWebMercator]; - SFPProjectionTransform *transform = [[SFPProjectionTransform alloc] initWithFromEpsg:PROJ_EPSG_WEB_MERCATOR andToEpsg:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; - layerBoundingBox = [webMercatorBoundingBox transform:transform]; - // [headerCell.mapView setRegion:layerBoundingBox.getCoordinateRegion]; // TODO sort this out for the new map - } -} - - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - - -#pragma mark - Table view data source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [_cellArray count]; -} - - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - return [_cellArray objectAtIndex:indexPath.row]; -} - - -- (void) renameLayer:(GPKGUserDao *) dao { - NSLog(@"Renaming Layer"); - - UIAlertController *renameAlert = [UIAlertController alertControllerWithTitle:@"Rename Layer" message:@"" preferredStyle:UIAlertControllerStyleAlert]; - [renameAlert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { - textField.text = dao.tableName; - }]; - - UIAlertAction *confirmRename = [UIAlertAction actionWithTitle:@"Rename" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { - NSLog(@"New name is: %@", renameAlert.textFields[0].text); - - NSString * newName = renameAlert.textFields[0].text; - - if(newName != nil && [newName length] > 0 && ![newName isEqualToString:dao.tableName]){ - @try { - if(newName != nil && [newName length] > 0 && ![newName isEqualToString:dao.tableName]){ - //self.database.name = newName; - [self initCellArray]; - [self.tableView reloadData]; - }else{ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL] - andMessage:[NSString stringWithFormat:@"Rename from %@ to %@ was not successful", @"OLDNAME", newName]]; - } - } - @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[NSString stringWithFormat:@"Rename %@ to %@", @"OLDNAME", newName] - andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; - } - } - }]; - - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { - [renameAlert dismissViewControllerAnimated:YES completion:nil]; - }]; - - [renameAlert addAction:confirmRename]; - [renameAlert addAction:cancel]; - - [self presentViewController:renameAlert animated:YES completion:nil]; -} - - -- (void) deleteLayer { - NSLog(@"Deleting layer"); - - UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you wanbt to delete this layer? This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { - [self.delegate deleteLayer]; - [self dismissViewControllerAnimated:YES completion:nil]; - }]; - - UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { - [deleteAlert dismissViewControllerAnimated:YES completion:nil]; - }]; - - [deleteAlert addAction:confirmDelete]; - [deleteAlert addAction:cancel]; - - [self presentViewController:deleteAlert animated:YES completion:nil]; -} - - -#pragma mark - MCFeatureLayerOperationsCellDelegate methods -- (void) renameFeatureLayer { - NSLog(@"MCLayerOperationsDelegate editLayer"); - [self renameLayer: _featureDao]; -} - - -- (void) indexFeatures { - NSLog(@"MCLayerOperationsDelegate indexLayer"); - [_delegate indexLayer]; -} - - -- (void) createTiles { - NSLog(@"MCLayerOperationsDelegate createTiles"); - [_delegate createTiles]; -} - - -- (void) createOverlay { - NSLog(@"MCLayerOperationsDelegate createOverlay"); - [_delegate createOverlay]; -} - - -- (void) deleteFeatureLayer { - NSLog(@"MCFeatureButtonsCellDelegate deleteLayer %@", _featureDao.tableName); - [self deleteLayer]; - -} - - -#pragma mark - MCTileButtonsDelegate methods -- (void) renameTileLayer { - NSLog(@"MCTileButtonsDelegate renameLayer"); - [self renameLayer: _tileDao]; -} - - -- (void) showScalingOptions { - NSLog(@"MCTileButtonsDelegate showScalingOptions"); - [_delegate showTileScalingOptions]; -} - - -- (void) deleteTileLayer { - NSLog(@"MCTileButtonsDelegate deleteTileLayer"); - [self deleteLayer]; -} - - -@end diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCCreateLayerViewController.h b/mapcache-ios/geopackage/NewLayerWizard/MCCreateLayerViewController.h index 8acc03b..38ea413 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCCreateLayerViewController.h +++ b/mapcache-ios/geopackage/NewLayerWizard/MCCreateLayerViewController.h @@ -8,7 +8,7 @@ #import #import -#import "GPKGSDatabase.h" +#import "MCDatabase.h" #import "NGADrawerViewController.h" diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.h b/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.h index 7bf8a99..1a54f37 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.h +++ b/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.h @@ -7,16 +7,17 @@ // #import +#import "NGADrawerViewController.h" #import #import #import -#import "GPKGSUtils.h" -#import "GPKGSConstants.h" +#import "MCUtils.h" +#import "MCConstants.h" #import "SFPProjectionConstants.h" -#import "GPKGSProperties.h" +#import "MCProperties.h" #import "MCButtonCell.h" #import "GPKGBoundingBox.h" -#import "GPKGSDatabase.h" +#import "MCDatabase.h" #import "MCDescriptionCell.h" #import "MCSectionTitleCell.h" #import "MCFieldWithTitleCell.h" @@ -25,10 +26,10 @@ @protocol MCFeatureLayerCreationDelegate //- (void) featureLayerCreationComplete:(BOOL)layerCreated withError:(NSString *)error; -- (void) createFeatueLayerIn:(NSString *)database with:(GPKGGeometryColumns *)geometryColumns andBoundingBox:(GPKGBoundingBox *)boundingBox andSrsId:(NSNumber *) srsId; +- (void) createFeatueLayerIn:(NSString *)database withGeomertyColumns:(GPKGGeometryColumns *)geometryColumns andBoundingBox:(GPKGBoundingBox *)boundingBox andSrsId:(NSNumber *) srsId; @end -@interface MCFeatureLayerDetailsViewController : UITableViewController -@property (strong, nonatomic) GPKGSDatabase *database; +@interface MCFeatureLayerDetailsViewController : NGADrawerViewController +@property (strong, nonatomic) MCDatabase *database; @property (weak, nonatomic) id delegate; @end diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.m b/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.m index ee10c8a..208060e 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.m +++ b/mapcache-ios/geopackage/NewLayerWizard/MCFeatureLayerDetailsViewController.m @@ -14,12 +14,12 @@ @interface MCFeatureLayerDetailsViewController () @property (strong, nonatomic) NSArray *geometryTypes; @property (strong, nonatomic) NSDictionary *geometryTypesDictionary; @property (strong, nonatomic) NSString *selectedGeometryType; - +@property (strong, nonatomic) UITableView *tableView; @property (strong, nonatomic) GPKGGeoPackageManager *manager; @property (strong, nonatomic) MCSectionTitleCell *titleCell; @property (strong, nonatomic) MCFieldWithTitleCell *layerNameCell; -@property (strong, nonatomic) MCPickerViewCell *geometryTypeCell; @property (strong, nonatomic) MCButtonCell *buttonCell; +@property (strong, nonatomic) MCDescriptionCell *descriptionCell; @end @implementation MCFeatureLayerDetailsViewController @@ -27,9 +27,19 @@ @implementation MCFeatureLayerDetailsViewController - (void)viewDidLoad { [super viewDidLoad]; - _manager = [GPKGGeoPackageFactory getManager]; - _geometryTypes = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES]; - _geometryTypesDictionary = [GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES_DICTIONARY]; + CGRect bounds = self.view.bounds; + CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y - 6, bounds.size.width, bounds.size.height); + self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; + self.tableView.delegate = self; + self.tableView.dataSource = self; + //self.tableView.estimatedRowHeight = 390.0; + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.tableView.allowsMultipleSelectionDuringEditing = NO; + + _geometryTypes = [MCProperties getArrayOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES]; + _geometryTypesDictionary = [MCProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES_DICTIONARY]; [self registerCellTypes]; [self initCellArray]; @@ -40,7 +50,8 @@ - (void)viewDidLoad { self.tableView.estimatedRowHeight = 100; self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.separatorStyle = UIAccessibilityTraitNone; - [self.tableView setBackgroundColor:[UIColor whiteColor]]; + [self.view addSubview:self.tableView]; + [self addCloseButton]; } - (void)didReceiveMemoryWarning { @@ -71,15 +82,6 @@ - (void) initCellArray { _layerNameCell.field.delegate = self; [_cellArray addObject:_layerNameCell]; - _geometryTypeCell = [self.tableView dequeueReusableCellWithIdentifier:@"picker"]; - _geometryTypeCell.label.text = @"Geometry Type"; - _geometryTypeCell.picker.delegate = self; - _geometryTypeCell.picker.dataSource = self; - _geometryTypeCell.picker.showsSelectionIndicator = YES; - [_geometryTypeCell.picker selectRow:[_geometryTypesDictionary.allKeys indexOfObject:@"Geometry"] inComponent:0 animated:YES]; - _selectedGeometryType = [_geometryTypesDictionary valueForKey:@"Geometry"]; - [_cellArray addObject:_geometryTypeCell]; - _buttonCell = [self.tableView dequeueReusableCellWithIdentifier:@"button"]; _buttonCell.delegate = self; _buttonCell.action = GPKGS_ACTION_NEW_FEATURE_LAYER; @@ -90,8 +92,12 @@ - (void) initCellArray { } else { [_buttonCell enableButton]; } - + [_cellArray addObject:_buttonCell]; + + _descriptionCell = [self.tableView dequeueReusableCellWithIdentifier:@"description"]; + [_descriptionCell setDescription:@"\n\n"]; + [_cellArray addObject:_descriptionCell]; } @@ -128,9 +134,14 @@ - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComp #pragma mark - UITextFieldDelegate - (void) textFieldDidEndEditing:(UITextField *)textField { - if ([_layerNameCell.field.text isEqualToString:@""]) { + if ([[_layerNameCell fieldValue] isEqualToString:@""]) { + [_buttonCell disableButton]; + } else if ([_database hasTableNamed:[_layerNameCell fieldValue]]) { [_buttonCell disableButton]; + [_layerNameCell useErrorAppearance]; + [_descriptionCell setDescription:@"This GeoPackage already has a layer with that name, please choose a new one."]; } else { + [_layerNameCell useNormalAppearance]; [_buttonCell enableButton]; } @@ -143,6 +154,12 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField { } +- (void) closeDrawer { + [self.drawerViewDelegate popDrawer]; +} + + + #pragma mark - GPKGSButtonCellDelegate - (void) performButtonAction:(NSString *) action { if ([action isEqualToString:GPKGS_ACTION_NEW_FEATURE_LAYER]) { @@ -167,16 +184,18 @@ - (void) performButtonAction:(NSString *) action { [NSException raise:@"Longitude Range" format:@"Min longitude can not be larger than max longitude"]; } + _selectedGeometryType = [_geometryTypesDictionary valueForKey:@"Geometry"]; enum SFGeometryType geometryType = [SFGeometryTypes fromName:_selectedGeometryType]; GPKGGeometryColumns * geometryColumns = [[GPKGGeometryColumns alloc] init]; [geometryColumns setTableName:tableName]; [geometryColumns setColumnName:@"geom"]; - [geometryColumns setGeometryType:geometryType]; + + [geometryColumns setGeometryType: geometryType]; [geometryColumns setZ:[NSNumber numberWithInt:0]]; [geometryColumns setM:[NSNumber numberWithInt:0]]; - [_delegate createFeatueLayerIn:_database.name with:geometryColumns andBoundingBox:boundingBox andSrsId:[NSNumber numberWithInt:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]]; + [_delegate createFeatueLayerIn:_database.name withGeomertyColumns:geometryColumns andBoundingBox:boundingBox andSrsId:[NSNumber numberWithInt:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]]; } @catch (NSException *e) { if(self.delegate != nil){ @@ -186,5 +205,6 @@ - (void) performButtonAction:(NSString *) action { } } + @end diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.h b/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.h index e623a89..02a531d 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.h +++ b/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.h @@ -25,7 +25,7 @@ - (BOOL) isLayerNameAvailable: (NSString *) layerName; @end -@interface MCTileLayerDetailsViewController : NGADrawerViewController +@interface MCTileLayerDetailsViewController : NGADrawerViewController @property (weak, nonatomic) id delegate; @property (nonatomic, strong) NSString *selectedServerURL; @property (nonatomic, strong) NSString *layerName; diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.m b/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.m index 33a1a6b..3e18b49 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.m +++ b/mapcache-ios/geopackage/NewLayerWizard/MCTileLayerDetailsViewController.m @@ -148,7 +148,7 @@ - (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(N #pragma mark- UITextFieldDelegate methods - (void) textFieldDidEndEditing:(UITextField *)textField { - [textField trimWhiteSpace:textField]; + [textField trimWhiteSpace]; if (textField == _urlCell.field) { NSLog(@"URL Field ended editing"); diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCTileServerHelpViewController.h b/mapcache-ios/geopackage/NewLayerWizard/MCTileServerHelpViewController.h index 265e451..747ffd7 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCTileServerHelpViewController.h +++ b/mapcache-ios/geopackage/NewLayerWizard/MCTileServerHelpViewController.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface MCTileServerHelpViewController : NGADrawerViewController +@interface MCTileServerHelpViewController : NGADrawerViewController @end diff --git a/mapcache-ios/geopackage/NewLayerWizard/MCZoomAndQualityViewController.h b/mapcache-ios/geopackage/NewLayerWizard/MCZoomAndQualityViewController.h index a0e7a7f..436214b 100644 --- a/mapcache-ios/geopackage/NewLayerWizard/MCZoomAndQualityViewController.h +++ b/mapcache-ios/geopackage/NewLayerWizard/MCZoomAndQualityViewController.h @@ -23,6 +23,6 @@ - (NSString *) updateTileDownloadSizeEstimateWith:(NSNumber *) minZoom andMaxZoom:(NSNumber *) maxZoom; @end -@interface MCZoomAndQualityViewController : NGADrawerViewController +@interface MCZoomAndQualityViewController : NGADrawerViewController @property (weak, nonatomic) id zoomAndQualityDelegate; @end diff --git a/mapcache-ios/geopackage/cells/MCButtonCell.h b/mapcache-ios/geopackage/cells/MCButtonCell.h index 4a7adbc..374e8b0 100644 --- a/mapcache-ios/geopackage/cells/MCButtonCell.h +++ b/mapcache-ios/geopackage/cells/MCButtonCell.h @@ -9,19 +9,22 @@ #import #import #import "MCColorUtil.h" -#import "GPKGSConstants.h" +#import "MCConstants.h" -@protocol GPKGSButtonCellDelegate +@protocol MCButtonCellDelegate - (void) performButtonAction:(NSString *) action; @end @interface MCButtonCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIButton *button; -@property (weak, nonatomic) id delegate; +@property (weak, nonatomic) id delegate; @property (strong, nonatomic) NSString *action; - (void) enableButton; - (void) disableButton; +- (void) usePrimaryColors; - (void) useSecondaryColors; +- (void) useRedColor; +- (void) useSecondaryRed; - (void) setButtonLabel: (NSString *) text; @end diff --git a/mapcache-ios/geopackage/cells/MCButtonCell.m b/mapcache-ios/geopackage/cells/MCButtonCell.m index 65804ba..d75570d 100644 --- a/mapcache-ios/geopackage/cells/MCButtonCell.m +++ b/mapcache-ios/geopackage/cells/MCButtonCell.m @@ -32,6 +32,13 @@ - (void) setButtonLabel: (NSString *) text { } +- (void) usePrimaryColors { + [self.button setBackgroundColor: [MCColorUtil getAccent]]; + self.button.clipsToBounds = YES; + [self.button setTitleColor: [UIColor whiteColor] forState:UIControlStateNormal]; +} + + - (void) useSecondaryColors { [self.button setBackgroundColor:[UIColor clearColor]]; self.button.clipsToBounds = YES; @@ -39,15 +46,29 @@ - (void) useSecondaryColors { } +- (void) useRedColor { + [self.button setBackgroundColor:[UIColor redColor]]; + self.button.clipsToBounds = YES; + [self.button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; +} + + +- (void) useSecondaryRed { + [self.button setBackgroundColor:[UIColor clearColor]]; + self.button.clipsToBounds = YES; + [self.button setTitleColor: [UIColor redColor] forState:UIControlStateNormal]; +} + + - (void) enableButton { _button.userInteractionEnabled = YES; - _button.backgroundColor = [MCColorUtil getAccent]; + [_button setBackgroundColor: [MCColorUtil getAccent]]; } - (void) disableButton { _button.userInteractionEnabled = NO; - _button.backgroundColor = [MCColorUtil getAccentLight]; + [_button setBackgroundColor: [MCColorUtil getMediumGrey]]; } @end diff --git a/mapcache-ios/geopackage/cells/MCDescriptionCell.h b/mapcache-ios/geopackage/cells/MCDescriptionCell.h index c2d5ad8..16d50b1 100644 --- a/mapcache-ios/geopackage/cells/MCDescriptionCell.h +++ b/mapcache-ios/geopackage/cells/MCDescriptionCell.h @@ -11,5 +11,9 @@ @interface MCDescriptionCell : UITableViewCell @property (weak, nonatomic) IBOutlet UILabel *descriptionLabel; - (void) setDescription: (NSString *) description; +- (void)textAlignCenter; +- (void)textAlignRight; +- (void)textAlignLeft; +- (void)useSecondaryAppearance; @end diff --git a/mapcache-ios/geopackage/cells/MCDescriptionCell.m b/mapcache-ios/geopackage/cells/MCDescriptionCell.m index c5a065f..06b6955 100644 --- a/mapcache-ios/geopackage/cells/MCDescriptionCell.m +++ b/mapcache-ios/geopackage/cells/MCDescriptionCell.m @@ -28,6 +28,26 @@ - (void) setDescription: (NSString *) description { [self updateConstraintsIfNeeded]; [self layoutSubviews]; [self.descriptionLabel layoutIfNeeded]; + } + + +- (void)textAlignCenter { + self.descriptionLabel.textAlignment = NSTextAlignmentCenter; +} + + +- (void)textAlignRight { + self.descriptionLabel.textAlignment = NSTextAlignmentRight; +} + + +- (void)textAlignLeft { + self.descriptionLabel.textAlignment = NSTextAlignmentLeft; +} + + +- (void)useSecondaryAppearance { + [self.descriptionLabel setTextColor:[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]]; } @end diff --git a/mapcache-ios/geopackage/cells/MCEmptyStateCell.h b/mapcache-ios/geopackage/cells/MCEmptyStateCell.h index 433ee7e..5339d4d 100644 --- a/mapcache-ios/geopackage/cells/MCEmptyStateCell.h +++ b/mapcache-ios/geopackage/cells/MCEmptyStateCell.h @@ -11,7 +11,10 @@ NS_ASSUME_NONNULL_BEGIN @interface MCEmptyStateCell : UITableViewCell - +@property (weak, nonatomic) IBOutlet UIImageView *logoImageView; +@property (weak, nonatomic) IBOutlet UILabel *titleLabel; +@property (weak, nonatomic) IBOutlet UILabel *detailLabel; +-(void)useAsSpacer; @end NS_ASSUME_NONNULL_END diff --git a/mapcache-ios/geopackage/cells/MCEmptyStateCell.m b/mapcache-ios/geopackage/cells/MCEmptyStateCell.m index 5e6f695..4177f4d 100644 --- a/mapcache-ios/geopackage/cells/MCEmptyStateCell.m +++ b/mapcache-ios/geopackage/cells/MCEmptyStateCell.m @@ -15,10 +15,17 @@ - (void)awakeFromNib { // Initialization code } + - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; +} + - // Configure the view for the selected state +- (void) useAsSpacer { + [self.logoImageView setHidden:YES]; + [self.titleLabel setHidden:YES]; + [self.detailLabel setHidden:YES]; } + @end diff --git a/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.h b/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.h index 0b8ec36..e10ebaa 100644 --- a/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.h +++ b/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.h @@ -8,19 +8,30 @@ #import #import "UITextField+Validators.h" +#import "GPKGDataTypes.h" @interface MCFieldWithTitleCell : UITableViewCell @property (weak, nonatomic) IBOutlet UILabel *title; @property (weak, nonatomic) IBOutlet UITextField *field; -- (NSString *)fieldValue; +/** + When editing the contents of a feature row this can be used to know which column the value of the field will need to be saved to. + */ +@property (strong, nonatomic) NSString *columnName; + +/** + Optional value used when validating data input from MCPointDataViewController. + */ +@property (nonatomic) enum GPKGDataType dataType; + +- (NSString *) fieldValue; - (void) setTitleText:(NSString *) titleText; - (void) setPlaceholder:(NSString *) placeholder; - (void) setFieldText:(NSString *) text; -- (void)setTextFielDelegate: (id)delegate; +- (void) setTextFielDelegate: (id)delegate; - (void) useReturnKeyDone; -- (void)setupNumericalKeyboard; +- (void) setupNumericalKeyboard; - (void) useNormalAppearance; - (void) useErrorAppearance; @end diff --git a/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.m b/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.m index 0b5879a..a972321 100644 --- a/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.m +++ b/mapcache-ios/geopackage/cells/MCFieldWithTitleCell.m @@ -44,6 +44,9 @@ - (void) setFieldText:(NSString *) text { } +/** + Change the return key to be a done button for the text field. + */ - (void) useReturnKeyDone { [self.field setReturnKeyType:UIReturnKeyDone]; } @@ -61,11 +64,10 @@ - (void)setTextFielDelegate: (id)delegate { - (void)setupNumericalKeyboard { self.field.keyboardType = UIKeyboardTypeNumberPad; - - UIToolbar *keyboardAccessoryView = [[UIToolbar alloc] init]; - [keyboardAccessoryView sizeToFit]; + UIToolbar *keyboardAccessoryView = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, [[UIApplication sharedApplication] keyWindow].frame.size.width, 40)]; UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(done:)]; [keyboardAccessoryView setItems:@[doneButton]]; + [keyboardAccessoryView sizeToFit]; self.field.inputAccessoryView = keyboardAccessoryView; } diff --git a/mapcache-ios/geopackage/cells/MCGeoPackageCell.h b/mapcache-ios/geopackage/cells/MCGeoPackageCell.h index 3bd0cc0..b274b61 100644 --- a/mapcache-ios/geopackage/cells/MCGeoPackageCell.h +++ b/mapcache-ios/geopackage/cells/MCGeoPackageCell.h @@ -7,6 +7,7 @@ // #import +#import "MCDatabase.h" @interface MCGeoPackageCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIImageView *visibilityStatusIndicator; @@ -14,6 +15,8 @@ @property (weak, nonatomic) IBOutlet UILabel *tileLayerDetailsLabel; @property (weak, nonatomic) IBOutlet UILabel *featureLayerDetailsLabel; @property (weak, nonatomic) IBOutlet UIView *contentView; +@property (strong, nonatomic) MCDatabase *database; +- (void)setContentWithDatabase: (MCDatabase *) database; - (void)activeLayersIndicatorOn; - (void)activeLayersIndicatorOff; - (void)toggleActiveIndicator; diff --git a/mapcache-ios/geopackage/cells/MCGeoPackageCell.m b/mapcache-ios/geopackage/cells/MCGeoPackageCell.m index 304a107..1e50db0 100644 --- a/mapcache-ios/geopackage/cells/MCGeoPackageCell.m +++ b/mapcache-ios/geopackage/cells/MCGeoPackageCell.m @@ -23,8 +23,29 @@ - (void)awakeFromNib { - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; +} + + +- (void)setContentWithDatabase: (MCDatabase *) database { + self.database = database; + [self.geoPackageNameLabel setText:database.name]; + + if ([database getFeatures].count == 1) { + [self.featureLayerDetailsLabel setText: [NSString stringWithFormat:@"%ld Feature layer", (long)[database getFeatures].count]]; + } else { + [self.featureLayerDetailsLabel setText: [NSString stringWithFormat:@"%ld Feature layers", (long)[database getFeatures].count]]; + } + + if ([database getTileCount] == 1) { + [self.tileLayerDetailsLabel setText: [NSString stringWithFormat:@"%ld Tile layer", (long)[database getTileCount]]]; + } else { + [self.tileLayerDetailsLabel setText: [NSString stringWithFormat:@"%ld Tile layers", (long)[database getTileCount]]]; + } +} + - // Configure the view for the selected state +- (void)setGeoPackageName:(NSString *) name { + [self.geoPackageNameLabel setText:name]; } diff --git a/mapcache-ios/geopackage/cells/MCHeaderCell.h b/mapcache-ios/geopackage/cells/MCHeaderCell.h index 41f3463..7f1f8e8 100644 --- a/mapcache-ios/geopackage/cells/MCHeaderCell.h +++ b/mapcache-ios/geopackage/cells/MCHeaderCell.h @@ -21,6 +21,9 @@ @property (weak, nonatomic) IBOutlet UILabel *detailLabelOne; @property (weak, nonatomic) IBOutlet UILabel *detailLabelTwo; @property (weak, nonatomic) IBOutlet UILabel *detailLabelThree; -@property (strong, nonatomic) MKTileOverlay *tileOverlay; -@property (strong, nonatomic) GPKGFeatureDao *featureDao; + +- (void)setNameLabelText:(NSString *) text; +- (void)setDetailLabelOneText:(NSString *) text; +- (void)setDetailLabelTwoText:(NSString *) text; +- (void)setDetailLabelThreeText:(NSString *) text; @end diff --git a/mapcache-ios/geopackage/cells/MCHeaderCell.m b/mapcache-ios/geopackage/cells/MCHeaderCell.m index 8d5e47e..919ae93 100644 --- a/mapcache-ios/geopackage/cells/MCHeaderCell.m +++ b/mapcache-ios/geopackage/cells/MCHeaderCell.m @@ -6,7 +6,7 @@ // Copyright © 2017 NGA. All rights reserved. // -#import "GPKGSConstants.h" +#import "MCConstants.h" #import "MCHeaderCell.h" @implementation MCHeaderCell @@ -23,4 +23,26 @@ - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; } + +- (void)setNameLabelText:(NSString *) text { + [self.nameLabel setText:text]; +} + + +- (void)setDetailLabelOneText:(NSString *) text { + [self.detailLabelOne setText:text]; +} + + +- (void)setDetailLabelTwoText:(NSString *) text { + [self.detailLabelTwo setText:text]; +} + + +- (void)setDetailLabelThreeText:(NSString *) text { + [self.detailLabelThree setText:text]; +} + + + @end diff --git a/mapcache-ios/geopackage/cells/MCLayerCell.h b/mapcache-ios/geopackage/cells/MCLayerCell.h index bd3a523..3bf6f3a 100644 --- a/mapcache-ios/geopackage/cells/MCLayerCell.h +++ b/mapcache-ios/geopackage/cells/MCLayerCell.h @@ -6,7 +6,11 @@ // Copyright © 2017 NGA. All rights reserved. // -#import "GPKGSTable.h" +#import "MCTable.h" +#import "MCFeatureTable.h" +#import "MCTileTable.h" +#import "MCConstants.h" +#import "MCProperties.h" #import @@ -15,10 +19,11 @@ @property (weak, nonatomic) IBOutlet UIImageView *layerTypeImage; @property (weak, nonatomic) IBOutlet UILabel *layerNameLabel; @property (weak, nonatomic) IBOutlet UILabel *detailLabel; -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; - (void)activeIndicatorOn; - (void)activeIndicatorOff; - (void)toggleActiveIndicator; - (void) setDetails: (NSString *) details; - (void) setName: (NSString *) name; +- (void)setContentsWithTable:(MCTable *) table; @end diff --git a/mapcache-ios/geopackage/cells/MCLayerCell.m b/mapcache-ios/geopackage/cells/MCLayerCell.m index 71fa1b9..b77ae39 100644 --- a/mapcache-ios/geopackage/cells/MCLayerCell.m +++ b/mapcache-ios/geopackage/cells/MCLayerCell.m @@ -24,6 +24,23 @@ - (void)setSelected:(BOOL)selected animated:(BOOL)animated { } +- (void)setContentsWithTable:(MCTable *) table { + self.table = table; + [self.layerNameLabel setText:table.name]; + + NSString *typeImageName = @""; + if ([table isMemberOfClass:[MCFeatureTable class]]) { + typeImageName = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_GEOMETRY]; + [self.detailLabel setText: [NSString stringWithFormat:@"%d features", [(MCFeatureTable *)table count]]]; + } else if ([table isMemberOfClass:[MCTileTable class]]) { + typeImageName = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_TILES]; + [self.detailLabel setText:[NSString stringWithFormat:@"Zoom levels %d - %d", [(MCTileTable *)table minZoom], [(MCTileTable *)table maxZoom]]]; + } + + [self.layerTypeImage setImage:[UIImage imageNamed:typeImageName]]; +} + + - (void) setName: (NSString *) name { [self.layerNameLabel setText:name]; } diff --git a/mapcache-ios/geopackage/cells/MCSegmentedControlCell.h b/mapcache-ios/geopackage/cells/MCSegmentedControlCell.h index c9fbe62..774f9ba 100644 --- a/mapcache-ios/geopackage/cells/MCSegmentedControlCell.h +++ b/mapcache-ios/geopackage/cells/MCSegmentedControlCell.h @@ -18,7 +18,8 @@ @property (weak, nonatomic) id delegate; @property (weak, nonatomic) IBOutlet UILabel *label; @property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl; -@property (strong, nonatomic) NSArray *items; +@property (strong, nonatomic) NSArray *updateItems; -- (void) setItems:(NSArray *)items; +- (void) updateItems:(NSArray *)items; +- (void) setLabelText:(NSString *)text; @end diff --git a/mapcache-ios/geopackage/cells/MCSegmentedControlCell.m b/mapcache-ios/geopackage/cells/MCSegmentedControlCell.m index 1b29f2b..937df02 100644 --- a/mapcache-ios/geopackage/cells/MCSegmentedControlCell.m +++ b/mapcache-ios/geopackage/cells/MCSegmentedControlCell.m @@ -22,16 +22,21 @@ - (void)setSelected:(BOOL)selected animated:(BOOL)animated { } -- (void) setItems:(NSArray *)items { - _items = items; +- (void) setLabelText:(NSString *)text { + [self.label setText:text]; +} + + +- (void) updateItems:(NSArray *)items { + _updateItems = items; [_segmentedControl removeAllSegments]; - for (int i = 0; i < _items.count; i++) { - [_segmentedControl insertSegmentWithTitle:[_items objectAtIndex:i] atIndex:i animated:NO]; + for (int i = 0; i < _updateItems.count; i++) { + [_segmentedControl insertSegmentWithTitle:[_updateItems objectAtIndex:i] atIndex:i animated:NO]; } - if (_items.count > 0) { + if (_updateItems.count > 0) { [_segmentedControl setSelectedSegmentIndex:0]; } } diff --git a/mapcache-ios/geopackage/cells/MCSwitchCell.h b/mapcache-ios/geopackage/cells/MCSwitchCell.h index 3a3b19a..1951a64 100644 --- a/mapcache-ios/geopackage/cells/MCSwitchCell.h +++ b/mapcache-ios/geopackage/cells/MCSwitchCell.h @@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN @property (weak, nonatomic) IBOutlet UISwitch *switchControl; @property (weak, nonatomic) IBOutlet UILabel *label; @property (weak, nonatomic) id switchDelegate; +@property (strong, nonatomic) NSString *columnName; - (void) switchOn; - (void) switchOff; diff --git a/mapcache-ios/geopackage/cells/MCTitleCell.h b/mapcache-ios/geopackage/cells/MCTitleCell.h index 7e0dd11..be4ed47 100644 --- a/mapcache-ios/geopackage/cells/MCTitleCell.h +++ b/mapcache-ios/geopackage/cells/MCTitleCell.h @@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @interface MCTitleCell : UITableViewCell +- (void)setLabelText:(NSString *) text; @property (weak, nonatomic) IBOutlet UILabel *label; @end diff --git a/mapcache-ios/geopackage/cells/MCTitleCell.m b/mapcache-ios/geopackage/cells/MCTitleCell.m index a0b8879..4c17625 100644 --- a/mapcache-ios/geopackage/cells/MCTitleCell.m +++ b/mapcache-ios/geopackage/cells/MCTitleCell.m @@ -17,10 +17,16 @@ - (void)awakeFromNib { // Initialization code } + - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } + +- (void)setLabelText:(NSString *) text { + [self.label setText:text]; +} + @end diff --git a/mapcache-ios/indexer/GPKGSIndexerTask.h b/mapcache-ios/indexer/MCIndexerTask.h similarity index 91% rename from mapcache-ios/indexer/GPKGSIndexerTask.h rename to mapcache-ios/indexer/MCIndexerTask.h index 6de581c..1c638ce 100644 --- a/mapcache-ios/indexer/GPKGSIndexerTask.h +++ b/mapcache-ios/indexer/MCIndexerTask.h @@ -11,7 +11,7 @@ #import "GPKGSIndexerProtocol.h" #import "GPKGFeatureIndexTypes.h" -@interface GPKGSIndexerTask : NSObject +@interface MCIndexerTask : NSObject +(void) indexFeaturesWithCallback: (NSObject *) callback andDatabase: (NSString *) database diff --git a/mapcache-ios/indexer/GPKGSIndexerTask.m b/mapcache-ios/indexer/MCIndexerTask.m similarity index 84% rename from mapcache-ios/indexer/GPKGSIndexerTask.m rename to mapcache-ios/indexer/MCIndexerTask.m index 38d7d38..741de2f 100644 --- a/mapcache-ios/indexer/GPKGSIndexerTask.m +++ b/mapcache-ios/indexer/MCIndexerTask.m @@ -6,16 +6,16 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSIndexerTask.h" +#import "MCIndexerTask.h" #import "GPKGGeoPackage.h" #import "GPKGGeoPackageManager.h" #import "GPKGGeoPackageFactory.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCUtils.h" #import "GPKGFeatureIndexManager.h" -@interface GPKGSIndexerTask () +@interface MCIndexerTask () @property (nonatomic, strong) NSNumber *maxIndex; @property (nonatomic, strong) GPKGGeoPackage *geoPackage; @@ -29,40 +29,41 @@ @interface GPKGSIndexerTask () @end -@implementation GPKGSIndexerTask +@implementation MCIndexerTask +(void) indexFeaturesWithCallback: (NSObject *) callback andDatabase: (NSString *) database andTable: (NSString *) tableName andFeatureIndexType: (enum GPKGFeatureIndexType) indexLocation{ - GPKGGeoPackageManager *manager = [GPKGGeoPackageFactory getManager]; + GPKGGeoPackageManager *manager = [GPKGGeoPackageFactory manager]; GPKGGeoPackage * geoPackage = nil; @try { geoPackage = [manager open:database]; - } - @finally { + } @catch (NSException *e) { + NSLog(@"---------- MCIndexerTask - Problem indexing \n%@", e.reason); + } @finally { [manager close]; } - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:tableName]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:tableName]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; [indexer setIndexLocation:indexLocation]; - GPKGSIndexerTask * indexTask = [[GPKGSIndexerTask alloc] initWithCallback:callback andGeoPackage:geoPackage andIndexer:indexer]; + MCIndexerTask * indexTask = [[MCIndexerTask alloc] initWithCallback:callback andGeoPackage:geoPackage andIndexer:indexer]; int max = [featureDao count]; [indexTask setMax:max]; [indexer setProgress:indexTask]; UIAlertView *alertView = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"%@ %@ - %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE], database, tableName] + initWithTitle:[NSString stringWithFormat:@"%@ %@ - %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE], database, tableName] message:@"" delegate:indexTask - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] otherButtonTitles:nil]; - UIProgressView *progressView = [GPKGSUtils buildProgressBarView]; + UIProgressView *progressView = [MCUtils buildProgressBarView]; [alertView setValue:progressView forKey:@"accessoryView"]; indexTask.alertView = alertView; diff --git a/mapcache-ios/layer/MCCreateLayerFieldViewController.swift b/mapcache-ios/layer/MCCreateLayerFieldViewController.swift new file mode 100644 index 0000000..d4bd8c8 --- /dev/null +++ b/mapcache-ios/layer/MCCreateLayerFieldViewController.swift @@ -0,0 +1,162 @@ +// +// MCLayerDetailsViewController.swift +// mapcache-ios +// +// Created by Tyler Burgett on 5/19/20. +// Copyright © 2020 NGA. All rights reserved. +// + +import UIKit + +protocol MCCreateLayerFieldDelegate: AnyObject { + func createField(name:String, type:GPKGDataType) + func checkFieldNameCollision(name: String) -> Bool +} + + +class MCCreateLayerFieldViewController: NGADrawerViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, MCDualButtonCellDelegate, MCSegmentedControlCellDelegate { + + var cellArray: Array = [] + var featureTable: MCFeatureTable = MCFeatureTable() + var tableView: UITableView = UITableView() + var haveScrolled: Bool = false + var contentOffset: CGFloat = 0.0 + var fieldName: MCFieldWithTitleCell? + var dualButtons: MCDualButtonCell? + var segmentedControl: MCSegmentedControlCell? + weak var createLayerFieldDelegate:MCCreateLayerFieldDelegate? + let typeDictionary: NSDictionary = ["Checkbox": GPKG_DT_BOOLEAN, "Number": GPKG_DT_DOUBLE, "Text": GPKG_DT_TEXT] + var selectedType: GPKGDataType = GPKG_DT_TEXT + + + override func viewDidLoad() { + super.viewDidLoad() + let bounds: CGRect = self.view.bounds + let insetBounds: CGRect = CGRect.init(x: bounds.origin.x, y: bounds.origin.y + 32, width: bounds.size.width, height: bounds.size.height) + self.tableView = UITableView.init(frame: insetBounds, style: UITableView.Style.plain) + self.tableView.autoresizingMask.insert(.flexibleWidth) + self.tableView.autoresizingMask.insert(.flexibleHeight) + self.tableView.separatorStyle = .none + self.tableView.delegate = self + self.tableView.dataSource = self + self.tableView.estimatedRowHeight = 140 + self.tableView.rowHeight = UITableView.automaticDimension + self.extendedLayoutIncludesOpaqueBars = false + + + addAndConstrainSubview(self.tableView) + registerCellTypes() + initCellArray() + addDragHandle() + addCloseButton() + } + + + func registerCellTypes() { + self.tableView.register(UINib.init(nibName: "MCTitleCell", bundle: nil), forCellReuseIdentifier: "title") + self.tableView.register(UINib.init(nibName: "MCFieldWithTitleCell", bundle: nil), forCellReuseIdentifier: "fieldWithTitle") + self.tableView.register(UINib.init(nibName: "MCSegmentedControlCell", bundle: nil), forCellReuseIdentifier: "segmentedControl") + self.tableView.register(UINib.init(nibName: "MCDualButtonCell", bundle: nil), forCellReuseIdentifier: "dualButtons") + } + + + func initCellArray() { + self.cellArray.removeAll() + + let titleCell:MCTitleCell = self.tableView.dequeueReusableCell(withIdentifier: "title") as! MCTitleCell + titleCell.setLabelText("New Field") + cellArray.append(titleCell) + + self.fieldName = (self.tableView.dequeueReusableCell(withIdentifier: "fieldWithTitle") as! MCFieldWithTitleCell) + self.fieldName?.setTitleText("Name") + self.fieldName?.useReturnKeyDone() + self.fieldName?.setTextFielDelegate(self) + self.cellArray.append(self.fieldName!) + + + self.segmentedControl = (self.tableView.dequeueReusableCell(withIdentifier: "segmentedControl") as! MCSegmentedControlCell) + self.segmentedControl?.setLabelText("Type") + self.segmentedControl?.updateItems(typeDictionary.allKeys) + self.segmentedControl?.delegate = self + self.cellArray.append(self.segmentedControl!) + + self.dualButtons = (self.tableView.dequeueReusableCell(withIdentifier: "dualButtons") as! MCDualButtonCell) + self.dualButtons?.setLeftButtonLabel("Cancel") + self.dualButtons?.leftButtonAction = "cancel" + self.dualButtons?.setRightButtonLabel("Save") + self.dualButtons?.rightButtonAction = "save" + self.dualButtons?.disableRightButton() //TODO: until we have a valid field name, don't enable the button + self.dualButtons?.dualButtonDelegate = self + self.cellArray.append(dualButtons!) + } + + + override func closeDrawer() { + self.drawerViewDelegate.popDrawer() + } + + func textFieldDidEndEditing(_ textField: UITextField) { + textField.trimWhiteSpace() + + if let isValidFieldName = self.createLayerFieldDelegate?.checkFieldNameCollision(name: textField.text!) { + if (!isValidFieldName || textField.text == "") { + self.fieldName?.useErrorAppearance() + } else { + self.fieldName?.useNormalAppearance() + } + } + + textField.resignFirstResponder() + self.dualButtons?.enableRightButton() + } + + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + self.dualButtons?.enableRightButton() + return true + } + + + // MARK: UITableViewDataSource and UITableViewDelegate methods + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.cellArray.count + } + + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + return cellArray[indexPath.row] + } + + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + if (self.haveScrolled) { + rollUpPanGesture(scrollView.panGestureRecognizer, with: scrollView) + } + } + + + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.haveScrolled = true + + if (!self.isFullView) { + scrollView.isScrollEnabled = false + scrollView.isScrollEnabled = true + } else { + scrollView.isScrollEnabled = true + } + } + + func performDualButtonAction(_ action: String) { + if (action == "save") { + self.createLayerFieldDelegate?.createField(name: (self.fieldName?.fieldValue())!, type: self.selectedType) + } else if (action == "cancel") { + self.closeDrawer() + } + } + + // MARK: MCSegmentedControlCellDelegate methods + func selectionChanged(_ selection: String!) { + self.selectedType = self.typeDictionary.value(forKey: selection) as! GPKGDataType + } +} diff --git a/mapcache-ios/layer/MCLayerCoordinator.swift b/mapcache-ios/layer/MCLayerCoordinator.swift new file mode 100644 index 0000000..09c67dd --- /dev/null +++ b/mapcache-ios/layer/MCLayerCoordinator.swift @@ -0,0 +1,160 @@ +// +// MCLayerCoordinator.swift +// mapcache-ios +// +// Created by Tyler Burgett on 5/19/20. +// Copyright © 2020 NGA. All rights reserved. +// + +import UIKit + +@objc protocol MCLayerCoordinatorDelegate: AnyObject { + func layerCoordinatorCompletionHandler() +} + + +@objc class MCLayerCoordinator: NSObject, MCLayerOperationsDelegate, MCCreateLayerFieldDelegate { + var table: MCTable + var drawerViewDelegate: NGADrawerViewDelegate + var layerViewController: MCLayerViewController + var fieldViewController: MCCreateLayerFieldViewController + @objc weak var layerCoordinatorDelegate:MCLayerCoordinatorDelegate? + + @objc public init(table:MCTable, drawerDelegate:NGADrawerViewDelegate, layerCoordinatorDelegate:MCLayerCoordinatorDelegate) { + self.drawerViewDelegate = drawerDelegate + self.layerCoordinatorDelegate = layerCoordinatorDelegate + self.table = table + self.layerViewController = MCLayerViewController(asFullView: true) + self.fieldViewController = MCCreateLayerFieldViewController(asFullView: true) + super.init() + } + + + @objc public func start() { + self.layerViewController.table = self.table + self.layerViewController.delegate = self + + if (self.table is MCFeatureTable) { + self.layerViewController.columns = MCGeoPackageRepository.shared().columns(forTable: table.name, database: table.database) + } + + self.layerViewController.drawerViewDelegate = self.drawerViewDelegate + self.layerViewController.pushOntoStack() + } + + + //MARK: MCLayerOperationsDelegate + func deleteLayer() { + //TODO: fill in + print("MCLayerCoordinator deleteLayer") + } + + + func createOverlay() { + //TODO: fill in + print("MCLayerCoordinator createOverlay") + } + + + func indexLayer() { + //TODO: fill in + print("MCLayerCoordinator indexLayer") + } + + + func createTiles() { + //TODO: fill in + print("MCLayerCoordinator createTiles") + } + + + func renameLayer(_ newLayerName: String!) -> Bool { + print("MCLayerCoordinator renameLayer") + // TODO refhresh the geopackage and hand it to the view + let didUpdate:Bool = MCGeoPackageRepository.shared().renameTable(self.table, toNewName: newLayerName) + let updatedDatabase:MCDatabase = MCGeoPackageRepository.shared().databaseNamed(self.table.database) + + if let renamedTable = updatedDatabase.tableNamed(newLayerName) { + self.table = renamedTable + self.layerViewController.table = self.table + self.layerViewController.update() + NotificationCenter.default.post(name: Notification.Name("MC_LAYER_RENAMED"), object: nil) + } + + return didUpdate + } + + + func showTileScalingOptions() { + //TODO: fill in + print("MCLayerCoordinator showTileScalingOptions") + } + + + func renameColumn(_ column: GPKGUserColumn!, name: String!) { + self.layerViewController.columns = MCGeoPackageRepository.shared().renameColumn(column, newName: name, table: self.table) + let updatedDatabase:MCDatabase = MCGeoPackageRepository.shared().databaseNamed(self.table.database) + self.table = updatedDatabase.tableNamed(self.table.name) + self.layerViewController.table = self.table + self.layerViewController.update() + } + + + func delete(_ column: GPKGUserColumn!) { + MCGeoPackageRepository.shared().delete(column, table: self.table) + self.layerViewController.columns = MCGeoPackageRepository.shared().columns(forTable: self.table.name, database: self.table.database) + self.layerViewController.update() + } + + + func showFieldCreationView() { + self.fieldViewController = MCCreateLayerFieldViewController(asFullView: true) + self.fieldViewController.drawerViewDelegate = self.drawerViewDelegate + self.fieldViewController.createLayerFieldDelegate = self + self.fieldViewController.pushOntoStack() + } + + + func layerViewDidClose() { + MCGeoPackageRepository.shared().selectedLayerName = "" + } + + + func setSelectedLayerName() { + MCGeoPackageRepository.shared().selectedLayerName = self.table.name + MCGeoPackageRepository.shared().selectedGeoPackageName = self.table.database + } + + + func layerViewCompletionHandler() { + layerCoordinatorDelegate?.layerCoordinatorCompletionHandler() + } + + //MARK: MCCreateLayerFieldDelegate + func createField(name: String, type: GPKGDataType) { + if let column = GPKGFeatureColumn.createColumn(withName: name, andDataType: type) { + let didAdd = MCGeoPackageRepository.shared().add(column, to: self.table) + + if (didAdd) { + MCGeoPackageRepository.shared().refreshDatabaseAndUpdateList(self.table.database) + self.fieldViewController.closeDrawer() + self.layerViewController.columns = MCGeoPackageRepository.shared().columns(forTable: self.table.name, database: self.table.database) + self.layerViewController.update() + } + } + } + + + func checkFieldNameCollision(name: String) -> Bool { + let columns = MCGeoPackageRepository.shared().columns(forTable: self.table.name, database: self.table.database) + + for column in columns { + let c = column as! GPKGUserColumn + if (name == c.name) { + return false + } + } + + return true + } +} diff --git a/mapcache-ios/layer/MCLayerViewController.h b/mapcache-ios/layer/MCLayerViewController.h new file mode 100644 index 0000000..eae7075 --- /dev/null +++ b/mapcache-ios/layer/MCLayerViewController.h @@ -0,0 +1,56 @@ +// +// MCLayerViewController.h +// mapcache-ios +// +// Created by Tyler Burgett on 7/3/18. +// Copyright © 2018 NGA. All rights reserved. +// + +#import +#import "NGADrawerViewController.h" +#import "GPKGUserDao.h" +#import "GPKGFeatureDao.h" +#import "GPKGTileDao.h" +#import "MCFeatureTable.h" +#import "MCTileTable.h" +#import "MCButtonCell.h" +#import "MCSectionTitleCell.h" +#import "MCHeaderCell.h" +#import "MCLayerCell.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import +#import "MCFeatureLayerOperationsCell.h" +#import "MCTileLayerOperationsCell.h" +#import "MCDescriptionCell.h" +#import "MCTitleCell.h" +#import "SFPProjectionConstants.h" +#import "GPKGOverlayFactory.h" +#import "MCTable.h" +#import "MCTileTable.h" +#import "MCFeatureTable.h" + + +@protocol MCLayerOperationsDelegate +- (void) deleteLayer; +- (void) createOverlay; +- (void) indexLayer; +- (void) createTiles; +- (BOOL) renameLayer:(NSString *) newLayerName; +- (void) showTileScalingOptions; +- (void) showFieldCreationView; +- (void) layerViewDidClose; +- (void) setSelectedLayerName; +- (void) renameColumn:(GPKGUserColumn *)column name:(NSString *)name; +- (void) deleteColumn:(GPKGUserColumn *)column; +- (void) layerViewCompletionHandler; +@end + + +@interface MCLayerViewController : NGADrawerViewController +- (void) update; +@property (strong, nonatomic) GPKGUserDao *layerDao; +@property (strong, nonatomic) MCTable* table; +@property (strong, nonatomic) NSArray *columns; +@property (weak, nonatomic) id delegate; +@end diff --git a/mapcache-ios/layer/MCLayerViewController.m b/mapcache-ios/layer/MCLayerViewController.m new file mode 100644 index 0000000..6604866 --- /dev/null +++ b/mapcache-ios/layer/MCLayerViewController.m @@ -0,0 +1,475 @@ +// +// MCLayerViewController.m +// mapcache-ios +// +// Created by Tyler Burgett on 7/3/18. +// Copyright © 2018 NGA. All rights reserved. +// + +#import "MCLayerViewController.h" +#import "mapcache_ios-Swift.h" + +@interface MCLayerViewController () +@property (strong, nonatomic) NSMutableArray *cellArray; +@property (strong, nonatomic) MCFeatureTable *featureTable; +@property (strong, nonatomic) MCTileTable *tileTable; +@property (strong, nonatomic) UITableView *tableView; +@property (nonatomic) BOOL haveScrolled; +@property (nonatomic) CGFloat contentOffset; +@end + +@implementation MCLayerViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + CGRect bounds = self.view.bounds; + CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y + 32, bounds.size.width, bounds.size.height - 20); + self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.tableView.allowsMultipleSelectionDuringEditing = NO; + self.tableView.delegate = self; + self.tableView.dataSource = self; + self.tableView.estimatedRowHeight = 141.0; + self.tableView.rowHeight = UITableViewAutomaticDimension; + + [self registerCellTypes]; + [self initCellArray]; + + self.edgesForExtendedLayout = UIRectEdgeNone; + self.extendedLayoutIncludesOpaqueBars = NO; + self.automaticallyAdjustsScrollViewInsets = NO; + + UIEdgeInsets tabBarInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0); + self.tableView.contentInset = tabBarInsets; + self.tableView.scrollIndicatorInsets = tabBarInsets; + [self addAndConstrainSubview:self.tableView]; + [self addDragHandle]; + [self addCloseButton]; + self.contentOffset = 0; + self.haveScrolled = NO; +} + + +- (void) registerCellTypes { + [self.tableView registerNib:[UINib nibWithNibName:@"MCHeaderCellDisplay" bundle:nil] forCellReuseIdentifier:@"header"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCFeatureLayerOperationsCell" bundle:nil] forCellReuseIdentifier:@"featureButtons"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCTileLayerOperationsCell" bundle:nil] forCellReuseIdentifier:@"tileButtons"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCTitleCell" bundle:nil] forCellReuseIdentifier:@"title"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCDescriptionCell" bundle:nil] forCellReuseIdentifier:@"description"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCLayerCell" bundle: nil] forCellReuseIdentifier:@"layerCell"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCButtonCell" bundle: nil] forCellReuseIdentifier:@"button"]; +} + + +- (void) initCellArray { + _cellArray = [[NSMutableArray alloc] init]; + + if ([self.table isKindOfClass:MCTileTable.class]) { + self.tileTable = (MCTileTable *) self.table; + } else if ([self.table isKindOfClass:MCFeatureTable.class]) { + self.featureTable = (MCFeatureTable *) self.table; + } + + MCHeaderCell *headerCell = [self.tableView dequeueReusableCellWithIdentifier:@"header"]; + headerCell.nameLabel.text = self.table.name; + + if (_featureTable != nil) { + [headerCell setDetailLabelOneText:[NSString stringWithFormat:@"feature layer in %@", _featureTable.database]]; + [headerCell setDetailLabelTwoText:[NSString stringWithFormat:@"%d features", _featureTable.count]]; + [headerCell setDetailLabelThreeText:@""]; + [_cellArray addObject:headerCell]; + + MCFeatureLayerOperationsCell *featureButtonsCell = [self.tableView dequeueReusableCellWithIdentifier:@"featureButtons"]; + featureButtonsCell.delegate = self; + [_cellArray addObject:featureButtonsCell]; + + MCDescriptionCell *featureAddDescription = [self.tableView dequeueReusableCellWithIdentifier:@"description"]; + [featureAddDescription setDescription:@"Long press the map to add points to this layer."]; + [featureAddDescription textAlignCenter]; + [_cellArray addObject:featureAddDescription]; + + MCTitleCell *fieldsTitle = [self.tableView dequeueReusableCellWithIdentifier:@"title"]; + [fieldsTitle setLabelText:@"Fields"]; + [_cellArray addObject:fieldsTitle]; + + MCButtonCell *addFieldsButton = [self.tableView dequeueReusableCellWithIdentifier:@"button"]; + [addFieldsButton setButtonLabel:@"Add a field"]; + addFieldsButton.action = @"add-fields"; + addFieldsButton.delegate = self; + [_cellArray addObject:addFieldsButton]; + + if (self.columns.count == 2) { + // TODO add empty state + } + + for (GPKGUserColumn *column in self.columns) { + if (![column.name isEqualToString:@"id"] && ![column.name isEqualToString:@"geom"]) { + MCLayerCell *fieldCell = [self.tableView dequeueReusableCellWithIdentifier:@"layerCell"]; + [fieldCell setName:column.name]; + [fieldCell activeIndicatorOff]; + + if (column.dataType == GPKG_DT_TEXT) { + [fieldCell.layerTypeImage setImage:[UIImage imageNamed:@"text"]]; + [fieldCell setDetails:@"Text"]; + } else if (column.dataType == GPKG_DT_INTEGER || column.dataType == GPKG_DT_REAL || column.dataType == GPKG_DT_DOUBLE || column.dataType == GPKG_DT_INT || column.dataType == GPKG_DT_FLOAT || column.dataType == GPKG_DT_SMALLINT || column.dataType == GPKG_DT_TINYINT || column.dataType == GPKG_DT_MEDIUMINT) { + [fieldCell.layerTypeImage setImage:[UIImage imageNamed:@"number"]]; + [fieldCell setDetails:@"Number"]; + } else if (column.dataType == GPKG_DT_BOOLEAN) { + [fieldCell.layerTypeImage setImage:[UIImage imageNamed:@"boolean"]]; + [fieldCell setDetails:@"Checkbox"]; + } + + [_cellArray addObject:fieldCell]; + } + } + + } else if (_tileTable != nil) { + MCTileLayerOperationsCell *tileButtonsCell = [self.tableView dequeueReusableCellWithIdentifier:@"tileButtons"]; + [headerCell setDetailLabelOneText: [NSString stringWithFormat:@"tile layer in %@", _tileTable.database]]; + [headerCell setDetailLabelTwoText: [NSString stringWithFormat:@"Zoom levels %d - %d", _tileTable.minZoom, _tileTable.maxZoom]]; + [headerCell setDetailLabelThreeText:[NSString stringWithFormat:@"%d tiles", _tileTable.count]]; + tileButtonsCell.delegate = self; + _cellArray = [[NSMutableArray alloc] initWithObjects:headerCell, tileButtonsCell, nil]; + + MCTitleCell *zoomLevelsTitle = [self.tableView dequeueReusableCellWithIdentifier:@"title"]; + [zoomLevelsTitle setLabelText:@"Zoom levels"]; + [_cellArray addObject:zoomLevelsTitle]; + + for (MCTileMatrix *tileMatrix in _tileTable.tileMatrices) { + if (tileMatrix.tileCount.intValue > 0) { + MCLayerCell *tileMatricCell = [self.tableView dequeueReusableCellWithIdentifier:@"layerCell"]; + [tileMatricCell setName:[NSString stringWithFormat: @"%@ ", tileMatrix.zoomLevel]]; + NSString *tileText = tileMatrix.tileCount.intValue > 1 ? @"tiles" : @"tile"; + [tileMatricCell setDetails:[NSString stringWithFormat:@"%@ %@", tileMatrix.tileCount, tileText]]; + [tileMatricCell.layerTypeImage setImage:[UIImage imageNamed:@"ZoomLevel"]]; + [tileMatricCell activeIndicatorOff]; + [_cellArray addObject:tileMatricCell]; + } + } + } +} + + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + + +- (void) update { + [self initCellArray]; + [self.tableView reloadData]; +} + + +#pragma mark - Table view data source and delegate methods +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [_cellArray count]; +} + + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + return [_cellArray objectAtIndex:indexPath.row]; +} + + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [self.tableView deselectRowAtIndexPath:indexPath animated:NO]; +} + + +- (void) renameLayer { + NSLog(@"Renaming Layer"); + + UIAlertController *renameAlert = [UIAlertController alertControllerWithTitle:@"Rename Layer" message:@"" preferredStyle:UIAlertControllerStyleAlert]; + [renameAlert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { + [textField setText:self.table.name]; + }]; + + UIAlertAction *confirmRename = [UIAlertAction actionWithTitle:@"Rename" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + NSLog(@"New name is: %@", renameAlert.textFields[0].text); + + NSString * newName = renameAlert.textFields[0].text; + + bool validName = newName != nil && [newName length] > 0 && ![newName isEqualToString:self.table.name]; + if(validName){ + @try { + NSString *originalName = self.table.name; + + if([self.delegate renameLayer:newName]){ + [self.table setName:newName]; + [self initCellArray]; + [self.tableView reloadData]; + }else{ + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL] + andMessage:[NSString stringWithFormat:@"Rename from %@ to %@ was not successful", originalName, newName]]; + } + } + @catch (NSException *exception) { + [MCUtils showMessageWithDelegate:self + andTitle:[NSString stringWithFormat:@"Rename %@ to %@", @"OLDNAME", newName] + andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; + } + } + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [renameAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [renameAlert addAction:confirmRename]; + [renameAlert addAction:cancel]; + + [self presentViewController:renameAlert animated:YES completion:nil]; +} + + +- (void) deleteLayer { + NSLog(@"Deleting layer"); + + UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you wanbt to delete this layer? This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [self.delegate deleteLayer]; + [self dismissViewControllerAnimated:YES completion:nil]; + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [deleteAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [deleteAlert addAction:confirmDelete]; + [deleteAlert addAction:cancel]; + + [self presentViewController:deleteAlert animated:YES completion:nil]; +} + + +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + if ([[_cellArray objectAtIndex:indexPath.row] isKindOfClass:[MCLayerCell class]]) { + return YES; + } else { + return NO; + } +} + + +- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath { + + if (_tileTable != nil) { + return nil; + } + + UIContextualAction *deleteAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"Delete" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { + MCLayerCell *cell = [self.cellArray objectAtIndex:indexPath.row]; + GPKGUserColumn *columnToDelete = nil; + + for (GPKGUserColumn *column in self.columns) { + if ([cell.layerNameLabel.text isEqualToString:column.name]) { + columnToDelete = column; + } + } + + UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you want to delete this field? Data saved in this field will be lost for all points in this layer. This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + @try { + [self.delegate deleteColumn:columnToDelete]; + } + @catch (NSException *exception) { + [MCUtils showMessageWithDelegate:self + andTitle:[NSString stringWithFormat:@"Delete failed"] + andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; + } + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [deleteAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [deleteAlert addAction:confirmDelete]; + [deleteAlert addAction:cancel]; + [self presentViewController:deleteAlert animated:YES completion:nil]; + + completionHandler(YES); + }]; + + + UIContextualAction *renameAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"Rename" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { + + MCLayerCell *cell = [self.cellArray objectAtIndex:indexPath.row]; + GPKGUserColumn *columnToRename = nil; + + for (GPKGUserColumn *column in self.columns) { + if ([cell.layerNameLabel.text isEqualToString:column.name]) { + columnToRename = column; + } + } + + UIAlertController *renameAlert = [UIAlertController alertControllerWithTitle:@"Rename" message:@"" preferredStyle:UIAlertControllerStyleAlert]; + [renameAlert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { + [textField setText:cell.layerNameLabel.text]; + }]; + + UIAlertAction *confirmRename = [UIAlertAction actionWithTitle:@"Rename" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + NSLog(@"New name is: %@", renameAlert.textFields[0].text); + NSString * newName = renameAlert.textFields[0].text; + + if(newName != nil && [newName length] > 0){ + @try { + [self.delegate renameColumn:columnToRename name:newName]; + } + @catch (NSException *exception) { + [MCUtils showMessageWithDelegate:self + andTitle:[NSString stringWithFormat:@"Rename failed"] + andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; + } + } + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [renameAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [renameAlert addAction:confirmRename]; + [renameAlert addAction:cancel]; + [self presentViewController:renameAlert animated:YES completion:nil]; + + completionHandler(YES); + }]; + + + + deleteAction.backgroundColor = [UIColor redColor]; + renameAction.backgroundColor = [UIColor orangeColor]; + UISwipeActionsConfiguration *configuration = [UISwipeActionsConfiguration configurationWithActions:@[]]; + configuration.performsFirstActionWithFullSwipe = YES; + return configuration; +} + + + +#pragma mark - MCFeatureLayerOperationsCellDelegate methods +// TODO pass these up to be done in the repository +- (void) renameFeatureLayer { + NSLog(@"MCLayerOperationsDelegate editLayer"); + [self renameLayer]; +} + + +- (void) indexFeatures { + NSLog(@"MCLayerOperationsDelegate indexLayer"); + //[_delegate indexLayer]; +} + + +- (void) createTiles { + NSLog(@"MCLayerOperationsDelegate createTiles"); + //[_delegate createTiles]; +} + + +- (void) createOverlay { + NSLog(@"MCLayerOperationsDelegate createOverlay"); + //[_delegate createOverlay]; +} + + +- (void) deleteFeatureLayer { + NSLog(@"MCFeatureButtonsCellDelegate deleteLayer %@", _table.name); + [self deleteLayer]; + +} + + +#pragma mark - MCButtonCellDelegate methods +- (void)performButtonAction:(NSString *)action { + if ([action isEqualToString:@"add-fields"]) { + + NSLog(@"show create fields view"); + [_delegate showFieldCreationView]; + } +} + + +#pragma mark - MCTileButtonsDelegate methods +- (void) renameTileLayer { + NSLog(@"MCTileButtonsDelegate renameLayer"); + [self renameLayer]; +} + + +- (void) showScalingOptions { + NSLog(@"MCTileButtonsDelegate showScalingOptions"); + //[_delegate showTileScalingOptions]; +} + + +- (void) deleteTileLayer { + NSLog(@"MCTileButtonsDelegate deleteTileLayer"); + [self deleteLayer]; +} + + +- (void)closeDrawer { + [self.drawerViewDelegate popDrawer]; + [self.delegate layerViewCompletionHandler]; +} + + +- (void) drawerWasCollapsed { + [super drawerWasCollapsed]; + [self.tableView setScrollEnabled:NO]; +} + + +- (void) drawerWasMadeFull { + [super drawerWasMadeFull]; + [self.tableView setScrollEnabled:YES]; +} + + +- (void) becameTopDrawer { + [self.delegate setSelectedLayerName]; +} + + +- (BOOL)gestureIsInConflict:(UIPanGestureRecognizer *) recognizer { + CGPoint point = [recognizer locationInView:self.view]; + + if (CGRectContainsPoint(self.tableView.frame, point)) { + return true; + } + + return false; +} + + +// Override this method to make the drawer and the scrollview play nice +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.haveScrolled) { + [self rollUpPanGesture:scrollView.panGestureRecognizer withScrollView:scrollView]; + } +} + + +// If the table view is scrolling rollup the gesture to the drawer and handle accordingly. +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + self.haveScrolled = YES; + + if (!self.isFullView) { + scrollView.scrollEnabled = NO; + scrollView.scrollEnabled = YES; + } else { + scrollView.scrollEnabled = YES; + } +} + + +@end diff --git a/mapcache-ios/layer/mapcache-ios-Bridging-Header.h b/mapcache-ios/layer/mapcache-ios-Bridging-Header.h new file mode 100644 index 0000000..ed10e41 --- /dev/null +++ b/mapcache-ios/layer/mapcache-ios-Bridging-Header.h @@ -0,0 +1,33 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// +#import "geopackage-ios-Bridging-Header.h" + +#import "MCDatabase.h" +#import "MCTable.h" +#import "MCTileTable.h" +#import "MCFeatureTable.h" +#import "MCGeoPackageRepository.h" + +#import "MCLayerViewController.h" +#import "NGADrawerViewController.h" +#import "NGADrawerCoordinator.h" + +#import "MCGeoPackageCell.h" +#import "MCHeaderCell.h" +#import "MCSectionTitleCell.h" +#import "MCLayerCell.h" +#import "MCButtonCell.h" +#import "MCDualButtonCell.h" +#import "MCFieldWithTitleCell.h" +#import "MCDescriptionCell.h" +#import "MCSegmentedControlCell.h" +#import "MCZoomCell.h" +#import "MCFeatureLayerOperationsCell.h" +#import "MCGeoPackageOperationsCell.h" +#import "MCTileLayerOperationsCell.h" +#import "MCTitleCell.h" +#import "MCEmptyStateCell.h" +#import "MCTutorialCell.h" +#import "MCSwitchCell.h" +#import "MCTextViewCell.h" diff --git a/mapcache-ios/load/GPKGSLoadTilesTask.h b/mapcache-ios/load/MCLoadTilesTask.h similarity index 90% rename from mapcache-ios/load/GPKGSLoadTilesTask.h rename to mapcache-ios/load/MCLoadTilesTask.h index bb16af1..f09fea1 100644 --- a/mapcache-ios/load/GPKGSLoadTilesTask.h +++ b/mapcache-ios/load/MCLoadTilesTask.h @@ -9,14 +9,14 @@ #import #import "GPKGProgress.h" #import "GPKGSLoadTilesProtocol.h" -#import "GPKGSDatabases.h" +#import "MCDatabases.h" #import "GPKGCompressFormats.h" #import "GPKGBoundingBox.h" #import "GPKGGeoPackage.h" #import "GPKGFeatureTiles.h" #import "GPKGTileScaling.h" -@interface GPKGSLoadTilesTask : NSObject +@interface MCLoadTilesTask : NSObject +(void) loadTilesWithCallback: (NSObject *) callback andDatabase: (NSString *) database @@ -27,7 +27,7 @@ andCompressFormat: (enum GPKGCompressFormat) compressFormat andCompressQuality: (int) compressQuality andCompressScale: (int) compressScale - andStandardFormat: (BOOL) standardWebMercatorFormat + andXyzTiles: (BOOL) xyzTiles andBoundingBox: (GPKGBoundingBox *) boundingBox andTileScaling: (GPKGTileScaling *) scaling andAuthority: (NSString *) authority @@ -43,7 +43,7 @@ andCompressFormat: (enum GPKGCompressFormat) compressFormat andCompressQuality: (int) compressQuality andCompressScale: (int) compressScale - andStandardFormat: (BOOL) standardWebMercatorFormat + andXyzTiles: (BOOL) xyzTiles andBoundingBox: (GPKGBoundingBox *) boundingBox andTileScaling: (GPKGTileScaling *) scaling andAuthority: (NSString *) authority diff --git a/mapcache-ios/load/GPKGSLoadTilesTask.m b/mapcache-ios/load/MCLoadTilesTask.m similarity index 89% rename from mapcache-ios/load/GPKGSLoadTilesTask.m rename to mapcache-ios/load/MCLoadTilesTask.m index 41f6923..4d25e36 100644 --- a/mapcache-ios/load/GPKGSLoadTilesTask.m +++ b/mapcache-ios/load/MCLoadTilesTask.m @@ -6,20 +6,20 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSLoadTilesTask.h" +#import "MCLoadTilesTask.h" #import "GPKGTileGenerator.h" #import "GPKGGeoPackageFactory.h" #import "GPKGUrlTileGenerator.h" #import "GPKGFeatureTileGenerator.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" #import "SFPProjectionFactory.h" #import "SFPProjectionTransform.h" #import "SFPProjectionConstants.h" #import "GPKGTileBoundingBoxUtils.h" -@interface GPKGSLoadTilesTask () +@interface MCLoadTilesTask () @property (nonatomic, strong) NSNumber *maxTiles; @property (nonatomic) int progress; @@ -32,7 +32,7 @@ @interface GPKGSLoadTilesTask () @end -@implementation GPKGSLoadTilesTask +@implementation MCLoadTilesTask +(void) loadTilesWithCallback: (NSObject *) callback andDatabase: (NSString *) database @@ -43,17 +43,19 @@ +(void) loadTilesWithCallback: (NSObject *) callback andCompressFormat: (enum GPKGCompressFormat) compressFormat andCompressQuality: (int) compressQuality andCompressScale: (int) compressScale - andStandardFormat: (BOOL) standardWebMercatorFormat + andXyzTiles: (BOOL) xyzTiles andBoundingBox: (GPKGBoundingBox *) boundingBox andTileScaling: (GPKGTileScaling *) scaling andAuthority: (NSString *) authority andCode: (NSString *) code andLabel: (NSString *) label{ - GPKGGeoPackageManager *manager = [GPKGGeoPackageFactory getManager]; + GPKGGeoPackageManager *manager = [GPKGGeoPackageFactory manager]; GPKGGeoPackage * geoPackage = nil; @try { geoPackage = [manager open:database]; + } @catch(NSException *e) { + NSLog(@"---------- MCLoadTilesTask - Problem downloading tiles\n%@", e.reason); } @finally { [manager close]; @@ -63,7 +65,7 @@ +(void) loadTilesWithCallback: (NSObject *) callback GPKGBoundingBox * bbox = [self transformBoundingBox:boundingBox withProjection:projection]; GPKGTileGenerator * tileGenerator = [[GPKGUrlTileGenerator alloc] initWithGeoPackage:geoPackage andTableName:tableName andTileUrl:tileUrl andMinZoom:minZoom andMaxZoom:maxZoom andBoundingBox:bbox andProjection:projection]; - [self setTileGenerator:tileGenerator withMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:compressFormat andCompressQuality:compressQuality andCompressScale:compressScale andStandardFormat:standardWebMercatorFormat andBoundingBox:boundingBox andTileScaling:scaling]; + [self setTileGenerator:tileGenerator withMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:compressFormat andCompressQuality:compressQuality andCompressScale:compressScale andXyzTiles:xyzTiles andBoundingBox:boundingBox andTileScaling:scaling]; [self loadTilesWithCallback:callback andGeoPackage:geoPackage andTable:tableName andTileGenerator:tileGenerator andLabel:label]; } @@ -77,7 +79,7 @@ +(void) loadTilesWithCallback: (NSObject *) callback andCompressFormat: (enum GPKGCompressFormat) compressFormat andCompressQuality: (int) compressQuality andCompressScale: (int) compressScale - andStandardFormat: (BOOL) standardWebMercatorFormat + andXyzTiles: (BOOL) xyzTiles andBoundingBox: (GPKGBoundingBox *) boundingBox andTileScaling: (GPKGTileScaling *) scaling andAuthority: (NSString *) authority @@ -88,7 +90,7 @@ +(void) loadTilesWithCallback: (NSObject *) callback GPKGBoundingBox * bbox = [self transformBoundingBox:boundingBox withProjection:projection]; GPKGTileGenerator * tileGenerator = [[GPKGFeatureTileGenerator alloc] initWithGeoPackage:geoPackage andTableName:tableName andFeatureTiles:featureTiles andMinZoom:minZoom andMaxZoom:maxZoom andBoundingBox:bbox andProjection:projection]; - [self setTileGenerator:tileGenerator withMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:compressFormat andCompressQuality:compressQuality andCompressScale:compressScale andStandardFormat:standardWebMercatorFormat andBoundingBox:boundingBox andTileScaling:scaling]; + [self setTileGenerator:tileGenerator withMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:compressFormat andCompressQuality:compressQuality andCompressScale:compressScale andXyzTiles:xyzTiles andBoundingBox:boundingBox andTileScaling:scaling]; [self loadTilesWithCallback:callback andGeoPackage:geoPackage andTable:tableName andTileGenerator:tileGenerator andLabel:label]; } @@ -112,7 +114,7 @@ +(void) setTileGenerator: (GPKGTileGenerator *) tileGenerator andCompressFormat: (enum GPKGCompressFormat) compressFormat andCompressQuality: (int) compressQuality andCompressScale: (int) compressScale - andStandardFormat: (BOOL) standardWebMercatorFormat + andXyzTiles: (BOOL) xyzTiles andBoundingBox: (GPKGBoundingBox *) boundingBox andTileScaling: (GPKGTileScaling *) scaling{ @@ -123,13 +125,13 @@ +(void) setTileGenerator: (GPKGTileGenerator *) tileGenerator [tileGenerator setCompressFormat:compressFormat]; [tileGenerator setCompressQualityAsIntPercentage:compressQuality]; [tileGenerator setCompressScaleAsIntPercentage:compressScale]; - [tileGenerator setStandardWebMercatorFormat:standardWebMercatorFormat]; + [tileGenerator setXyzTiles:xyzTiles]; [tileGenerator setScaling:scaling]; } +(void) loadTilesWithCallback:(NSObject *)callback andGeoPackage:(GPKGGeoPackage *)geoPackage andTable:(NSString *)tableName andTileGenerator: (GPKGTileGenerator *) tileGenerator andLabel: (NSString *) label{ - GPKGSLoadTilesTask * loadTilesTask = [[GPKGSLoadTilesTask alloc] initWithCallback:callback]; + MCLoadTilesTask * loadTilesTask = [[MCLoadTilesTask alloc] initWithCallback:callback]; [tileGenerator setProgress:loadTilesTask]; @@ -139,9 +141,9 @@ +(void) loadTilesWithCallback:(NSObject *)callback andGe initWithTitle:[NSString stringWithFormat:@"%@ for %@ into layer: %@", label, geoPackage.name, tableName] message:@"" delegate:loadTilesTask - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_STOP_LABEL] + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_STOP_LABEL] otherButtonTitles:nil]; - UIProgressView *progressView = [GPKGSUtils buildProgressBarView]; + UIProgressView *progressView = [MCUtils buildProgressBarView]; [alertView setValue:progressView forKey:@"accessoryView"]; loadTilesTask.alertView = alertView; diff --git a/mapcache-ios/manager/GPKGSActiveTableSwitch.h b/mapcache-ios/manager/GPKGSActiveTableSwitch.h index c0d6031..8b2dcb7 100644 --- a/mapcache-ios/manager/GPKGSActiveTableSwitch.h +++ b/mapcache-ios/manager/GPKGSActiveTableSwitch.h @@ -7,10 +7,10 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" @interface GPKGSActiveTableSwitch : UISwitch -@property (nonatomic, strong) GPKGSTable * table; +@property (nonatomic, strong) MCTable * table; @end diff --git a/mapcache-ios/manager/GPKGSAddTileOverlayViewController.h b/mapcache-ios/manager/GPKGSAddTileOverlayViewController.h index 391f1f5..b2db8cb 100644 --- a/mapcache-ios/manager/GPKGSAddTileOverlayViewController.h +++ b/mapcache-ios/manager/GPKGSAddTileOverlayViewController.h @@ -7,21 +7,21 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGGeoPackageManager.h" -#import "GPKGSFeatureOverlayTable.h" +#import "MCFeatureOverlayTable.h" @class GPKGSAddTileOverlayViewController; @protocol GPKGSAddTileOverlayDelegate -- (void)addTileOverlayViewController:(GPKGSAddTileOverlayViewController *)controller featureOverlayTable:(GPKGSFeatureOverlayTable *)featureOverlayTable; +- (void)addTileOverlayViewController:(GPKGSAddTileOverlayViewController *)controller featureOverlayTable:(MCFeatureOverlayTable *)featureOverlayTable; @end @interface GPKGSAddTileOverlayViewController : UIViewController @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; @property (weak, nonatomic) IBOutlet UITextField *databaseValue; @property (weak, nonatomic) IBOutlet UITextField *nameValue; diff --git a/mapcache-ios/manager/GPKGSAddTileOverlayViewController.m b/mapcache-ios/manager/GPKGSAddTileOverlayViewController.m index bbd5535..6f15e74 100644 --- a/mapcache-ios/manager/GPKGSAddTileOverlayViewController.m +++ b/mapcache-ios/manager/GPKGSAddTileOverlayViewController.m @@ -8,11 +8,11 @@ #import "GPKGSAddTileOverlayViewController.h" #import "GPKGSEditTileOverlayData.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCUtils.h" #import "GPKGSEditTileOverlayViewController.h" -#import "GPKGSFeatureOverlayTable.h" +#import "MCFeatureOverlayTable.h" #import "GPKGFeatureIndexManager.h" NSString * const GPKGS_ADD_TILE_OVERLAY_SEG_EDIT_TILE_OVERLAY = @"editTileOverlay"; @@ -31,9 +31,9 @@ - (void)viewDidLoad { [self.databaseValue setText:self.table.database]; // Set a default name - [self.nameValue setText:[NSString stringWithFormat:@"%@%@", self.table.name, [GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_OVERLAY_TILES_NAME_SUFFIX]]]; + [self.nameValue setText:[NSString stringWithFormat:@"%@%@", self.table.name, [MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_OVERLAY_TILES_NAME_SUFFIX]]]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.nameValue.inputAccessoryView = keyboardToolbar; } @@ -48,7 +48,7 @@ - (IBAction)cancelButton:(id)sender { - (IBAction)addButton:(id)sender { - GPKGSFeatureOverlayTable * overlayTable = [[GPKGSFeatureOverlayTable alloc] initWithDatabase:self.table.database andName:self.nameValue.text andFeatureTable:self.table.name andGeometryType:SF_NONE andCount:0]; + MCFeatureOverlayTable * overlayTable = [[MCFeatureOverlayTable alloc] initWithDatabase:self.table.database andName:self.nameValue.text andFeatureTable:self.table.name andGeometryType:SF_NONE andCount:0]; [overlayTable setMinZoom:[self.editTileOverlayData.minZoom intValue]]; [overlayTable setMaxZoom:[self.editTileOverlayData.maxZoom intValue]]; @@ -95,10 +95,10 @@ -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ GPKGGeoPackage * geoPackage = [self.manager open:self.table.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.table.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:self.table.name]; // Set the min zoom level - [self.editTileOverlayData setMinZoom:[NSNumber numberWithInt:[featureDao getZoomLevel]]]; + [self.editTileOverlayData setMinZoom:[NSNumber numberWithInt:[featureDao zoomLevel]]]; // Check if indexed GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @@ -108,12 +108,12 @@ -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ // Only default the max features if indexed, otherwise an unindexed feature table will // not show any tiles with features NSNumber * maxFeatures = nil; - switch([featureDao getGeometryType]){ + switch([featureDao geometryType]){ case SF_POINT: - maxFeatures = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_FEATURE_TILES_OVERLAY_MAX_POINTS_PER_TILE_DEFAULT]; + maxFeatures = [MCProperties getNumberValueOfProperty:GPKGS_PROP_FEATURE_TILES_OVERLAY_MAX_POINTS_PER_TILE_DEFAULT]; break; default: - maxFeatures = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_FEATURE_TILES_OVERLAY_MAX_FEATURES_PER_TILE_DEFAULT]; + maxFeatures = [MCProperties getNumberValueOfProperty:GPKGS_PROP_FEATURE_TILES_OVERLAY_MAX_FEATURES_PER_TILE_DEFAULT]; break; } [self.editTileOverlayData setMaxFeaturesPerTile:maxFeatures]; diff --git a/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.h b/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.h index d93f12a..1829c4b 100644 --- a/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.h +++ b/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGGeoPackageManager.h" #import "GPKGSGenerateTilesData.h" #import "GPKGSFeatureTilesDrawData.h" diff --git a/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.m b/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.m index 47507cc..c551aef 100644 --- a/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.m +++ b/mapcache-ios/manager/GPKGSCreateFeatureTilesViewController.m @@ -9,13 +9,13 @@ #import "GPKGSCreateFeatureTilesViewController.h" #import "GPKGSGenerateTilesViewController.h" #import "GPKGSFeatureTilesDrawViewController.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCProperties.h" +#import "MCConstants.h" #import "SFPProjectionTransform.h" #import "SFPProjectionConstants.h" #import "GPKGTileBoundingBoxUtils.h" -#import "GPKGSLoadTilesTask.h" -#import "GPKGSUtils.h" +#import "MCLoadTilesTask.h" +#import "MCUtils.h" #import "SFPProjectionFactory.h" #import "GPKGNumberFeaturesTile.h" @@ -38,15 +38,15 @@ - (void)viewDidLoad { // Check if indexed GPKGGeoPackage * geoPackage = [self.manager open:self.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:self.name]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @try{ self.indexed = [indexer isIndexed]; if(self.indexed){ - [self.warningLabel setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_INDEX_VALIDATION]]; + [self.warningLabel setText:[MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_INDEX_VALIDATION]]; [self.warningLabel setTextColor:[UIColor greenColor]]; }else{ - [self.warningLabel setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_INDEX_WARNING]]; + [self.warningLabel setText:[MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_INDEX_WARNING]]; } }@finally{ [indexer close]; @@ -57,9 +57,9 @@ - (void)viewDidLoad { } // Set a default name - [self.nameValue setText:[NSString stringWithFormat:@"%@%@", self.name, [GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_NAME_SUFFIX]]]; + [self.nameValue setText:[NSString stringWithFormat:@"%@%@", self.name, [MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_NAME_SUFFIX]]]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.nameValue.inputAccessoryView = keyboardToolbar; } @@ -104,7 +104,7 @@ - (IBAction)createButton:(id)sender { } GPKGGeoPackage * geoPackage = [self.manager open:self.database]; - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:self.name]; // Load tiles GPKGFeatureTiles * featureTiles = [[GPKGFeatureTiles alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @@ -144,9 +144,9 @@ - (IBAction)createButton:(id)sender { [featureTiles calculateDrawOverlap]; - GPKGTileScaling *scaling = [GPKGSLoadTilesTask tileScaling]; - - [GPKGSLoadTilesTask loadTilesWithCallback:self andGeoPackage:geoPackage andTable:tableName andFeatureTiles:featureTiles andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andStandardFormat:generateTiles.standardWebMercatorFormat andBoundingBox:boundingBox andTileScaling:scaling andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",PROJ_EPSG_WEB_MERCATOR] andLabel:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL]]; + GPKGTileScaling *scaling = [MCLoadTilesTask tileScaling]; + [MCLoadTilesTask loadTilesWithCallback:self andGeoPackage:geoPackage andTable:tableName andFeatureTiles:featureTiles andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andXyzTiles:generateTiles.xyzTiles andBoundingBox:boundingBox andTileScaling:scaling andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",PROJ_EPSG_WEB_MERCATOR] andLabel:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL]]; + } @catch (NSException *e) { @@ -174,7 +174,7 @@ -(void)setGenerateTilesFields{ GPKGGeoPackage * geoPackage = [self.manager open:self.database]; @try { - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; GPKGContents * contents = (GPKGContents *)[contentsDao queryForIdObject:self.name]; if(contents != nil){ @@ -185,12 +185,12 @@ -(void)setGenerateTilesFields{ boundingBox = self.generateTilesData.boundingBox; projection = [SFPProjectionFactory projectionWithEpsgInt: PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; }else{ - boundingBox = [contents getBoundingBox]; + boundingBox = [contents boundingBox]; if(boundingBox == nil){ boundingBox = [[GPKGBoundingBox alloc] initWithMinLongitudeDouble:-PROJ_WGS84_HALF_WORLD_LON_WIDTH andMinLatitudeDouble:PROJ_WEB_MERCATOR_MIN_LAT_RANGE andMaxLongitudeDouble:PROJ_WGS84_HALF_WORLD_LON_WIDTH andMaxLatitudeDouble:PROJ_WEB_MERCATOR_MAX_LAT_RANGE]; projection = [SFPProjectionFactory projectionWithEpsgInt: PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; }else{ - projection = [contentsDao getProjection:contents]; + projection = [contentsDao projection:contents]; } } @@ -201,20 +201,21 @@ -(void)setGenerateTilesFields{ webMercatorBoundingBox = [boundingBox transform:webMercatorTransform]; // Try to find a good zoom starting point - int zoomLevel = [GPKGTileBoundingBoxUtils getZoomLevelWithWebMercatorBoundingBox:webMercatorBoundingBox]; - int maxZoomLevel = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT] intValue]; + int zoomLevel = [GPKGTileBoundingBoxUtils zoomLevelWithWebMercatorBoundingBox:webMercatorBoundingBox]; + int maxZoomLevel = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT] intValue]; + zoomLevel = MAX(0, MIN(zoomLevel, maxZoomLevel - 1)); self.generateTilesData.minZoom = [NSNumber numberWithInt:zoomLevel]; self.generateTilesData.maxZoom = [NSNumber numberWithInt:maxZoomLevel]; // Check if indexed and set max features - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:self.name]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @try{ BOOL indexed = [indexer isIndexed]; self.generateTilesData.supportsMaxFeatures = true; if(indexed){ - NSNumber * maxFeaturesPerTile = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_FEATURE_TILES_LOAD_MAX_FEATURES_PER_TILE_DEFAULT]; + NSNumber * maxFeaturesPerTile = [MCProperties getNumberValueOfProperty:GPKGS_PROP_FEATURE_TILES_LOAD_MAX_FEATURES_PER_TILE_DEFAULT]; if([maxFeaturesPerTile intValue] >= 0){ self.generateTilesData.maxFeaturesPerTile = maxFeaturesPerTile; } diff --git a/mapcache-ios/manager/GPKGSCreateFeaturesViewController.h b/mapcache-ios/manager/GPKGSCreateFeaturesViewController.h index 11f4f56..469e6ce 100644 --- a/mapcache-ios/manager/GPKGSCreateFeaturesViewController.h +++ b/mapcache-ios/manager/GPKGSCreateFeaturesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSDatabase.h" +#import "MCDatabase.h" #import "GPKGGeoPackageManager.h" #import "GPKGSBoundingBoxViewController.h" @@ -21,7 +21,7 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSDatabase *database; +@property (nonatomic, strong) MCDatabase *database; @property (weak, nonatomic) IBOutlet UITextField *databaseValue; @property (weak, nonatomic) IBOutlet UITextField *nameValue; @property (weak, nonatomic) IBOutlet UIButton *geometryTypeButton; diff --git a/mapcache-ios/manager/GPKGSCreateFeaturesViewController.m b/mapcache-ios/manager/GPKGSCreateFeaturesViewController.m index 20b4224..c2fa921 100644 --- a/mapcache-ios/manager/GPKGSCreateFeaturesViewController.m +++ b/mapcache-ios/manager/GPKGSCreateFeaturesViewController.m @@ -7,13 +7,13 @@ // #import "GPKGSCreateFeaturesViewController.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSDecimalValidator.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCDecimalValidator.h" #import "GPKGGeoPackage.h" #import "SFPProjectionConstants.h" #import "GPKGSBoundingBoxViewController.h" -#import "GPKGSUtils.h" +#import "MCUtils.h" NSString * const GPKGS_CREATE_FEATURES_SEG_BOUNDING_BOX = @"boundingBox"; @@ -33,10 +33,10 @@ - (void)viewDidLoad { [super viewDidLoad]; [self.databaseValue setText:self.database.name]; - self.geometryTypes = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES]; + self.geometryTypes = [MCProperties getArrayOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES]; [self.geometryTypeButton setTitle:[self.geometryTypes objectAtIndex:0] forState:UIControlStateNormal]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.nameValue.inputAccessoryView = keyboardToolbar; } @@ -115,7 +115,7 @@ -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)button - (IBAction)geometryType:(id)sender { UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPE_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPE_LABEL] message:nil delegate:self cancelButtonTitle:nil @@ -124,7 +124,7 @@ - (IBAction)geometryType:(id)sender { for (NSString *geometryType in self.geometryTypes) { [alert addButtonWithTitle:geometryType]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_GEOMETRY_TYPES; diff --git a/mapcache-ios/manager/GPKGSDatabaseOptionsButton.h b/mapcache-ios/manager/GPKGSDatabaseOptionsButton.h index 6a15f56..6324771 100644 --- a/mapcache-ios/manager/GPKGSDatabaseOptionsButton.h +++ b/mapcache-ios/manager/GPKGSDatabaseOptionsButton.h @@ -7,11 +7,11 @@ // #import -#import "GPKGSDatabase.h" +#import "MCDatabase.h" @interface GPKGSDatabaseOptionsButton : UIButton -@property (nonatomic, strong) GPKGSDatabase * database; +@property (nonatomic, strong) MCDatabase * database; @end diff --git a/mapcache-ios/manager/GPKGSDisplayTextViewController.h b/mapcache-ios/manager/GPKGSDisplayTextViewController.h index fae5d2d..72a6d86 100644 --- a/mapcache-ios/manager/GPKGSDisplayTextViewController.h +++ b/mapcache-ios/manager/GPKGSDisplayTextViewController.h @@ -7,8 +7,8 @@ // #import -#import "GPKGSTable.h" -#import "GPKGSDatabase.h" +#import "MCTable.h" +#import "MCDatabase.h" #import @interface GPKGSDisplayTextViewController : UIViewController @@ -16,7 +16,7 @@ @property (weak, nonatomic) IBOutlet UIButton *titleButton; @property (weak, nonatomic) IBOutlet UITextView *textView; @property (nonatomic, strong) GPKGMapPoint *mapPoint; -@property (nonatomic, strong) GPKGSDatabase * database; -@property (nonatomic, strong) GPKGSTable * table; +@property (nonatomic, strong) MCDatabase * database; +@property (nonatomic, strong) MCTable * table; @end diff --git a/mapcache-ios/manager/GPKGSDisplayTextViewController.m b/mapcache-ios/manager/GPKGSDisplayTextViewController.m index ced5339..87488f2 100644 --- a/mapcache-ios/manager/GPKGSDisplayTextViewController.m +++ b/mapcache-ios/manager/GPKGSDisplayTextViewController.m @@ -10,11 +10,11 @@ #import "GPKGSMapPointData.h" #import #import -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" #import "SFGeometryPrinter.h" -#import "GPKGSFeatureOverlayTable.h" +#import "MCFeatureOverlayTable.h" @interface GPKGSDisplayTextViewController () @@ -26,7 +26,7 @@ @implementation GPKGSDisplayTextViewController - (void)viewDidLoad { [super viewDidLoad]; - self.manager = [GPKGGeoPackageFactory getManager]; + self.manager = [GPKGGeoPackageFactory manager]; if (self.mapPoint) { [self.titleButton setTitle:[self getTitleAndSubtitleWithMapPoint:self.mapPoint andDelimiter:@" "] forState:UIControlStateNormal]; @@ -79,20 +79,20 @@ -(GPKGSMapPointData *) getOrCreateDataWithMapPoint: (GPKGMapPoint *) mapPoint{ return (GPKGSMapPointData *) mapPoint.data; } --(NSString *) buildTextForDatabase: (GPKGSDatabase *) database{ +-(NSString *) buildTextForDatabase: (MCDatabase *) database{ NSMutableString * info = [[NSMutableString alloc] init]; GPKGGeoPackage * geoPackage = [self.manager open:database.name]; @try { - GPKGSpatialReferenceSystemDao * srsDao = [geoPackage getSpatialReferenceSystemDao]; + GPKGSpatialReferenceSystemDao * srsDao = [geoPackage spatialReferenceSystemDao]; [info appendFormat:@"Size: %@", [self.manager readableSize:database.name]]; [info appendFormat:@"\n\nPath: %@", [self.manager pathForDatabase:database.name]]; [info appendFormat:@"\nDocuments Path: %@", [self.manager documentsPathForDatabase:database.name]]; - [info appendFormat:@"\n\nFeature Tables: %d", [geoPackage getFeatureTableCount]]; - [info appendFormat:@"\nTile Tables: %d", [geoPackage getTileTableCount]]; + [info appendFormat:@"\n\nFeature Tables: %d", [geoPackage featureTableCount]]; + [info appendFormat:@"\nTile Tables: %d", [geoPackage tileTableCount]]; GPKGResultSet * results = [srsDao queryForAll]; [info appendFormat:@"\nSpatial Reference Systems: %d", [results count]]; while([results moveToNext]){ - GPKGSpatialReferenceSystem * srs = (GPKGSpatialReferenceSystem *)[srsDao getObject:results]; + GPKGSpatialReferenceSystem * srs = (GPKGSpatialReferenceSystem *)[srsDao object:results]; [info appendString:@"\n"]; [self addSrsToInfoString:info withSrs:srs]; } @@ -106,7 +106,7 @@ -(NSString *) buildTextForDatabase: (GPKGSDatabase *) database{ return info; } --(NSString *) buildTextForTable: (GPKGSTable *) table{ +-(NSString *) buildTextForTable: (MCTable *) table{ NSMutableString * info = [[NSMutableString alloc] init]; GPKGGeoPackage * geoPackage = [self.manager open:table.database]; @try { @@ -118,12 +118,12 @@ -(NSString *) buildTextForTable: (GPKGSTable *) table{ switch([table getType]){ case GPKGS_TT_FEATURE_OVERLAY: - tableName = ((GPKGSFeatureOverlayTable *) table).featureTable; + tableName = ((MCFeatureOverlayTable *) table).featureTable; case GPKGS_TT_FEATURE: { - featureDao = [geoPackage getFeatureDaoWithTableName:tableName]; - GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage getGeometryColumnsDao]; - contents = [geometryColumnsDao getContents:featureDao.geometryColumns]; + featureDao = [geoPackage featureDaoWithTableName:tableName]; + GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage geometryColumnsDao]; + contents = [geometryColumnsDao contents:featureDao.geometryColumns]; [info appendString:@"Feature Table"]; [info appendFormat:@"\nFeatures: %d", [featureDao count]]; userTable = featureDao.table; @@ -131,9 +131,9 @@ -(NSString *) buildTextForTable: (GPKGSTable *) table{ break; case GPKGS_TT_TILE: { - tileDao = [geoPackage getTileDaoWithTableName:tableName]; - GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - contents = [tileMatrixSetDao getContents:tileDao.tileMatrixSet]; + tileDao = [geoPackage tileDaoWithTableName:tableName]; + GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage tileMatrixSetDao]; + contents = [tileMatrixSetDao contents:tileDao.tileMatrixSet]; [info appendString:@"Tile Table"]; [info appendFormat:@"\nZoom Levels: %lu", (unsigned long)[tileDao.tileMatrices count]]; [info appendFormat:@"\nTiles: %d", [tileDao count]]; @@ -144,8 +144,8 @@ -(NSString *) buildTextForTable: (GPKGSTable *) table{ [NSException raise:@"Unsupported" format:@"Unsupported table type: %d", [table getType]]; } - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; - GPKGSpatialReferenceSystem * srs = [contentsDao getSrs:contents]; + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; + GPKGSpatialReferenceSystem * srs = [contentsDao srs:contents]; [info appendString:@"\n\nSpatial Reference System:"]; [self addSrsToInfoString:info withSrs:srs]; @@ -174,8 +174,8 @@ -(NSString *) buildTextForTable: (GPKGSTable *) table{ if(tileDao != nil){ GPKGTileMatrixSet * tileMatrixSet = tileDao.tileMatrixSet; - GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - GPKGSpatialReferenceSystem * tileMatrixSetSrs = [tileMatrixSetDao getSrs:tileMatrixSet]; + GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage tileMatrixSetDao]; + GPKGSpatialReferenceSystem * tileMatrixSetSrs = [tileMatrixSetDao srs:tileMatrixSet]; if(![tileMatrixSetSrs.srsId isEqualToNumber:srs.srsId]){ [info appendString:@"\n\nTile Matrix Set Spatial Reference System:"]; [self addSrsToInfoString:info withSrs:tileMatrixSetSrs]; @@ -203,7 +203,7 @@ -(NSString *) buildTextForTable: (GPKGSTable *) table{ } [info appendFormat:@"\n\n%@ columns:", tableName]; - GPKGDataColumnsDao *dataColumnsDao = [geoPackage getDataColumnsDao]; + GPKGDataColumnsDao *dataColumnsDao = [geoPackage dataColumnsDao]; for(GPKGUserColumn * userColumn in userTable.columns){ [info appendFormat:@"\n\nIndex: %d", userColumn.index]; [info appendFormat:@"\nName: %@", userColumn.name]; @@ -218,7 +218,7 @@ -(NSString *) buildTextForTable: (GPKGSTable *) table{ [info appendFormat:@"\nPrimary Key: %d", userColumn.primaryKey]; } [info appendFormat:@"\nType: %@", userColumn.type]; - GPKGDataColumns * dataColumn = [dataColumnsDao getDataColumnByTableName:tableName andColumnName:userColumn.name]; + GPKGDataColumns * dataColumn = [dataColumnsDao dataColumnByTableName:tableName andColumnName:userColumn.name]; if (dataColumn) { [info appendFormat: @"\nData Column Information:"]; if ([dataColumn name]) { @@ -265,14 +265,14 @@ -(NSString *) buildInfoForExistingFeatureMapPoint: (GPKGMapPoint *) mapPoint{ GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - self.manager = [GPKGGeoPackageFactory getManager]; + self.manager = [GPKGGeoPackageFactory manager]; GPKGGeoPackage * geoPackage = [self.manager open:data.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:data.tableName]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:data.tableName]; - GPKGDataColumnsDao * dataColumnsDao = [geoPackage getDataColumnsDao]; + GPKGDataColumnsDao * dataColumnsDao = [geoPackage dataColumnsDao]; NSNumber * featureId = [NSNumber numberWithInt:data.featureId]; if(featureId != nil){ @@ -280,13 +280,13 @@ -(NSString *) buildInfoForExistingFeatureMapPoint: (GPKGMapPoint *) mapPoint{ if(featureRow != nil){ - int geometryColumn = [featureRow getGeometryColumnIndex]; + int geometryColumn = [featureRow geometryColumnIndex]; for(int i = 0; i < featureRow.columnCount; i++){ if(i != geometryColumn){ - NSObject * value = [featureRow getValueWithIndex:i]; + NSObject * value = [featureRow valueWithIndex:i]; if(value != nil){ - GPKGDataColumns * dataColumn = [dataColumnsDao getDataColumnByTableName:data.tableName andColumnName:[featureRow getColumnWithIndex:i].name]; - NSString *columnName = [featureRow getColumnWithIndex:i].name; + GPKGDataColumns * dataColumn = [dataColumnsDao dataColumnByTableName:data.tableName andColumnName:[featureRow columnWithIndex:i].name]; + NSString *columnName = [featureRow columnWithIndex:i].name; if (dataColumn) { columnName = dataColumn.name; } @@ -295,7 +295,7 @@ -(NSString *) buildInfoForExistingFeatureMapPoint: (GPKGMapPoint *) mapPoint{ } } - GPKGGeometryData * geomData = [featureRow getGeometry]; + GPKGGeometryData * geomData = [featureRow geometry]; if(geomData != nil){ SFGeometry * geometry = geomData.geometry; if(geometry != nil){ @@ -312,8 +312,8 @@ -(NSString *) buildInfoForExistingFeatureMapPoint: (GPKGMapPoint *) mapPoint{ } @catch (NSException *e) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL] andMessage:[NSString stringWithFormat:@"%@", [e description]]]; } @finally { diff --git a/mapcache-ios/manager/GPKGSEditFeaturesViewController.h b/mapcache-ios/manager/GPKGSEditFeaturesViewController.h index 0595652..ea1662d 100644 --- a/mapcache-ios/manager/GPKGSEditFeaturesViewController.h +++ b/mapcache-ios/manager/GPKGSEditFeaturesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGGeoPackageManager.h" #import "GPKGSEditContentsData.h" @@ -21,7 +21,7 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; @property (weak, nonatomic) IBOutlet UIButton *geometryTypeButton; @property (weak, nonatomic) IBOutlet UITextField *zTextField; @property (weak, nonatomic) IBOutlet UITextField *mTextField; diff --git a/mapcache-ios/manager/GPKGSEditFeaturesViewController.m b/mapcache-ios/manager/GPKGSEditFeaturesViewController.m index 4cb6a43..7fdf539 100644 --- a/mapcache-ios/manager/GPKGSEditFeaturesViewController.m +++ b/mapcache-ios/manager/GPKGSEditFeaturesViewController.m @@ -8,17 +8,17 @@ #import "GPKGSEditFeaturesViewController.h" #import "GPKGSEditContentsViewController.h" -#import "GPKGSUtils.h" -#import "GPKGSDecimalValidator.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCUtils.h" +#import "MCDecimalValidator.h" +#import "MCProperties.h" +#import "MCConstants.h" NSString * const GPKGS_MANAGER_EDIT_FEATURES_SEG_EDIT_CONTENTS = @"editContents"; @interface GPKGSEditFeaturesViewController () @property (nonatomic, strong) GPKGSEditContentsData *data; -@property (nonatomic, strong) GPKGSDecimalValidator * zAndMValidator; +@property (nonatomic, strong) MCDecimalValidator * zAndMValidator; @property (nonatomic, strong) NSArray * geometryTypes; @end @@ -30,13 +30,13 @@ @implementation GPKGSEditFeaturesViewController - (void)viewDidLoad { [super viewDidLoad]; - self.geometryTypes = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES]; + self.geometryTypes = [MCProperties getArrayOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPES]; - self.zAndMValidator = [[GPKGSDecimalValidator alloc] initWithMinimumInt:0 andMaximumInt:2]; + self.zAndMValidator = [[MCDecimalValidator alloc] initWithMinimumInt:0 andMaximumInt:2]; [self.zTextField setDelegate:self.zAndMValidator]; [self.mTextField setDelegate:self.zAndMValidator]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.zTextField.inputAccessoryView = keyboardToolbar; self.zTextField.inputAccessoryView = keyboardToolbar; @@ -55,10 +55,10 @@ - (IBAction)editButton:(id)sender { GPKGGeoPackage * geoPackage = [self.manager open:self.table.database]; @try { - GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage getGeometryColumnsDao]; - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; + GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage geometryColumnsDao]; + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; GPKGGeometryColumns * geometryColumns = (GPKGGeometryColumns *)[geometryColumnsDao queryForTableName:self.table.name]; - GPKGContents * contents = [geometryColumnsDao getContents:geometryColumns]; + GPKGContents * contents = [geometryColumnsDao contents:geometryColumns]; [contents setIdentifier:self.data.identifier]; [contents setTheDescription:self.data.theDescription]; @@ -93,7 +93,7 @@ - (IBAction)editButton:(id)sender { } } @catch (NSException *e) { - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:@"Edit Features" andMessage:[NSString stringWithFormat:@"Error editing features table '%@' in database: '%@'\n\nError: %@", self.table.name, self.table.database, [e description]]]; } @@ -123,7 +123,7 @@ -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)button - (IBAction)geometryType:(id)sender { UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPE_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_GEOMETRY_TYPE_LABEL] message:nil delegate:self cancelButtonTitle:nil @@ -132,7 +132,7 @@ - (IBAction)geometryType:(id)sender { for (NSString *geometryType in self.geometryTypes) { [alert addButtonWithTitle:geometryType]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_GEOMETRY_TYPES; @@ -156,9 +156,9 @@ -(void) setFields{ GPKGGeoPackage * geoPackage = [self.manager open:self.table.database]; @try { - GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage getGeometryColumnsDao]; + GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage geometryColumnsDao]; GPKGGeometryColumns * geometryColumns = (GPKGGeometryColumns *)[geometryColumnsDao queryForTableName:self.table.name]; - GPKGContents * contents = [geometryColumnsDao getContents:geometryColumns]; + GPKGContents * contents = [geometryColumnsDao contents:geometryColumns]; [self.data setIdentifier:contents.identifier]; [self.data setTheDescription:contents.theDescription]; @@ -167,7 +167,7 @@ -(void) setFields{ [self.data setMinX:contents.minX]; [self.data setMaxX:contents.maxX]; - enum SFGeometryType geometryType = [geometryColumns getGeometryType]; + enum SFGeometryType geometryType = [geometryColumns geometryType]; [self.geometryTypeButton setTitle:[SFGeometryTypes name:geometryType] forState:UIControlStateNormal]; [self.zTextField setText:[geometryColumns.z stringValue]]; [self.mTextField setText:[geometryColumns.m stringValue]]; diff --git a/mapcache-ios/manager/GPKGSEditTilesViewController.h b/mapcache-ios/manager/GPKGSEditTilesViewController.h index 3b7391a..aa56342 100644 --- a/mapcache-ios/manager/GPKGSEditTilesViewController.h +++ b/mapcache-ios/manager/GPKGSEditTilesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGGeoPackageManager.h" #import "GPKGSEditContentsData.h" @@ -21,7 +21,7 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; @property (weak, nonatomic) IBOutlet UITextField *minYTextField; @property (weak, nonatomic) IBOutlet UITextField *maxYTextField; @property (weak, nonatomic) IBOutlet UITextField *minXTextField; diff --git a/mapcache-ios/manager/GPKGSEditTilesViewController.m b/mapcache-ios/manager/GPKGSEditTilesViewController.m index 85e41e8..61f917c 100644 --- a/mapcache-ios/manager/GPKGSEditTilesViewController.m +++ b/mapcache-ios/manager/GPKGSEditTilesViewController.m @@ -8,9 +8,9 @@ #import "GPKGSEditTilesViewController.h" #import "GPKGSEditContentsViewController.h" -#import "GPKGSUtils.h" -#import "GPKGSDecimalValidator.h" -#import "GPKGSLoadTilesTask.h" +#import "MCUtils.h" +#import "MCDecimalValidator.h" +#import "MCLoadTilesTask.h" #import "GPKGTileTableScaling.h" NSString * const GPKGS_MANAGER_EDIT_TILES_SEG_EDIT_CONTENTS = @"editContents"; @@ -18,7 +18,7 @@ @interface GPKGSEditTilesViewController () @property (nonatomic, strong) GPKGSEditContentsData *data; -@property (nonatomic, strong) GPKGSDecimalValidator * xAndYValidator; +@property (nonatomic, strong) MCDecimalValidator * xAndYValidator; @end @@ -27,13 +27,13 @@ @implementation GPKGSEditTilesViewController - (void)viewDidLoad { [super viewDidLoad]; - self.xAndYValidator = [[GPKGSDecimalValidator alloc] initWithMinimum:nil andMaximum:nil]; + self.xAndYValidator = [[MCDecimalValidator alloc] initWithMinimum:nil andMaximum:nil]; [self.minYTextField setDelegate:self.xAndYValidator]; [self.maxYTextField setDelegate:self.xAndYValidator]; [self.minXTextField setDelegate:self.xAndYValidator]; [self.maxXTextField setDelegate:self.xAndYValidator]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.minYTextField.inputAccessoryView = keyboardToolbar; self.maxYTextField.inputAccessoryView = keyboardToolbar; @@ -56,10 +56,10 @@ - (IBAction)editButton:(id)sender { GPKGGeoPackage * geoPackage = [self.manager open:self.table.database]; @try { - GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; + GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage tileMatrixSetDao]; + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; GPKGTileMatrixSet * tileMatrixSet = (GPKGTileMatrixSet *)[tileMatrixSetDao queryForIdObject:self.table.name]; - GPKGContents * contents = [tileMatrixSetDao getContents:tileMatrixSet]; + GPKGContents * contents = [tileMatrixSetDao contents:tileMatrixSet]; [contents setIdentifier:self.data.identifier]; [contents setTheDescription:self.data.theDescription]; @@ -100,7 +100,7 @@ - (IBAction)editButton:(id)sender { [tileMatrixSetDao update:tileMatrixSet]; - GPKGTileScaling *scaling = [GPKGSLoadTilesTask tileScaling]; + GPKGTileScaling *scaling = [MCLoadTilesTask tileScaling]; GPKGTileTableScaling *tileTableScaling = [[GPKGTileTableScaling alloc] initWithGeoPackage:geoPackage andTileMatrixSet:tileMatrixSet]; if(scaling != nil){ [tileTableScaling createOrUpdate:scaling]; @@ -113,7 +113,7 @@ - (IBAction)editButton:(id)sender { } } @catch (NSException *e) { - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:@"Edit Tiles" andMessage:[NSString stringWithFormat:@"Error editing tiles table '%@' in database: '%@'\n\nError: %@", self.table.name, self.table.database, [e description]]]; } @@ -139,9 +139,9 @@ -(void) setFields{ GPKGGeoPackage * geoPackage = [self.manager open:self.table.database]; @try { - GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; + GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage tileMatrixSetDao]; GPKGTileMatrixSet * tileMatrixSet = (GPKGTileMatrixSet *)[tileMatrixSetDao queryForIdObject:self.table.name]; - GPKGContents * contents = [tileMatrixSetDao getContents:tileMatrixSet]; + GPKGContents * contents = [tileMatrixSetDao contents:tileMatrixSet]; [self.data setIdentifier:contents.identifier]; [self.data setTheDescription:contents.theDescription]; diff --git a/mapcache-ios/manager/GPKGSLinkedTablesViewController.h b/mapcache-ios/manager/GPKGSLinkedTablesViewController.h index d70add6..1e64331 100644 --- a/mapcache-ios/manager/GPKGSLinkedTablesViewController.h +++ b/mapcache-ios/manager/GPKGSLinkedTablesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGGeoPackageManager.h" @class GPKGSLinkedTablesViewController; @@ -20,6 +20,6 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; @end diff --git a/mapcache-ios/manager/GPKGSLinkedTablesViewController.m b/mapcache-ios/manager/GPKGSLinkedTablesViewController.m index 2aba94c..c61686b 100644 --- a/mapcache-ios/manager/GPKGSLinkedTablesViewController.m +++ b/mapcache-ios/manager/GPKGSLinkedTablesViewController.m @@ -9,7 +9,7 @@ #import "GPKGSLinkedTablesViewController.h" #import "GPKGSTableCell.h" #import "GPKGFeatureTileTableLinker.h" -#import "GPKGSConstants.h" +#import "MCConstants.h" @interface GPKGSLinkedTablesViewController () @@ -33,11 +33,11 @@ - (void)viewDidLoad { GPKGResultSet * linkedTableResults = nil; switch([self.table getType]){ case GPKGS_TT_FEATURE: - tables = [geoPackage getTileTables]; + tables = [geoPackage tileTables]; linkedTableResults = [linker queryForFeatureTable:self.table.name]; break; case GPKGS_TT_TILE: - tables = [geoPackage getFeatureTables]; + tables = [geoPackage featureTables]; linkedTableResults = [linker queryForTileTable:self.table.name]; break; default: @@ -47,7 +47,7 @@ - (void)viewDidLoad { // Build a set of currently linked tables self.linkedTableSet = [[NSMutableSet alloc] init]; while([linkedTableResults moveToNext]){ - GPKGFeatureTileLink * link = [linker getLinkFromResultSet:linkedTableResults]; + GPKGFeatureTileLink * link = [linker linkFromResultSet:linkedTableResults]; switch([self.table getType]){ case GPKGS_TT_FEATURE: [self.linkedTableSet addObject:link.tileTableName]; @@ -63,7 +63,7 @@ - (void)viewDidLoad { self.tableCells = [[NSMutableArray alloc] init]; for(NSString * table in tables){ - GPKGSTable * linkTable = [[GPKGSTable alloc] initWithDatabase:self.table.database andName:table andCount:0]; + MCTable * linkTable = [[MCTable alloc] initWithDatabase:self.table.database andName:table andCount:0]; linkTable.active = [self.linkedTableSet containsObject:table]; [self.tableCells addObject:linkTable]; } @@ -87,7 +87,7 @@ - (IBAction)editButton:(id)sender { // Determine which links were newly checked or removed NSMutableArray * newLinks = [[NSMutableArray alloc] init]; NSMutableArray * removedLinks = [[NSMutableArray alloc] init]; - for(GPKGSTable * linkTable in self.tableCells){ + for(MCTable * linkTable in self.tableCells){ BOOL wasActive = [self.linkedTableSet containsObject:linkTable.name]; if(linkTable.active){ if(!wasActive){ @@ -152,7 +152,7 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - GPKGSTable * linkTable = (GPKGSTable *) [self.tableCells objectAtIndex:indexPath.row]; + MCTable * linkTable = (MCTable *) [self.tableCells objectAtIndex:indexPath.row]; GPKGSTableCell * tableCell = (GPKGSTableCell *) [tableView dequeueReusableCellWithIdentifier:GPKGS_CELL_LINKED_TABLE forIndexPath:indexPath]; tableCell.active.on = linkTable.active; [tableCell.tableName setText:linkTable.name]; @@ -163,7 +163,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } - (IBAction)tableActiveChanged:(GPKGSActiveTableSwitch *)sender { - GPKGSTable * table = sender.table; + MCTable * table = sender.table; table.active = sender.on; } diff --git a/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.h b/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.h index 20f2f36..129e6d3 100644 --- a/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.h +++ b/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSDatabase.h" +#import "MCDatabase.h" #import "GPKGGeoPackageManager.h" #import "GPKGSCreateTilesData.h" #import "GPKGSLoadTilesProtocol.h" @@ -22,7 +22,7 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSDatabase *database; +@property (nonatomic, strong) MCDatabase *database; @property (nonatomic, strong) GPKGSCreateTilesData *data; @property (weak, nonatomic) IBOutlet UITextField *databaseValue; diff --git a/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.m b/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.m index df42622..a7f9eee 100644 --- a/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.m +++ b/mapcache-ios/manager/GPKGSManagerCreateTilesViewController.m @@ -12,10 +12,10 @@ #import "SFPProjectionTransform.h" #import "SFPProjectionConstants.h" #import "GPKGTileBoundingBoxUtils.h" -#import "GPKGSLoadTilesTask.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSUtils.h" +#import "MCLoadTilesTask.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCUtils.h" #import "SFPProjectionFactory.h" #import "GPKGTileTableScaling.h" @@ -32,7 +32,7 @@ - (void)viewDidLoad { [self.databaseValue setText:self.database.name]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.databaseValue.inputAccessoryView = keyboardToolbar; } @@ -76,7 +76,7 @@ - (IBAction)createButton:(id)sender { [NSException raise:@"Longitude Range" format:@"Min longitude (%@) can not be larger than max longitude (%@)", boundingBox.minLongitude, boundingBox.maxLongitude]; } - GPKGTileScaling *scaling = [GPKGSLoadTilesTask tileScaling]; + GPKGTileScaling *scaling = [MCLoadTilesTask tileScaling]; // If not importing tiles, just create the table if(url == nil || [url length] == 0){ @@ -84,11 +84,11 @@ - (IBAction)createButton:(id)sender { GPKGGeoPackage * geoPackage = [self.manager open:self.database.name]; @try { // Create the srs if needed - GPKGSpatialReferenceSystemDao * srsDao = [geoPackage getSpatialReferenceSystemDao]; - GPKGSpatialReferenceSystem * srs = [srsDao getOrCreateWithEpsg:[NSNumber numberWithInt:loadTiles.epsg]]; + GPKGSpatialReferenceSystemDao * srsDao = [geoPackage spatialReferenceSystemDao]; + GPKGSpatialReferenceSystem * srs = [srsDao srsWithEpsg:[NSNumber numberWithInt:loadTiles.epsg]]; // Create the tile table SFPProjection * projection = [SFPProjectionFactory projectionWithEpsgInt:loadTiles.epsg]; - GPKGBoundingBox * bbox = [GPKGSLoadTilesTask transformBoundingBox:boundingBox withProjection:projection]; + GPKGBoundingBox * bbox = [MCLoadTilesTask transformBoundingBox:boundingBox withProjection:projection]; [geoPackage createTileTableWithTableName:name andContentsBoundingBox:bbox andContentsSrsId:srs.srsId andTileMatrixSetBoundingBox:bbox andTileMatrixSetSrsId:srs.srsId]; GPKGTileTableScaling *tileTableScaling = [[GPKGTileTableScaling alloc] initWithGeoPackage:geoPackage andTableName:name]; @@ -105,8 +105,8 @@ - (IBAction)createButton:(id)sender { }else{ // Load tiles - [GPKGSLoadTilesTask loadTilesWithCallback:self andDatabase:self.database.name andTable:name andUrl:url andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andStandardFormat:generateTiles.standardWebMercatorFormat andBoundingBox:boundingBox andTileScaling:scaling andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",loadTiles.epsg] andLabel:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL]]; - } + [MCLoadTilesTask loadTilesWithCallback:self andDatabase:self.database.name andTable:name andUrl:url andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andXyzTiles:generateTiles.xyzTiles andBoundingBox:boundingBox andTileScaling:scaling andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d", loadTiles.epsg] andLabel:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL]]; + } } @catch (NSException *e) { diff --git a/mapcache-ios/manager/GPKGSManagerEditTileOverlayViewController.h b/mapcache-ios/manager/GPKGSManagerEditTileOverlayViewController.h index c1ef975..a575f34 100644 --- a/mapcache-ios/manager/GPKGSManagerEditTileOverlayViewController.h +++ b/mapcache-ios/manager/GPKGSManagerEditTileOverlayViewController.h @@ -7,19 +7,19 @@ // #import -#import "GPKGSFeatureOverlayTable.h" +#import "MCFeatureOverlayTable.h" #import "GPKGGeoPackageManager.h" -#import "GPKGSTable.h" +#import "MCTable.h" @class GPKGSManagerEditTileOverlayViewController; @protocol GPKGSEditTileOverlayDelegate -- (void)editTileOverlayViewController:(GPKGSManagerEditTileOverlayViewController *)controller featureOverlayTable:(GPKGSFeatureOverlayTable *)featureOverlayTable; +- (void)editTileOverlayViewController:(GPKGSManagerEditTileOverlayViewController *)controller featureOverlayTable:(MCFeatureOverlayTable *)featureOverlayTable; @end @interface GPKGSManagerEditTileOverlayViewController : UIViewController @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSFeatureOverlayTable *table; +@property (nonatomic, strong) MCFeatureOverlayTable *table; @end diff --git a/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.h b/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.h index a86f9a3..cada081 100644 --- a/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.h +++ b/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.h @@ -7,7 +7,7 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" #import "GPKGGeoPackageManager.h" #import "GPKGSLoadTilesData.h" #import "GPKGSLoadTilesProtocol.h" @@ -22,7 +22,7 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSTable *table; +@property (nonatomic, strong) MCTable *table; @property (nonatomic, strong) GPKGSLoadTilesData *data; diff --git a/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.m b/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.m index d093c6c..a5e86b3 100644 --- a/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.m +++ b/mapcache-ios/manager/GPKGSManagerLoadTilesViewController.m @@ -12,9 +12,9 @@ #import "SFPProjectionTransform.h" #import "SFPProjectionConstants.h" #import "GPKGTileBoundingBoxUtils.h" -#import "GPKGSLoadTilesTask.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCLoadTilesTask.h" +#import "MCProperties.h" +#import "MCConstants.h" #import "SFPProjectionFactory.h" #import "GPKGTileTableScaling.h" @@ -63,11 +63,11 @@ - (IBAction)loadButton:(id)sender { GPKGGeoPackage * geoPackage = [self.manager open:self.table.database]; @try { // Create the srs if needed - GPKGSpatialReferenceSystemDao * srsDao = [geoPackage getSpatialReferenceSystemDao]; - GPKGSpatialReferenceSystem * srs = [srsDao getOrCreateWithEpsg:[NSNumber numberWithInt:loadTiles.epsg]]; + GPKGSpatialReferenceSystemDao * srsDao = [geoPackage spatialReferenceSystemDao]; + GPKGSpatialReferenceSystem * srs = [srsDao srsWithEpsg:[NSNumber numberWithInt:loadTiles.epsg]]; // Create the tile table SFPProjection * projection = [SFPProjectionFactory projectionWithEpsgInt:loadTiles.epsg]; - GPKGBoundingBox * bbox = [GPKGSLoadTilesTask transformBoundingBox:boundingBox withProjection:projection]; + GPKGBoundingBox * bbox = [MCLoadTilesTask transformBoundingBox:boundingBox withProjection:projection]; [geoPackage createTileTableWithTableName:name andContentsBoundingBox:bbox andContentsSrsId:srs.srsId andTileMatrixSetBoundingBox:bbox andTileMatrixSetSrsId:srs.srsId]; } @finally { @@ -81,7 +81,7 @@ - (IBAction)loadButton:(id)sender { }else{ // Load tiles - [GPKGSLoadTilesTask loadTilesWithCallback:self andDatabase:self.table.database andTable:name andUrl:url andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andStandardFormat:generateTiles.standardWebMercatorFormat andBoundingBox:boundingBox andTileScaling:nil andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",loadTiles.epsg] andLabel:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_TILES_LOAD_LABEL]]; + [MCLoadTilesTask loadTilesWithCallback:self andDatabase:self.table.database andTable:name andUrl:url andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andXyzTiles:generateTiles.xyzTiles andBoundingBox:boundingBox andTileScaling:nil andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",loadTiles.epsg] andLabel:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_TILES_LOAD_LABEL]]; } } diff --git a/mapcache-ios/manager/GPKGSManagerViewController.m b/mapcache-ios/manager/GPKGSManagerViewController.m index 68c3af0..17d994f 100644 --- a/mapcache-ios/manager/GPKGSManagerViewController.m +++ b/mapcache-ios/manager/GPKGSManagerViewController.m @@ -9,19 +9,19 @@ #import "GPKGSManagerViewController.h" #import #import "GPKGGeoPackageFactory.h" -#import "GPKGSFeatureTable.h" -#import "GPKGSTileTable.h" -#import "GPKGSDatabase.h" +#import "MCFeatureTable.h" +#import "MCTileTable.h" +#import "MCDatabase.h" #import "GPKGSTableCell.h" #import "GPKGSDatabaseCell.h" -#import "GPKGSConstants.h" +#import "MCConstants.h" #import "GPKGSActiveTableSwitch.h" -#import "GPKGSProperties.h" -#import "GPKGSUtils.h" +#import "MCProperties.h" +#import "MCUtils.h" #import "GPKGSDisplayTextViewController.h" -#import "GPKGSFeatureOverlayTable.h" -#import "GPKGSDatabases.h" -#import "GPKGSIndexerTask.h" +#import "MCFeatureOverlayTable.h" +#import "MCDatabases.h" +#import "MCIndexerTask.h" #import "GPKGSCreateFeaturesViewController.h" #import "GPKGSManagerCreateTilesViewController.h" #import "GPKGSManagerLoadTilesViewController.h" @@ -31,7 +31,7 @@ #import "GPKGSAddTileOverlayViewController.h" #import "GPKGSManagerEditTileOverlayViewController.h" #import "GPKGFeatureIndexManager.h" -#import "GPKGSTableIndex.h" +#import "MCTableIndex.h" #import "GPKGSLinkedTablesViewController.h" NSString * const GPKGS_MANAGER_SEG_DOWNLOAD_FILE = @"downloadFile"; @@ -55,7 +55,7 @@ @interface GPKGSManagerViewController () @property (nonatomic, strong) GPKGGeoPackageManager *manager; @property (nonatomic, strong) NSMutableDictionary *databases; @property (nonatomic, strong) NSMutableArray *tableCells; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @property (nonatomic, strong) NSUserDefaults * settings; @property (nonatomic) BOOL retainModifiedForMap; @property (nonatomic, strong) UIDocumentInteractionController *shareDocumentController; @@ -85,13 +85,13 @@ -(void)viewDidLoad{ name:GPKGS_IMPORT_GEOPACKAGE_NOTIFICATION object:nil]; - self.manager = [GPKGGeoPackageFactory getManager]; - self.active = [GPKGSDatabases getInstance]; + self.manager = [GPKGGeoPackageFactory manager]; + self.active = [MCDatabases getInstance]; self.settings = [NSUserDefaults standardUserDefaults]; NSArray * expandedDatabases = [self.settings stringArrayForKey:GPKGS_EXPANDED_PREFERENCE]; self.databases = [[NSMutableDictionary alloc] init]; for(NSString * expandedDatabase in expandedDatabases){ - [self.databases setObject:[[GPKGSDatabase alloc] initWithName:expandedDatabase andExpanded:true] forKey:expandedDatabase]; + [self.databases setObject:[[MCDatabase alloc] initWithName:expandedDatabase andExpanded:true] forKey:expandedDatabase]; } self.retainModifiedForMap = false; [self update]; @@ -131,27 +131,27 @@ -(void) update{ geoPackage = [self.manager open:database]; BOOL expanded = false; if(previousDatabases != nil){ - GPKGSDatabase * previousDatabase = [previousDatabases objectForKey:database]; + MCDatabase * previousDatabase = [previousDatabases objectForKey:database]; if(previousDatabase != nil){ expanded = previousDatabase.expanded; } } - GPKGSDatabase * theDatabase = [[GPKGSDatabase alloc] initWithName:database andExpanded:expanded]; + MCDatabase * theDatabase = [[MCDatabase alloc] initWithName:database andExpanded:expanded]; [self.databases setObject:theDatabase forKey:database]; [self.tableCells addObject:theDatabase]; NSMutableArray * tables = [[NSMutableArray alloc] init]; - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; - for(NSString * tableName in [geoPackage getFeatureTables]){ - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:tableName]; + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; + for(NSString * tableName in [geoPackage featureTables]){ + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:tableName]; int count = [featureDao count]; GPKGContents * contents = (GPKGContents *)[contentsDao queryForIdObject:tableName]; - GPKGGeometryColumns * geometryColumns = [contentsDao getGeometryColumns:contents]; + GPKGGeometryColumns * geometryColumns = [contentsDao geometryColumns:contents]; enum SFGeometryType geometryType = [SFGeometryTypes fromName:geometryColumns.geometryTypeName]; - GPKGSFeatureTable * table = [[GPKGSFeatureTable alloc] initWithDatabase:database andName:tableName andGeometryType:geometryType andCount:count]; + MCFeatureTable * table = [[MCFeatureTable alloc] initWithDatabase:database andName:tableName andGeometryType:geometryType andCount:count]; [table setActive:[self.active exists:table]]; [tables addObject:table]; @@ -161,11 +161,11 @@ -(void) update{ } } - for(NSString * tableName in [geoPackage getTileTables]){ - GPKGTileDao * tileDao = [geoPackage getTileDaoWithTableName: tableName]; + for(NSString * tableName in [geoPackage tileTables]){ + GPKGTileDao * tileDao = [geoPackage tileDaoWithTableName: tableName]; int count = [tileDao count]; - GPKGSTileTable * table = [[GPKGSTileTable alloc] initWithDatabase:database andName:tableName andCount:count]; + MCTileTable * table = [[MCTileTable alloc] initWithDatabase:database andName:tableName andCount:count]; [table setActive:[self.active exists:table]]; [tables addObject:table]; @@ -175,8 +175,8 @@ -(void) update{ } } - for(GPKGSFeatureOverlayTable * table in [self.active featureOverlays:database]){ - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:table.featureTable]; + for(MCFeatureOverlayTable * table in [self.active featureOverlays:database]){ + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:table.featureTable]; int count = [featureDao count]; [table setCount:count]; @@ -221,29 +221,29 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N UITableViewCell *cell = nil; NSObject * cellObject = [self.tableCells objectAtIndex:indexPath.row]; - if([cellObject isKindOfClass:[GPKGSDatabase class]]){ + if([cellObject isKindOfClass:[MCDatabase class]]){ cell = [tableView dequeueReusableCellWithIdentifier:GPKGS_CELL_DATABASE forIndexPath:indexPath]; GPKGSDatabaseCell * dbCell = (GPKGSDatabaseCell *) cell; - GPKGSDatabase * database = (GPKGSDatabase *) cellObject; + MCDatabase * database = (MCDatabase *) cellObject; [dbCell.database setText:database.name]; - NSString *expandImage = database.expanded ? [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_UP] : [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_DOWN]; + NSString *expandImage = database.expanded ? [MCProperties getValueOfProperty:GPKGS_PROP_ICON_UP] : [MCProperties getValueOfProperty:GPKGS_PROP_ICON_DOWN]; [dbCell.expandImage setImage:[UIImage imageNamed:expandImage]]; [dbCell.optionsButton setDatabase:database]; }else{ cell = [tableView dequeueReusableCellWithIdentifier:GPKGS_CELL_TABLE forIndexPath:indexPath]; GPKGSTableCell * tableCell = (GPKGSTableCell *) cell; - GPKGSTable * table = (GPKGSTable *) cellObject; + MCTable * table = (MCTable *) cellObject; NSString * typeImage = nil; - if([cellObject isKindOfClass:[GPKGSFeatureOverlayTable class]]){ - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_PAINT]; - }else if([cellObject isKindOfClass:[GPKGSFeatureTable class]]){ - GPKGSFeatureTable * featureTable = (GPKGSFeatureTable *) cellObject; - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_GEOMETRY]; + if([cellObject isKindOfClass:[MCFeatureOverlayTable class]]){ + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_PAINT]; + }else if([cellObject isKindOfClass:[MCFeatureTable class]]){ + MCFeatureTable * featureTable = (MCFeatureTable *) cellObject; + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_GEOMETRY]; if(featureTable.geometryType != SF_NONE){ switch(featureTable.geometryType){ case SF_POINT: case SF_MULTIPOINT: - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_POINT]; + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_POINT]; break; case SF_LINESTRING: case SF_MULTILINESTRING: @@ -251,7 +251,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N case SF_COMPOUNDCURVE: case SF_CIRCULARSTRING: case SF_MULTICURVE: - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_LINESTRING]; + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_LINESTRING]; break; case SF_POLYGON: case SF_SURFACE: @@ -261,17 +261,17 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N case SF_TIN: case SF_MULTIPOLYGON: case SF_MULTISURFACE: - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_POLYGON]; + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_POLYGON]; break; case SF_GEOMETRY: case SF_GEOMETRYCOLLECTION: case SF_NONE: - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_GEOMETRY]; + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_GEOMETRY]; break; } } - }else if([cellObject isKindOfClass:[GPKGSTileTable class]]){ - typeImage = [GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_TILES]; + }else if([cellObject isKindOfClass:[MCTileTable class]]){ + typeImage = [MCProperties getValueOfProperty:GPKGS_PROP_ICON_TILES]; } tableCell.active.on = table.active; if(typeImage != nil){ @@ -289,8 +289,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N -(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSObject * cellObject = [self.tableCells objectAtIndex:indexPath.row]; - if([cellObject isKindOfClass:[GPKGSDatabase class]]){ - GPKGSDatabase * database = (GPKGSDatabase *) cellObject; + if([cellObject isKindOfClass:[MCDatabase class]]){ + MCDatabase * database = (MCDatabase *) cellObject; [self expandOrCollapseDatabase:database atIndexPath:indexPath]; // MCGeoPackageCoordinator *coordinator = [[MCGeoPackageCoordinator alloc] initWithDelegate:self andDatabase:database]; @@ -310,12 +310,12 @@ - (void) geoPackageCoordinatorCompletionHandlerForDatabase:(NSString *)database } --(void) expandOrCollapseDatabase: (GPKGSDatabase *) database atIndexPath:(NSIndexPath *)indexPath{ +-(void) expandOrCollapseDatabase: (MCDatabase *) database atIndexPath:(NSIndexPath *)indexPath{ if(database.expanded){ for(NSInteger i = indexPath.row + 1; i < self.tableCells.count;){ NSObject * cellObject = [self.tableCells objectAtIndex:i]; - if([cellObject isKindOfClass:[GPKGSDatabase class]]){ + if([cellObject isKindOfClass:[MCDatabase class]]){ break; }else{ [self.tableCells removeObjectAtIndex:i]; @@ -336,7 +336,7 @@ -(void) expandOrCollapseDatabase: (GPKGSDatabase *) database atIndexPath:(NSInde } - (IBAction)tableActiveChanged:(GPKGSActiveTableSwitch *)sender { - GPKGSTable * table = sender.table; + MCTable * table = sender.table; table.active = sender.on; if([table getType] == GPKGS_TT_FEATURE_OVERLAY){ @@ -396,14 +396,14 @@ - (IBAction)databaseOptions:(GPKGSDatabaseOptionsButton *)sender { initWithTitle:sender.database.name message:nil delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_VIEW_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_DELETE_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_SHARE_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_FEATURES_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_VIEW_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_DELETE_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_SHARE_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_FEATURES_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL], nil]; alert.tag = TAG_DATABASE_OPTIONS; @@ -416,7 +416,7 @@ - (IBAction)databaseOptions:(GPKGSDatabaseOptionsButton *)sender { - (void) handleDatabaseOptionsWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex > 0){ - GPKGSDatabase *database = objc_getAssociatedObject(alertView, &ConstantKey); + MCDatabase *database = objc_getAssociatedObject(alertView, &ConstantKey); switch (buttonIndex) { case 1: [self viewDatabaseOption:database]; @@ -448,25 +448,25 @@ - (void) handleDatabaseOptionsWithAlertView:(UIAlertView *)alertView clickedButt - (IBAction)tableOptions:(GPKGSTableOptionsButton *)sender { NSMutableArray * options = [[NSMutableArray alloc] init]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_VIEW_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_EDIT_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_VIEW_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_EDIT_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL]]; switch([sender.table getType]){ case GPKGS_TT_FEATURE: - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_ADD_FEATURE_OVERLAY_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_LINKED_TABLES_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_ADD_FEATURE_OVERLAY_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_LINKED_TABLES_LABEL]]; break; case GPKGS_TT_TILE: - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_TILES_LOAD_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_LINKED_TABLES_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_TILES_LOAD_LABEL]]; + [options addObject:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_LINKED_TABLES_LABEL]]; break; case GPKGS_TT_FEATURE_OVERLAY: break; default: - [NSException raise:@"Unsupported" format:@"Unsupported table type: %@", [GPKGSTableTypes name:sender.table.getType]]; + [NSException raise:@"Unsupported" format:@"Unsupported table type: %@", [MCTableTypes name:sender.table.getType]]; } UIAlertView *alert = [[UIAlertView alloc] @@ -479,7 +479,7 @@ - (IBAction)tableOptions:(GPKGSTableOptionsButton *)sender { for (NSString *option in options) { [alert addButtonWithTitle:option]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_TABLE_OPTIONS; @@ -491,7 +491,7 @@ - (IBAction)tableOptions:(GPKGSTableOptionsButton *)sender { - (void) handleTableOptionsWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex >= 0){ - GPKGSTable *table = objc_getAssociatedObject(alertView, &ConstantKey); + MCTable *table = objc_getAssociatedObject(alertView, &ConstantKey); switch(buttonIndex){ case 0: switch([table getType]){ @@ -511,7 +511,7 @@ - (void) handleTableOptionsWithAlertView:(UIAlertView *)alertView clickedButtonA [self editTilesTableOption:table]; break; case GPKGS_TT_FEATURE_OVERLAY: - [self editFeatureOverlayTableOption:(GPKGSFeatureOverlayTable *)table]; + [self editFeatureOverlayTableOption:(MCFeatureOverlayTable *)table]; break; } break; @@ -573,17 +573,17 @@ - (void) handleTableOptionsWithAlertView:(UIAlertView *)alertView clickedButtonA } } --(void) viewDatabaseOption: (GPKGSDatabase *) database{ +-(void) viewDatabaseOption: (MCDatabase *) database{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_DISPLAY_TEXT sender:database]; } -(void) deleteDatabaseOption: (NSString *) database{ - NSString * label = [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_DELETE_LABEL]; + NSString * label = [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_DELETE_LABEL]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:label message:[NSString stringWithFormat:@"%@ %@?", label, database] delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] otherButtonTitles:label, nil]; alert.tag = TAG_DATABASE_DELETE; @@ -602,11 +602,11 @@ - (void) handleDeleteDatabaseWithAlertView:(UIAlertView *)alertView clickedButto -(void) renameDatabaseOption: (NSString *) database{ UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"%@ '%@'", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL], database] + initWithTitle:[NSString stringWithFormat:@"%@ '%@'", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL], database] message:nil delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; [[alert textFieldAtIndex:0] setText:database]; @@ -625,13 +625,13 @@ - (void) handleRenameDatabaseWithAlertView:(UIAlertView *)alertView clickedButto [self.active renameDatabase:database asNewDatabase:newName]; [self updateAndReloadData]; }else{ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_RENAME_LABEL] andMessage:[NSString stringWithFormat:@"Rename from %@ to %@ was not successful", database, newName]]; } } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:[NSString stringWithFormat:@"Rename %@ to %@", database, newName] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } @@ -641,14 +641,14 @@ - (void) handleRenameDatabaseWithAlertView:(UIAlertView *)alertView clickedButto -(void) copyDatabaseOption: (NSString *) database{ UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"%@ '%@'", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL], database] + initWithTitle:[NSString stringWithFormat:@"%@ '%@'", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL], database] message:nil delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; - [[alert textFieldAtIndex:0] setText:[NSString stringWithFormat:@"%@%@", database, [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_SUFFIX]]]; + [[alert textFieldAtIndex:0] setText:[NSString stringWithFormat:@"%@%@", database, [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_SUFFIX]]]; alert.tag = TAG_DATABASE_COPY; objc_setAssociatedObject(alert, &ConstantKey, database, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [alert show]; @@ -663,13 +663,13 @@ - (void) handleCopyDatabaseWithAlertView:(UIAlertView *)alertView clickedButtonA if([self.manager copy:database to:newName]){ [self updateAndReloadData]; }else{ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_COPY_LABEL] andMessage:[NSString stringWithFormat:@"Copy from %@ to %@ was not successful", database, newName]]; } } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:[NSString stringWithFormat:@"Copy %@ to %@", database, newName] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } @@ -686,45 +686,45 @@ -(void) shareDatabaseOption: (NSString *) database{ [self.shareDocumentController setUTI:@"public.database"]; [self.shareDocumentController presentOpenInMenuFromRect:self.view.bounds inView:self.view animated:YES]; }else{ - [GPKGSUtils showMessageWithDelegate:self + [MCUtils showMessageWithDelegate:self andTitle:[NSString stringWithFormat:@"Share Database %@", database] andMessage:[NSString stringWithFormat:@"No path was found for database %@", database]]; } } --(void) createFeaturesDatabaseOption: (GPKGSDatabase *) database +-(void) createFeaturesDatabaseOption: (MCDatabase *) database { [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_CREATE_FEATURES sender:database]; } --(void) createTilesDatabaseOption: (GPKGSDatabase *) database +-(void) createTilesDatabaseOption: (MCDatabase *) database { [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_CREATE_TILES sender:database]; } --(void) viewTableOption: (GPKGSTable *) table{ +-(void) viewTableOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_DISPLAY_TEXT sender:table]; } --(void) editFeaturesTableOption: (GPKGSTable *) table{ +-(void) editFeaturesTableOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_EDIT_FEATURES sender:table]; } --(void) editTilesTableOption: (GPKGSTable *) table{ +-(void) editTilesTableOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_EDIT_TILES sender:table]; } --(void) editFeatureOverlayTableOption: (GPKGSFeatureOverlayTable *) table{ +-(void) editFeatureOverlayTableOption: (MCFeatureOverlayTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_EDIT_TILE_OVERLAY sender:table]; } --(void) deleteTableOption: (GPKGSTable *) table{ - NSString * label = [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL]; +-(void) deleteTableOption: (MCTable *) table{ + NSString * label = [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:label message:[NSString stringWithFormat:@"%@ %@ - %@?", label, table.database, table.name] delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] otherButtonTitles:label, nil]; alert.tag = TAG_TABLE_DELETE; @@ -734,7 +734,7 @@ -(void) deleteTableOption: (GPKGSTable *) table{ - (void) handleDeleteTableWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex > 0){ - GPKGSTable *table = objc_getAssociatedObject(alertView, &ConstantKey); + MCTable *table = objc_getAssociatedObject(alertView, &ConstantKey); switch([table getType]){ case GPKGS_TT_FEATURE: @@ -747,8 +747,8 @@ - (void) handleDeleteTableWithAlertView:(UIAlertView *)alertView clickedButtonAt [self updateAndReloadData]; } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[NSString stringWithFormat:@"%@ %@ - %@ Table", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL], table.database, table.name] + [MCUtils showMessageWithDelegate:self + andTitle:[NSString stringWithFormat:@"%@ %@ - %@ Table", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_DELETE_LABEL], table.database, table.name] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } @finally { @@ -765,13 +765,13 @@ - (void) handleDeleteTableWithAlertView:(UIAlertView *)alertView clickedButtonAt } } --(void) indexFeaturesOption: (GPKGSTable *) table{ +-(void) indexFeaturesOption: (MCTable *) table{ BOOL geoPackageIndexed = false; BOOL metadataIndexed = false; GPKGGeoPackage * geoPackage = [self.manager open:table.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:table.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:table.name]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @try{ @@ -786,20 +786,20 @@ -(void) indexFeaturesOption: (GPKGSTable *) table{ } NSMutableString * geoPackageIndexLabel = [[NSMutableString alloc] initWithString:geoPackageIndexed ? - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL] : - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL]]; - [geoPackageIndexLabel appendFormat:@" %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_GEOPACKAGE_LABEL]]; + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL] : + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL]]; + [geoPackageIndexLabel appendFormat:@" %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_GEOPACKAGE_LABEL]]; NSMutableString * metadataIndexLabel = [[NSMutableString alloc] initWithString:metadataIndexed ? - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL] : - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL]]; - [metadataIndexLabel appendFormat:@" %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_METADATA_LABEL]]; + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL] : + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL]]; + [metadataIndexLabel appendFormat:@" %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_METADATA_LABEL]]; UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"%@ - %@ %@",table.database,table.name, [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]] + initWithTitle:[NSString stringWithFormat:@"%@ - %@ %@",table.database,table.name, [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]] message:nil delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] otherButtonTitles:geoPackageIndexLabel, metadataIndexLabel, nil]; @@ -814,7 +814,7 @@ -(void) indexFeaturesOption: (GPKGSTable *) table{ - (void) handleIndexFeaturesWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex > 0){ - GPKGSTable *table = objc_getAssociatedObject(alertView, &ConstantKey); + MCTable *table = objc_getAssociatedObject(alertView, &ConstantKey); enum GPKGFeatureIndexType indexLocation = GPKG_FIT_NONE; switch(buttonIndex){ @@ -828,16 +828,16 @@ - (void) handleIndexFeaturesWithAlertView:(UIAlertView *)alertView clickedButton break; } - GPKGSTableIndex * tableIndex = [[GPKGSTableIndex alloc] initWithTable:table andIndexLocation:indexLocation]; + MCTableIndex * tableIndex = [[MCTableIndex alloc] initWithTable:table andIndexLocation:indexLocation]; [self createOrDeleteFeatureIndexWithTableIndex:tableIndex]; } } -- (void) createOrDeleteFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ +- (void) createOrDeleteFeatureIndexWithTableIndex: (MCTableIndex *) tableIndex{ BOOL indexed = false; GPKGGeoPackage * geoPackage = [self.manager open:tableIndex.table.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:tableIndex.table.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:tableIndex.table.name]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @try{ indexed = [indexer isIndexedWithFeatureIndexType:tableIndex.indexLocation]; @@ -855,20 +855,20 @@ - (void) createOrDeleteFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableInde } } -- (void) deleteFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ - NSString * title = [NSString stringWithFormat:@"%@ %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; +- (void) deleteFeatureIndexWithTableIndex: (MCTableIndex *) tableIndex{ + NSString * title = [NSString stringWithFormat:@"%@ %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; NSMutableString * message = [[NSMutableString alloc] initWithFormat:@"%@ %@ - %@ %@", - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_LABEL], tableIndex.table.database, tableIndex.table.name, - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; switch(tableIndex.indexLocation){ case GPKG_FIT_GEOPACKAGE: - [message appendFormat:@" %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_GEOPACKAGE_LABEL]]; + [message appendFormat:@" %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_GEOPACKAGE_LABEL]]; break; case GPKG_FIT_METADATA: - [message appendFormat:@" %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_METADATA_LABEL]]; + [message appendFormat:@" %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_DELETE_METADATA_LABEL]]; break; default: break; @@ -877,8 +877,8 @@ - (void) deleteFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ initWithTitle:title message:message delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; alert.tag = TAG_DELETE_INDEX_FEATURES; objc_setAssociatedObject(alert, &ConstantKey, tableIndex, OBJC_ASSOCIATION_RETAIN_NONATOMIC); @@ -888,11 +888,11 @@ - (void) deleteFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ - (void) handleDeleteIndexFeaturesWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex > 0){ - GPKGSTableIndex *tableIndex = objc_getAssociatedObject(alertView, &ConstantKey); + MCTableIndex *tableIndex = objc_getAssociatedObject(alertView, &ConstantKey); GPKGGeoPackage * geoPackage = [self.manager open:tableIndex.table.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:tableIndex.table.name]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:tableIndex.table.name]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @try{ [indexer setIndexLocation:tableIndex.indexLocation]; @@ -907,20 +907,20 @@ - (void) handleDeleteIndexFeaturesWithAlertView:(UIAlertView *)alertView clicked } } -- (void) createFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ - NSString * title = [NSString stringWithFormat:@"%@ %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; +- (void) createFeatureIndexWithTableIndex: (MCTableIndex *) tableIndex{ + NSString * title = [NSString stringWithFormat:@"%@ %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; NSMutableString * message = [[NSMutableString alloc] initWithFormat:@"%@ %@ - %@ %@", - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL], + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_LABEL], tableIndex.table.database, tableIndex.table.name, - [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; + [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_TITLE]]; switch(tableIndex.indexLocation){ case GPKG_FIT_GEOPACKAGE: - [message appendFormat:@" %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_GEOPACKAGE_LABEL]]; + [message appendFormat:@" %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_GEOPACKAGE_LABEL]]; break; case GPKG_FIT_METADATA: - [message appendFormat:@" %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_METADATA_LABEL]]; + [message appendFormat:@" %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_INDEX_FEATURES_INDEX_CREATE_METADATA_LABEL]]; break; default: break; @@ -929,8 +929,8 @@ - (void) createFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ initWithTitle:title message:message delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; alert.tag = TAG_CREATE_INDEX_FEATURES; objc_setAssociatedObject(alert, &ConstantKey, tableIndex, OBJC_ASSOCIATION_RETAIN_NONATOMIC); @@ -939,24 +939,24 @@ - (void) createFeatureIndexWithTableIndex: (GPKGSTableIndex *) tableIndex{ - (void) handleCreateIndexFeaturesWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex > 0){ - GPKGSTableIndex *tableIndex = objc_getAssociatedObject(alertView, &ConstantKey); - [GPKGSIndexerTask indexFeaturesWithCallback:self andDatabase:tableIndex.table.database andTable:tableIndex.table.name andFeatureIndexType:tableIndex.indexLocation]; + MCTableIndex *tableIndex = objc_getAssociatedObject(alertView, &ConstantKey); + [MCIndexerTask indexFeaturesWithCallback:self andDatabase:tableIndex.table.database andTable:tableIndex.table.name andFeatureIndexType:tableIndex.indexLocation]; } } --(void) linkedTablesOption: (GPKGSTable *) table{ +-(void) linkedTablesOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_LINKED_TABLES sender:table]; } --(void) loadTilesTableOption: (GPKGSTable *) table{ +-(void) loadTilesTableOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_LOAD_TILES sender:table]; } --(void) createFeatureTilesTableOption: (GPKGSTable *) table{ +-(void) createFeatureTilesTableOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_CREATE_FEATURE_TILES sender:table]; } --(void) addFeatureOverlayTableOption: (GPKGSTable *) table{ +-(void) addFeatureOverlayTableOption: (MCTable *) table{ [self performSegueWithIdentifier:GPKGS_MANAGER_SEG_ADD_TILE_OVERLAY sender:table]; } @@ -979,11 +979,11 @@ - (IBAction)downloadFile:(id)sender { - (IBAction)create:(id)sender { UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_LABEL] message:nil delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; alert.tag = TAG_DATABASE_CREATE; @@ -998,14 +998,14 @@ - (void) handleCreateWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex if([self.manager create:createName]){ [self updateAndReloadData]; }else{ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_LABEL] andMessage:[NSString stringWithFormat:@"Failed to create GeoPackage: %@", createName]]; } } @catch (NSException *exception) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[NSString stringWithFormat:@"%@ %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_LABEL], createName] + [MCUtils showMessageWithDelegate:self + andTitle:[NSString stringWithFormat:@"%@ %@", [MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_LABEL], createName] andMessage:[NSString stringWithFormat:@"%@", [exception description]]]; } } @@ -1013,7 +1013,7 @@ - (void) handleCreateWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex } - (IBAction)expandAll:(id)sender { - for(GPKGSDatabase * database in [self.databases allValues]){ + for(MCDatabase * database in [self.databases allValues]){ database.expanded = true; [self addExpandedSetting:database.name]; } @@ -1021,7 +1021,7 @@ - (IBAction)expandAll:(id)sender { } - (IBAction)collapseAll:(id)sender { - for(GPKGSDatabase * database in [self.databases allValues]){ + for(MCDatabase * database in [self.databases allValues]){ database.expanded = false; } [self clearExpandedSettings]; @@ -1031,10 +1031,10 @@ - (IBAction)collapseAll:(id)sender { - (IBAction)clearActive:(id)sender { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil - message:[NSString stringWithFormat:@"%@ - %d", [GPKGSProperties getValueOfProperty:GPKGS_PROP_CLEAR_ACTIVE_LABEL], [self.active getActiveTableCount]] + message:[NSString stringWithFormat:@"%@ - %d", [MCProperties getValueOfProperty:GPKGS_PROP_CLEAR_ACTIVE_LABEL], [self.active getActiveTableCount]] delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + cancelButtonTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; alert.tag = TAG_CLEAR_ACTIVE; [alert show]; @@ -1049,9 +1049,9 @@ - (void) handleClearActiveWithAlertView:(UIAlertView *)alertView clickedButtonAt -(void) updateClearActiveButton{ if([self.active getActiveTableCount] > 0){ - [GPKGSUtils enableButton:self.clearActiveButton]; + [MCUtils enableButton:self.clearActiveButton]; }else{ - [GPKGSUtils disableButton:self.clearActiveButton]; + [MCUtils disableButton:self.clearActiveButton]; } } @@ -1060,8 +1060,8 @@ - (void)downloadFileViewController:(MCDownloadGeopackage *)controller downloaded [self updateAndReloadData]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_IMPORT_URL_ERROR] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_IMPORT_URL_ERROR] andMessage:[NSString stringWithFormat:@"Error downloading '%@' at:\n%@\n\nError: %@", controller.nameTextField.text, controller.urlTextField.text, error]]; } } @@ -1071,8 +1071,8 @@ - (void)createFeaturesViewController:(GPKGSCreateFeaturesViewController *)contro [self updateAndReloadData]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_FEATURES_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_FEATURES_LABEL] andMessage:[NSString stringWithFormat:@"Error creating features table '%@' in database: '%@'\n\nError: %@", controller.nameValue.text, controller.database.name, error]]; } } @@ -1084,8 +1084,8 @@ - (void)createManagerTilesViewController:(GPKGSManagerCreateTilesViewController [self.active setModified:true]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_CREATE_TILES_LABEL] andMessage:[NSString stringWithFormat:@"Error creating tiles table '%@' in database: '%@'\n\nError: %@", controller.data.name, controller.database.name, error]]; } } @@ -1097,8 +1097,8 @@ - (void)loadManagerTilesViewController:(GPKGSManagerLoadTilesViewController *)co [self.active setModified:true]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_TILES_LOAD_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_TILES_LOAD_LABEL] andMessage:[NSString stringWithFormat:@"Error loading tiles into table '%@' in database: '%@'\n\nError: %@", controller.table.name, controller.table.database, error]]; } } @@ -1124,16 +1124,16 @@ - (void)createFeatureTilesViewController:(GPKGSCreateFeatureTilesViewController [self.active setModified:true]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL] andMessage:[NSString stringWithFormat:@"Error creating feature tiles table '%@' for feature table '%@' in database: '%@'\n\nError: %@", controller.nameValue.text, controller.name, controller.database, error]]; } } -- (void)addTileOverlayViewController:(GPKGSAddTileOverlayViewController *)controller featureOverlayTable:(GPKGSFeatureOverlayTable *)featureOverlayTable{ +- (void)addTileOverlayViewController:(GPKGSAddTileOverlayViewController *)controller featureOverlayTable:(MCFeatureOverlayTable *)featureOverlayTable{ if([self.active exists:featureOverlayTable]){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_ADD_FEATURE_OVERLAY_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_ADD_FEATURE_OVERLAY_LABEL] andMessage:[NSString stringWithFormat:@"Feature overlay '%@' already exists in database '%@'. Could not create for feature table '%@'", controller.nameValue.text, controller.table.database, controller.table.name]]; }else{ self.retainModifiedForMap = true; @@ -1142,7 +1142,7 @@ - (void)addTileOverlayViewController:(GPKGSAddTileOverlayViewController *)contro } } -- (void)editTileOverlayViewController:(GPKGSManagerEditTileOverlayViewController *)controller featureOverlayTable:(GPKGSFeatureOverlayTable *)featureOverlayTable{ +- (void)editTileOverlayViewController:(GPKGSManagerEditTileOverlayViewController *)controller featureOverlayTable:(MCFeatureOverlayTable *)featureOverlayTable{ self.retainModifiedForMap = true; [self.active removeTable:featureOverlayTable]; [self.active addTable:featureOverlayTable]; @@ -1155,8 +1155,8 @@ - (void)linkedTablesViewController:(GPKGSLinkedTablesViewController *)controller [self.active setModified:true]; } if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_LINKED_TABLES_LABEL] + [MCUtils showMessageWithDelegate:self + andTitle:[MCProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_LINKED_TABLES_LABEL] andMessage:[NSString stringWithFormat:@"Error editing linked tables for table '%@' in database: '%@'\n\nError: %@", controller.table.name, controller.table.database, error]]; } } @@ -1170,48 +1170,48 @@ -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_DISPLAY_TEXT]){ GPKGSDisplayTextViewController *displayTextViewController = segue.destinationViewController; - if([sender isKindOfClass:[GPKGSDatabase class]]){ - GPKGSDatabase * database = (GPKGSDatabase *)sender; + if([sender isKindOfClass:[MCDatabase class]]){ + MCDatabase * database = (MCDatabase *)sender; displayTextViewController.database = database; - }else if([sender isKindOfClass:[GPKGSTable class]]){ - GPKGSTable * table = (GPKGSTable *)sender; + }else if([sender isKindOfClass:[MCTable class]]){ + MCTable * table = (MCTable *)sender; displayTextViewController.table = table; } }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_CREATE_FEATURES]){ GPKGSCreateFeaturesViewController *createFeaturesViewController = segue.destinationViewController; - GPKGSDatabase * database = (GPKGSDatabase *)sender; + MCDatabase * database = (MCDatabase *)sender; createFeaturesViewController.delegate = self; createFeaturesViewController.database = database; createFeaturesViewController.manager = self.manager; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_CREATE_TILES]){ GPKGSManagerCreateTilesViewController *createTilesViewController = segue.destinationViewController; - GPKGSDatabase * database = (GPKGSDatabase *)sender; + MCDatabase * database = (MCDatabase *)sender; createTilesViewController.delegate = self; createTilesViewController.database = database; createTilesViewController.manager = self.manager; createTilesViewController.data = [[GPKGSCreateTilesData alloc] init]; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_LOAD_TILES]){ GPKGSManagerLoadTilesViewController *loadTilesViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; + MCTable * table = (MCTable *)sender; loadTilesViewController.delegate = self; loadTilesViewController.table = table; loadTilesViewController.manager = self.manager; loadTilesViewController.data = [[GPKGSLoadTilesData alloc] init]; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_EDIT_FEATURES]){ GPKGSEditFeaturesViewController *editFeaturesViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; + MCTable * table = (MCTable *)sender; editFeaturesViewController.table = table; editFeaturesViewController.manager = self.manager; editFeaturesViewController.delegate = self; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_EDIT_TILES]){ GPKGSEditTilesViewController *editTilesViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; + MCTable * table = (MCTable *)sender; editTilesViewController.delegate = self; editTilesViewController.table = table; editTilesViewController.manager = self.manager; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_CREATE_FEATURE_TILES]){ GPKGSCreateFeatureTilesViewController *createFeatureTilesViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; + MCTable * table = (MCTable *)sender; createFeatureTilesViewController.delegate = self; createFeatureTilesViewController.database = table.database; createFeatureTilesViewController.name = table.name; @@ -1220,19 +1220,19 @@ -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ createFeatureTilesViewController.generateTilesData = [[GPKGSGenerateTilesData alloc] init]; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_ADD_TILE_OVERLAY]){ GPKGSAddTileOverlayViewController *addTileOverlayViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; + MCTable * table = (MCTable *)sender; addTileOverlayViewController.delegate = self; addTileOverlayViewController.table = table; addTileOverlayViewController.manager = self.manager; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_EDIT_TILE_OVERLAY]){ GPKGSManagerEditTileOverlayViewController *editTileOverlayViewController = segue.destinationViewController; - GPKGSFeatureOverlayTable * table = (GPKGSFeatureOverlayTable *)sender; + MCFeatureOverlayTable * table = (MCFeatureOverlayTable *)sender; editTileOverlayViewController.delegate = self; editTileOverlayViewController.table = table; editTileOverlayViewController.manager = self.manager; }else if([segue.identifier isEqualToString:GPKGS_MANAGER_SEG_LINKED_TABLES]){ GPKGSLinkedTablesViewController *linkedTablesViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; + MCTable * table = (MCTable *)sender; linkedTablesViewController.delegate = self; linkedTablesViewController.table = table; linkedTablesViewController.manager = self.manager; diff --git a/mapcache-ios/manager/GPKGSTableOptionsButton.h b/mapcache-ios/manager/GPKGSTableOptionsButton.h index 1284cbc..47fb2af 100644 --- a/mapcache-ios/manager/GPKGSTableOptionsButton.h +++ b/mapcache-ios/manager/GPKGSTableOptionsButton.h @@ -7,10 +7,10 @@ // #import -#import "GPKGSTable.h" +#import "MCTable.h" @interface GPKGSTableOptionsButton : UIButton -@property (nonatomic, strong) GPKGSTable * table; +@property (nonatomic, strong) MCTable * table; @end diff --git a/mapcache-ios/manager/MCDownloadGeopackage.m b/mapcache-ios/manager/MCDownloadGeopackage.m index e25e5dc..e512218 100644 --- a/mapcache-ios/manager/MCDownloadGeopackage.m +++ b/mapcache-ios/manager/MCDownloadGeopackage.m @@ -9,9 +9,9 @@ #import "MCDownloadGeopackage.h" #import "GPKGGeoPackageFactory.h" #import "GPKGIOUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCUtils.h" @interface MCDownloadGeopackage () @@ -35,8 +35,8 @@ - (instancetype) initAsFullView:(BOOL) isFullView withExample:(BOOL) prefillExam - (void)viewDidLoad { [super viewDidLoad]; - [GPKGSUtils disableButton:self.importButton]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + [MCUtils disableButton:self.importButton]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.nameTextField.inputAccessoryView = keyboardToolbar; self.urlTextField.inputAccessoryView = keyboardToolbar; @@ -50,7 +50,7 @@ - (void)viewDidLoad { self.haveScrolled = NO; if (_prefillExample) { - NSArray * urls = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS]; + NSArray * urls = [MCProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS]; NSDictionary * url = (NSDictionary *)[urls objectAtIndex:0]; [self.nameTextField setText:[url objectForKey:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS_NAME]]; [self.urlTextField setText:[url objectForKey:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS_URL]]; @@ -86,10 +86,10 @@ - (IBAction)cancel:(id)sender { if(self.active){ self.active = false; [self.importButton setTitle:@"Import" forState:UIControlStateNormal]; - [GPKGSUtils enableButton:self.preloadedButton]; - [GPKGSUtils enableButton:self.importButton]; - [GPKGSUtils enableTextField:self.urlTextField]; - [GPKGSUtils enableTextField:self.nameTextField]; + [MCUtils enableButton:self.preloadedButton]; + [MCUtils enableButton:self.importButton]; + [MCUtils enableTextField:self.urlTextField]; + [MCUtils enableTextField:self.nameTextField]; [self.cancelButton setHidden:YES]; [self.downloadedLabel setHidden:YES]; [self.progressView setHidden:YES]; @@ -100,13 +100,13 @@ - (IBAction)cancel:(id)sender { - (IBAction)preloaded:(id)sender { NSMutableArray * options = [[NSMutableArray alloc] init]; - NSArray * urls = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS]; + NSArray * urls = [MCProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS]; for(NSDictionary * url in urls){ [options addObject:[url objectForKey:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS_LABEL]]; } UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_IMPORT_URL_PRELOADED_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_IMPORT_URL_PRELOADED_LABEL] message:nil delegate:self cancelButtonTitle:nil @@ -115,7 +115,7 @@ - (IBAction)preloaded:(id)sender { for (NSString *option in options) { [alert addButtonWithTitle:option]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_PRELOADED; @@ -128,7 +128,7 @@ -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)button case TAG_PRELOADED: if(buttonIndex >= 0){ - NSArray * urls = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS]; + NSArray * urls = [MCProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS]; if(buttonIndex < [urls count]){ NSDictionary * url = (NSDictionary *)[urls objectAtIndex:buttonIndex]; [self.nameTextField setText:[url objectForKey:GPKGS_PROP_PRELOADED_GEOPACKAGE_URLS_NAME]]; @@ -147,12 +147,12 @@ - (IBAction)import:(id)sender { [self.downloadedLabel setHidden:NO]; [self.progressView setHidden:NO]; - [GPKGSUtils disableButton:self.preloadedButton]; - [GPKGSUtils disableButton:self.importButton]; - [GPKGSUtils disableTextField:self.urlTextField]; - [GPKGSUtils disableTextField:self.nameTextField]; + [MCUtils disableButton:self.preloadedButton]; + [MCUtils disableButton:self.importButton]; + [MCUtils disableTextField:self.urlTextField]; + [MCUtils disableTextField:self.nameTextField]; - GPKGGeoPackageManager * manager = [GPKGGeoPackageFactory getManager]; + GPKGGeoPackageManager * manager = [GPKGGeoPackageFactory manager]; self.active = true; self.progress = [NSNumber numberWithInt:0]; @@ -220,18 +220,18 @@ -(void) failureWithError: (NSString *) error{ #pragma mark- UITextFieldDelegate methods - (void) textFieldDidEndEditing:(UITextField *)textField { - [textField trimWhiteSpace:textField]; + [textField trimWhiteSpace]; if (textField == self.urlTextField) { NSLog(@"URL Field ended editing"); [self validateURLField]; } else { if ([self.nameTextField.text isEqualToString:@""] || [self.urlTextField.text isEqualToString:@""]) { - [GPKGSUtils disableButton:self.importButton]; + [MCUtils disableButton:self.importButton]; [self.downloadedLabel setText:@"Check your GeoPackage's name and URL"]; self.downloadedLabel.hidden = NO; } else { - [GPKGSUtils enableButton:self.importButton]; + [MCUtils enableButton:self.importButton]; [self.downloadedLabel setText:@""]; self.downloadedLabel.hidden = YES; } @@ -251,14 +251,14 @@ - (void) validateURLField { self.urlTextField.layer.borderColor = [[UIColor colorWithRed:0.79 green:0.8 blue:0.8 alpha:1] CGColor]; self.urlTextField.layer.borderWidth = 0.5; - [GPKGSUtils enableButton:self.importButton]; + [MCUtils enableButton:self.importButton]; [self.downloadedLabel setText:@""]; self.downloadedLabel.hidden = YES; }); } else { NSLog(@"Bad url"); dispatch_async(dispatch_get_main_queue(), ^{ - [GPKGSUtils disableButton:self.importButton]; + [MCUtils disableButton:self.importButton]; [self.downloadedLabel setText:@"Invalid URL"]; self.downloadedLabel.hidden = NO; diff --git a/mapcache-ios/map/GPKGSDownloadTilesViewController.m b/mapcache-ios/map/GPKGSDownloadTilesViewController.m index 54810bd..73729f5 100644 --- a/mapcache-ios/map/GPKGSDownloadTilesViewController.m +++ b/mapcache-ios/map/GPKGSDownloadTilesViewController.m @@ -7,14 +7,14 @@ // #import "GPKGSDownloadTilesViewController.h" -#import "GPKGSUtils.h" +#import "MCUtils.h" #import "GPKGSCreateTilesViewController.h" #import "SFPProjectionTransform.h" #import "SFPProjectionConstants.h" #import "GPKGTileBoundingBoxUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSLoadTilesTask.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCLoadTilesTask.h" NSString * const GPKGS_DOWNLOAD_TILES_SEG_CREATE_TILES = @"createTiles"; @@ -31,7 +31,7 @@ @implementation GPKGSDownloadTilesViewController - (void)viewDidLoad { [super viewDidLoad]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.databaseValue.inputAccessoryView = keyboardToolbar; } @@ -66,7 +66,7 @@ - (IBAction)existingButton:(id)sender { self.existing = [self.manager databases]; UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_CREATE_TILES_EXISTING_GEOPACKAGE_DIALOG_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_CREATE_TILES_EXISTING_GEOPACKAGE_DIALOG_LABEL] message:nil delegate:self cancelButtonTitle:nil @@ -75,7 +75,7 @@ - (IBAction)existingButton:(id)sender { for (NSString *database in self.existing) { [alert addButtonWithTitle:database]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_EXISTING_GEOPACKAGES; @@ -122,10 +122,10 @@ - (IBAction)downloadButton:(id)sender { [self.manager create:database]; } - GPKGTileScaling *scaling = [GPKGSLoadTilesTask tileScaling]; + GPKGTileScaling *scaling = [MCLoadTilesTask tileScaling]; // Load tiles - [GPKGSLoadTilesTask loadTilesWithCallback:self andDatabase:database andTable:tableName andUrl:url andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andStandardFormat:generateTiles.standardWebMercatorFormat andBoundingBox:boundingBox andTileScaling:scaling andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",loadTiles.epsg] andLabel:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_CREATE_TILES_DIALOG_LABEL]]; + [MCLoadTilesTask loadTilesWithCallback:self andDatabase:database andTable:tableName andUrl:url andMinZoom:minZoom andMaxZoom:maxZoom andCompressFormat:generateTiles.compressFormat andCompressQuality:[generateTiles.compressQuality intValue] andCompressScale:[generateTiles.compressScale intValue] andXyzTiles:generateTiles.xyzTiles andBoundingBox:boundingBox andTileScaling:scaling andAuthority:PROJ_AUTHORITY_EPSG andCode:[NSString stringWithFormat:@"%d",loadTiles.epsg] andLabel:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_CREATE_TILES_DIALOG_LABEL]]; } @catch (NSException *e) { @@ -148,8 +148,8 @@ -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ SFPProjectionTransform * webMercatorTransform = [[SFPProjectionTransform alloc] initWithFromEpsg:PROJ_EPSG_WORLD_GEODETIC_SYSTEM andToEpsg:PROJ_EPSG_WEB_MERCATOR]; GPKGBoundingBox * webMercatorBoundingBox = [self.data.loadTiles.generateTiles.boundingBox transform:webMercatorTransform]; - int zoomLevel = [GPKGTileBoundingBoxUtils getZoomLevelWithWebMercatorBoundingBox:webMercatorBoundingBox]; - int maxZoomLevel = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT] intValue]; + int zoomLevel = [GPKGTileBoundingBoxUtils zoomLevelWithWebMercatorBoundingBox:webMercatorBoundingBox]; + int maxZoomLevel = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT] intValue]; zoomLevel = MAX(0, MIN(zoomLevel, maxZoomLevel - 2)); self.data.loadTiles.generateTiles.minZoom = [NSNumber numberWithInt:zoomLevel]; self.data.loadTiles.generateTiles.maxZoom = [NSNumber numberWithInt:maxZoomLevel]; diff --git a/mapcache-ios/map/GPKGSMapView.h b/mapcache-ios/map/GPKGSMapView.h deleted file mode 100644 index 31a2e0e..0000000 --- a/mapcache-ios/map/GPKGSMapView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// GPKGSMapView.h -// mapcache-ios -// -// Created by Brian Osborn on 7/10/15. -// Copyright (c) 2015 NGA. All rights reserved. -// - -#import - -@interface GPKGSMapView : MKMapView - -@end diff --git a/mapcache-ios/map/GPKGSMapView.m b/mapcache-ios/map/GPKGSMapView.m deleted file mode 100644 index ccb4d57..0000000 --- a/mapcache-ios/map/GPKGSMapView.m +++ /dev/null @@ -1,21 +0,0 @@ -// -// GPKGSMapView.m -// mapcache-ios -// -// Created by Brian Osborn on 7/10/15. -// Copyright (c) 2015 NGA. All rights reserved. -// - -#import "GPKGSMapView.h" - -@implementation GPKGSMapView - -/* -// Only override drawRect: if you perform custom drawing. -// An empty implementation adversely affects performance during animation. -- (void)drawRect:(CGRect)rect { - // Drawing code -} -*/ - -@end diff --git a/mapcache-ios/map/GPKGSMapViewController.h b/mapcache-ios/map/GPKGSMapViewController.h deleted file mode 100644 index 6bd9623..0000000 --- a/mapcache-ios/map/GPKGSMapViewController.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// GPKGSMapViewController.h -// mapcache-ios -// -// Created by Brian Osborn on 7/13/15. -// Copyright (c) 2015 NGA. All rights reserved. -// - -#import -#import "GPKGSMapView.h" -#import "GPKGSDownloadTilesViewController.h" -#import "GPKGSSelectFeatureTableViewController.h" -#import "GPKGSCreateFeatureTilesViewController.h" - -@interface GPKGSMapViewController : UIViewController - -@property (weak, nonatomic) IBOutlet GPKGSMapView *mapView; -@property (weak, nonatomic) IBOutlet UIButton *boundingBoxButton; -@property (weak, nonatomic) IBOutlet UIButton *featuresButton; -@property (weak, nonatomic) IBOutlet UIButton *downloadTilesButton; -@property (weak, nonatomic) IBOutlet UIButton *featureTilesButton; -@property (weak, nonatomic) IBOutlet UIButton *boundingBoxClearButton; -@property (weak, nonatomic) IBOutlet UIButton *drawPointButton; -@property (weak, nonatomic) IBOutlet UIButton *drawLineButton; -@property (weak, nonatomic) IBOutlet UIButton *drawPolygonButton; -@property (weak, nonatomic) IBOutlet UIButton *editFeaturesConfirmButton; -@property (weak, nonatomic) IBOutlet UIButton *editFeaturesClearButton; -@property (weak, nonatomic) IBOutlet UIButton *drawPolygonHoleButton; -@property (weak, nonatomic) IBOutlet UIButton *editPolygonHoleConfirmButton; -@property (weak, nonatomic) IBOutlet UIButton *editPolygonHoleClearButton; - -@end diff --git a/mapcache-ios/map/GPKGSMapViewController.m b/mapcache-ios/map/GPKGSMapViewController.m deleted file mode 100644 index f157761..0000000 --- a/mapcache-ios/map/GPKGSMapViewController.m +++ /dev/null @@ -1,2892 +0,0 @@ -// -// GPKGSMapViewController.m -// mapcache-ios -// -// Created by Brian Osborn on 7/13/15. -// Copyright (c) 2015 NGA. All rights reserved. -// - -#import "GPKGSMapViewController.h" -#import -#import "GPKGGeoPackageManager.h" -#import "GPKGSDatabases.h" -#import "GPKGGeoPackageFactory.h" -#import "GPKGSTileTable.h" -#import "GPKGOverlayFactory.h" -#import "SFPProjectionTransform.h" -#import "SFPProjectionConstants.h" -#import "SFPProjectionFactory.h" -#import "GPKGTileBoundingBoxUtils.h" -#import "GPKGSFeatureOverlayTable.h" -#import "GPKGMapShapeConverter.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGFeatureTiles.h" -#import "GPKGFeatureOverlay.h" -#import "GPKGSUtils.h" -#import "GPKGUtils.h" -#import "GPKGSDownloadTilesViewController.h" -#import "GPKGSCreateTilesData.h" -#import "GPKGSSelectFeatureTableViewController.h" -#import "GPKGSCreateFeatureTilesViewController.h" -#import "GPKGSMapPointData.h" -#import "GPKGSEditTypes.h" -#import "GPKGSDisplayTextViewController.h" -#import "SFGeometryPrinter.h" -#import "GPKGShapePoints.h" -#import "GPKGShapeWithChildrenPoints.h" -#import "GPGKSMapPointInitializer.h" -#import "GPKGNumberFeaturesTile.h" -#import "GPKGFeatureOverlayQuery.h" -#import "GPKGFeatureTileTableLinker.h" -#import "GPKGFeatureShapes.h" -#import "GPKGMapUtils.h" -#import "SFGeometryEnvelopeBuilder.h" -#import "GPKGMultipleFeatureIndexResults.h" -#import "GPKGFeatureIndexListResults.h" -#import "GPKGTileTableScaling.h" -#import "GPKGGeoPackageCache.h" -#import "GPKGStyleCache.h" - -NSString * const GPKGS_MAP_SEG_DOWNLOAD_TILES = @"downloadTiles"; -NSString * const GPKGS_MAP_SEG_SELECT_FEATURE_TABLE = @"selectFeatureTable"; -NSString * const GPKGS_MAP_SEG_FEATURE_TILES_REQUEST = @"featureTiles"; -NSString * const GPKGS_MAP_SEG_EDIT_FEATURES_REQUEST = @"editFeatures"; -NSString * const GPKGS_MAP_SEG_CREATE_FEATURE_TILES = @"createFeatureTiles"; -NSString * const GPKGS_MAP_SEG_DISPLAY_TEXT = @"displayText"; - -const char MapConstantKey; - -@interface GPKGSMapViewController () -@property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSDatabases *active; -@property (nonatomic, strong) GPKGGeoPackageCache * geoPackages; -@property (nonatomic, strong) NSMutableDictionary * featureDaos; -@property (nonatomic, strong) GPKGBoundingBox * featuresBoundingBox; -@property (nonatomic, strong) GPKGBoundingBox * tilesBoundingBox; -@property (nonatomic) BOOL featureOverlayTiles; -@property (strong, nonatomic) CLLocationManager *locationManager; -@property (nonatomic, strong) NSUserDefaults * settings; -@property (atomic) int updateCountId; -@property (atomic) int featureUpdateCountId; -@property (nonatomic) BOOL boundingBoxMode; -@property (nonatomic) BOOL editFeaturesMode; -@property (nonatomic) CLLocationCoordinate2D boundingBoxStartCorner; -@property (nonatomic) CLLocationCoordinate2D boundingBoxEndCorner; -@property (nonatomic, strong) GPKGPolygon * boundingBox; -@property (nonatomic) BOOL drawing; -@property (nonatomic, strong) NSString * editFeaturesDatabase; -@property (nonatomic, strong) NSString * editFeaturesTable; -@property (nonatomic, strong) NSMutableDictionary * editFeatureIds; -@property (nonatomic, strong) NSMutableDictionary * editFeatureObjects; -@property (nonatomic) enum GPKGSEditType editFeatureType; -@property (nonatomic, strong) NSMutableArray * editPoints; -@property (nonatomic, strong) NSMutableArray * editHolePoints; -@property (nonatomic, strong) GPKGMapPoint * editFeatureMapPoint; -@property (nonatomic, strong) GPKGMapPoint * tempEditFeatureMapPoint; -@property (nonatomic, strong) GPKGMapShapePoints * editFeatureShape; -@property (nonatomic, strong) NSObject * editFeatureShapePoints; -@property (nonatomic, strong) MKPolyline * editLinestring; -@property (nonatomic, strong) MKPolygon * editPolygon; -@property (nonatomic, strong) NSMutableArray * holePolygons; -@property (nonatomic, strong) UIColor * boundingBoxColor; -@property (nonatomic) double boundingBoxLineWidth; -@property (nonatomic, strong) UIColor * boundingBoxFillColor; -@property (nonatomic, strong) UIColor * defaultPolylineColor; -@property (nonatomic) double defaultPolylineLineWidth; -@property (nonatomic, strong) UIColor * defaultPolygonColor; -@property (nonatomic) double defaultPolygonLineWidth; -@property (nonatomic, strong) UIColor * defaultPolygonFillColor; -@property (nonatomic, strong) UIColor * editPolylineColor; -@property (nonatomic) double editPolylineLineWidth; -@property (nonatomic, strong) UIColor * editPolygonColor; -@property (nonatomic) double editPolygonLineWidth; -@property (nonatomic, strong) UIColor * editPolygonFillColor; -@property (nonatomic, strong) UIColor * drawPolylineColor; -@property (nonatomic) double drawPolylineLineWidth; -@property (nonatomic, strong) UIColor * drawPolygonColor; -@property (nonatomic) double drawPolygonLineWidth; -@property (nonatomic, strong) UIColor * drawPolygonFillColor; -@property (nonatomic) BOOL internalSeg; -@property (nonatomic, strong) NSString * segRequest; -@property (nonatomic, strong) GPKGMapPoint * selectedMapPoint; -@property (nonatomic, strong) NSNumberFormatter *locationDecimalFormatter; -@property (nonatomic, strong) NSMutableArray * featureOverlayQueries; -@property (nonatomic, strong) GPKGFeatureShapes * featureShapes; -@property (nonatomic) int currentZoom; -@property (nonatomic) BOOL needsInitialZoom; -@property (nonatomic) BOOL ignoreRegionChange; - -@end - -@implementation GPKGSMapViewController - -#define TAG_MAP_TYPE 1 -#define TAG_MAX_FEATURES 2 -#define TAG_EXISTING_FEATURE 3 -#define TAG_DELETE_EXISTING_FEATURE 4 -#define TAG_CLEAR_EDIT_FEATURES 5 -#define TAG_DELETE_EDIT_POINT 6 -#define TAG_EDIT_FEATURE_SHAPE 7 - -static NSString *mapPointImageReuseIdentifier = @"mapPointImageReuseIdentifier"; -static NSString *mapPointPinReuseIdentifier = @"mapPointPinReuseIdentifier"; - -- (void)viewDidLoad { - [super viewDidLoad]; - self.updateCountId = 0; - self.featureUpdateCountId = 0; - self.settings = [NSUserDefaults standardUserDefaults]; - self.mapView.delegate = self; - self.mapView.showsUserLocation = YES; - self.manager = [GPKGGeoPackageFactory getManager]; - self.active = [GPKGSDatabases getInstance]; - self.geoPackages = [[GPKGGeoPackageCache alloc] initWithManager:self.manager]; - self.featureDaos = [[NSMutableDictionary alloc] init]; - self.locationManager = [[CLLocationManager alloc] init]; - [self.locationManager setDelegate:self]; - [self.locationManager requestWhenInUseAuthorization]; - self.editFeatureIds = [[NSMutableDictionary alloc] init]; - self.editFeatureObjects = [[NSMutableDictionary alloc] init]; - self.editFeatureType = GPKGS_ET_NONE; - self.editPoints = [[NSMutableArray alloc] init]; - self.editHolePoints = [[NSMutableArray alloc] init]; - self.holePolygons = [[NSMutableArray alloc] init]; - self.featureOverlayQueries = [[NSMutableArray alloc] init]; - self.featureShapes = [[GPKGFeatureShapes alloc] init]; - self.currentZoom = -1; - self.needsInitialZoom = true; - self.ignoreRegionChange = false; - [self resetBoundingBox]; - [self resetEditFeatures]; - UITapGestureRecognizer * singleTapGesture = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(singleTapGesture:)]; - singleTapGesture.numberOfTapsRequired = 1; - [self.mapView addGestureRecognizer:singleTapGesture]; - UITapGestureRecognizer * doubleTapGesture = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(doubleTapGesture:)]; - doubleTapGesture.numberOfTapsRequired = 2; - [self.mapView addGestureRecognizer:doubleTapGesture]; - [self.mapView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] - initWithTarget:self action:@selector(longPressGesture:)]]; - [singleTapGesture requireGestureRecognizerToFail:doubleTapGesture]; - self.boundingBoxStartCorner = kCLLocationCoordinate2DInvalid; - self.boundingBoxEndCorner = kCLLocationCoordinate2DInvalid; - - self.boundingBoxColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_COLOR]]; - self.boundingBoxLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_FILL]){ - self.boundingBoxFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_FILL_COLOR]]; - } - - self.defaultPolylineColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYLINE_COLOR]]; - self.defaultPolylineLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DEFAULT_POLYLINE_LINE_WIDTH] doubleValue]; - - self.defaultPolygonColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYGON_COLOR]]; - self.defaultPolygonLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DEFAULT_POLYGON_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_DEFAULT_POLYGON_FILL]){ - self.defaultPolygonFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYGON_FILL_COLOR]]; - } - - self.editPolylineColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYLINE_COLOR]]; - self.editPolylineLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_EDIT_POLYLINE_LINE_WIDTH] doubleValue]; - - self.editPolygonColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYGON_COLOR]]; - self.editPolygonLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_EDIT_POLYGON_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_EDIT_POLYGON_FILL]){ - self.editPolygonFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYGON_FILL_COLOR]]; - } - - self.drawPolylineColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYLINE_COLOR]]; - self.drawPolylineLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DRAW_POLYLINE_LINE_WIDTH] doubleValue]; - - self.drawPolygonColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYGON_COLOR]]; - self.drawPolygonLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DRAW_POLYGON_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_DRAW_POLYGON_FILL]){ - self.drawPolygonFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYGON_FILL_COLOR]]; - } - - self.locationDecimalFormatter = [[NSNumberFormatter alloc] init]; - self.locationDecimalFormatter.numberStyle = NSNumberFormatterDecimalStyle; - self.locationDecimalFormatter.maximumFractionDigits = 4; - - [self.active setModified:true]; -} - -- (void) viewWillAppear:(BOOL)animated{ - [super viewWillAppear:animated]; - - if(self.internalSeg){ - self.internalSeg = false; - }else{ - if(self.active.modified){ - [self.active setModified:false]; - [self resetBoundingBox]; - [self resetEditFeatures]; - [self updateInBackgroundWithZoom:true]; - } - } -} - -- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay { - MKOverlayRenderer * rendered = nil; - if ([overlay isKindOfClass:[MKPolygon class]]) { - MKPolygonRenderer * polygonRenderer = [[MKPolygonRenderer alloc] initWithPolygon:overlay]; - UIColor *strokeColor = self.defaultPolygonColor; - double lineWidth = self.defaultPolygonLineWidth; - UIColor *fillColor = self.defaultPolygonFillColor; - if ([overlay isKindOfClass:[GPKGPolygon class]]) { - GPKGPolygon *polygon = (GPKGPolygon *) overlay; - GPKGPolygonOptions *options = polygon.options; - if(options != nil){ - if(options.strokeColor != nil){ - strokeColor = options.strokeColor; - fillColor = nil; - } - if(options.lineWidth > 0){ - lineWidth = options.lineWidth; - } - if(options.fillColor != nil){ - fillColor = options.fillColor; - } - } - } - polygonRenderer.strokeColor = strokeColor; - polygonRenderer.lineWidth = lineWidth; - if(fillColor != nil){ - polygonRenderer.fillColor = fillColor; - } - rendered = polygonRenderer; - }else if ([overlay isKindOfClass:[MKPolyline class]]) { - MKPolylineRenderer * polylineRenderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay]; - UIColor *strokeColor = self.defaultPolylineColor; - double lineWidth = self.defaultPolylineLineWidth; - if ([overlay isKindOfClass:[GPKGPolyline class]]) { - GPKGPolyline *polyline = (GPKGPolyline *) overlay; - GPKGPolylineOptions *options = polyline.options; - if(options != nil){ - if(options.strokeColor != nil){ - strokeColor = options.strokeColor; - } - if(options.lineWidth > 0){ - lineWidth = options.lineWidth; - } - } - } - polylineRenderer.strokeColor = strokeColor; - polylineRenderer.lineWidth = lineWidth; - rendered = polylineRenderer; - }else if ([overlay isKindOfClass:[MKTileOverlay class]]) { - rendered = [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay]; - } - return rendered; -} - -- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id ) annotation -{ - MKAnnotationView * view = nil; - - if ([annotation isKindOfClass:[GPKGMapPoint class]]){ - - GPKGMapPoint * mapPoint = (GPKGMapPoint *) annotation; - - if(mapPoint.options.image != nil){ - - MKAnnotationView *mapPointImageView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:mapPointImageReuseIdentifier]; - if (mapPointImageView == nil) - { - mapPointImageView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:mapPointImageReuseIdentifier]; - } - mapPointImageView.image = mapPoint.options.image; - mapPointImageView.centerOffset = mapPoint.options.imageCenterOffset; - - view = mapPointImageView; - - }else{ - MKPinAnnotationView *mapPointPinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:mapPointPinReuseIdentifier]; - if(mapPointPinView == nil){ - mapPointPinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:mapPointPinReuseIdentifier]; - } - mapPointPinView.pinTintColor = mapPoint.options.pinTintColor; - view = mapPointPinView; - } - - if(mapPoint.title == nil){ - [self setTitleWithMapPoint:mapPoint]; - } - - UIButton *optionsButton = [UIButton buttonWithType:UIButtonTypeInfoDark]; - [optionsButton addTarget:self action:@selector(selectedMapPointOptions:) forControlEvents:UIControlEventTouchUpInside]; - - view.rightCalloutAccessoryView = optionsButton; - view.canShowCallout = YES; - - view.draggable = mapPoint.options.draggable; - } - return view; -} - -//-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { -// -//} - --(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ - - if(self.ignoreRegionChange){ - self.ignoreRegionChange = false; - }else{ - - // If not editing a shape, update the feature shapes for the current map view region - if(!self.editFeaturesMode || self.editFeatureType == GPKGS_ET_NONE || ([self.editPoints count] == 0 && self.editFeatureMapPoint == nil)){ - - int updateId = ++self.featureUpdateCountId; - - int previousZoom = self.currentZoom; - int zoom = (int)[GPKGMapUtils currentZoomWithMapView:self.mapView]; - self.currentZoom = zoom; - if(zoom != previousZoom){ - // Zoom level changed, remove all feature shapes except for markers - [self.featureShapes removeShapesFromMapView:mapView withExclusions:[[NSSet alloc] initWithObjects:[NSNumber numberWithInt:GPKG_MST_POINT], [NSNumber numberWithInt:GPKG_MST_MULTI_POINT], nil]]; - }else{ - // Remove shapes no longer visible on the map view - [self.featureShapes removeShapesNotWithinMapView:mapView]; - } - - GPKGBoundingBox *mapViewBoundingBox = [GPKGMapUtils boundingBoxOfMapView:self.mapView]; - double toleranceDistance = [GPKGMapUtils toleranceDistanceInMapView:self.mapView]; - - int maxFeatures = [self getMaxFeatures]; - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul); - dispatch_async(queue, ^{ - [self addFeaturesWithId:updateId andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:YES]; - }); - } - } -} - --(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - - switch(alertView.tag){ - case TAG_MAP_TYPE: - [self handleMapTypeWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - case TAG_MAX_FEATURES: - [self handleMaxFeaturesWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - case TAG_EXISTING_FEATURE: - [self handleEditExistingFeatureWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - case TAG_DELETE_EXISTING_FEATURE: - [self handleDeleteExistingFeatureWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - case TAG_CLEAR_EDIT_FEATURES: - [self handleClearEditFeaturesWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - case TAG_DELETE_EDIT_POINT: - [self handleDeleteEditPointWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - case TAG_EDIT_FEATURE_SHAPE: - [self handleEditFeatureShapeWithAlertView:alertView clickedButtonAtIndex:buttonIndex]; - break; - } -} - -- (IBAction) selectedMapPointOptions:(id)sender { - - if(self.selectedMapPoint != nil){ - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:self.selectedMapPoint]; - switch(data.type){ - case GPKGS_MPDT_EDIT_FEATURE_POINT: - [self editFeatureShapeClickWithMapPoint:self.selectedMapPoint]; - break; - case GPKGS_MPDT_EDIT_FEATURE: - // Handle clicks on an existing feature in edit mode - [self editExistingFeatureClickWithMapPoint:self.selectedMapPoint]; - break; - case GPKGS_MPDT_NEW_EDIT_POINT: - case GPKGS_MPDT_NEW_EDIT_HOLE_POINT: - [self editPointClickWithMapPoint:self.selectedMapPoint]; - break; - case GPKGS_MPDT_POINT: - case GPKGS_MPDT_NONE: - // Handle clicks on normal map points or points within geometries - [self performSegueWithIdentifier:GPKGS_MAP_SEG_DISPLAY_TEXT sender:self.selectedMapPoint]; - break; - default: - break; - } - } - -} - --(void) editFeatureShapeClickWithMapPoint: (GPKGMapPoint *) mapPoint{ - - NSObject * shapePoints = [self.editFeatureShape getShapePointsForPoint:mapPoint]; - - if(shapePoints != nil){ - - NSMutableArray * options = [[NSMutableArray alloc] init]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_SHAPE_POINT_DELETE_LABEL]]; - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_SHAPE_ADD_POINTS_LABEL]]; - - if([[shapePoints class] conformsToProtocol:@protocol(GPKGShapeWithChildrenPoints)]){ - [options addObject:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_SHAPE_ADD_HOLE_LABEL]]; - } - - UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[self getTitleAndSubtitleWithMapPoint:mapPoint andDelimiter:@"\n"] - message:nil - delegate:self - cancelButtonTitle:nil - otherButtonTitles:nil]; - - for (NSString *option in options) { - [alert addButtonWithTitle:option]; - } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; - - alert.tag = TAG_EDIT_FEATURE_SHAPE; - - objc_setAssociatedObject(alert, &MapConstantKey, mapPoint, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - - [alert show]; - }else{ - // Click on an actual point being edited - [self performSegueWithIdentifier:GPKGS_MAP_SEG_DISPLAY_TEXT sender:mapPoint]; - } -} - -- (void) handleEditFeatureShapeWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - - if(buttonIndex >= 0){ - - GPKGMapPoint *mapPoint = objc_getAssociatedObject(alertView, &MapConstantKey); - NSObject * shapePoints = [self.editFeatureShape getShapePointsForPoint:mapPoint]; - - switch(buttonIndex){ - case 0: - [self.editFeatureShape deletePoint:mapPoint fromMapView:self.mapView]; - [self updateEditState:true]; - break; - case 1: - self.editFeatureShapePoints = shapePoints; - break; - case 2: - if([[shapePoints class] conformsToProtocol:@protocol(GPKGShapeWithChildrenPoints)]){ - NSObject * shapeWithChildrenPoints = (NSObject *) shapePoints; - self.editFeatureShapePoints = [shapeWithChildrenPoints createChild]; - } - break; - default: - break; - } - } -} - --(void) editExistingFeatureClickWithMapPoint: (GPKGMapPoint *) mapPoint{ - - UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[self getTitleAndSubtitleWithMapPoint:mapPoint andDelimiter:@"\n"] - message:nil - delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_INFO_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_EDIT_LABEL], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL], - nil]; - - alert.tag = TAG_EXISTING_FEATURE; - - objc_setAssociatedObject(alert, &MapConstantKey, mapPoint, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - - [alert show]; -} - -- (void) handleEditExistingFeatureWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - - if(buttonIndex > 0){ - - GPKGMapPoint *mapPoint = objc_getAssociatedObject(alertView, &MapConstantKey); - - switch(buttonIndex){ - case 1: - [self performSegueWithIdentifier:GPKGS_MAP_SEG_DISPLAY_TEXT sender:mapPoint]; - break; - case 2: - self.tempEditFeatureMapPoint = mapPoint; - [self validateAndClearEditFeaturesForType:GPKGS_ET_EDIT_FEATURE]; - break; - case 3: - [self deleteExistingFeatureOptionWithMapPoint:mapPoint]; - break; - } - - } -} - --(void) deleteExistingFeatureOptionWithMapPoint: (GPKGMapPoint *) mapPoint{ - - UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"%@ %@", [GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL], [self getTitleAndSubtitleWithMapPoint:mapPoint andDelimiter:@" "]] - message:[NSString stringWithFormat:@"%@ %@ from %@ - %@ %@ ?", [GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL], mapPoint.title, self.editFeaturesDatabase, self.editFeaturesTable, mapPoint.subtitle] - delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL], - nil]; - objc_setAssociatedObject(alert, &MapConstantKey, mapPoint, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - alert.tag = TAG_DELETE_EXISTING_FEATURE; - [alert show]; - -} - -- (void) handleDeleteExistingFeatureWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - - if(buttonIndex > 0){ - - GPKGMapPoint *mapPoint = objc_getAssociatedObject(alertView, &MapConstantKey); - - GPKGGeoPackage * geoPackage = [self.manager open:self.editFeaturesDatabase]; - @try { - - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.editFeaturesTable]; - - NSNumber * mapPointId = [mapPoint getIdAsNumber]; - NSNumber * featureId = [self.editFeatureIds objectForKey:mapPointId]; - if(featureId != nil){ - GPKGFeatureRow * featureRow = (GPKGFeatureRow *)[featureDao queryForIdObject:featureId]; - - if(featureRow != nil){ - [featureDao delete:featureRow]; - [self.mapView removeAnnotation:mapPoint]; - [self.editFeatureIds removeObjectForKey:mapPointId]; - GPKGMapShape * featureObject = [self.editFeatureObjects objectForKey:mapPointId]; - if(featureObject != nil){ - [self.editFeatureObjects removeObjectForKey:mapPointId]; - [featureObject removeFromMapView:self.mapView]; - } - [self updateLastChangeWithGeoPackage:geoPackage andFeatureDao:featureDao]; - - [self.active setModified:true]; - } - } - - } - @catch (NSException *e) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL] - andMessage:[NSString stringWithFormat:@"%@", [e description]]]; - } - @finally { - [geoPackage close]; - } - } -} - --(void) expandBoundsWithGeoPackage: (GPKGGeoPackage *) geoPackage andFeatureDao: (GPKGFeatureDao *) featureDao andGeometry: (SFGeometry *) geometry{ - if(geometry != nil){ - @try { - GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage getGeometryColumnsDao]; - GPKGContents * contents = [geometryColumnsDao getContents:featureDao.geometryColumns]; - GPKGBoundingBox *boundingBox = [contents getBoundingBox]; - if(boundingBox != nil){ - - SFGeometryEnvelope *envelope = [SFGeometryEnvelopeBuilder buildEnvelopeWithGeometry:geometry]; - GPKGBoundingBox *geometryBoundingBox = [[GPKGBoundingBox alloc] initWithGeometryEnvelope:envelope]; - GPKGBoundingBox *unionBoundingBox = [boundingBox union:geometryBoundingBox]; - - [contents setBoundingBox:unionBoundingBox]; - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; - [contentsDao update:contents]; - } - - } - @catch (NSException *e) { - NSLog(@"Failed to update contents bounding box. GeoPackage: %@, Table: %@, Error:%@", geoPackage.name, featureDao.tableName, [e description]); - } - } -} - --(void) updateLastChangeWithGeoPackage: (GPKGGeoPackage *) geoPackage andFeatureDao: (GPKGFeatureDao *) featureDao{ - @try { - GPKGGeometryColumnsDao * geometryColumnsDao = [geoPackage getGeometryColumnsDao]; - GPKGContents * contents = [geometryColumnsDao getContents:featureDao.geometryColumns]; - [contents setLastChange:[NSDate date]]; - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; - [contentsDao update:contents]; - } - @catch (NSException *e) { - NSLog(@"Failed to update contents last change date. GeoPackage: %@, Table: %@, Error:%@", geoPackage.name, featureDao.tableName, [e description]); - } -} - --(void) editPointClickWithMapPoint: (GPKGMapPoint *) mapPoint{ - - UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL] - message:[NSString stringWithFormat:@"%@ %@ ?", [GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL], [self getTitleAndSubtitleWithMapPoint:mapPoint andDelimiter:@" "]] - delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_DELETE_LABEL], - nil]; - objc_setAssociatedObject(alert, &MapConstantKey, mapPoint, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - alert.tag = TAG_DELETE_EDIT_POINT; - [alert show]; -} - --(void) handleDeleteEditPointWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - - if(buttonIndex > 0){ - - GPKGMapPoint *mapPoint = objc_getAssociatedObject(alertView, &MapConstantKey); - - NSMutableArray * points = nil; - - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - switch(data.type){ - case GPKGS_MPDT_NEW_EDIT_POINT: - points = self.editPoints; - break; - case GPKGS_MPDT_NEW_EDIT_HOLE_POINT: - points = self.editHolePoints; - break; - default: - break; - } - - if(points != nil){ - - [points removeObject:mapPoint]; - [self.mapView removeAnnotation:mapPoint]; - - [self updateEditState:true]; - } - } -} - -- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState { - if ([view.annotation isKindOfClass:[GPKGMapPoint class]]) { - if (newState == MKAnnotationViewDragStateEnding) { - view.dragState = MKAnnotationViewDragStateNone; - } - GPKGMapPoint * mapPoint = (GPKGMapPoint *) view.annotation; - [self updateTitleWithMapPoint:mapPoint]; - [self updateEditState:false]; - } -} - -- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{ - - if ([view.annotation isKindOfClass:[GPKGMapPoint class]]) { - self.selectedMapPoint = (GPKGMapPoint *) view.annotation; - } - -} - --(void) singleTapGesture:(UITapGestureRecognizer *) tapGestureRecognizer{ - - if(!self.editFeaturesMode && tapGestureRecognizer.state == UIGestureRecognizerStateEnded){ - - NSMutableString * clickMessage = [[NSMutableString alloc] init]; - - if(self.featureOverlayQueries.count > 0){ - CGPoint cgPoint = [tapGestureRecognizer locationInView:self.mapView]; - CLLocationCoordinate2D point = [self.mapView convertPoint:cgPoint toCoordinateFromView:self.mapView]; - - for(GPKGFeatureOverlayQuery * query in self.featureOverlayQueries){ - NSString * message = [query buildMapClickMessageWithLocationCoordinate:point andMapView:self.mapView]; - if(message != nil){ - if(clickMessage.length > 0){ - [clickMessage appendString:@"\n\n"]; - } - [clickMessage appendString:message]; - } - } - - } - - for (GPKGSDatabase *database in [self.active getDatabases]) { - if([database getFeatures].count > 0){ - CGPoint cgPoint = [tapGestureRecognizer locationInView:self.mapView]; - CLLocationCoordinate2D point = [self.mapView convertPoint:cgPoint toCoordinateFromView:self.mapView]; - - float screenClickPercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_FEATURE_CLICK_SCREEN_PERCENTAGE] floatValue]; - - GPKGBoundingBox *clickBoundingBox = [GPKGMapUtils buildClickBoundingBoxWithLocationCoordinate:point andMapView:self.mapView andScreenPercentage:screenClickPercentage]; - clickBoundingBox = [clickBoundingBox expandWgs84Coordinates]; - SFPProjection *clickProjection = [SFPProjectionFactory projectionWithEpsgInt:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; - - GPKGMapTolerance *tolerance = [GPKGMapUtils toleranceWithLocationCoordinate:point andMapView:self.mapView andScreenPercentage:screenClickPercentage]; - - for(GPKGSTable *features in [database getFeatures]){ - - GPKGGeoPackage *geoPackage = [self.geoPackages get:database.name]; - NSDictionary *databaseFeatureDaos = [self.featureDaos objectForKey:database.name]; - - if(geoPackage != nil && databaseFeatureDaos != nil){ - - GPKGFeatureDao *featureDao = [databaseFeatureDaos objectForKey:features.name]; - - if (featureDao != nil) { - - GPKGFeatureIndexResults *indexResults = nil; - - GPKGFeatureIndexManager *indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; - @try{ - if ([indexer isIndexed]) { - - indexResults = [indexer queryWithBoundingBox:clickBoundingBox inProjection:clickProjection]; - GPKGBoundingBox *complementary = [clickBoundingBox complementaryWgs84]; - if (complementary != nil) { - GPKGFeatureIndexResults *indexResults2 = [indexer queryWithBoundingBox:complementary inProjection:clickProjection]; - indexResults = [[GPKGMultipleFeatureIndexResults alloc] initWithFeatureIndexResults1:indexResults andFeatureIndexResults2:indexResults2]; - } - - } else { - - SFPProjection *featureProjection = featureDao.projection; - SFPProjectionTransform *projectionTransform = [[SFPProjectionTransform alloc] initWithFromProjection:clickProjection andToProjection:featureProjection]; - GPKGBoundingBox *boundedClickBoundingBox = [clickBoundingBox boundWgs84Coordinates]; - GPKGBoundingBox *transformedBoundingBox = [boundedClickBoundingBox transform:projectionTransform]; - double filterMaxLongitude = 0; - if([featureProjection isUnit:SFP_UNIT_DEGREES]){ - filterMaxLongitude = PROJ_WGS84_HALF_WORLD_LON_WIDTH; - }else if([featureProjection isUnit:SFP_UNIT_METERS]){ - filterMaxLongitude = PROJ_WEB_MERCATOR_HALF_WORLD_WIDTH; - } - - GPKGFeatureIndexListResults *listResults = [[GPKGFeatureIndexListResults alloc] init]; - - // Query for all rows - GPKGResultSet * results = [featureDao queryForAll]; - @try { - while([results moveToNext]){ - @try { - GPKGFeatureRow * row = [featureDao getFeatureRow:results]; - - GPKGGeometryData *geometryData = [row getGeometry]; - if(geometryData != nil && !geometryData.empty){ - - SFGeometry *geometry = geometryData.geometry; - - if (geometry != nil) { - - SFGeometryEnvelope *envelope = geometryData.envelope; - if (envelope == nil) { - envelope = [SFGeometryEnvelopeBuilder buildEnvelopeWithGeometry:geometry]; - } - if (envelope != nil) { - GPKGBoundingBox *geometryBoundingBox = [[GPKGBoundingBox alloc] initWithGeometryEnvelope:envelope]; - - if([GPKGTileBoundingBoxUtils overlapWithBoundingBox:transformedBoundingBox andBoundingBox:geometryBoundingBox withMaxLongitude:filterMaxLongitude] != nil){ - [listResults addRow:row]; - } - - } - } - } - - } @catch (NSException *e) { - NSLog(@"Failed to query feature. database: %@, feature table: %@, Error: %@", - database.name, features.name, [e description]); - } - } - - } @finally { - [results close]; - } - - indexResults = listResults; - } - }@finally{ - [indexer close]; - } - - if ([indexResults count] > 0) { - GPKGFeatureInfoBuilder *featureInfoBuilder = [[GPKGFeatureInfoBuilder alloc] initWithFeatureDao:featureDao]; - [featureInfoBuilder ignoreGeometryType:SF_POINT]; - NSString *message = [featureInfoBuilder buildResultsInfoMessageAndCloseWithFeatureIndexResults:indexResults andTolerance:tolerance andLocationCoordinate:point]; - if(message != nil){ - if(clickMessage.length > 0){ - [clickMessage appendString:@"\n\n"]; - } - [clickMessage appendString:message]; - } - } - } - - } - } - } - } - - if(clickMessage.length > 0){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:nil - andMessage:clickMessage]; - } - } -} - --(void) doubleTapGesture:(UITapGestureRecognizer *) tapGestureRecognizer{ - -} - --(void) longPressGesture:(UILongPressGestureRecognizer *) longPressGestureRecognizer{ - - CGPoint cgPoint = [longPressGestureRecognizer locationInView:self.mapView]; - CLLocationCoordinate2D point = [self.mapView convertPoint:cgPoint toCoordinateFromView:self.mapView]; - - if(self.boundingBoxMode){ - - if(longPressGestureRecognizer.state == UIGestureRecognizerStateBegan){ - - // Check to see if editing any of the bounding box corners - if (self.boundingBox != nil && CLLocationCoordinate2DIsValid(self.boundingBoxEndCorner)) { - - double allowableScreenPercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_TILES_LONG_CLICK_SCREEN_PERCENTAGE] intValue] / 100.0; - if([self isWithinDistanceWithPoint:cgPoint andLocation:self.boundingBoxEndCorner andAllowableScreenPercentage:allowableScreenPercentage]){ - [self setDrawing:true]; - }else if([self isWithinDistanceWithPoint:cgPoint andLocation:self.boundingBoxStartCorner andAllowableScreenPercentage:allowableScreenPercentage]){ - CLLocationCoordinate2D temp = self.boundingBoxStartCorner; - self.boundingBoxStartCorner = self.boundingBoxEndCorner; - self.boundingBoxEndCorner = temp; - [self setDrawing:true]; - }else{ - CLLocationCoordinate2D corner1 = CLLocationCoordinate2DMake(self.boundingBoxStartCorner.latitude, self.boundingBoxEndCorner.longitude); - CLLocationCoordinate2D corner2 = CLLocationCoordinate2DMake(self.boundingBoxEndCorner.latitude, self.boundingBoxStartCorner.longitude); - if([self isWithinDistanceWithPoint:cgPoint andLocation:corner1 andAllowableScreenPercentage:allowableScreenPercentage]){ - self.boundingBoxStartCorner = corner2; - self.boundingBoxEndCorner = corner1; - [self setDrawing:true]; - }else if([self isWithinDistanceWithPoint:cgPoint andLocation:corner2 andAllowableScreenPercentage:allowableScreenPercentage]){ - self.boundingBoxStartCorner = corner1; - self.boundingBoxEndCorner = corner2; - [self setDrawing:true]; - } - } - } - - // Start drawing a new polygon - if(!self.drawing){ - if(self.boundingBox != nil){ - [self.mapView removeOverlay:self.boundingBox]; - } - self.boundingBoxStartCorner = point; - self.boundingBoxEndCorner = point; - CLLocationCoordinate2D * points = [self getPolygonPointsWithPoint1:self.boundingBoxStartCorner andPoint2:self.boundingBoxEndCorner]; - self.boundingBox = [GPKGPolygon polygonWithCoordinates:points count:4]; - [self setBoundingBoxPolygonOptions:self.boundingBox]; - [self.mapView addOverlay:self.boundingBox]; - [self setDrawing:true]; - [self.boundingBoxClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_BOUNDING_BOX_CLEAR_ACTIVE_IMAGE] forState:UIControlStateNormal]; - } - - }else{ - switch(longPressGestureRecognizer.state){ - case UIGestureRecognizerStateChanged: - case UIGestureRecognizerStateEnded: - if(self.boundingBoxMode){ - if(self.drawing && self.boundingBox != nil){ - self.boundingBoxEndCorner = point; - CLLocationCoordinate2D * points = [self getPolygonPointsWithPoint1:self.boundingBoxStartCorner andPoint2:self.boundingBoxEndCorner]; - GPKGPolygon * newBoundingBox = [GPKGPolygon polygonWithCoordinates:points count:4]; - [self setBoundingBoxPolygonOptions:newBoundingBox]; - [self.mapView removeOverlay:self.boundingBox]; - [self.mapView addOverlay:newBoundingBox]; - self.boundingBox = newBoundingBox; - } - if(longPressGestureRecognizer.state == UIGestureRecognizerStateEnded){ - [self setDrawing:false]; - } - } - break; - default: - break; - } - } - } else if(self.editFeatureType != GPKGS_ET_NONE){ - - if(longPressGestureRecognizer.state == UIGestureRecognizerStateBegan){ - if(self.editFeatureType == GPKGS_ET_EDIT_FEATURE){ - if(self.editFeatureShapePoints != nil){ - GPKGMapPoint * mapPoint = [self addEditPoint:point]; - [self.editFeatureShapePoints addNewPoint:mapPoint]; - [self.editFeatureShape addPoint:mapPoint withShape:self.editFeatureShapePoints]; - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - data.type = GPKGS_MPDT_EDIT_FEATURE_POINT; - [self setTitleWithGeometryType:self.editFeatureShape.shape.geometryType andMapPoint:mapPoint]; - [self updateEditState:true]; - } - }else{ - GPKGMapPoint * mapPoint = [self addEditPoint:point]; - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - if(self.editFeatureType == GPKGS_ET_POLYGON_HOLE){ - [self.editHolePoints addObject:mapPoint]; - data.type = GPKGS_MPDT_NEW_EDIT_HOLE_POINT; - }else{ - [self.editPoints addObject:mapPoint]; - data.type = GPKGS_MPDT_NEW_EDIT_POINT; - } - [self setTitleWithTitle:[GPKGSEditTypes pointName:self.editFeatureType] andMapPoint:mapPoint]; - [self updateEditState:true]; - } - } - } -} - --(GPKGMapPoint *) addEditPoint: (CLLocationCoordinate2D) point{ - GPKGMapPoint * mapPoint = [[GPKGMapPoint alloc] initWithLocation:point]; - mapPoint.options.draggable = true; - - switch(self.editFeatureType){ - case GPKGS_ET_POINT: - [mapPoint.options setPinTintColor:[UIColor redColor]]; - break; - case GPKGS_ET_LINESTRING: - case GPKGS_ET_POLYGON: - [mapPoint.options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POINT_IMAGE]]; - [mapPoint.options setPinTintColor:[UIColor greenColor]]; - break; - case GPKGS_ET_POLYGON_HOLE: - [mapPoint.options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_HOLE_POINT_IMAGE]]; - break; - case GPKGS_ET_EDIT_FEATURE: - if([self.editFeatureShapePoints isKindOfClass:[GPKGPolygonHolePoints class]]){ - [mapPoint.options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_HOLE_POINT_IMAGE]]; - }else if([self.editFeatureShapePoints isKindOfClass:[GPKGMultiPoint class]]){ - [mapPoint.options setPinTintColor:[UIColor redColor]]; - }else{ - [mapPoint.options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POINT_IMAGE]]; - } - break; - default: - break; - } - [self.mapView addAnnotation:mapPoint]; - return mapPoint; -} - --(GPKGPolylineOptions *) drawPolylineOptions{ - - GPKGPolylineOptions *options = [[GPKGPolylineOptions alloc] init]; - - [options setStrokeColor:self.drawPolylineColor]; - [options setLineWidth:self.drawPolylineLineWidth]; - - return options; -} - --(GPKGPolygonOptions *) drawPolygonOptions{ - - GPKGPolygonOptions *options = [[GPKGPolygonOptions alloc] init]; - - [options setStrokeColor:self.drawPolygonColor]; - [options setLineWidth:self.drawPolygonLineWidth]; - if(self.drawPolygonFillColor != nil){ - [options setFillColor:self.drawPolygonFillColor]; - } - - return options; -} - --(void) setBoundingBoxPolygonOptions: (GPKGPolygon *) polygon{ - - GPKGPolygonOptions *options = [[GPKGPolygonOptions alloc] init]; - - [options setStrokeColor:self.boundingBoxColor]; - [options setLineWidth:self.boundingBoxLineWidth]; - if(self.boundingBoxFillColor != nil){ - [options setFillColor:self.boundingBoxFillColor]; - } - - [polygon setOptions:options]; -} - --(BOOL) isWithinDistanceWithPoint: (CGPoint) point andLocation: (CLLocationCoordinate2D) location andAllowableScreenPercentage: (double) allowableScreenPercentage{ - - CGPoint locationPoint = [self.mapView convertCoordinate:location toPointToView:self.mapView]; - double distance = sqrt(pow(point.x - locationPoint.x, 2) + pow(point.y - locationPoint.y, 2)); - - BOOL withinDistance = distance / MIN(self.mapView.frame.size.width, self.mapView.frame.size.height) <= allowableScreenPercentage; - return withinDistance; -} - --(CLLocationCoordinate2D *) getPolygonPointsWithPoint1: (CLLocationCoordinate2D) point1 andPoint2: (CLLocationCoordinate2D) point2{ - CLLocationCoordinate2D *coordinates = calloc(4, sizeof(CLLocationCoordinate2D)); - coordinates[0] = CLLocationCoordinate2DMake(point1.latitude, point1.longitude); - coordinates[1] = CLLocationCoordinate2DMake(point1.latitude, point2.longitude); - coordinates[2] = CLLocationCoordinate2DMake(point2.latitude, point2.longitude); - coordinates[3] = CLLocationCoordinate2DMake(point2.latitude, point1.longitude); - return coordinates; -} - -- (IBAction)zoomToActiveButton:(id)sender { - [self zoomToActive]; -} - -- (IBAction)featuresButton:(id)sender { - if(!self.editFeaturesMode){ - self.segRequest = GPKGS_MAP_SEG_EDIT_FEATURES_REQUEST; - [self performSegueWithIdentifier:GPKGS_MAP_SEG_SELECT_FEATURE_TABLE sender:self]; - }else{ - [self resetEditFeatures]; - [self updateInBackgroundWithZoom:false andFilter:true]; - } -} - -- (IBAction)boundingBoxButton:(id)sender { - if(!self.boundingBoxMode){ - - if(self.editFeaturesMode){ - [self resetEditFeatures]; - [self updateInBackgroundWithZoom:false andFilter:true]; - } - - self.boundingBoxMode = true; - [self setBoundingBoxButtonsHidden:false]; - - }else{ - [self resetBoundingBox]; - } -} - -- (IBAction)downloadTilesButton:(id)sender { - [self performSegueWithIdentifier:GPKGS_MAP_SEG_DOWNLOAD_TILES sender:self]; -} - -- (IBAction)featureTilesButton:(id)sender { - self.segRequest = GPKGS_MAP_SEG_FEATURE_TILES_REQUEST; - [self performSegueWithIdentifier:GPKGS_MAP_SEG_SELECT_FEATURE_TABLE sender:self]; -} - -- (IBAction)boundingBoxClearButton:(id)sender { - [self clearBoundingBox]; -} - -- (IBAction)editPointButton:(id)sender { - [self validateAndClearEditFeaturesForType:GPKGS_ET_POINT]; -} - -- (IBAction)editLinestringButton:(id)sender { - [self validateAndClearEditFeaturesForType:GPKGS_ET_LINESTRING]; -} - -- (IBAction)editPolygonButton:(id)sender { - [self validateAndClearEditFeaturesForType:GPKGS_ET_POLYGON]; -} - -- (IBAction)editAcceptButton:(id)sender { - if(self.editFeatureType != GPKGS_ET_NONE && ([self.editPoints count] > 0 || self.editFeatureType == GPKGS_ET_EDIT_FEATURE)){ - BOOL accept = false; - switch(self.editFeatureType){ - case GPKGS_ET_POINT: - accept = true; - break; - case GPKGS_ET_LINESTRING: - if([self.editPoints count] >= 2){ - accept = true; - } - break; - case GPKGS_ET_POLYGON: - case GPKGS_ET_POLYGON_HOLE: - if([self.editPoints count] >= 3 && [self.editHolePoints count] == 0){ - accept = true; - } - break; - case GPKGS_ET_EDIT_FEATURE: - accept = self.editFeatureShape != nil && [self.editFeatureShape isValid]; - break; - default: - break; - } - if(accept){ - [self saveEditFeatures]; - } - } -} - -- (IBAction)editClearButton:(id)sender { - if([self.editPoints count] > 0 || self.editFeatureType == GPKGS_ET_EDIT_FEATURE){ - if(self.editFeatureType == GPKGS_ET_EDIT_FEATURE){ - self.editFeatureType = GPKGS_ET_NONE; - } - [self clearEditFeaturesAndPreserveType]; - } -} -- (IBAction)editPolygonHolesButton:(id)sender { - if(self.editFeatureType != GPKGS_ET_POLYGON_HOLE){ - self.editFeatureType = GPKGS_ET_POLYGON_HOLE; - [self.drawPolygonHoleButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POLYGON_HOLE_ACTIVE_IMAGE] forState:UIControlStateNormal]; - } else{ - self.editFeatureType = GPKGS_ET_POLYGON; - [self.drawPolygonHoleButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POLYGON_HOLE_IMAGE] forState:UIControlStateNormal]; - } -} - -- (IBAction)editAcceptPolygonHolesButton:(id)sender { - if([self.editHolePoints count] >= 3){ - NSArray * locationPoints = [self getLocationPoints:self.editHolePoints]; - [self.holePolygons addObject:locationPoints]; - [self clearEditHoleFeatures]; - [self updateEditState:true]; - } -} - -- (IBAction)editClearPolygonHolesButton:(id)sender { - [self clearEditHoleFeatures]; - [self updateEditState:true]; -} - --(NSArray *) getLocationPoints: (NSArray *) pointArray{ - NSMutableArray * points = [[NSMutableArray alloc] init]; - for(GPKGMapPoint * editPoint in pointArray){ - CLLocation * location = [[CLLocation alloc] initWithLatitude:editPoint.coordinate.latitude longitude:editPoint.coordinate.longitude]; - [points addObject:location]; - } - return points; -} - --(void) validateAndClearEditFeaturesForType: (enum GPKGSEditType) editTypeClicked{ - - if([self.editPoints count] == 0 && self.editFeatureType != GPKGS_ET_EDIT_FEATURE){ - [self clearEditFeaturesAndUpdateType:editTypeClicked]; - }else{ - UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_CLEAR_VALIDATION_LABEL] - message:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURES_CLEAR_VALIDATION_MESSAGE] - delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], - nil]; - objc_setAssociatedObject(alert, &MapConstantKey, [NSNumber numberWithInt:editTypeClicked], OBJC_ASSOCIATION_RETAIN_NONATOMIC); - alert.tag = TAG_CLEAR_EDIT_FEATURES; - [alert show]; - } - -} - -- (void) handleClearEditFeaturesWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - if(buttonIndex > 0){ - NSNumber *editTypeClicked = objc_getAssociatedObject(alertView, &MapConstantKey); - if (self.editFeatureType == GPKGS_ET_EDIT_FEATURE) { - self.editFeatureType = GPKGS_ET_NONE; - } - [self clearEditFeaturesAndUpdateType:(enum GPKGSEditType)[editTypeClicked intValue]]; - } -} - --(void) clearEditFeaturesAndUpdateType: (enum GPKGSEditType) editType{ - enum GPKGSEditType previousType = self.editFeatureType; - [self clearEditFeatures]; - [self setEditTypeWithPrevious:previousType andNew:editType]; -} - --(void) clearEditFeaturesAndPreserveType{ - enum GPKGSEditType previousType = self.editFeatureType; - [self clearEditFeatures]; - [self setEditTypeWithPrevious:GPKGS_ET_NONE andNew:previousType]; -} - --(void) setEditTypeWithPrevious: (enum GPKGSEditType) previousType andNew: (enum GPKGSEditType) editType{ - - if(editType != GPKGS_ET_NONE && previousType != editType){ - - self.editFeatureType = editType; - switch(editType){ - case GPKGS_ET_POINT: - [self.drawPointButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POINT_ACTIVE_IMAGE] forState:UIControlStateNormal]; - break; - case GPKGS_ET_LINESTRING: - [self.drawLineButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_LINE_ACTIVE_IMAGE] forState:UIControlStateNormal]; - break; - case GPKGS_ET_POLYGON_HOLE: - self.editFeatureType = GPKGS_ET_POLYGON; - case GPKGS_ET_POLYGON: - [self.drawPolygonButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POLYGON_ACTIVE_IMAGE] forState:UIControlStateNormal]; - [self setEditPolygonHoleButtonsHidden:false]; - break; - case GPKGS_ET_EDIT_FEATURE: - { - self.editFeatureMapPoint = self.tempEditFeatureMapPoint; - self.tempEditFeatureMapPoint = nil; - NSNumber * featureId = [self.editFeatureIds objectForKey:[self.editFeatureMapPoint getIdAsNumber]]; - GPKGGeoPackage * geoPackage = [self.manager open:self.editFeaturesDatabase]; - @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.editFeaturesTable]; - GPKGFeatureRow * featureRow = (GPKGFeatureRow *)[featureDao queryForIdObject:featureId]; - SFGeometry * geometry = [featureRow getGeometry].geometry; - GPKGMapShapeConverter * converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; - GPKGMapShape * shape = [converter toShapeWithGeometry:geometry]; - - [self.mapView removeAnnotation:self.editFeatureMapPoint]; - GPKGMapShape * featureObject = [self.editFeatureObjects objectForKey:[self.editFeatureMapPoint getIdAsNumber]]; - if(featureObject != nil){ - [self.editFeatureObjects removeObjectForKey:[self.editFeatureMapPoint getIdAsNumber]]; - [featureObject removeFromMapView:self.mapView]; - } - - self.editFeatureShape = [converter addMapShape:shape asPointsToMapView:self.mapView withPointOptions:[self getEditFeaturePointOptions] andPolylinePointOptions:[self getEditFeatureShapePointOptions] andPolygonPointOptions:[self getEditFeatureShapePointOptions] andPolygonPointHoleOptions:[self getEditFeatureShapeHolePointOptions] andPolylineOptions:[self drawPolylineOptions] andPolygonOptions:[self drawPolygonOptions]]; - [self updateEditState:true]; - } - @finally { - [geoPackage close]; - } - } - break; - default: - break; - } - } - -} - --(void) addEditableShapeBack{ - - NSNumber * featureId = [self.editFeatureIds objectForKey:[self.editFeatureMapPoint getIdAsNumber]]; - GPKGGeoPackage * geoPackage = [self.manager open:self.editFeaturesDatabase]; - @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.editFeaturesTable]; - GPKGFeatureRow * featureRow = (GPKGFeatureRow *) [featureDao queryForIdObject:featureId]; - GPKGGeometryData * geomData = [featureRow getGeometry]; - if(geomData != nil){ - SFGeometry * geometry = geomData.geometry; - if(geometry != nil){ - GPKGMapShapeConverter * converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; - GPKGMapShape * shape = [converter toShapeWithGeometry:geometry]; - GPKGStyleCache *styleCache = [[GPKGStyleCache alloc] initWithGeoPackage:geoPackage]; - [self prepareShapeOptionsWithShape:shape andStyleCache:styleCache andFeature:featureRow andEditable:true andTopLevel:true]; - GPKGMapShape * mapShape = [GPKGMapShapeConverter addMapShape:shape toMapView:self.mapView]; - [self addEditableShapeWithFeatureId:featureId andShape:mapShape]; - [styleCache clear]; - } - } - } - @finally { - if(geoPackage != nil){ - [geoPackage close]; - } - } -} - --(GPKGMapPointOptions *) getEditFeaturePointOptions{ - GPKGMapPointOptions * options = [[GPKGMapPointOptions alloc] init]; - options.draggable = true; - options.pinTintColor = [UIColor redColor]; - options.initializer = [[GPGKSMapPointInitializer alloc] initWithPointType:GPKGS_MPDT_EDIT_FEATURE_POINT]; - return options; -} - --(GPKGMapPointOptions *) getEditFeatureShapePointOptions{ - GPKGMapPointOptions * options = [[GPKGMapPointOptions alloc] init]; - options.draggable = true; - [options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POINT_IMAGE]]; - options.initializer = [[GPGKSMapPointInitializer alloc] initWithPointType:GPKGS_MPDT_EDIT_FEATURE_POINT]; - return options; -} - --(GPKGMapPointOptions *) getEditFeatureShapeHolePointOptions{ - GPKGMapPointOptions * options = [[GPKGMapPointOptions alloc] init]; - options.draggable = true; - [options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_HOLE_POINT_IMAGE]]; - options.initializer = [[GPGKSMapPointInitializer alloc] initWithPointType:GPKGS_MPDT_EDIT_FEATURE_POINT]; - return options; -} - --(void) saveEditFeatures{ - - BOOL changesMade = false; - - GPKGGeoPackage * geoPackage = [self.manager open:self.editFeaturesDatabase]; - GPKGFeatureIndexManager *indexer = nil; - enum GPKGSEditType tempEditFeatureType = self.editFeatureType; - @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.editFeaturesTable]; - NSNumber * srsId = featureDao.geometryColumns.srsId; - indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; - NSArray *indexedTypes = [indexer indexedTypes]; - - GPKGMapShapeConverter * converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; - - switch(self.editFeatureType){ - - case GPKGS_ET_POINT: - { - for(GPKGMapPoint * mapPoint in self.editPoints){ - SFPoint * point = [converter toPointWithMapPoint:mapPoint]; - GPKGFeatureRow * newPoint = [featureDao newRow]; - GPKGGeometryData * pointGeomData = [[GPKGGeometryData alloc] initWithSrsId:srsId]; - [pointGeomData setGeometry:point]; - [newPoint setGeometry:pointGeomData]; - [featureDao insert:newPoint]; - [self expandBoundsWithGeoPackage:geoPackage andFeatureDao:featureDao andGeometry:point]; - [self updateLastChangeWithGeoPackage:geoPackage andFeatureDao:featureDao]; - if(indexedTypes.count > 0){ - [indexer indexWithFeatureRow:newPoint andFeatureIndexTypes:indexedTypes]; - } - } - changesMade = true; - } - break; - - case GPKGS_ET_LINESTRING: - { - SFLineString * lineString = [converter toLineStringWithMapPolyline:self.editLinestring]; - GPKGFeatureRow * newLineString = [featureDao newRow]; - GPKGGeometryData * lineStringGeomData = [[GPKGGeometryData alloc] initWithSrsId:srsId]; - [lineStringGeomData setGeometry:lineString]; - [newLineString setGeometry:lineStringGeomData]; - [featureDao insert:newLineString]; - [self expandBoundsWithGeoPackage:geoPackage andFeatureDao:featureDao andGeometry:lineString]; - [self updateLastChangeWithGeoPackage:geoPackage andFeatureDao:featureDao]; - if(indexedTypes.count > 0){ - [indexer indexWithFeatureRow:newLineString andFeatureIndexTypes:indexedTypes]; - } - changesMade = true; - } - break; - - case GPKGS_ET_POLYGON: - case GPKGS_ET_POLYGON_HOLE: - { - SFPolygon * polygon = [converter toPolygonWithMapPolygon:self.editPolygon]; - GPKGFeatureRow * newPolygon = [featureDao newRow]; - GPKGGeometryData * polygonGeomData = [[GPKGGeometryData alloc] initWithSrsId:srsId]; - [polygonGeomData setGeometry:polygon]; - [newPolygon setGeometry:polygonGeomData]; - [featureDao insert:newPolygon]; - [self expandBoundsWithGeoPackage:geoPackage andFeatureDao:featureDao andGeometry:polygon]; - [self updateLastChangeWithGeoPackage:geoPackage andFeatureDao:featureDao]; - if(indexedTypes.count > 0){ - [indexer indexWithFeatureRow:newPolygon andFeatureIndexTypes:indexedTypes]; - } - changesMade = true; - } - break; - - case GPKGS_ET_EDIT_FEATURE: - { - self.editFeatureType = GPKGS_ET_NONE; - NSNumber * featureId = [self.editFeatureIds objectForKey:[self.editFeatureMapPoint getIdAsNumber]]; - - SFGeometry * geometry = [converter toGeometryFromMapShape:self.editFeatureShape.shape]; - if(geometry != nil){ - GPKGFeatureRow * featureRow = (GPKGFeatureRow *)[featureDao queryForIdObject:featureId]; - GPKGGeometryData * geomData = [featureRow getGeometry]; - [geomData setGeometry:geometry]; - if(geomData.envelope != nil){ - geomData.envelope = [SFGeometryEnvelopeBuilder buildEnvelopeWithGeometry:geometry]; - } - [featureRow setGeometry:geomData]; - [featureDao update:featureRow]; - [self expandBoundsWithGeoPackage:geoPackage andFeatureDao:featureDao andGeometry:geometry]; - [self updateLastChangeWithGeoPackage:geoPackage andFeatureDao:featureDao]; - if(indexedTypes.count > 0){ - [indexer indexWithFeatureRow:featureRow andFeatureIndexTypes:indexedTypes]; - } - }else{ - [featureDao deleteById:featureId]; - self.editFeatureMapPoint = nil; - [self updateLastChangeWithGeoPackage:geoPackage andFeatureDao:featureDao]; - if(indexedTypes.count > 0){ - [indexer deleteIndexWithGeomId:[featureId intValue] andFeatureIndexTypes:indexedTypes]; - } - } - [self.active setModified:true]; - } - break; - - default: - break; - } - - } - @catch (NSException *e) { - [GPKGSUtils showMessageWithDelegate:self - andTitle:[NSString stringWithFormat:@"Save %@", [GPKGSEditTypes name:tempEditFeatureType]] - andMessage:[NSString stringWithFormat:@"%@", [e description]]]; - } - @finally { - if(indexer != nil){ - [indexer close]; - } - if(geoPackage != nil){ - [geoPackage close]; - } - } - - [self clearEditFeaturesAndPreserveType]; - - if(changesMade){ - [self.active setModified:true]; - [self updateInBackgroundWithZoom:false andFilter:true]; - } -} - --(void) updateEditState: (BOOL) updateAcceptClear{ - - BOOL accept = false; - GPKGPolygon * editHolePolygon = nil; - - switch(self.editFeatureType){ - - case GPKGS_ET_POINT: - if([self.editPoints count] > 0){ - accept = true; - } - break; - - case GPKGS_ET_LINESTRING: - if([self.editPoints count] >= 2){ - accept = true; - - NSArray * points = [self getLocationPoints:self.editPoints]; - CLLocationCoordinate2D * locations = [GPKGMapShapeConverter getLocationCoordinatesFromLocations:points]; - GPKGPolyline * tempPolyline = [GPKGPolyline polylineWithCoordinates:locations count:[points count]]; - GPKGPolylineOptions *options = [self drawPolylineOptions]; - [tempPolyline setOptions:options]; - if(self.editLinestring != nil){ - [self.mapView removeOverlay:self.editLinestring]; - } - self.editLinestring = tempPolyline; - [self.mapView addOverlay:self.editLinestring]; - } else if(self.editLinestring != nil){ - [self.mapView removeOverlay:self.editLinestring]; - self.editLinestring = nil; - } - break; - - case GPKGS_ET_POLYGON_HOLE: - - if(self.editFeatureType == GPKGS_ET_POLYGON_HOLE){ - - if([self.editHolePoints count] > 0){ - accept = false; - [self.editPolygonHoleClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POLYGON_HOLE_CLEAR_ACTIVE_IMAGE] forState:UIControlStateNormal]; - }else{ - [self.editPolygonHoleClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POLYGON_HOLE_CLEAR_IMAGE] forState:UIControlStateNormal]; - } - - if([self.editHolePoints count] >= 3){ - - [self.editPolygonHoleConfirmButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POLYGON_HOLE_CONFIRM_ACTIVE_IMAGE] forState:UIControlStateNormal]; - - NSArray * points = [self getLocationPoints:self.editHolePoints]; - CLLocationCoordinate2D * locations = [GPKGMapShapeConverter getLocationCoordinatesFromLocations:points]; - editHolePolygon = [GPKGPolygon polygonWithCoordinates:locations count:[points count]]; - }else{ - [self.editPolygonHoleConfirmButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POLYGON_HOLE_CONFIRM_IMAGE] forState:UIControlStateNormal]; - } - } - - // Continue to polygon - - case GPKGS_ET_POLYGON: - - if([self.editPoints count] >= 3){ - accept = true; - - NSArray * points = [self getLocationPoints:self.editPoints]; - CLLocationCoordinate2D * locations = [GPKGMapShapeConverter getLocationCoordinatesFromLocations:points]; - NSMutableArray * polygonHoles = [[NSMutableArray alloc] initWithCapacity:[self.holePolygons count]]; - for(NSArray * holePoints in self.holePolygons){ - CLLocationCoordinate2D * holeLocations = [GPKGMapShapeConverter getLocationCoordinatesFromLocations:holePoints]; - GPKGPolyline * polygonHole = [GPKGPolyline polylineWithCoordinates:holeLocations count:[holePoints count]]; - [polygonHoles addObject:polygonHole]; - } - if(editHolePolygon != nil){ - [polygonHoles addObject:editHolePolygon]; - } - GPKGPolygon * tempPolygon = [GPKGPolygon polygonWithCoordinates:locations count:[points count] interiorPolygons:polygonHoles]; - GPKGPolygonOptions *options = [self drawPolygonOptions]; - [tempPolygon setOptions:options]; - if(self.editPolygon != nil){ - [self.mapView removeOverlay:self.editPolygon]; - } - self.editPolygon = tempPolygon; - [self.mapView addOverlay:self.editPolygon]; - } else if(self.editPolygon != nil){ - [self.mapView removeOverlay:self.editPolygon]; - self.editPolygon = nil; - } - - break; - - case GPKGS_ET_EDIT_FEATURE: - accept = true; - - if(self.editFeatureShape != nil){ - [self.editFeatureShape updateWithMapView:self.mapView]; - accept = [self.editFeatureShape isValid]; - } - break; - - default: - break; - } - - if(updateAcceptClear){ - if([self.editPoints count] > 0 || self.editFeatureType == GPKGS_ET_EDIT_FEATURE){ - [self.editFeaturesClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_CLEAR_ACTIVE_IMAGE] forState:UIControlStateNormal]; - } else{ - [self.editFeaturesClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_CLEAR_IMAGE] forState:UIControlStateNormal]; - } - if(accept){ - [self.editFeaturesConfirmButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_CONFIRM_ACTIVE_IMAGE] forState:UIControlStateNormal]; - }else{ - [self.editFeaturesConfirmButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_CONFIRM_IMAGE] forState:UIControlStateNormal]; - } - } -} - --(void) resetBoundingBox{ - self.boundingBoxMode = false; - [self setBoundingBoxButtonsHidden:true]; - [self clearBoundingBox]; -} - --(void) resetEditFeatures{ - self.editFeaturesMode = false; - [self setEditFeaturesButtonsHidden:true]; - self.editFeaturesDatabase = nil; - self.editFeaturesTable = nil; - [self.editFeatureIds removeAllObjects]; - [self.editFeatureObjects removeAllObjects]; - self.editFeatureShape = nil; - self.editFeatureShapePoints = nil; - self.editFeatureMapPoint = nil; - self.tempEditFeatureMapPoint = nil; - [self clearEditFeatures]; -} - --(void) clearBoundingBox{ - [self resetBoundingBoxButtonImages]; - if(self.boundingBox != nil){ - [self.mapView removeOverlay:self.boundingBox]; - } - self.boundingBoxStartCorner = kCLLocationCoordinate2DInvalid; - self.boundingBoxEndCorner = kCLLocationCoordinate2DInvalid; - self.boundingBox = nil; - [self setDrawing:false]; -} - --(void) clearEditFeatures{ - self.editFeatureType = GPKGS_ET_NONE; - for(GPKGMapPoint * editMapPoint in self.editPoints){ - [self.mapView removeAnnotation:editMapPoint]; - } - [self.editPoints removeAllObjects]; - if(self.editLinestring != nil){ - [self.mapView removeOverlay:self.editLinestring]; - self.editLinestring = nil; - } - if(self.editPolygon != nil){ - [self.mapView removeOverlay:self.editPolygon]; - self.editPolygon = nil; - } - [self.holePolygons removeAllObjects]; - [self resetEditFeaturesButtonImages]; - [self setEditPolygonHoleButtonsHidden:true]; - [self clearEditHoleFeatures]; - if(self.editFeatureShape != nil){ - [self.editFeatureShape removeFromMapView:self.mapView]; - if(self.editFeatureMapPoint != nil){ - [self addEditableShapeBack]; - self.editFeatureMapPoint = nil; - } - self.editFeatureShape = nil; - self.editFeatureShapePoints = nil; - } -} - --(void) clearEditHoleFeatures{ - - for(GPKGMapPoint * editMapPoint in self.editHolePoints){ - [self.mapView removeAnnotation:editMapPoint]; - } - [self.editHolePoints removeAllObjects]; - [self resetEditPolygonHoleChoiceButtonImages]; -} - -- (IBAction)userLocation:(id)sender { - if([CLLocationManager locationServicesEnabled]){ - [self.locationManager startUpdatingLocation]; - } -} - -- (IBAction)maxFeaturesButton:(id)sender { - UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES] - message:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES_MESSAGE] - delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], - nil]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - UITextField* textField = [alert textFieldAtIndex:0]; - textField.keyboardType = UIKeyboardTypeNumberPad; - [textField setText:[NSString stringWithFormat:@"%d", [self getMaxFeatures]]]; - alert.tag = TAG_MAX_FEATURES; - [alert show]; -} - -- (void) handleMaxFeaturesWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - if(buttonIndex > 0){ - NSString * maxFeatures = [[alertView textFieldAtIndex:0] text]; - if(maxFeatures != nil && [maxFeatures length] > 0){ - @try { - NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; - formatter.numberStyle = NSNumberFormatterDecimalStyle; - NSNumber *maxFeaturesNumber = [formatter numberFromString:maxFeatures]; - [self.settings setInteger:[maxFeaturesNumber integerValue] forKey:GPKGS_PROP_MAP_MAX_FEATURES]; - [self.settings synchronize]; - [self updateInBackgroundWithZoom:false andFilter:true]; - } - @catch (NSException *e) { - NSLog(@"Invalid max features value: %@, Error: %@", maxFeatures, [e description]); - } - } - } -} - -- (IBAction)mapType:(id)sender { - UIAlertView * alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE] - message:nil - delegate:self - cancelButtonTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL] - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_HYBRID], - nil]; - alert.tag = TAG_MAP_TYPE; - [alert show]; -} - -- (void) handleMapTypeWithAlertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ - if(buttonIndex > 0){ - MKMapType mapType; - switch(buttonIndex){ - case 1: - mapType = MKMapTypeStandard; - break; - case 2: - mapType = MKMapTypeSatellite; - break; - case 3: - mapType = MKMapTypeHybrid; - break; - default: - mapType = MKMapTypeStandard; - } - [self.mapView setMapType:mapType]; - } -} - -- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { - CLLocation * userLocation = self.mapView.userLocation.location; - if(userLocation != nil){ - - MKCoordinateRegion region; - region.center = self.mapView.userLocation.coordinate; - region.span = MKCoordinateSpanMake(0.02, 0.02); - - region = [self.mapView regionThatFits:region]; - [self.mapView setRegion:region animated:YES]; - - // This pans without zooming instead of the pan and zoom above - //[self.mapView setCenterCoordinate:userLocation.coordinate animated:YES]; - - [self.locationManager stopUpdatingLocation]; - } -} - --(void) updateInBackgroundWithZoom: (BOOL) zoom{ - [self updateInBackgroundWithZoom:zoom andFilter:false]; -} - --(void) updateInBackgroundWithZoom: (BOOL) zoom andFilter: (BOOL) filter{ - - int updateId = ++self.updateCountId; - int featureUpdateId = ++self.featureUpdateCountId; - [self.mapView removeAnnotations:self.mapView.annotations]; - [self.mapView removeOverlays:self.mapView.overlays]; - [self.geoPackages closeAll]; - [self.featureDaos removeAllObjects]; - - if(zoom){ - [self zoomToActiveBounds]; - } - - self.featuresBoundingBox = nil; - self.tilesBoundingBox = nil; - self.featureOverlayTiles = false; - [self.featureOverlayQueries removeAllObjects]; - [self.featureShapes clear]; - int maxFeatures = [self getMaxFeatures]; - - GPKGBoundingBox *mapViewBoundingBox = [GPKGMapUtils boundingBoxOfMapView:self.mapView]; - double toleranceDistance = [GPKGMapUtils toleranceDistanceInMapView:self.mapView]; - - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul); - dispatch_async(queue, ^{ - [self updateWithId: updateId andFeatureUpdateId:featureUpdateId andZoom:zoom andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; - }); -} - --(void) zoomToActiveBounds{ - - self.featuresBoundingBox = nil; - self.tilesBoundingBox = nil; - - // Pre zoom - NSMutableArray *activeDatabase = [[NSMutableArray alloc] init]; - [activeDatabase addObjectsFromArray:[self.active getDatabases]]; - for(GPKGSDatabase *database in activeDatabase){ - GPKGGeoPackage *geoPackage = [self.manager open:database.name]; - if (geoPackage != nil) { - - NSMutableSet *featureTableDaos = [[NSMutableSet alloc] init]; - NSArray *features = [database getFeatures]; - if(features.count > 0){ - for(GPKGSTable *featureTable in features){ - [featureTableDaos addObject:featureTable.name]; - } - } - - for(GPKGSFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ - if(featureOverlay.active){ - [featureTableDaos addObject:featureOverlay.featureTable]; - } - } - - if(featureTableDaos.count > 0){ - - GPKGContentsDao *contentsDao = [geoPackage getContentsDao]; - - for (NSString *featureTable in featureTableDaos) { - - @try { - GPKGContents *contents = (GPKGContents *)[contentsDao queryForIdObject:featureTable]; - GPKGBoundingBox *contentsBoundingBox = [contents getBoundingBox]; - - if (contentsBoundingBox != nil) { - - contentsBoundingBox = [self transformBoundingBoxToWgs84: contentsBoundingBox withSrs: [contentsDao getSrs:contents]]; - - if (self.featuresBoundingBox != nil) { - self.featuresBoundingBox = [self.featuresBoundingBox union:contentsBoundingBox]; - } else { - self.featuresBoundingBox = contentsBoundingBox; - } - } - } @catch (NSException *e) { - NSLog(@"%@", [e description]); - } - } - } - - NSArray *tileTables = [database getTiles]; - if(tileTables.count > 0){ - - GPKGTileMatrixSetDao *tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - - for(GPKGSTileTable *tileTable in tileTables){ - - @try { - GPKGTileMatrixSet *tileMatrixSet = (GPKGTileMatrixSet *)[tileMatrixSetDao queryForIdObject:tileTable.name]; - GPKGBoundingBox *tileMatrixSetBoundingBox = [tileMatrixSet getBoundingBox]; - - tileMatrixSetBoundingBox = [self transformBoundingBoxToWgs84:tileMatrixSetBoundingBox withSrs:[tileMatrixSetDao getSrs:tileMatrixSet]]; - - if (self.tilesBoundingBox != nil) { - self.tilesBoundingBox = [self.tilesBoundingBox union:tileMatrixSetBoundingBox]; - } else { - self.tilesBoundingBox = tileMatrixSetBoundingBox; - } - } @catch (NSException *e) { - NSLog(@"%@", [e description]); - } - } - } - - [geoPackage close]; - } - } - [self zoomToActiveAndIgnoreRegionChange:YES]; -} - --(GPKGBoundingBox *) transformBoundingBoxToWgs84: (GPKGBoundingBox *) boundingBox withSrs: (GPKGSpatialReferenceSystem *) srs{ - - SFPProjection *projection = [srs projection]; - if([projection isUnit:SFP_UNIT_DEGREES]){ - boundingBox = [GPKGTileBoundingBoxUtils boundDegreesBoundingBoxWithWebMercatorLimits:boundingBox]; - } - SFPProjectionTransform *transformToWebMercator = [[SFPProjectionTransform alloc] initWithFromProjection:projection andToEpsg:PROJ_EPSG_WEB_MERCATOR]; - GPKGBoundingBox *webMercatorBoundingBox = [boundingBox transform:transformToWebMercator]; - SFPProjectionTransform *transform = [[SFPProjectionTransform alloc] initWithFromEpsg:PROJ_EPSG_WEB_MERCATOR andToEpsg:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; - boundingBox = [webMercatorBoundingBox transform:transform]; - return boundingBox; -} - --(BOOL) updateCanceled: (int) updateId{ - BOOL canceled = updateId < self.updateCountId; - return canceled; -} - --(BOOL) featureUpdateCanceled: (int) updateId{ - BOOL canceled = updateId < self.featureUpdateCountId; - return canceled; -} - --(int) updateWithId: (int) updateId andFeatureUpdateId: (int) featureUpdateId andZoom: (BOOL) zoom andMaxFeatures: (int) maxFeatures andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter{ - - int count = 0; - - if(self.active != nil){ - - NSArray * activeDatabases = [[NSArray alloc] initWithArray:[self.active getDatabases]]; - - // Open active GeoPackages and create feature DAOS, display tiles and feature tiles - for(GPKGSDatabase * database in activeDatabases){ - - if([self updateCanceled:updateId]){ - break; - } - - GPKGGeoPackage *geoPackage = [self.geoPackages getOrOpen:database.name]; - - if(geoPackage != nil){ - - NSMutableSet * featureTableDaos = [[NSMutableSet alloc] init]; - NSArray * features = [database getFeatures]; - if([features count] > 0){ - for(GPKGSTable * features in [database getFeatures]){ - [featureTableDaos addObject:features.name]; - } - } - - for(GPKGSFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ - if(featureOverlay.active){ - [featureTableDaos addObject:featureOverlay.featureTable]; - } - } - - if(featureTableDaos.count > 0){ - NSMutableDictionary * databaseFeatureDaos = [[NSMutableDictionary alloc] init]; - [self.featureDaos setObject:databaseFeatureDaos forKey:database.name]; - for(NSString *featureTable in featureTableDaos){ - - if([self updateCanceled:updateId]){ - break; - } - - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:featureTable]; - [databaseFeatureDaos setObject:featureDao forKey:featureTable]; - } - } - - // Display the tiles - for(GPKGSTileTable * tiles in [database getTiles]){ - if([self updateCanceled:updateId]){ - break; - } - @try { - [self displayTiles:tiles]; - } - @catch (NSException *e) { - NSLog(@"%@", [e description]); - } - } - - // Display the feature tiles - for(GPKGSFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ - if([self updateCanceled:updateId]){ - break; - } - if(featureOverlay.active){ - @try { - [self displayFeatureTiles:featureOverlay]; - } - @catch (NSException *e) { - NSLog(@"%@", [e description]); - } - } - } - - } else{ - [self.active removeDatabase:database.name andPreserveOverlays:false]; - } - } - - // Add features - if(![self featureUpdateCanceled:featureUpdateId]){ - count = [self addFeaturesWithId:featureUpdateId andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; - } - } - - if(self.boundingBox != nil){ - [self.mapView addOverlay:self.boundingBox]; - } - - if(self.needsInitialZoom || zoom){ - dispatch_sync(dispatch_get_main_queue(), ^{ - [self zoomToActiveIfNothingVisible:YES]; - self.needsInitialZoom = false; - }); - } - - return count; -} - --(int) addFeaturesWithId: (int) updateId andMaxFeatures: (int) maxFeatures andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter{ - - int count = 0; - - // Add features - NSMutableDictionary * featureTables = [[NSMutableDictionary alloc] init]; - if(self.editFeaturesMode){ - NSMutableArray * databaseFeatures = [[NSMutableArray alloc] init]; - [databaseFeatures addObject:self.editFeaturesTable]; - [featureTables setObject:databaseFeatures forKey:self.editFeaturesDatabase]; - GPKGGeoPackage *geoPackage = [self.geoPackages getOrOpen:self.editFeaturesDatabase]; - NSMutableDictionary * databaseFeatureDaos = [self.featureDaos objectForKey:self.editFeaturesDatabase]; - if(databaseFeatureDaos == nil){ - databaseFeatureDaos = [[NSMutableDictionary alloc] init]; - [self.featureDaos setObject:databaseFeatureDaos forKey:self.editFeaturesDatabase]; - } - GPKGFeatureDao * featureDao = [databaseFeatureDaos objectForKey:self.editFeaturesTable]; - if(featureDao == nil){ - featureDao = [geoPackage getFeatureDaoWithTableName:self.editFeaturesTable]; - [databaseFeatureDaos setObject:featureDao forKey:self.editFeaturesTable]; - } - }else{ - for(GPKGSDatabase * database in [self.active getDatabases]){ - NSArray * features = [database getFeatures]; - if([features count] > 0){ - NSMutableArray * databaseFeatures = [[NSMutableArray alloc] init]; - [featureTables setObject:databaseFeatures forKey:database.name]; - for(GPKGSTable * features in [database getFeatures]){ - [databaseFeatures addObject:features.name]; - } - } - } - } - - for(NSString * databaseName in [featureTables allKeys]){ - - if(count >= maxFeatures){ - break; - } - - if([self.geoPackages has:databaseName]){ - - NSMutableArray * databaseFeatures = [featureTables objectForKey:databaseName]; - - GPKGGeoPackage *geoPackage = [self.geoPackages getOrOpen:databaseName]; - GPKGStyleCache *styleCache = [[GPKGStyleCache alloc] initWithGeoPackage:geoPackage]; - - for(NSString * features in databaseFeatures){ - - if([[self.featureDaos objectForKey:databaseName] objectForKey:features] != nil){ - - count = [self displayFeaturesWithId:updateId andGeoPackage:geoPackage andStyleCache:styleCache andFeatures:features andCount:count andMaxFeatures:maxFeatures andEditable:self.editFeaturesMode andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; - if([self featureUpdateCanceled:updateId] || count >= maxFeatures){ - break; - } - } - } - - [styleCache clear]; - } - - if([self featureUpdateCanceled:updateId]){ - break; - } - } - - return count; -} - --(void) zoomToActive{ - [self zoomToActiveIfNothingVisible:NO]; -} - --(void) zoomToActiveAndIgnoreRegionChange: (BOOL) ignoreChange{ - [self zoomToActiveIfNothingVisible:NO andIgnoreRegionChange:ignoreChange]; -} - --(void) zoomToActiveIfNothingVisible: (BOOL) nothingVisible{ - [self zoomToActiveIfNothingVisible:nothingVisible andIgnoreRegionChange:NO]; -} - --(void) zoomToActiveIfNothingVisible: (BOOL) nothingVisible andIgnoreRegionChange: (BOOL) ignoreChange{ - - GPKGBoundingBox * bbox = self.featuresBoundingBox; - BOOL tileBox = false; - - float paddingPercentage; - if(bbox == nil){ - bbox = self.tilesBoundingBox; - tileBox = true; - if(self.featureOverlayTiles){ - paddingPercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_FEATURE_TILES_ZOOM_PADDING_PERCENTAGE] intValue] * .01; - }else{ - paddingPercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_TILES_ZOOM_PADDING_PERCENTAGE] intValue] * .01; - } - }else{ - paddingPercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_FEATURES_ZOOM_PADDING_PERCENTAGE] intValue] * .01f; - } - - if(bbox != nil){ - - BOOL zoomToActive = YES; - if(nothingVisible){ - GPKGBoundingBox *mapViewBoundingBox = [GPKGMapUtils boundingBoxOfMapView:self.mapView]; - if([GPKGTileBoundingBoxUtils overlapWithBoundingBox:bbox andBoundingBox:mapViewBoundingBox withMaxLongitude:PROJ_WGS84_HALF_WORLD_LON_WIDTH] != nil){ - - struct GPKGBoundingBoxSize bboxSize = [bbox sizeInMeters]; - struct GPKGBoundingBoxSize mapViewSize = [mapViewBoundingBox sizeInMeters]; - - double longitudeDistance = bboxSize.width; - double latitudeDistance = bboxSize.height; - double mapViewLongitudeDistance = mapViewSize.width; - double mapViewLatitudeDistance = mapViewSize.height; - - if (mapViewLongitudeDistance > longitudeDistance && mapViewLatitudeDistance > latitudeDistance) { - - double longitudeRatio = longitudeDistance / mapViewLongitudeDistance; - double latitudeRatio = latitudeDistance / mapViewLatitudeDistance; - - double zoomAlreadyVisiblePercentage; - if (tileBox) { - zoomAlreadyVisiblePercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_TILES_ZOOM_ALREADY_VISIBLE_PERCENTAGE] intValue] * .01; - }else{ - zoomAlreadyVisiblePercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_FEATURES_ZOOM_ALREADY_VISIBLE_PERCENTAGE] intValue] * .01; - } - - if(longitudeRatio >= zoomAlreadyVisiblePercentage && latitudeRatio >= zoomAlreadyVisiblePercentage){ - zoomToActive = false; - } - } - } - } - - if(zoomToActive){ - struct GPKGBoundingBoxSize size = [bbox sizeInMeters]; - double expandedHeight = size.height + (2 * (size.height * paddingPercentage)); - double expandedWidth = size.width + (2 * (size.width * paddingPercentage)); - - CLLocationCoordinate2D center = [bbox getCenter]; - MKCoordinateRegion expandedRegion = MKCoordinateRegionMakeWithDistance(center, expandedHeight, expandedWidth); - - double latitudeRange = expandedRegion.span.latitudeDelta / 2.0; - - if(expandedRegion.center.latitude + latitudeRange > 90.0 || expandedRegion.center.latitude - latitudeRange < -90.0){ - expandedRegion = MKCoordinateRegionMake(self.mapView.centerCoordinate, MKCoordinateSpanMake(180, 360)); - } - - if(ignoreChange){ - self.ignoreRegionChange = true; - } - [self.mapView setRegion:expandedRegion animated:true]; - } - } -} - --(void) displayTiles: (GPKGSTileTable *) tiles{ - - GPKGGeoPackage *geoPackage = [self.geoPackages getOrOpen:tiles.database]; - - GPKGTileDao * tileDao = [geoPackage getTileDaoWithTableName:tiles.name]; - - GPKGTileTableScaling *tileTableScaling = [[GPKGTileTableScaling alloc] initWithGeoPackage:geoPackage andTileDao:tileDao]; - GPKGTileScaling *tileScaling = [tileTableScaling get]; - - GPKGBoundedOverlay * overlay = [GPKGOverlayFactory boundedOverlay:tileDao andScaling:tileScaling]; - overlay.canReplaceMapContent = false; - - GPKGTileMatrixSet * tileMatrixSet = tileDao.tileMatrixSet; - - GPKGFeatureTileTableLinker * linker = [[GPKGFeatureTileTableLinker alloc] initWithGeoPackage:geoPackage]; - NSArray * featureDaos = [linker getFeatureDaosForTileTable:tileDao.tableName]; - for(GPKGFeatureDao * featureDao in featureDaos){ - - // Create the feature tiles - GPKGFeatureTiles * featureTiles = [[GPKGFeatureTiles alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; - - self.featureOverlayTiles = true; - - // Add the feature overlay query - GPKGFeatureOverlayQuery * featureOverlayQuery = [[GPKGFeatureOverlayQuery alloc] initWithBoundedOverlay:overlay andFeatureTiles:featureTiles]; - [self.featureOverlayQueries addObject:featureOverlayQuery]; - } - - GPKGBoundingBox *displayBoundingBox = [tileMatrixSet getBoundingBox]; - GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - GPKGSpatialReferenceSystem *tileMatrixSetSrs = [tileMatrixSetDao getSrs:tileMatrixSet]; - GPKGContents *contents = [tileMatrixSetDao getContents:tileMatrixSet]; - GPKGBoundingBox *contentsBoundingBox = [contents getBoundingBox]; - if(contentsBoundingBox != nil){ - GPKGContentsDao *contentsDao = [geoPackage getContentsDao]; - SFPProjectionTransform *transform = [[SFPProjectionTransform alloc] initWithFromProjection:[[contentsDao getSrs:contents] projection] andToProjection:[tileMatrixSetSrs projection]]; - GPKGBoundingBox *transformedContentsBoundingBox = contentsBoundingBox; - if(![transform isSameProjection]){ - transformedContentsBoundingBox = [transformedContentsBoundingBox transform:transform]; - } - displayBoundingBox = [displayBoundingBox overlap:transformedContentsBoundingBox]; - } - - [self displayTilesWithOverlay:overlay andBoundingBox:displayBoundingBox andSrs:tileMatrixSetSrs andSpecifiedBoundingBox:nil]; -} - --(void) displayFeatureTiles: (GPKGSFeatureOverlayTable *) featureOverlayTable{ - - GPKGGeoPackage *geoPackage = [self.geoPackages getOrOpen:featureOverlayTable.database]; - - GPKGFeatureDao * featureDao = [[self.featureDaos objectForKey:featureOverlayTable.database] objectForKey:featureOverlayTable.featureTable]; - - GPKGBoundingBox * boundingBox = [[GPKGBoundingBox alloc] initWithMinLongitudeDouble:featureOverlayTable.minLon andMinLatitudeDouble:featureOverlayTable.minLat andMaxLongitudeDouble:featureOverlayTable.maxLon andMaxLatitudeDouble:featureOverlayTable.maxLat]; - - // Load tiles - GPKGFeatureTiles * featureTiles = [[GPKGFeatureTiles alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; - if(featureOverlayTable.ignoreGeoPackageStyles){ - [featureTiles ignoreFeatureTableStyles]; - } - - [featureTiles setMaxFeaturesPerTile:featureOverlayTable.maxFeaturesPerTile]; - if(featureOverlayTable.maxFeaturesPerTile != nil){ - [featureTiles setMaxFeaturesTileDraw:[[GPKGNumberFeaturesTile alloc] init]]; - } - - [featureTiles setPointColor:featureOverlayTable.pointColor]; - [featureTiles setPointRadius:featureOverlayTable.pointRadius]; - [featureTiles setLineColor:featureOverlayTable.lineColor]; - [featureTiles setLineStrokeWidth:featureOverlayTable.lineStroke]; - [featureTiles setPolygonColor:featureOverlayTable.polygonColor]; - [featureTiles setPolygonStrokeWidth:featureOverlayTable.polygonStroke]; - [featureTiles setFillPolygon:featureOverlayTable.polygonFill]; - if(featureTiles.fillPolygon){ - [featureTiles setPolygonFillColor:featureOverlayTable.polygonFillColor]; - } - - [featureTiles calculateDrawOverlap]; - - GPKGFeatureOverlay * featureOverlay = [[GPKGFeatureOverlay alloc] initWithFeatureTiles:featureTiles]; - boundingBox = [GPKGTileBoundingBoxUtils boundWgs84BoundingBoxWithWebMercatorLimits:boundingBox]; - [featureOverlay setBoundingBox:boundingBox withProjection:[SFPProjectionFactory projectionWithEpsgInt:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]]; - [featureOverlay setMinZoom:[NSNumber numberWithInt:featureOverlayTable.minZoom]]; - [featureOverlay setMaxZoom:[NSNumber numberWithInt:featureOverlayTable.maxZoom]]; - - // Get the tile linked overlay - GPKGBoundedOverlay *overlay = [GPKGOverlayFactory linkedFeatureOverlayWithOverlay:featureOverlay andGeoPackage:geoPackage]; - - GPKGGeometryColumns * geometryColumns = featureDao.geometryColumns; - GPKGContents * contents = [[geoPackage getGeometryColumnsDao] getContents:geometryColumns]; - - self.featureOverlayTiles = true; - - GPKGFeatureOverlayQuery * featureOverlayQuery = [[GPKGFeatureOverlayQuery alloc] initWithBoundedOverlay:overlay andFeatureTiles:featureTiles]; - [self.featureOverlayQueries addObject:featureOverlayQuery]; - - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; - [self displayTilesWithOverlay:overlay andBoundingBox:[contents getBoundingBox] andSrs:[contentsDao getSrs:contents] andSpecifiedBoundingBox:boundingBox]; -} - --(void) displayTilesWithOverlay: (MKTileOverlay *) overlay andBoundingBox: (GPKGBoundingBox *) dataBoundingBox andSrs: (GPKGSpatialReferenceSystem *) srs andSpecifiedBoundingBox: (GPKGBoundingBox *) specifiedBoundingBox{ - - GPKGBoundingBox * boundingBox = dataBoundingBox; - if(boundingBox != nil){ - boundingBox = [self transformBoundingBoxToWgs84:boundingBox withSrs:srs]; - }else{ - boundingBox = [[GPKGBoundingBox alloc] initWithMinLongitudeDouble:-PROJ_WGS84_HALF_WORLD_LON_WIDTH andMinLatitudeDouble:PROJ_WEB_MERCATOR_MIN_LAT_RANGE andMaxLongitudeDouble:PROJ_WGS84_HALF_WORLD_LON_WIDTH andMaxLatitudeDouble:PROJ_WEB_MERCATOR_MAX_LAT_RANGE]; - } - - if(specifiedBoundingBox != nil){ - boundingBox = [boundingBox overlap:specifiedBoundingBox]; - } - - if(self.tilesBoundingBox == nil){ - self.tilesBoundingBox = boundingBox; - }else{ - self.tilesBoundingBox = [self.tilesBoundingBox union:boundingBox]; - } - - dispatch_sync(dispatch_get_main_queue(), ^{ - [self.mapView addOverlay:overlay]; - }); -} - --(int) displayFeaturesWithId: (int) updateId andGeoPackage: (GPKGGeoPackage *) geoPackage andStyleCache: (GPKGStyleCache *) styleCache andFeatures: (NSString *) features andCount: (int) count andMaxFeatures: (int) maxFeatures andEditable: (BOOL) editable andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter{ - - NSString *database = geoPackage.name; - GPKGFeatureDao * featureDao = [[self.featureDaos objectForKey:database] objectForKey:features]; - NSString * tableName = featureDao.tableName; - GPKGMapShapeConverter * converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; - - [converter setSimplifyToleranceAsDouble:toleranceDistance]; - - if(![[styleCache featureStyleExtension] hasWithTable:features]){ - styleCache = nil; - } - - count += [self.featureShapes featureIdsCountInDatabase:database withTable:tableName]; - - if(![self featureUpdateCanceled:updateId] && count < maxFeatures){ - - SFPProjection *mapViewProjection = [SFPProjectionFactory projectionWithEpsgInt: PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; - - GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; - @try{ - if(filter && [indexer isIndexed]){ - - GPKGFeatureIndexResults *indexResults = [indexer queryWithBoundingBox:mapViewBoundingBox inProjection:mapViewProjection]; - GPKGBoundingBox *complementary = [mapViewBoundingBox complementaryWgs84]; - if(complementary != nil){ - GPKGFeatureIndexResults *indexResults2 = [indexer queryWithBoundingBox:complementary inProjection:mapViewProjection]; - indexResults = [[GPKGMultipleFeatureIndexResults alloc] initWithFeatureIndexResults1:indexResults andFeatureIndexResults2:indexResults2]; - } - count = [self processFeatureIndexResults:indexResults withUpdateId:updateId andDatabase:database andCount:count andMaxFeatures:maxFeatures andEditable:editable andTableName:tableName andConverter:converter andStyleCache:styleCache andFilter:filter]; - - }else{ - - GPKGBoundingBox *filterBoundingBox = nil; - double filterMaxLongitude = 0; - - if(filter){ - SFPProjection *featureProjection = featureDao.projection; - SFPProjectionTransform * projectionTransform = [[SFPProjectionTransform alloc] initWithFromProjection:mapViewProjection andToProjection:featureProjection]; - GPKGBoundingBox *boundedMapViewBoundingBox = [mapViewBoundingBox boundWgs84Coordinates]; - GPKGBoundingBox *transformedBoundingBox = [boundedMapViewBoundingBox transform:projectionTransform]; - if([featureProjection isUnit:SFP_UNIT_DEGREES]){ - filterMaxLongitude = PROJ_WGS84_HALF_WORLD_LON_WIDTH; - }else if([featureProjection isUnit:SFP_UNIT_METERS]){ - filterMaxLongitude = PROJ_WEB_MERCATOR_HALF_WORLD_WIDTH; - } - filterBoundingBox = [transformedBoundingBox expandCoordinatesWithMaxLongitude:filterMaxLongitude]; - } - - // Query for all rows - GPKGResultSet * results = [featureDao queryForAll]; - @try { - while(![self featureUpdateCanceled:updateId] && count < maxFeatures && [results moveToNext]){ - @try { - GPKGFeatureRow * row = [featureDao getFeatureRow:results]; - - count = [self processFeatureRow:row withDatabase:database andCount:count andMaxFeatures:maxFeatures andEditable:editable andTableName:tableName andConverter:converter andStyleCache:styleCache andFilterBoundingBox:filterBoundingBox andFilterMaxLongitude:filterMaxLongitude andFilter:filter]; - } @catch (NSException *exception) { - NSLog(@"Failed to display feature. database: %@, feature table: %@, error: %@", database, features, [exception description]); - } - } - } - @finally { - [results close]; - } - } - }@finally{ - [indexer close]; - } - - } - - return count; -} - --(int) processFeatureIndexResults: (GPKGFeatureIndexResults *) indexResults withUpdateId: (int) updateId andDatabase: (NSString *) database andCount: (int) count andMaxFeatures: (int) maxFeatures andEditable: (BOOL) editable andTableName: (NSString *) tableName andConverter: (GPKGMapShapeConverter *) converter andStyleCache: (GPKGStyleCache *) styleCache andFilter: (BOOL) filter{ - - @try { - for(GPKGFeatureRow *row in indexResults){ - - if([self featureUpdateCanceled:updateId] || count >= maxFeatures){ - break; - } - - count = [self processFeatureRow:row withDatabase:database andCount:count andMaxFeatures:maxFeatures andEditable:editable andTableName:tableName andConverter:converter andStyleCache:styleCache andFilterBoundingBox:nil andFilterMaxLongitude:0 andFilter:filter]; - } - } - @finally { - [indexResults close]; - } - - return count; -} - --(int) processFeatureRow: (GPKGFeatureRow *) row withDatabase: (NSString *) database andCount: (int) count andMaxFeatures: (int) maxFeatures andEditable: (BOOL) editable andTableName: (NSString *) tableName andConverter: (GPKGMapShapeConverter *) converter andStyleCache: (GPKGStyleCache *) styleCache andFilterBoundingBox: (GPKGBoundingBox *) filterBoundingBox andFilterMaxLongitude: (double) maxLongitude andFilter: (BOOL) filter{ - - if(![self.featureShapes existsWithFeatureId:[row getId] inDatabase:database withTable:tableName]){ - count = [self processFeatureRowWithDatabase:database andTableName:tableName andConverter:converter andStyleCache:styleCache andFeatureRow:row andCount:count andMaxFeatures:maxFeatures andEditable:editable andFilterBoundingBox:filterBoundingBox andFilterMaxLongitude:maxLongitude andFilter:filter]; - } - - return count; -} - --(int) processFeatureRowWithDatabase: (NSString *) database andTableName: (NSString *) tableName andConverter: (GPKGMapShapeConverter *) converter andStyleCache: (GPKGStyleCache *) styleCache andFeatureRow: (GPKGFeatureRow *) row andCount: (int) count andMaxFeatures: (int) maxFeatures andEditable: (BOOL) editable andFilterBoundingBox: (GPKGBoundingBox *) boundingBox andFilterMaxLongitude: (double) maxLongitude andFilter: (BOOL) filter{ - - GPKGGeometryData * geometryData = [row getGeometry]; - if(geometryData != nil && !geometryData.empty){ - - SFGeometry * geometry = geometryData.geometry; - - if(geometry != nil){ - - BOOL passesFilter = YES; - - if(filter && boundingBox != nil){ - SFGeometryEnvelope * envelope = geometryData.envelope; - if(envelope == nil){ - envelope = [SFGeometryEnvelopeBuilder buildEnvelopeWithGeometry:geometry]; - } - if(envelope != nil){ - if(geometry.geometryType == SF_POINT){ - SFPoint *point = (SFPoint *) geometry; - passesFilter = [GPKGTileBoundingBoxUtils isPoint:point inBoundingBox:boundingBox withMaxLongitude:maxLongitude]; - }else{ - GPKGBoundingBox *geometryBoundingBox = [[GPKGBoundingBox alloc] initWithGeometryEnvelope:envelope]; - passesFilter = [GPKGTileBoundingBoxUtils overlapWithBoundingBox:boundingBox andBoundingBox:geometryBoundingBox withMaxLongitude:maxLongitude] != nil; - } - } - } - - if(passesFilter && count++ < maxFeatures){ - NSNumber * featureId = [row getId]; - GPKGMapShape * shape = [converter toShapeWithGeometry:geometry]; - [self updateFeaturesBoundingBox:shape]; - [self prepareShapeOptionsWithShape:shape andStyleCache:styleCache andFeature:row andEditable:editable andTopLevel:true]; - dispatch_sync(dispatch_get_main_queue(), ^{ - GPKGMapShape * mapShape = [GPKGMapShapeConverter addMapShape:shape toMapView:self.mapView]; - if(self.editFeaturesMode){ - GPKGMapPoint *mapPoint = [self addEditableShapeWithFeatureId:featureId andShape:mapShape]; - if(mapPoint != nil){ - GPKGMapShape *mapPointShape = [[GPKGMapShape alloc] initWithGeometryType:SF_POINT andShapeType:GPKG_MST_POINT andShape:mapPoint]; - [self.featureShapes addMapMetadataShape:mapPointShape withFeatureId:featureId toDatabase:database withTable:tableName]; - } - }else{ - [self addMapPointShapeWithFeatureId:[featureId intValue] andDatabase:database andTableName:tableName andMapShape:mapShape]; - } - [self.featureShapes addMapShape:mapShape withFeatureId:featureId toDatabase:database withTable:tableName]; - }); - } - } - - } - return count; -} - --(void) updateFeaturesBoundingBox: (GPKGMapShape *) shape -{ - if(self.featuresBoundingBox != nil){ - [shape expandBoundingBox:self.featuresBoundingBox]; - }else{ - self.featuresBoundingBox = [shape boundingBox]; - } -} - --(void) prepareShapeOptionsWithShape: (GPKGMapShape *) shape andStyleCache: (GPKGStyleCache *) styleCache andFeature: (GPKGFeatureRow *) featureRow andEditable: (BOOL) editable andTopLevel: (BOOL) topLevel{ - - GPKGFeatureStyle *featureStyle = nil; - if (styleCache != nil) { - featureStyle = [[styleCache featureStyleExtension] featureStyleWithFeature:featureRow andGeometryType:shape.geometryType]; - } - - switch(shape.shapeType){ - case GPKG_MST_POINT: - { - GPKGMapPoint * mapPoint = (GPKGMapPoint *) shape.shape; - [self setShapeOptionsWithMapPoint:mapPoint andStyleCache:styleCache andFeatureStyle:featureStyle andEditable:editable andClickable:topLevel]; - } - break; - - case GPKG_MST_POLYLINE: - { - GPKGPolyline *polyline = (GPKGPolyline *) shape.shape; - [self setShapeOptionsWithPolyline:polyline andStyleCache:styleCache andFeatureStyle:featureStyle andEditable:editable]; - } - break; - - case GPKG_MST_POLYGON: - { - GPKGPolygon *polygon = (GPKGPolygon *) shape.shape; - [self setShapeOptionsWithPolygon:polygon andStyleCache:styleCache andFeatureStyle:featureStyle andEditable:editable]; - } - break; - - case GPKG_MST_MULTI_POINT: - { - GPKGMultiPoint * multiPoint = (GPKGMultiPoint *) shape.shape; - for(GPKGMapPoint * mapPoint in multiPoint.points){ - [self setShapeOptionsWithMapPoint:mapPoint andStyleCache:styleCache andFeatureStyle:featureStyle andEditable:editable andClickable:false]; - } - } - break; - - case GPKG_MST_MULTI_POLYLINE: - { - GPKGMultiPolyline *multiPolyline = (GPKGMultiPolyline *) shape.shape; - for(GPKGPolyline *polyline in multiPolyline.polylines){ - [self setShapeOptionsWithPolyline:polyline andStyleCache:styleCache andFeatureStyle:featureStyle andEditable:editable]; - } - } - break; - - case GPKG_MST_MULTI_POLYGON: - { - GPKGMultiPolygon *multiPolygon = (GPKGMultiPolygon *) shape.shape; - for(GPKGPolygon *polygon in multiPolygon.polygons){ - [self setShapeOptionsWithPolygon:polygon andStyleCache:styleCache andFeatureStyle:featureStyle andEditable:editable]; - } - } - break; - - case GPKG_MST_COLLECTION: - { - NSArray * shapeArray = (NSArray *) shape.shape; - for(GPKGMapShape * shape in shapeArray){ - [self prepareShapeOptionsWithShape:shape andStyleCache:styleCache andFeature:featureRow andEditable:editable andTopLevel:false]; - } - } - break; - - default: - - break; - } - -} - --(void) setShapeOptionsWithMapPoint: (GPKGMapPoint *) mapPoint andStyleCache: (GPKGStyleCache *) styleCache andFeatureStyle: (GPKGFeatureStyle *) featureStyle andEditable: (BOOL) editable andClickable: (BOOL) clickable{ - - if(editable){ - if(clickable){ - [mapPoint.options setPinTintColor:[UIColor greenColor]]; - }else{ - [mapPoint.options setPinTintColor:[UIColor purpleColor]]; - } - }else if(styleCache == nil || ![styleCache setFeatureStyleWithMapPoint:mapPoint andFeatureStyle:featureStyle]){ - [mapPoint.options setPinTintColor:[UIColor purpleColor]]; - } - -} - --(void) setShapeOptionsWithPolyline: (GPKGPolyline *) polyline andStyleCache: (GPKGStyleCache *) styleCache andFeatureStyle: (GPKGFeatureStyle *) featureStyle andEditable: (BOOL) editable{ - - if(editable){ - GPKGPolylineOptions *options = [[GPKGPolylineOptions alloc] init]; - [options setStrokeColor:self.editPolylineColor]; - [options setLineWidth:self.editPolylineLineWidth]; - [polyline setOptions:options]; - }else if(styleCache == nil || ![styleCache setFeatureStyleWithPolyline:polyline andFeatureStyle:featureStyle]){ - GPKGPolylineOptions *options = [[GPKGPolylineOptions alloc] init]; - [options setStrokeColor:self.defaultPolylineColor]; - [options setLineWidth:self.defaultPolylineLineWidth]; - [polyline setOptions:options]; - } - -} - --(void) setShapeOptionsWithPolygon: (GPKGPolygon *) polygon andStyleCache: (GPKGStyleCache *) styleCache andFeatureStyle: (GPKGFeatureStyle *) featureStyle andEditable: (BOOL) editable{ - - if(editable){ - GPKGPolygonOptions *options = [[GPKGPolygonOptions alloc] init]; - [options setStrokeColor:self.editPolygonColor]; - [options setLineWidth:self.editPolygonLineWidth]; - if(self.editPolygonFillColor != nil){ - [options setFillColor:self.editPolygonFillColor]; - } - [polygon setOptions:options]; - }else if(styleCache == nil || ![styleCache setFeatureStyleWithPolygon:polygon andFeatureStyle:featureStyle]){ - GPKGPolygonOptions *options = [[GPKGPolygonOptions alloc] init]; - [options setStrokeColor:self.defaultPolygonColor]; - [options setLineWidth:self.defaultPolygonLineWidth]; - if(self.defaultPolygonFillColor != nil){ - [options setFillColor:self.defaultPolygonFillColor]; - } - [polygon setOptions:options]; - } - -} - --(GPKGMapPoint *) addEditableShapeWithFeatureId: (NSNumber *) featureId andShape: (GPKGMapShape *) shape{ - - GPKGMapPoint * mapPoint = nil; - - if(shape.shapeType == GPKG_MST_POINT){ - mapPoint = (GPKGMapPoint *) shape.shape; - }else{ - mapPoint = [self getMapPointWithShape:shape]; - if(mapPoint != nil){ - [self.editFeatureObjects setObject:shape forKey:[mapPoint getIdAsNumber]]; - } - } - - if(mapPoint != nil){ - [self.editFeatureIds setObject:featureId forKey:[mapPoint getIdAsNumber]]; - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - data.type = GPKGS_MPDT_EDIT_FEATURE; - data.database = self.editFeaturesDatabase; - data.tableName = self.editFeaturesTable; - data.featureId = [featureId intValue]; - [self setTitleWithGeometryType:shape.geometryType andMapPoint:mapPoint]; - } - - return mapPoint; -} - --(void) addMapPointShapeWithFeatureId: (int) featureId andDatabase: (NSString *) database andTableName: (NSString *) tableName andMapShape: (GPKGMapShape *) shape -{ - if(shape.shapeType == GPKG_MST_POINT){ - GPKGMapPoint * mapPoint = (GPKGMapPoint *) shape.shape; - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - data.type = GPKGS_MPDT_POINT; - data.database = database; - data.tableName = tableName; - data.featureId = featureId; - [self setTitleWithGeometryType:shape.geometryType andMapPoint:mapPoint]; - } - -} - --(GPKGMapPoint *) getMapPointWithShape: (GPKGMapShape *) shape{ - - GPKGMapPoint * editMapPoint = nil; - - switch(shape.shapeType){ - - case GPKG_MST_POINT: - { - GPKGMapPoint * mapPoint = (GPKGMapPoint *) shape.shape; - editMapPoint = [self createEditMapPointWithMapPoint:mapPoint]; - } - break; - - case GPKG_MST_POLYLINE: - { - MKPolyline * polyline = (MKPolyline *) shape.shape; - MKMapPoint mkMapPoint = polyline.points[0]; - editMapPoint = [self createEditMapPointWithMKMapPoint:mkMapPoint]; - } - break; - - case GPKG_MST_POLYGON: - { - MKPolygon * polygon = (MKPolygon *) shape.shape; - MKMapPoint mkMapPoint = polygon.points[0]; - editMapPoint = [self createEditMapPointWithMKMapPoint:mkMapPoint]; - } - break; - - case GPKG_MST_MULTI_POINT: - { - GPKGMultiPoint * multiPoint = (GPKGMultiPoint *) shape.shape; - GPKGMapPoint * mapPoint = (GPKGMapPoint *) [multiPoint.points objectAtIndex:0]; - editMapPoint = [self createEditMapPointWithMapPoint:mapPoint]; - } - break; - - case GPKG_MST_MULTI_POLYLINE: - { - GPKGMultiPolyline * multiPolyline = (GPKGMultiPolyline *) shape.shape; - MKPolyline * polyline = [multiPolyline.polylines objectAtIndex:0]; - MKMapPoint mkMapPoint = polyline.points[0]; - editMapPoint = [self createEditMapPointWithMKMapPoint:mkMapPoint]; - } - break; - - case GPKG_MST_MULTI_POLYGON: - { - GPKGMultiPolygon * multiPolygon = (GPKGMultiPolygon *) shape.shape; - MKPolygon * polygon = [multiPolygon.polygons objectAtIndex:0]; - MKMapPoint mkMapPoint = polygon.points[0]; - editMapPoint = [self createEditMapPointWithMKMapPoint:mkMapPoint]; - } - break; - - case GPKG_MST_COLLECTION: - { - NSArray * shapeArray = (NSArray *) shape.shape; - for(GPKGMapShape * shape in shapeArray){ - editMapPoint = [self getMapPointWithShape:shape]; - if(editMapPoint != nil){ - break; - } - } - } - break; - - default: - break; - - } - - return editMapPoint; -} - --(GPKGMapPoint *) createEditMapPointWithMapPoint: (GPKGMapPoint *) mapPoint{ - GPKGMapPoint * editMapPoint = [[GPKGMapPoint alloc] initWithLocation:mapPoint.coordinate]; - [self addEditMapPoint:editMapPoint]; - return editMapPoint; -} - --(GPKGMapPoint *) createEditMapPointWithMKMapPoint: (MKMapPoint) mkMapPoint{ - GPKGMapPoint * editMapPoint = [[GPKGMapPoint alloc] initWithMKMapPoint:mkMapPoint]; - [self addEditMapPoint:editMapPoint]; - return editMapPoint; -} - --(void) addEditMapPoint: (GPKGMapPoint *) editMapPoint{ - [editMapPoint.options setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_EXISTING_FEATURE_IMAGE]]; - [self.mapView addAnnotation:editMapPoint]; -} - --(int) getMaxFeatures{ - int maxFeatures = (int)[self.settings integerForKey:GPKGS_PROP_MAP_MAX_FEATURES]; - if(maxFeatures == 0){ - maxFeatures = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES_DEFAULT] intValue]; - } - return maxFeatures; -} - -- (void)downloadTilesViewController:(GPKGSDownloadTilesViewController *)controller downloadedTiles:(int)count withError: (NSString *) error{ - self.internalSeg = true; - if(count > 0){ - GPKGSTable * table = [[GPKGSTileTable alloc] initWithDatabase:controller.databaseValue.text andName:controller.data.name andCount:0]; - [self.active addTable:table]; - - [self updateInBackgroundWithZoom:false]; - [self.active setModified:true]; - } - if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_CREATE_TILES_DIALOG_LABEL] - andMessage:[NSString stringWithFormat:@"Error downloading tiles to table '%@' in database: '%@'\n\nError: %@", controller.data.name, controller.databaseValue.text, error]]; - } -} - -- (void)selectFeatureTableViewController:(GPKGSSelectFeatureTableViewController *)controller database:(NSString *)database table: (NSString *) table request: (NSString *) request{ - self.internalSeg = true; - if([request isEqualToString:GPKGS_MAP_SEG_EDIT_FEATURES_REQUEST]){ - - if(self.boundingBoxMode){ - [self resetBoundingBox]; - } - - self.editFeaturesDatabase = database; - self.editFeaturesTable = table; - - self.editFeaturesMode = true; - [self setEditFeaturesButtonsHidden:false]; - [self updateInBackgroundWithZoom:false andFilter:true]; - - }else if ([request isEqualToString:GPKGS_MAP_SEG_FEATURE_TILES_REQUEST]){ - - GPKGSTable * dbTable = [[GPKGSTable alloc] initWithDatabase:database andName:table andCount:0]; - [self performSegueWithIdentifier:GPKGS_MAP_SEG_CREATE_FEATURE_TILES sender:dbTable]; - } - -} - -- (void)createFeatureTilesViewController:(GPKGSCreateFeatureTilesViewController *)controller createdTiles:(int)count withError: (NSString *) error{ - self.internalSeg = true; - if(count > 0){ - GPKGSTable * table = [[GPKGSTileTable alloc] initWithDatabase:controller.databaseValue.text andName:controller.nameValue.text andCount:0]; - [self.active addTable:table]; - - [self updateInBackgroundWithZoom:false]; - [self.active setModified:true]; - } - if(error != nil){ - [GPKGSUtils showMessageWithDelegate:self - andTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_GEOPACKAGE_TABLE_CREATE_FEATURE_TILES_LABEL] - andMessage:[NSString stringWithFormat:@"Error creating feature tiles table '%@' for feature table '%@' in database: '%@'\n\nError: %@", controller.nameValue.text, controller.name, controller.database, error]]; - } -} - --(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ - - if([segue.identifier isEqualToString:GPKGS_MAP_SEG_DOWNLOAD_TILES]) - { - GPKGSDownloadTilesViewController *downloadTilesViewController = segue.destinationViewController; - downloadTilesViewController.delegate = self; - downloadTilesViewController.manager = self.manager; - downloadTilesViewController.data = [[GPKGSCreateTilesData alloc] init]; - if(self.boundingBox != nil){ - GPKGBoundingBox * bbox = [self buildBoundingBox]; - [downloadTilesViewController.data.loadTiles.generateTiles setBoundingBox:bbox]; - } - } else if([segue.identifier isEqualToString:GPKGS_MAP_SEG_SELECT_FEATURE_TABLE]){ - GPKGSSelectFeatureTableViewController * selectFeatureTableViewController = segue.destinationViewController; - selectFeatureTableViewController.delegate = self; - selectFeatureTableViewController.manager = self.manager; - selectFeatureTableViewController.active = self.active; - selectFeatureTableViewController.request = self.segRequest; - } else if([segue.identifier isEqualToString:GPKGS_MAP_SEG_CREATE_FEATURE_TILES]){ - GPKGSCreateFeatureTilesViewController *createFeatureTilesViewController = segue.destinationViewController; - GPKGSTable * table = (GPKGSTable *)sender; - createFeatureTilesViewController.delegate = self; - createFeatureTilesViewController.database = table.database; - createFeatureTilesViewController.name = table.name; - createFeatureTilesViewController.manager = self.manager; - createFeatureTilesViewController.featureTilesDrawData = [[GPKGSFeatureTilesDrawData alloc] init]; - createFeatureTilesViewController.generateTilesData = [[GPKGSGenerateTilesData alloc] init]; - if(self.boundingBox != nil){ - GPKGBoundingBox * bbox = [self buildBoundingBox]; - [createFeatureTilesViewController.generateTilesData setBoundingBox:bbox]; - } - } else if([segue.identifier isEqualToString:GPKGS_MAP_SEG_DISPLAY_TEXT]){ - GPKGSDisplayTextViewController *displayTextViewController = segue.destinationViewController; - if([sender isKindOfClass:[GPKGMapPoint class]]){ - GPKGMapPoint * mapPoint = (GPKGMapPoint *)sender; - displayTextViewController.mapPoint = mapPoint; - } - } -} - - --(GPKGBoundingBox *) buildBoundingBox{ - double minLat = 90.0; - double minLon = 180.0; - double maxLat = -90.0; - double maxLon = -180.0; - for(int i = 0; i < self.boundingBox.pointCount; i++){ - MKMapPoint mapPoint = self.boundingBox.points[i]; - CLLocationCoordinate2D coord = MKCoordinateForMapPoint(mapPoint); - minLat = MIN(minLat, coord.latitude); - minLon = MIN(minLon, coord.longitude); - maxLat = MAX(maxLat, coord.latitude); - maxLon = MAX(maxLon, coord.longitude); - } - GPKGBoundingBox * bbox = [[GPKGBoundingBox alloc]initWithMinLongitudeDouble:minLon andMinLatitudeDouble:minLat andMaxLongitudeDouble:maxLon andMaxLatitudeDouble:maxLat]; - return bbox; -} - --(void) setBoundingBoxButtonsHidden: (BOOL) hidden{ - [self.downloadTilesButton setHidden:hidden]; - [self.featureTilesButton setHidden:hidden]; - [self.boundingBoxClearButton setHidden:hidden]; - - if(hidden){ - [self.boundingBoxButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_BOUNDING_BOX_IMAGE] forState:UIControlStateNormal]; - } else{ - [self.boundingBoxButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_BOUNDING_BOX_ACTIVE_IMAGE] forState:UIControlStateNormal]; - } - - [self resetBoundingBoxButtonImages]; -} - --(void) resetBoundingBoxButtonImages{ - [self.boundingBoxClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_BOUNDING_BOX_CLEAR_IMAGE] forState:UIControlStateNormal]; -} - --(void) setEditFeaturesButtonsHidden: (BOOL) hidden{ - - [self.drawPointButton setHidden:hidden]; - [self.drawLineButton setHidden:hidden]; - [self.drawPolygonButton setHidden:hidden]; - [self.editFeaturesConfirmButton setHidden:hidden]; - [self.editFeaturesClearButton setHidden:hidden]; - - if(hidden){ - [self.featuresButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_IMAGE] forState:UIControlStateNormal]; - } else{ - [self.featuresButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_ACTIVE_IMAGE] forState:UIControlStateNormal]; - } - - [self resetEditFeaturesButtonImages]; - - if(hidden){ - [self setEditPolygonHoleButtonsHidden:true]; - } -} - --(void) resetEditFeaturesButtonImages{ - [self.drawPointButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POINT_IMAGE] forState:UIControlStateNormal]; - [self.drawLineButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_LINE_IMAGE] forState:UIControlStateNormal]; - [self.drawPolygonButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POLYGON_IMAGE] forState:UIControlStateNormal]; - [self.editFeaturesConfirmButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_CONFIRM_IMAGE] forState:UIControlStateNormal]; - [self.editFeaturesClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_FEATURES_CLEAR_IMAGE] forState:UIControlStateNormal]; -} - --(void) setEditPolygonHoleButtonsHidden: (BOOL) hidden{ - - [self.drawPolygonHoleButton setHidden:hidden]; - [self.editPolygonHoleConfirmButton setHidden:hidden]; - [self.editPolygonHoleClearButton setHidden:hidden]; - - [self resetEditPolygonHoleButtonImages]; -} - --(void) resetEditPolygonHoleButtonImages{ - [self.drawPolygonHoleButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_DRAW_POLYGON_HOLE_IMAGE] forState:UIControlStateNormal]; - [self resetEditPolygonHoleChoiceButtonImages]; -} - --(void) resetEditPolygonHoleChoiceButtonImages{ - [self.editPolygonHoleConfirmButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POLYGON_HOLE_CONFIRM_IMAGE] forState:UIControlStateNormal]; - [self.editPolygonHoleClearButton setImage:[UIImage imageNamed:GPKGS_MAP_BUTTON_EDIT_POLYGON_HOLE_CLEAR_IMAGE] forState:UIControlStateNormal]; -} - --(GPKGSMapPointData *) getOrCreateDataWithMapPoint: (GPKGMapPoint *) mapPoint{ - if(mapPoint.data == nil){ - mapPoint.data = [[GPKGSMapPointData alloc] init]; - } - return (GPKGSMapPointData *) mapPoint.data; -} - --(void) setTitleWithMapPoint: (GPKGMapPoint *) mapPoint{ - [self setTitleWithTitle:nil andMapPoint:mapPoint]; -} - --(void) setTitleWithGeometryType: (enum SFGeometryType) type andMapPoint: (GPKGMapPoint *) mapPoint{ - NSString * title = nil; - if(type != SF_NONE){ - title = [SFGeometryTypes name:type]; - } - [self setTitleWithTitle:title andMapPoint:mapPoint]; -} - --(void) setTitleWithTitle: (NSString *) title andMapPoint: (GPKGMapPoint *) mapPoint{ - - NSString * locationTitle = [self buildLocationTitleWithMapPoint:mapPoint]; - - if(title == nil){ - [mapPoint setTitle:locationTitle]; - }else{ - [mapPoint setTitle:title]; - [mapPoint setSubtitle:locationTitle]; - } -} - --(void) updateTitleWithMapPoint: (GPKGMapPoint *) mapPoint{ - - NSString * locationTitle = [self buildLocationTitleWithMapPoint:mapPoint]; - - if(mapPoint.subtitle != nil){ - [mapPoint setSubtitle:locationTitle]; - } else{ - [mapPoint setTitle:locationTitle]; - } -} - --(NSString *) buildLocationTitleWithMapPoint: (GPKGMapPoint *) mapPoint{ - - CLLocationCoordinate2D coordinate = mapPoint.coordinate; - - NSString *lat = [self.locationDecimalFormatter stringFromNumber:[NSNumber numberWithDouble:coordinate.latitude]]; - NSString *lon = [self.locationDecimalFormatter stringFromNumber:[NSNumber numberWithDouble:coordinate.longitude]]; - - NSString * title = [NSString stringWithFormat:@"(lat=%@, lon=%@)", lat, lon]; - - return title; -} - --(NSString *) getTitleAndSubtitleWithMapPoint: (GPKGMapPoint *) mapPoint andDelimiter: (NSString *) delimiter{ - NSMutableString * value = [[NSMutableString alloc] init]; - [value appendString:mapPoint.title]; - if(mapPoint.subtitle != nil){ - if(delimiter != nil){ - [value appendString:delimiter]; - } - [value appendString:mapPoint.subtitle]; - } - return value; -} - -@end diff --git a/mapcache-ios/map/GPKGSSelectFeatureTableViewController.h b/mapcache-ios/map/GPKGSSelectFeatureTableViewController.h index 0f985a5..d205a67 100644 --- a/mapcache-ios/map/GPKGSSelectFeatureTableViewController.h +++ b/mapcache-ios/map/GPKGSSelectFeatureTableViewController.h @@ -8,7 +8,7 @@ #import #import "GPKGGeoPackageManager.h" -#import "GPKGSDatabases.h" +#import "MCDatabases.h" @class GPKGSSelectFeatureTableViewController; @@ -20,7 +20,7 @@ @property (nonatomic, weak) id delegate; @property (nonatomic, strong) GPKGGeoPackageManager *manager; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @property (nonatomic, strong) NSString *request; @property (weak, nonatomic) IBOutlet UIPickerView *databasePicker; @property (weak, nonatomic) IBOutlet UIPickerView *featurePicker; diff --git a/mapcache-ios/map/GPKGSSelectFeatureTableViewController.m b/mapcache-ios/map/GPKGSSelectFeatureTableViewController.m index 29b771d..b6ed908 100644 --- a/mapcache-ios/map/GPKGSSelectFeatureTableViewController.m +++ b/mapcache-ios/map/GPKGSSelectFeatureTableViewController.m @@ -7,7 +7,7 @@ // #import "GPKGSSelectFeatureTableViewController.h" -#import "GPKGSUtils.h" +#import "MCUtils.h" @interface GPKGSSelectFeatureTableViewController () @@ -55,7 +55,7 @@ - (void)viewDidLoad { self.tableMapping = tempTableMapping; if([self.databases count] == 0){ - [GPKGSUtils disableButton:self.okButton]; + [MCUtils disableButton:self.okButton]; }else{ self.tables = [self.tableMapping objectForKey:[NSNumber numberWithInt:0]]; self.databasePicker.dataSource = self; @@ -125,7 +125,7 @@ - (NSArray *) getFeatureTables: (NSString *) database{ NSArray * tables = nil; GPKGGeoPackage * geopackage = [self.manager open:database]; @try { - tables = [geopackage getFeatureTables]; + tables = [geopackage featureTables]; } @finally { [geopackage close]; diff --git a/mapcache-ios/map/MCDrawingStatusViewController.h b/mapcache-ios/map/MCDrawingStatusViewController.h new file mode 100644 index 0000000..8e8993a --- /dev/null +++ b/mapcache-ios/map/MCDrawingStatusViewController.h @@ -0,0 +1,44 @@ +// +// MCDrawingStatusViewController.h +// mapcache-ios +// +// Created by Tyler Burgett on 2/20/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import "NGADrawerViewController.h" +#import "MCButtonCell.h" +#import "MCDualButtonCell.h" +#import "MCDescriptionCell.h" +#import "MCTitleCell.h" +#import "MCGeoPackageCell.h" +#import "MCLayerCell.h" +#import "MCLayerCell.h" +#import "MCDatabase.h" +#import "MCDatabases.h" +#import "GPKGUserRow.h" + +NS_ASSUME_NONNULL_BEGIN + + +@protocol MCDrawingStatusDelegate +- (void)cancelDrawingFeatures; +- (void)showNewGeoPacakgeView; +- (void)showNewLayerViewWithDatabase:(MCDatabase*) database; +- (BOOL)savePointsToDatabase:(MCDatabase *)database andTable:(MCTable *) table; +- (void)didSelectGeoPackage:(NSString *)geopackageName; +- (void)didSelectLayer:(NSString *)layerName; +@end + + +@interface MCDrawingStatusViewController : NGADrawerViewController +@property (nonatomic, strong) id drawingStatusDelegate; +@property (nonatomic, strong) NSArray *databases; +@property (nonatomic, strong) MCDatabase *selectedGeoPackage; +- (void)updateStatusLabelWithString:(NSString *) string; +- (void)refreshViewWithNewGeoPackageList:(NSArray *)databases; +- (void)showGeoPackageSelectMode; +- (void)showLayerSelectionMode; +@end + +NS_ASSUME_NONNULL_END diff --git a/mapcache-ios/map/MCDrawingStatusViewController.m b/mapcache-ios/map/MCDrawingStatusViewController.m new file mode 100644 index 0000000..e1996ac --- /dev/null +++ b/mapcache-ios/map/MCDrawingStatusViewController.m @@ -0,0 +1,233 @@ +// +// MCDrawingStatusViewController.m +// mapcache-ios +// +// Created by Tyler Burgett on 2/20/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import "MCDrawingStatusViewController.h" + +@interface MCDrawingStatusViewController () +@property (nonatomic, strong) NSMutableArray *cellArray; +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) MCDescriptionCell *statusCell; +@property (nonatomic, strong) MCDualButtonCell *buttonsCell; +@property (nonatomic, strong) MCTable *selectedTable; +@end + +@implementation MCDrawingStatusViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + CGRect bounds = self.view.bounds; + CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y + 6, bounds.size.width, bounds.size.height); + self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; + self.tableView.delegate = self; + self.tableView.dataSource = self; + //self.tableView.estimatedRowHeight = 390.0; + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.tableView.allowsMultipleSelectionDuringEditing = NO; + [self registerCellTypes]; + [self initCellArray]; + self.edgesForExtendedLayout = UIRectEdgeNone; + self.extendedLayoutIncludesOpaqueBars = NO; + self.automaticallyAdjustsScrollViewInsets = NO; + + [self.view addSubview:self.tableView]; + [self.tableView setScrollEnabled:NO]; +} + + +- (void)registerCellTypes { + [self.tableView registerNib:[UINib nibWithNibName:@"MCButtonCell" bundle:nil] forCellReuseIdentifier:@"button"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCDualButtonCell" bundle:nil] forCellReuseIdentifier:@"buttons"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCTitleCell" bundle:nil] forCellReuseIdentifier:@"title"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCDescriptionCell" bundle:nil] forCellReuseIdentifier:@"description"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCGeoPackageCell" bundle:nil] forCellReuseIdentifier:@"geopackage"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCLayerCell" bundle:nil] forCellReuseIdentifier:@"layer"]; +} + + +- (void)initCellArray { + _cellArray = [[NSMutableArray alloc] init]; + + _statusCell = [_tableView dequeueReusableCellWithIdentifier:@"description"]; + [_statusCell textAlignCenter]; + [_statusCell setDescription:@"1 new point"]; + + _buttonsCell = [_tableView dequeueReusableCellWithIdentifier:@"buttons"]; + _buttonsCell.dualButtonDelegate = self; + [_buttonsCell setLeftButtonLabel:@"Cancel"]; + [_buttonsCell setLeftButtonAction:@"cancel"]; + [_buttonsCell setRightButtonLabel:@"Continue"]; + [_buttonsCell setRightButtonAction:@"show-select"]; + + [_cellArray addObject:_statusCell]; + [_cellArray addObject:_buttonsCell]; +} + + +- (void)refreshViewWithNewGeoPackageList:(NSArray *)databases { + [_tableView reloadData]; + _databases = databases; + [self showGeoPackageSelectMode]; +} + + +- (void)showGeoPackageSelectMode { + NSMutableArray *switchModeCells = [[NSMutableArray alloc] init]; + + _buttonsCell = [_tableView dequeueReusableCellWithIdentifier:@"buttons"]; + _buttonsCell.dualButtonDelegate = self; + [_buttonsCell setLeftButtonLabel:@"Cancel"]; + [_buttonsCell setLeftButtonAction:@"cancel"]; + [_buttonsCell setRightButtonLabel:@"New GeoPacakge"]; + [_buttonsCell setRightButtonAction:@"new-geopackage"]; + [switchModeCells addObject:_buttonsCell]; + + MCDescriptionCell *chooseGeoPackageHelp = [_tableView dequeueReusableCellWithIdentifier:@"description"]; + [chooseGeoPackageHelp setDescription:@"To save your new point, either create a new GeoPackage or select one from below."]; + [switchModeCells addObject:chooseGeoPackageHelp]; + + for (MCDatabase *database in _databases) { + MCGeoPackageCell *geoPackageCell = [_tableView dequeueReusableCellWithIdentifier:@"geopackage"]; + [geoPackageCell setContentWithDatabase:database]; + [geoPackageCell activeLayersIndicatorOff]; + [switchModeCells addObject:geoPackageCell]; + } + + [self makeFullView]; + _cellArray = switchModeCells; + + [_tableView reloadData]; + [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; + [self.tableView setScrollEnabled:YES]; +} + + +- (void)updateStatusLabelWithString:(NSString *) string { + [_statusCell setDescription:string]; + +} + + +- (void)showLayerSelectionMode { + NSMutableArray *layerSelectionModeCells = [[NSMutableArray alloc] init]; + + _buttonsCell = [_tableView dequeueReusableCellWithIdentifier:@"buttons"]; + _buttonsCell.dualButtonDelegate = self; + [_buttonsCell setLeftButtonLabel:@"Cancel"]; + [_buttonsCell setLeftButtonAction:@"cancel"]; + [_buttonsCell setRightButtonLabel:@"New Layer"]; + [_buttonsCell setRightButtonAction:@"new-layer"]; + [layerSelectionModeCells addObject:_buttonsCell]; + + MCGeoPackageCell *geoPackageCell = [_tableView dequeueReusableCellWithIdentifier:@"geopackage"]; + [geoPackageCell setContentWithDatabase:_selectedGeoPackage]; + [geoPackageCell activeLayersIndicatorOff]; + [layerSelectionModeCells addObject:geoPackageCell]; + + MCDescriptionCell *chooselayerHelp = [_tableView dequeueReusableCellWithIdentifier:@"description"]; + [chooselayerHelp setDescription:@"Create a new layer or select one from below."]; + [layerSelectionModeCells addObject:chooselayerHelp]; + + for (MCTable *table in [_selectedGeoPackage getFeatures]) { + MCLayerCell *layerCell = [_tableView dequeueReusableCellWithIdentifier:@"layer"]; + [layerCell setContentsWithTable:table]; + [layerCell activeIndicatorOff]; + [layerSelectionModeCells addObject:layerCell]; + } + + _cellArray = layerSelectionModeCells; + [_tableView reloadData]; + [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; + [self.tableView setScrollEnabled:YES]; +} + + +- (void)showSaveMode { + NSMutableArray *saveModeCells = [[NSMutableArray alloc] init]; + + MCDescriptionCell *saveDescription = [_tableView dequeueReusableCellWithIdentifier:@"description"]; + [saveDescription setDescription:@"Tap below to save your features."]; + [saveModeCells addObject:saveDescription]; + + MCGeoPackageCell *geoPackageCell = [_tableView dequeueReusableCellWithIdentifier:@"geopackage"]; + [geoPackageCell setContentWithDatabase:_selectedGeoPackage]; + [geoPackageCell activeLayersIndicatorOff]; + [saveModeCells addObject:geoPackageCell]; + + MCLayerCell *layerCell = [_tableView dequeueReusableCellWithIdentifier:@"layer"]; + [layerCell setContentsWithTable:_selectedTable]; + [layerCell activeIndicatorOff]; + [saveModeCells addObject:layerCell]; + + _buttonsCell = [_tableView dequeueReusableCellWithIdentifier:@"buttons"]; + _buttonsCell.dualButtonDelegate = self; + [_buttonsCell setLeftButtonLabel:@"Discard"]; + [_buttonsCell setLeftButtonAction:@"cancel"]; + [_buttonsCell setRightButtonLabel:@"Save"]; + [_buttonsCell setRightButtonAction:@"save"]; + [saveModeCells addObject:_buttonsCell]; + + _cellArray = saveModeCells; + [_tableView reloadData]; + [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; +} + + +#pragma mark - UITableView datasource and delegate methods +- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { + return [_cellArray objectAtIndex:indexPath.row]; +} + + +- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [_cellArray count]; +} + + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSObject *cellObject = [_cellArray objectAtIndex:indexPath.row]; + + if ([cellObject isKindOfClass:[MCGeoPackageCell class]]) { + _selectedGeoPackage = ((MCGeoPackageCell *)cellObject).database; + [self.drawingStatusDelegate didSelectGeoPackage:_selectedGeoPackage.name]; + [self showLayerSelectionMode]; + } else if ([cellObject isKindOfClass:[MCLayerCell class]]) { + _selectedTable = ((MCLayerCell *)cellObject).table; + [self.drawingStatusDelegate didSelectLayer:_selectedTable.name]; + } + +} + + +#pragma mark - MCDualButtonCellDelegate +- (void) performDualButtonAction:(NSString *)action { + if ([action isEqualToString:@"show-select"]) { + NSLog(@"Continue tapped"); + [self showGeoPackageSelectMode]; + } else if ([action isEqualToString:@"new-geopackage"]) { + NSLog(@"Show new GeoPackage view."); + [self.drawingStatusDelegate showNewGeoPacakgeView]; + } else if ([action isEqualToString:@"new-layer"]) { + NSLog(@"Show new layer view."); + [self.drawingStatusDelegate showNewLayerViewWithDatabase:_selectedGeoPackage]; + } else if ([action isEqualToString:@"save"]) { + BOOL pointsSaved = [self.drawingStatusDelegate savePointsToDatabase: _selectedGeoPackage andTable:_selectedTable]; + if (pointsSaved) { + [self.drawerViewDelegate popDrawer]; + } + } else { + NSLog(@"Cancel tapped"); + [self.drawingStatusDelegate cancelDrawingFeatures]; + [self.drawerViewDelegate popDrawer]; + } +} + + +@end diff --git a/mapcache-ios/map/MCFeatureHelper.h b/mapcache-ios/map/MCFeatureHelper.h index 254ae7e..65d10b6 100644 --- a/mapcache-ios/map/MCFeatureHelper.h +++ b/mapcache-ios/map/MCFeatureHelper.h @@ -24,8 +24,8 @@ #import "GPKGFeatureIndexManager.h" #import "GPKGFeatureIndexResults.h" #import "GPKGMultipleFeatureIndexResults.h" -#import "GPKGSDatabase.h" -#import "GPKGSDatabases.h" +#import "MCDatabase.h" +#import "MCDatabases.h" #import "GPKGGeoPackage.h" #import "GPKGSMapPointData.h" #import "GPKGStyleCache.h" @@ -50,7 +50,7 @@ - (int)getNewFeatureUpdateId; - (void)prepareFeaturesWithUpdateId:(int) updateId andFeatureUpdateId:(int) featureUpdateId andZoom:(int) zoom andMaxFeatures:(int) maxFeatures andMapViewBoundingBox:(GPKGBoundingBox *) mapViewBoudingBox andToleranceDistance:(double) toleranceDistance andFilter:(BOOL) filter; -- (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase:(GPKGSDatabase *) database andUpdateId:(int) updateId andFeatureUpdateId:(int) featureUpdateId andZoom:(int) zoom andMaxFeatures:(int) maxFeatures andMapViewBoundingBox:(GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance:(double) toleranceDistance andFilter:(BOOL) filter; +- (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase:(MCDatabase *) database andUpdateId:(int) updateId andFeatureUpdateId:(int) featureUpdateId andZoom:(int) zoom andMaxFeatures:(int) maxFeatures andMapViewBoundingBox:(GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance:(double) toleranceDistance andFilter:(BOOL) filter; -(void) addMapPointShapeWithFeatureId: (int) featureId andDatabase: (NSString *) database andTableName: (NSString *) tableName andMapShape: (GPKGMapShape *) shape; @@ -60,10 +60,10 @@ -(void) prepareShapeOptionsWithShape: (GPKGMapShape *) shape andStyleCache: (GPKGStyleCache *) styleCache andFeature: (GPKGFeatureRow *) featureRow andEditable: (BOOL) editable andTopLevel: (BOOL) topLevel; --(int) addFeaturesWithId: (int) updateId andMaxFeatures: (int) maxFeatures andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter; +-(int) addFeaturesWithFeaureUpdateId: (int) updateId andMaxFeatures: (int) maxFeatures andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter; -(GPKGMapShape *) processFeatureRow: (GPKGFeatureRow *) row WithDatabase: (NSString *) database andTableName: (NSString *) tableName andConverter: (GPKGMapShapeConverter *) converter andStyleCache: (GPKGStyleCache *) styleCache andCount: (int) count andMaxFeatures: (int) maxFeatures andEditable: (BOOL) editable andFilterBoundingBox: (GPKGBoundingBox *) boundingBox andFilterMaxLongitude: (double) maxLongitude andFilter: (BOOL) filter; - +-(NSString *) buildLocationTitleWithMapPoint: (GPKGMapPoint *) mapPoint; @end diff --git a/mapcache-ios/map/MCFeatureHelper.m b/mapcache-ios/map/MCFeatureHelper.m index 31bb62f..634ad7c 100644 --- a/mapcache-ios/map/MCFeatureHelper.m +++ b/mapcache-ios/map/MCFeatureHelper.m @@ -12,7 +12,7 @@ @interface MCFeatureHelper () @property (nonatomic, strong) GPKGBoundingBox *featuresBoundingBox; @property (nonatomic, strong) NSNumberFormatter *locationDecimalFormatter; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @property (nonatomic, strong) GPKGGeoPackageManager *manager; @property (nonatomic, strong) NSMutableDictionary *geoPackages; @property (nonatomic, strong) NSMutableDictionary *featureDaos; @@ -30,8 +30,8 @@ - (instancetype) initWithFeatureHelperDelegate:(id) del self.locationDecimalFormatter = [[NSNumberFormatter alloc] init]; self.locationDecimalFormatter.numberStyle = NSNumberFormatterDecimalStyle; self.locationDecimalFormatter.maximumFractionDigits = 4; - self.active = [GPKGSDatabases getInstance]; - self.manager = [GPKGGeoPackageFactory getManager]; + self.active = [MCDatabases getInstance]; + self.manager = [GPKGGeoPackageFactory manager]; self.geoPackages = [[NSMutableDictionary alloc] init]; self.featureDaos = [[NSMutableDictionary alloc] init]; self.featureUpdateCountId = 0; @@ -49,43 +49,54 @@ - (void)prepareFeaturesWithUpdateId:(int) updateId andFeatureUpdateId:(int) feat NSArray * activeDatabases = [[NSArray alloc] initWithArray:[self.active getDatabases]]; // Open active GeoPackages and create feature DAOS, and feature tiles - for(GPKGSDatabase * database in activeDatabases){ + for(MCDatabase * database in activeDatabases){ if([self updateCanceled:updateId]){ break; } - GPKGGeoPackage * geoPackage = [self.manager open:database.name]; + GPKGGeoPackage * geoPackage; - if(geoPackage != nil){ - [self.geoPackages setObject:geoPackage forKey:database.name]; - - NSMutableSet * featureTableDaos = [[NSMutableSet alloc] init]; - NSArray * features = [database getFeatures]; - if([features count] > 0){ - for(GPKGSTable * features in [database getFeatures]){ - [featureTableDaos addObject:features.name]; + @try { + geoPackage = [self.manager open:database.name]; + + if(geoPackage != nil){ + [self.geoPackages setObject:geoPackage forKey:database.name]; + + NSMutableSet * featureTableDaos = [[NSMutableSet alloc] init]; + NSArray * features = [database getFeatures]; + if([features count] > 0){ + for(MCTable * features in [database getFeatures]){ + [featureTableDaos addObject:features.name]; + } } - } - - if(featureTableDaos.count > 0){ - NSMutableDictionary * databaseFeatureDaos = [[NSMutableDictionary alloc] init]; - [self.featureDaos setObject:databaseFeatureDaos forKey:database.name]; - for(NSString *featureTable in featureTableDaos){ - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:featureTable]; - [databaseFeatureDaos setObject:featureDao forKey:featureTable]; + + if(featureTableDaos.count > 0){ + NSMutableDictionary * databaseFeatureDaos = [[NSMutableDictionary alloc] init]; + [self.featureDaos setObject:databaseFeatureDaos forKey:database.name]; + for(NSString *featureTable in featureTableDaos){ + + if([self updateCanceled:updateId]){ + break; + } + + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:featureTable]; + [databaseFeatureDaos setObject:featureDao forKey:featureTable]; + } } + } else{ + [self.active removeDatabase:database.name andPreserveOverlays:false]; } - } else{ - [self.active removeDatabase:database.name andPreserveOverlays:false]; + } @catch (NSException *e) { + NSLog(@"Problem preparing features in %@ %@", database.name, e.reason); } } - count = [self addFeaturesWithId:featureUpdateId andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; + count = [self addFeaturesWithFeaureUpdateId:featureUpdateId andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; } -- (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase:(GPKGSDatabase *) database andUpdateId:(int) updateId andFeatureUpdateId:(int) featureUpdateId andZoom:(int) zoom andMaxFeatures:(int) maxFeatures andMapViewBoundingBox:(GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance:(double) toleranceDistance andFilter:(BOOL) filter { +- (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase:(MCDatabase *) database andUpdateId:(int) updateId andFeatureUpdateId:(int) featureUpdateId andZoom:(int) zoom andMaxFeatures:(int) maxFeatures andMapViewBoundingBox:(GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance:(double) toleranceDistance andFilter:(BOOL) filter { if([self updateCanceled:updateId]){ return; @@ -97,8 +108,8 @@ - (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase: NSMutableSet * featureTableDaos = [[NSMutableSet alloc] init]; NSArray * features = [database getFeatures]; if([features count] > 0){ - for(GPKGSTable * features in [database getFeatures]){ - [featureTableDaos addObject:features.name]; + for(MCTable * featureTable in features){ + [featureTableDaos addObject:featureTable.name]; } } @@ -106,7 +117,12 @@ - (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase: NSMutableDictionary * databaseFeatureDaos = [[NSMutableDictionary alloc] init]; [self.featureDaos setObject:databaseFeatureDaos forKey:database.name]; for(NSString *featureTable in featureTableDaos){ - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:featureTable]; + + if([self updateCanceled:updateId]){ + break; + } + + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:featureTable]; [databaseFeatureDaos setObject:featureDao forKey:featureTable]; } } @@ -114,11 +130,11 @@ - (void)prepareFeaturesWithGeoPackage:(GPKGGeoPackage *) geoPackage andDatabase: [self.active removeDatabase:database.name andPreserveOverlays:false]; } - [self addFeaturesWithId:featureUpdateId andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; + [self addFeaturesWithFeaureUpdateId:featureUpdateId andMaxFeatures:maxFeatures andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; } --(int) addFeaturesWithId: (int) updateId andMaxFeatures: (int) maxFeatures andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter { +-(int) addFeaturesWithFeaureUpdateId: (int) featureUpdateId andMaxFeatures: (int) maxFeatures andMapViewBoundingBox: (GPKGBoundingBox *) mapViewBoundingBox andToleranceDistance: (double) toleranceDistance andFilter: (BOOL) filter { // Add features NSMutableDictionary * featureTables = [[NSMutableDictionary alloc] init]; // if(self.editFeaturesMode){ @@ -141,12 +157,12 @@ -(int) addFeaturesWithId: (int) updateId andMaxFeatures: (int) maxFeatures andMa // [databaseFeatureDaos setObject:featureDao forKey:self.editFeaturesTable]; // } // }else{ - for(GPKGSDatabase * database in [self.active getDatabases]){ + for(MCDatabase * database in [self.active getDatabases]){ NSArray * features = [database getFeatures]; if([features count] > 0){ NSMutableArray * databaseFeatures = [[NSMutableArray alloc] init]; [featureTables setObject:databaseFeatures forKey:database.name]; - for(GPKGSTable * features in [database getFeatures]){ + for(MCTable * features in [database getFeatures]){ [databaseFeatures addObject:features.name]; } } @@ -167,11 +183,10 @@ -(int) addFeaturesWithId: (int) updateId andMaxFeatures: (int) maxFeatures andMa GPKGStyleCache *styleCache = [[GPKGStyleCache alloc] initWithGeoPackage:geoPackage]; for(NSString * features in databaseFeatures){ - if([[self.featureDaos objectForKey:databaseName] objectForKey:features] != nil){ - self.featureCount = [self displayFeaturesWithId:updateId andGeoPackage:geoPackage andStyleCache:styleCache andFeatures:features andCount:self.featureCount andMaxFeatures:maxFeatures andEditable:NO andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; - if([self featureUpdateCanceled:updateId]){ + self.featureCount = [self displayFeaturesWithId:featureUpdateId andGeoPackage:geoPackage andStyleCache:styleCache andFeatures:features andCount:self.featureCount andMaxFeatures:maxFeatures andEditable:NO andMapViewBoundingBox:mapViewBoundingBox andToleranceDistance:toleranceDistance andFilter:filter]; + if([self featureUpdateCanceled:featureUpdateId]){ break; } else if (self.featureCount >= maxFeatures) { [self.featureHelperDelegate showMaxFeaturesWarning]; @@ -183,7 +198,7 @@ -(int) addFeaturesWithId: (int) updateId andMaxFeatures: (int) maxFeatures andMa [styleCache clear]; } - if([self featureUpdateCanceled:updateId]){ + if([self featureUpdateCanceled:featureUpdateId]){ break; } } @@ -198,7 +213,6 @@ -(int) displayFeaturesWithId: (int) updateId andGeoPackage: (GPKGGeoPackage *) g GPKGFeatureDao * featureDao = [[self.featureDaos objectForKey:database] objectForKey:features]; NSString * tableName = featureDao.tableName; GPKGMapShapeConverter * converter = [[GPKGMapShapeConverter alloc] initWithProjection:featureDao.projection]; - [converter setSimplifyToleranceAsDouble:toleranceDistance]; if(![[styleCache featureStyleExtension] hasWithTable:features]){ @@ -208,16 +222,15 @@ -(int) displayFeaturesWithId: (int) updateId andGeoPackage: (GPKGGeoPackage *) g count += [self.featureShapes featureIdsCountInDatabase:database withTable:tableName]; if(![self featureUpdateCanceled:updateId] && count < maxFeatures){ - SFPProjection *mapViewProjection = [SFPProjectionFactory projectionWithEpsgInt: PROJ_EPSG_WORLD_GEODETIC_SYSTEM]; - + NSArray *columns = [featureDao idAndGeometryColumnNames]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; + if(filter && [indexer isIndexed]){ - - GPKGFeatureIndexResults *indexResults = [indexer queryWithBoundingBox:mapViewBoundingBox inProjection:mapViewProjection]; + GPKGFeatureIndexResults *indexResults = [indexer queryWithColumns:columns andBoundingBox:mapViewBoundingBox inProjection:mapViewProjection]; GPKGBoundingBox *complementary = [mapViewBoundingBox complementaryWgs84]; if(complementary != nil){ - GPKGFeatureIndexResults *indexResults2 = [indexer queryWithBoundingBox:complementary inProjection:mapViewProjection]; + GPKGFeatureIndexResults *indexResults2 = [indexer queryWithColumns:columns andBoundingBox:complementary inProjection:mapViewProjection]; indexResults = [[GPKGMultipleFeatureIndexResults alloc] initWithFeatureIndexResults1:indexResults andFeatureIndexResults2:indexResults2]; } count = [self processFeatureIndexResults:indexResults withUpdateId:updateId andDatabase:database andCount:count andMaxFeatures:maxFeatures andEditable:editable andTableName:tableName andConverter:converter andStyleCache:styleCache andFilter:filter]; @@ -241,22 +254,26 @@ -(int) displayFeaturesWithId: (int) updateId andGeoPackage: (GPKGGeoPackage *) g } // Query for all rows - GPKGResultSet * results = [featureDao queryForAll]; + GPKGResultSet * results = [featureDao queryWithColumns:columns]; @try { while(![self featureUpdateCanceled:updateId] && count < maxFeatures && [results moveToNext]){ @try { - GPKGFeatureRow * row = [featureDao getFeatureRow:results]; - GPKGMapShape *shape = [self processFeatureRow:row WithDatabase:database andTableName:tableName andConverter:converter andStyleCache:styleCache andCount:count andMaxFeatures:maxFeatures andEditable:editable andFilterBoundingBox:filterBoundingBox andFilterMaxLongitude:filterMaxLongitude andFilter:filter]; + GPKGFeatureRow * row = [featureDao featureRow:results]; - if (shape != nil && count++ < maxFeatures) { - [self.featureHelperDelegate addShapeToMapView:shape withCount:count]; + if (![self.featureShapes existsWithFeatureId:[row id] inDatabase:database withTable:[row tableName]]) { + GPKGMapShape *shape = [self processFeatureRow:row WithDatabase:database andTableName:tableName andConverter:converter andStyleCache:styleCache andCount:count andMaxFeatures:maxFeatures andEditable:editable andFilterBoundingBox:filterBoundingBox andFilterMaxLongitude:filterMaxLongitude andFilter:filter]; + + if (shape != nil && count++ < maxFeatures) { + [self.featureHelperDelegate addShapeToMapView:shape withCount:count]; + } } } @catch (NSException *exception) { NSLog(@"Failed to display feature. database: %@, feature table: %@, error: %@", database, features, [exception description]); } } - } - @finally { + } @catch(NSException *e) { + NSLog(@"---------- MCFeatureHelper - DisplayFeaturesWithId\n%@", e.reason); + } @finally { [results close]; } } @@ -275,7 +292,7 @@ -(int) processFeatureIndexResults: (GPKGFeatureIndexResults *) indexResults with break; } - if(![self.featureShapes existsWithFeatureId:[row getId] inDatabase:database withTable:tableName]){ + if(![self.featureShapes existsWithFeatureId:[row id] inDatabase:database withTable:tableName]){ GPKGMapShape *shape = [self processFeatureRow:row WithDatabase:database andTableName:tableName andConverter:converter andStyleCache:styleCache andCount:count andMaxFeatures:maxFeatures andEditable:editable andFilterBoundingBox:nil andFilterMaxLongitude:0 andFilter:filter]; if (shape != nil && count++ < maxFeatures) { @@ -365,7 +382,7 @@ -(NSString *) buildLocationTitleWithMapPoint: (GPKGMapPoint *) mapPoint{ CLLocationCoordinate2D coordinate = mapPoint.coordinate; NSString *lat = [self.locationDecimalFormatter stringFromNumber:[NSNumber numberWithDouble:coordinate.latitude]]; NSString *lon = [self.locationDecimalFormatter stringFromNumber:[NSNumber numberWithDouble:coordinate.longitude]]; - NSString * title = [NSString stringWithFormat:@"(lat=%@, lon=%@)", lat, lon]; + NSString * title = [NSString stringWithFormat:@"lat: %@, lon: %@", lat, lon]; return title; } @@ -505,7 +522,7 @@ -(void) prepareShapeOptionsWithShape: (GPKGMapShape *) shape andStyleCache: (GPK -(GPKGMapShape *) processFeatureRow: (GPKGFeatureRow *) row WithDatabase: (NSString *) database andTableName: (NSString *) tableName andConverter: (GPKGMapShapeConverter *) converter andStyleCache: (GPKGStyleCache *) styleCache andCount: (int) count andMaxFeatures: (int) maxFeatures andEditable: (BOOL) editable andFilterBoundingBox: (GPKGBoundingBox *) boundingBox andFilterMaxLongitude: (double) maxLongitude andFilter: (BOOL) filter { - GPKGGeometryData * geometryData = [row getGeometry]; + GPKGGeometryData * geometryData = [row geometry]; if(geometryData != nil && !geometryData.empty){ SFGeometry * geometry = geometryData.geometry; @@ -524,14 +541,14 @@ -(GPKGMapShape *) processFeatureRow: (GPKGFeatureRow *) row WithDatabase: (NSStr SFPoint *point = (SFPoint *) geometry; passesFilter = [GPKGTileBoundingBoxUtils isPoint:point inBoundingBox:boundingBox withMaxLongitude:maxLongitude]; }else{ - GPKGBoundingBox *geometryBoundingBox = [[GPKGBoundingBox alloc] initWithGeometryEnvelope:envelope]; + GPKGBoundingBox *geometryBoundingBox = [[GPKGBoundingBox alloc] initWithEnvelope:envelope]; passesFilter = [GPKGTileBoundingBoxUtils overlapWithBoundingBox:boundingBox andBoundingBox:geometryBoundingBox withMaxLongitude:maxLongitude] != nil; } } } if(passesFilter){ - NSNumber * featureId = [row getId]; + NSNumber * featureId = [row id]; GPKGMapShape * shape = [converter toShapeWithGeometry:geometry]; [self updateFeaturesBoundingBox:shape]; [self prepareShapeOptionsWithShape:shape andStyleCache:styleCache andFeature:row andEditable:editable andTopLevel:true]; diff --git a/mapcache-ios/map/MCMapCoordinator.h b/mapcache-ios/map/MCMapCoordinator.h index 722d145..09a197a 100644 --- a/mapcache-ios/map/MCMapCoordinator.h +++ b/mapcache-ios/map/MCMapCoordinator.h @@ -12,6 +12,12 @@ #import "GPKGGeoPackageManager.h" #import "MCSettingsCoordinator.h" #import "MCBoundingBoxGuideView.h" +#import "MCDrawingStatusViewController.h" +#import "MCGeoPackageRepository.h" +#import "MCCreateGeoPacakgeViewController.h" +#import "MCFeatureLayerDetailsViewController.h" +#import "MCMapPointDataViewController.h" + @class MCMapViewController; @@ -19,16 +25,16 @@ @protocol MCMapDelegate - (void) updateMapLayers; -- (void) toggleGeoPackage:(GPKGSDatabase *) geoPackage; +- (void) toggleGeoPackage:(MCDatabase *) geoPackage; - (void) zoomToSelectedGeoPackage:(NSString *) geoPackageName; -- (void) setupTileBoundingBoxGuide:(UIView *) boudingBoxGuideView; +- (void)zoomToPoint:(CLLocationCoordinate2D)point withZoomLevel:(NSUInteger) zoomLevel; +- (void) setupTileBoundingBoxGuide:(UIView *) boudingBoxGuideView tileUrl:(NSString *)tileUrl; - (void) removeTileBoundingBoxGuide; - (CLLocationCoordinate2D) convertPointToCoordinate:(CGPoint) point; @end -@interface MCMapCoordinator : NSObject +@interface MCMapCoordinator : NSObject - (instancetype) initWithMapViewController:(MCMapViewController *) mapViewController; - @property (nonatomic, strong) id drawerViewDelegate; @end diff --git a/mapcache-ios/map/MCMapCoordinator.m b/mapcache-ios/map/MCMapCoordinator.m index 1fb0a8b..8160d54 100644 --- a/mapcache-ios/map/MCMapCoordinator.m +++ b/mapcache-ios/map/MCMapCoordinator.m @@ -19,6 +19,11 @@ @interface MCMapCoordinator () @property (nonatomic, strong) GPKGGeoPackageManager *manager; @property (nonatomic, strong) NSMutableArray *childCoordinators; @property (nonatomic, strong) NSUserDefaults *preferences; +@property (nonatomic, strong) MCDrawingStatusViewController *drawingStatusViewController; +@property (nonatomic, strong) MCMapPointDataViewController *mapPointDataViewController; +@property (nonatomic, strong) MCFeatureLayerDetailsViewController *featureLayerDetailsView; +@property (nonatomic, strong) MCGeoPackageRepository *repository; +@property (nonatomic, strong) GPKGMapPoint *mapPoint; @end @@ -28,16 +33,17 @@ - (instancetype) initWithMapViewController:(MCMapViewController *) mapViewContro self = [super init]; self.mcMapViewController = mapViewController; self.mcMapViewController.mapActionDelegate = self; - self.manager = [GPKGGeoPackageFactory getManager]; + self.manager = [GPKGGeoPackageFactory manager]; self.childCoordinators = [[NSMutableArray alloc] init]; self.preferences = [NSUserDefaults standardUserDefaults]; + self.repository = [MCGeoPackageRepository sharedRepository]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(layerRenamed:) name:@"MC_LAYER_RENAMED" object:nil]; return self; } - (void) loadPreferences { - [self.preferences stringForKey:MC_MAP_TYPE_PREFERENCE]; [self.preferences integerForKey:MC_MAX_FEATURES_PREFERENCE]; // check for a map prefenrence, if there isnt one, use the standard map @@ -56,32 +62,69 @@ - (void) setMaxFeaturesPreference { } +- (void)layerRenamed:(NSNotification *)notification { + [self updateMapLayers]; +} + + #pragma mark - MCMapDelegate methods +/** + Update the data on the map. + */ - (void) updateMapLayers { NSLog(@"In MapCoordinator, going to update layers"); - [self.mcMapViewController updateInBackgroundWithZoom:NO]; + self.mcMapViewController.active = [_repository activeDatabases]; + [self.mcMapViewController updateInBackgroundWithZoom:NO andFilter:YES]; } -- (void) toggleGeoPackage:(GPKGSDatabase *) geoPackage { +- (void) toggleGeoPackage:(MCDatabase *) geoPackage { NSLog(@"In MCMapCoordinator, going to toggle %@", geoPackage.name); } +/** + React to a GeoPackage being selected from the list. Set the map region to have the selected GeoPackage in view. + */ - (void)zoomToSelectedGeoPackage:(NSString *)geoPackageName { - GPKGGeoPackage *geoPackage = [self.manager open:geoPackageName]; - GPKGBoundingBox *boundingBox = [geoPackage contentsBoundingBoxInProjection:[SFPProjectionFactory projectionWithEpsgInt:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]]; - CLLocationCoordinate2D center = [boundingBox getCenter]; + GPKGGeoPackage *geoPackage = nil; - if (center.latitude != 0 && center.longitude != 0) { - [self.mcMapViewController zoomToPointWithOffset:center]; + @try { + geoPackage = [self.manager open:geoPackageName]; + GPKGBoundingBox *boundingBox = [geoPackage contentsBoundingBoxInProjection:[SFPProjectionFactory projectionWithEpsgInt:PROJ_EPSG_WORLD_GEODETIC_SYSTEM]]; + CLLocationCoordinate2D center = [boundingBox center]; + + if (center.latitude != 0 && center.longitude != 0) { + [self.mcMapViewController zoomToPointWithOffset:center]; + } + } @catch (NSException *e) { + NSLog(@"MCMapCoordinator - Problem zooming to geopacakge\n%@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } } - - [geoPackage close]; } -- (void) setupTileBoundingBoxGuide:(UIView *) boudingBoxGuideView { +/** + React to a GeoPackage being selected from the list. Set the map region to have the selected GeoPackage in view. + */ +- (void)zoomToPoint:(CLLocationCoordinate2D)point withZoomLevel:(NSUInteger) zoomLevel { + if (point.latitude != 0 && point.longitude != 0) { + @try { + [self.mcMapViewController zoomToPointWithOffset:point zoomLevel:zoomLevel]; + } @catch (NSException *e) { + NSLog(@"MCMapCoordinator - Problem zooming to point\n%@", e.reason); + } + } +} + + +/** + Get the map view ready to select an area where you would like to download tiles. + */ +- (void) setupTileBoundingBoxGuide:(UIView *) boudingBoxGuideView tileUrl:(NSString *)tileUrl { self.boundingBoxGuideView = boudingBoxGuideView; self.boundingBoxGuideView.alpha = 0.0; [self.mcMapViewController.view addSubview:self.boundingBoxGuideView]; @@ -91,9 +134,13 @@ - (void) setupTileBoundingBoxGuide:(UIView *) boudingBoxGuideView { } completion:nil]; [self.mcMapViewController toggleMapControls]; + [self.mcMapViewController addUserTilesWithUrl:tileUrl]; } +/** + Clear the tile drawing bounding box and bring back the drawer and map controls. + */ - (void) removeTileBoundingBoxGuide { if (self.boundingBoxGuideView != nil) { @@ -113,6 +160,9 @@ - (CLLocationCoordinate2D) convertPointToCoordinate:(CGPoint) point { #pragma mark - MCMapActionDelegate +/** + When the info button on the map is pressed show the info/settings drawer. + */ - (void)showMapInfoDrawer { MCSettingsCoordinator *settingsCoordinator = [[MCSettingsCoordinator alloc] init]; [self.childCoordinators addObject:settingsCoordinator]; @@ -121,6 +171,256 @@ - (void)showMapInfoDrawer { [settingsCoordinator start]; } + +/** + Update the status label on the drawing tools view. This will show the number of points that will be added. + */ +- (void)updateDrawingStatus { + [_drawingStatusViewController updateStatusLabelWithString:[NSString stringWithFormat:@"%d new points", (int)self.mcMapViewController.tempMapPoints.count]]; +} + + +/** + A map point was pressed, Query the GeoPackage's feature table for that row and show the details view. By default there are two columns, id and geom. If threre are additional columns they will be shown in this view. + If the drawer was already displaying data from another point, pass the data to the drawer and it will reload and update. + */ +- (void)showDetailsForAnnotation:(GPKGMapPoint *)mapPoint { + if (mapPoint.data == nil) { // this is a new point + // When you have selected a geopackage and a layer from the main list, when you longpress on the map we assume + // that is where you would like to save the new point. If you have not selected anything, then you will be + // presented with the existing geopackages and layers, or offered the ability to create a new one. + + self.mapPoint = mapPoint; + NSString *selectedGeoPackage = _repository.selectedGeoPackageName; + NSString *selectedLayer = _repository.selectedLayerName; + + // No GeoPackage or layer selected + if (selectedGeoPackage == nil || [selectedGeoPackage isEqualToString:@""] || selectedLayer == nil || [selectedLayer isEqualToString:@""]) { + _drawingStatusViewController = [[MCDrawingStatusViewController alloc] initAsFullView:YES]; + _drawingStatusViewController.drawerViewDelegate = _drawerViewDelegate; + _drawingStatusViewController.drawingStatusDelegate = self; + + if (selectedGeoPackage == nil || [selectedGeoPackage isEqualToString:@""]) { // show the geopackage selection view + _drawingStatusViewController.databases = [_repository databaseList]; + [_drawingStatusViewController pushOntoStack]; + [_drawingStatusViewController showGeoPackageSelectMode]; + } else if (selectedLayer == nil || [selectedLayer isEqualToString:@""]) { //show the layer selection view + _drawingStatusViewController.selectedGeoPackage = [_repository databaseNamed:_repository.selectedGeoPackageName]; + [_drawingStatusViewController pushOntoStack]; + [_drawingStatusViewController showLayerSelectionMode]; + } + + } else { // Use the selected GeoPackage and layer to set the point data view + GPKGFeatureRow *newRow = [_repository newRowInTable:selectedLayer database:selectedGeoPackage mapPoint:mapPoint]; + + if (_mapPointDataViewController == nil) { + _mapPointDataViewController = [[MCMapPointDataViewController alloc] initWithMapPoint:mapPoint row:newRow databaseName:selectedGeoPackage layerName:selectedLayer mode:MCPointViewModeEdit asFullView:YES drawerDelegate:_drawerViewDelegate pointDataDelegate:self]; + + [_mapPointDataViewController pushOntoStack]; + } else { + _mapPointDataViewController.databaseName = selectedGeoPackage; + _mapPointDataViewController.layerName = selectedLayer; + _mapPointDataViewController.mapPointDataDelegate = self; + [_mapPointDataViewController reloadWith:newRow mapPoint:mapPoint mode:MCPointViewModeEdit]; + } + } + } else { // this is an existing point, query it's data and show it + GPKGSMapPointData *pointData = (GPKGSMapPointData *)mapPoint.data; + [_repository setSelectedGeoPackageName: pointData.database]; + [_repository setSelectedLayerName:pointData.tableName]; + GPKGUserRow *userRow = [_repository queryRow:pointData.featureId fromTableNamed:pointData.tableName inDatabase:pointData.database]; + + if (_mapPointDataViewController == nil) { + _mapPointDataViewController = [[MCMapPointDataViewController alloc] initWithMapPoint:mapPoint row:userRow databaseName:_repository.selectedGeoPackageName layerName:_repository.selectedLayerName mode:MCPointViewModeDisplay asFullView:YES drawerDelegate:_drawerViewDelegate pointDataDelegate:self]; + [_drawerViewDelegate pushDrawer:_mapPointDataViewController]; + } else { + [_mapPointDataViewController reloadWith:userRow mapPoint:mapPoint mode:MCPointViewModeDisplay]; + } + } +} + + +- (void)showDrawingStatusViewController { + +} + + +#pragma mark - MCDrawingStatusDelegate methods +/** + The user has long pressed and added one or more points to the map, and gone through the drawing status wizard that lets them choose where to save the points, ask the repository to save the points to the selected GeoPackage and table. + */ +- (BOOL)savePointsToDatabase:(MCDatabase *)database andTable:(MCTable *) table { + if (self.mcMapViewController.tempMapPoints && self.mcMapViewController.tempMapPoints.count > 0) { + if ([_repository savePoints:self.mcMapViewController.tempMapPoints toDatabase:database table:table]) { + [_mcMapViewController setDrawing:NO]; + [_mcMapViewController clearTempPoints]; + [self updateMapLayers]; + [[NSNotificationCenter defaultCenter] postNotificationName:MC_GEOPACKAGE_MODIFIED_NOTIFICATION object:self]; + return YES; + } + } + + return NO; +} + + +/** + Show the view that allows the user to create a new GeoPackage. This can happen from the map when the user has long pressed to create new points, and would like to save them to a new geopackage. + */ +- (void)showNewGeoPacakgeView { + MCCreateGeoPacakgeViewController *createGeoPackageView = [[MCCreateGeoPacakgeViewController alloc] initAsFullView:YES]; + createGeoPackageView.drawerViewDelegate = self.drawerViewDelegate; + createGeoPackageView.createGeoPackageDelegate = self; + [createGeoPackageView.drawerViewDelegate pushDrawer:createGeoPackageView]; +} + + +/** + Show the new layer view. This can happen when the user is going to save new points and would like to save them to a new layer. + */ +- (void)showNewLayerViewWithDatabase:(MCDatabase *)database { + _featureLayerDetailsView = [[MCFeatureLayerDetailsViewController alloc] initAsFullView:YES]; + _featureLayerDetailsView.delegate = self; + _featureLayerDetailsView.drawerViewDelegate = _drawerViewDelegate; + _featureLayerDetailsView.database = database; + [_drawerViewDelegate pushDrawer:_featureLayerDetailsView]; + +} + + +/** + Cancel adding new points. Clean up the map and remove the drawing status view. + */ +- (void)cancelDrawingFeatures { + [_mcMapViewController setDrawing:NO]; + [_mcMapViewController clearTempPoints]; + [_repository setSelectedLayerName:@""]; + [_repository setSelectedGeoPackageName:@""]; + [[NSNotificationCenter defaultCenter] postNotificationName:MC_GEOPACKAGE_MODIFIED_NOTIFICATION object:self]; +} + + +- (void)didSelectGeoPackage:(NSString *)geopackageName { + [_repository setSelectedGeoPackageName:geopackageName]; +} + + +- (void)didSelectLayer:(NSString *)layerName { + [_repository setSelectedLayerName:layerName]; + // query and show the point data view + + [_drawingStatusViewController.drawerViewDelegate popDrawer]; + + if (self.mapPoint != nil) { + GPKGFeatureRow *newRow = [_repository newRowInTable:_repository.selectedLayerName database:_repository.selectedGeoPackageName mapPoint:self.mapPoint]; + _mapPointDataViewController = [[MCMapPointDataViewController alloc] initWithMapPoint:self.mapPoint row:newRow databaseName:_repository.selectedGeoPackageName layerName:_repository.selectedLayerName mode:MCPointViewModeEdit asFullView:YES drawerDelegate:_drawerViewDelegate pointDataDelegate:self]; + + [_mapPointDataViewController pushOntoStack]; + } +} + + +#pragma mark - MCMapPointDataDelegate +/** + Save the data from a map point, which is a row in a geopackage feature table. + */ +- (BOOL)saveRow:(GPKGUserRow *)row{ + if([_repository saveRow:row]) { + [_mcMapViewController setDrawing:NO]; + [_mcMapViewController clearTempPoints]; + [self updateMapLayers]; + [[NSNotificationCenter defaultCenter] postNotificationName:MC_GEOPACKAGE_MODIFIED_NOTIFICATION object:self]; + return YES; + } + + return NO; +} + + +/** + Delete the row (map point) from the GeoPackage's feature table. + */ +- (int)deleteRow:(GPKGUserRow *)row fromDatabase:(NSString *)database andRemoveMapPoint:(nonnull GPKGMapPoint *)mapPoint { + int rowsRemoved = [_repository deleteRow:row fromDatabase:database]; + + if (rowsRemoved == 1) { + [self.mcMapViewController removeMapPoint:mapPoint]; + [_mapPointDataViewController.drawerViewDelegate popDrawer]; + _mapPointDataViewController = nil; + } + + return rowsRemoved; +} + + +/** + The user has closed the map point details. Setting the drawer to nil cleans it up so a new drawer can be used next time a point is tapped. + */ +- (void)mapPointDataViewClosedWithNewPoint:(BOOL)didCloseWithNewPoint { + [self.mcMapViewController.mapView deselectAnnotation:_mapPointDataViewController.mapPoint animated:YES]; + + if (didCloseWithNewPoint) { + [_mcMapViewController setDrawing:NO]; + [_mcMapViewController clearTempPoints]; + [_repository setSelectedLayerName:@""]; + [_repository setSelectedGeoPackageName:@""]; + } + + _mapPointDataViewController = nil; +} + + +#pragma mark - MCFeatureLayerCreationDelegate methods +/** + Add a new feature layer to the GeoPackage. + */ +- (void) createFeatueLayerIn:(NSString *)database withGeomertyColumns:(GPKGGeometryColumns *)geometryColumns andBoundingBox:(GPKGBoundingBox *)boundingBox andSrsId:(NSNumber *) srsId { + NSLog(@"creating layer %@ in database %@ ", geometryColumns.tableName, database); + + BOOL didCreateLayer = [_repository createFeatueLayerIn:database withGeomertyColumns:geometryColumns boundingBox:boundingBox srsId:srsId]; + if (didCreateLayer) { + [_drawerViewDelegate popDrawer]; + [_repository regenerateDatabaseList]; + _drawingStatusViewController.selectedGeoPackage = [_repository databaseNamed:database]; + [_drawingStatusViewController showLayerSelectionMode]; + } else { + //TODO handle the case where a new feature layer could not be created + } +} + + +#pragma mark - MCCreateGeoPackageDelegate methods +/** + When the user is creating a new GeoPackage check to make sure the name is not already in use or invalid. + */ +- (BOOL) isValidGeoPackageName:(NSString *) name { + NSArray *databaseNames = [self.manager databases]; + + if ([name isEqualToString: @""]) { + return NO; + } + + for (NSString * databaseName in databaseNames) { + if ([name isEqualToString:databaseName]) { + return NO; + } + } + + return YES; +} + + +/** + Create a new GeoPackage. + */ +- (void) createGeoPackage:(NSString *) geoPackageName { + NSLog(@"Creating GeoPackage %@", geoPackageName); + [_repository createGeoPackage:geoPackageName]; + [_repository regenerateDatabaseList]; + [_drawingStatusViewController refreshViewWithNewGeoPackageList:[_repository databaseList]]; +} + + -(CLLocationCoordinate2D *) getPolygonPointsWithPoint1: (CLLocationCoordinate2D) point1 andPoint2: (CLLocationCoordinate2D) point2{ CLLocationCoordinate2D *coordinates = calloc(4, sizeof(CLLocationCoordinate2D)); coordinates[0] = CLLocationCoordinate2DMake(point1.latitude, point1.longitude); @@ -130,4 +430,5 @@ -(CLLocationCoordinate2D *) getPolygonPointsWithPoint1: (CLLocationCoordinate2D) return coordinates; } + @end diff --git a/mapcache-ios/map/MCMapPointDataViewController.h b/mapcache-ios/map/MCMapPointDataViewController.h new file mode 100644 index 0000000..c72cdb5 --- /dev/null +++ b/mapcache-ios/map/MCMapPointDataViewController.h @@ -0,0 +1,52 @@ +// +// MCMapPointDataViewController.h +// mapcache-ios +// +// Created by Tyler Burgett on 4/16/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import "NGADrawerViewController.h" +#import "MCFieldWithTitleCell.h" +#import "MCButtonCell.h" +#import "MCTitleCell.h" +#import "MCDescriptionCell.h" +#import "MCDualButtonCell.h" +#import "MCTextViewCell.h" +#import "MCLayerCell.h" +#import "MCEmptyStateCell.h" +#import "MCKeyValueDisplayCell.h" +#import "GPKGMapUtils.h" +#import "GPKGUserRow.h" +#import "GPKGFeatureRow.h" +#import "MCSwitchCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, MCMapPointViewMode) { + MCPointViewModeNew, + MCPointViewModeEdit, + MCPointViewModeDisplay +}; + +@protocol MCMapPointDataDelegate +- (BOOL)saveRow:(GPKGUserRow *)row; +- (int)deleteRow:(GPKGUserRow *)row fromDatabase:(NSString *)database andRemoveMapPoint:(GPKGMapPoint *)mapPoint; +- (void)mapPointDataViewClosedWithNewPoint:(BOOL)didCloseWithNewPoint; +@end + +@interface MCMapPointDataViewController : NGADrawerViewController +@property (nonatomic, strong) idmapPointDataDelegate; +@property (nonatomic, strong) GPKGMapPoint *mapPoint; +@property (nonatomic, strong) GPKGUserRow *row; +@property (nonatomic, strong) NSString *databaseName; +@property (nonatomic, strong) NSString *layerName; +@property (nonatomic) MCMapPointViewMode mode; +- (void)showEditMode; +- (void)showDisplayMode; +- (void)reloadWith:(GPKGUserRow *)row mapPoint:(GPKGMapPoint *)mapPoint mode:(MCMapPointViewMode)mode; +- (instancetype) initWithMapPoint:(GPKGMapPoint *)mapPoint row:(GPKGUserRow *)row databaseName:(NSString *)databaseName layerName:(NSString *)layerName mode:(MCMapPointViewMode)mode asFullView:(BOOL)fullView drawerDelegate:(id) drawerDelegate pointDataDelegate:(id) pointDataDelegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/mapcache-ios/map/MCMapPointDataViewController.m b/mapcache-ios/map/MCMapPointDataViewController.m new file mode 100644 index 0000000..54332ab --- /dev/null +++ b/mapcache-ios/map/MCMapPointDataViewController.m @@ -0,0 +1,419 @@ + // +// MCMapPointDataViewController.m +// mapcache-ios +// +// Created by Tyler Burgett on 4/16/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import "MCMapPointDataViewController.h" + + +@interface MCMapPointDataViewController () +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) NSMutableArray *cellArray; +@property (nonatomic, strong) MCFieldWithTitleCell *titleCell; +@property (nonatomic, strong) MCTextViewCell *descriptionCell; +@property (nonatomic, strong) MCDualButtonCell *buttonsCell; +@property (nonatomic) BOOL haveScrolled; +@end + +@implementation MCMapPointDataViewController + +- (instancetype) initWithMapPoint:(GPKGMapPoint *)mapPoint row:(GPKGUserRow *)row databaseName:(NSString *)databaseName layerName:(NSString *)layerName mode:(MCMapPointViewMode)mode asFullView:(BOOL)fullView drawerDelegate:(id) drawerDelegate pointDataDelegate:(id) pointDataDelegate { + self = [super initAsFullView:fullView]; + self.mapPoint = mapPoint; + self.databaseName = databaseName; + self.layerName = layerName; + self.drawerViewDelegate = drawerDelegate; + self.mapPointDataDelegate = pointDataDelegate; + self.mode = mode; + self.row = row; + return self; +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + self.tableView = [[UITableView alloc] init]; + CGRect bounds = self.view.bounds; + CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y + 32, bounds.size.width, bounds.size.height - 20); + self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; + self.tableView.delegate = self; + self.tableView.dataSource = self; + self.tableView.estimatedRowHeight = 390.0; + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.tableView.allowsMultipleSelectionDuringEditing = NO; + UIEdgeInsets tabBarInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0); + self.tableView.contentInset = tabBarInsets; + self.tableView.scrollIndicatorInsets = tabBarInsets; + [self.view addSubview:self.tableView]; + [self registerCellTypes]; + self.edgesForExtendedLayout = UIRectEdgeNone; + self.extendedLayoutIncludesOpaqueBars = NO; + + [self addDragHandle]; + [self addCloseButton]; + self.haveScrolled = NO; +} + + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + if (self.mode == MCPointViewModeEdit) { + [self showEditMode]; + } else { + [self showDisplayMode]; + } +} + + +- (void) registerCellTypes { + [self.tableView registerNib:[UINib nibWithNibName:@"MCFieldWithTitleCell" bundle:nil] forCellReuseIdentifier:@"fieldWithTitle"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCTextViewCell" bundle:nil] forCellReuseIdentifier:@"textView"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCDualButtonCell" bundle:nil] forCellReuseIdentifier:@"buttons"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCButtonCell" bundle:nil] forCellReuseIdentifier:@"button"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCTitleCell" bundle:nil] forCellReuseIdentifier:@"titleDisplay"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCDescriptionCell" bundle:nil] forCellReuseIdentifier:@"descriptionDisplay"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCKeyValueDisplayCell" bundle:nil] forCellReuseIdentifier:@"keyValue"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCSwitchCell" bundle:nil] forCellReuseIdentifier:@"switchCell"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCLayerCell" bundle:nil] forCellReuseIdentifier:@"layerCell"]; + [self.tableView registerNib:[UINib nibWithNibName:@"MCEmptyStateCell" bundle:nil] forCellReuseIdentifier:@"spacer"]; +} + + +/** + Show the key-value pairs for the feature row. Currently only displaying text and numbers. + */ +- (void)showDisplayMode { + _cellArray = [[NSMutableArray alloc] init]; + + MCLayerCell *details = [self.tableView dequeueReusableCellWithIdentifier:@"layerCell"]; + [details setName:self.databaseName]; + [details setDetails:self.layerName]; + [details activeIndicatorOff]; + [details.layerTypeImage setImage:[UIImage imageNamed:@"Point"]]; + [_cellArray addObject:details]; + + if (_row.columnCount == 2) { // no user editable columns + MCDescriptionCell *empty = [self.tableView dequeueReusableCellWithIdentifier:@"descriptionDisplay"]; + [empty setDescription:@"This layer has no fields."]; + [_cellArray addObject:empty]; + } + + for (int i = 0; i < _row.columnCount; i++) { + NSString *columnName = _row.columnNames[i]; + enum GPKGDataType dataType = _row.columns.columns[i].dataType; + NSString *idColumnName = [_row idColumnName]; // the Primary Key column name + NSString *geometryColumnName = [(GPKGFeatureRow*)_row geometryColumnName]; + + if (![columnName isEqualToString:idColumnName] && ![columnName isEqualToString:geometryColumnName]) { + MCKeyValueDisplayCell *displayCell = [self.tableView dequeueReusableCellWithIdentifier:@"keyValue"]; + + if (_row.columns.columns[i].dataType == GPKG_DT_TEXT) { + if (!_row.values[i] || [_row.values[i] isKindOfClass:NSNull.class] || [_row.values[i] isEqualToString:@""]) { + [displayCell setValueLabelText:@"none"]; + } else { + [displayCell setValueLabelText: _row.values[i]]; + } + } else if (dataType == GPKG_DT_INTEGER || dataType == GPKG_DT_REAL || dataType == GPKG_DT_DOUBLE || dataType == GPKG_DT_INT || dataType == GPKG_DT_FLOAT || dataType == GPKG_DT_SMALLINT || dataType == GPKG_DT_TINYINT || dataType == GPKG_DT_MEDIUMINT) { + if ([_row.values[i] respondsToSelector:@selector(stringValue)]) { + [displayCell setValueLabelText:[_row.values[i] stringValue]]; + } else if ([_row.values[i] isKindOfClass:NSString.class]) { + [displayCell setValueLabelText: _row.values[i]]; + } + } else if (dataType == GPKG_DT_BLOB) { + [displayCell setValueLabelText: @"Binary data, unable to display"]; + } else if (dataType == GPKG_DT_BOOLEAN) { + if ([_row.values[i] isKindOfClass:NSNull.class] || _row.values[i] == nil || [_row.values[i] boolValue] == NO) { + [displayCell setValueLabelText:@"false"]; + } else { + [displayCell setValueLabelText:@"true"]; + } + + + } else if ([_row.values[i] isKindOfClass:NSNull.class] || _row.values[i] == nil) { + [displayCell setValueLabelText:@""]; + } + + [displayCell setKeyLabelText:columnName]; + [_cellArray addObject:displayCell]; + } + } + + if (_row.columnCount == 2) { + + } + + MCButtonCell *buttonCell = [self.tableView dequeueReusableCellWithIdentifier:@"button"]; + [buttonCell usePrimaryColors]; + buttonCell.delegate = self; + [buttonCell setAction:@"edit"]; + [buttonCell setButtonLabel:@"Edit"]; + [_cellArray addObject:buttonCell]; + + MCButtonCell *deleteButtonCell = [self.tableView dequeueReusableCellWithIdentifier:@"button"]; + [deleteButtonCell useSecondaryRed]; + deleteButtonCell.delegate = self; + [deleteButtonCell setAction:@"delete"]; + [deleteButtonCell setButtonLabel:@"Delete"]; + [_cellArray addObject:deleteButtonCell]; + + [_tableView reloadData]; + [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; + self.mode = MCPointViewModeDisplay; + // TODO add empty state +} + + +/** + Take the contents of the queried feature row and show the appropriate edit control and keyboard type based on the datatype of the database column. + */ +- (void)showEditMode { + _cellArray = [[NSMutableArray alloc] init]; + + MCLayerCell *details = [self.tableView dequeueReusableCellWithIdentifier:@"layerCell"]; + [details setName:self.databaseName]; + [details setDetails:self.layerName]; + [details activeIndicatorOff]; + [details.layerTypeImage setImage:[UIImage imageNamed:@"Point"]]; + [_cellArray addObject:details]; + + if (_row.columnCount == 2) { // no user editable columns + MCDescriptionCell *empty = [self.tableView dequeueReusableCellWithIdentifier:@"descriptionDisplay"]; + [empty setDescription:@"This layer has no fields."]; + [_cellArray addObject:empty]; + } + + if (_row) { + NSString *idColumnName = [_row idColumnName]; // the Primary Key column name + NSString *geometryColumnName = [(GPKGFeatureRow*)_row geometryColumnName]; + + for (int i = 0; i < _row.columnCount; i++) { + NSString *columnName = _row.columnNames[i]; + enum GPKGDataType dataType = _row.columns.columns[i].dataType; + + if (![columnName isEqualToString:idColumnName] && ![columnName isEqualToString:@"id"] && ![columnName isEqualToString:geometryColumnName]) { + MCFieldWithTitleCell *fieldWithTitle = [self.tableView dequeueReusableCellWithIdentifier:@"fieldWithTitle"]; + [fieldWithTitle setTitleText:columnName]; + fieldWithTitle.columnName = columnName; + fieldWithTitle.dataType = dataType; + [fieldWithTitle setTextFielDelegate:self]; + + if (_row.columns.columns[i].dataType == GPKG_DT_TEXT) { + if (![_row.values[i] isKindOfClass:NSNull.class]) { + [fieldWithTitle setFieldText:_row.values[i]]; + } + + [fieldWithTitle useReturnKeyDone]; + [_cellArray addObject:fieldWithTitle]; + } else if (dataType == GPKG_DT_INTEGER || dataType == GPKG_DT_REAL || dataType == GPKG_DT_DOUBLE || dataType == GPKG_DT_INT || dataType == GPKG_DT_FLOAT || dataType == GPKG_DT_SMALLINT || dataType == GPKG_DT_TINYINT || dataType == GPKG_DT_MEDIUMINT) { + if (![_row.values[i] isKindOfClass:NSNull.class] && _row.values[i] != nil) { + if ([_row.values[i] respondsToSelector:@selector(stringValue)]) { + [fieldWithTitle setFieldText:[_row.values[i] stringValue]]; + } + } + [fieldWithTitle setupNumericalKeyboard]; + [_cellArray addObject:fieldWithTitle]; + } else if (dataType == GPKG_DT_BOOLEAN) { + MCSwitchCell *switchCell = [self.tableView dequeueReusableCellWithIdentifier:@"switchCell"]; + [switchCell.label setText:columnName]; + switchCell.columnName = columnName; + switchCell.switchDelegate = self; + + if ([_row.values[i] isKindOfClass:NSNull.class] || _row.values[i] == nil || [_row.values[i] boolValue] == NO) { + [switchCell switchOff]; + } else { + [switchCell switchOn]; + } + + [_cellArray addObject:switchCell]; + } + } + } + } + _buttonsCell = [self.tableView dequeueReusableCellWithIdentifier:@"buttons"]; + [_buttonsCell setLeftButtonLabel:@"Cancel"]; + [_buttonsCell setLeftButtonAction:@"cancel"]; + [_buttonsCell setRightButtonLabel:@"Save"]; + [_buttonsCell setRightButtonAction:@"save"]; + _buttonsCell.dualButtonDelegate = self; + [_cellArray addObject:_buttonsCell]; + + MCEmptyStateCell *spacer = [self.tableView dequeueReusableCellWithIdentifier:@"spacer"]; + [spacer useAsSpacer]; + [_cellArray addObject:spacer]; + + [_tableView reloadData]; + [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; + self.mode = MCPointViewModeEdit; +} + + +- (void)reloadWith:(GPKGUserRow *)row mapPoint:(GPKGMapPoint *)mapPoint mode:(MCMapPointViewMode)mode { + self.row = row; + self.mapPoint = mapPoint; + + if (mode == MCPointViewModeDisplay) { + [self showDisplayMode]; + } else if (mode == MCPointViewModeEdit) { + [self showEditMode]; + } +} + + +#pragma mark - UITableViewDelegate methods +- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath { + return [self.cellArray objectAtIndex:indexPath.row]; +} + + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [self.tableView deselectRowAtIndexPath:indexPath animated:NO]; +} + + +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.cellArray count]; +} + + +#pragma mark- UITextFieldDelegate methods +- (void) textFieldDidBeginEditing:(UITextField *)textField { + UITableViewCell *cell = (UITableViewCell *)[textField superview]; + [_tableView scrollToRowAtIndexPath:[_tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES]; +} + + +- (void)textFieldDidEndEditing:(UITextField *)textField { + MCFieldWithTitleCell *fieldWithTitleCell = (MCFieldWithTitleCell *)[textField superview]; + [fieldWithTitleCell.field trimWhiteSpace]; + + BOOL inputIsValid = [fieldWithTitleCell.field fieldValueValidForType:fieldWithTitleCell.dataType]; + if (!inputIsValid) { + [fieldWithTitleCell useErrorAppearance]; + [_buttonsCell disableRightButton]; + } else { + [fieldWithTitleCell useNormalAppearance]; + [_buttonsCell enableRightButton]; + } + + [_row setValueWithColumnName:fieldWithTitleCell.columnName andValue: [fieldWithTitleCell fieldValue]]; +} + + +- (BOOL) textFieldShouldReturn:(UITextField *)textField { + [textField resignFirstResponder]; + return YES; +} + + +#pragma mark - MCDualButtonCellDelegate methods +- (void)performDualButtonAction:(NSString *)action { + if ([action isEqualToString:@"save"]) { + NSLog(@"Saving point data"); + + BOOL saved = [_mapPointDataDelegate saveRow:_row]; + + if (saved) { + [self showDisplayMode]; + } + + } else if ([action isEqualToString:@"edit"]) { + // TODO Add switch to edit mode + NSLog(@"Editing point"); + + if (self.mode != MCPointViewModeEdit) { + [self showEditMode]; + } else { + [self showDisplayMode]; + } + } else if ([action isEqualToString:@"cancel"]) { + NSLog(@"Canceling point edit"); + + if (self.mapPoint.data == nil) { // the point is new, close out the view + [self.drawerViewDelegate popDrawer]; + [self.mapPointDataDelegate mapPointDataViewClosedWithNewPoint:YES]; + } else { + [self showDisplayMode]; + } + } +} + + +- (void)performButtonAction:(NSString *)action { + if ([action isEqualToString:@"edit"]) { + // TODO Add switch to edit mode + NSLog(@"Editing point"); + + if (self.mode != MCPointViewModeEdit) { + [self showEditMode]; + } else { + [self showDisplayMode]; + } + } else if ([action isEqualToString:@"delete"]) { + UIAlertController *deleteAlert = [UIAlertController alertControllerWithTitle:@"Delete" message:@"Do you want to delete this point? This action can not be undone." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *confirmDelete = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + NSString *databaseName = [self.mapPoint.data valueForKey:@"database"]; + [self.mapPointDataDelegate deleteRow:self.row fromDatabase:databaseName andRemoveMapPoint:self.mapPoint]; + }]; + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [deleteAlert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [deleteAlert addAction:confirmDelete]; + [deleteAlert addAction:cancel]; + + [self presentViewController:deleteAlert animated:YES completion:nil]; + } +} + + +#pragma mark - MCSwitchCellDelegate methods +- (void) switchChanged:(id) sender { + UISwitch *switchControl = (UISwitch*)sender; + + MCSwitchCell *switchCell = (MCSwitchCell *)[sender superview]; + NSNumber *isOn = [switchControl isOn] ? [NSNumber numberWithInt:1] : [NSNumber numberWithInt:0]; + [self.row setValueWithColumnName:switchCell.columnName andValue:isOn]; +} + + +#pragma mark - NGADrawerView methods +- (void) closeDrawer { + BOOL haveNewPoint = _mapPoint.data == nil; + [self.drawerViewDelegate popDrawer]; + [self.mapPointDataDelegate mapPointDataViewClosedWithNewPoint:haveNewPoint]; +} + + +// Override this method to make the drawer and the scrollview play nice +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.haveScrolled) { + [self rollUpPanGesture:scrollView.panGestureRecognizer withScrollView:scrollView]; + } +} + + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + self.haveScrolled = YES; + + if (!self.isFullView) { + scrollView.scrollEnabled = NO; + scrollView.scrollEnabled = YES; + } else { + scrollView.scrollEnabled = YES; + } +} + + +@end diff --git a/mapcache-ios/map/MCMapViewController.h b/mapcache-ios/map/MCMapViewController.h index dc38fa4..c2891d9 100644 --- a/mapcache-ios/map/MCMapViewController.h +++ b/mapcache-ios/map/MCMapViewController.h @@ -9,11 +9,11 @@ #import #import #import "NGADrawerCoordinator.h" -#import "GPKGSDatabases.h" -#import "GPKGSDatabase.h" +#import "MCDatabases.h" +#import "MCDatabase.h" #import "GPKGGeoPackageManager.h" #import "GPKGGeoPackageFactory.h" -#import "GPKGSUtils.h" +#import "MCUtils.h" #import "GPKGUtils.h" #import "GPKGMapUtils.h" #import "GPKGTileBoundingBoxUtils.h" @@ -30,6 +30,8 @@ @protocol MCMapActionDelegate - (void)showMapInfoDrawer; +- (void)updateDrawingStatus; +- (void)showDetailsForAnnotation:(GPKGMapPoint *)mapPoint; @end @@ -40,9 +42,18 @@ @property (weak, nonatomic) IBOutlet UIButton *zoomIndicatorButton; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *zoomIndicatorButtonWidth; @property (nonatomic, strong) id mapActionDelegate; +@property (nonatomic) BOOL drawing; +@property (nonatomic, strong) NSMutableArray *tempMapPoints; +@property (nonatomic, strong) MCDatabases *active; - (int)updateInBackgroundWithZoom: (BOOL) zoom; +- (int)updateInBackgroundWithZoom: (BOOL) zoom andFilter: (BOOL) filter; - (void)zoomToPointWithOffset:(CLLocationCoordinate2D) point; +- (void)zoomToPointWithOffset:(CLLocationCoordinate2D) point zoomLevel:(NSUInteger)zoomLevel; - (CLLocationCoordinate2D) convertPointToCoordinate:(CGPoint) point; -- (void) toggleMapControls; +- (void)toggleMapControls; +- (void)clearTempPoints; +- (void)removeMapPoint:(GPKGMapPoint *) mapPoint; +- (void)addUserTilesWithUrl:(NSString *) tileTemplateURL; +- (void)removeUserTiles; @end diff --git a/mapcache-ios/map/MCMapViewController.m b/mapcache-ios/map/MCMapViewController.m index 920a0c0..a37ef15 100644 --- a/mapcache-ios/map/MCMapViewController.m +++ b/mapcache-ios/map/MCMapViewController.m @@ -10,7 +10,6 @@ @interface MCMapViewController () @property (nonatomic, strong) NSMutableArray *childCoordinators; -@property (nonatomic, strong) GPKGSDatabases *active; @property (nonatomic, strong) NSUserDefaults *settings; @property (nonatomic, strong) GPKGGeoPackageManager *manager; @property (nonatomic, strong) NSMutableDictionary *geoPackages; @@ -22,6 +21,7 @@ @interface MCMapViewController () @property (nonatomic, strong) CLLocationManager *locationManager; @property (nonatomic) BOOL showingUserLocation; @property (nonatomic) BOOL featureOverlayTiles; +@property (nonatomic) BOOL ignoreRegionChange; @property (atomic) int updateCountId; @property (atomic) int featureUpdateCountId; @property (nonatomic, strong) GPKGFeatureShapes *featureShapes; @@ -46,7 +46,6 @@ @interface MCMapViewController () @property (nonatomic, strong) UIColor *drawPolygonFillColor; @property (nonatomic, strong) NSNumberFormatter *locationDecimalFormatter; @property (nonatomic) BOOL boundingBoxMode; -@property (nonatomic) BOOL drawing; @property (nonatomic, strong) GPKGPolygon *boundingBox; @property (nonatomic) CLLocationCoordinate2D boundingBoxStartCorner; @property (nonatomic) CLLocationCoordinate2D boundingBoxEndCorner; @@ -56,7 +55,9 @@ @interface MCMapViewController () @property (nonatomic) double maxLon; @property (nonatomic) BOOL settingsDrawerVisible; @property (nonatomic) int currentZoom; +@property (nonatomic) CLLocationCoordinate2D currentCenter; @property (nonatomic) BOOL expandedZoomDetails; +@property (nonatomic, strong) MKTileOverlay *userTileOverlay; @end @@ -78,8 +79,8 @@ - (void)viewDidLoad { self.geoPackages = [[NSMutableDictionary alloc] init]; self.featureShapes = [[GPKGFeatureShapes alloc] init]; self.featureDaos = [[NSMutableDictionary alloc] init]; - self.manager = [GPKGGeoPackageFactory getManager]; - self.active = [GPKGSDatabases getInstance]; + self.manager = [GPKGGeoPackageFactory manager]; + self.active = [MCDatabases getInstance]; self.needsInitialZoom = true; self.updateCountId = 0; self.featureUpdateCountId = 0; @@ -94,7 +95,9 @@ - (void)viewDidLoad { self.locationManager.delegate = self; self.showingUserLocation = NO; self.settingsDrawerVisible = NO; + self.ignoreRegionChange = YES; self.currentZoom = -1; + self.currentCenter = self.mapView.centerCoordinate; self.infoButton.layer.shadowColor = [UIColor blackColor].CGColor; self.infoButton.layer.shadowOpacity = 0.3; @@ -124,11 +127,12 @@ - (void)viewDidLoad { self.boundingBoxMode = NO; [_mapView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget: self action:@selector(longPressGesture:)]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enableBoundingBoxMode) name:@"drawBoundingBox" object:nil]; + self.tempMapPoints = [[NSMutableArray alloc] init]; NSString *mapType = [self.settings stringForKey:GPKGS_PROP_MAP_TYPE]; - if (mapType == nil || [mapType isEqualToString:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD]]) { + if (mapType == nil || [mapType isEqualToString:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD]]) { [self.mapView setMapType:MKMapTypeStandard]; - } else if ([mapType isEqualToString:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE]]) { + } else if ([mapType isEqualToString:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE]]) { [self.mapView setMapType:MKMapTypeSatellite]; } else { [self.mapView setMapType:MKMapTypeHybrid]; @@ -141,7 +145,7 @@ - (void) viewWillAppear:(BOOL)animated { if (self.active.modified) { [self.active setModified:NO]; - [self updateInBackgroundWithZoom:YES]; + [self updateInBackgroundWithZoom:NO]; } // iOS 13 dark mode support @@ -175,6 +179,27 @@ - (void) zoomToPointWithOffset:(CLLocationCoordinate2D) point { } +- (void) zoomToPointWithOffset:(CLLocationCoordinate2D) point zoomLevel:(NSUInteger)zoomLevel { + //point.latitude -= self.mapView.region.span.latitudeDelta * (1.0/3.0); + MKCoordinateSpan span = MKCoordinateSpanMake(0, 360/pow(2, zoomLevel)*self.mapView.frame.size.width/256); + [self.mapView setRegion:MKCoordinateRegionMake(point, span) animated:YES]; +} + + +- (void)clearTempPoints { + for (GPKGMapPoint *point in self.tempMapPoints) { + [self.mapView removeAnnotation:point]; + } + + [self.tempMapPoints removeAllObjects]; +} + + +- (void) removeMapPoint:(GPKGMapPoint *) mapPoint { + [self.mapView removeAnnotation:mapPoint]; +} + + #pragma mark - Button actions - (IBAction)showInfo:(id)sender { @@ -265,10 +290,10 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray - (void)setMapType:(NSString *)mapType { NSLog(@"In MCMapViewController handing setting map change"); - if ([mapType isEqualToString:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD]]) { + if ([mapType isEqualToString:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD]]) { [self.mapView setMapType:MKMapTypeStandard]; [self.settings setObject:mapType forKey:GPKGS_PROP_MAP_TYPE]; - } else if ([mapType isEqualToString:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE]]) { + } else if ([mapType isEqualToString:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE]]) { [self.mapView setMapType:MKMapTypeSatellite]; [self.settings setObject:mapType forKey:GPKGS_PROP_MAP_TYPE]; } else { @@ -317,7 +342,7 @@ - (void) toggleMapControls { } #pragma mark - MCTileHelperDelegate methods -- (void)addTileOverlayToMapView:(MKTileOverlay *)tileOverlay { +- (void)addTileOverlayToMapView:(MKTileOverlay *)tileOverlay withTable:(MCTileTable *)table { dispatch_sync(dispatch_get_main_queue(), ^{ [self.mapView addOverlay:tileOverlay]; }); @@ -409,7 +434,6 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id= zoomAlreadyVisiblePercentage && latitudeRatio >= zoomAlreadyVisiblePercentage){ @@ -635,7 +681,7 @@ -(void) zoomToActiveIfNothingVisible: (BOOL) nothingVisible andIgnoreRegionChang double expandedHeight = size.height + (2 * (size.height * paddingPercentage)); double expandedWidth = size.width + (2 * (size.width * paddingPercentage)); - CLLocationCoordinate2D center = [bbox getCenter]; + CLLocationCoordinate2D center = [bbox center]; MKCoordinateRegion expandedRegion = MKCoordinateRegionMakeWithDistance(center, expandedHeight, expandedWidth); double latitudeRange = expandedRegion.span.latitudeDelta / 2.0; @@ -644,9 +690,9 @@ -(void) zoomToActiveIfNothingVisible: (BOOL) nothingVisible andIgnoreRegionChang expandedRegion = MKCoordinateRegionMake(self.mapView.centerCoordinate, MKCoordinateSpanMake(180, 360)); } -// if(ignoreChange){ -// self.ignoreRegionChange = true; -// } + if(ignoreChange){ + self.ignoreRegionChange = YES; + } [self.mapView setRegion:expandedRegion animated:true]; } } @@ -654,88 +700,93 @@ -(void) zoomToActiveIfNothingVisible: (BOOL) nothingVisible andIgnoreRegionChang -(void) zoomToActiveBounds{ - self.featuresBoundingBox = nil; self.tilesBoundingBox = nil; // Pre zoom NSMutableArray *activeDatabase = [[NSMutableArray alloc] init]; [activeDatabase addObjectsFromArray:[self.active getDatabases]]; - for(GPKGSDatabase *database in activeDatabase){ - GPKGGeoPackage *geoPackage = [self.manager open:database.name]; - if (geoPackage != nil) { - - NSMutableSet *featureTableDaos = [[NSMutableSet alloc] init]; - NSArray *features = [database getFeatures]; - if(features.count > 0){ - for(GPKGSTable *featureTable in features){ - [featureTableDaos addObject:featureTable.name]; - } - } - - for(GPKGSFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ - if(featureOverlay.active){ - [featureTableDaos addObject:featureOverlay.featureTable]; + for(MCDatabase *database in activeDatabase){ + GPKGGeoPackage *geoPackage; + + @try { + geoPackage = [self.manager open:database.name]; + if (geoPackage != nil) { + NSMutableSet *featureTableDaos = [[NSMutableSet alloc] init]; + NSArray *features = [database getFeatures]; + + if(features.count > 0){ + for(MCTable *featureTable in features){ + [featureTableDaos addObject:featureTable.name]; + } } - } - - if(featureTableDaos.count > 0){ - GPKGContentsDao *contentsDao = [geoPackage getContentsDao]; + for(MCFeatureOverlayTable * featureOverlay in [database getFeatureOverlays]){ + if(featureOverlay.active){ + [featureTableDaos addObject:featureOverlay.featureTable]; + } + } - for (NSString *featureTable in featureTableDaos) { + if(featureTableDaos.count > 0){ + GPKGContentsDao *contentsDao = [geoPackage contentsDao]; - @try { - GPKGContents *contents = (GPKGContents *)[contentsDao queryForIdObject:featureTable]; - GPKGBoundingBox *contentsBoundingBox = [contents getBoundingBox]; - - if (contentsBoundingBox != nil) { - - contentsBoundingBox = [self.tileHelper transformBoundingBoxToWgs84: contentsBoundingBox withSrs: [contentsDao getSrs:contents]]; + for (NSString *featureTable in featureTableDaos) { + @try { + GPKGContents *contents = (GPKGContents *)[contentsDao queryForIdObject:featureTable]; + GPKGBoundingBox *contentsBoundingBox = [contents boundingBox]; - if (self.featuresBoundingBox != nil) { - self.featuresBoundingBox = [self.featuresBoundingBox union:contentsBoundingBox]; - } else { - self.featuresBoundingBox = contentsBoundingBox; + if (contentsBoundingBox != nil) { + contentsBoundingBox = [self.tileHelper transformBoundingBoxToWgs84: contentsBoundingBox withSrs: [contentsDao srs:contents]]; + + if (self.featuresBoundingBox != nil) { + self.featuresBoundingBox = [self.featuresBoundingBox union:contentsBoundingBox]; + } else { + self.featuresBoundingBox = contentsBoundingBox; + } } + } @catch (NSException *e) { + NSLog(@"%@", [e description]); + } @finally { + [geoPackage close]; } - } @catch (NSException *e) { - NSLog(@"%@", [e description]); - } @finally { - [geoPackage close]; } } - } - - NSArray *tileTables = [database getTiles]; - if(tileTables.count > 0){ - - GPKGTileMatrixSetDao *tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - for(GPKGSTileTable *tileTable in tileTables){ + NSArray *tileTables = [database getTiles]; + if(tileTables.count > 0){ - @try { - GPKGTileMatrixSet *tileMatrixSet = (GPKGTileMatrixSet *)[tileMatrixSetDao queryForIdObject:tileTable.name]; - GPKGBoundingBox *tileMatrixSetBoundingBox = [tileMatrixSet getBoundingBox]; - - tileMatrixSetBoundingBox = [self.tileHelper transformBoundingBoxToWgs84:tileMatrixSetBoundingBox withSrs:[tileMatrixSetDao getSrs:tileMatrixSet]]; + GPKGTileMatrixSetDao *tileMatrixSetDao = [geoPackage tileMatrixSetDao]; + + for(MCTileTable *tileTable in tileTables){ - if (self.tilesBoundingBox != nil) { - self.tilesBoundingBox = [self.tilesBoundingBox union:tileMatrixSetBoundingBox]; - } else { - self.tilesBoundingBox = tileMatrixSetBoundingBox; + @try { + GPKGTileMatrixSet *tileMatrixSet = (GPKGTileMatrixSet *)[tileMatrixSetDao queryForIdObject:tileTable.name]; + GPKGBoundingBox *tileMatrixSetBoundingBox = [tileMatrixSet boundingBox]; + + tileMatrixSetBoundingBox = [self.tileHelper transformBoundingBoxToWgs84:tileMatrixSetBoundingBox withSrs:[tileMatrixSetDao srs:tileMatrixSet]]; + + if (self.tilesBoundingBox != nil) { + self.tilesBoundingBox = [self.tilesBoundingBox union:tileMatrixSetBoundingBox]; + } else { + self.tilesBoundingBox = tileMatrixSetBoundingBox; + } + } @catch (NSException *e) { + NSLog(@"%@", [e description]); + } @finally { + [geoPackage close]; } - } @catch (NSException *e) { - NSLog(@"%@", [e description]); - } @finally { - [geoPackage close]; } } } - - [geoPackage close]; + } @catch (NSException *e) { + NSLog(@"Problem zooming to bounds %@", e.reason); + } @finally { + if (geoPackage != nil) { + [geoPackage close]; + } } } + [self zoomToActiveAndIgnoreRegionChange:YES]; } @@ -743,44 +794,67 @@ -(void) zoomToActiveBounds{ -(int) getMaxFeatures{ int maxFeatures = (int)[self.settings integerForKey:GPKGS_PROP_MAP_MAX_FEATURES]; if(maxFeatures == 0){ - maxFeatures = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES_DEFAULT] intValue]; + maxFeatures = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES_DEFAULT] intValue]; } return maxFeatures; } - (void) setupColors { - self.boundingBoxColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_COLOR]]; - self.boundingBoxLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_FILL]){ - self.boundingBoxFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_FILL_COLOR]]; + self.boundingBoxColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_COLOR]]; + self.boundingBoxLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_LINE_WIDTH] doubleValue]; + if([MCProperties getBoolOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_FILL]){ + self.boundingBoxFillColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_BOUNDING_BOX_DRAW_FILL_COLOR]]; } - self.defaultPolylineColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYLINE_COLOR]]; - self.defaultPolylineLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DEFAULT_POLYLINE_LINE_WIDTH] doubleValue]; + self.defaultPolylineColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYLINE_COLOR]]; + self.defaultPolylineLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_DEFAULT_POLYLINE_LINE_WIDTH] doubleValue]; - self.defaultPolygonColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYGON_COLOR]]; - self.defaultPolygonLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DEFAULT_POLYGON_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_DEFAULT_POLYGON_FILL]){ - self.defaultPolygonFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYGON_FILL_COLOR]]; + self.defaultPolygonColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYGON_COLOR]]; + self.defaultPolygonLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_DEFAULT_POLYGON_LINE_WIDTH] doubleValue]; + if([MCProperties getBoolOfProperty:GPKGS_PROP_DEFAULT_POLYGON_FILL]){ + self.defaultPolygonFillColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_DEFAULT_POLYGON_FILL_COLOR]]; } - self.editPolylineColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYLINE_COLOR]]; - self.editPolylineLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_EDIT_POLYLINE_LINE_WIDTH] doubleValue]; + self.editPolylineColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYLINE_COLOR]]; + self.editPolylineLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_EDIT_POLYLINE_LINE_WIDTH] doubleValue]; - self.editPolygonColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYGON_COLOR]]; - self.editPolygonLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_EDIT_POLYGON_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_EDIT_POLYGON_FILL]){ - self.editPolygonFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYGON_FILL_COLOR]]; + self.editPolygonColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYGON_COLOR]]; + self.editPolygonLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_EDIT_POLYGON_LINE_WIDTH] doubleValue]; + if([MCProperties getBoolOfProperty:GPKGS_PROP_EDIT_POLYGON_FILL]){ + self.editPolygonFillColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_EDIT_POLYGON_FILL_COLOR]]; } - self.drawPolylineColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYLINE_COLOR]]; - self.drawPolylineLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DRAW_POLYLINE_LINE_WIDTH] doubleValue]; + self.drawPolylineColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYLINE_COLOR]]; + self.drawPolylineLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_DRAW_POLYLINE_LINE_WIDTH] doubleValue]; + + self.drawPolygonColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYGON_COLOR]]; + self.drawPolygonLineWidth = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_DRAW_POLYGON_LINE_WIDTH] doubleValue]; + if([MCProperties getBoolOfProperty:GPKGS_PROP_DRAW_POLYGON_FILL]){ + self.drawPolygonFillColor = [GPKGUtils color:[MCProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYGON_FILL_COLOR]]; + } +} + + +/** + Used to show tile previews after a tile download, or switch on saved tile URLs from the map. +*/ +- (void) addUserTilesWithUrl:(NSString *) tileTemplateURL { + if (self.userTileOverlay != nil) { + [self.mapView removeOverlay:self.userTileOverlay]; + } - self.drawPolygonColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYGON_COLOR]]; - self.drawPolygonLineWidth = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_DRAW_POLYGON_LINE_WIDTH] doubleValue]; - if([GPKGSProperties getBoolOfProperty:GPKGS_PROP_DRAW_POLYGON_FILL]){ - self.drawPolygonFillColor = [GPKGUtils getColor:[GPKGSProperties getDictionaryOfProperty:GPKGS_PROP_DRAW_POLYGON_FILL_COLOR]]; + self.userTileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:tileTemplateURL]; + [self.mapView insertOverlay:self.userTileOverlay atIndex:0]; +} + + +/** + Used to remove tile previews after a tile download, or switch off saved tile URLs from the map. + */ +- (void) removeUserTiles { + if (self.userTileOverlay != nil) { + [self.mapView removeOverlay:self.userTileOverlay]; } } @@ -798,142 +872,31 @@ -(void) longPressGesture:(UILongPressGestureRecognizer *) longPressGestureRecogn CGPoint cgPoint = [longPressGestureRecognizer locationInView:self.mapView]; CLLocationCoordinate2D point = [self.mapView convertPoint:cgPoint toCoordinateFromView:self.mapView]; - if(self.boundingBoxMode){ - NSLog(@"Bounding Box mode"); - if(longPressGestureRecognizer.state == UIGestureRecognizerStateBegan){ - //[_editBoundingBoxButton setTitle:@"Edit Bounding Box" forState:UIControlStateNormal]; - - // Check to see if editing any of the bounding box corners - if (self.boundingBox != nil && CLLocationCoordinate2DIsValid(self.boundingBoxEndCorner)) { - - double allowableScreenPercentage = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_TILES_LONG_CLICK_SCREEN_PERCENTAGE] intValue] / 100.0; - if([self isWithinDistanceWithPoint:cgPoint andLocation:self.boundingBoxEndCorner andAllowableScreenPercentage:allowableScreenPercentage]){ - [self setDrawing:true]; - }else if([self isWithinDistanceWithPoint:cgPoint andLocation:self.boundingBoxStartCorner andAllowableScreenPercentage:allowableScreenPercentage]){ - CLLocationCoordinate2D temp = self.boundingBoxStartCorner; - self.boundingBoxStartCorner = self.boundingBoxEndCorner; - self.boundingBoxEndCorner = temp; - [self setDrawing:true]; - }else{ - CLLocationCoordinate2D corner1 = CLLocationCoordinate2DMake(self.boundingBoxStartCorner.latitude, self.boundingBoxEndCorner.longitude); - CLLocationCoordinate2D corner2 = CLLocationCoordinate2DMake(self.boundingBoxEndCorner.latitude, self.boundingBoxStartCorner.longitude); - if([self isWithinDistanceWithPoint:cgPoint andLocation:corner1 andAllowableScreenPercentage:allowableScreenPercentage]){ - self.boundingBoxStartCorner = corner2; - self.boundingBoxEndCorner = corner1; - [self setDrawing:true]; - }else if([self isWithinDistanceWithPoint:cgPoint andLocation:corner2 andAllowableScreenPercentage:allowableScreenPercentage]){ - self.boundingBoxStartCorner = corner1; - self.boundingBoxEndCorner = corner2; - [self setDrawing:true]; - } - } - } - - // Start drawing a new polygon - if(!self.drawing){ - if(self.boundingBox != nil){ - [self.mapView removeOverlay:self.boundingBox]; - } - self.boundingBoxStartCorner = point; - self.boundingBoxEndCorner = point; - CLLocationCoordinate2D * points = [self getPolygonPointsWithPoint1:self.boundingBoxStartCorner andPoint2:self.boundingBoxEndCorner]; - self.boundingBox = [GPKGPolygon polygonWithCoordinates:points count:4]; - - [self.mapView addOverlay:self.boundingBox]; - [self setDrawing:true]; - } + if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan && self.tempMapPoints.count == 0) { + UINotificationFeedbackGenerator *feedbackGenerator = [[UINotificationFeedbackGenerator alloc] init]; + [feedbackGenerator notificationOccurred:UINotificationFeedbackTypeSuccess]; + + NSLog(@"Adding a pin"); + GPKGMapPoint * mapPoint = [[GPKGMapPoint alloc] initWithLocation:point]; + [mapPoint.options setPinTintColor:[UIColor redColor]]; + + [self.mapView addAnnotation: mapPoint]; + [self.tempMapPoints addObject:mapPoint]; + + if (!_drawing && self.tempMapPoints.count > 0) { + [self zoomToPointWithOffset: point]; + [mapPoint setTitle:[_featureHelper buildLocationTitleWithMapPoint:mapPoint]]; + [self.mapView selectAnnotation:mapPoint animated:YES]; - }else{ - switch(longPressGestureRecognizer.state){ - case UIGestureRecognizerStateChanged: - case UIGestureRecognizerStateEnded: - if(self.boundingBoxMode){ - if(self.drawing && self.boundingBox != nil){ - self.boundingBoxEndCorner = point; - CLLocationCoordinate2D * points = [self getPolygonPointsWithPoint1:self.boundingBoxStartCorner andPoint2:self.boundingBoxEndCorner]; - GPKGPolygon * newBoundingBox = [GPKGPolygon polygonWithCoordinates:points count:4]; - [self.mapView removeOverlay:self.boundingBox]; - [self.mapView addOverlay:newBoundingBox]; - self.boundingBox = newBoundingBox; - //_nextButton.enabled = YES; - self.navigationItem.prompt = @"You can drag the corners of the bounding box to adjust it."; - - if (_boundingBoxStartCorner.latitude > _boundingBoxEndCorner.latitude) { - _minLat = _boundingBoxEndCorner.latitude; - _maxLat = _boundingBoxStartCorner.latitude; - - //_upperRightLatitudeLabel.text = [NSString stringWithFormat:@"Lat: %.2f", self.boundingBoxStartCorner.latitude]; - //_lowerLeftLatitudeLabel.text = [NSString stringWithFormat:@"Lat: %.2f", self.boundingBoxEndCorner.latitude]; - } else { - _minLat = _boundingBoxStartCorner.latitude; - _maxLat = _boundingBoxEndCorner.latitude; - - //_upperRightLatitudeLabel.text = [NSString stringWithFormat:@"Lat: %.2f", self.boundingBoxEndCorner.latitude]; - //_lowerLeftLatitudeLabel.text = [NSString stringWithFormat:@"Lat: %.2f", self.boundingBoxStartCorner.latitude]; - } - - if (_boundingBoxStartCorner.longitude < _boundingBoxEndCorner.longitude) { - _minLon = _boundingBoxStartCorner.longitude; - _maxLon = _boundingBoxEndCorner.longitude; - - //_lowerLeftLongitudeLabel.text = [NSString stringWithFormat:@"Lon: %.2f", self.boundingBoxStartCorner.longitude]; - //_upperRightLongitudeLabel.text = [NSString stringWithFormat:@"Lon: %.2f", self.boundingBoxEndCorner.longitude]; - } else { - _minLon = _boundingBoxEndCorner.longitude; - _maxLon = _boundingBoxStartCorner.longitude; - - //_lowerLeftLongitudeLabel.text = [NSString stringWithFormat:@"Lon: %.2f", self.boundingBoxEndCorner.longitude]; - //_upperRightLongitudeLabel.text = [NSString stringWithFormat:@"Lon: %.2f", self.boundingBoxStartCorner.longitude]; - } - - -// [self animateShowHide:_lowerLeftLabel :NO]; -// [self animateShowHide:_upperRightLabel :NO]; -// [self animateShowHide:_lowerLeftLatitudeLabel :NO]; -// [self animateShowHide:_lowerLeftLongitudeLabel :NO]; -// [self animateShowHide:_upperRightLatitudeLabel :NO]; -// [self animateShowHide:_upperRightLongitudeLabel :NO]; - } - if(longPressGestureRecognizer.state == UIGestureRecognizerStateEnded){ - [self setDrawing:false]; - - GPKGBoundingBox *boundingBox = [[GPKGBoundingBox alloc] initWithMinLongitude:[[NSDecimalNumber alloc] initWithDouble:_minLon] - andMinLatitude:[[NSDecimalNumber alloc] initWithDouble:_minLat] - andMaxLongitude:[[NSDecimalNumber alloc] initWithDouble:_maxLon] - andMaxLatitude:[[NSDecimalNumber alloc] initWithDouble:_maxLat]]; - - NSDictionary *boundingBoxResults = @{@"boundingBox": boundingBox}; - - // MCBoundingBoxDetailsViewController is on the recieving end - [[NSNotificationCenter defaultCenter] postNotificationName:@"boundingBoxResults" object:self userInfo:boundingBoxResults]; - } - } - break; - default: - break; - } + _drawing = YES; + } else { + [self.mapActionDelegate updateDrawingStatus]; } - } - /*else if(self.editFeatureType != GPKGS_ET_NONE){ - if(longPressGestureRecognizer.state == UIGestureRecognizerStateBegan){ - if(self.editFeatureType == GPKGS_ET_EDIT_FEATURE){ - if(self.editFeatureShapePoints != nil){ - GPKGMapPoint * mapPoint = [self addEditPoint:point]; - [self.editFeatureShapePoints addNewPoint:mapPoint]; - [self.editFeatureShape addPoint:mapPoint withShape:self.editFeatureShapePoints]; - GPKGSMapPointData * data = [self getOrCreateDataWithMapPoint:mapPoint]; - data.type = GPKGS_MPDT_EDIT_FEATURE_POINT; - [self setTitleWithGeometryType:self.editFeatureShape.shape.geometryType andMapPoint:mapPoint]; - [self updateEditState:true]; // TODO figure out if I need all of this method - } - }else{ - GPKGMapPoint * mapPoint = [self addEditPoint:point]; - [self setTitleWithTitle:[GPKGSEditTypes pointName:self.editFeatureType] andMapPoint:mapPoint]; - [self updateEditState:true]; // TODO figure out if I need all of this method - } - } - }*/ + } + + // MKMapView workaround for unresponsiveness after a longpress https://forums.developer.apple.com/thread/126473 + //[self.mapView setCenterCoordinate:self.mapView.centerCoordinate animated:NO]; } diff --git a/mapcache-ios/map/MCTileHelper.h b/mapcache-ios/map/MCTileHelper.h index bea1c00..283e626 100644 --- a/mapcache-ios/map/MCTileHelper.h +++ b/mapcache-ios/map/MCTileHelper.h @@ -7,24 +7,24 @@ // #import -#import "GPKGSDatabase.h" -#import "GPKGSTileTable.h" +#import "MCDatabase.h" +#import "MCTileTable.h" #import "GPKGGeoPackageManager.h" #import "GPKGGeoPackageFactory.h" #import "GPKGTileBoundingBoxUtils.h" #import "GPKGTileTableScaling.h" -#import "GPKGSTileTable.h" +#import "MCTileTable.h" #import "GPKGTileBoundingBoxUtils.h" #import "GPKGBoundedOverlay.h" #import "GPKGOverlayFactory.h" #import "SFPProjectionFactory.h" #import "SFGeometryEnvelopeBuilder.h" #import "SFPProjectionConstants.h" -#import "GPKGSDatabases.h" +#import "MCDatabases.h" @protocol MCTileHelperDelegate -- (void) addTileOverlayToMapView: (MKTileOverlay *) tileOverlay; +- (void) addTileOverlayToMapView:(MKTileOverlay *) tileOverlay withTable:(MCTileTable *)table; @end @@ -33,8 +33,8 @@ - (instancetype)initWithTileHelperDelegate: (id) delegate; - (void)prepareTiles; -- (void) prepareTilesForGeoPackage: (GPKGGeoPackage *) geoPackage andDatabase:(GPKGSDatabase *) database; -- (MKTileOverlay *)createOverlayForTiles: (GPKGSTileTable *) tiles fromGeoPacakge:(GPKGGeoPackage *) geoPackage; +- (void) prepareTilesForGeoPackage: (GPKGGeoPackage *) geoPackage andDatabase:(MCDatabase *) database; +- (MKTileOverlay *)createOverlayForTiles: (MCTileTable *) tiles fromGeoPacakge:(GPKGGeoPackage *) geoPackage; - (GPKGBoundingBox *)tilesBoundingBox; - (GPKGBoundingBox *)transformBoundingBoxToWgs84: (GPKGBoundingBox *)boundingBox withSrs: (GPKGSpatialReferenceSystem *)srs; @end diff --git a/mapcache-ios/map/MCTileHelper.m b/mapcache-ios/map/MCTileHelper.m index 3c119c4..e7a98e1 100644 --- a/mapcache-ios/map/MCTileHelper.m +++ b/mapcache-ios/map/MCTileHelper.m @@ -12,7 +12,7 @@ @interface MCTileHelper() @property (nonatomic, strong) GPKGGeoPackageManager *manager; @property (nonatomic, strong) GPKGBoundingBox * tilesBoundingBox; -@property (nonatomic, strong) GPKGSDatabases *active; +@property (nonatomic, strong) MCDatabases *active; @end @@ -20,8 +20,8 @@ @implementation MCTileHelper - (instancetype) init { self = [super init]; - self.active = [GPKGSDatabases getInstance]; - self.manager = [GPKGGeoPackageFactory getManager]; + self.active = [MCDatabases getInstance]; + self.manager = [GPKGGeoPackageFactory manager]; return self; } @@ -30,8 +30,8 @@ - (instancetype) init { - (instancetype) initWithTileHelperDelegate: (id) delegate { self = [super init]; self.tileHelperDelegate = delegate; - self.active = [GPKGSDatabases getInstance]; - self.manager = [GPKGGeoPackageFactory getManager]; + self.active = [MCDatabases getInstance]; + self.manager = [GPKGGeoPackageFactory manager]; return self; } @@ -40,77 +40,90 @@ - (instancetype) initWithTileHelperDelegate: (id) delegate - (void) prepareTiles { NSArray *activeDatabases = [[NSArray alloc] initWithArray: [self.active getDatabases]]; - for (GPKGSDatabase *database in activeDatabases) { - GPKGGeoPackage *geoPackage = [self.manager open:database.name]; + for (MCDatabase *database in activeDatabases) { + GPKGGeoPackage *geoPackage; - if (geoPackage != nil) { - for (GPKGSTileTable *tiles in [database getTiles]) { - @try { + @try { + geoPackage = [self.manager open:database.name]; + + if (geoPackage != nil) { + for (MCTileTable *tiles in [database getTiles]) { MKTileOverlay *tileOverlay = [self createOverlayForTiles:tiles fromGeoPacakge:geoPackage]; - [self.tileHelperDelegate addTileOverlayToMapView:tileOverlay]; - } @catch (NSException *e) { - NSLog(@"%@", [e description]); - } + if (tileOverlay != nil) { + [self.tileHelperDelegate addTileOverlayToMapView:tileOverlay withTable:tiles]; + } + } } + } @catch (NSException *e) { + NSLog(@"MCTileHelper - prepareTiles: %@", e.reason); } } } -- (void) prepareTilesForGeoPackage: (GPKGGeoPackage *) geoPackage andDatabase:(GPKGSDatabase *) database { - for (GPKGSTileTable *tiles in [database getTiles]) { +- (void) prepareTilesForGeoPackage: (GPKGGeoPackage *) geoPackage andDatabase:(MCDatabase *) database { + for (MCTileTable *tiles in [database getTiles]) { @try { MKTileOverlay *tileOverlay = [self createOverlayForTiles:tiles fromGeoPacakge:geoPackage]; - [self.tileHelperDelegate addTileOverlayToMapView:tileOverlay]; + [self.tileHelperDelegate addTileOverlayToMapView:tileOverlay withTable:tiles]; } @catch (NSException *e) { - NSLog(@"%@", [e description]); + NSLog(@"MCTileHelper - prepareTilesForGeoPackage: %@", [e description]); } } } // MCTileHelper version of -(void) displayTiles: (GPKGSTileTable *) --(MKTileOverlay *) createOverlayForTiles: (GPKGSTileTable *) tiles fromGeoPacakge:(GPKGGeoPackage *) geoPackage { - GPKGTileDao * tileDao = [geoPackage getTileDaoWithTableName:tiles.name]; - GPKGTileTableScaling *tileTableScaling = [[GPKGTileTableScaling alloc] initWithGeoPackage:geoPackage andTileDao:tileDao]; - GPKGTileScaling *tileScaling = [tileTableScaling get]; - GPKGBoundedOverlay * overlay = [GPKGOverlayFactory boundedOverlay:tileDao andScaling:tileScaling]; - overlay.canReplaceMapContent = false; - - GPKGTileMatrixSet * tileMatrixSet = tileDao.tileMatrixSet; +-(MKTileOverlay *) createOverlayForTiles: (MCTileTable *) tiles fromGeoPacakge:(GPKGGeoPackage *) geoPackage { + GPKGBoundedOverlay *overlay = nil; - // TODO: handle feature tiles. - // GPKGFeatureTileTableLinker * linker = [[GPKGFeatureTileTableLinker alloc] initWithGeoPackage:geoPackage]; - // NSArray * featureDaos = [linker getFeatureDaosForTileTable:tileDao.tableName]; - // for(GPKGFeatureDao * featureDao in featureDaos){ - // - // // Create the feature tiles - // GPKGFeatureTiles * featureTiles = [[GPKGFeatureTiles alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; - // - // self.featureOverlayTiles = true; - // - // // Add the feature overlay query - //// GPKGFeatureOverlayQuery * featureOverlayQuery = [[GPKGFeatureOverlayQuery alloc] initWithBoundedOverlay:overlay andFeatureTiles:featureTiles]; - // [self.featureOverlayQueries addObject:featureOverlayQuery]; - // } - - GPKGBoundingBox *displayBoundingBox = [tileMatrixSet getBoundingBox]; - GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage getTileMatrixSetDao]; - GPKGSpatialReferenceSystem *tileMatrixSetSrs = [tileMatrixSetDao getSrs:tileMatrixSet]; - GPKGContents *contents = [tileMatrixSetDao getContents:tileMatrixSet]; - GPKGBoundingBox *contentsBoundingBox = [contents getBoundingBox]; - if(contentsBoundingBox != nil){ - GPKGContentsDao *contentsDao = [geoPackage getContentsDao]; - SFPProjectionTransform *transform = [[SFPProjectionTransform alloc] initWithFromProjection:[[contentsDao getSrs:contents] projection] andToProjection:[tileMatrixSetSrs projection]]; - GPKGBoundingBox *transformedContentsBoundingBox = contentsBoundingBox; - if(![transform isSameProjection]){ - transformedContentsBoundingBox = [transformedContentsBoundingBox transform:transform]; + @try { + GPKGTileDao * tileDao = [geoPackage tileDaoWithTableName:tiles.name]; + GPKGTileTableScaling *tileTableScaling = [[GPKGTileTableScaling alloc] initWithGeoPackage:geoPackage andTileDao:tileDao]; + GPKGTileScaling *tileScaling = [tileTableScaling tileScaling]; + overlay = [GPKGOverlayFactory boundedOverlay:tileDao andScaling:tileScaling]; + overlay.canReplaceMapContent = false; + + GPKGTileMatrixSet * tileMatrixSet = tileDao.tileMatrixSet; + + // TODO: handle feature tiles. + // GPKGFeatureTileTableLinker * linker = [[GPKGFeatureTileTableLinker alloc] initWithGeoPackage:geoPackage]; + // NSArray * featureDaos = [linker getFeatureDaosForTileTable:tileDao.tableName]; + // for(GPKGFeatureDao * featureDao in featureDaos){ + // + // // Create the feature tiles + // GPKGFeatureTiles * featureTiles = [[GPKGFeatureTiles alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; + // + // self.featureOverlayTiles = true; + // + // // Add the feature overlay query + //// GPKGFeatureOverlayQuery * featureOverlayQuery = [[GPKGFeatureOverlayQuery alloc] initWithBoundedOverlay:overlay andFeatureTiles:featureTiles]; + // [self.featureOverlayQueries addObject:featureOverlayQuery]; + // } + + GPKGBoundingBox *displayBoundingBox = [tileMatrixSet boundingBox]; + GPKGTileMatrixSetDao * tileMatrixSetDao = [geoPackage tileMatrixSetDao]; + GPKGSpatialReferenceSystem *tileMatrixSetSrs = [tileMatrixSetDao srs:tileMatrixSet]; + GPKGContents *contents = [tileMatrixSetDao contents:tileMatrixSet]; + GPKGBoundingBox *contentsBoundingBox = [contents boundingBox]; + if(contentsBoundingBox != nil){ + GPKGContentsDao *contentsDao = [geoPackage contentsDao]; + SFPProjectionTransform *transform = [[SFPProjectionTransform alloc] initWithFromProjection:[[contentsDao srs:contents] projection] andToProjection:[tileMatrixSetSrs projection]]; + GPKGBoundingBox *transformedContentsBoundingBox = contentsBoundingBox; + if(![transform isSameProjection]){ + transformedContentsBoundingBox = [transformedContentsBoundingBox transform:transform]; + } + displayBoundingBox = [GPKGTileBoundingBoxUtils overlapWithBoundingBox:displayBoundingBox andBoundingBox:transformedContentsBoundingBox]; } - displayBoundingBox = [GPKGTileBoundingBoxUtils overlapWithBoundingBox:displayBoundingBox andBoundingBox:transformedContentsBoundingBox]; + + [self updateTileBoundingBox:displayBoundingBox withSrs:tileMatrixSetSrs andSpecifiedBoundingBox:nil]; + + } @catch(NSException *e) { + NSLog(@"MCTileHelper - createOverlayForTilesFromGeoPacakge %@", e.reason); + } @finally { + return overlay; } - [self updateTileBoundingBox:displayBoundingBox withSrs:tileMatrixSetSrs andSpecifiedBoundingBox:nil]; - return overlay; } diff --git a/mapcache-ios/mapcache.plist b/mapcache-ios/mapcache.plist index 34b91ca..3f4a878 100644 --- a/mapcache-ios/mapcache.plist +++ b/mapcache-ios/mapcache.plist @@ -2,6 +2,8 @@ + nga_drawer_view_space_from_top + 200 animate_screen_touches icon_geometry diff --git a/mapcache-ios/settings/MCNewTileServerViewController.h b/mapcache-ios/settings/MCNewTileServerViewController.h index b2a6670..c60f388 100644 --- a/mapcache-ios/settings/MCNewTileServerViewController.h +++ b/mapcache-ios/settings/MCNewTileServerViewController.h @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface MCNewTileServerViewController : NGADrawerViewController +@interface MCNewTileServerViewController : NGADrawerViewController @property (nonatomic, strong) idsaveTileServerDelegate; - (void) setServerName:(NSString *) serverName; - (void) setServerURL:(NSString *) serverURL; diff --git a/mapcache-ios/settings/MCNewTileServerViewController.m b/mapcache-ios/settings/MCNewTileServerViewController.m index 7439ea2..1f1a1d4 100644 --- a/mapcache-ios/settings/MCNewTileServerViewController.m +++ b/mapcache-ios/settings/MCNewTileServerViewController.m @@ -113,7 +113,7 @@ - (BOOL) textFieldShouldReturn:(UITextField *)textField { #pragma mark - UITextFieldDelegate - (void) textFieldDidEndEditing:(UITextField *)textField { - [textField trimWhiteSpace:textField]; + [textField trimWhiteSpace]; if (textField.text && ![textField.text isEqualToString:@""]) { self.nameIsValid = YES; [self.nameField useNormalAppearance]; diff --git a/mapcache-ios/settings/MCSettingsCoordinator.h b/mapcache-ios/settings/MCSettingsCoordinator.h index 8f44a8a..074afc6 100644 --- a/mapcache-ios/settings/MCSettingsCoordinator.h +++ b/mapcache-ios/settings/MCSettingsCoordinator.h @@ -11,7 +11,7 @@ #import "MCNoticeAndAttributionViewController.h" #import "MCTileServerURLManagerViewController.h" #import "MCNewTileServerViewController.h" -#import "GPKGSConstants.h" +#import "MCConstants.h" @interface MCSettingsCoordinator : NSObject diff --git a/mapcache-ios/settings/MCSettingsViewController.h b/mapcache-ios/settings/MCSettingsViewController.h index 3d483ca..b0761b6 100644 --- a/mapcache-ios/settings/MCSettingsViewController.h +++ b/mapcache-ios/settings/MCSettingsViewController.h @@ -14,7 +14,7 @@ #import "MCFieldWithTitleCell.h" #import "MCSwitchCell.h" #import "MCButtonCell.h" -#import "GPKGSProperties.h" +#import "MCProperties.h" #import /* Settings that change the state of the map, or the controls that are shown are handled here */ @@ -33,7 +33,7 @@ @end -@interface MCSettingsViewController : NGADrawerViewController +@interface MCSettingsViewController : NGADrawerViewController @property (nonatomic, strong) id mapSettingsDelegate; @property (nonatomic, strong) id settingsDelegate; @end diff --git a/mapcache-ios/settings/MCSettingsViewController.m b/mapcache-ios/settings/MCSettingsViewController.m index 6716493..468ae6f 100644 --- a/mapcache-ios/settings/MCSettingsViewController.m +++ b/mapcache-ios/settings/MCSettingsViewController.m @@ -28,9 +28,10 @@ - (void)viewDidLoad { [super viewDidLoad]; self.haveScrolled = NO; - CGRect bounds = self.view.bounds; - CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y + 32, bounds.size.width, bounds.size.height - 20); - self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; +// CGRect bounds = self.view.bounds; +// CGRect insetBounds = CGRectMake(bounds.origin.x, bounds.origin.y + 32, bounds.size.width, bounds.size.height - 20); + //self.tableView = [[UITableView alloc] initWithFrame: insetBounds style:UITableViewStylePlain]; + self.tableView = [[UITableView alloc] init]; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; self.tableView.delegate = self; self.tableView.dataSource = self; @@ -41,13 +42,14 @@ - (void)viewDidLoad { [self registerCellTypes]; [self initCellArray]; - self.edgesForExtendedLayout = UIRectEdgeNone; - self.extendedLayoutIncludesOpaqueBars = NO; - self.automaticallyAdjustsScrollViewInsets = NO; - UIEdgeInsets tabBarInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0); - self.tableView.contentInset = tabBarInsets; - self.tableView.scrollIndicatorInsets = tabBarInsets; - [self.view addSubview:self.tableView]; +// self.edgesForExtendedLayout = UIRectEdgeNone; +// self.extendedLayoutIncludesOpaqueBars = NO; +// self.automaticallyAdjustsScrollViewInsets = NO; +// UIEdgeInsets tabBarInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0); +// self.tableView.contentInset = tabBarInsets; +// self.tableView.scrollIndicatorInsets = tabBarInsets; + //[self.view addSubview:self.tableView]; + [self addAndConstrainSubview:self.tableView]; [self addDragHandle]; [self addCloseButton]; @@ -73,16 +75,16 @@ - (void)initCellArray { _baseMapSelector = [_tableView dequeueReusableCellWithIdentifier:@"segmentedControl"]; _baseMapSelector.label.text = @"Base Map Type"; _baseMapSelector.delegate = self; - NSArray *maps = [[NSArray alloc] initWithObjects: [GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE], - [GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_HYBRID], nil]; + NSArray *maps = [[NSArray alloc] initWithObjects: [MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD], + [MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE], + [MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_HYBRID], nil]; - [_baseMapSelector setItems:maps]; + [_baseMapSelector updateItems:maps]; NSString *mapType = [self.settings stringForKey:GPKGS_PROP_MAP_TYPE]; - if (mapType == nil || [mapType isEqualToString:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD]]) { + if (mapType == nil || [mapType isEqualToString:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_STANDARD]]) { [_baseMapSelector.segmentedControl setSelectedSegmentIndex:0]; - } else if ([mapType isEqualToString:[GPKGSProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE]]) { + } else if ([mapType isEqualToString:[MCProperties getValueOfProperty:GPKGS_PROP_MAP_TYPE_SATELLITE]]) { [_baseMapSelector.segmentedControl setSelectedSegmentIndex:1]; } else { [_baseMapSelector.segmentedControl setSelectedSegmentIndex:2]; @@ -94,7 +96,7 @@ - (void)initCellArray { _maxFeaturesCell.title.text = @"Maximum number of features"; int maxFeatures = (int)[self.settings integerForKey:GPKGS_PROP_MAP_MAX_FEATURES]; if(maxFeatures == 0){ - maxFeatures = [[GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES_DEFAULT] intValue]; + maxFeatures = [[MCProperties getNumberValueOfProperty:GPKGS_PROP_MAP_MAX_FEATURES_DEFAULT] intValue]; } _maxFeaturesCell.field.text = [NSString stringWithFormat:@"%d", maxFeatures]; [_maxFeaturesCell setTextFielDelegate:self]; diff --git a/mapcache-ios/settings/MCTileServerURLManagerViewController.h b/mapcache-ios/settings/MCTileServerURLManagerViewController.h index ca693f3..941c0e0 100644 --- a/mapcache-ios/settings/MCTileServerURLManagerViewController.h +++ b/mapcache-ios/settings/MCTileServerURLManagerViewController.h @@ -14,7 +14,7 @@ #import "MCButtonCell.h" #import "MCTitleCell.h" #import "MCLayerCell.h" -#import "GPKGSProperties.h" +#import "MCProperties.h" NS_ASSUME_NONNULL_BEGIN @@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface MCTileServerURLManagerViewController : NGADrawerViewController +@interface MCTileServerURLManagerViewController : NGADrawerViewController @property (weak, nonatomic) id tileServerManagerDelegate; @property (weak, nonatomic) id selectServerDelegate; @property (nonatomic) BOOL selectMode; diff --git a/mapcache-ios/settings/MCTileServerURLManagerViewController.m b/mapcache-ios/settings/MCTileServerURLManagerViewController.m index db46371..1c62676 100644 --- a/mapcache-ios/settings/MCTileServerURLManagerViewController.m +++ b/mapcache-ios/settings/MCTileServerURLManagerViewController.m @@ -77,7 +77,7 @@ - (void) initCellArray { [testURL1 setName:@"GEOINT Services OSM"]; [testURL1 setDetails:@"https://osm.gs.mil/tiles/default/{z}/{x}/{y}.png"]; [testURL1 activeIndicatorOff]; - [testURL1.layerTypeImage setImage:[UIImage imageNamed:[GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_TILE_SERVER]]]; + [testURL1.layerTypeImage setImage:[UIImage imageNamed:[MCProperties getValueOfProperty:GPKGS_PROP_ICON_TILE_SERVER]]]; [self.cellArray addObject:testURL1]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; @@ -90,7 +90,7 @@ - (void) initCellArray { [tileServerCell setName: serverName]; [tileServerCell setDetails: [serverUrls objectForKey:serverName]]; [tileServerCell activeIndicatorOff]; - [tileServerCell.layerTypeImage setImage:[UIImage imageNamed:[GPKGSProperties getValueOfProperty:GPKGS_PROP_ICON_TILE_SERVER]]]; + [tileServerCell.layerTypeImage setImage:[UIImage imageNamed:[MCProperties getValueOfProperty:GPKGS_PROP_ICON_TILE_SERVER]]]; [self.cellArray addObject:tileServerCell]; } } diff --git a/mapcache-ios/ui/GPKGSBoundingBoxViewController.m b/mapcache-ios/ui/GPKGSBoundingBoxViewController.m index 1429899..e101d0f 100644 --- a/mapcache-ios/ui/GPKGSBoundingBoxViewController.m +++ b/mapcache-ios/ui/GPKGSBoundingBoxViewController.m @@ -7,16 +7,16 @@ // #import "GPKGSBoundingBoxViewController.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSDecimalValidator.h" -#import "GPKGSUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCDecimalValidator.h" +#import "MCUtils.h" @interface GPKGSBoundingBoxViewController () @property (nonatomic, strong) NSArray * boundingBoxes; -@property (nonatomic, strong) GPKGSDecimalValidator * latitudeValidator; -@property (nonatomic, strong) GPKGSDecimalValidator * longitudeValidator; +@property (nonatomic, strong) MCDecimalValidator * latitudeValidator; +@property (nonatomic, strong) MCDecimalValidator * longitudeValidator; @end @@ -27,18 +27,18 @@ @implementation GPKGSBoundingBoxViewController - (void)viewDidLoad { [super viewDidLoad]; - self.latitudeValidator = [[GPKGSDecimalValidator alloc] initWithMinimumDouble:-90.0 andMaximumDouble:90.0]; - self.longitudeValidator = [[GPKGSDecimalValidator alloc] initWithMinimumDouble:-180.0 andMaximumDouble:180.0]; + self.latitudeValidator = [[MCDecimalValidator alloc] initWithMinimumDouble:-90.0 andMaximumDouble:90.0]; + self.longitudeValidator = [[MCDecimalValidator alloc] initWithMinimumDouble:-180.0 andMaximumDouble:180.0]; [self.minLatValue setDelegate:self.latitudeValidator]; [self.maxLatValue setDelegate:self.latitudeValidator]; [self.minLonValue setDelegate:self.longitudeValidator]; [self.maxLonValue setDelegate:self.longitudeValidator]; - self.boundingBoxes = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_BOUNDING_BOXES]; + self.boundingBoxes = [MCProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_BOUNDING_BOXES]; if(self.boundingBox == nil){ - [self.minLatValue setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MIN_LATITUDE]]; - [self.maxLatValue setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MAX_LATITUDE]]; - [self.minLonValue setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MIN_LONGITUDE]]; - [self.maxLonValue setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MAX_LONGITUDE]]; + [self.minLatValue setText:[MCProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MIN_LATITUDE]]; + [self.maxLatValue setText:[MCProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MAX_LATITUDE]]; + [self.minLonValue setText:[MCProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MIN_LONGITUDE]]; + [self.maxLonValue setText:[MCProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_DEFAULT_MAX_LONGITUDE]]; self.boundingBox = [[GPKGBoundingBox alloc] initWithMinLongitudeDouble:-180.0 andMinLatitudeDouble:-90.0 andMaxLongitudeDouble:180.0 andMaxLatitudeDouble:90.0]; [self updateBoundingBox]; } else{ @@ -48,7 +48,7 @@ - (void)viewDidLoad { [self.maxLonValue setText:[self.boundingBox.maxLongitude stringValue]]; } - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.minLatValue.inputAccessoryView = keyboardToolbar; self.maxLatValue.inputAccessoryView = keyboardToolbar; @@ -91,7 +91,7 @@ - (IBAction)preloadedLocations:(id)sender { } UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_PRELOADED_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_BOUNDING_BOX_PRELOADED_LABEL] message:nil delegate:self cancelButtonTitle:nil @@ -100,7 +100,7 @@ - (IBAction)preloadedLocations:(id)sender { for (NSString *box in boxes) { [alert addButtonWithTitle:box]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_BOUNDING_BOXES; diff --git a/mapcache-ios/ui/GPKGSCreateTilesViewController.m b/mapcache-ios/ui/GPKGSCreateTilesViewController.m index be35d69..28efa9a 100644 --- a/mapcache-ios/ui/GPKGSCreateTilesViewController.m +++ b/mapcache-ios/ui/GPKGSCreateTilesViewController.m @@ -7,7 +7,7 @@ // #import "GPKGSCreateTilesViewController.h" -#import "GPKGSUtils.h" +#import "MCUtils.h" #import "GPKGSLoadTilesViewController.h" NSString * const GPKGS_CREATE_TILES_SEG_LOAD_TILES = @"loadTiles"; @@ -21,7 +21,7 @@ @implementation GPKGSCreateTilesViewController - (void)viewDidLoad { [super viewDidLoad]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.nameTextField.inputAccessoryView = keyboardToolbar; } diff --git a/mapcache-ios/ui/GPKGSEditContentsViewController.m b/mapcache-ios/ui/GPKGSEditContentsViewController.m index bac6200..b7957cb 100644 --- a/mapcache-ios/ui/GPKGSEditContentsViewController.m +++ b/mapcache-ios/ui/GPKGSEditContentsViewController.m @@ -7,12 +7,12 @@ // #import "GPKGSEditContentsViewController.h" -#import "GPKGSDecimalValidator.h" -#import "GPKGSUtils.h" +#import "MCDecimalValidator.h" +#import "MCUtils.h" @interface GPKGSEditContentsViewController () -@property (nonatomic, strong) GPKGSDecimalValidator * xAndYValidator; +@property (nonatomic, strong) MCDecimalValidator * xAndYValidator; @end @@ -21,7 +21,7 @@ @implementation GPKGSEditContentsViewController - (void)viewDidLoad { [super viewDidLoad]; - self.xAndYValidator = [[GPKGSDecimalValidator alloc] initWithMinimum:nil andMaximum:nil]; + self.xAndYValidator = [[MCDecimalValidator alloc] initWithMinimum:nil andMaximum:nil]; [self.minYTextField setDelegate:self.xAndYValidator]; [self.maxYTextField setDelegate:self.xAndYValidator]; [self.minXTextField setDelegate:self.xAndYValidator]; @@ -42,7 +42,7 @@ - (void)viewDidLoad { [self.maxXTextField setText:[self.data.maxX stringValue]]; } - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.identifierTextField.inputAccessoryView = keyboardToolbar; self.descriptionTextField.inputAccessoryView = keyboardToolbar; diff --git a/mapcache-ios/ui/GPKGSEditTileOverlayViewController.h b/mapcache-ios/ui/GPKGSEditTileOverlayViewController.h index c2b0fbf..e4dd8ce 100644 --- a/mapcache-ios/ui/GPKGSEditTileOverlayViewController.h +++ b/mapcache-ios/ui/GPKGSEditTileOverlayViewController.h @@ -10,7 +10,7 @@ #import "GPKGSBoundingBoxViewController.h" #import "GPKGSEditTileOverlayData.h" #import "GPKGGeoPackageManager.h" -#import "GPKGSTable.h" +#import "MCTable.h" @interface GPKGSEditTileOverlayViewController : UIViewController diff --git a/mapcache-ios/ui/GPKGSEditTileOverlayViewController.m b/mapcache-ios/ui/GPKGSEditTileOverlayViewController.m index c256729..893f76f 100644 --- a/mapcache-ios/ui/GPKGSEditTileOverlayViewController.m +++ b/mapcache-ios/ui/GPKGSEditTileOverlayViewController.m @@ -8,10 +8,10 @@ #import "GPKGSEditTileOverlayViewController.h" #import "GPKGSBoundingBoxViewController.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSDecimalValidator.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCDecimalValidator.h" #import "GPKGGeoPackage.h" #import "GPKGSFeatureTilesDrawViewController.h" #import "SFPProjectionTransform.h" @@ -24,7 +24,7 @@ @interface GPKGSEditTileOverlayViewController () -@property (nonatomic, strong) GPKGSDecimalValidator * zoomValidator; +@property (nonatomic, strong) MCDecimalValidator * zoomValidator; @property (nonatomic, strong) NSNumberFormatter * numberFormatter; @end @@ -40,15 +40,15 @@ - (void)viewDidLoad { // Check if indexed GPKGGeoPackage * geoPackage = [self.manager open:self.database]; @try { - GPKGFeatureDao * featureDao = [geoPackage getFeatureDaoWithTableName:self.featureTable]; + GPKGFeatureDao * featureDao = [geoPackage featureDaoWithTableName:self.featureTable]; GPKGFeatureIndexManager * indexer = [[GPKGFeatureIndexManager alloc] initWithGeoPackage:geoPackage andFeatureDao:featureDao]; @try{ self.data.indexed = [indexer isIndexed]; if(self.data.indexed){ - [self.warningLabel setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURE_OVERLAY_INDEX_VALIDATION]]; + [self.warningLabel setText:[MCProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURE_OVERLAY_INDEX_VALIDATION]]; [self.warningLabel setTextColor:[UIColor greenColor]]; }else{ - [self.warningLabel setText:[GPKGSProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURE_OVERLAY_INDEX_WARNING]]; + [self.warningLabel setText:[MCProperties getValueOfProperty:GPKGS_PROP_EDIT_FEATURE_OVERLAY_INDEX_WARNING]]; } }@finally{ [indexer close]; @@ -58,9 +58,9 @@ - (void)viewDidLoad { [geoPackage close]; } - NSNumber * minZoomValidation = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MIN_ZOOM_DEFAULT]; - NSNumber * maxZoomValidation = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT]; - self.zoomValidator = [[GPKGSDecimalValidator alloc] initWithMinimumNumber:minZoomValidation andMaximumNumber:maxZoomValidation]; + NSNumber * minZoomValidation = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MIN_ZOOM_DEFAULT]; + NSNumber * maxZoomValidation = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT]; + self.zoomValidator = [[MCDecimalValidator alloc] initWithMinimumNumber:minZoomValidation andMaximumNumber:maxZoomValidation]; [self.minZoomTextField setDelegate:self.zoomValidator]; [self.maxZoomTextField setDelegate:self.zoomValidator]; @@ -85,7 +85,7 @@ - (void)viewDidLoad { } } - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.minZoomTextField.inputAccessoryView = keyboardToolbar; self.maxZoomTextField.inputAccessoryView = keyboardToolbar; @@ -131,13 +131,13 @@ -(void) setBoundingBox{ if(self.data.boundingBox == nil){ GPKGGeoPackage * geoPackage = [self.manager open:self.database]; @try { - GPKGContentsDao * contentsDao = [geoPackage getContentsDao]; + GPKGContentsDao * contentsDao = [geoPackage contentsDao]; GPKGContents * contents = (GPKGContents *)[contentsDao queryForIdObject:self.featureTable]; if(contents != nil){ - GPKGBoundingBox * boundingBox = [contents getBoundingBox]; + GPKGBoundingBox * boundingBox = [contents boundingBox]; GPKGBoundingBox * worldGeodeticBoundingBox = nil; if(boundingBox != nil){ - SFPProjection * projection = [contentsDao getProjection:contents]; + SFPProjection * projection = [contentsDao projection:contents]; SFPProjectionTransform * webMercatorTransform = [[SFPProjectionTransform alloc] initWithFromProjection:projection andToEpsg:PROJ_EPSG_WEB_MERCATOR]; if([projection isUnit:SFP_UNIT_DEGREES]){ diff --git a/mapcache-ios/ui/GPKGSFeatureTilesDrawViewController.m b/mapcache-ios/ui/GPKGSFeatureTilesDrawViewController.m index c41e8b8..4e34567 100644 --- a/mapcache-ios/ui/GPKGSFeatureTilesDrawViewController.m +++ b/mapcache-ios/ui/GPKGSFeatureTilesDrawViewController.m @@ -7,16 +7,16 @@ // #import "GPKGSFeatureTilesDrawViewController.h" -#import "GPKGSUtils.h" +#import "MCUtils.h" #import "GPKGUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSDecimalValidator.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCDecimalValidator.h" @interface GPKGSFeatureTilesDrawViewController () -@property (nonatomic, strong) GPKGSDecimalValidator * alphaValidator; -@property (nonatomic, strong) GPKGSDecimalValidator * decimalValidator; +@property (nonatomic, strong) MCDecimalValidator * alphaValidator; +@property (nonatomic, strong) MCDecimalValidator * decimalValidator; @property (nonatomic, strong) NSNumberFormatter * numberFormatter; @property (nonatomic, strong) NSArray * colors; @@ -35,8 +35,8 @@ - (void)viewDidLoad { self.numberFormatter = [[NSNumberFormatter alloc] init]; self.numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; - self.alphaValidator = [[GPKGSDecimalValidator alloc] initWithMinimumInt:0 andMaximumInt:255]; - self.decimalValidator = [[GPKGSDecimalValidator alloc] initWithMinimum:[[NSDecimalNumber alloc] initWithDouble:0.0] andMaximum:nil]; + self.alphaValidator = [[MCDecimalValidator alloc] initWithMinimumInt:0 andMaximumInt:255]; + self.decimalValidator = [[MCDecimalValidator alloc] initWithMinimum:[[NSDecimalNumber alloc] initWithDouble:0.0] andMaximum:nil]; [self.pointAlphaTextField setDelegate:self.alphaValidator]; [self.pointRadiusTextField setDelegate:self.decimalValidator]; @@ -46,7 +46,7 @@ - (void)viewDidLoad { [self.polygonStrokeTextField setDelegate:self.decimalValidator]; [self.polygonFillAlphaTextField setDelegate:self.alphaValidator]; - self.colors = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS]; + self.colors = [MCProperties getArrayOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS]; NSMutableDictionary * colorNames = [[NSMutableDictionary alloc] initWithCapacity:self.colors.count]; for(NSDictionary * color in self.colors){ [colorNames setObject:color forKey:[color objectForKey:GPKGS_PROP_COLORS_NAME]]; @@ -58,7 +58,7 @@ - (void)viewDidLoad { if(self.data.pointColorName != nil){ pointColor = [colorNames objectForKey:self.data.pointColorName]; }else{ - pointColor = [colorNames objectForKey:[GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_POINT]]; + pointColor = [colorNames objectForKey:[MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_POINT]]; } [self setColor:pointColor withTag:TAG_POINT_COLOR]; @@ -78,7 +78,7 @@ - (void)viewDidLoad { if(self.data.lineColorName != nil){ lineColor = [colorNames objectForKey:self.data.lineColorName]; }else{ - lineColor = [colorNames objectForKey:[GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_LINE]]; + lineColor = [colorNames objectForKey:[MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_LINE]]; } [self setColor:lineColor withTag:TAG_LINE_COLOR]; @@ -98,7 +98,7 @@ - (void)viewDidLoad { if(self.data.polygonColorName != nil){ polygonColor = [colorNames objectForKey:self.data.polygonColorName]; }else{ - polygonColor = [colorNames objectForKey:[GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_POLYGON]]; + polygonColor = [colorNames objectForKey:[MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_POLYGON]]; } [self setColor:polygonColor withTag:TAG_POLYGON_COLOR]; @@ -120,7 +120,7 @@ - (void)viewDidLoad { if(self.data.polygonFillColorName != nil){ polygonFillColor = [colorNames objectForKey:self.data.polygonFillColorName]; }else{ - polygonFillColor = [colorNames objectForKey:[GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_POLYGON_FILL]]; + polygonFillColor = [colorNames objectForKey:[MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_COLORS_DEFAULT_POLYGON_FILL]]; } [self setColor:polygonFillColor withTag:TAG_POLYGON_FILL_COLOR]; @@ -131,7 +131,7 @@ - (void)viewDidLoad { } } - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.pointAlphaTextField.inputAccessoryView = keyboardToolbar; self.pointRadiusTextField.inputAccessoryView = keyboardToolbar; @@ -204,7 +204,7 @@ -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)button -(void) setColor: (NSDictionary *) color withTag: (NSInteger) tag{ - UIColor * createdColor = [GPKGUtils getColor:color]; + UIColor * createdColor = [GPKGUtils color:color]; NSString * name = [color objectForKey:GPKGS_PROP_COLORS_NAME]; @@ -238,25 +238,25 @@ -(void) setColor: (NSDictionary *) color withTag: (NSInteger) tag{ - (IBAction)pointColorButton:(id)sender { - UIAlertView *alert = [self buildColorAlertViewWithTitle: [GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_POINT_COLOR_LABEL]]; + UIAlertView *alert = [self buildColorAlertViewWithTitle: [MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_POINT_COLOR_LABEL]]; alert.tag = TAG_POINT_COLOR; [alert show]; } - (IBAction)lineColorButton:(id)sender { - UIAlertView *alert = [self buildColorAlertViewWithTitle: [GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_LINE_COLOR_LABEL]]; + UIAlertView *alert = [self buildColorAlertViewWithTitle: [MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_LINE_COLOR_LABEL]]; alert.tag = TAG_LINE_COLOR; [alert show]; } - (IBAction)polygonColorButton:(id)sender { - UIAlertView *alert = [self buildColorAlertViewWithTitle: [GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_POLYGON_COLOR_LABEL]]; + UIAlertView *alert = [self buildColorAlertViewWithTitle: [MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_POLYGON_COLOR_LABEL]]; alert.tag = TAG_POLYGON_COLOR; [alert show]; } - (IBAction)polygonFillColorButton:(id)sender { - UIAlertView *alert = [self buildColorAlertViewWithTitle: [GPKGSProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_POLYGON_FILL_COLOR_LABEL]]; + UIAlertView *alert = [self buildColorAlertViewWithTitle: [MCProperties getValueOfProperty:GPKGS_PROP_FEATURE_TILES_DRAW_POLYGON_FILL_COLOR_LABEL]]; alert.tag = TAG_POLYGON_FILL_COLOR; [alert show]; } @@ -278,7 +278,7 @@ - (UIAlertView *)buildColorAlertViewWithTitle: (NSString *) title{ for (NSString *option in options) { [alert addButtonWithTitle:option]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; return alert; } diff --git a/mapcache-ios/ui/GPKGSGenerateTilesData.h b/mapcache-ios/ui/GPKGSGenerateTilesData.h index ff722f4..7b546ba 100644 --- a/mapcache-ios/ui/GPKGSGenerateTilesData.h +++ b/mapcache-ios/ui/GPKGSGenerateTilesData.h @@ -20,7 +20,7 @@ @property (nonatomic) enum GPKGCompressFormat compressFormat; @property (nonatomic, strong) NSNumber * compressQuality; @property (nonatomic, strong) NSNumber * compressScale; -@property (nonatomic) BOOL standardWebMercatorFormat; +@property (nonatomic) BOOL xyzTiles; @property (nonatomic, strong) GPKGBoundingBox * boundingBox; -(instancetype) init; diff --git a/mapcache-ios/ui/GPKGSGenerateTilesData.m b/mapcache-ios/ui/GPKGSGenerateTilesData.m index 1d7de3b..919759c 100644 --- a/mapcache-ios/ui/GPKGSGenerateTilesData.m +++ b/mapcache-ios/ui/GPKGSGenerateTilesData.m @@ -14,7 +14,7 @@ -(instancetype) init{ self = [super init]; if(self){ self.compressFormat = GPKG_CF_NONE; - self.standardWebMercatorFormat = false; + self.xyzTiles = false; self.setZooms = true; } return self; diff --git a/mapcache-ios/ui/GPKGSGenerateTilesViewController.m b/mapcache-ios/ui/GPKGSGenerateTilesViewController.m index e752e14..0c9f84f 100644 --- a/mapcache-ios/ui/GPKGSGenerateTilesViewController.m +++ b/mapcache-ios/ui/GPKGSGenerateTilesViewController.m @@ -8,17 +8,17 @@ #import "GPKGSGenerateTilesViewController.h" #import "GPKGSBoundingBoxViewController.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSDecimalValidator.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCDecimalValidator.h" NSString * const GPKGS_GENERATE_TILES_SEG_BOUNDING_BOX = @"boundingBox"; @interface GPKGSGenerateTilesViewController () -@property (nonatomic, strong) GPKGSDecimalValidator * zoomValidator; -@property (nonatomic, strong) GPKGSDecimalValidator * percentageValidator; +@property (nonatomic, strong) MCDecimalValidator * zoomValidator; +@property (nonatomic, strong) MCDecimalValidator * percentageValidator; @property (nonatomic, strong) NSNumberFormatter * numberFormatter; @end @@ -31,10 +31,10 @@ - (void)viewDidLoad { self.numberFormatter = [[NSNumberFormatter alloc] init]; self.numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; - NSNumber * minZoomValidation = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MIN_ZOOM_DEFAULT]; - NSNumber * maxZoomValidation = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT]; - self.zoomValidator = [[GPKGSDecimalValidator alloc] initWithMinimumNumber:minZoomValidation andMaximumNumber:maxZoomValidation]; - self.percentageValidator = [[GPKGSDecimalValidator alloc] initWithMinimumInt:0 andMaximumInt:100]; + NSNumber * minZoomValidation = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MIN_ZOOM_DEFAULT]; + NSNumber * maxZoomValidation = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_MAX_ZOOM_DEFAULT]; + self.zoomValidator = [[MCDecimalValidator alloc] initWithMinimumNumber:minZoomValidation andMaximumNumber:maxZoomValidation]; + self.percentageValidator = [[MCDecimalValidator alloc] initWithMinimumInt:0 andMaximumInt:100]; [self.minZoomTextField setDelegate:self.zoomValidator]; [self.maxZoomTextField setDelegate:self.zoomValidator]; @@ -44,12 +44,12 @@ - (void)viewDidLoad { if(self.data != nil){ if(self.data.minZoom == nil){ - self.data.minZoom = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_DEFAULT_MIN_ZOOM_DEFAULT]; + self.data.minZoom = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_DEFAULT_MIN_ZOOM_DEFAULT]; } [self.minZoomTextField setText:[self.data.minZoom stringValue]]; if(self.data.maxZoom == nil){ - self.data.maxZoom = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_DEFAULT_MAX_ZOOM_DEFAULT]; + self.data.maxZoom = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_DEFAULT_MAX_ZOOM_DEFAULT]; } [self.maxZoomTextField setText:[self.data.maxZoom stringValue]]; @@ -63,18 +63,18 @@ - (void)viewDidLoad { } if(self.data.compressQuality == nil){ - self.data.compressQuality = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_COMPRESS_QUALITY_DEFAULT]; + self.data.compressQuality = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_COMPRESS_QUALITY_DEFAULT]; } [self.compressQualityTextField setText:[self.data.compressQuality stringValue]]; if(self.data.compressScale == nil){ - self.data.compressScale = [GPKGSProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_COMPRESS_SCALE_DEFAULT]; + self.data.compressScale = [MCProperties getNumberValueOfProperty:GPKGS_PROP_LOAD_TILES_COMPRESS_SCALE_DEFAULT]; } [self.compressScaleTextField setText:[self.data.compressScale stringValue]]; } - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.minZoomTextField.inputAccessoryView = keyboardToolbar; self.maxZoomTextField.inputAccessoryView = keyboardToolbar; @@ -133,10 +133,10 @@ - (IBAction)compressScaleChanged:(id)sender { - (IBAction)tileFormatChanged:(id)sender { switch (self.tileFormatSegmentedControl.selectedSegmentIndex){ case 0: - self.data.standardWebMercatorFormat = false; + self.data.xyzTiles = false; break; case 1: - self.data.standardWebMercatorFormat = true; + self.data.xyzTiles = true; break; } } diff --git a/mapcache-ios/ui/GPKGSLoadTilesViewController.m b/mapcache-ios/ui/GPKGSLoadTilesViewController.m index e503044..47bd1d0 100644 --- a/mapcache-ios/ui/GPKGSLoadTilesViewController.m +++ b/mapcache-ios/ui/GPKGSLoadTilesViewController.m @@ -8,10 +8,10 @@ #import "GPKGSLoadTilesViewController.h" #import "GPKGSGenerateTilesViewController.h" -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" -#import "GPKGSDecimalValidator.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" +#import "MCDecimalValidator.h" NSString * const GPKGS_LOAD_TILES_SEG_GENERATE_TILES = @"generateTiles"; @@ -19,7 +19,7 @@ @interface GPKGSLoadTilesViewController () @property (nonatomic, strong) NSArray * urls; @property (nonatomic, strong) GPKGSGenerateTilesViewController *generateTilesViewController; -@property (nonatomic, strong) GPKGSDecimalValidator * epsgValidator; +@property (nonatomic, strong) MCDecimalValidator * epsgValidator; @end @@ -30,12 +30,12 @@ @implementation GPKGSLoadTilesViewController - (void)viewDidLoad { [super viewDidLoad]; - self.urls = [GPKGSProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_TILE_URLS]; + self.urls = [MCProperties getArrayOfProperty:GPKGS_PROP_PRELOADED_TILE_URLS]; - self.epsgValidator = [[GPKGSDecimalValidator alloc] initWithMinimumInt:-1 andMaximumInt:99999]; + self.epsgValidator = [[MCDecimalValidator alloc] initWithMinimumInt:-1 andMaximumInt:99999]; [self.epsgTextField setDelegate:self.epsgValidator]; - UIToolbar *keyboardToolbar = [GPKGSUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; + UIToolbar *keyboardToolbar = [MCUtils buildKeyboardDoneToolbarWithTarget:self andAction:@selector(doneButtonPressed)]; self.urlTextField.inputAccessoryView = keyboardToolbar; self.epsgTextField.inputAccessoryView = keyboardToolbar; @@ -95,7 +95,7 @@ - (IBAction)preloadedUrlsButton:(id)sender { } UIAlertView *alert = [[UIAlertView alloc] - initWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_LOAD_TILES_PRELOADED_LABEL] + initWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_LOAD_TILES_PRELOADED_LABEL] message:nil delegate:self cancelButtonTitle:nil @@ -104,7 +104,7 @@ - (IBAction)preloadedUrlsButton:(id)sender { for (NSString *urlLabel in urlLabels) { [alert addButtonWithTitle:urlLabel]; } - alert.cancelButtonIndex = [alert addButtonWithTitle:[GPKGSProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; + alert.cancelButtonIndex = [alert addButtonWithTitle:[MCProperties getValueOfProperty:GPKGS_PROP_CANCEL_LABEL]]; alert.tag = TAG_PRELOADED_URLS; diff --git a/mapcache-ios/util/MCColorUtil.h b/mapcache-ios/util/MCColorUtil.h index ca31f35..1542b12 100644 --- a/mapcache-ios/util/MCColorUtil.h +++ b/mapcache-ios/util/MCColorUtil.h @@ -21,20 +21,5 @@ + (UIColor *) getAccentLight; + (UIColor *) getMediumGrey; - -//+ (UIColor *) getBackgroundColor; -//- (UIColor *) getDanger; -//- (UIColor *) getWarning; -//- (UIColor *) getSuccess; -//- (UIColor *) getInfo; - -@property (nonatomic, strong) UIColor *primaryColor; -@property (nonatomic, strong) UIColor *primaryLightColor; -@property (nonatomic, strong) UIColor *accentColor; -@property (nonatomic, strong) UIColor *accentLightColor; -@property (nonatomic, strong) UIColor *mediumGreyColorColor; -@property (nonatomic, strong) UIColor *polygonFillColor; -@property (nonatomic, strong) UIColor *polygonStrokeColor; -@property (nonatomic, strong) UIColor *boundingBoxColor; -@property (nonatomic, strong) UIColor *polylineColor; ++ (UIColor *) getLightGrey; @end diff --git a/mapcache-ios/util/MCColorUtil.m b/mapcache-ios/util/MCColorUtil.m index 029dd40..b97dcf7 100644 --- a/mapcache-ios/util/MCColorUtil.m +++ b/mapcache-ios/util/MCColorUtil.m @@ -27,17 +27,22 @@ + (UIColor *) getPrimaryLight { + (UIColor *) getAccent { - return [UIColor colorWithRed:0.28f green:0.69f blue:0.71f alpha:1]; + return [UIColor colorWithRed:36.0/255.0 green:169.0/255.0 blue:176.0/255.0 alpha:1.0]; } + (UIColor *) getAccentLight { - return [UIColor colorWithRed:0.51f green:0.78f blue:0.8f alpha:1]; + return [UIColor colorWithRed:0.51f green:0.78f blue:0.8f alpha:0.85]; } + (UIColor *) getMediumGrey { - return [UIColor colorWithRed:(229/255.0) green:(230/255.0) blue:(230/255.0) alpha:1]; + return [UIColor colorWithRed:(215/255.0) green:(215/255.0) blue:(215/255.0) alpha:1]; +} + + ++ (UIColor *) getLightGrey { + return [UIColor colorWithRed:(240/255.0) green:(240/255.0) blue:(240/255.0) alpha:1]; } diff --git a/mapcache-ios/util/GPKGSConstants.h b/mapcache-ios/util/MCConstants.h similarity index 98% rename from mapcache-ios/util/GPKGSConstants.h rename to mapcache-ios/util/MCConstants.h index 92b792c..c94d98e 100644 --- a/mapcache-ios/util/GPKGSConstants.h +++ b/mapcache-ios/util/MCConstants.h @@ -10,6 +10,7 @@ extern NSString * const GPKGS_MAPCACHE_RESOURCES_PROPERTIES; extern NSString * const GPKGS_ANIMATE_SCREEN_TOUCHES; +extern NSString * const MC_GEOPACKAGE_MODIFIED_NOTIFICATION; extern NSString * const GPKGS_IMPORT_GEOPACKAGE_NOTIFICATION; extern NSString * const GPKGS_CELL_DATABASE; extern NSString * const GPKGS_CELL_TABLE; @@ -189,7 +190,8 @@ extern NSString * const GPKGS_ACTION_DELETE; extern NSString * const GPKGS_ACTION_SHARE; extern NSString * const GPKGS_ACTION_NEW_LAYER; extern NSString * const GPKGS_ACTION_NEW_FEATURE_LAYER; +extern NSString * const NGA_DRAWER_VIEW_SPACE_FROM_TOP; -@interface GPKGSConstants : NSObject +@interface MCConstants : NSObject @end diff --git a/mapcache-ios/util/GPKGSConstants.m b/mapcache-ios/util/MCConstants.m similarity index 98% rename from mapcache-ios/util/GPKGSConstants.m rename to mapcache-ios/util/MCConstants.m index a99a8dd..606bc9f 100644 --- a/mapcache-ios/util/GPKGSConstants.m +++ b/mapcache-ios/util/MCConstants.m @@ -6,10 +6,11 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSConstants.h" +#import "MCConstants.h" NSString * const GPKGS_MAPCACHE_RESOURCES_PROPERTIES = @"mapcache"; NSString * const GPKGS_ANIMATE_SCREEN_TOUCHES = @"animate_screen_touches"; +NSString * const MC_GEOPACKAGE_MODIFIED_NOTIFICATION = @"ReloadGeoPacakgeList"; NSString * const GPKGS_IMPORT_GEOPACKAGE_NOTIFICATION = @"ImportGeoPackageNotification"; NSString * const GPKGS_CELL_DATABASE = @"GeoPackageDatabaseCell"; NSString * const GPKGS_CELL_TABLE = @"GeoPackageTableCell"; @@ -189,7 +190,8 @@ NSString * const GPKGS_ACTION_SHARE = @"action_share"; NSString * const GPKGS_ACTION_NEW_LAYER = @"action_new_layer"; NSString * const GPKGS_ACTION_NEW_FEATURE_LAYER = @"action_new_feature_layer"; +NSString * const NGA_DRAWER_VIEW_SPACE_FROM_TOP = @"nga_drawer_view_space_from_top"; -@implementation GPKGSConstants +@implementation MCConstants @end diff --git a/mapcache-ios/util/GPKGSDecimalValidator.h b/mapcache-ios/util/MCDecimalValidator.h similarity index 91% rename from mapcache-ios/util/GPKGSDecimalValidator.h rename to mapcache-ios/util/MCDecimalValidator.h index 785420e..96b63f8 100644 --- a/mapcache-ios/util/GPKGSDecimalValidator.h +++ b/mapcache-ios/util/MCDecimalValidator.h @@ -8,7 +8,7 @@ #import -@interface GPKGSDecimalValidator : NSObject +@interface MCDecimalValidator : NSObject @property (nonatomic, strong) NSDecimalNumber *min; @property (nonatomic, strong) NSDecimalNumber *max; diff --git a/mapcache-ios/util/GPKGSDecimalValidator.m b/mapcache-ios/util/MCDecimalValidator.m similarity index 94% rename from mapcache-ios/util/GPKGSDecimalValidator.m rename to mapcache-ios/util/MCDecimalValidator.m index 80cbbe7..6c584db 100644 --- a/mapcache-ios/util/GPKGSDecimalValidator.m +++ b/mapcache-ios/util/MCDecimalValidator.m @@ -6,13 +6,13 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSDecimalValidator.h" +#import "MCDecimalValidator.h" -@interface GPKGSDecimalValidator () +@interface MCDecimalValidator () @end -@implementation GPKGSDecimalValidator +@implementation MCDecimalValidator -(instancetype) initWithMinimum: (NSDecimalNumber *) minimum andMaximum: (NSDecimalNumber *) maximum{ self = [super init]; diff --git a/mapcache-ios/util/GPKGSProperties.h b/mapcache-ios/util/MCProperties.h similarity index 92% rename from mapcache-ios/util/GPKGSProperties.h rename to mapcache-ios/util/MCProperties.h index 9034a54..641c1c9 100644 --- a/mapcache-ios/util/GPKGSProperties.h +++ b/mapcache-ios/util/MCProperties.h @@ -8,7 +8,7 @@ #import -@interface GPKGSProperties : NSObject +@interface MCProperties : NSObject +(NSString *) getValueOfProperty: (NSString *) property; diff --git a/mapcache-ios/util/GPKGSProperties.m b/mapcache-ios/util/MCProperties.m similarity index 90% rename from mapcache-ios/util/GPKGSProperties.m rename to mapcache-ios/util/MCProperties.m index 00204d4..3773afd 100644 --- a/mapcache-ios/util/GPKGSProperties.m +++ b/mapcache-ios/util/MCProperties.m @@ -6,13 +6,13 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCProperties.h" +#import "MCConstants.h" #import "GPKGIOUtils.h" static NSDictionary * properties; -@implementation GPKGSProperties +@implementation MCProperties +(NSString *) getValueOfProperty: (NSString *) property{ @@ -81,7 +81,7 @@ +(BOOL) getBoolOfProperty: (NSString *) property{ +(void) loadProperties{ if(properties == nil){ - NSString * propertiesPath = [GPKGIOUtils getPropertyListPathWithName:GPKGS_MAPCACHE_RESOURCES_PROPERTIES]; + NSString * propertiesPath = [GPKGIOUtils propertyListPathWithName:GPKGS_MAPCACHE_RESOURCES_PROPERTIES]; properties = [NSDictionary dictionaryWithContentsOfFile:propertiesPath]; } } diff --git a/mapcache-ios/util/GPKGSUtils.h b/mapcache-ios/util/MCUtils.h similarity index 95% rename from mapcache-ios/util/GPKGSUtils.h rename to mapcache-ios/util/MCUtils.h index 5c18127..dfec626 100644 --- a/mapcache-ios/util/GPKGSUtils.h +++ b/mapcache-ios/util/MCUtils.h @@ -9,7 +9,7 @@ #import #import -@interface GPKGSUtils : NSObject +@interface MCUtils : NSObject +(void) showMessageWithDelegate: (id) delegate andTitle: (NSString *) title andMessage: (NSString *) message; diff --git a/mapcache-ios/util/GPKGSUtils.m b/mapcache-ios/util/MCUtils.m similarity index 90% rename from mapcache-ios/util/GPKGSUtils.m rename to mapcache-ios/util/MCUtils.m index 1ccf6a7..7ef02b1 100644 --- a/mapcache-ios/util/GPKGSUtils.m +++ b/mapcache-ios/util/MCUtils.m @@ -6,11 +6,11 @@ // Copyright (c) 2015 NGA. All rights reserved. // -#import "GPKGSUtils.h" -#import "GPKGSProperties.h" -#import "GPKGSConstants.h" +#import "MCUtils.h" +#import "MCProperties.h" +#import "MCConstants.h" -@implementation GPKGSUtils +@implementation MCUtils +(void) showMessageWithDelegate: (id) delegate andTitle: (NSString *) title andMessage: (NSString *) message{ UIAlertView *alert = [[UIAlertView alloc] @@ -18,7 +18,7 @@ +(void) showMessageWithDelegate: (id) delegate andTitle: (NSString *) title andM message:message delegate:delegate cancelButtonTitle:nil - otherButtonTitles:[GPKGSProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], + otherButtonTitles:[MCProperties getValueOfProperty:GPKGS_PROP_OK_LABEL], nil]; [alert show]; } diff --git a/mapcache-ios/util/UITextField+Validators.h b/mapcache-ios/util/UITextField+Validators.h index 0186b5c..e9f535f 100644 --- a/mapcache-ios/util/UITextField+Validators.h +++ b/mapcache-ios/util/UITextField+Validators.h @@ -7,13 +7,15 @@ // #import +#import "GPKGDataTypes.h" NS_ASSUME_NONNULL_BEGIN @interface UITextField (Validators) - (void)isValidTileServerURL:(UITextField *)textField withResult:(void(^)(BOOL isValid))resultBlock; - (void)isValidGeoPackageURL:(UITextField *)textField withResult:(void(^)(BOOL isValid))resultBlock; -- (void)trimWhiteSpace:(UITextField *)textField; +- (void)trimWhiteSpace; +- (BOOL)fieldValueValidForType:(enum GPKGDataType) dataType; @end NS_ASSUME_NONNULL_END diff --git a/mapcache-ios/util/UITextField+Validators.m b/mapcache-ios/util/UITextField+Validators.m index 2f2553b..de33d4f 100644 --- a/mapcache-ios/util/UITextField+Validators.m +++ b/mapcache-ios/util/UITextField+Validators.m @@ -89,9 +89,45 @@ - (void)isValidGeoPackageURL:(UITextField *)textField withResult:(void(^)(BOOL i } -- (void)trimWhiteSpace:(UITextField *)textField { - textField.text = [textField.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; +- (void)trimWhiteSpace { + self.text = [self.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; } +- (BOOL)fieldValueValidForType:(enum GPKGDataType) dataType { + BOOL isValid = YES; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + NSDecimalNumber *dn; + + switch(dataType) { + case GPKG_DT_BOOLEAN: + case GPKG_DT_TINYINT: + case GPKG_DT_SMALLINT: + case GPKG_DT_MEDIUMINT: + case GPKG_DT_INT: + case GPKG_DT_INTEGER: + // NSNumber + isValid = [numberFormatter numberFromString:self.text] == nil ? NO : YES; + break; + case GPKG_DT_FLOAT: + case GPKG_DT_DOUBLE: + case GPKG_DT_REAL: + // NSDecimalNumber + dn = [[NSDecimalNumber alloc] initWithString:self.text]; + isValid = dn == [NSDecimalNumber notANumber] ? NO : YES; + break; + case GPKG_DT_TEXT: + // NSString + isValid = self.text != nil; + break; + case GPKG_DT_BLOB: // not alowing editing for these types yet + case GPKG_DT_DATE: + case GPKG_DT_DATETIME: + // NSDate class + break; + } + + return isValid; +} + @end diff --git a/mapcache-ios/views/DisplayCells/MCButtonCell.xib b/mapcache-ios/views/DisplayCells/MCButtonCell.xib index 3eb1732..18c4739 100644 --- a/mapcache-ios/views/DisplayCells/MCButtonCell.xib +++ b/mapcache-ios/views/DisplayCells/MCButtonCell.xib @@ -1,11 +1,9 @@ - - - - + + - + @@ -47,7 +45,7 @@ - + diff --git a/mapcache-ios/views/DisplayCells/MCDualButtonCell.h b/mapcache-ios/views/DisplayCells/MCDualButtonCell.h new file mode 100644 index 0000000..4df4eb2 --- /dev/null +++ b/mapcache-ios/views/DisplayCells/MCDualButtonCell.h @@ -0,0 +1,35 @@ +// +// MCDualButtonCell.h +// mapcache-ios +// +// Created by Tyler Burgett on 2/21/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import +#import "MCColorUtil.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol MCDualButtonCellDelegate +- (void)performDualButtonAction: (NSString *) action; +@end + +@interface MCDualButtonCell : UITableViewCell +@property (nonatomic, weak) id dualButtonDelegate; +@property (nonatomic, weak) IBOutlet UIButton *leftButton; +@property (nonatomic, weak) IBOutlet UIButton *rightButton; +@property (nonatomic, strong) NSString *leftButtonAction; +@property (nonatomic, strong) NSString *rightButtonAction; + +- (void)setLeftButtonLabel: (NSString *) text; +- (void)setRightButtonLabel: (NSString *) text; +- (void)enableLeftButton; +- (void)enableRightButton; +- (void)disableLeftButton; +- (void)disableRightButton; +- (void)disableButtons; +- (void)enableButtons; +@end + +NS_ASSUME_NONNULL_END diff --git a/mapcache-ios/views/DisplayCells/MCDualButtonCell.m b/mapcache-ios/views/DisplayCells/MCDualButtonCell.m new file mode 100644 index 0000000..0433a20 --- /dev/null +++ b/mapcache-ios/views/DisplayCells/MCDualButtonCell.m @@ -0,0 +1,86 @@ +// +// MCDualButtonCell.m +// mapcache-ios +// +// Created by Tyler Burgett on 2/21/20. +// Copyright © 2020 NGA. All rights reserved. +// + +#import "MCDualButtonCell.h" + +@implementation MCDualButtonCell + +- (void)awakeFromNib { + [super awakeFromNib]; + [self setBackgroundColor:[UIColor clearColor]]; + [self setSelectionStyle:UITableViewCellSelectionStyleNone]; + // Initialization code +} + + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; +} + + +- (IBAction)leftButtonPressed:(id)sender { + [_dualButtonDelegate performDualButtonAction:self.leftButtonAction]; +} + + +- (IBAction)rightButtonPressed:(id)sender { + [_dualButtonDelegate performDualButtonAction:self.rightButtonAction]; +} + + +- (void)setLeftButtonLabel: (NSString *) text { + [_leftButton setTitle:text forState:UIControlStateNormal]; +} + + +- (void)setRightButtonLabel: (NSString *) text { + [_rightButton setTitle:text forState:UIControlStateNormal]; +} + + +- (void)enableLeftButton { + [_leftButton setEnabled: YES]; + [_leftButton setBackgroundColor:[MCColorUtil getMediumGrey]]; +} + + +- (void)enableRightButton { + [_rightButton setEnabled: YES]; + [_rightButton setBackgroundColor:[MCColorUtil getAccent]]; +} + + +- (void)disableLeftButton { + [_leftButton setEnabled: NO]; + [_leftButton setBackgroundColor:[MCColorUtil getLightGrey]]; +} + + +- (void)disableRightButton { + [_rightButton setEnabled: NO]; + [_rightButton setBackgroundColor:[MCColorUtil getAccentLight]]; +} + + +- (void)disableButtons { + [_leftButton setEnabled: NO]; + [_leftButton setBackgroundColor:[MCColorUtil getLightGrey]]; + [_rightButton setEnabled: NO]; + [_rightButton setBackgroundColor:[MCColorUtil getAccentLight]]; +} + + +- (void)enableButtons { + [_leftButton setEnabled: YES]; + [_leftButton setBackgroundColor:[MCColorUtil getMediumGrey]]; + [_rightButton setEnabled: YES]; + [_rightButton setBackgroundColor:[MCColorUtil getAccent]]; +} + + +@end diff --git a/mapcache-ios/views/DisplayCells/MCDualButtonCell.xib b/mapcache-ios/views/DisplayCells/MCDualButtonCell.xib new file mode 100644 index 0000000..11a4fd0 --- /dev/null +++ b/mapcache-ios/views/DisplayCells/MCDualButtonCell.xib @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mapcache-ios/views/DisplayCells/MCEmptyStateCell.xib b/mapcache-ios/views/DisplayCells/MCEmptyStateCell.xib index 18e2d00..3b86331 100644 --- a/mapcache-ios/views/DisplayCells/MCEmptyStateCell.xib +++ b/mapcache-ios/views/DisplayCells/MCEmptyStateCell.xib @@ -1,10 +1,9 @@ - - - - + + - + + @@ -56,6 +55,11 @@ + + + + + diff --git a/mapcache-ios/views/DisplayCells/MCFeatureLayerOperationsCell.xib b/mapcache-ios/views/DisplayCells/MCFeatureLayerOperationsCell.xib index ce7c4ac..53c548e 100644 --- a/mapcache-ios/views/DisplayCells/MCFeatureLayerOperationsCell.xib +++ b/mapcache-ios/views/DisplayCells/MCFeatureLayerOperationsCell.xib @@ -1,11 +1,9 @@ - - - - + + - + @@ -20,10 +18,10 @@ - - - + + + @@ -97,7 +62,5 @@ - - diff --git a/mapcache-ios/views/DisplayCells/MCGeoPackageCell.xib b/mapcache-ios/views/DisplayCells/MCGeoPackageCell.xib index 8682052..f5fa874 100644 --- a/mapcache-ios/views/DisplayCells/MCGeoPackageCell.xib +++ b/mapcache-ios/views/DisplayCells/MCGeoPackageCell.xib @@ -1,9 +1,9 @@ - + - + @@ -39,7 +39,7 @@ - + - + - diff --git a/mapcache-ios/views/MCGeoPackageList.xib b/mapcache-ios/views/MCGeoPackageList.xib index 37199d8..f70d594 100644 --- a/mapcache-ios/views/MCGeoPackageList.xib +++ b/mapcache-ios/views/MCGeoPackageList.xib @@ -1,15 +1,17 @@ - + - + + + diff --git a/mapcache-ios/views/MCSingleGeoPackageView.xib b/mapcache-ios/views/MCSingleGeoPackageView.xib deleted file mode 100644 index a05529f..0000000 --- a/mapcache-ios/views/MCSingleGeoPackageView.xib +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -