Skip to content

Instantly share code, notes, and snippets.

@ciiqr
Last active August 29, 2015 13:58
Show Gist options
  • Save ciiqr/10425684 to your computer and use it in GitHub Desktop.
Save ciiqr/10425684 to your computer and use it in GitHub Desktop.
Bookmarks Bar Layout for BMarks Bar - Chrome
// BookmarksBar Layout code from BMarks Bar - Chrome (iOS Tweak)
// User Settings
// DISPLAY_OTHER_BOOKMARKS_ITEM = [YES|NO]
// DISPLAY_REST_BOOKMARKS_ITEM = [YES|NO]
// ...
// Application Constants
// #define kEdgeSpacing 9.f
// #define kItemSpacing 10.f
// ...
// Bookmark Bars layout subviews
// - Determines Bookmark Sizes
// - Spaces out items appropriately
// - Add/Remove bookmarks on rotate & when bookmarks change
// - Dismisses folder popovers (future, reposition them)
// - Adds a "Rest" item for any bookmarks that do not fit (Dependent on User Settings)
// - Adds a right aligned, always there "Other" bookmarks item (Dependent on User Settings)
- (void)layoutSubviews
{
// Super
[super layoutSubviews];
// Bookmarks
NSArray *items = _items;
// Number of Bookmarks
NSUInteger itemsCount = items.count;
// xOffset of Bookamrks
CGFloat xOffset = kEdgeSpacing;
// Bar Width
CGFloat barWidth = self.bounds.size.width;
// Add Other Item
if (DISPLAY_OTHER_BOOKMARKS_ITEM && itemsCount > 0)
{
// Retrieve From Items (Should always be the last Item, if DISPLAY_OTHER_BOOKMARKS_ITEM is YES)
WVBookmarkItem *otherBookmarkItem = [items lastObject]; // is the Other Bookmark Item
// Others View
UIView *otherView = otherBookmarkItem.customView;
// Position
CGRect otherFrame = otherView.frame;
CGFloat otherWidth = otherFrame.size.width + kEdgeSpacing;
otherFrame.origin.x = barWidth - otherWidth;
otherView.frame = otherFrame;
// Reduce Bar Width So Items Dont Over Lap Other
barWidth -= otherWidth;
// Prevent loop Messing with Other Item
itemsCount--;
}
// Create Rest Item (So we know Size & Can Add it if Needed)
CGFloat restItemWidth = 0;
if (DISPLAY_REST_BOOKMARKS_ITEM && itemsCount > 0)
{
if (!_restItem) // If it doesn't exist, create
_restItem = [WVBookmarkItem restItemTypeWithTarget:self];
// Rest View
UIView *restView = _restItem.customView;
// Position
CGRect restFrame = restView.frame;
restItemWidth = restFrame.size.width; // Rest Includes its Own Tappable Spacing
restFrame.origin.x = barWidth - restItemWidth;
restView.frame = restFrame;
}
// Add Items
for (NSUInteger index = 0; index < itemsCount; index++)
{
// BookmarkItem
WVBookmarkItem *bookmarkItem = items[index];
UIView *bookmarkView = bookmarkItem.customView;
// If bookmarkView in not in superView, add to superview (For When Rotating and adding more items)
if (!bookmarkView.superview)
[self addSubview:bookmarkView];
// Item Width & Location
CGRect itemFrame = bookmarkView.frame;
CGFloat itemWidth = itemFrame.size.width;
itemFrame.origin.x = xOffset;
bookmarkView.frame = itemFrame;
// Set the next items X Offset
xOffset += (itemWidth + kItemSpacing);
BOOL fitsOnBar = (xOffset < barWidth);
BOOL sufficientSpaceForRestItem = ((barWidth - xOffset) >= restItemWidth);
BOOL lastItem = ((index + 1) == itemsCount);
// Rest Item is Not Needed
if (lastItem && fitsOnBar)
{
// Remove if it was previously on the bar
[_restItem.customView removeFromSuperview];
// Popover is Showing Rest Item
if ([_popover isPopoverVisible] && (((WVBookmarksTVC *)_popover.contentViewController).bookmarkItem == _restItem))
{
// Dismiss Popover
if ([_popover.delegate popoverControllerShouldDismissPopover:_popover])
{
[_popover dismissPopoverAnimated:NO];
[_popover.delegate popoverControllerDidDismissPopover:_popover];
}
}
}
if (fitsOnBar && (sufficientSpaceForRestItem || lastItem))
{
// Items is going to be added to the bar...
// Dismiss OR Reposition Popover (W.I.P.)
if (lastItem && _popover.isPopoverVisible)
{
#ifdef TESTING_POPOVER_REPOSITION
// is Normal Bar Item... I Think (or rest.children.children OR Lower (FixWith WVBookmarkItem - (BOOL)reccursiveChildrenContainsItem:(WVBookmarkItem *)item))
[_popover repositionPopoverFromRect:bookmarkItem.customView.frame
inView:bookmarkItem.customView
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
#else
// Dismiss Popover
if ([_popover.delegate popoverControllerShouldDismissPopover:_popover])
{
[_popover dismissPopoverAnimated:NO];
[_popover.delegate popoverControllerDidDismissPopover:_popover];
}
#endif // TESTING_POPOVER_REPOSITION //
}
}
else // Item wont be displayed, add it (and the rest) to the restItem
{
// Get The Rest of The Items
NSArray *remainingItems = [items subarrayWithRange:NSMakeRange(index, itemsCount - index)];
// Remove Items Views From Bar
[remainingItems enumerateObjectsUsingBlock: ^(WVBookmarkItem *remainingBookmarkItem, NSUInteger idx, BOOL *stop)
{
[remainingBookmarkItem.customView removeFromSuperview];
}];
// Set the Rest Items Children to the Remaining Items
_restItem.children = remainingItems;
// Add RestItem if it isn't already on the bar
if (!_restItem.customView.superview)
[self addSubview:_restItem.customView];
// #warning BELOW
// For Right Now we are going to dismiss on rotate (but the infastructure is here NOT too, just have to figure out why it does not position the popover properly)
// ^^ May have to create a new popover with rotate
// if Popover is Visible (restItem, display its items)
// ^^ If Not Rest But is now inside rest dismiss
if ([_popover isPopoverVisible])
{
WVBookmarkItem *popoverBookmarkItem = ((WVBookmarksTVC *)_popover.contentViewController).bookmarkItem;
if (popoverBookmarkItem == _restItem)
{
// Dismiss
[_popover dismissPopoverAnimated:NO];
// ReShow Rest Popover with new items if it was visible before
if (_restItem.children.count > 0)
{
#ifdef TESTING_POPOVER_REPOSITION
WVBookmarksTVC *newRestVC = [[WVBookmarksTVC alloc] initWithBookmarkItem:_restItem delegate:self];
_popover.contentViewController = newRestVC;
// Set Popover Size Based on ViewController Size
_popover.popoverContentSize = newRestVC.contentSizeForViewInPopover;
// Present Popover
UIView *customView = _currentBookmarkItem.customView;
[_popover presentPopoverFromRect:customView.frame
inView:customView.superview
permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
#else
// Dismiss Popover
if ([_popover.delegate popoverControllerShouldDismissPopover:_popover])
{
[_popover dismissPopoverAnimated:NO];
[_popover.delegate popoverControllerDidDismissPopover:_popover];
}
#endif // TESTING_POPOVER_REPOSITION //
}
}
// if Item is in Rest then dismiss
else if ([_restItem.children containsObject:popoverBookmarkItem])
{
// Dismiss Popover
if ([_popover.delegate popoverControllerShouldDismissPopover:_popover])
{
[_popover dismissPopoverAnimated:NO];
[_popover.delegate popoverControllerDidDismissPopover:_popover];
}
}
// is Normal Bar Item... I Think (or rest.children.children OR Lower (FixWith WVBookmarkItem - (BOOL)reccursiveChildrenContainsItem:(WVBookmarkItem *)item))
else //if item is on bar & visible (has SuperView)
{
#ifdef TESTING_POPOVER_REPOSITION
// is Normal Bar Item... I Think (or rest.children.children OR Lower (FixWith WVBookmarkItem - (BOOL)reccursiveChildrenContainsItem:(WVBookmarkItem *)item))
[_popover repositionPopoverFromRect:bookmarkItem.customView.frame
inView:bookmarkItem.customView
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
#else
// Dismiss Popover
if ([_popover.delegate popoverControllerShouldDismissPopover:_popover])
{
[_popover dismissPopoverAnimated:NO];
[_popover.delegate popoverControllerDidDismissPopover:_popover];
}
#endif // TESTING_POPOVER_REPOSITION //
}
}
break; // Because The Rest of the items are in the "rest item"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment