LookinDisplayItem.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. #ifdef SHOULD_COMPILE_LOOKIN_SERVER
  2. //
  3. // LookinDisplayItem.m
  4. // qmuidemo
  5. //
  6. // Created by Li Kai on 2018/11/15.
  7. // Copyright © 2018 QMUI Team. All rights reserved.
  8. //
  9. #import "LookinDisplayItem.h"
  10. #import "LookinAttributesGroup.h"
  11. #import "LookinAttributesSection.h"
  12. #import "LookinAttribute.h"
  13. #import "LookinEventHandler.h"
  14. #import "LookinIvarTrace.h"
  15. #import "Color+Lookin.h"
  16. #import "NSArray+Lookin.h"
  17. #import "NSObject+Lookin.h"
  18. #import "LookinDashboardBlueprint.h"
  19. #if TARGET_OS_IPHONE
  20. #import "UIColor+LookinServer.h"
  21. #import "UIImage+LookinServer.h"
  22. #elif TARGET_OS_MAC
  23. #endif
  24. @interface LookinDisplayItem ()
  25. @property(nonatomic, assign, readwrite) CGRect frameToRoot;
  26. @property(nonatomic, assign, readwrite) BOOL inNoPreviewHierarchy;
  27. @property(nonatomic, assign) NSInteger indentLevel;
  28. @property(nonatomic, assign, readwrite) BOOL isExpandable;
  29. @property(nonatomic, assign, readwrite) BOOL inHiddenHierarchy;
  30. @property(nonatomic, assign, readwrite) BOOL displayingInHierarchy;
  31. @end
  32. @implementation LookinDisplayItem
  33. #pragma mark - <NSCopying>
  34. - (id)copyWithZone:(NSZone *)zone {
  35. LookinDisplayItem *newDisplayItem = [[LookinDisplayItem allocWithZone:zone] init];
  36. newDisplayItem.subitems = [self.subitems lookin_map:^id(NSUInteger idx, LookinDisplayItem *value) {
  37. return value.copy;
  38. }];
  39. newDisplayItem.customInfo = self.customInfo.copy;
  40. newDisplayItem.isHidden = self.isHidden;
  41. newDisplayItem.alpha = self.alpha;
  42. newDisplayItem.frame = self.frame;
  43. newDisplayItem.bounds = self.bounds;
  44. newDisplayItem.soloScreenshot = self.soloScreenshot;
  45. newDisplayItem.groupScreenshot = self.groupScreenshot;
  46. newDisplayItem.viewObject = self.viewObject.copy;
  47. newDisplayItem.layerObject = self.layerObject.copy;
  48. newDisplayItem.hostViewControllerObject = self.hostViewControllerObject.copy;
  49. newDisplayItem.attributesGroupList = [self.attributesGroupList lookin_map:^id(NSUInteger idx, LookinAttributesGroup *value) {
  50. return value.copy;
  51. }];
  52. newDisplayItem.customAttrGroupList = [self.customAttrGroupList lookin_map:^id(NSUInteger idx, LookinAttributesGroup *value) {
  53. return value.copy;
  54. }];
  55. newDisplayItem.eventHandlers = [self.eventHandlers lookin_map:^id(NSUInteger idx, LookinEventHandler *value) {
  56. return value.copy;
  57. }];
  58. newDisplayItem.shouldCaptureImage = self.shouldCaptureImage;
  59. newDisplayItem.representedAsKeyWindow = self.representedAsKeyWindow;
  60. newDisplayItem.customDisplayTitle = self.customDisplayTitle;
  61. newDisplayItem.danceuiSource = self.danceuiSource;
  62. [newDisplayItem _updateDisplayingInHierarchyProperty];
  63. return newDisplayItem;
  64. }
  65. #pragma mark - <NSCoding>
  66. - (void)encodeWithCoder:(NSCoder *)aCoder {
  67. [aCoder encodeObject:self.customInfo forKey:@"customInfo"];
  68. [aCoder encodeObject:self.subitems forKey:@"subitems"];
  69. [aCoder encodeBool:self.isHidden forKey:@"hidden"];
  70. [aCoder encodeFloat:self.alpha forKey:@"alpha"];
  71. [aCoder encodeObject:self.viewObject forKey:@"viewObject"];
  72. [aCoder encodeObject:self.layerObject forKey:@"layerObject"];
  73. [aCoder encodeObject:self.hostViewControllerObject forKey:@"hostViewControllerObject"];
  74. [aCoder encodeObject:self.attributesGroupList forKey:@"attributesGroupList"];
  75. [aCoder encodeObject:self.customAttrGroupList forKey:@"customAttrGroupList"];
  76. [aCoder encodeBool:self.representedAsKeyWindow forKey:@"representedAsKeyWindow"];
  77. [aCoder encodeObject:self.eventHandlers forKey:@"eventHandlers"];
  78. [aCoder encodeBool:self.shouldCaptureImage forKey:@"shouldCaptureImage"];
  79. if (self.screenshotEncodeType == LookinDisplayItemImageEncodeTypeNSData) {
  80. [aCoder encodeObject:[self.soloScreenshot lookin_encodedObjectWithType:LookinCodingValueTypeImage] forKey:@"soloScreenshot"];
  81. [aCoder encodeObject:[self.groupScreenshot lookin_encodedObjectWithType:LookinCodingValueTypeImage] forKey:@"groupScreenshot"];
  82. } else if (self.screenshotEncodeType == LookinDisplayItemImageEncodeTypeImage) {
  83. [aCoder encodeObject:self.soloScreenshot forKey:@"soloScreenshot"];
  84. [aCoder encodeObject:self.groupScreenshot forKey:@"groupScreenshot"];
  85. }
  86. [aCoder encodeObject:self.customDisplayTitle forKey:@"customDisplayTitle"];
  87. [aCoder encodeObject:self.danceuiSource forKey:@"danceuiSource"];
  88. #if TARGET_OS_IPHONE
  89. [aCoder encodeCGRect:self.frame forKey:@"frame"];
  90. [aCoder encodeCGRect:self.bounds forKey:@"bounds"];
  91. [aCoder encodeObject:self.backgroundColor.lks_rgbaComponents forKey:@"backgroundColor"];
  92. #elif TARGET_OS_MAC
  93. [aCoder encodeRect:self.frame forKey:@"frame"];
  94. [aCoder encodeRect:self.bounds forKey:@"bounds"];
  95. [aCoder encodeObject:self.backgroundColor.lookin_rgbaComponents forKey:@"backgroundColor"];
  96. #endif
  97. }
  98. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  99. if (self = [super init]) {
  100. self.customInfo = [aDecoder decodeObjectForKey:@"customInfo"];
  101. self.subitems = [aDecoder decodeObjectForKey:@"subitems"];
  102. self.isHidden = [aDecoder decodeBoolForKey:@"hidden"];
  103. self.alpha = [aDecoder decodeFloatForKey:@"alpha"];
  104. self.viewObject = [aDecoder decodeObjectForKey:@"viewObject"];
  105. self.layerObject = [aDecoder decodeObjectForKey:@"layerObject"];
  106. self.hostViewControllerObject = [aDecoder decodeObjectForKey:@"hostViewControllerObject"];
  107. self.attributesGroupList = [aDecoder decodeObjectForKey:@"attributesGroupList"];
  108. self.customAttrGroupList = [aDecoder decodeObjectForKey:@"customAttrGroupList"];
  109. self.representedAsKeyWindow = [aDecoder decodeBoolForKey:@"representedAsKeyWindow"];
  110. id soloScreenshotObj = [aDecoder decodeObjectForKey:@"soloScreenshot"];
  111. if (soloScreenshotObj) {
  112. if ([soloScreenshotObj isKindOfClass:[NSData class]]) {
  113. self.soloScreenshot = [soloScreenshotObj lookin_decodedObjectWithType:LookinCodingValueTypeImage];
  114. } else if ([soloScreenshotObj isKindOfClass:[LookinImage class]]) {
  115. self.soloScreenshot = soloScreenshotObj;
  116. } else {
  117. NSAssert(NO, @"");
  118. }
  119. }
  120. id groupScreenshotObj = [aDecoder decodeObjectForKey:@"groupScreenshot"];
  121. if (groupScreenshotObj) {
  122. if ([groupScreenshotObj isKindOfClass:[NSData class]]) {
  123. self.groupScreenshot = [groupScreenshotObj lookin_decodedObjectWithType:LookinCodingValueTypeImage];
  124. } else if ([groupScreenshotObj isKindOfClass:[LookinImage class]]) {
  125. self.groupScreenshot = groupScreenshotObj;
  126. } else {
  127. NSAssert(NO, @"");
  128. }
  129. }
  130. self.eventHandlers = [aDecoder decodeObjectForKey:@"eventHandlers"];
  131. /// this property was added in LookinServer 1.1.3
  132. self.shouldCaptureImage = [aDecoder containsValueForKey:@"shouldCaptureImage"] ? [aDecoder decodeBoolForKey:@"shouldCaptureImage"] : YES;
  133. self.customDisplayTitle = [aDecoder decodeObjectForKey:@"customDisplayTitle"];
  134. self.danceuiSource = [aDecoder decodeObjectForKey:@"danceuiSource"];
  135. #if TARGET_OS_IPHONE
  136. self.frame = [aDecoder decodeCGRectForKey:@"frame"];
  137. self.bounds = [aDecoder decodeCGRectForKey:@"bounds"];
  138. self.backgroundColor = [UIColor lks_colorFromRGBAComponents:[aDecoder decodeObjectForKey:@"backgroundColor"]];
  139. #elif TARGET_OS_MAC
  140. self.frame = [aDecoder decodeRectForKey:@"frame"];
  141. self.bounds = [aDecoder decodeRectForKey:@"bounds"];
  142. self.backgroundColor = [NSColor lookin_colorFromRGBAComponents:[aDecoder decodeObjectForKey:@"backgroundColor"]];
  143. #endif
  144. [self _updateDisplayingInHierarchyProperty];
  145. }
  146. return self;
  147. }
  148. + (BOOL)supportsSecureCoding {
  149. return YES;
  150. }
  151. - (instancetype)init {
  152. if (self = [super init]) {
  153. /// 在手机端,displayItem 被创建时会调用这个方法
  154. [self _updateDisplayingInHierarchyProperty];
  155. }
  156. return self;
  157. }
  158. - (LookinObject *)displayingObject {
  159. return self.viewObject ? : self.layerObject;
  160. }
  161. - (void)setAttributesGroupList:(NSArray<LookinAttributesGroup *> *)attributesGroupList {
  162. _attributesGroupList = attributesGroupList;
  163. [_attributesGroupList enumerateObjectsUsingBlock:^(LookinAttributesGroup * _Nonnull group, NSUInteger idx, BOOL * _Nonnull stop) {
  164. [group.attrSections enumerateObjectsUsingBlock:^(LookinAttributesSection * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) {
  165. [section.attributes enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) {
  166. attr.targetDisplayItem = self;
  167. }];
  168. }];
  169. }];
  170. }
  171. - (void)setCustomAttrGroupList:(NSArray<LookinAttributesGroup *> *)customAttrGroupList {
  172. _customAttrGroupList = customAttrGroupList;
  173. // 传进来的时候就已经排好序了
  174. [customAttrGroupList enumerateObjectsUsingBlock:^(LookinAttributesGroup * _Nonnull group, NSUInteger idx, BOOL * _Nonnull stop) {
  175. [group.attrSections enumerateObjectsUsingBlock:^(LookinAttributesSection * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) {
  176. [section.attributes enumerateObjectsUsingBlock:^(LookinAttribute * _Nonnull attr, NSUInteger idx, BOOL * _Nonnull stop) {
  177. attr.targetDisplayItem = self;
  178. }];
  179. }];
  180. }];
  181. }
  182. - (void)setSubitems:(NSArray<LookinDisplayItem *> *)subitems {
  183. [_subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  184. obj.superItem = nil;
  185. }];
  186. _subitems = subitems;
  187. self.isExpandable = (subitems.count > 0);
  188. [subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  189. NSAssert(!obj.superItem, @"");
  190. obj.superItem = self;
  191. [obj _updateInHiddenHierarchyProperty];
  192. [obj _updateDisplayingInHierarchyProperty];
  193. }];
  194. }
  195. - (void)setIsExpandable:(BOOL)isExpandable {
  196. if (_isExpandable == isExpandable) {
  197. return;
  198. }
  199. _isExpandable = isExpandable;
  200. [self _notifyDelegatesWith:LookinDisplayItemProperty_IsExpandable];
  201. }
  202. - (void)setIsExpanded:(BOOL)isExpanded {
  203. if (_isExpanded == isExpanded) {
  204. return;
  205. }
  206. _isExpanded = isExpanded;
  207. [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  208. [obj _updateDisplayingInHierarchyProperty];
  209. }];
  210. [self _notifyDelegatesWith:LookinDisplayItemProperty_IsExpanded];
  211. }
  212. - (void)setSoloScreenshot:(LookinImage *)soloScreenshot {
  213. if (_soloScreenshot == soloScreenshot) {
  214. return;
  215. }
  216. _soloScreenshot = soloScreenshot;
  217. [self _notifyDelegatesWith:LookinDisplayItemProperty_SoloScreenshot];
  218. }
  219. - (void)notifySelectionChangeToDelegates {
  220. [self _notifyDelegatesWith:LookinDisplayItemProperty_IsSelected];
  221. }
  222. - (void)notifyHoverChangeToDelegates {
  223. [self _notifyDelegatesWith:LookinDisplayItemProperty_IsHovered];
  224. }
  225. - (void)setDoNotFetchScreenshotReason:(LookinDoNotFetchScreenshotReason)doNotFetchScreenshotReason {
  226. if (_doNotFetchScreenshotReason == doNotFetchScreenshotReason) {
  227. return;
  228. }
  229. _doNotFetchScreenshotReason = doNotFetchScreenshotReason;
  230. [self _notifyDelegatesWith:LookinDisplayItemProperty_AvoidSyncScreenshot];
  231. }
  232. - (void)setGroupScreenshot:(LookinImage *)groupScreenshot {
  233. if (_groupScreenshot == groupScreenshot) {
  234. return;
  235. }
  236. _groupScreenshot = groupScreenshot;
  237. [self _notifyDelegatesWith:LookinDisplayItemProperty_GroupScreenshot];
  238. }
  239. - (void)setDisplayingInHierarchy:(BOOL)displayingInHierarchy {
  240. if (_displayingInHierarchy == displayingInHierarchy) {
  241. return;
  242. }
  243. _displayingInHierarchy = displayingInHierarchy;
  244. [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  245. [obj _updateDisplayingInHierarchyProperty];
  246. }];
  247. [self _notifyDelegatesWith:LookinDisplayItemProperty_DisplayingInHierarchy];
  248. }
  249. - (void)_updateDisplayingInHierarchyProperty {
  250. if (self.superItem && (!self.superItem.displayingInHierarchy || !self.superItem.isExpanded)) {
  251. self.displayingInHierarchy = NO;
  252. } else {
  253. self.displayingInHierarchy = YES;
  254. }
  255. }
  256. - (void)setIsHidden:(BOOL)isHidden {
  257. _isHidden = isHidden;
  258. [self _updateInHiddenHierarchyProperty];
  259. }
  260. - (void)setAlpha:(float)alpha {
  261. _alpha = alpha;
  262. [self _updateInHiddenHierarchyProperty];
  263. }
  264. - (void)setInHiddenHierarchy:(BOOL)inHiddenHierarchy {
  265. if (_inHiddenHierarchy == inHiddenHierarchy) {
  266. return;
  267. }
  268. _inHiddenHierarchy = inHiddenHierarchy;
  269. [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  270. [obj _updateInHiddenHierarchyProperty];
  271. }];
  272. [self _notifyDelegatesWith:LookinDisplayItemProperty_InHiddenHierarchy];
  273. }
  274. - (void)_updateInHiddenHierarchyProperty {
  275. if (self.superItem.inHiddenHierarchy || self.isHidden || self.alpha <= 0) {
  276. self.inHiddenHierarchy = YES;
  277. } else {
  278. self.inHiddenHierarchy = NO;
  279. }
  280. }
  281. + (NSArray<LookinDisplayItem *> *)flatItemsFromHierarchicalItems:(NSArray<LookinDisplayItem *> *)items {
  282. NSMutableArray *resultArray = [NSMutableArray array];
  283. [items enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  284. if (obj.superItem) {
  285. obj.indentLevel = obj.superItem.indentLevel + 1;
  286. }
  287. [resultArray addObject:obj];
  288. if (obj.subitems.count) {
  289. [resultArray addObjectsFromArray:[self flatItemsFromHierarchicalItems:obj.subitems]];
  290. }
  291. }];
  292. return resultArray;
  293. }
  294. - (NSString *)description {
  295. if (self.viewObject) {
  296. return self.viewObject.rawClassName;
  297. } else if (self.layerObject) {
  298. return self.layerObject.rawClassName;
  299. } else {
  300. return [super description];
  301. }
  302. }
  303. - (void)setPreviewItemDelegate:(id<LookinDisplayItemDelegate>)previewItemDelegate {
  304. _previewItemDelegate = previewItemDelegate;
  305. if (![previewItemDelegate respondsToSelector:@selector(displayItem:propertyDidChange:)]) {
  306. NSAssert(NO, @"");
  307. _previewItemDelegate = nil;
  308. return;
  309. }
  310. [self.previewItemDelegate displayItem:self propertyDidChange:LookinDisplayItemProperty_None];
  311. }
  312. - (void)setRowViewDelegate:(id<LookinDisplayItemDelegate>)rowViewDelegate {
  313. if (_rowViewDelegate == rowViewDelegate) {
  314. return;
  315. }
  316. _rowViewDelegate = rowViewDelegate;
  317. if (![rowViewDelegate respondsToSelector:@selector(displayItem:propertyDidChange:)]) {
  318. NSAssert(NO, @"");
  319. _rowViewDelegate = nil;
  320. return;
  321. }
  322. [self.rowViewDelegate displayItem:self propertyDidChange:LookinDisplayItemProperty_None];
  323. }
  324. - (void)setFrame:(CGRect)frame {
  325. _frame = frame;
  326. [self recursivelyNotifyFrameToRootMayChange];
  327. }
  328. - (void)recursivelyNotifyFrameToRootMayChange {
  329. [self _notifyDelegatesWith:LookinDisplayItemProperty_FrameToRoot];
  330. [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  331. [obj recursivelyNotifyFrameToRootMayChange];
  332. }];
  333. }
  334. - (void)setBounds:(CGRect)bounds {
  335. _bounds = bounds;
  336. [self recursivelyNotifyFrameToRootMayChange];
  337. }
  338. - (void)setInNoPreviewHierarchy:(BOOL)inNoPreviewHierarchy {
  339. if (_inNoPreviewHierarchy == inNoPreviewHierarchy) {
  340. return;
  341. }
  342. _inNoPreviewHierarchy = inNoPreviewHierarchy;
  343. [self.subitems enumerateObjectsUsingBlock:^(LookinDisplayItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  344. [obj _updateInNoPreviewHierarchy];
  345. }];
  346. [self _notifyDelegatesWith:LookinDisplayItemProperty_InNoPreviewHierarchy];
  347. }
  348. - (void)setNoPreview:(BOOL)noPreview {
  349. _noPreview = noPreview;
  350. [self _updateInNoPreviewHierarchy];
  351. }
  352. - (void)_updateInNoPreviewHierarchy {
  353. if (self.superItem.inNoPreviewHierarchy || self.noPreview) {
  354. self.inNoPreviewHierarchy = YES;
  355. } else {
  356. self.inNoPreviewHierarchy = NO;
  357. }
  358. }
  359. - (void)_notifyDelegatesWith:(LookinDisplayItemProperty)property {
  360. [self.previewItemDelegate displayItem:self propertyDidChange:property];
  361. [self.rowViewDelegate displayItem:self propertyDidChange:property];
  362. }
  363. - (void)setIsInSearch:(BOOL)isInSearch {
  364. _isInSearch = isInSearch;
  365. [self _notifyDelegatesWith:LookinDisplayItemProperty_IsInSearch];
  366. }
  367. - (void)setHighlightedSearchString:(NSString *)highlightedSearchString {
  368. _highlightedSearchString = highlightedSearchString;
  369. [self _notifyDelegatesWith:LookinDisplayItemProperty_HighlightedSearchString];
  370. }
  371. - (NSArray<LookinAttributesGroup *> *)queryAllAttrGroupList {
  372. NSMutableArray *array = [NSMutableArray array];
  373. if (self.attributesGroupList) {
  374. [array addObjectsFromArray:self.attributesGroupList];
  375. }
  376. if (self.customAttrGroupList) {
  377. [array addObjectsFromArray:self.customAttrGroupList];
  378. }
  379. return array;
  380. }
  381. //- (void)dealloc
  382. //{
  383. // NSLog(@"moss dealloc -%@", self);
  384. //}
  385. @end
  386. #endif /* SHOULD_COMPILE_LOOKIN_SERVER */