diff --git a/Example Apps/Example ObjC/MenuManager.m b/Example Apps/Example ObjC/MenuManager.m index 308a66eee..ec9d221b3 100644 --- a/Example Apps/Example ObjC/MenuManager.m +++ b/Example Apps/Example ObjC/MenuManager.m @@ -58,7 +58,7 @@ + (SDLMenuCell *)sdlex_menuCellGetAllVehicleDataWithManager:(SDLManager *)manage [submenuItems addObject:cell]; } - return [[SDLMenuCell alloc] initWithTitle:ACGetAllVehicleDataMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:CarBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] subCells:submenuItems]; + return [[SDLMenuCell alloc] initWithTitle:ACGetAllVehicleDataMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:CarBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] submenuLayout:SDLMenuLayoutTiles subCells:submenuItems]; } + (NSArray *)sdlex_allVehicleDataTypes { @@ -117,7 +117,7 @@ + (SDLMenuCell *)sdlex_menuCellChangeTemplateWithManager:(SDLManager *)manager { }]; [submenuItems addObject:cell2]; - return [[SDLMenuCell alloc] initWithTitle:ACSubmenuTemplateMenuName icon:nil subCells:[submenuItems copy]]; + return [[SDLMenuCell alloc] initWithTitle:ACSubmenuTemplateMenuName icon:nil submenuLayout:SDLMenuLayoutList subCells:[submenuItems copy]]; } + (SDLMenuCell *)sdlex_menuCellWithSubmenuWithManager:(SDLManager *)manager { @@ -129,7 +129,7 @@ + (SDLMenuCell *)sdlex_menuCellWithSubmenuWithManager:(SDLManager *)manager { [submenuItems addObject:cell]; } - return [[SDLMenuCell alloc] initWithTitle:ACSubmenuMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] subCells:[submenuItems copy]]; + return [[SDLMenuCell alloc] initWithTitle:ACSubmenuMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] submenuLayout:SDLMenuLayoutList subCells:[submenuItems copy]]; } + (SDLMenuCell *)sdlex_sliderMenuCellWithManager:(SDLManager *)manager { diff --git a/Example Apps/Example Swift/MenuManager.swift b/Example Apps/Example Swift/MenuManager.swift index 89ae1c741..f87b66099 100644 --- a/Example Apps/Example Swift/MenuManager.swift +++ b/Example Apps/Example Swift/MenuManager.swift @@ -67,7 +67,7 @@ private extension MenuManager { }) } - return SDLMenuCell(title: ACGetAllVehicleDataMenuName, icon: SDLArtwork(image: UIImage(named: CarBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), subCells: submenuItems) + return SDLMenuCell(title: ACGetAllVehicleDataMenuName, submenuLayout: .tiles, icon: SDLArtwork(image: UIImage(named: CarBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), subCells: submenuItems) } /// A list of all possible vehicle data types @@ -151,7 +151,7 @@ private extension MenuManager { } })) - return SDLMenuCell(title: ACSubmenuTemplateMenuName, icon: nil, subCells: submenuItems) + return SDLMenuCell(title: ACSubmenuTemplateMenuName, submenuLayout: .list, icon: nil, subCells: submenuItems) } /// Menu item that opens a submenu when selected @@ -174,7 +174,7 @@ private extension MenuManager { })) } - return SDLMenuCell(title: ACSubmenuMenuName, icon: SDLArtwork(image: #imageLiteral(resourceName: "choice_set").withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), subCells: submenuItems) + return SDLMenuCell(title: ACSubmenuMenuName, submenuLayout: .list, icon: SDLArtwork(image: #imageLiteral(resourceName: "choice_set").withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), subCells: submenuItems) } private class func sliderMenuCell(with manager: SDLManager) -> SDLMenuCell { diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index ede06fda0..284577fc8 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -217,6 +217,8 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLMediaServiceManifest.h', 'SmartDeviceLink/SDLMediaType.h', 'SmartDeviceLink/SDLMenuCell.h', +'SmartDeviceLink/SDLMenuConfiguration.h', +'SmartDeviceLink/SDLMenuLayout.h', 'SmartDeviceLink/SDLMenuManagerConstants.h', 'SmartDeviceLink/SDLMenuParams.h', 'SmartDeviceLink/SDLMetadataTags.h', diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 18765fcd2..7e98d9a5b 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -1028,6 +1028,12 @@ 5D75960D22972F830013207C /* TestSystemCapabilityObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D75960C22972F830013207C /* TestSystemCapabilityObserver.m */; }; 5D75961122972FCA0013207C /* SDLSystemCapabilityObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D75960F22972FCA0013207C /* SDLSystemCapabilityObserver.h */; }; 5D75961222972FCA0013207C /* SDLSystemCapabilityObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D75961022972FCA0013207C /* SDLSystemCapabilityObserver.m */; }; + 5D76750E22D8FB3700E8D71A /* SDLMenuLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D76750C22D8FB3700E8D71A /* SDLMenuLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5D76750F22D8FB3700E8D71A /* SDLMenuLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D76750D22D8FB3700E8D71A /* SDLMenuLayout.m */; }; + 5D76751322D9088F00E8D71A /* SDLMenuConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D76751122D9088F00E8D71A /* SDLMenuConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5D76751422D9088F00E8D71A /* SDLMenuConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D76751222D9088F00E8D71A /* SDLMenuConfiguration.m */; }; + 5D76751622D920FD00E8D71A /* SDLMenuConfigurationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D76751522D920FD00E8D71A /* SDLMenuConfigurationSpec.m */; }; + 5D76751822D921CB00E8D71A /* SDLMenuLayoutSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D76751722D921CB00E8D71A /* SDLMenuLayoutSpec.m */; }; 5D76E31C1D3805FF00647CFA /* SDLLockScreenManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D76E31B1D3805FF00647CFA /* SDLLockScreenManagerSpec.m */; }; 5D76E3211D39742300647CFA /* SDLViewControllerPresentable.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D76E3201D39742300647CFA /* SDLViewControllerPresentable.h */; }; 5D76E3241D39767000647CFA /* SDLLockScreenPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D76E3221D39767000647CFA /* SDLLockScreenPresenter.h */; }; @@ -2761,6 +2767,12 @@ 5D75960C22972F830013207C /* TestSystemCapabilityObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TestSystemCapabilityObserver.m; path = DevAPISpecs/TestSystemCapabilityObserver.m; sourceTree = ""; }; 5D75960F22972FCA0013207C /* SDLSystemCapabilityObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLSystemCapabilityObserver.h; sourceTree = ""; }; 5D75961022972FCA0013207C /* SDLSystemCapabilityObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLSystemCapabilityObserver.m; sourceTree = ""; }; + 5D76750C22D8FB3700E8D71A /* SDLMenuLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLMenuLayout.h; sourceTree = ""; }; + 5D76750D22D8FB3700E8D71A /* SDLMenuLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuLayout.m; sourceTree = ""; }; + 5D76751122D9088F00E8D71A /* SDLMenuConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLMenuConfiguration.h; sourceTree = ""; }; + 5D76751222D9088F00E8D71A /* SDLMenuConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuConfiguration.m; sourceTree = ""; }; + 5D76751522D920FD00E8D71A /* SDLMenuConfigurationSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLMenuConfigurationSpec.m; path = DevAPISpecs/SDLMenuConfigurationSpec.m; sourceTree = ""; }; + 5D76751722D921CB00E8D71A /* SDLMenuLayoutSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuLayoutSpec.m; sourceTree = ""; }; 5D76E31B1D3805FF00647CFA /* SDLLockScreenManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLockScreenManagerSpec.m; path = DevAPISpecs/SDLLockScreenManagerSpec.m; sourceTree = ""; }; 5D76E3201D39742300647CFA /* SDLViewControllerPresentable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLViewControllerPresentable.h; sourceTree = ""; }; 5D76E3221D39767000647CFA /* SDLLockScreenPresenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLockScreenPresenter.h; sourceTree = ""; }; @@ -3460,6 +3472,7 @@ 1EB59CC9202DC8E300343A61 /* SDLMassageZoneSpec.m */, 162E82061A9BDE8A00906325 /* SDLMediaClockFormatSpec.m */, 88E6F1A9220E1720006156F9 /* SDLMediaTypeSpec.m */, + 5D76751722D921CB00E8D71A /* SDLMenuLayoutSpec.m */, 8BBEA6081F324832003EEA26 /* SDLMetadataTypeSpec.m */, 1EB59CC7202DC86A00343A61 /* SDLModuleTypeSpec.m */, 88B58DC822204C9E0011B063 /* SDLNavigationActionSpec.m */, @@ -4020,6 +4033,7 @@ 5D339CE5207C0651000CC364 /* Menu */ = { isa = PBXGroup; children = ( + 5D76751022D907F500E8D71A /* Configuration */, 755F175E229F14F70041B9CB /* Dynamic Menu Update Utilities */, 5D339CEC207C08AB000CC364 /* Cells */, 5D339CF1207C0ACE000CC364 /* SDLMenuManager.h */, @@ -4898,10 +4912,12 @@ 5D61FB0A1A84238A00846EE7 /* SDLMediaClockFormat.m */, 88E6F1A5220E1588006156F9 /* SDLMediaType.h */, 88E6F1A6220E1588006156F9 /* SDLMediaType.m */, - 1E5AD0461F1F773E0029B8AF /* SDLModuleType.h */, - 1E5AD0471F1F773E0029B8AF /* SDLModuleType.m */, + 5D76750C22D8FB3700E8D71A /* SDLMenuLayout.h */, + 5D76750D22D8FB3700E8D71A /* SDLMenuLayout.m */, 8BBEA6041F324165003EEA26 /* SDLMetadataType.h */, 8BBEA6051F324165003EEA26 /* SDLMetadataType.m */, + 1E5AD0461F1F773E0029B8AF /* SDLModuleType.h */, + 1E5AD0471F1F773E0029B8AF /* SDLModuleType.m */, 88B58DC422204AF10011B063 /* SDLNavigationAction.h */, 88B58DC522204AF10011B063 /* SDLNavigationAction.m */, 88B58DBE222045320011B063 /* SDLNavigationJunction.h */, @@ -5353,6 +5369,15 @@ name = Utilities; sourceTree = ""; }; + 5D76751022D907F500E8D71A /* Configuration */ = { + isa = PBXGroup; + children = ( + 5D76751122D9088F00E8D71A /* SDLMenuConfiguration.h */, + 5D76751222D9088F00E8D71A /* SDLMenuConfiguration.m */, + ); + name = Configuration; + sourceTree = ""; + }; 5D76E31A1D3805E600647CFA /* LockScreen */ = { isa = PBXGroup; children = ( @@ -6063,6 +6088,7 @@ 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */, 752ECDB8228C42E100D945F4 /* SDLMenuRunScoreSpec.m */, 752ECDBA228C532600D945F4 /* SDLMenuUpdateAlgorithmSpec.m */, + 5D76751522D920FD00E8D71A /* SDLMenuConfigurationSpec.m */, ); name = Menu; sourceTree = ""; @@ -6681,6 +6707,7 @@ 5D61FC511A84238C00846EE7 /* SDLButtonCapabilities.h in Headers */, 5D61FDE91A84238C00846EE7 /* SDLUnsubscribeButtonResponse.h in Headers */, 5D61FCD51A84238C00846EE7 /* SDLImageType.h in Headers */, + 5D76750E22D8FB3700E8D71A /* SDLMenuLayout.h in Headers */, 8803DCEF22C2B84B00FBB7CE /* SDLBackgroundTaskManager.h in Headers */, 5D61FC2F1A84238C00846EE7 /* SDLAddCommandResponse.h in Headers */, 5D0C2A0020D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h in Headers */, @@ -6697,6 +6724,7 @@ 5D61FD7B1A84238C00846EE7 /* SDLScrollableMessage.h in Headers */, DA9F7E931DCC04E400ACAE48 /* SDLUnsubscribeWayPoints.h in Headers */, 5D61FD3D1A84238C00846EE7 /* SDLPrimaryAudioSource.h in Headers */, + 5D76751322D9088F00E8D71A /* SDLMenuConfiguration.h in Headers */, DAC5725C1D10B81E0004288B /* SDLTouch.h in Headers */, 5D6F7A2E1BC5650B0070BF37 /* SDLLifecycleConfiguration.h in Headers */, 5D61FCCD1A84238C00846EE7 /* SDLImage.h in Headers */, @@ -7515,6 +7543,7 @@ 5D92935F20B33FF700FCC775 /* SDLChoiceSet.m in Sources */, 8855F9E4220CB04000A5C897 /* SDLOnAppServiceData.m in Sources */, 5D61FC321A84238C00846EE7 /* SDLAddSubMenu.m in Sources */, + 5D76751422D9088F00E8D71A /* SDLMenuConfiguration.m in Sources */, 5D61FDF61A84238C00846EE7 /* SDLV1ProtocolHeader.m in Sources */, EE798CA620561218008EDE8E /* SDLSecondaryTransportManager.m in Sources */, 88B58DC1222045320011B063 /* SDLNavigationJunction.m in Sources */, @@ -7560,6 +7589,7 @@ 5D61FD9E1A84238C00846EE7 /* SDLSliderResponse.m in Sources */, 1EAA47462035623B000FE74B /* SDLLightControlData.m in Sources */, 0055412F22D759BD003194D3 /* SDLSeatLocation.m in Sources */, + 5D76750F22D8FB3700E8D71A /* SDLMenuLayout.m in Sources */, 5D61FC5C1A84238C00846EE7 /* SDLChangeRegistration.m in Sources */, 5D1665C91CF8CA3D00CC4CA1 /* SDLPermissionFilter.m in Sources */, 5D61FDBA1A84238C00846EE7 /* SDLSyncPDataResponse.m in Sources */, @@ -7747,12 +7777,14 @@ 162E82FD1A9BDE8B00906325 /* SDLSystemContextSpec.m in Sources */, 162E82E21A9BDE8B00906325 /* SDLIgnitionStableStatusSpec.m in Sources */, 162E82EE1A9BDE8B00906325 /* SDLMediaClockFormatSpec.m in Sources */, + 5D76751822D921CB00E8D71A /* SDLMenuLayoutSpec.m in Sources */, 5DA026901AD44EE700019F86 /* SDLDialNumberResponseSpec.m in Sources */, 162E83901A9BDE8B00906325 /* SDLTireStatusSpec.m in Sources */, 000DD57622EF0971005AB7A7 /* SDLReleaseInteriorVehicleDataModuleResponseSpec.m in Sources */, 162E82E01A9BDE8B00906325 /* SDLHMILevelSpec.m in Sources */, 88F65133220C6DC300CAF321 /* SDLWeatherAlertSpec.m in Sources */, 5DC09EDA1F2F7FEC00F4AB1D /* SDLControlFramePayloadNakSpec.m in Sources */, + 5D76751622D920FD00E8D71A /* SDLMenuConfigurationSpec.m in Sources */, 1EB59CCE202DC97900343A61 /* SDLMassageCushionSpec.m in Sources */, 88EF8EBA22D8F48300CB06C2 /* SDLCancelInteractionSpec.m in Sources */, 162E83041A9BDE8B00906325 /* SDLUpdateModeSpec.m in Sources */, diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index a27254288..84841ee6e 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -218,6 +218,8 @@ sdefault.public_header_files = [ 'SmartDeviceLink/SDLMediaServiceManifest.h', 'SmartDeviceLink/SDLMediaType.h', 'SmartDeviceLink/SDLMenuCell.h', +'SmartDeviceLink/SDLMenuConfiguration.h', +'SmartDeviceLink/SDLMenuLayout.h', 'SmartDeviceLink/SDLMenuManagerConstants.h', 'SmartDeviceLink/SDLMenuParams.h', 'SmartDeviceLink/SDLMetadataTags.h', diff --git a/SmartDeviceLink/SDLAddSubMenu.h b/SmartDeviceLink/SDLAddSubMenu.h index bd5537c2d..338ecd645 100644 --- a/SmartDeviceLink/SDLAddSubMenu.h +++ b/SmartDeviceLink/SDLAddSubMenu.h @@ -3,6 +3,8 @@ #import "SDLRPCRequest.h" +#import "SDLMenuLayout.h" + @class SDLImage; /** @@ -25,9 +27,11 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName; -- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName position:(UInt8)position __deprecated_msg(("Use initWithId:menuName:menuIcon:position: instead")); +- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName position:(UInt8)position __deprecated_msg("Use initWithId:menuName:menuLayout:menuIcon:position: instead"); + +- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName menuIcon:(nullable SDLImage *)icon position:(UInt8)position __deprecated_msg("Use initWithId:menuName:menuLayout:menuIcon:position: instead"); -- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName menuIcon:(nullable SDLImage *)icon position:(UInt8)position; +- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName menuLayout:(nullable SDLMenuLayout)menuLayout menuIcon:(nullable SDLImage *)icon position:(UInt8)position; /** * a Menu ID that identifies a sub menu @@ -68,6 +72,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (strong, nonatomic, nullable) SDLImage *menuIcon; +/** + The sub-menu layout. See available menu layouts on SDLWindowCapability.menuLayoutsAvailable. Defaults to LIST. + */ +@property (strong, nonatomic, nullable) SDLMenuLayout menuLayout; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLAddSubMenu.m b/SmartDeviceLink/SDLAddSubMenu.m index 48ea43c8a..649a10a31 100644 --- a/SmartDeviceLink/SDLAddSubMenu.m +++ b/SmartDeviceLink/SDLAddSubMenu.m @@ -20,28 +20,33 @@ - (instancetype)init { } #pragma clang diagnostic pop -- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName menuIcon:(nullable SDLImage *)icon position:(UInt8)position { - self = [self initWithId:menuId menuName:menuName]; - if (!self) { return nil; } +- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName { + self = [self init]; + if (!self) { + return nil; + } - self.position = @(position); - self.menuIcon = icon; + self.menuID = @(menuId); + self.menuName = menuName; return self; } - (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName position:(UInt8)position { - return [self initWithId:menuId menuName:menuName menuIcon:nil position:position]; + return [self initWithId:menuId menuName:menuName menuLayout:nil menuIcon:nil position:position]; } -- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName { - self = [self init]; - if (!self) { - return nil; - } +- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName menuIcon:(nullable SDLImage *)icon position:(UInt8)position { + return [self initWithId:menuId menuName:menuName menuLayout:nil menuIcon:icon position:position]; +} - self.menuID = @(menuId); - self.menuName = menuName; +- (instancetype)initWithId:(UInt32)menuId menuName:(NSString *)menuName menuLayout:(nullable SDLMenuLayout)menuLayout menuIcon:(nullable SDLImage *)icon position:(UInt8)position { + self = [self initWithId:menuId menuName:menuName]; + if (!self) { return nil; } + + self.position = @(position); + self.menuIcon = icon; + self.menuLayout = menuLayout; return self; } @@ -80,6 +85,14 @@ - (nullable SDLImage *)menuIcon { return [self.parameters sdl_objectForName:SDLRPCParameterNameMenuIcon ofClass:[SDLImage class] error:nil]; } +- (void)setMenuLayout:(nullable SDLMenuLayout)menuLayout { + [self.parameters sdl_setObject:menuLayout forName:SDLRPCParameterNameMenuLayout]; +} + +- (nullable SDLMenuLayout)menuLayout { + return [self.parameters sdl_enumForName:SDLRPCParameterNameMenuLayout error:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLMenuCell.h b/SmartDeviceLink/SDLMenuCell.h index 1c9c8dcbc..5d5d1ea2b 100644 --- a/SmartDeviceLink/SDLMenuCell.h +++ b/SmartDeviceLink/SDLMenuCell.h @@ -8,6 +8,7 @@ #import +#import "SDLMenuLayout.h" #import "SDLTriggerSource.h" @class SDLArtwork; @@ -43,6 +44,11 @@ typedef void(^SDLMenuCellSelectionHandler)(SDLTriggerSource triggerSource); */ @property (copy, nonatomic, readonly, nullable) NSArray *subCells; +/** + The layout in which the `subCells` will be displayed. + */ +@property (strong, nonatomic, readonly, nullable) SDLMenuLayout submenuLayout; + /** Create a menu cell that has no subcells. @@ -71,7 +77,19 @@ typedef void(^SDLMenuCellSelectionHandler)(SDLTriggerSource triggerSource); @param subCells The subcells that will appear when the cell is selected @return The menu cell */ -- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon subCells:(NSArray *)subCells; +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon subCells:(NSArray *)subCells __deprecated_msg("Use initWithTitle:icon:layout:subcells: instead"); + +/** + Create a menu cell that has subcells and when selected will go into a deeper part of the menu + + @param title The cell's primary text + @param icon The cell's image + @param layout The layout that the subCells will be layed out in if that submenu is entered + @param subCells The subcells that will appear when the cell is selected + @return The menu cell + */ +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray *)subCells; + @end diff --git a/SmartDeviceLink/SDLMenuCell.m b/SmartDeviceLink/SDLMenuCell.m index 81ba056bf..67281cb21 100644 --- a/SmartDeviceLink/SDLMenuCell.m +++ b/SmartDeviceLink/SDLMenuCell.m @@ -37,14 +37,19 @@ - (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon } - (instancetype)initWithTitle:(NSString *)title subCells:(NSArray *)subCells { - return [self initWithTitle:title icon:nil subCells:subCells]; + return [self initWithTitle:title icon:nil submenuLayout:nil subCells:subCells]; } - (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon subCells:(NSArray *)subCells { + return [self initWithTitle:title icon:icon submenuLayout:nil subCells:subCells]; +} + +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray *)subCells { self = [super init]; if (!self) { return nil; } _title = title; + _submenuLayout = layout; _icon = icon; _subCells = subCells; @@ -55,7 +60,7 @@ - (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon } - (NSString *)description { - return [NSString stringWithFormat:@"SDLMenuCell: %u-\"%@\", artworkName: %@, voice commands: %lu, isSubcell: %@, hasSubcells: %@", (unsigned int)_cellId, _title, _icon.name, (unsigned long)_voiceCommands.count, (_parentCellId != UINT32_MAX ? @"YES" : @"NO"), (_subCells.count > 0 ? @"YES" : @"NO")]; + return [NSString stringWithFormat:@"SDLMenuCell: %u-\"%@\", artworkName: %@, voice commands: %lu, isSubcell: %@, hasSubcells: %@, submenuLayout: %@", (unsigned int)_cellId, _title, _icon.name, (unsigned long)_voiceCommands.count, (_parentCellId != UINT32_MAX ? @"YES" : @"NO"), (_subCells.count > 0 ? @"YES" : @"NO"), _submenuLayout]; } #pragma mark - Object Equality @@ -69,7 +74,8 @@ - (NSUInteger)hash { return NSUIntRotateCell(self.title.hash, NSUIntBitCell / 2) ^ NSUIntRotateCell(self.icon.name.hash, NSUIntBitCell / 3) ^ NSUIntRotateCell(self.voiceCommands.hash, NSUIntBitCell / 4) - ^ NSUIntRotateCell(self.subCells.count !=0, NSUIntBitCell / 5 ); + ^ NSUIntRotateCell(self.subCells.count !=0, NSUIntBitCell / 5) + ^ NSUIntRotateCell(self.submenuLayout.hash, NSUIntBitCell / 6); } - (BOOL)isEqual:(id)object { diff --git a/SmartDeviceLink/SDLMenuConfiguration.h b/SmartDeviceLink/SDLMenuConfiguration.h new file mode 100644 index 000000000..6aefdb2f4 --- /dev/null +++ b/SmartDeviceLink/SDLMenuConfiguration.h @@ -0,0 +1,36 @@ +// +// SDLMenuConfiguration.h +// SmartDeviceLink +// +// Created by Joel Fischer on 7/12/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLMenuLayout.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLMenuConfiguration : NSObject + +/** + * Changes the default main menu layout. Defaults to `SDLMenuLayoutList`. + */ +@property (strong, nonatomic, readonly) SDLMenuLayout mainMenuLayout; + +/** + * Changes the default submenu layout. To change this for an individual submenu, set the `menuLayout` property on the `SDLMenuCell` initializer for creating a cell with sub-cells. Defaults to `SDLMenuLayoutList`. + */ +@property (strong, nonatomic, readonly) SDLMenuLayout defaultSubmenuLayout; + +/** + Initialize a new menu configuration with a main menu layout and a default submenu layout which can be overriden per-submenu if desired. + + @param mainMenuLayout The new main menu layout + @param defaultSubmenuLayout The new default submenu layout + @return The menu configuration + */ +- (instancetype)initWithMainMenuLayout:(SDLMenuLayout)mainMenuLayout defaultSubmenuLayout:(SDLMenuLayout)defaultSubmenuLayout; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLMenuConfiguration.m b/SmartDeviceLink/SDLMenuConfiguration.m new file mode 100644 index 000000000..2049c83bf --- /dev/null +++ b/SmartDeviceLink/SDLMenuConfiguration.m @@ -0,0 +1,31 @@ +// +// SDLMenuConfiguration.m +// SmartDeviceLink +// +// Created by Joel Fischer on 7/12/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLMenuConfiguration.h" + +@implementation SDLMenuConfiguration + +- (instancetype)init { + return [self initWithMainMenuLayout:SDLMenuLayoutList defaultSubmenuLayout:SDLMenuLayoutList]; +} + +- (instancetype)initWithMainMenuLayout:(SDLMenuLayout)mainMenuLayout defaultSubmenuLayout:(SDLMenuLayout)defaultSubmenuLayout { + self = [super init]; + if (!self) { return nil; } + + _mainMenuLayout = mainMenuLayout; + _defaultSubmenuLayout = defaultSubmenuLayout; + + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"Menu configuration, main menu layout: %@, submenu default layout: %@", _mainMenuLayout, _defaultSubmenuLayout]; +} + +@end diff --git a/SmartDeviceLink/SDLMenuLayout.h b/SmartDeviceLink/SDLMenuLayout.h new file mode 100644 index 000000000..e2fe8e40a --- /dev/null +++ b/SmartDeviceLink/SDLMenuLayout.h @@ -0,0 +1,25 @@ +// +// SDLMenuLayout.h +// SmartDeviceLink +// +// Created by Joel Fischer on 7/12/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLEnum.h" + +/** + * Enum for each type of video streaming protocol, used in VideoStreamingFormat + */ +typedef SDLEnum SDLMenuLayout SDL_SWIFT_ENUM; + +/** + * The menu should be laid out in a scrollable list format with one menu cell below the previous, each is stretched across the view + */ +extern SDLMenuLayout const SDLMenuLayoutList; + +/** + * The menu should be laid out in a scrollable tiles format with each menu cell laid out in a square-ish format next to each other horizontally + */ +extern SDLMenuLayout const SDLMenuLayoutTiles; + diff --git a/SmartDeviceLink/SDLMenuLayout.m b/SmartDeviceLink/SDLMenuLayout.m new file mode 100644 index 000000000..8b1b95b38 --- /dev/null +++ b/SmartDeviceLink/SDLMenuLayout.m @@ -0,0 +1,12 @@ +// +// SDLMenuLayout.m +// SmartDeviceLink +// +// Created by Joel Fischer on 7/12/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLMenuLayout.h" + +SDLMenuLayout const SDLMenuLayoutList = @"LIST"; +SDLMenuLayout const SDLMenuLayoutTiles = @"TILES"; diff --git a/SmartDeviceLink/SDLMenuManager.h b/SmartDeviceLink/SDLMenuManager.h index 84a75170e..54701313b 100644 --- a/SmartDeviceLink/SDLMenuManager.h +++ b/SmartDeviceLink/SDLMenuManager.h @@ -11,6 +11,7 @@ @class SDLFileManager; @class SDLMenuCell; +@class SDLMenuConfiguration; @class SDLSystemCapabilityManager; @class SDLVoiceCommand; @@ -34,6 +35,8 @@ typedef void(^SDLMenuUpdateCompletionHandler)(NSError *__nullable error); */ - (void)stop; +@property (strong, nonatomic) SDLMenuConfiguration *menuConfiguration; + @property (copy, nonatomic) NSArray *menuCells; @property (assign, nonatomic) SDLDynamicMenuUpdatesMode dynamicMenuUpdatesMode; diff --git a/SmartDeviceLink/SDLMenuManager.m b/SmartDeviceLink/SDLMenuManager.m index be83af2e3..aa3a1e22f 100644 --- a/SmartDeviceLink/SDLMenuManager.m +++ b/SmartDeviceLink/SDLMenuManager.m @@ -22,6 +22,7 @@ #import "SDLImage.h" #import "SDLLogMacros.h" #import "SDLMenuCell.h" +#import "SDLMenuConfiguration.h" #import "SDLMenuParams.h" #import "SDLDynamicMenuUpdateRunScore.h" #import "SDLDynamicMenuUpdateAlgorithm.h" @@ -32,6 +33,7 @@ #import "SDLRPCNotificationNotification.h" #import "SDLRPCResponseNotification.h" #import "SDLSetDisplayLayoutResponse.h" +#import "SDLSetGlobalProperties.h" #import "SDLScreenManager.h" #import "SDLShowAppMenu.h" #import "SDLSystemCapabilityManager.h" @@ -51,6 +53,7 @@ @interface SDLMenuCell() @interface SDLMenuManager() +// Dependencies @property (weak, nonatomic) id connectionManager; @property (weak, nonatomic) SDLFileManager *fileManager; @property (weak, nonatomic) SDLSystemCapabilityManager *systemCapabilityManager; @@ -78,6 +81,7 @@ - (instancetype)init { if (!self) { return nil; } _lastMenuId = MenuCellIdMin; + _menuConfiguration = [[SDLMenuConfiguration alloc] init]; _menuCells = @[]; _oldMenuCells = @[]; _dynamicMenuUpdatesMode = SDLDynamicMenuUpdatesModeOnWithCompatibility; @@ -114,6 +118,42 @@ - (void)stop { #pragma mark - Setters +- (void)setMenuConfiguration:(SDLMenuConfiguration *)menuConfiguration { + NSArray *layoutsAvailable = self.systemCapabilityManager.defaultMainWindowCapability.menuLayoutsAvailable; + + if ([[SDLGlobals sharedGlobals].rpcVersion isLessThanVersion:[SDLVersion versionWithMajor:6 minor:0 patch:0]]) { + SDLLogW(@"Menu configurations is only supported on head units with RPC spec version 6.0.0 or later. Currently connected head unit RPC spec version is %@", [SDLGlobals sharedGlobals].rpcVersion); + return; + } else if (layoutsAvailable == nil) { + SDLLogW(@"Could not set the main menu configuration. Which menu layouts can be used is not available"); + return; + } else if (![layoutsAvailable containsObject:menuConfiguration.mainMenuLayout] + || ![layoutsAvailable containsObject:menuConfiguration.defaultSubmenuLayout]) { + SDLLogE(@"One or more of the set menu layouts are not available on this system. The menu configuration will not be set. Available menu layouts: %@, set menu layouts: %@", layoutsAvailable, menuConfiguration); + return; + } else if (self.currentHMILevel == nil + || [self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) { + SDLLogE(@"Could not set main menu configuration, HMI level: %@, required: 'Not-NONE', system context: %@, required: 'Not MENU'", self.currentHMILevel, self.currentSystemContext); + return; + } + + SDLMenuConfiguration *oldConfig = _menuConfiguration; + _menuConfiguration = menuConfiguration; + + SDLSetGlobalProperties *setGlobalsRPC = [[SDLSetGlobalProperties alloc] init]; + setGlobalsRPC.menuLayout = menuConfiguration.mainMenuLayout; + + __weak typeof(self) weakself = self; + [self.connectionManager sendConnectionRequest:setGlobalsRPC withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { + __strong typeof(weakself) strongself = weakself; + if (error != nil) { + SDLLogE(@"Could not set main menu configuration: %@", error); + strongself.menuConfiguration = oldConfig; + return; + } + }]; +} + - (void)setMenuCells:(NSArray *)menuCells { if (self.currentHMILevel == nil || [self.currentHMILevel isEqualToEnum:SDLHMILevelNone] @@ -561,7 +601,15 @@ - (SDLAddCommand *)sdl_commandForMenuCell:(SDLMenuCell *)cell withArtwork:(BOOL) - (SDLAddSubMenu *)sdl_subMenuCommandForMenuCell:(SDLMenuCell *)cell withArtwork:(BOOL)shouldHaveArtwork position:(UInt16)position { SDLImage *icon = (shouldHaveArtwork && (cell.icon.name != nil)) ? cell.icon.imageRPC : nil; - return [[SDLAddSubMenu alloc] initWithId:cell.cellId menuName:cell.title menuIcon:icon position:(UInt8)position]; + + SDLMenuLayout submenuLayout = nil; + if (cell.submenuLayout && [self.systemCapabilityManager.defaultMainWindowCapability.menuLayoutsAvailable containsObject:cell.submenuLayout]) { + submenuLayout = cell.submenuLayout; + } else { + submenuLayout = self.menuConfiguration.defaultSubmenuLayout; + } + + return [[SDLAddSubMenu alloc] initWithId:cell.cellId menuName:cell.title menuLayout:submenuLayout menuIcon:icon position:(UInt8)position]; } #pragma mark - Calling handlers diff --git a/SmartDeviceLink/SDLRPCParameterNames.h b/SmartDeviceLink/SDLRPCParameterNames.h index 03f919b23..718d42bfc 100644 --- a/SmartDeviceLink/SDLRPCParameterNames.h +++ b/SmartDeviceLink/SDLRPCParameterNames.h @@ -379,6 +379,8 @@ extern SDLRPCParameterName const SDLRPCParameterNameMediaType; extern SDLRPCParameterName const SDLRPCParameterNameMemory; extern SDLRPCParameterName const SDLRPCParameterNameMenuIcon; extern SDLRPCParameterName const SDLRPCParameterNameMenuId; +extern SDLRPCParameterName const SDLRPCParameterNameMenuLayout; +extern SDLRPCParameterName const SDLRPCParameterNameMenuLayoutsAvailable; extern SDLRPCParameterName const SDLRPCParameterNameMenuName; extern SDLRPCParameterName const SDLRPCParameterNameMenuParams; extern SDLRPCParameterName const SDLRPCParameterNameMenuTitle; diff --git a/SmartDeviceLink/SDLRPCParameterNames.m b/SmartDeviceLink/SDLRPCParameterNames.m index 4bd3f6115..c928fcb30 100644 --- a/SmartDeviceLink/SDLRPCParameterNames.m +++ b/SmartDeviceLink/SDLRPCParameterNames.m @@ -372,6 +372,8 @@ SDLRPCParameterName const SDLRPCParameterNameMemoryAvailable = @"memoryAvailable"; SDLRPCParameterName const SDLRPCParameterNameMenuIcon = @"menuIcon"; SDLRPCParameterName const SDLRPCParameterNameMenuId = @"menuID"; +SDLRPCParameterName const SDLRPCParameterNameMenuLayout = @"menuLayout"; +SDLRPCParameterName const SDLRPCParameterNameMenuLayoutsAvailable = @"menuLayoutsAvailable"; SDLRPCParameterName const SDLRPCParameterNameMenuName = @"menuName"; SDLRPCParameterName const SDLRPCParameterNameMenuParams = @"menuParams"; SDLRPCParameterName const SDLRPCParameterNameMenuTitle = @"menuTitle"; diff --git a/SmartDeviceLink/SDLScreenManager.h b/SmartDeviceLink/SDLScreenManager.h index 15d159de4..0df4c21a6 100644 --- a/SmartDeviceLink/SDLScreenManager.h +++ b/SmartDeviceLink/SDLScreenManager.h @@ -20,6 +20,7 @@ @class SDLFileManager; @class SDLKeyboardProperties; @class SDLMenuCell; +@class SDLMenuConfiguration; @class SDLSoftButtonObject; @class SDLSystemCapabilityManager; @class SDLVoiceCommand; @@ -122,6 +123,17 @@ typedef void(^SDLPreloadChoiceCompletionHandler)(NSError *__nullable error); #pragma mark Menu +/** + Configures the layout of the menu and sub-menus. If set after a menu already exists, the existing main menu layout will be updated, _HOWEVER_ sub-menus will not be automatically updated; you will have to send a new menu to see the new submenu layout. + + If set menu layouts don't match available menu layouts in WindowCapability, an error log will be emitted and the layout will not be set. + + Setting this parameter will send a message to the remote system. This value will be set immediately, but if that message is rejected, the original value will be re-set and an error log will be emitted. + + This only works on head units supporting RPC spec version 6.0 and newer. If the connected head unit does not support this feature, a warning log will be emitted and nothing will be set. + */ +@property (strong, nonatomic) SDLMenuConfiguration *menuConfiguration; + /** The current list of menu cells displayed in the app's menu. */ diff --git a/SmartDeviceLink/SDLScreenManager.m b/SmartDeviceLink/SDLScreenManager.m index ea9ea5676..fac9ca4c0 100644 --- a/SmartDeviceLink/SDLScreenManager.m +++ b/SmartDeviceLink/SDLScreenManager.m @@ -138,6 +138,10 @@ - (void)setSoftButtonObjects:(NSArray *)softButtonObjects self.softButtonManager.softButtonObjects = softButtonObjects; } +- (void)setMenuConfiguration:(SDLMenuConfiguration *)menuConfiguration { + self.menuManager.menuConfiguration = menuConfiguration; +} + - (void)setMenu:(NSArray *)menu { self.menuManager.menuCells = menu; } @@ -216,6 +220,10 @@ - (nullable SDLMetadataType)textField4Type { return _softButtonManager.softButtonObjects; } +- (SDLMenuConfiguration *)menuConfiguration { + return _menuManager.menuConfiguration; +} + - (NSArray *)menu { return _menuManager.menuCells; } diff --git a/SmartDeviceLink/SDLSetGlobalProperties.h b/SmartDeviceLink/SDLSetGlobalProperties.h index a0a947757..ef1746ad5 100644 --- a/SmartDeviceLink/SDLSetGlobalProperties.h +++ b/SmartDeviceLink/SDLSetGlobalProperties.h @@ -3,6 +3,8 @@ #import "SDLRPCRequest.h" +#import "SDLMenuLayout.h" + @class SDLImage; @class SDLKeyboardProperties; @class SDLTTSChunk; @@ -27,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @param timeoutText A string that will be turned into TTS chunks for the timeout prompt @return The SetGlobalProperties RPC */ -- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText; +- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText __deprecated_msg("Use initWithHelpText:timeoutText:vrHelpTitle:vrHelp:menuTitle:menuIcon:keyboardProperties:menuLayout: instead"); /** Initialize SetGlobalProperties with help text, timeout text, help title, and help items @@ -38,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN @param vrHelp The items of the help interface prompt @return The SetGlobalProperties RPC */ -- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp; +- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp __deprecated_msg("Use initWithHelpText:timeoutText:vrHelpTitle:vrHelp:menuTitle:menuIcon:keyboardProperties:menuLayout: instead"); /** Initialize SetGlobalProperties with all possible items @@ -52,7 +54,22 @@ NS_ASSUME_NONNULL_BEGIN @param keyboardProperties The properties of a keyboard prompt @return The SetGlobalProperties RPC */ -- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp menuTitle:(nullable NSString *)menuTitle menuIcon:(nullable SDLImage *)menuIcon keyboardProperties:(nullable SDLKeyboardProperties *)keyboardProperties; +- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp menuTitle:(nullable NSString *)menuTitle menuIcon:(nullable SDLImage *)menuIcon keyboardProperties:(nullable SDLKeyboardProperties *)keyboardProperties __deprecated_msg("Use initWithHelpText:timeoutText:vrHelpTitle:vrHelp:menuTitle:menuIcon:keyboardProperties:menuLayout: instead"); + +/** + Initialize SetGlobalProperties with all possible items + + @param helpText A string that will be turned into TTS chunks for the help prompt + @param timeoutText A string that will be turned into TTS chunks for the timeout prompt + @param vrHelpTitle The title of the help interface prompt + @param vrHelp The items of the help interface prompt + @param menuTitle The title of the menu button + @param menuIcon The icon on the menu button + @param keyboardProperties The properties of a keyboard prompt + @param menuLayout The layout of the top-level main menu + @return The SetGlobalProperties RPC + */ +- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp menuTitle:(nullable NSString *)menuTitle menuIcon:(nullable SDLImage *)menuIcon keyboardProperties:(nullable SDLKeyboardProperties *)keyboardProperties menuLayout:(nullable SDLMenuLayout)menuLayout; /** Help prompt for when the user asks for help with an interface prompt @@ -112,6 +129,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (strong, nonatomic, nullable) SDLSeatLocation *userLocation; +/** + The main menu layout. If this is sent while a menu is already on-screen, the head unit will change the display to the new layout type. See available menu layouts on DisplayCapabilities.menuLayoutsAvailable. Defaults to the head unit default. + */ +@property (strong, nonatomic, nullable) SDLMenuLayout menuLayout; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLSetGlobalProperties.m b/SmartDeviceLink/SDLSetGlobalProperties.m index 6dc337505..b502fcfd1 100644 --- a/SmartDeviceLink/SDLSetGlobalProperties.m +++ b/SmartDeviceLink/SDLSetGlobalProperties.m @@ -27,14 +27,18 @@ - (instancetype)init { #pragma clang diagnostic pop - (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText { - return [self initWithHelpText:helpText timeoutText:timeoutText vrHelpTitle:nil vrHelp:nil]; + return [self initWithHelpText:helpText timeoutText:timeoutText vrHelpTitle:nil vrHelp:nil menuTitle:nil menuIcon:nil keyboardProperties:nil menuLayout:nil]; } - (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp { - return [self initWithHelpText:helpText timeoutText:timeoutText vrHelpTitle:vrHelpTitle vrHelp:vrHelp menuTitle:nil menuIcon:nil keyboardProperties:nil]; + return [self initWithHelpText:helpText timeoutText:timeoutText vrHelpTitle:vrHelpTitle vrHelp:vrHelp menuTitle:nil menuIcon:nil keyboardProperties:nil menuLayout:nil]; } - (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp menuTitle:(nullable NSString *)menuTitle menuIcon:(nullable SDLImage *)menuIcon keyboardProperties:(nullable SDLKeyboardProperties *)keyboardProperties { + return [self initWithHelpText:helpText timeoutText:timeoutText vrHelpTitle:vrHelpTitle vrHelp:vrHelp menuTitle:menuTitle menuIcon:menuIcon keyboardProperties:keyboardProperties menuLayout:nil]; +} + +- (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(nullable NSString *)timeoutText vrHelpTitle:(nullable NSString *)vrHelpTitle vrHelp:(nullable NSArray *)vrHelp menuTitle:(nullable NSString *)menuTitle menuIcon:(nullable SDLImage *)menuIcon keyboardProperties:(nullable SDLKeyboardProperties *)keyboardProperties menuLayout:(nullable SDLMenuLayout)menuLayout { self = [self init]; if (!self) { return nil; @@ -47,6 +51,7 @@ - (instancetype)initWithHelpText:(nullable NSString *)helpText timeoutText:(null self.menuTitle = menuTitle; self.menuIcon = menuIcon; self.keyboardProperties = keyboardProperties; + self.menuLayout = menuLayout; return self; } @@ -115,6 +120,14 @@ - (nullable SDLSeatLocation *)userLocation { return [self.parameters sdl_objectForName:SDLRPCParameterNameUserLocation ofClass:SDLSeatLocation.class error:nil]; } +- (void)setMenuLayout:(nullable SDLMenuLayout)menuLayout { + [self.parameters sdl_setObject:menuLayout forName:SDLRPCParameterNameMenuLayout]; +} + +- (nullable SDLMenuLayout)menuLayout { + return [self.parameters sdl_enumForName:SDLRPCParameterNameMenuLayout error:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLWindowCapability.h b/SmartDeviceLink/SDLWindowCapability.h index b569f0020..a68eb0127 100644 --- a/SmartDeviceLink/SDLWindowCapability.h +++ b/SmartDeviceLink/SDLWindowCapability.h @@ -4,6 +4,7 @@ #import "SDLRPCStruct.h" #import "SDLImageType.h" +#import "SDLMenuLayout.h" @class SDLTextField; @class SDLImageField; @@ -76,6 +77,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, strong, nonatomic) NSArray *softButtonCapabilities; +/** + An array of available menu layouts. If this parameter is not provided, only the `LIST` layout is assumed to be available. + + Optional, array of 1 to 100, see SDLMenuLayout + */ +@property (nullable, strong, nonatomic) NSArray *menuLayoutsAvailable; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLWindowCapability.m b/SmartDeviceLink/SDLWindowCapability.m index 6ace664b6..509e2aa96 100644 --- a/SmartDeviceLink/SDLWindowCapability.m +++ b/SmartDeviceLink/SDLWindowCapability.m @@ -78,4 +78,12 @@ - (void)setSoftButtonCapabilities:(nullable NSArray return [self.store sdl_objectsForName:SDLRPCParameterNameSoftButtonCapabilities ofClass:SDLSoftButtonCapabilities.class error:nil]; } +- (void)setMenuLayoutsAvailable:(nullable NSArray *)menuLayoutsAvailable { + [self.store sdl_setObject:menuLayoutsAvailable forName:SDLRPCParameterNameMenuLayoutsAvailable]; +} + +- (nullable NSArray *)menuLayoutsAvailable { + return [self.store sdl_enumsForName:SDLRPCParameterNameMenuLayoutsAvailable error:nil]; +} + @end diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index 8292e5624..efa4f8b2d 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -335,6 +335,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLMassageZone.h" #import "SDLMediaClockFormat.h" #import "SDLMediaType.h" +#import "SDLMenuLayout.h" #import "SDLMenuManagerConstants.h" #import "SDLMetadataType.h" #import "SDLModuleType.h" @@ -437,6 +438,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLSoftButtonState.h" #import "SDLMenuCell.h" +#import "SDLMenuConfiguration.h" #import "SDLVoiceCommand.h" #import "SDLChoiceCell.h" diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m index ee6f61278..ab8b281fd 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m @@ -9,6 +9,7 @@ describe(@"a menu cell", ^{ __block SDLMenuCell *testCell = nil; __block SDLMenuCell *testCell2 = nil; + __block SDLMenuLayout testLayout = SDLMenuLayoutList; describe(@"initializing", ^{ __block NSString *someTitle = nil; @@ -43,29 +44,44 @@ expect(testCell.icon).to(beNil()); expect(testCell.voiceCommands).to(beNil()); expect(testCell.subCells).to(equal(someSubcells)); + expect(testCell.submenuLayout).to(beNil()); #pragma clang diagnostic pop }); it(@"should initialize properly as a submenu item with icon", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork subCells:someSubcells]; expect(testCell.title).to(equal(someTitle)); expect(testCell.icon).to(equal(someArtwork)); expect(testCell.voiceCommands).to(beNil()); expect(testCell.subCells).to(equal(someSubcells)); + expect(testCell.submenuLayout).to(beNil()); +#pragma clang diagnostic pop + }); + + it(@"should initialize properly as a submenu item with icon and layout", ^{ + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork submenuLayout:testLayout subCells:someSubcells]; + + expect(testCell.title).to(equal(someTitle)); + expect(testCell.icon).to(equal(someArtwork)); + expect(testCell.voiceCommands).to(beNil()); + expect(testCell.subCells).to(equal(someSubcells)); + expect(testCell.submenuLayout).to(equal(testLayout)); }); }); describe(@"check cell eqality", ^{ it(@"should compare cells and return true if cells equal", ^{ - testCell = [[SDLMenuCell alloc] initWithTitle:@"Title" icon:nil subCells:@[]]; - testCell2 = [[SDLMenuCell alloc] initWithTitle:@"Title" icon:nil subCells:@[]]; + testCell = [[SDLMenuCell alloc] initWithTitle:@"Title" icon:nil submenuLayout:testLayout subCells:@[]]; + testCell2 = [[SDLMenuCell alloc] initWithTitle:@"Title" icon:nil submenuLayout:testLayout subCells:@[]]; expect([testCell isEqual:testCell2]).to(equal(true)); }); it(@"should compare cells and return false if not equal ", ^{ - testCell = [[SDLMenuCell alloc] initWithTitle:@"True" icon:nil subCells:@[]]; - testCell2 = [[SDLMenuCell alloc] initWithTitle:@"False" icon:nil subCells:@[]]; + testCell = [[SDLMenuCell alloc] initWithTitle:@"True" icon:nil submenuLayout:testLayout subCells:@[]]; + testCell2 = [[SDLMenuCell alloc] initWithTitle:@"False" icon:nil submenuLayout:testLayout subCells:@[]]; expect([testCell isEqual:testCell2]).to(equal(false)); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuConfigurationSpec.m new file mode 100644 index 000000000..3c8f5190c --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuConfigurationSpec.m @@ -0,0 +1,28 @@ +#import +#import + +#import "SDLMenuConfiguration.h" + +QuickSpecBegin(SDLMenuConfigurationSpec) + +describe(@"a menu configuration", ^{ + __block SDLMenuConfiguration *testConfiguration = nil; + + describe(@"initializing", ^{ + it(@"should initialize properly with no variables", ^{ + testConfiguration = [[SDLMenuConfiguration alloc] init]; + + expect(testConfiguration.mainMenuLayout).to(equal(SDLMenuLayoutList)); + expect(testConfiguration.defaultSubmenuLayout).to(equal(SDLMenuLayoutList)); + }); + + it(@"should initialize properly when set", ^{ + testConfiguration = [[SDLMenuConfiguration alloc] initWithMainMenuLayout:SDLMenuLayoutTiles defaultSubmenuLayout:SDLMenuLayoutTiles]; + + expect(testConfiguration.mainMenuLayout).to(equal(SDLMenuLayoutTiles)); + expect(testConfiguration.defaultSubmenuLayout).to(equal(SDLMenuLayoutTiles)); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m index 29ed043c3..815105331 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m @@ -52,16 +52,20 @@ @interface SDLMenuManager() __block SDLMenuCell *submenuCell = nil; __block SDLMenuCell *submenuImageCell = nil; + __block SDLMenuConfiguration *testMenuConfiguration = nil; + beforeEach(^{ testArtwork = [[SDLArtwork alloc] initWithData:[@"Test data" dataUsingEncoding:NSUTF8StringEncoding] name:@"some artwork name" fileExtension:@"png" persistent:NO]; testArtwork2 = [[SDLArtwork alloc] initWithData:[@"Test data 2" dataUsingEncoding:NSUTF8StringEncoding] name:@"some artwork name 2" fileExtension:@"png" persistent:NO]; textOnlyCell = [[SDLMenuCell alloc] initWithTitle:@"Test 1" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Test 3" icon:nil subCells:@[textOnlyCell, textAndImageCell]]; - submenuImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 4" icon:testArtwork2 subCells:@[textOnlyCell]]; + submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Test 3" icon:nil submenuLayout:nil subCells:@[textOnlyCell, textAndImageCell]]; + submenuImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 4" icon:testArtwork2 submenuLayout:SDLMenuLayoutTiles subCells:@[textOnlyCell]]; textOnlyCell2 = [[SDLMenuCell alloc] initWithTitle:@"Test 5" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + testMenuConfiguration = [[SDLMenuConfiguration alloc] initWithMainMenuLayout:SDLMenuLayoutTiles defaultSubmenuLayout:SDLMenuLayoutList]; + mockConnectionManager = [[TestConnectionManager alloc] init]; mockFileManager = OCMClassMock([SDLFileManager class]); @@ -74,6 +78,7 @@ @interface SDLMenuManager() windowCapability.windowID = @(SDLPredefinedWindowsDefaultWindow); windowCapability.imageFields = @[commandIconField]; windowCapability.imageTypeSupported = @[SDLImageTypeDynamic, SDLImageTypeStatic]; + windowCapability.menuLayoutsAvailable = @[SDLMenuLayoutList, SDLMenuLayoutTiles]; SDLDisplayCapability *displayCapability = [[SDLDisplayCapability alloc] initWithDisplayName:SDLDisplayTypeGeneric]; displayCapability.windowCapabilities = @[windowCapability]; @@ -94,6 +99,7 @@ @interface SDLMenuManager() expect(testManager.lastMenuId).to(equal(1)); expect(testManager.oldMenuCells).to(beEmpty()); expect(testManager.waitingUpdateMenuCells).to(beNil()); + expect(testManager.menuConfiguration).toNot(beNil()); }); describe(@"updating menu cells before HMI is ready", ^{ @@ -126,38 +132,31 @@ @interface SDLMenuManager() context(@"when no HMI level has been received", ^{ beforeEach(^{ testManager.currentHMILevel = nil; - testManager.menuCells = @[textOnlyCell]; }); - it(@"should not update", ^{ + it(@"should not update the menu configuration", ^{ + testManager.menuConfiguration = testMenuConfiguration; + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + expect(testManager.menuConfiguration).toNot(equal(testMenuConfiguration)); + }); + + it(@"should not update the menu cells", ^{ + testManager.menuCells = @[textOnlyCell]; expect(mockConnectionManager.receivedRequests).to(beEmpty()); }); }); context(@"when in the menu", ^{ beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithString:@"6.0.0"]; testManager.currentHMILevel = SDLHMILevelFull; testManager.currentSystemContext = SDLSystemContextMenu; - testManager.menuCells = @[textOnlyCell]; - }); - - it(@"should not update", ^{ - expect(mockConnectionManager.receivedRequests).to(beEmpty()); }); - describe(@"when exiting the menu", ^{ - beforeEach(^{ - SDLOnHMIStatus *onHMIStatus = [[SDLOnHMIStatus alloc] init]; - onHMIStatus.hmiLevel = SDLHMILevelFull; - onHMIStatus.systemContext = SDLSystemContextMain; - - SDLRPCNotificationNotification *testSystemContextNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:onHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:testSystemContextNotification]; - }); - - it(@"should update", ^{ - expect(mockConnectionManager.receivedRequests).toNot(beEmpty()); - }); + fit(@"should update the menu configuration", ^{ + testManager.menuConfiguration = testMenuConfiguration; + expect(mockConnectionManager.receivedRequests).toNot(beEmpty()); + expect(testManager.menuConfiguration).to(equal(testMenuConfiguration)); }); }); }); @@ -544,7 +543,7 @@ @interface SDLMenuManager() testTriggerSource = triggerSource; }]; - SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Submenu" icon:nil subCells:@[cellWithHandler]]; + SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Submenu" icon:nil submenuLayout:SDLMenuLayoutTiles subCells:@[cellWithHandler]]; testManager.menuCells = @[submenuCell]; }); @@ -563,7 +562,46 @@ @interface SDLMenuManager() }); }); - context(@"On disconnects", ^{ + describe(@"updating the menu configuration", ^{ + beforeEach(^{ + testManager.currentHMILevel = SDLHMILevelFull; + testManager.currentSystemContext = SDLSystemContextMain; + }); + + context(@"if the connection RPC version is less than 6.0.0", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithString:@"5.0.0"]; + }); + + it(@"should fail to send a SetGlobalProperties RPC update", ^{ + testManager.menuConfiguration = testMenuConfiguration; + + expect(testManager.menuConfiguration).toNot(equal(testMenuConfiguration)); + expect(mockConnectionManager.receivedRequests).to(haveCount(0)); + }); + }); + + context(@"if the connection RPC version is greater than or equal to 6.0.0", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithString:@"6.0.0"]; + }); + + it(@"should send a SetGlobalProperties RPC update", ^{ + testManager.menuConfiguration = testMenuConfiguration; + + expect(testManager.menuConfiguration).to(equal(testMenuConfiguration)); + expect(mockConnectionManager.receivedRequests).to(haveCount(1)); + + SDLSetGlobalPropertiesResponse *response = [[SDLSetGlobalPropertiesResponse alloc] init]; + response.success = @YES; + [mockConnectionManager respondToLastRequestWithResponse:response]; + + expect(testManager.menuConfiguration).to(equal(testMenuConfiguration)); + }); + }); + }); + + context(@"when the manager stops", ^{ beforeEach(^{ [testManager stop]; }); @@ -580,6 +618,7 @@ @interface SDLMenuManager() expect(testManager.lastMenuId).to(equal(1)); expect(testManager.oldMenuCells).to(beEmpty()); expect(testManager.waitingUpdateMenuCells).to(beEmpty()); + expect(testManager.menuConfiguration).toNot(beNil()); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLMenuLayoutSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLMenuLayoutSpec.m new file mode 100644 index 000000000..ce2b079a6 --- /dev/null +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLMenuLayoutSpec.m @@ -0,0 +1,15 @@ +#import +#import + +#import "SDLMenuLayout.h" + +QuickSpecBegin(SDLMenuLayoutSpec) + +describe(@"Individual Enum Value Tests", ^{ + it(@"Should match internal values", ^{ + expect(SDLMenuLayoutList).to(equal(@"LIST")); + expect(SDLMenuLayoutTiles).to(equal(@"TILES")); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m index 2efd1eee2..5c5e98547 100644 --- a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m @@ -20,6 +20,7 @@ __block UInt8 position = 27; __block NSString *menuName = @"Welcome to the menu"; __block SDLImage *image = nil; + __block SDLMenuLayout testLayout = SDLMenuLayoutList; beforeEach(^{ image = [[SDLImage alloc] initWithName:@"Test" isTemplate:false]; @@ -47,12 +48,25 @@ }); it(@"should correctly initialize with initWithId:menuName:menuIcon:position:", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SDLAddSubMenu *testRequest = [[SDLAddSubMenu alloc] initWithId:menuId menuName:menuName menuIcon:image position:position]; expect(testRequest.menuID).to(equal(@(menuId))); expect(testRequest.position).to(equal(@(position))); expect(testRequest.menuName).to(equal(menuName)); expect(testRequest.menuIcon).to(equal(image)); +#pragma clang diagnostic pop + }); + + it(@"should correctly initialize with initWithId:menuName:menuLayout:menuIcon:position:", ^{ + SDLAddSubMenu *testRequest = [[SDLAddSubMenu alloc] initWithId:menuId menuName:menuName menuLayout:testLayout menuIcon:image position:position]; + + expect(testRequest.menuID).to(equal(@(menuId))); + expect(testRequest.position).to(equal(@(position))); + expect(testRequest.menuName).to(equal(menuName)); + expect(testRequest.menuIcon).to(equal(image)); + expect(testRequest.menuLayout).to(equal(testLayout)); }); it(@"Should set and get correctly", ^ { @@ -62,11 +76,13 @@ testRequest.position = @27; testRequest.menuName = @"Welcome to the menu"; testRequest.menuIcon = image; + testRequest.menuLayout = testLayout; expect(testRequest.menuID).to(equal(@(menuId))); expect(testRequest.position).to(equal(@(position))); expect(testRequest.menuName).to(equal(menuName)); expect(testRequest.menuIcon).to(equal(image)); + expect(testRequest.menuLayout).to(equal(testLayout)); }); it(@"Should get correctly when initialized", ^ { @@ -77,7 +93,8 @@ SDLRPCParameterNameMenuName:@"Welcome to the menu", SDLRPCParameterNameMenuIcon: @{ SDLRPCParameterNameValue: @"Test" - } + }, + SDLRPCParameterNameMenuLayout: testLayout }, SDLRPCParameterNameOperationName:SDLRPCFunctionNameAddSubMenu}} mutableCopy]; #pragma clang diagnostic push @@ -89,6 +106,7 @@ expect(testRequest.position).to(equal(@(position))); expect(testRequest.menuName).to(equal(menuName)); expect(testRequest.menuIcon.value).to(equal(@"Test")); + expect(testRequest.menuLayout).to(equal(testLayout)); }); it(@"Should return nil if not set", ^ { @@ -98,6 +116,7 @@ expect(testRequest.position).to(beNil()); expect(testRequest.menuName).to(beNil()); expect(testRequest.menuIcon).to(beNil()); + expect(testRequest.menuLayout).to(beNil()); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitiesSpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitiesSpec.m index ab19ae425..6e89c7461 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitiesSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitiesSpec.m @@ -39,7 +39,7 @@ testStruct.templatesAvailable = [@[@"String", @"String", @"String"] mutableCopy]; testStruct.screenParams = screenParams; testStruct.numCustomPresetsAvailable = @43; - + expect(testStruct.displayType).to(equal(SDLDisplayTypeGen26DMA)); expect(testStruct.displayName).to(equal(@"test")); expect(testStruct.textFields).to(equal([@[textField] mutableCopy])); @@ -52,7 +52,7 @@ }); it(@"Should get correctly when initialized", ^ { - NSMutableDictionary* dict = [@{SDLRPCParameterNameDisplayType:SDLDisplayTypeGen26DMA, + NSMutableDictionary* dict = @{SDLRPCParameterNameDisplayType:SDLDisplayTypeGen26DMA, SDLRPCParameterNameDisplayName: @"test", SDLRPCParameterNameTextFields:[@[textField] mutableCopy], SDLRPCParameterNameImageFields:[@[imageField] mutableCopy], @@ -60,7 +60,8 @@ SDLRPCParameterNameGraphicSupported:@YES, SDLRPCParameterNameTemplatesAvailable:[@[@"String", @"String", @"String"] mutableCopy], SDLRPCParameterNameScreenParams:screenParams, - SDLRPCParameterNameNumberCustomPresetsAvailable:@43} mutableCopy]; + SDLRPCParameterNameNumberCustomPresetsAvailable:@43, + }; SDLDisplayCapabilities* testStruct = [[SDLDisplayCapabilities alloc] initWithDictionary:dict]; expect(testStruct.displayType).to(equal(SDLDisplayTypeGen26DMA)); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitySpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitySpec.m index 4cd68a799..1d0aad819 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitySpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLDisplayCapabilitySpec.m @@ -63,7 +63,6 @@ testWindowCapability.imageTypeSupported = @[testImageType]; testWindowCapability.buttonCapabilities = @[testButtonCapabilities]; testWindowCapability.softButtonCapabilities = @[testSoftButtonscapabilities]; - }); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m index 0589337ce..94eecde90 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m @@ -17,7 +17,6 @@ QuickSpecBegin(SDLWindowCapabilitySpec) describe(@"Getter/Setter Tests", ^ { - __block SDLTextField* testTextField = nil; __block SDLImageField *testImageField = nil; __block SDLButtonCapabilities *testButtonCapabilities = nil; @@ -55,6 +54,7 @@ testStruct.imageTypeSupported = @[testImageType]; testStruct.buttonCapabilities = @[testButtonCapabilities]; testStruct.softButtonCapabilities = @[testSoftButtonscapabilities]; + testStruct.menuLayoutsAvailable = @[SDLMenuLayoutTiles]; expect(testStruct.windowID).to(equal(@444)); expect(testStruct.textFields.firstObject.name).to(equal(SDLTextFieldNameTertiaryText)); @@ -65,6 +65,7 @@ expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(equal(@YES)); expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(equal(@YES)); + expect(testStruct.menuLayoutsAvailable).to(equal(@[SDLMenuLayoutTiles])); }); });