mirror of
https://github.com/danog/Telegram.git
synced 2024-12-02 09:27:55 +01:00
355 lines
8.2 KiB
Objective-C
355 lines
8.2 KiB
Objective-C
#import "TGModernViewModel.h"
|
|
|
|
#import "TGModernView.h"
|
|
|
|
@interface TGModernViewModelId : NSObject <NSCopying>
|
|
|
|
@end
|
|
|
|
@implementation TGModernViewModelId
|
|
|
|
- (instancetype)copyWithZone:(NSZone *)__unused zone
|
|
{
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface TGModernViewModel ()
|
|
{
|
|
UIView<TGModernView> *_view;
|
|
|
|
NSString *_viewIdentifier;
|
|
NSMutableArray *_submodels;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGModernViewModel
|
|
|
|
- (instancetype)init
|
|
{
|
|
self = [super init];
|
|
if (self != nil)
|
|
{
|
|
_alpha = 1.0f;
|
|
_modelId = [[TGModernViewModelId alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (bool)hasNoView
|
|
{
|
|
return _modelFlags.hasNoView;
|
|
}
|
|
|
|
- (void)setHasNoView:(bool)hasNoView
|
|
{
|
|
_modelFlags.hasNoView = hasNoView;
|
|
}
|
|
|
|
- (bool)skipDrawInContext
|
|
{
|
|
return _modelFlags.skipDrawInContext;
|
|
}
|
|
|
|
- (void)setSkipDrawInContext:(bool)skipDrawInContext
|
|
{
|
|
_modelFlags.skipDrawInContext = skipDrawInContext;
|
|
}
|
|
|
|
- (bool)disableSubmodelAutomaticBinding
|
|
{
|
|
return _modelFlags.disableSubmodelAutomaticBinding;
|
|
}
|
|
|
|
- (void)setDisableSubmodelAutomaticBinding:(bool)disableSubmodelAutomaticBinding
|
|
{
|
|
_modelFlags.disableSubmodelAutomaticBinding = disableSubmodelAutomaticBinding;
|
|
}
|
|
|
|
- (bool)viewUserInteractionDisabled
|
|
{
|
|
return _modelFlags.viewUserInteractionDisabled;
|
|
}
|
|
|
|
- (void)setViewUserInteractionDisabled:(bool)viewUserInteractionDisabled
|
|
{
|
|
if (_modelFlags.viewUserInteractionDisabled != viewUserInteractionDisabled)
|
|
{
|
|
_modelFlags.viewUserInteractionDisabled = viewUserInteractionDisabled;
|
|
_view.userInteractionEnabled = !viewUserInteractionDisabled;
|
|
}
|
|
}
|
|
|
|
- (Class)viewClass
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
- (UIView<TGModernView> *)_dequeueView:(TGModernViewStorage *)viewStorage
|
|
{
|
|
if (_viewIdentifier == nil)
|
|
_viewIdentifier = NSStringFromClass([self viewClass]);
|
|
|
|
UIView<TGModernView> *view = [viewStorage dequeueViewWithIdentifier:_viewIdentifier viewStateIdentifier:_viewStateIdentifier];
|
|
if (view == nil)
|
|
{
|
|
view = [[[self viewClass] alloc] init];
|
|
[view setViewIdentifier:_viewIdentifier];
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
- (UIView<TGModernView> *)boundView
|
|
{
|
|
return _view;
|
|
}
|
|
|
|
- (void)bindViewToContainer:(UIView *)container viewStorage:(TGModernViewStorage *)viewStorage
|
|
{
|
|
if (!_modelFlags.hasNoView)
|
|
_view = [self _dequeueView:viewStorage];
|
|
|
|
if (_view != nil || _modelFlags.hasNoView)
|
|
{
|
|
if (!_modelFlags.hasNoView)
|
|
{
|
|
[container addSubview:_view];
|
|
|
|
[_view setFrame:CGRectOffset(_frame, _parentOffset.x, _parentOffset.y)];
|
|
[_view setAlpha:_alpha];
|
|
[_view setHidden:_hidden];
|
|
|
|
_view.userInteractionEnabled = !_modelFlags.viewUserInteractionDisabled;
|
|
}
|
|
|
|
bool disableSubmodelAutomaticBinding = _modelFlags.disableSubmodelAutomaticBinding;
|
|
|
|
for (TGModernViewModel *submodel in self.submodels)
|
|
{
|
|
if (!disableSubmodelAutomaticBinding || submodel.skipDrawInContext)
|
|
[submodel bindViewToContainer:_modelFlags.hasNoView ? container : _view viewStorage:viewStorage];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)unbindView:(TGModernViewStorage *)viewStorage
|
|
{
|
|
if (_unbindAction)
|
|
_unbindAction();
|
|
|
|
for (TGModernViewModel *submodel in self.submodels)
|
|
{
|
|
[submodel unbindView:viewStorage];
|
|
}
|
|
|
|
if (_view != nil)
|
|
{
|
|
[_view removeFromSuperview];
|
|
[viewStorage enqueueView:_view];
|
|
_view = nil;
|
|
}
|
|
}
|
|
|
|
- (void)moveViewToContainer:(UIView *)container
|
|
{
|
|
if (!_modelFlags.hasNoView)
|
|
{
|
|
if (_view != nil)
|
|
[container addSubview:_view];
|
|
}
|
|
else
|
|
{
|
|
bool disableSubmodelAutomaticBinding = _modelFlags.disableSubmodelAutomaticBinding;
|
|
|
|
for (TGModernViewModel *submodel in self.submodels)
|
|
{
|
|
if (!disableSubmodelAutomaticBinding || submodel.skipDrawInContext)
|
|
[submodel moveViewToContainer:container];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)_offsetBoundViews:(CGSize)offset
|
|
{
|
|
if (!_modelFlags.hasNoView)
|
|
{
|
|
if (_view != nil)
|
|
_view.frame = CGRectOffset(_view.frame, offset.width, offset.height);
|
|
}
|
|
else
|
|
{
|
|
bool disableSubmodelAutomaticBinding = _modelFlags.disableSubmodelAutomaticBinding;
|
|
|
|
for (TGModernViewModel *submodel in self.submodels)
|
|
{
|
|
if (!disableSubmodelAutomaticBinding || submodel.skipDrawInContext)
|
|
[submodel _offsetBoundViews:offset];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setFrame:(CGRect)frame
|
|
{
|
|
_frame = frame;
|
|
|
|
if (_view != nil)
|
|
[_view setFrame:CGRectOffset(_frame, _parentOffset.x, _parentOffset.y)];
|
|
}
|
|
|
|
- (void)setParentOffset:(CGPoint)parentOffset
|
|
{
|
|
_parentOffset = parentOffset;
|
|
}
|
|
|
|
- (void)setAlpha:(float)alpha
|
|
{
|
|
_alpha = alpha;
|
|
|
|
if (_view != nil)
|
|
[_view setAlpha:alpha];
|
|
}
|
|
|
|
- (void)setHidden:(bool)hidden
|
|
{
|
|
_hidden = hidden;
|
|
|
|
if (_view != nil)
|
|
[_view setHidden:hidden];
|
|
}
|
|
|
|
- (void)drawInContext:(CGContextRef)context
|
|
{
|
|
if (_modelFlags.skipDrawInContext || _hidden || _alpha < FLT_EPSILON)
|
|
return;
|
|
|
|
[self drawSubmodelsInContext:context];
|
|
}
|
|
|
|
- (void)drawSubmodelsInContext:(CGContextRef)context
|
|
{
|
|
for (TGModernViewModel *submodel in self.submodels)
|
|
{
|
|
CGRect frame = submodel.frame;
|
|
CGContextTranslateCTM(context, frame.origin.x, frame.origin.y);
|
|
[submodel drawInContext:context];
|
|
CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
|
|
}
|
|
}
|
|
|
|
- (void)sizeToFit
|
|
{
|
|
}
|
|
|
|
- (CGRect)bounds
|
|
{
|
|
return CGRectMake(0, 0, _frame.size.width, _frame.size.height);
|
|
}
|
|
|
|
- (NSArray *)submodels
|
|
{
|
|
return _submodels;
|
|
}
|
|
|
|
- (bool)containsSubmodel:(TGModernViewModel *)model
|
|
{
|
|
return _submodels != nil && [_submodels containsObject:model];
|
|
}
|
|
|
|
- (void)addSubmodel:(TGModernViewModel *)model
|
|
{
|
|
if (model == nil)
|
|
return;
|
|
|
|
if (_submodels == nil)
|
|
_submodels = [[NSMutableArray alloc] init];
|
|
|
|
[_submodels addObject:model];
|
|
}
|
|
|
|
- (void)insertSubmodel:(TGModernViewModel *)model belowSubmodel:(TGModernViewModel *)belowSubmodel {
|
|
if (model == nil)
|
|
return;
|
|
|
|
if (_submodels == nil)
|
|
_submodels = [[NSMutableArray alloc] init];
|
|
|
|
NSUInteger index = [_submodels indexOfObject:belowSubmodel];
|
|
if (index != NSNotFound)
|
|
[_submodels insertObject:model atIndex:index];
|
|
else
|
|
[_submodels addObject:model];
|
|
}
|
|
|
|
- (void)insertSubmodel:(TGModernViewModel *)model aboveSubmodel:(TGModernViewModel *)aboveSubmodel
|
|
{
|
|
if (model == nil)
|
|
return;
|
|
|
|
if (_submodels == nil)
|
|
_submodels = [[NSMutableArray alloc] init];
|
|
|
|
NSUInteger index = [_submodels indexOfObject:aboveSubmodel];
|
|
if (index != NSNotFound)
|
|
[_submodels insertObject:model atIndex:index + 1];
|
|
else
|
|
[_submodels addObject:model];
|
|
}
|
|
|
|
- (void)removeSubmodel:(TGModernViewModel *)model viewStorage:(TGModernViewStorage *)viewStorage
|
|
{
|
|
if (model == nil)
|
|
return;
|
|
|
|
if ([_submodels containsObject:model])
|
|
{
|
|
[model unbindView:viewStorage];
|
|
[_submodels removeObject:model];
|
|
}
|
|
}
|
|
|
|
- (void)layoutForContainerSize:(CGSize)__unused containerSize
|
|
{
|
|
}
|
|
|
|
- (void)collectBoundModelViewFramesRecursively:(NSMutableDictionary *)dict
|
|
{
|
|
if (_modelId != nil && _view != nil)
|
|
dict[_modelId] = [NSValue valueWithCGRect:_view.frame];
|
|
|
|
for (TGModernViewModel *submodel in _submodels)
|
|
{
|
|
[submodel collectBoundModelViewFramesRecursively:dict];
|
|
}
|
|
}
|
|
|
|
- (void)collectBoundModelViewFramesRecursively:(NSMutableDictionary *)dict ifPresentInDict:(NSMutableDictionary *)anotherDict
|
|
{
|
|
if (_modelId != nil && _view != nil && anotherDict[_modelId] != nil)
|
|
dict[_modelId] = [NSValue valueWithCGRect:_view.frame];
|
|
|
|
for (TGModernViewModel *submodel in _submodels)
|
|
{
|
|
[submodel collectBoundModelViewFramesRecursively:dict];
|
|
}
|
|
}
|
|
|
|
- (void)restoreBoundModelViewFramesRecursively:(NSMutableDictionary *)dict
|
|
{
|
|
if (_modelId != nil && _view != nil)
|
|
{
|
|
NSValue *value = dict[_modelId];
|
|
if (value != nil)
|
|
_view.frame = [value CGRectValue];
|
|
}
|
|
|
|
for (TGModernViewModel *submodel in _submodels)
|
|
{
|
|
[submodel restoreBoundModelViewFramesRecursively:dict];
|
|
}
|
|
}
|
|
|
|
@end
|