added files via upload

This commit is contained in:
Balackburn
2023-06-27 09:54:41 +02:00
commit 2ff6aac218
1420 changed files with 88898 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
//
// FLEXExplorerToolbar.h
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FLEXExplorerToolbarItem;
NS_ASSUME_NONNULL_BEGIN
/// Users of the toolbar can configure the enabled state
/// and event target/actions for each item.
@interface FLEXExplorerToolbar : UIView
/// The items to be displayed in the toolbar. Defaults to:
/// globalsItem, hierarchyItem, selectItem, moveItem, closeItem
@property (nonatomic, copy) NSArray<FLEXExplorerToolbarItem *> *toolbarItems;
/// Toolbar item for selecting views.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *selectItem;
/// Toolbar item for presenting a list with the view hierarchy.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *hierarchyItem;
/// Toolbar item for moving views.
/// Its \c sibling is the \c lastTabItem
@property (nonatomic, readonly) FLEXExplorerToolbarItem *moveItem;
/// Toolbar item for presenting the currently active tab.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *recentItem;
/// Toolbar item for presenting a screen with various tools for inspecting the app.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *globalsItem;
/// Toolbar item for hiding the explorer.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *closeItem;
/// A view for moving the entire toolbar.
/// Users of the toolbar can attach a pan gesture recognizer to decide how to reposition the toolbar.
@property (nonatomic, readonly) UIView *dragHandle;
/// A color matching the overlay on color on the selected view.
@property (nonatomic) UIColor *selectedViewOverlayColor;
/// Description text for the selected view displayed below the toolbar items.
@property (nonatomic, copy) NSString *selectedViewDescription;
/// Area where details of the selected view are shown
/// Users of the toolbar can attach a tap gesture recognizer to show additional details.
@property (nonatomic, readonly) UIView *selectedViewDescriptionContainer;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,256 @@
//
// FLEXExplorerToolbar.m
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import "FLEXColor.h"
#import "FLEXExplorerToolbar.h"
#import "FLEXExplorerToolbarItem.h"
#import "FLEXResources.h"
#import "FLEXUtility.h"
@interface FLEXExplorerToolbar ()
@property (nonatomic, readwrite) FLEXExplorerToolbarItem *globalsItem;
@property (nonatomic, readwrite) FLEXExplorerToolbarItem *hierarchyItem;
@property (nonatomic, readwrite) FLEXExplorerToolbarItem *selectItem;
@property (nonatomic, readwrite) FLEXExplorerToolbarItem *recentItem;
@property (nonatomic, readwrite) FLEXExplorerToolbarItem *moveItem;
@property (nonatomic, readwrite) FLEXExplorerToolbarItem *closeItem;
@property (nonatomic, readwrite) UIView *dragHandle;
@property (nonatomic) UIImageView *dragHandleImageView;
@property (nonatomic) UIView *selectedViewDescriptionContainer;
@property (nonatomic) UIView *selectedViewDescriptionSafeAreaContainer;
@property (nonatomic) UIView *selectedViewColorIndicator;
@property (nonatomic) UILabel *selectedViewDescriptionLabel;
@property (nonatomic,readwrite) UIView *backgroundView;
@end
@implementation FLEXExplorerToolbar
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Background
self.backgroundView = [UIView new];
self.backgroundView.backgroundColor = [FLEXColor secondaryBackgroundColorWithAlpha:0.95];
[self addSubview:self.backgroundView];
// Drag handle
self.dragHandle = [UIView new];
self.dragHandle.backgroundColor = UIColor.clearColor;
self.dragHandleImageView = [[UIImageView alloc] initWithImage:FLEXResources.dragHandle];
self.dragHandleImageView.tintColor = [FLEXColor.iconColor colorWithAlphaComponent:0.666];
[self.dragHandle addSubview:self.dragHandleImageView];
[self addSubview:self.dragHandle];
// Buttons
self.globalsItem = [FLEXExplorerToolbarItem itemWithTitle:@"menu" image:FLEXResources.globalsIcon];
self.hierarchyItem = [FLEXExplorerToolbarItem itemWithTitle:@"views" image:FLEXResources.hierarchyIcon];
self.selectItem = [FLEXExplorerToolbarItem itemWithTitle:@"select" image:FLEXResources.selectIcon];
self.recentItem = [FLEXExplorerToolbarItem itemWithTitle:@"recent" image:FLEXResources.recentIcon];
self.moveItem = [FLEXExplorerToolbarItem itemWithTitle:@"move" image:FLEXResources.moveIcon sibling:self.recentItem];
self.closeItem = [FLEXExplorerToolbarItem itemWithTitle:@"close" image:FLEXResources.closeIcon];
// Selected view box //
self.selectedViewDescriptionContainer = [UIView new];
self.selectedViewDescriptionContainer.backgroundColor = [FLEXColor tertiaryBackgroundColorWithAlpha:0.95];
self.selectedViewDescriptionContainer.hidden = YES;
[self addSubview:self.selectedViewDescriptionContainer];
self.selectedViewDescriptionSafeAreaContainer = [UIView new];
self.selectedViewDescriptionSafeAreaContainer.backgroundColor = UIColor.clearColor;
[self.selectedViewDescriptionContainer addSubview:self.selectedViewDescriptionSafeAreaContainer];
self.selectedViewColorIndicator = [UIView new];
self.selectedViewColorIndicator.backgroundColor = UIColor.redColor;
[self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewColorIndicator];
self.selectedViewDescriptionLabel = [UILabel new];
self.selectedViewDescriptionLabel.backgroundColor = UIColor.clearColor;
self.selectedViewDescriptionLabel.font = [[self class] descriptionLabelFont];
[self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewDescriptionLabel];
// toolbarItems
self.toolbarItems = @[_globalsItem, _hierarchyItem, _selectItem, _moveItem, _closeItem];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect safeArea = [self safeArea];
// Drag Handle
const CGFloat kToolbarItemHeight = [[self class] toolbarItemHeight];
self.dragHandle.frame = CGRectMake(CGRectGetMinX(safeArea), CGRectGetMinY(safeArea), [[self class] dragHandleWidth], kToolbarItemHeight);
CGRect dragHandleImageFrame = self.dragHandleImageView.frame;
dragHandleImageFrame.origin.x = FLEXFloor((self.dragHandle.frame.size.width - dragHandleImageFrame.size.width) / 2.0);
dragHandleImageFrame.origin.y = FLEXFloor((self.dragHandle.frame.size.height - dragHandleImageFrame.size.height) / 2.0);
self.dragHandleImageView.frame = dragHandleImageFrame;
// Toolbar Items
CGFloat originX = CGRectGetMaxX(self.dragHandle.frame);
CGFloat originY = CGRectGetMinY(safeArea);
CGFloat height = kToolbarItemHeight;
CGFloat width = FLEXFloor((CGRectGetWidth(safeArea) - CGRectGetWidth(self.dragHandle.frame)) / self.toolbarItems.count);
for (FLEXExplorerToolbarItem *toolbarItem in self.toolbarItems) {
toolbarItem.currentItem.frame = CGRectMake(originX, originY, width, height);
originX = CGRectGetMaxX(toolbarItem.currentItem.frame);
}
// Make sure the last toolbar item goes to the edge to account for any accumulated rounding effects.
UIView *lastToolbarItem = self.toolbarItems.lastObject.currentItem;
CGRect lastToolbarItemFrame = lastToolbarItem.frame;
lastToolbarItemFrame.size.width = CGRectGetMaxX(safeArea) - lastToolbarItemFrame.origin.x;
lastToolbarItem.frame = lastToolbarItemFrame;
self.backgroundView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), kToolbarItemHeight);
const CGFloat kSelectedViewColorDiameter = [[self class] selectedViewColorIndicatorDiameter];
const CGFloat kDescriptionLabelHeight = [[self class] descriptionLabelHeight];
const CGFloat kHorizontalPadding = [[self class] horizontalPadding];
const CGFloat kDescriptionVerticalPadding = [[self class] descriptionVerticalPadding];
const CGFloat kDescriptionContainerHeight = [[self class] descriptionContainerHeight];
CGRect descriptionContainerFrame = CGRectZero;
descriptionContainerFrame.size.width = CGRectGetWidth(self.bounds);
descriptionContainerFrame.size.height = kDescriptionContainerHeight;
descriptionContainerFrame.origin.x = CGRectGetMinX(self.bounds);
descriptionContainerFrame.origin.y = CGRectGetMaxY(self.bounds) - kDescriptionContainerHeight;
self.selectedViewDescriptionContainer.frame = descriptionContainerFrame;
CGRect descriptionSafeAreaContainerFrame = CGRectZero;
descriptionSafeAreaContainerFrame.size.width = CGRectGetWidth(safeArea);
descriptionSafeAreaContainerFrame.size.height = kDescriptionContainerHeight;
descriptionSafeAreaContainerFrame.origin.x = CGRectGetMinX(safeArea);
descriptionSafeAreaContainerFrame.origin.y = CGRectGetMinY(safeArea);
self.selectedViewDescriptionSafeAreaContainer.frame = descriptionSafeAreaContainerFrame;
// Selected View Color
CGRect selectedViewColorFrame = CGRectZero;
selectedViewColorFrame.size.width = kSelectedViewColorDiameter;
selectedViewColorFrame.size.height = kSelectedViewColorDiameter;
selectedViewColorFrame.origin.x = kHorizontalPadding;
selectedViewColorFrame.origin.y = FLEXFloor((kDescriptionContainerHeight - kSelectedViewColorDiameter) / 2.0);
self.selectedViewColorIndicator.frame = selectedViewColorFrame;
self.selectedViewColorIndicator.layer.cornerRadius = ceil(selectedViewColorFrame.size.height / 2.0);
// Selected View Description
CGRect descriptionLabelFrame = CGRectZero;
CGFloat descriptionOriginX = CGRectGetMaxX(selectedViewColorFrame) + kHorizontalPadding;
descriptionLabelFrame.size.height = kDescriptionLabelHeight;
descriptionLabelFrame.origin.x = descriptionOriginX;
descriptionLabelFrame.origin.y = kDescriptionVerticalPadding;
descriptionLabelFrame.size.width = CGRectGetMaxX(self.selectedViewDescriptionContainer.bounds) - kHorizontalPadding - descriptionOriginX;
self.selectedViewDescriptionLabel.frame = descriptionLabelFrame;
}
#pragma mark - Setter Overrides
- (void)setToolbarItems:(NSArray<FLEXExplorerToolbarItem *> *)toolbarItems {
if (_toolbarItems == toolbarItems) {
return;
}
// Remove old toolbar items, if any
for (FLEXExplorerToolbarItem *item in _toolbarItems) {
[item.currentItem removeFromSuperview];
}
// Trim to 5 items if necessary
if (toolbarItems.count > 5) {
toolbarItems = [toolbarItems subarrayWithRange:NSMakeRange(0, 5)];
}
for (FLEXExplorerToolbarItem *item in toolbarItems) {
[self addSubview:item.currentItem];
}
_toolbarItems = toolbarItems.copy;
// Lay out new items
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setSelectedViewOverlayColor:(UIColor *)selectedViewOverlayColor {
if (![_selectedViewOverlayColor isEqual:selectedViewOverlayColor]) {
_selectedViewOverlayColor = selectedViewOverlayColor;
self.selectedViewColorIndicator.backgroundColor = selectedViewOverlayColor;
}
}
- (void)setSelectedViewDescription:(NSString *)selectedViewDescription {
if (![_selectedViewDescription isEqual:selectedViewDescription]) {
_selectedViewDescription = selectedViewDescription;
self.selectedViewDescriptionLabel.text = selectedViewDescription;
BOOL showDescription = selectedViewDescription.length > 0;
self.selectedViewDescriptionContainer.hidden = !showDescription;
}
}
#pragma mark - Sizing Convenience Methods
+ (UIFont *)descriptionLabelFont {
return [UIFont systemFontOfSize:12.0];
}
+ (CGFloat)toolbarItemHeight {
return 44.0;
}
+ (CGFloat)dragHandleWidth {
return FLEXResources.dragHandle.size.width;
}
+ (CGFloat)descriptionLabelHeight {
return ceil([[self descriptionLabelFont] lineHeight]);
}
+ (CGFloat)descriptionVerticalPadding {
return 2.0;
}
+ (CGFloat)descriptionContainerHeight {
return [self descriptionVerticalPadding] * 2.0 + [self descriptionLabelHeight];
}
+ (CGFloat)selectedViewColorIndicatorDiameter {
return ceil([self descriptionLabelHeight] / 2.0);
}
+ (CGFloat)horizontalPadding {
return 11.0;
}
- (CGSize)sizeThatFits:(CGSize)size {
CGFloat height = 0.0;
height += [[self class] toolbarItemHeight];
height += [[self class] descriptionContainerHeight];
return CGSizeMake(size.width, height);
}
- (CGRect)safeArea {
CGRect safeArea = self.bounds;
if (@available(iOS 11.0, *)) {
safeArea = UIEdgeInsetsInsetRect(self.bounds, self.safeAreaInsets);
}
return safeArea;
}
@end

View File

@@ -0,0 +1,44 @@
//
// FLEXExplorerToolbarItem.h
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FLEXExplorerToolbarItem : UIButton
+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image;
/// @param backupItem a toolbar item to use in place of this item when it becomes disabled.
/// Items without a sibling item exhibit expected behavior when they become disabled, and are greyed out.
+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image sibling:(nullable FLEXExplorerToolbarItem *)backupItem;
/// If a toolbar item has a sibling, the item will replace itself with its
/// sibling when it becomes disabled, and vice versa when it becomes enabled again.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *sibling;
/// When a toolbar item has a sibling and it becomes disabled, the sibling is the view
/// that should be added to or removed from a new or existing toolbar. This property
/// alleviates the programmer from determining whether to use \c item or \c item.sibling
/// or \c item.sibling.sibling and so on. Yes, sibling items can also have siblings so
/// that each item which becomes disabled may present another item in its place, creating
/// a "stack" of toolbar items. This behavior is useful for making buttons which occupy
/// the same space under different states.
///
/// With this in mind, you should never access a stored toolbar item's view properties
/// such as \c frame or \c superview directly; you should access them on \c currentItem.
/// If you are trying to modify the frame of an item, and the item itself is not currently
/// displayed but instead its sibling is being displayed, then your changes could be ignored.
///
/// @return the result of the item's sibling's \c currentItem,
/// if this item has a sibling and this item is disabled, otherwise this item.
@property (nonatomic, readonly) FLEXExplorerToolbarItem *currentItem;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,155 @@
//
// FLEXExplorerToolbarItem.m
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import "FLEXColor.h"
#import "FLEXExplorerToolbarItem.h"
#import "FLEXUtility.h"
@interface FLEXExplorerToolbarItem ()
@property (nonatomic) FLEXExplorerToolbarItem *sibling;
@property (nonatomic, copy) NSString *title;
@property (nonatomic) UIImage *image;
@property (nonatomic, readonly, class) UIColor *defaultBackgroundColor;
@property (nonatomic, readonly, class) UIColor *highlightedBackgroundColor;
@property (nonatomic, readonly, class) UIColor *selectedBackgroundColor;
@end
@implementation FLEXExplorerToolbarItem
#pragma mark - Public
+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image {
return [self itemWithTitle:title image:image sibling:nil];
}
+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image sibling:(FLEXExplorerToolbarItem *)backupItem {
NSParameterAssert(title); NSParameterAssert(image);
FLEXExplorerToolbarItem *toolbarItem = [self buttonWithType:UIButtonTypeSystem];
toolbarItem.sibling = backupItem;
toolbarItem.title = title;
toolbarItem.image = image;
toolbarItem.tintColor = FLEXColor.iconColor;
toolbarItem.backgroundColor = self.defaultBackgroundColor;
toolbarItem.titleLabel.font = [UIFont systemFontOfSize:12.0];
[toolbarItem setTitle:title forState:UIControlStateNormal];
[toolbarItem setImage:image forState:UIControlStateNormal];
[toolbarItem setTitleColor:FLEXColor.primaryTextColor forState:UIControlStateNormal];
[toolbarItem setTitleColor:FLEXColor.deemphasizedTextColor forState:UIControlStateDisabled];
return toolbarItem;
}
- (FLEXExplorerToolbarItem *)currentItem {
if (!self.enabled && self.sibling) {
return self.sibling.currentItem;
}
return self;
}
#pragma mark - Display Defaults
+ (NSDictionary<NSString *, id> *)titleAttributes {
return @{ NSFontAttributeName : [UIFont systemFontOfSize:12.0] };
}
+ (UIColor *)highlightedBackgroundColor {
return FLEXColor.toolbarItemHighlightedColor;
}
+ (UIColor *)selectedBackgroundColor {
return FLEXColor.toolbarItemSelectedColor;
}
+ (UIColor *)defaultBackgroundColor {
return UIColor.clearColor;
}
+ (CGFloat)topMargin {
return 2.0;
}
#pragma mark - State Changes
- (void)setHighlighted:(BOOL)highlighted {
super.highlighted = highlighted;
[self updateColors];
}
- (void)setSelected:(BOOL)selected {
super.selected = selected;
[self updateColors];
}
- (void)setEnabled:(BOOL)enabled {
if (self.enabled != enabled) {
if (self.sibling) {
if (enabled) { // Replace sibling with myself
UIView *superview = self.sibling.superview;
[self.sibling removeFromSuperview];
self.frame = self.sibling.frame;
[superview addSubview:self];
} else { // Replace myself with sibling
UIView *superview = self.superview;
[self removeFromSuperview];
self.sibling.frame = self.frame;
[superview addSubview:self.sibling];
}
}
super.enabled = enabled;
}
}
+ (id)_selectedIndicatorImage { return nil; }
- (void)updateColors {
// Background color
if (self.highlighted) {
self.backgroundColor = self.class.highlightedBackgroundColor;
} else if (self.selected) {
self.backgroundColor = self.class.selectedBackgroundColor;
} else {
self.backgroundColor = self.class.defaultBackgroundColor;
}
}
#pragma mark - UIButton Layout Overrides
- (CGRect)titleRectForContentRect:(CGRect)contentRect {
NSDictionary *attrs = [[self class] titleAttributes];
// Bottom aligned and centered.
CGRect titleRect = CGRectZero;
CGSize titleSize = [self.title boundingRectWithSize:contentRect.size
options:0
attributes:attrs
context:nil].size;
titleSize = CGSizeMake(ceil(titleSize.width), ceil(titleSize.height));
titleRect.size = titleSize;
titleRect.origin.y = contentRect.origin.y + CGRectGetMaxY(contentRect) - titleSize.height;
titleRect.origin.x = contentRect.origin.x + FLEXFloor((contentRect.size.width - titleSize.width) / 2.0);
return titleRect;
}
- (CGRect)imageRectForContentRect:(CGRect)contentRect {
CGSize imageSize = self.image.size;
CGRect titleRect = [self titleRectForContentRect:contentRect];
CGFloat availableHeight = contentRect.size.height - titleRect.size.height - [[self class] topMargin];
CGFloat originY = [[self class] topMargin] + FLEXFloor((availableHeight - imageSize.height) / 2.0);
CGFloat originX = FLEXFloor((contentRect.size.width - imageSize.width) / 2.0);
CGRect imageRect = CGRectMake(originX, originY, imageSize.width, imageSize.height);
return imageRect;
}
@end