[NUI] Cache url when we call SetImage + Make way to skip visual creation
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / ImageViewBindableProperty.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System.ComponentModel;
19 using System.Runtime.InteropServices;
20 using Tizen.NUI.Binding;
21
22 namespace Tizen.NUI.BaseComponents
23 {
24     public partial class ImageView
25     {
26         /// Intenal used, will never be opened.
27         [EditorBrowsable(EditorBrowsableState.Never)]
28         public static readonly BindableProperty ResourceUrlProperty = BindableProperty.Create(nameof(ImageView.ResourceUrl), typeof(string), typeof(ImageView), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
29         {
30             var imageView = (ImageView)bindable;
31
32             if (newValue is Selector<string> selector)
33             {
34                 imageView.ResourceUrlSelector = selector;
35             }
36             else
37             {
38                 imageView.resourceUrlSelector?.Reset(imageView);
39                 imageView.SetResourceUrl((string)newValue);
40             }
41         },
42         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
43         {
44             var imageView = (ImageView)bindable;
45             string ret = "";
46
47             imageView.GetCachedImageVisualProperty(ImageVisualProperty.URL)?.Get(out ret);
48
49             return ret;
50         }));
51
52         /// Intenal used, will never be opened.
53         [EditorBrowsable(EditorBrowsableState.Never)]
54         public static readonly BindableProperty ImageProperty = BindableProperty.Create(nameof(ImageView.Image), typeof(PropertyMap), typeof(ImageView), null, propertyChanged: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) =>
55         {
56             var imageView = (ImageView)bindable;
57             if (newValue != null)
58             {
59                 PropertyMap map = (PropertyMap)newValue;
60                 if (imageView.IsCreateByXaml)
61                 {
62                     string url = "", alphaMaskURL = "", auxiliaryImageURL = "";
63                     string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
64                     PropertyValue urlValue = map.Find(NDalic.ImageVisualUrl);
65                     bool ret = false;
66                     if (urlValue != null) ret = urlValue.Get(out url);
67                     PropertyMap mmap = new PropertyMap();
68                     if (ret && url.StartsWith("*Resource*"))
69                     {
70                         url = url.Replace("*Resource*", resource);
71                         mmap.Insert(NDalic.ImageVisualUrl, new PropertyValue(url));
72                     }
73
74                     ret = false;
75                     PropertyValue alphaMaskUrlValue = map.Find(NDalic.ImageVisualAlphaMaskUrl);
76                     if (alphaMaskUrlValue != null) ret = alphaMaskUrlValue.Get(out alphaMaskURL);
77                     if (ret && alphaMaskURL.StartsWith("*Resource*"))
78                     {
79                         alphaMaskURL = alphaMaskURL.Replace("*Resource*", resource);
80                         mmap.Insert(NDalic.ImageVisualUrl, new PropertyValue(alphaMaskURL));
81                     }
82
83                     ret = false;
84                     PropertyValue auxiliaryImageURLValue = map.Find(NDalic.ImageVisualAuxiliaryImageUrl);
85                     if (auxiliaryImageURLValue != null) ret = auxiliaryImageURLValue.Get(out auxiliaryImageURL);
86                     if (ret && auxiliaryImageURL.StartsWith("*Resource*"))
87                     {
88                         auxiliaryImageURL = auxiliaryImageURL.Replace("*Resource*", resource);
89                         mmap.Insert(NDalic.ImageVisualAuxiliaryImageUrl, new PropertyValue(auxiliaryImageURL));
90                     }
91
92                     map.Merge(mmap);
93                 }
94                 if (imageView._border == null)
95                 {
96                     // Image properties are changed hardly. We should ignore lazy UpdateImage
97                     imageView.imagePropertyUpdatedFlag = false;
98                     imageView.cachedImagePropertyMap?.Dispose();
99                     imageView.cachedImagePropertyMap = null;
100                     imageView.MergeCachedImageVisualProperty(map);
101
102                     Tizen.NUI.Object.SetProperty((HandleRef)imageView.SwigCPtr, ImageView.Property.IMAGE, new Tizen.NUI.PropertyValue(map));
103                 }
104             }
105         }),
106         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
107         {
108             var imageView = (ImageView)bindable;
109             if (imageView._border == null)
110             {
111                 // Sync as current properties
112                 imageView.UpdateImage();
113
114                 // Get current properties force.
115                 PropertyMap returnValue = new PropertyMap();
116                 Tizen.NUI.Object.GetProperty((HandleRef)imageView.SwigCPtr, ImageView.Property.IMAGE).Get(returnValue);
117
118                 // Update cached property map
119                 if (returnValue != null)
120                 {
121                     imageView.MergeCachedImageVisualProperty(returnValue);
122                 }
123                 return returnValue;
124             }
125             else
126             {
127                 return null;
128             }
129         }));
130
131         /// Intenal used, will never be opened.
132         [EditorBrowsable(EditorBrowsableState.Never)]
133         public static readonly BindableProperty PreMultipliedAlphaProperty = BindableProperty.Create(nameof(PreMultipliedAlpha), typeof(bool), typeof(ImageView), false, propertyChanged: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) =>
134         {
135             var imageView = (ImageView)bindable;
136             if (newValue != null)
137             {
138                 if (imageView.imagePropertyUpdatedFlag)
139                 {
140                     // If imageView Property still not send to the dali, Append cached property.
141                     imageView.UpdateImage(Visual.Property.PremultipliedAlpha, new PropertyValue((bool)newValue));
142                 }
143                 else
144                 {
145                     // Else, we don't need to re-create view. Get value from current ImageView.
146                     Object.InternalSetPropertyBool(imageView.SwigCPtr, ImageView.Property.PreMultipliedAlpha, (bool)newValue);
147                 }
148             }
149         }),
150         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
151         {
152             var imageView = (ImageView)bindable;
153             bool temp = false;
154
155             if (imageView.imagePropertyUpdatedFlag)
156             {
157                 // If imageView Property still not send to the dali, just get cached property.
158                 imageView.GetCachedImageVisualProperty(Visual.Property.PremultipliedAlpha)?.Get(out temp);
159             }
160             else
161             {
162                 // Else, PremultipliedAlpha may not setuped in cached property. Get value from current ImageView.
163                 temp = Object.InternalGetPropertyBool(imageView.SwigCPtr, ImageView.Property.PreMultipliedAlpha);
164             }
165             return temp;
166         }));
167
168         /// Intenal used, will never be opened.
169         [EditorBrowsable(EditorBrowsableState.Never)]
170         public static readonly BindableProperty PixelAreaProperty = BindableProperty.Create(nameof(PixelArea), typeof(RelativeVector4), typeof(ImageView), null, propertyChanged: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) =>
171         {
172             var imageView = (ImageView)bindable;
173             if (newValue != null)
174             {
175
176                 Object.InternalSetPropertyVector4(imageView.SwigCPtr, ImageView.Property.PixelArea, ((RelativeVector4)newValue).SwigCPtr);
177             }
178         }),
179         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
180         {
181             var imageView = (ImageView)bindable;
182
183             if (imageView.internalPixelArea == null)
184             {
185                 imageView.internalPixelArea = new RelativeVector4(imageView.OnPixelAreaChanged, 0, 0, 0, 0);
186             }
187             Object.InternalRetrievingPropertyVector4(imageView.SwigCPtr, ImageView.Property.PixelArea, imageView.internalPixelArea.SwigCPtr);
188             return imageView.internalPixelArea;
189         }));
190
191         /// Intenal used, will never be opened.
192         [EditorBrowsable(EditorBrowsableState.Never)]
193         public static readonly BindableProperty BorderProperty = BindableProperty.Create(nameof(Border), typeof(Rectangle), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
194         {
195             var imageView = (ImageView)bindable;
196             imageView.borderSelector?.Reset(imageView);
197
198             if (newValue is Selector<Rectangle> selector)
199             {
200                 if (selector.HasAll()) imageView.SetBorder(selector.All);
201                 else imageView.borderSelector = new TriggerableSelector<Rectangle>(imageView, selector, imageView.SetBorder, true);
202             }
203             else
204             {
205                 imageView.SetBorder((Rectangle)newValue);
206             }
207         },
208         defaultValueCreator: (bindable) =>
209         {
210             var imageView = (ImageView)bindable;
211             return imageView._border;
212         });
213
214         /// Intenal used, will never be opened.
215         [EditorBrowsable(EditorBrowsableState.Never)]
216         public static readonly BindableProperty BorderOnlyProperty = BindableProperty.Create(nameof(BorderOnly), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
217         {
218             var imageView = (ImageView)bindable;
219             if (newValue != null)
220             {
221                 if (oldValue != null)
222                 {
223                     bool oldBool = (bool)oldValue;
224                     bool newBool = (bool)newValue;
225                     if (oldBool == newBool)
226                     {
227                         return;
228                     }
229                 }
230                 imageView.UpdateImage(NpatchImageVisualProperty.BorderOnly, new PropertyValue((bool)newValue));
231             }
232         },
233         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
234         {
235             var imageView = (ImageView)bindable;
236             bool ret = false;
237
238             imageView.GetCachedImageVisualProperty(NpatchImageVisualProperty.BorderOnly)?.Get(out ret);
239
240             return ret;
241         }));
242
243         /// Intenal used, will never be opened.
244         [EditorBrowsable(EditorBrowsableState.Never)]
245         public static readonly BindableProperty SynchronosLoadingProperty = BindableProperty.Create(nameof(SynchronousLoading), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
246         {
247             var imageView = (ImageView)bindable;
248             if (newValue != null)
249             {
250                 if (oldValue != null)
251                 {
252                     bool oldBool = (bool)oldValue;
253                     bool newBool = (bool)newValue;
254                     if (oldBool == newBool)
255                     {
256                         return;
257                     }
258                 }
259                 // Note : We need to create new visual if previous visual was async, and now we set value as sync.
260                 imageView.UpdateImage(ImageVisualProperty.SynchronousLoading, new PropertyValue((bool)newValue), (bool)newValue);
261             }
262         },
263         defaultValueCreator: (bindable) =>
264         {
265             var imageView = (ImageView)bindable;
266             bool ret = false;
267
268             imageView.GetCachedImageVisualProperty(ImageVisualProperty.SynchronousLoading)?.Get(out ret);
269
270             return ret;
271         });
272
273         /// This will be public opened in tizen_7.0 after ACR done. Before ACR, need to be hidden as inhouse API.
274         [EditorBrowsable(EditorBrowsableState.Never)]
275         public static readonly BindableProperty SynchronousLoadingProperty = BindableProperty.Create(nameof(SynchronousLoading), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
276         {
277             var imageView = (ImageView)bindable;
278             if (newValue != null)
279             {
280                 if (oldValue != null)
281                 {
282                     bool oldBool = (bool)oldValue;
283                     bool newBool = (bool)newValue;
284                     if (oldBool == newBool)
285                     {
286                         return;
287                     }
288                 }
289                 // Note : We need to create new visual if previous visual was async, and now we set value as sync.
290                 imageView.UpdateImage(ImageVisualProperty.SynchronousLoading, new PropertyValue((bool)newValue), (bool)newValue);
291             }
292         },
293         defaultValueCreator: (bindable) =>
294         {
295             var imageView = (ImageView)bindable;
296             bool ret = false;
297
298             imageView.GetCachedImageVisualProperty(ImageVisualProperty.SynchronousLoading)?.Get(out ret);
299
300             return ret;
301         });
302
303         /// Intenal used, will never be opened.
304         [EditorBrowsable(EditorBrowsableState.Never)]
305         public static readonly BindableProperty OrientationCorrectionProperty = BindableProperty.Create(nameof(OrientationCorrection), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
306         {
307             var imageView = (ImageView)bindable;
308             if (newValue != null)
309             {
310                 if (oldValue != null)
311                 {
312                     bool oldBool = (bool)oldValue;
313                     bool newBool = (bool)newValue;
314                     if (oldBool == newBool)
315                     {
316                         return;
317                     }
318                 }
319                 imageView.UpdateImage(ImageVisualProperty.OrientationCorrection, new PropertyValue((bool)newValue));
320             }
321         },
322         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
323         {
324             var imageView = (ImageView)bindable;
325
326             bool ret = false;
327
328             imageView.GetCachedImageVisualProperty(ImageVisualProperty.OrientationCorrection)?.Get(out ret);
329
330             return ret;
331         }));
332
333         /// <summary>
334         /// MaskingModeProperty
335         /// </summary>
336         [EditorBrowsable(EditorBrowsableState.Never)]
337         public static readonly BindableProperty MaskingModeProperty = BindableProperty.Create(nameof(MaskingMode), typeof(MaskingModeType), typeof(ImageView), default(MaskingModeType), propertyChanged: (bindable, oldValue, newValue) =>
338         {
339             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
340             if (newValue != null)
341             {
342                 instance.InternalMaskingMode = (ImageView.MaskingModeType)newValue;
343             }
344         },
345         defaultValueCreator: (bindable) =>
346         {
347             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
348             return instance.InternalMaskingMode;
349         });
350
351         /// <summary>
352         /// ImageMapProperty
353         /// </summary>
354         [EditorBrowsable(EditorBrowsableState.Never)]
355         public static readonly BindableProperty ImageMapProperty = BindableProperty.Create(nameof(ImageMap), typeof(Tizen.NUI.PropertyMap), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
356         {
357             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
358             if (newValue != null)
359             {
360                 instance.InternalImageMap = (Tizen.NUI.PropertyMap)newValue;
361             }
362         },
363         defaultValueCreator: (bindable) =>
364         {
365             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
366             return instance.InternalImageMap;
367         });
368
369         /// <summary>
370         /// AlphaMaskURLProperty
371         /// </summary>
372         [EditorBrowsable(EditorBrowsableState.Never)]
373         public static readonly BindableProperty AlphaMaskURLProperty = BindableProperty.Create(nameof(AlphaMaskURL), typeof(string), typeof(ImageView), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
374         {
375             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
376             if (newValue != null)
377             {
378                 instance.InternalAlphaMaskURL = (string)newValue;
379             }
380         },
381         defaultValueCreator: (bindable) =>
382         {
383             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
384             return instance.InternalAlphaMaskURL;
385         });
386
387         /// <summary>
388         /// CropToMaskProperty
389         /// </summary>
390         [EditorBrowsable(EditorBrowsableState.Never)]
391         public static readonly BindableProperty CropToMaskProperty = BindableProperty.Create(nameof(CropToMask), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
392         {
393             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
394             if (newValue != null)
395             {
396                 instance.InternalCropToMask = (bool)newValue;
397             }
398         },
399         defaultValueCreator: (bindable) =>
400         {
401             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
402             return instance.InternalCropToMask;
403         });
404
405         /// <summary>
406         /// FittingModeProperty
407         /// </summary>
408         [EditorBrowsable(EditorBrowsableState.Never)]
409         public static readonly BindableProperty FittingModeProperty = BindableProperty.Create(nameof(FittingMode), typeof(FittingModeType), typeof(ImageView), default(FittingModeType), propertyChanged: (bindable, oldValue, newValue) =>
410         {
411             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
412             if (newValue != null)
413             {
414                 instance.InternalFittingMode = (Tizen.NUI.FittingModeType)newValue;
415             }
416         },
417         defaultValueCreator: (bindable) =>
418         {
419             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
420             return instance.InternalFittingMode;
421         });
422
423         /// <summary>
424         /// DesiredWidthProperty
425         /// </summary>
426         [EditorBrowsable(EditorBrowsableState.Never)]
427         public static readonly BindableProperty DesiredWidthProperty = BindableProperty.Create(nameof(DesiredWidth), typeof(int), typeof(ImageView), 0, propertyChanged: (bindable, oldValue, newValue) =>
428         {
429             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
430             if (newValue != null)
431             {
432                 instance.InternalDesiredWidth = (int)newValue;
433             }
434         },
435         defaultValueCreator: (bindable) =>
436         {
437             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
438             return instance.InternalDesiredWidth;
439         });
440
441         /// <summary>
442         /// DesiredHeightProperty
443         /// </summary>
444         [EditorBrowsable(EditorBrowsableState.Never)]
445         public static readonly BindableProperty DesiredHeightProperty = BindableProperty.Create(nameof(DesiredHeight), typeof(int), typeof(ImageView), 0, propertyChanged: (bindable, oldValue, newValue) =>
446         {
447             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
448             if (newValue != null)
449             {
450                 instance.InternalDesiredHeight = (int)newValue;
451             }
452         },
453         defaultValueCreator: (bindable) =>
454         {
455             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
456             return instance.InternalDesiredHeight;
457         });
458
459         /// <summary>
460         /// ReleasePolicyProperty
461         /// </summary>
462         [EditorBrowsable(EditorBrowsableState.Never)]
463         public static readonly BindableProperty ReleasePolicyProperty = BindableProperty.Create(nameof(ReleasePolicy), typeof(ReleasePolicyType), typeof(ImageView), default(ReleasePolicyType), propertyChanged: (bindable, oldValue, newValue) =>
464         {
465             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
466             if (newValue != null)
467             {
468                 instance.InternalReleasePolicy = (Tizen.NUI.ReleasePolicyType)newValue;
469             }
470         },
471         defaultValueCreator: (bindable) =>
472         {
473             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
474             return instance.InternalReleasePolicy;
475         });
476
477         /// <summary>
478         /// WrapModeUProperty
479         /// </summary>
480         [EditorBrowsable(EditorBrowsableState.Never)]
481         public static readonly BindableProperty WrapModeUProperty = BindableProperty.Create(nameof(WrapModeU), typeof(Tizen.NUI.WrapModeType), typeof(ImageView), default(WrapModeType), propertyChanged: (bindable, oldValue, newValue) =>
482         {
483             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
484             if (newValue != null)
485             {
486                 instance.InternalWrapModeU = (Tizen.NUI.WrapModeType)newValue;
487             }
488         },
489         defaultValueCreator: (bindable) =>
490         {
491             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
492             return instance.InternalWrapModeU;
493         });
494
495         /// <summary>
496         /// WrapModeVProperty
497         /// </summary>
498         [EditorBrowsable(EditorBrowsableState.Never)]
499         public static readonly BindableProperty WrapModeVProperty = BindableProperty.Create(nameof(WrapModeV), typeof(Tizen.NUI.WrapModeType), typeof(ImageView), default(WrapModeType), propertyChanged: (bindable, oldValue, newValue) =>
500         {
501             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
502             if (newValue != null)
503             {
504                 instance.InternalWrapModeV = (Tizen.NUI.WrapModeType)newValue;
505             }
506         },
507         defaultValueCreator: (bindable) =>
508         {
509             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
510             return instance.InternalWrapModeV;
511         });
512
513         /// <summary>
514         /// AdjustViewSizeProperty
515         /// </summary>
516         [EditorBrowsable(EditorBrowsableState.Never)]
517         public static readonly BindableProperty AdjustViewSizeProperty = BindableProperty.Create(nameof(AdjustViewSize), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
518         {
519             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
520             if (newValue != null)
521             {
522                 instance.adjustViewSize = (bool)newValue;
523             }
524         },
525         defaultValueCreator: (bindable) =>
526         {
527             var instance = (Tizen.NUI.BaseComponents.ImageView)bindable;
528             return instance.adjustViewSize;
529         });
530
531         /// <summary>
532         /// PlaceHolderUrlProperty
533         /// </summary>
534         [EditorBrowsable(EditorBrowsableState.Never)]
535         public static readonly BindableProperty PlaceHolderUrlProperty = BindableProperty.Create(nameof(PlaceHolderUrl), typeof(string), typeof(ImageView), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
536         {
537             var imageView = (Tizen.NUI.BaseComponents.ImageView)bindable;
538             if (newValue != null)
539             {
540                 Object.InternalSetPropertyString(imageView.SwigCPtr, ImageView.Property.PlaceHolderUrl, (string)newValue );
541             }
542         },
543         defaultValueCreator: (bindable) =>
544         {
545             var imageView = (Tizen.NUI.BaseComponents.ImageView)bindable;
546             return Object.InternalGetPropertyString(imageView.SwigCPtr, ImageView.Property.PlaceHolderUrl);
547         });
548
549         /// Intenal used, will never be opened.
550         [EditorBrowsable(EditorBrowsableState.Never)]
551         public static readonly BindableProperty TransitionEffectProperty = BindableProperty.Create(nameof(TransitionEffect), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
552         {
553             var imageView = (ImageView)bindable;
554             if (newValue != null)
555             {
556                 Object.InternalSetPropertyBool(imageView.SwigCPtr, ImageView.Property.TransitionEffect, (bool)newValue);
557             }
558         },
559         defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) =>
560         {
561             var imageView = (ImageView)bindable;
562             return Object.InternalGetPropertyBool(imageView.SwigCPtr, ImageView.Property.TransitionEffect);
563         }));
564     }
565 }