mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-18 22:41:18 +00:00
Merge pull request #3142 from daboe01/new-CPSplitViewController
new: CPSplitViewController and CPSplitViewItem
This commit is contained in:
2 files changed
+574
No files matched your search
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* CPSplitViewController.j
|
||||
*
|
||||
* Created by Daniel Boehringer on September 2, 2025.
|
||||
* Copyright (c) 2025 Daniel Boehringer. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPViewController.j"
|
||||
@import "CPSplitView.j"
|
||||
|
||||
var CPSplitViewControllerAutomaticDimension = -1.0;
|
||||
|
||||
/**
|
||||
* A container view controller that manages two or more child view
|
||||
* controllers in a split view interface.
|
||||
*
|
||||
* This class provides a controller-level abstraction for CPSplitView,
|
||||
* managing the addition, removal, and arrangement of view controllers
|
||||
* through CPSplitViewItem instances.
|
||||
*
|
||||
* This implementation was synthesized with the assistance of an LLM,
|
||||
* directed by the author.
|
||||
*/
|
||||
@implementation CPSplitViewController : CPViewController <CPSplitViewDelegate>
|
||||
{
|
||||
/** @private The underlying split view that arranges the child views. */
|
||||
CPSplitView _splitView;
|
||||
|
||||
/** @private An array of CPSplitViewItem objects managed by this controller. */
|
||||
CPMutableArray _splitViewItems;
|
||||
|
||||
/** @private The minimum thickness for sidebars to be displayed inline. */
|
||||
CPNumber _minimumThicknessForInlineSidebars;
|
||||
}
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_splitViewItems = [CPMutableArray array];
|
||||
_minimumThicknessForInlineSidebars = 20.0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
if (!_splitView)
|
||||
{
|
||||
_splitView = [[CPSplitView alloc] initWithFrame:CGRectMake(0,0,400,400)];
|
||||
[_splitView setDelegate:self];
|
||||
}
|
||||
[self setView:_splitView];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
for (var i = 0; i < [_splitViewItems count]; i++)
|
||||
{
|
||||
var viewController = [[_splitViewItems objectAtIndex:i] viewController];
|
||||
[[self splitView] addArrangedSubview:[viewController view]];
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Accessors
|
||||
|
||||
/**
|
||||
* Returns the CPSplitView instance managed by the controller.
|
||||
*
|
||||
* @returns {CPSplitView} The split view.
|
||||
*/
|
||||
- (CPSplitView)splitView
|
||||
{
|
||||
return _splitView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom split view for the controller.
|
||||
*
|
||||
* @param {CPSplitView} splitView The custom split view to use.
|
||||
*/
|
||||
- (void)setSplitView:(CPSplitView)splitView
|
||||
{
|
||||
if (_splitView !== splitView)
|
||||
{
|
||||
_splitView = splitView;
|
||||
[_splitView setDelegate:self];
|
||||
if ([self isViewLoaded])
|
||||
[self setView:_splitView];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of split view items.
|
||||
*
|
||||
* @returns {CPArray} The array of CPSplitViewItem objects.
|
||||
*/
|
||||
- (CPArray)splitViewItems
|
||||
{
|
||||
return _splitViewItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the array of split view items, replacing any existing items.
|
||||
*
|
||||
* @param {CPArray} splitViewItems An array of CPSplitViewItem objects.
|
||||
*/
|
||||
- (void)setSplitViewItems:(CPArray)splitViewItems
|
||||
{
|
||||
// Remove all existing items
|
||||
while ([_splitViewItems count] > 0)
|
||||
{
|
||||
[self removeSplitViewItem:[_splitViewItems lastObject]];
|
||||
}
|
||||
|
||||
// Add new items
|
||||
for (var i = 0; i < [splitViewItems count]; i++)
|
||||
{
|
||||
[self addSplitViewItem:[splitViewItems objectAtIndex:i]];
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Managing Split View Items
|
||||
|
||||
/**
|
||||
* Adds a split view item to the end of the split view.
|
||||
*
|
||||
* @param {CPSplitViewItem} splitViewItem The split view item to add.
|
||||
*/
|
||||
- (void)addSplitViewItem:(CPSplitViewItem)splitViewItem
|
||||
{
|
||||
[self insertSplitViewItem:splitViewItem atIndex:[_splitViewItems count]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a split view item at a specific index.
|
||||
*
|
||||
* @param {CPSplitViewItem} splitViewItem The split view item to insert.
|
||||
* @param {CPInteger} index The zero-based index at which to insert the item.
|
||||
*/
|
||||
- (void)insertSplitViewItem:(CPSplitViewItem)splitViewItem atIndex:(CPInteger)index
|
||||
{
|
||||
[splitViewItem _setSplitViewController:self];
|
||||
[_splitViewItems insertObject:splitViewItem atIndex:index];
|
||||
[self addChildViewController:[splitViewItem viewController]];
|
||||
|
||||
if ([self isViewLoaded])
|
||||
[[self splitView] insertArrangedSubview:[[splitViewItem viewController] view] atIndex:index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified split view item.
|
||||
*
|
||||
* @param {CPSplitViewItem} splitViewItem The split view item to remove.
|
||||
*/
|
||||
- (void)removeSplitViewItem:(CPSplitViewItem)splitViewItem
|
||||
{
|
||||
var viewController = [splitViewItem viewController];
|
||||
if ([self isViewLoaded])
|
||||
[[viewController view] removeFromSuperview];
|
||||
|
||||
[viewController removeFromParentViewController];
|
||||
[splitViewItem _setSplitViewController:nil];
|
||||
[_splitViewItems removeObject:splitViewItem];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the split view item associated with a given view controller.
|
||||
*
|
||||
* @param {CPViewController} viewController The view controller to find.
|
||||
* @returns {CPSplitViewItem | null} The corresponding split view item, or nil if not found.
|
||||
*/
|
||||
- (CPSplitViewItem)splitViewItemForViewController:(CPViewController)viewController
|
||||
{
|
||||
for (var i = 0; i < [_splitViewItems count]; i++)
|
||||
{
|
||||
var item = [_splitViewItems objectAtIndex:i];
|
||||
if ([item viewController] === viewController)
|
||||
return item;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// MARK: - Managing Sidebars and Inspectors
|
||||
|
||||
/**
|
||||
* Toggles the collapsed state of the first split view item, typically a sidebar.
|
||||
*
|
||||
* @param {id} sender The object that initiated the action.
|
||||
*/
|
||||
- (void)toggleSidebar:(id)sender
|
||||
{
|
||||
if ([_splitViewItems count] > 0)
|
||||
{
|
||||
var sidebarItem = [_splitViewItems objectAtIndex:0];
|
||||
[sidebarItem setCollapsed:![sidebarItem isCollapsed]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the collapsed state of the last split view item, typically an inspector.
|
||||
*
|
||||
* @param {id} sender The object that initiated the action.
|
||||
*/
|
||||
- (void)toggleInspector:(id)sender
|
||||
{
|
||||
if ([_splitViewItems count] > 1)
|
||||
{
|
||||
var inspectorItem = [_splitViewItems lastObject];
|
||||
[inspectorItem setCollapsed:![inspectorItem isCollapsed]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum thickness for sidebars to be displayed inline.
|
||||
*
|
||||
* @returns {CPNumber} The minimum thickness.
|
||||
*/
|
||||
- (CPNumber)minimumThicknessForInlineSidebars
|
||||
{
|
||||
return _minimumThicknessForInlineSidebars;
|
||||
}
|
||||
|
||||
// MARK: - CPSplitViewDelegate Methods
|
||||
|
||||
// Note: A more complete implementation would forward these delegate methods
|
||||
// to a separate delegate property on the CPSplitViewController itself.
|
||||
// For now, these are stubbed to demonstrate where they would be handled.
|
||||
|
||||
- (BOOL)splitView:(CPSplitView)splitView canCollapseSubview:(CPView)subview
|
||||
{
|
||||
// Default behavior: allow all subviews to be collapsed.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CGFloat)splitView:(CPSplitView)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(CPInteger)dividerIndex
|
||||
{
|
||||
return proposedMinimumPosition;
|
||||
}
|
||||
|
||||
- (CGFloat)splitView:(CPSplitView)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(CPInteger)dividerIndex
|
||||
{
|
||||
return proposedMaximumPosition;
|
||||
}
|
||||
|
||||
- (CGRect)splitView:(CPSplitView)splitView effectiveRect:(CGRect)proposedEffectiveRect forDrawnRect:(CGRect)drawnRect ofDividerAtIndex:(CPInteger)dividerIndex
|
||||
{
|
||||
// Default behavior: return the proposed rectangle.
|
||||
// This can be overridden to provide a larger or custom hit area for the divider.
|
||||
return proposedEffectiveRect;
|
||||
}
|
||||
|
||||
- (void)splitViewDidResizeSubviews:(CPNotification)notification
|
||||
{
|
||||
// Can be used to respond to user-initiated resizing.
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* An object that manages a view controller within a CPSplitViewController.
|
||||
*
|
||||
* A CPSplitViewItem acts as a wrapper around a CPViewController,
|
||||
* maintaining properties like its collapsed state within the parent
|
||||
* split view controller.
|
||||
*/
|
||||
@implementation CPSplitViewItem : CPObject
|
||||
{
|
||||
/** @private The view controller managed by this item. */
|
||||
CPViewController _viewController;
|
||||
|
||||
/** @private A boolean indicating whether the item is collapsed. */
|
||||
BOOL _isCollapsed;
|
||||
|
||||
/** @private A weak reference to the owning split view controller. */
|
||||
CPSplitViewController _splitViewController;
|
||||
}
|
||||
|
||||
// MARK: - Class Methods
|
||||
|
||||
/**
|
||||
* Creates and returns a new split view item with the specified view controller.
|
||||
*
|
||||
* @param {CPViewController} viewController The view controller for the new item.
|
||||
* @returns {instancetype} A new CPSplitViewItem instance.
|
||||
*/
|
||||
+ (instancetype)splitViewItemWithViewController:(CPViewController)viewController
|
||||
{
|
||||
return [[self alloc] initWithViewController:viewController];
|
||||
}
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
/**
|
||||
* Initializes a new split view item with the specified view controller.
|
||||
*
|
||||
* @param {CPViewController} viewController The view controller for the new item.
|
||||
* @returns {id} The initialized CPSplitViewItem instance.
|
||||
*/
|
||||
- (id)initWithViewController:(CPViewController)viewController
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_viewController = viewController;
|
||||
_isCollapsed = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// MARK: - Accessors
|
||||
|
||||
/**
|
||||
* Returns the view controller associated with the item.
|
||||
*
|
||||
* @returns {CPViewController} The associated view controller.
|
||||
*/
|
||||
- (CPViewController)viewController
|
||||
{
|
||||
return _viewController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean value indicating whether the item is collapsed.
|
||||
*
|
||||
* @returns {BOOL} YES if the item is collapsed, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isCollapsed
|
||||
{
|
||||
return _isCollapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the collapsed state of the item.
|
||||
* When collapsed, the view controller's view is hidden.
|
||||
*
|
||||
* @param {BOOL} shouldCollapse YES to collapse the item, NO to expand it.
|
||||
*/
|
||||
- (void)setCollapsed:(BOOL)shouldCollapse
|
||||
{
|
||||
if (_isCollapsed === shouldCollapse)
|
||||
return;
|
||||
|
||||
_isCollapsed = shouldCollapse;
|
||||
[[_viewController view] setHidden:shouldCollapse];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the split view controller that owns this item.
|
||||
*
|
||||
* @returns {CPSplitViewController | null} The parent split view controller.
|
||||
*/
|
||||
- (CPSplitViewController)splitViewController
|
||||
{
|
||||
return _splitViewController;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Sets the owning split view controller. This method is for internal use by
|
||||
* CPSplitViewController.
|
||||
*
|
||||
* @param {CPSplitViewController} splitViewController The parent controller.
|
||||
*/
|
||||
- (void)_setSplitViewController:(CPSplitViewController)splitViewController
|
||||
{
|
||||
_splitViewController = splitViewController;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,186 @@
|
||||
@import <AppKit/CPSplitViewController.j>
|
||||
@import <AppKit/CPViewController.j>
|
||||
|
||||
// MARK: - Test Implementation
|
||||
|
||||
@implementation CPSplitViewControllerTest : OJTestCase
|
||||
{
|
||||
// Instance variables can be declared here if needed for tests.
|
||||
}
|
||||
|
||||
// MARK: - Initialization Tests
|
||||
|
||||
- (void)testInit
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
|
||||
[self assertNotNil:splitViewController message:@"CPSplitViewController should initialize."];
|
||||
[self assertNotNil:[splitViewController splitViewItems] message:@"splitViewItems should be an empty array on init."];
|
||||
[self assert:[[splitViewController splitViewItems] count] equals:0 message:@"splitViewItems should have 0 items on init."];
|
||||
}
|
||||
|
||||
- (void)testViewLoading
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
|
||||
// Accessing the view property triggers loadView
|
||||
var view = [splitViewController view];
|
||||
|
||||
[self assertNotNil:view message:@"The controller's view should be created."];
|
||||
[self assertTrue:[view isKindOfClass:[CPSplitView class]] message:@"The controller's view should be a CPSplitView."];
|
||||
[self assert:[splitViewController splitView] equals:view message:@"The splitView accessor should return the controller's view."];
|
||||
}
|
||||
|
||||
- (void)testSplitViewItemInit
|
||||
{
|
||||
var childVC = [[CPViewController alloc] init];
|
||||
var item = [CPSplitViewItem splitViewItemWithViewController:childVC];
|
||||
|
||||
[self assertNotNil:item message:@"CPSplitViewItem should be created."];
|
||||
[self assert:[item viewController] equals:childVC message:@"The item should hold the correct view controller."];
|
||||
[self assertFalse:[item isCollapsed] message:@"A new item should not be collapsed."];
|
||||
}
|
||||
|
||||
// MARK: - Item Management Tests
|
||||
|
||||
- (void)testAddSplitViewItem
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
[splitViewController view]; // Ensure view is loaded
|
||||
|
||||
var childVC1 = [[CPViewController alloc] init];
|
||||
var item1 = [CPSplitViewItem splitViewItemWithViewController:childVC1];
|
||||
|
||||
[splitViewController addSplitViewItem:item1];
|
||||
|
||||
[self assert:[[splitViewController splitViewItems] count] equals:1 message:@"Should have 1 split view item."];
|
||||
[self assert:[splitViewController splitViewItemForViewController:childVC1] equals:item1 message:@"Should be able to retrieve item by its view controller."];
|
||||
[self assert:[item1 splitViewController] equals:splitViewController message:@"Item should have a reference to its parent controller."];
|
||||
[self assert:[[[splitViewController splitView] arrangedSubviews] count] equals:1 message:@"The splitView should have one arranged subview."];
|
||||
[self assert:[[[childVC1 view] superview] equals:[splitViewController splitView]] message:@"Child's view should be a subview of the splitView."];
|
||||
}
|
||||
|
||||
- (void)testInsertSplitViewItem
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
[splitViewController view];
|
||||
|
||||
var childVC1 = [[CPViewController alloc] init];
|
||||
var childVC2 = [[CPViewController alloc] init];
|
||||
var item1 = [CPSplitViewItem splitViewItemWithViewController:childVC1];
|
||||
var item2 = [CPSplitViewItem splitViewItemWithViewController:childVC2];
|
||||
|
||||
[splitViewController addSplitViewItem:item1];
|
||||
[splitViewController insertSplitViewItem:item2 atIndex:0];
|
||||
|
||||
[self assert:[[splitViewController splitViewItems] count] equals:2 message:@"Should have 2 split view items."];
|
||||
[self assert:[[splitViewController splitViewItems] objectAtIndex:0] equals:item2 message:@"Item2 should be at index 0."];
|
||||
|
||||
var arrangedSubviews = [[splitViewController splitView] arrangedSubviews];
|
||||
[self assert:[arrangedSubviews objectAtIndex:0] equals:[childVC2 view] message:@"The view of item2 should be the first arranged subview."];
|
||||
}
|
||||
|
||||
- (void)testRemoveSplitViewItem
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
[splitViewController view];
|
||||
|
||||
var childVC1 = [[CPViewController alloc] init];
|
||||
var item1 = [CPSplitViewItem splitViewItemWithViewController:childVC1];
|
||||
|
||||
[splitViewController addSplitViewItem:item1];
|
||||
[self assert:[[splitViewController splitViewItems] count] equals:1 message:@"Pre-condition: Should have 1 item."];
|
||||
|
||||
[splitViewController removeSplitViewItem:item1];
|
||||
|
||||
[self assert:[[splitViewController splitViewItems] count] equals:0 message:@"Should have 0 split view items after removal."];
|
||||
[self assertNil:[item1 splitViewController] message:@"Item's reference to parent should be nil after removal."];
|
||||
[self assert:[[[splitViewController splitView] arrangedSubviews] count] equals:0 message:@"The splitView should have no arranged subviews after removal."];
|
||||
[self assertNil:[[childVC1 view] superview] message:@"Child's view should be removed from the splitView."];
|
||||
}
|
||||
|
||||
- (void)testAddingItemsBeforeViewLoads
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
|
||||
var childVC1 = [[CPViewController alloc] init];
|
||||
var childVC2 = [[CPViewController alloc] init];
|
||||
var item1 = [CPSplitViewItem splitViewItemWithViewController:childVC1];
|
||||
var item2 = [CPSplitViewItem splitViewItemWithViewController:childVC2];
|
||||
|
||||
[splitViewController addSplitViewItem:item1];
|
||||
[splitViewController addSplitViewItem:item2];
|
||||
|
||||
[self assert:[[[splitViewController childViewControllers] objectAtIndex:0] equals:childVC1] message:@"Child view controllers should be added immediately."];
|
||||
|
||||
// View is not loaded yet, so it should have no arranged subviews
|
||||
[self assertNil:[splitViewController _splitView] message:@"SplitView should not exist yet."];
|
||||
|
||||
// Trigger viewDidLoad
|
||||
[splitViewController view];
|
||||
|
||||
// Now check if the views were added
|
||||
var arrangedSubviews = [[splitViewController splitView] arrangedSubviews];
|
||||
[self assert:[arrangedSubviews count] equals:2 message:@"SplitView should have 2 subviews after loading."];
|
||||
[self assert:[arrangedSubviews objectAtIndex:0] equals:[childVC1 view]];
|
||||
[self assert:[arrangedSubviews objectAtIndex:1] equals:[childVC2 view]];
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Toggling and State Tests
|
||||
|
||||
- (void)testToggleSidebar
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
var childVC1 = [[CPViewController alloc] init];
|
||||
var item1 = [CPSplitViewItem splitViewItemWithViewController:childVC1];
|
||||
[splitViewController addSplitViewItem:item1];
|
||||
|
||||
[splitViewController toggleSidebar:self];
|
||||
[self assertTrue:[item1 isCollapsed] message:@"Sidebar item should be collapsed."];
|
||||
[self assertTrue:[[childVC1 view] isHidden] message:@"Sidebar view should be hidden."];
|
||||
|
||||
[splitViewController toggleSidebar:self];
|
||||
[self assertFalse:[item1 isCollapsed] message:@"Sidebar item should be expanded again."];
|
||||
[self assertFalse:[[childVC1 view] isHidden] message:@"Sidebar view should be visible again."];
|
||||
}
|
||||
|
||||
- (void)testToggleInspector
|
||||
{
|
||||
var splitViewController = [[CPSplitViewController alloc] init];
|
||||
var childVC1 = [[CPViewController alloc] init];
|
||||
var childVC2 = [[CPViewController alloc] init];
|
||||
var item1 = [CPSplitViewItem splitViewItemWithViewController:childVC1];
|
||||
var item2 = [CPSplitViewItem splitViewItemWithViewController:childVC2];
|
||||
[splitViewController addSplitViewItem:item1];
|
||||
[splitViewController addSplitViewItem:item2];
|
||||
|
||||
[splitViewController toggleInspector:self];
|
||||
[self assertTrue:[item2 isCollapsed] message:@"Inspector item should be collapsed."];
|
||||
[self assertTrue:[[childVC2 view] isHidden] message:@"Inspector view should be hidden."];
|
||||
|
||||
[splitViewController toggleInspector:self];
|
||||
[self assertFalse:[item2 isCollapsed] message:@"Inspector item should be expanded again."];
|
||||
[self assertFalse:[[childVC2 view] isHidden] message:@"Inspector view should be visible again."];
|
||||
}
|
||||
|
||||
- (void)testSetCollapsed
|
||||
{
|
||||
var childVC = [[CPViewController alloc] init];
|
||||
var item = [CPSplitViewItem splitViewItemWithViewController:childVC];
|
||||
var childView = [childVC view];
|
||||
|
||||
[item setCollapsed:YES];
|
||||
[self assertTrue:[item isCollapsed] message:@"Item's collapsed property should be YES."];
|
||||
[self assertTrue:[childView isHidden] message:@"The item's view should be hidden."];
|
||||
|
||||
[item setCollapsed:NO];
|
||||
[self assertFalse:[item isCollapsed] message:@"Item's collapsed property should be NO."];
|
||||
[self assertFalse:[childView isHidden] message:@"The item's view should be visible."];
|
||||
|
||||
// Test idempotency
|
||||
[item setCollapsed:NO];
|
||||
[self assertFalse:[item isCollapsed] message:@"Setting the same value should have no effect."];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in new issue
Block a user