2 * Copyright (c) 2017 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (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
8 * http://floralicense.org/license/
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.
17 using TVMediaHub.Tizen.ViewModels;
19 using Tizen.Xamarin.Forms.Extension;
20 using TVMediaHub.Tizen.Utils;
23 using TVMediaHub.Tizen.Controls;
24 using System.Collections.Generic;
27 namespace TVMediaHub.Tizen.Views
29 public partial class ImageViewerZoom : ContentPageEx
31 private static List<string> MoveDirection = new List<string> { "Up", "Down", "Left", "Right" };
33 //TODO: need to check the move size
34 private static int clipperMoveGap = 10;
35 private static double zoomRatio = 1.5;
36 private ElmSharp.ImageOrientation imgOrientation = ElmSharp.ImageOrientation.None;
38 private ElmSharp.Rectangle backgroundThumbnail;
39 private ElmSharp.Image thumbnailImg;
40 private ElmSharp.Image thumbnailDim;
41 private ElmSharp.Image clippingImg;
42 private ElmSharp.Rectangle clipper;
43 private ElmSharp.Image clipperBorder;
45 public static readonly BindableProperty SavedRotationProperty = BindableProperty.Create("SavedRotation", typeof(double), typeof(ImageViewerZoom), default(double));
46 public double SavedRotation
48 get { return (double)GetValue(SavedRotationProperty); }
49 set { SetValue(SavedRotationProperty, value); }
52 public static readonly BindableProperty ThumbnailPathProperty = BindableProperty.Create("ThumbnailPath", typeof(string), typeof(ImageViewerZoom), default(string));
53 public string ThumbnailPath
55 get { return (string)GetValue(ThumbnailPathProperty); }
56 set { SetValue(ThumbnailPathProperty, value); }
59 public ImageViewerZoom()
61 BindingContext = ImageTabViewModelLocator.ViewModel;
62 InitializeComponent();
64 int BackKeyInfoLabelSize = SizeUtils.GetFontSize(28);
65 BackKeyInfoLabel.FontSize = BackKeyInfoLabelSize;
66 Toast.DisplayText("Press [Back] to Escape from Zoom mode.");
68 /// Set the current image
71 /// Create the mini map
74 OnBackButtonPressedHandler += (s, e) =>
76 Program.TransitionTo(new SimpleImageViewer());
80 protected override void InitializePage()
82 /// Grabs the hw keys to move the given image
86 protected override void FinalizePage()
90 if (backgroundThumbnail != null)
92 backgroundThumbnail.Unrealize();
93 backgroundThumbnail = null;
96 if (thumbnailImg != null)
98 thumbnailImg.Unrealize();
102 if (thumbnailDim != null)
104 thumbnailDim.Unrealize();
108 if (clippingImg != null)
110 clippingImg.Unrealize();
120 if (clipperBorder != null)
122 clipperBorder.Unrealize();
123 clipperBorder = null;
128 /// Grabs the hw keys to move the given image
130 private void grabMoveKeys()
132 foreach (string direction in MoveDirection)
134 App.MainWindow.KeyGrab(direction, false);
137 App.MainWindow.KeyUp += MoveKeyUpListener;
138 App.MainWindow.KeyDown += MoveKeyDownListener;
142 /// Ungrab the hw keys
144 private void ungrabMoveKeys()
146 App.MainWindow.KeyUp -= MoveKeyUpListener;
147 App.MainWindow.KeyDown -= MoveKeyDownListener;
149 foreach (string direction in MoveDirection)
151 App.MainWindow.KeyUngrab(direction);
155 private void MoveKeyUpListener(object sender, ElmSharp.EvasKeyEventArgs e)
157 DbgPort.D("[ZoomMode] key up : " + e.KeyName);
159 if (!MoveDirection.Contains(e.KeyName))
164 int direction = MoveDirection.FindIndex(x => x.Equals(e.KeyName));
165 object[] buttons = new object[4] { UpButton, DownButton, LeftButton, RightButton };
166 (buttons[direction] as CustomImageButton).OnButtonReleased();
169 private void MoveKeyDownListener(object sender, ElmSharp.EvasKeyEventArgs e)
171 DbgPort.D("[ZoomMode] key down : " + e.KeyName);
173 if (!MoveDirection.Contains(e.KeyName))
178 MoveCurrentImage(e.KeyName);
180 int direction = MoveDirection.FindIndex(x => x.Equals(e.KeyName));
181 object[] buttons = new object[4] { UpButton, DownButton, LeftButton, RightButton };
182 (buttons[direction] as CustomImageButton).OnButtonPressed();
185 private void MoveCurrentImage(string direction)
187 int moveDuration = 350;
188 if (direction.Equals("Up"))
190 int toY = clipper.Geometry.Y - clipperMoveGap;
192 if (toY <= thumbnailDim.Geometry.Y)
194 clipper.Move(clipper.Geometry.X, thumbnailDim.Geometry.Y);
195 CurrentImage.TranslateTo(CurrentImage.TranslationX, CurrentImage.Y, Convert.ToUInt32(moveDuration), Easing.CubicOut);
200 ElmSharp.EcoreAnimator.AddAmimator(delegate ()
202 clipper.Move(clipper.Geometry.X, clipper.Geometry.Y - 1);
203 if (clipper.Geometry.Y <= toY)
205 clipper.Move(clipper.Geometry.X, toY);
213 CurrentImage.TranslateTo(CurrentImage.TranslationX, CurrentImage.TranslationY + clipperMoveGap * (CurrentImage.Height / thumbnailDim.Geometry.Height), Convert.ToUInt32(moveDuration), Easing.CubicOut);
215 else if (direction.Equals("Down"))
217 int toY = clipper.Geometry.Y + clipperMoveGap;
219 if ((toY + clipper.Geometry.Height) >= (thumbnailDim.Geometry.Y + thumbnailDim.Geometry.Height))
221 clipper.Move(clipper.Geometry.X, (thumbnailDim.Geometry.Y + thumbnailDim.Geometry.Height) - clipper.Geometry.Height);
222 CurrentImage.TranslateTo(CurrentImage.TranslationX, -(CurrentImage.Height - App.MainWindow.Geometry.Height), Convert.ToUInt32(moveDuration), Easing.CubicOut);
227 ElmSharp.EcoreAnimator.AddAmimator(delegate ()
229 clipper.Move(clipper.Geometry.X, clipper.Geometry.Y + 1);
230 if (clipper.Geometry.Y >= toY)
232 clipper.Move(clipper.Geometry.X, toY);
240 CurrentImage.TranslateTo(CurrentImage.TranslationX, CurrentImage.TranslationY - clipperMoveGap * (CurrentImage.Height / thumbnailDim.Geometry.Height), Convert.ToUInt32(moveDuration), Easing.CubicOut);
242 else if (direction.Equals("Left"))
244 int toX = clipper.Geometry.X - clipperMoveGap;
246 if (toX <= thumbnailDim.Geometry.X)
248 clipper.Move(thumbnailDim.Geometry.X, clipper.Geometry.Y);
249 CurrentImage.TranslateTo(CurrentImage.X, CurrentImage.TranslationY, Convert.ToUInt32(moveDuration), Easing.CubicOut);
254 ElmSharp.EcoreAnimator.AddAmimator(delegate ()
256 clipper.Move(clipper.Geometry.X - 1, clipper.Geometry.Y);
257 if (clipper.Geometry.X <= toX)
259 clipper.Move(toX, clipper.Geometry.Y);
267 CurrentImage.TranslateTo(CurrentImage.TranslationX + clipperMoveGap * (CurrentImage.Width / thumbnailDim.Geometry.Width), CurrentImage.TranslationY, Convert.ToUInt32(moveDuration), Easing.CubicOut);
269 else if (direction.Equals("Right"))
271 int toX = clipper.Geometry.X + clipperMoveGap;
272 if ((toX + clipper.Geometry.Width) >= (thumbnailDim.Geometry.X + thumbnailDim.Geometry.Width))
274 clipper.Move((thumbnailDim.Geometry.X + thumbnailDim.Geometry.Width) - clipper.Geometry.Width, clipper.Geometry.Y);
275 CurrentImage.TranslateTo(-(CurrentImage.Width - App.MainWindow.Geometry.Width), CurrentImage.TranslationY, Convert.ToUInt32(moveDuration), Easing.CubicOut);
280 ElmSharp.EcoreAnimator.AddAmimator(delegate ()
282 clipper.Move(clipper.Geometry.X + 1, clipper.Geometry.Y);
283 if (clipper.Geometry.X >= toX)
285 clipper.Move(toX, clipper.Geometry.Y);
293 CurrentImage.TranslateTo(CurrentImage.TranslationX - clipperMoveGap * (CurrentImage.Width / thumbnailDim.Geometry.Width), CurrentImage.TranslationY, Convert.ToUInt32(moveDuration), Easing.CubicOut);
297 DbgPort.D("Wrong direction : " + direction);
302 private void setCurrentImage()
304 CurrentImage.WidthRequest = App.MainWindow.Geometry.Width * zoomRatio;
305 CurrentImage.HeightRequest = App.MainWindow.Geometry.Height * zoomRatio;
306 CurrentImage.TranslationX = -((App.MainWindow.Geometry.Width * zoomRatio) - App.MainWindow.Geometry.Width) / 2;
307 CurrentImage.TranslationY = -((App.MainWindow.Geometry.Height * zoomRatio) - App.MainWindow.Geometry.Height) / 2;
309 int currentAngle = Convert.ToInt32(SavedRotation);
310 imgOrientation = (ElmSharp.ImageOrientation)Enum.ToObject(typeof(ElmSharp.ImageOrientation), currentAngle / 90);
312 CurrentImage.Scale = (currentAngle == 90 || currentAngle == 270) ? (double)((double)App.MainWindow.Geometry.Height / (double)App.MainWindow.Geometry.Width) : 1;
313 CurrentImage.Aspect = (currentAngle == 90 || currentAngle == 270) ? Aspect.AspectFill : Aspect.AspectFit;
314 CurrentImage.Rotation = SavedRotation;
317 private void createMiniMap()
319 Grid miniMap = new Grid()
325 miniMap.RowDefinitions.Add(new RowDefinition { Height = new GridLength(430) });
326 miniMap.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(640) });
327 ZoomLayout.Children.Add(miniMap,
328 Constraint.Constant(App.MainWindow.Geometry.Width - 96 - 480 - 80), /// X
329 Constraint.Constant(App.MainWindow.Geometry.Height - 96 - 270 - 80), /// Y
330 Constraint.Constant(640), /// Width
331 Constraint.Constant(430)); /// Height
333 /// create the shadow of the mini map
334 var backgroundShadow = new NinePatch
336 Source = "img_zoom_minimap_shadow.9.png",
337 WidthRequest = miniMap.Width,
338 HeightRequest = miniMap.Height,
343 Aspect = Aspect.Fill,
345 miniMap.Children.Add(backgroundShadow, 0, 0);
347 Grid thumbnailFrame = new Grid();
348 thumbnailFrame.RowDefinitions.Add(new RowDefinition { Height = new GridLength(80) });
349 thumbnailFrame.RowDefinitions.Add(new RowDefinition { Height = new GridLength(270) });
350 thumbnailFrame.RowDefinitions.Add(new RowDefinition { Height = new GridLength(80) });
351 thumbnailFrame.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(80) });
352 thumbnailFrame.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(480) });
353 thumbnailFrame.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(80) });
354 miniMap.Children.Add(thumbnailFrame, 0, 0);
356 RelativeLayout thumbnailMap = new RelativeLayout();
357 thumbnailFrame.Children.Add(thumbnailMap, 1, 1);
360 backgroundThumbnail = new ElmSharp.Rectangle(App.MainWindow);
361 backgroundThumbnail.Color = new ElmSharp.Color(0, 0, 0, 255);
362 backgroundThumbnail.Resize(480, 270);
363 backgroundThumbnail.Move(App.MainWindow.Geometry.Width - 96 - backgroundThumbnail.Geometry.Width, App.MainWindow.Geometry.Height - 96 - backgroundThumbnail.Geometry.Height);
364 backgroundThumbnail.Show();
366 thumbnailImg = new ElmSharp.Image(App.MainWindow);
367 thumbnailImg.Load((ThumbnailPath != null) ? ThumbnailPath : (CurrentImage.Source as FileImageSource).File);
368 thumbnailImg.Orientation = imgOrientation;
369 thumbnailImg.Resize(backgroundThumbnail.Geometry.Width, backgroundThumbnail.Geometry.Height);
370 thumbnailImg.Move(backgroundThumbnail.Geometry.X, backgroundThumbnail.Geometry.Y);
373 thumbnailDim = new ElmSharp.Image(App.MainWindow);
374 thumbnailDim.Load(Path.Combine(Program.Current.DirectoryInfo.Resource, "img_zoom_minimap_dimmed.png"));
375 thumbnailDim.Resize(thumbnailImg.Geometry.Width, thumbnailImg.Geometry.Height);
376 thumbnailDim.Geometry = thumbnailImg.Geometry;
377 thumbnailDim.Moved += (s, e) =>
379 thumbnailDim.Geometry = ((ElmSharp.Rectangle)s).Geometry;
383 clippingImg = new ElmSharp.Image(App.MainWindow);
384 clippingImg.Load((ThumbnailPath != null) ? ThumbnailPath : (CurrentImage.Source as FileImageSource).File);
385 clippingImg.Orientation = imgOrientation;
386 clippingImg.Resize(thumbnailImg.Geometry.Width, thumbnailImg.Geometry.Height);
387 clippingImg.Geometry = thumbnailImg.Geometry;
388 clippingImg.Moved += (s, e) =>
390 clippingImg.Geometry = ((ElmSharp.Rectangle)s).Geometry;
394 clipper = new ElmSharp.Rectangle(App.MainWindow);
395 clipper.Color = new ElmSharp.Color(255, 255, 255, 255);
396 clipper.Resize((int)(backgroundThumbnail.Geometry.Width / zoomRatio), (int)(backgroundThumbnail.Geometry.Height / zoomRatio));
397 clipper.Move(thumbnailDim.Geometry.X + (thumbnailDim.Geometry.Width / 2) - (clipper.Geometry.Width / 2), thumbnailDim.Geometry.Y + (thumbnailDim.Geometry.Height / 2) - (clipper.Geometry.Height / 2));
398 clippingImg.SetClip(clipper);
401 clipperBorder = new ElmSharp.Image(App.MainWindow)
403 IsFixedAspect = false,
405 clipperBorder.Load(Path.Combine(Program.Current.DirectoryInfo.Resource, "img_zoom_minimap_line.9.png"));
406 clipperBorder.Resize(clipper.Geometry.Width, clipper.Geometry.Height);
407 clipperBorder.Geometry = clipper.Geometry;
408 clipperBorder.SetBorder(clipperBorder.Geometry.Width / 2, clipperBorder.Geometry.Width / 2, clipperBorder.Geometry.Height / 2, clipperBorder.Geometry.Height / 2);
409 clipperBorder.Show();
411 clipper.Moved += (s, e) =>
413 clipperBorder.Move(clipper.Geometry.X, clipper.Geometry.Y);
416 object[] buttons = new object[4] { UpButton, DownButton, LeftButton, RightButton };
417 foreach (object button in buttons)
419 (button as CustomImageButton).OnButtonDown += (s, e) =>
421 DbgPort.D("'" + e + "' is pressed");
423 MoveCurrentImage(e as string);
428 protected override void LayoutChildren(double x, double y, double width, double height)
430 base.LayoutChildren(x, y, width, height);
431 GradientDim.HeightRequest = height;
432 GradientDim.WidthRequest = width;
435 public override void RunHideAnimation()
439 public override void RunShowAnimation()