1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef IOS_CHROME_BROWSER_UI_UTIL_UIKIT_UI_UTIL_H_
6 #define IOS_CHROME_BROWSER_UI_UTIL_UIKIT_UI_UTIL_H_
7 
8 #include <CoreGraphics/CoreGraphics.h>
9 #import <Foundation/Foundation.h>
10 #import <UIKit/UIKit.h>
11 
12 #import "ios/chrome/browser/ui/util/ui_util.h"
13 
14 // UI Util containing functions that require UIKit.
15 
16 // Utility function to set the |element|'s accessibility label to the localized
17 // message corresponding to |idsAccessibilityLabel| and its accessibility
18 // identifier to |englishUiAutomationName|.
19 // Call SetA11yLabelAndUiAutomationName() if |element| is accessible and its
20 // a11y label should be localized.
21 // By convention |englishUiAutomationName| must be equal to the English
22 // localized string corresponding to |idsAccessibilityLabel|.
23 // |englishUiAutomationName| is the name used in JavaScript UI Automation test
24 // scripts to identify the |element|.
25 void SetA11yLabelAndUiAutomationName(
26     NSObject<UIAccessibilityIdentification>* element,
27     int idsAccessibilityLabel,
28     NSString* englishUiAutomationName);
29 
30 // Sets dynamic font for the given |font| on iOS 11+ on the givel |label| or
31 // |textField|. Use |maybe| versions to keep code short when dynamic types are
32 // not in use yet.
33 void SetUILabelScaledFont(UILabel* label, UIFont* font);
34 void MaybeSetUILabelScaledFont(BOOL maybe, UILabel* label, UIFont* font);
35 void SetUITextFieldScaledFont(UITextField* textField, UIFont* font);
36 void MaybeSetUITextFieldScaledFont(BOOL maybe,
37                                    UITextField* textField,
38                                    UIFont* font);
39 
40 enum CaptureViewOption {
41   kNoCaptureOption,      // Equivalent to calling CaptureView without options.
42   kAfterScreenUpdate,    // Require a synchronization with CA process which can
43                          // have side effects.
44   kClientSideRendering,  // Triggers a client side compositing, very slow.
45 };
46 
47 // Captures and returns an autoreleased rendering of the |view|.
48 // The |view| is assumed to be opaque and the returned image does
49 // not have an alpha channel. The scale parameter is used as a scale factor
50 // for the rendering context. Using 0.0 as scale will result in the device's
51 // main screen scale to be used.
52 // The CaptureViewWithOption function can be used with the |option|
53 // parameter set to kAfterScreenUpdate if some changes performed in the view
54 // and/or it's subtree that have not yet been part of a committed implicit
55 // transaction must be reflected in the snapshot.
56 // For example, it should be used if you just performed changes in the view or
57 // its subviews before calling that function and wants those changes to be
58 // reflected in the snapshot.
59 // Calling CaptureView without option gives the best performances. If you only
60 // need to hide subviews consider selectively rendering subviews in a bitmap
61 // context using drawViewHierarchyInRect:afterScreenUpdates:NO.
62 // The kClientSideRendering option can be used to directly re-render the view
63 // client side instead of reusing the core animation layer's backing store, this
64 // is slow.
65 // On iOS < 9 this function is slow and always behave as if the option was set
66 // to kClientSideRendering.
67 UIImage* CaptureViewWithOption(UIView* view,
68                                CGFloat scale,
69                                CaptureViewOption option);
70 UIImage* CaptureView(UIView* view, CGFloat scale);
71 
72 // Converts input image and returns a grey scaled version.
73 UIImage* GreyImage(UIImage* image);
74 
75 // Returns an UIColor with |rgb| and |alpha|. The caller should pass the RGB
76 // value in hexadecimal as this is the typical way they are provided by UX.
77 // For example a call to |UIColorFromRGB(0xFF7D40, 1.0)| returns an orange
78 // UIColor object.
79 inline UIColor* UIColorFromRGB(int rgb, CGFloat alpha = 1.0) {
80   return [UIColor colorWithRed:((CGFloat)((rgb & 0xFF0000) >> 16)) / 255.0
81                          green:((CGFloat)((rgb & 0x00FF00) >> 8)) / 255.0
82                           blue:((CGFloat)(rgb & 0x0000FF)) / 255.0
83                          alpha:alpha];
84 }
85 
86 // Returns the image from the shared resource bundle with the image id
87 // |imageID|. If |reversable| is YES and RTL layout is in use, the image
88 // will be flipped for RTL.
89 UIImage* NativeReversableImage(int imageID, BOOL reversable);
90 
91 // Convenience version of NativeReversableImage for images that are never
92 // reversable; equivalent to NativeReversableImage(imageID, NO).
93 UIImage* NativeImage(int imageID);
94 
95 // Returns an image resized to |targetSize|. It first calculate the projection
96 // by calling CalculateProjection() and then create a new image of the desired
97 // size and project the correct subset of the original image onto it.
98 // The resulting image will have an alpha channel.
99 //
100 // Image interpolation level for resizing is set to kCGInterpolationDefault.
101 //
102 // The resize always preserves the scale of the original image.
103 UIImage* ResizeImage(UIImage* image,
104                      CGSize targetSize,
105                      ProjectionMode projectionMode);
106 
107 // Returns an image resized to |targetSize|. It first calculate the projection
108 // by calling CalculateProjection() and then create a new image of the desired
109 // size and project the correct subset of the original image onto it.
110 // |opaque| determine whether resulting image should have an alpha channel.
111 // Prefer setting |opaque| to YES for better performances.
112 //
113 // Image interpolation level for resizing is set to kCGInterpolationDefault.
114 //
115 // The resize always preserves the scale of the original image.
116 UIImage* ResizeImage(UIImage* image,
117                      CGSize targetSize,
118                      ProjectionMode projectionMode,
119                      BOOL opaque);
120 
121 // Returns an output image where each pixel has RGB values equal to a color and
122 // the alpha value sampled from the given image. The RGB values of the image are
123 // ignored. If the color has alpha value of less than one, then the entire
124 // output image's alpha is scaled by the color's alpha value.
125 UIImage* TintImage(UIImage* image, UIColor* color);
126 
127 // Returns the first responder in the subviews of |view|, or nil if no view in
128 // the subtree is the first responder.
129 UIView* GetFirstResponderSubview(UIView* view);
130 
131 // Returns the interface orientation of the given window in the app.
132 UIInterfaceOrientation GetInterfaceOrientation(UIWindow* window);
133 
134 // Returns the height of the keyboard in the current orientation.
135 CGFloat CurrentKeyboardHeight(NSValue* keyboardFrameValue);
136 
137 // Create 1x1px image from |color|.
138 UIImage* ImageWithColor(UIColor* color);
139 
140 // Returns a circular image of width |width| based on |image| scaled up or
141 // down. If the source image is not square, the image is first cropped.
142 UIImage* CircularImageFromImage(UIImage* image, CGFloat width);
143 
144 // Returns true if the window is in portrait orientation or if orientation is
145 // unknown.
146 bool IsPortrait(UIWindow* window);
147 
148 // Returns true if the window is in landscape orientation.
149 bool IsLandscape(UIWindow* window);
150 
151 // Whether the |environment| has a compact horizontal size class.
152 bool IsCompactWidth(id<UITraitEnvironment> environment);
153 
154 // Whether the |traitCollection| has a compact horizontal size class.
155 bool IsCompactWidth(UITraitCollection* traitCollection);
156 
157 // Whether the |environment| has a compact vertical size class.
158 bool IsCompactHeight(id<UITraitEnvironment> environment);
159 
160 // Whether the |traitCollection| has a compact vertical size class.
161 bool IsCompactHeight(UITraitCollection* traitCollection);
162 
163 // Whether toolbar should be shown in compact mode in |environment|.
164 bool ShouldShowCompactToolbar(id<UITraitEnvironment> environment);
165 
166 // Whether toolbar should be shown in compact mode in |traitCollection|.
167 bool ShouldShowCompactToolbar(UITraitCollection* traitCollection);
168 
169 // Whether the |environment| has a regular vertical and regular horizontal
170 // size class.
171 bool IsRegularXRegularSizeClass(id<UITraitEnvironment> environment);
172 // Whether the |traitCollection| has a regular vertical and regular horizontal
173 // size class.
174 bool IsRegularXRegularSizeClass(UITraitCollection* traitCollection);
175 
176 // Returns whether the |environment|'s toolbar is split between top and bottom
177 // toolbar or if it is displayed as only one toolbar.
178 bool IsSplitToolbarMode(id<UITraitEnvironment> environment);
179 
180 // Returns whether the |traitCollection|'s toolbar is split between top and
181 // bottom toolbar or if it is displayed as only one toolbar.
182 bool IsSplitToolbarMode(UITraitCollection* traitCollection);
183 
184 // Returns the current first responder for keyWindow.
185 UIResponder* GetFirstResponder();
186 
187 // Trigger a haptic vibration for various types of actions. This is a no-op for
188 // devices that do not support haptic feedback.
189 void TriggerHapticFeedbackForSelectionChange();
190 // |impactStyle| should represent the mass of the object in the collision
191 // simulated by this feedback.
192 void TriggerHapticFeedbackForImpact(UIImpactFeedbackStyle impactStyle);
193 // |type| represent the type of notification associated with this feedback.
194 void TriggerHapticFeedbackForNotification(UINotificationFeedbackType type);
195 
196 // Returns the text for tabs count to be displayed in toolbar and tab_grid.
197 // As an easter egg, show a smiley face instead of the count if the user has
198 // more than 99 tabs open.
199 NSString* TextForTabCount(long count);
200 
201 // Adds |item| to the global Edit Menu configuration (UIMenuController). No-op
202 // if a UIMenuItem with the same selector as |item| has already been registered.
203 void RegisterEditMenuItem(UIMenuItem* item);
204 
205 // Finds the root of |view|'s view hierarchy -- its window if it has one, or
206 // the first (recursive) superview with no superview.
207 UIView* ViewHierarchyRootForView(UIView* view);
208 
209 #endif  // IOS_CHROME_BROWSER_UI_UTIL_UIKIT_UI_UTIL_H_
210